diff --git a/mock_ssh_test.go b/mock_ssh_test.go index 744a0da..fca1a78 100644 --- a/mock_ssh_test.go +++ b/mock_ssh_test.go @@ -1152,7 +1152,11 @@ func moduleBlockinfileWithClient(_ *Executor, client sshFileRunner, args map[str replaceAll(endMarker, "/", "\\/"), path) _, _, _, _ = client.Run(context.Background(), cmd) - return &TaskResult{Changed: true}, nil + result := &TaskResult{Changed: true} + if backupPath != "" { + result.Data = map[string]any{"backup_file": backupPath} + } + return result, nil } // Create file if needed (best-effort) diff --git a/modules.go b/modules.go index 54d9c59..1c82c84 100644 --- a/modules.go +++ b/modules.go @@ -3565,8 +3565,22 @@ func (e *Executor) moduleBlockinfile(ctx context.Context, client sshExecutorClie replaceAll(beginMarker, "/", "\\/"), replaceAll(endMarker, "/", "\\/"), path) - _, _, _, _ = client.Run(ctx, cmd) - return &TaskResult{Changed: true}, nil + stdout, stderr, rc, err := client.Run(ctx, cmd) + if err != nil || rc != 0 { + return &TaskResult{Failed: true, Msg: stderr, Stdout: stdout, RC: rc}, nil + } + + result := &TaskResult{Changed: true} + if backupPath != "" { + result.Data = map[string]any{"backup_file": backupPath} + } + if e.Diff { + if after, ok := remoteFileText(ctx, client, path); ok && before != after { + result.Data = ensureTaskResultData(result.Data) + result.Data["diff"] = fileDiffData(path, before, after) + } + } + return result, nil } // Create file if needed (best-effort) diff --git a/modules_file_test.go b/modules_file_test.go index 0610cb2..40dbcdf 100644 --- a/modules_file_test.go +++ b/modules_file_test.go @@ -1045,6 +1045,29 @@ func TestModulesFile_ModuleBlockinfile_Good_RemoveBlock(t *testing.T) { assert.True(t, mock.hasExecuted(`sed -i '/.*BEGIN ANSIBLE MANAGED BLOCK/,/.*END ANSIBLE MANAGED BLOCK/d'`)) } +func TestModulesFile_ModuleBlockinfile_Good_RemoveBlockWithBackup(t *testing.T) { + e, mock := newTestExecutorWithMock("host1") + mock.addFile("/etc/config", []byte("before\n# BEGIN ANSIBLE MANAGED BLOCK\nmanaged\n# END ANSIBLE MANAGED BLOCK\nafter\n")) + + result, err := moduleBlockinfileWithClient(e, mock, map[string]any{ + "path": "/etc/config", + "state": "absent", + "backup": true, + }) + + require.NoError(t, err) + assert.True(t, result.Changed) + require.NotNil(t, result.Data) + + backupPath, ok := result.Data["backup_file"].(string) + require.True(t, ok) + assert.Contains(t, backupPath, "/etc/config.") + + backupContent, err := mock.Download(context.Background(), backupPath) + require.NoError(t, err) + assert.Equal(t, []byte("before\n# BEGIN ANSIBLE MANAGED BLOCK\nmanaged\n# END ANSIBLE MANAGED BLOCK\nafter\n"), backupContent) +} + func TestModulesFile_ModuleBlockinfile_Good_RemoveBlockWithCustomMarkerBeginAndEnd(t *testing.T) { e, mock := newTestExecutorWithMock("host1")