diff --git a/async_features.go b/async_features.go index 763a099..30a8c67 100644 --- a/async_features.go +++ b/async_features.go @@ -40,7 +40,9 @@ func (e *Executor) launchDetachedAsyncTask(ctx context.Context, host string, hos defer cancel() } - _ = clone.runTaskOnHost(asyncCtx, host, cloneHosts, &cloneTask, clonePlay) + if err := clone.runTaskOnHost(asyncCtx, host, cloneHosts, &cloneTask, clonePlay); err != nil { + return + } }() } diff --git a/ax7_public_test.go b/ax7_public_test.go new file mode 100644 index 0000000..afd32bf --- /dev/null +++ b/ax7_public_test.go @@ -0,0 +1,1256 @@ +package ansible + +import ( + "context" + "crypto/rand" + "crypto/rsa" + "io" + "net" + "os" + "path/filepath" + "strings" + "time" + + core "dappco.re/go" + coreio "dappco.re/go/io" + "golang.org/x/crypto/ssh" + "gopkg.in/yaml.v3" +) + +func ax7WriteFile(t *core.T, path string, data string) { + t.Helper() + core.RequireNoError(t, os.MkdirAll(filepath.Dir(path), 0o755)) + core.RequireNoError(t, os.WriteFile(path, []byte(data), 0o644)) +} + +func ax7Inventory() *Inventory { + return &Inventory{ + All: &InventoryGroup{ + Hosts: map[string]*Host{ + "web1": {AnsibleHost: "10.0.0.1"}, + }, + Children: map[string]*InventoryGroup{ + "db": { + Hosts: map[string]*Host{ + "db1": {AnsibleHost: "10.0.0.2"}, + }, + Vars: map[string]any{"tier": "database"}, + }, + }, + Vars: map[string]any{"env": "test"}, + }, + HostVars: map[string]map[string]any{ + "db1": {"role": "primary"}, + }, + } +} + +func ax7ConnectedSSHClient(t *core.T, responses map[string]string) *SSHClient { + t.Helper() + serverConfig := &ssh.ServerConfig{NoClientAuth: true} + key, err := rsa.GenerateKey(rand.Reader, 1024) + core.RequireNoError(t, err) + signer, err := ssh.NewSignerFromKey(key) + core.RequireNoError(t, err) + serverConfig.AddHostKey(signer) + + listener, err := net.Listen("tcp", "127.0.0.1:0") + core.RequireNoError(t, err) + go func() { + defer listener.Close() + serverConn, err := listener.Accept() + if err != nil { + return + } + conn, chans, reqs, err := ssh.NewServerConn(serverConn, serverConfig) + if err != nil { + return + } + defer conn.Close() + go ssh.DiscardRequests(reqs) + for next := range chans { + if next.ChannelType() != "session" { + _ = next.Reject(ssh.UnknownChannelType, "session required") + continue + } + channel, requests, err := next.Accept() + if err != nil { + continue + } + go func() { + defer channel.Close() + for req := range requests { + if req.Type != "exec" { + _ = req.Reply(false, nil) + continue + } + var payload struct{ Command string } + ssh.Unmarshal(req.Payload, &payload) + if req.WantReply { + _ = req.Reply(true, nil) + } + out := responses[payload.Command] + if out == "" { + for key, value := range responses { + if strings.Contains(payload.Command, key) { + out = value + break + } + } + } + _, _ = io.WriteString(channel, out) + _, _ = channel.SendRequest("exit-status", false, ssh.Marshal(struct{ Status uint32 }{0})) + return + } + }() + } + }() + clientConn, err := net.Dial("tcp", listener.Addr().String()) + core.RequireNoError(t, err) + + clientConfig := &ssh.ClientConfig{ + User: "tester", + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + Timeout: time.Second, + } + conn, chans, reqs, err := ssh.NewClientConn(clientConn, "pipe", clientConfig) + core.RequireNoError(t, err) + return &SSHClient{client: ssh.NewClient(conn, chans, reqs), host: "pipe", port: 22, user: "tester"} +} + +func TestAX7_Client_BecomeState_Good(t *core.T) { + client := newLocalClient() + client.SetBecome(true, "deploy", "secret") + become, user, password := client.BecomeState() + core.AssertTrue(t, become) + core.AssertEqual(t, "deploy", user) + core.AssertEqual(t, "secret", password) +} + +func TestAX7_Client_BecomeState_Bad(t *core.T) { + client := newLocalClient() + become, user, password := client.BecomeState() + core.AssertFalse(t, become) + core.AssertEmpty(t, user) + core.AssertEmpty(t, password) +} + +func TestAX7_Client_BecomeState_Ugly(t *core.T) { + client := newLocalClient() + client.SetBecome(true, "", "") + become, user, password := client.BecomeState() + core.AssertTrue(t, become) + core.AssertEmpty(t, user) + core.AssertEmpty(t, password) +} + +func TestAX7_Client_SetBecome_Good(t *core.T) { + client := newLocalClient() + client.SetBecome(true, "root", "pw") + become, user, password := client.BecomeState() + core.AssertTrue(t, become) + core.AssertEqual(t, "root", user) + core.AssertEqual(t, "pw", password) +} + +func TestAX7_Client_SetBecome_Bad(t *core.T) { + client := newLocalClient() + client.SetBecome(false, "root", "pw") + become, user, password := client.BecomeState() + core.AssertFalse(t, become) + core.AssertEmpty(t, user) + core.AssertEmpty(t, password) +} + +func TestAX7_Client_SetBecome_Ugly(t *core.T) { + client := newLocalClient() + client.SetBecome(true, "root", "pw") + client.SetBecome(true, "", "") + _, user, password := client.BecomeState() + core.AssertEqual(t, "root", user) + core.AssertEqual(t, "pw", password) +} + +func TestAX7_Client_Close_Good(t *core.T) { + client := newLocalClient() + err := client.Close() + core.AssertNoError(t, err) + core.AssertNotNil(t, client) +} + +func TestAX7_Client_Close_Bad(t *core.T) { + client := newLocalClient() + first := client.Close() + second := client.Close() + core.AssertNoError(t, first) + core.AssertNoError(t, second) +} + +func TestAX7_Client_Close_Ugly(t *core.T) { + client := newLocalClient() + client.SetBecome(true, "root", "pw") + err := client.Close() + core.AssertNoError(t, err) + core.AssertNotNil(t, client) +} + +func TestAX7_Client_Run_Good(t *core.T) { + client := newLocalClient() + stdout, stderr, code, err := client.Run(context.Background(), "printf local") + core.AssertNoError(t, err) + core.AssertEqual(t, "local", stdout) + core.AssertEmpty(t, stderr) + core.AssertEqual(t, 0, code) +} + +func TestAX7_Client_Run_Bad(t *core.T) { + client := newLocalClient() + stdout, _, code, err := client.Run(context.Background(), "exit 7") + core.AssertNoError(t, err) + core.AssertEmpty(t, stdout) + core.AssertEqual(t, 7, code) +} + +func TestAX7_Client_Run_Ugly(t *core.T) { + client := newLocalClient() + stdout, stderr, code, err := client.Run(context.Background(), "") + core.AssertNoError(t, err) + core.AssertEmpty(t, stdout) + core.AssertEmpty(t, stderr) + core.AssertEqual(t, 0, code) +} + +func TestAX7_Client_RunScript_Good(t *core.T) { + client := newLocalClient() + stdout, _, code, err := client.RunScript(context.Background(), "printf script") + core.AssertNoError(t, err) + core.AssertEqual(t, "script", stdout) + core.AssertEqual(t, 0, code) +} + +func TestAX7_Client_RunScript_Bad(t *core.T) { + client := newLocalClient() + _, _, code, err := client.RunScript(context.Background(), "exit 9") + core.AssertNoError(t, err) + core.AssertEqual(t, 9, code) +} + +func TestAX7_Client_RunScript_Ugly(t *core.T) { + client := newLocalClient() + stdout, stderr, code, err := client.RunScript(context.Background(), "\n") + core.AssertNoError(t, err) + core.AssertEmpty(t, stdout) + core.AssertEmpty(t, stderr) + core.AssertEqual(t, 0, code) +} + +func TestAX7_Client_Upload_Good(t *core.T) { + client := newLocalClient() + path := filepath.Join(t.TempDir(), "remote.txt") + err := client.Upload(context.Background(), strings.NewReader("payload"), path, 0o644) + core.AssertNoError(t, err) + content, readErr := os.ReadFile(path) + core.AssertNoError(t, readErr) + core.AssertEqual(t, "payload", string(content)) +} + +func TestAX7_Client_Upload_Bad(t *core.T) { + client := newLocalClient() + err := client.Upload(context.Background(), strings.NewReader("payload"), "", 0o644) + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "write remote file") +} + +func TestAX7_Client_Upload_Ugly(t *core.T) { + client := newLocalClient() + path := filepath.Join(t.TempDir(), "nested", "remote.txt") + err := client.Upload(context.Background(), strings.NewReader(""), path, 0) + core.AssertNoError(t, err) + info, statErr := os.Stat(path) + core.AssertNoError(t, statErr) + core.AssertEqual(t, os.FileMode(0), info.Mode().Perm()) +} + +func TestAX7_Client_Download_Good(t *core.T) { + client := newLocalClient() + path := filepath.Join(t.TempDir(), "remote.txt") + ax7WriteFile(t, path, "download") + data, err := client.Download(context.Background(), path) + core.AssertNoError(t, err) + core.AssertEqual(t, "download", string(data)) +} + +func TestAX7_Client_Download_Bad(t *core.T) { + client := newLocalClient() + data, err := client.Download(context.Background(), filepath.Join(t.TempDir(), "missing.txt")) + core.AssertError(t, err) + core.AssertNil(t, data) +} + +func TestAX7_Client_Download_Ugly(t *core.T) { + client := newLocalClient() + data, err := client.Download(context.Background(), "") + core.AssertError(t, err) + core.AssertNil(t, data) +} + +func TestAX7_Client_FileExists_Good(t *core.T) { + client := newLocalClient() + path := filepath.Join(t.TempDir(), "exists.txt") + ax7WriteFile(t, path, "x") + exists, err := client.FileExists(context.Background(), path) + core.AssertNoError(t, err) + core.AssertTrue(t, exists) +} + +func TestAX7_Client_FileExists_Bad(t *core.T) { + client := newLocalClient() + exists, err := client.FileExists(context.Background(), filepath.Join(t.TempDir(), "missing.txt")) + core.AssertNoError(t, err) + core.AssertFalse(t, exists) +} + +func TestAX7_Client_FileExists_Ugly(t *core.T) { + client := newLocalClient() + exists, err := client.FileExists(context.Background(), string([]byte{'b', 0, 'd'})) + core.AssertError(t, err) + core.AssertFalse(t, exists) +} + +func TestAX7_Client_Stat_Good(t *core.T) { + client := newLocalClient() + path := filepath.Join(t.TempDir(), "exists.txt") + ax7WriteFile(t, path, "x") + info, err := client.Stat(context.Background(), path) + core.AssertNoError(t, err) + core.AssertEqual(t, true, info["exists"]) + core.AssertEqual(t, false, info["isdir"]) +} + +func TestAX7_Client_Stat_Bad(t *core.T) { + client := newLocalClient() + info, err := client.Stat(context.Background(), filepath.Join(t.TempDir(), "missing.txt")) + core.AssertNoError(t, err) + core.AssertEqual(t, false, info["exists"]) +} + +func TestAX7_Client_Stat_Ugly(t *core.T) { + client := newLocalClient() + dir := t.TempDir() + info, err := client.Stat(context.Background(), dir) + core.AssertNoError(t, err) + core.AssertEqual(t, true, info["exists"]) + core.AssertEqual(t, true, info["isdir"]) +} + +func TestAX7_NewSSHClient_Good(t *core.T) { + client, err := NewSSHClient(SSHConfig{Host: "web1", Port: 2200, User: "deploy"}) + core.AssertNoError(t, err) + core.AssertEqual(t, "web1", client.host) + core.AssertEqual(t, 2200, client.port) + core.AssertEqual(t, "deploy", client.user) +} + +func TestAX7_NewSSHClient_Bad(t *core.T) { + client, err := NewSSHClient(SSHConfig{Host: "web1"}) + core.AssertNoError(t, err) + core.AssertEqual(t, 22, client.port) + core.AssertEqual(t, "root", client.user) +} + +func TestAX7_NewSSHClient_Ugly(t *core.T) { + client, err := NewSSHClient(SSHConfig{Host: "", Timeout: time.Nanosecond}) + core.AssertNoError(t, err) + core.AssertEqual(t, "", client.host) + core.AssertEqual(t, time.Nanosecond, client.timeout) +} + +func TestAX7_SSHClient_SetBecome_Good(t *core.T) { + client := &SSHClient{} + client.SetBecome(true, "admin", "pw") + become, user, password := client.BecomeState() + core.AssertTrue(t, become) + core.AssertEqual(t, "admin", user) + core.AssertEqual(t, "pw", password) +} + +func TestAX7_SSHClient_SetBecome_Bad(t *core.T) { + client := &SSHClient{} + client.SetBecome(false, "admin", "pw") + become, user, password := client.BecomeState() + core.AssertFalse(t, become) + core.AssertEmpty(t, user) + core.AssertEmpty(t, password) +} + +func TestAX7_SSHClient_SetBecome_Ugly(t *core.T) { + client := &SSHClient{} + client.SetBecome(true, "admin", "pw") + client.SetBecome(true, "", "") + _, user, password := client.BecomeState() + core.AssertEqual(t, "admin", user) + core.AssertEqual(t, "pw", password) +} + +func TestAX7_SSHClient_BecomeState_Good(t *core.T) { + client := &SSHClient{become: true, becomeUser: "root", becomePass: "pw"} + become, user, password := client.BecomeState() + core.AssertTrue(t, become) + core.AssertEqual(t, "root", user) + core.AssertEqual(t, "pw", password) +} + +func TestAX7_SSHClient_BecomeState_Bad(t *core.T) { + client := &SSHClient{} + become, user, password := client.BecomeState() + core.AssertFalse(t, become) + core.AssertEmpty(t, user) + core.AssertEmpty(t, password) +} + +func TestAX7_SSHClient_BecomeState_Ugly(t *core.T) { + client := &SSHClient{become: true} + become, user, password := client.BecomeState() + core.AssertTrue(t, become) + core.AssertEmpty(t, user) + core.AssertEmpty(t, password) +} + +func TestAX7_SSHClient_Close_Good(t *core.T) { + client := ax7ConnectedSSHClient(t, nil) + err := client.Close() + core.AssertNoError(t, err) + core.AssertNil(t, client.client) +} + +func TestAX7_SSHClient_Close_Bad(t *core.T) { + client := &SSHClient{} + err := client.Close() + core.AssertNoError(t, err) + core.AssertNil(t, client.client) +} + +func TestAX7_SSHClient_Close_Ugly(t *core.T) { + client := ax7ConnectedSSHClient(t, nil) + first := client.Close() + second := client.Close() + core.AssertNoError(t, first) + core.AssertNoError(t, second) +} + +func TestAX7_SSHClient_Connect_Good(t *core.T) { + client := ax7ConnectedSSHClient(t, nil) + err := client.Connect(context.Background()) + core.AssertNoError(t, err) + core.AssertNotNil(t, client.client) +} + +func TestAX7_SSHClient_Connect_Bad(t *core.T) { + client := &SSHClient{host: "127.0.0.1", port: 1, user: "root"} + err := client.Connect(context.Background()) + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "no authentication method") +} + +func TestAX7_SSHClient_Connect_Ugly(t *core.T) { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + client := &SSHClient{host: "127.0.0.1", port: 1, user: "root", password: "pw"} + err := client.Connect(ctx) + core.AssertError(t, err) +} + +func TestAX7_SSHClient_Run_Good(t *core.T) { + client := ax7ConnectedSSHClient(t, map[string]string{"hostname": "web1\n"}) + stdout, stderr, code, err := client.Run(context.Background(), "hostname") + core.AssertNoError(t, err) + core.AssertEqual(t, "web1\n", stdout) + core.AssertEmpty(t, stderr) + core.AssertEqual(t, 0, code) +} + +func TestAX7_SSHClient_Run_Bad(t *core.T) { + client := &SSHClient{host: "127.0.0.1", port: 1, user: "root"} + stdout, _, code, err := client.Run(context.Background(), "hostname") + core.AssertError(t, err) + core.AssertEmpty(t, stdout) + core.AssertEqual(t, -1, code) +} + +func TestAX7_SSHClient_Run_Ugly(t *core.T) { + client := ax7ConnectedSSHClient(t, map[string]string{"": ""}) + stdout, stderr, code, err := client.Run(context.Background(), "") + core.AssertNoError(t, err) + core.AssertEmpty(t, stdout) + core.AssertEmpty(t, stderr) + core.AssertEqual(t, 0, code) +} + +func TestAX7_SSHClient_RunScript_Good(t *core.T) { + client := ax7ConnectedSSHClient(t, map[string]string{"ANSIBLE_SCRIPT_EOF": "script\n"}) + stdout, _, code, err := client.RunScript(context.Background(), "echo script") + core.AssertNoError(t, err) + core.AssertEqual(t, "script\n", stdout) + core.AssertEqual(t, 0, code) +} + +func TestAX7_SSHClient_RunScript_Bad(t *core.T) { + client := &SSHClient{host: "127.0.0.1", port: 1, user: "root"} + _, _, code, err := client.RunScript(context.Background(), "echo script") + core.AssertError(t, err) + core.AssertEqual(t, -1, code) +} + +func TestAX7_SSHClient_RunScript_Ugly(t *core.T) { + client := ax7ConnectedSSHClient(t, map[string]string{"ANSIBLE_SCRIPT_EOF": ""}) + stdout, stderr, code, err := client.RunScript(context.Background(), "") + core.AssertNoError(t, err) + core.AssertEmpty(t, stdout) + core.AssertEmpty(t, stderr) + core.AssertEqual(t, 0, code) +} + +func TestAX7_SSHClient_Upload_Good(t *core.T) { + client := ax7ConnectedSSHClient(t, map[string]string{"mkdir -p": ""}) + err := client.Upload(context.Background(), strings.NewReader("payload"), "/tmp/file.txt", 0o644) + core.AssertNoError(t, err) + core.AssertNotNil(t, client.client) +} + +func TestAX7_SSHClient_Upload_Bad(t *core.T) { + client := &SSHClient{host: "127.0.0.1", port: 1, user: "root"} + err := client.Upload(context.Background(), strings.NewReader("payload"), "/tmp/file.txt", 0o644) + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "no authentication method") +} + +func TestAX7_SSHClient_Upload_Ugly(t *core.T) { + client := ax7ConnectedSSHClient(t, map[string]string{"mkdir -p": ""}) + err := client.Upload(context.Background(), strings.NewReader(""), "/tmp/empty.txt", 0) + core.AssertNoError(t, err) + core.AssertNotNil(t, client.client) +} + +func TestAX7_SSHClient_Download_Good(t *core.T) { + client := ax7ConnectedSSHClient(t, map[string]string{"cat": "downloaded"}) + data, err := client.Download(context.Background(), "/tmp/file.txt") + core.AssertNoError(t, err) + core.AssertEqual(t, "downloaded", string(data)) +} + +func TestAX7_SSHClient_Download_Bad(t *core.T) { + client := &SSHClient{host: "127.0.0.1", port: 1, user: "root"} + data, err := client.Download(context.Background(), "/tmp/file.txt") + core.AssertError(t, err) + core.AssertNil(t, data) +} + +func TestAX7_SSHClient_Download_Ugly(t *core.T) { + client := ax7ConnectedSSHClient(t, map[string]string{"cat": ""}) + data, err := client.Download(context.Background(), "") + core.AssertNoError(t, err) + core.AssertEmpty(t, data) +} + +func TestAX7_SSHClient_FileExists_Good(t *core.T) { + client := ax7ConnectedSSHClient(t, map[string]string{"test -e": "yes\n"}) + exists, err := client.FileExists(context.Background(), "/tmp/file.txt") + core.AssertNoError(t, err) + core.AssertTrue(t, exists) +} + +func TestAX7_SSHClient_FileExists_Bad(t *core.T) { + client := ax7ConnectedSSHClient(t, map[string]string{"test -e": "no\n"}) + exists, err := client.FileExists(context.Background(), "/tmp/missing.txt") + core.AssertNoError(t, err) + core.AssertFalse(t, exists) +} + +func TestAX7_SSHClient_FileExists_Ugly(t *core.T) { + client := &SSHClient{host: "127.0.0.1", port: 1, user: "root"} + exists, err := client.FileExists(context.Background(), "/tmp/file.txt") + core.AssertError(t, err) + core.AssertFalse(t, exists) +} + +func TestAX7_SSHClient_Stat_Good(t *core.T) { + client := ax7ConnectedSSHClient(t, map[string]string{"if [ -e": "exists=true isdir=false\n"}) + info, err := client.Stat(context.Background(), "/tmp/file.txt") + core.AssertNoError(t, err) + core.AssertEqual(t, true, info["exists"]) + core.AssertEqual(t, false, info["isdir"]) +} + +func TestAX7_SSHClient_Stat_Bad(t *core.T) { + client := ax7ConnectedSSHClient(t, map[string]string{"if [ -e": "exists=false\n"}) + info, err := client.Stat(context.Background(), "/tmp/missing.txt") + core.AssertNoError(t, err) + core.AssertEqual(t, false, info["exists"]) +} + +func TestAX7_SSHClient_Stat_Ugly(t *core.T) { + client := &SSHClient{host: "127.0.0.1", port: 1, user: "root"} + info, err := client.Stat(context.Background(), "/tmp/file.txt") + core.AssertError(t, err) + core.AssertNil(t, info) +} + +func TestAX7_NewExecutor_Bad(t *core.T) { + executor := NewExecutor("") + core.AssertNotNil(t, executor) + core.AssertNotNil(t, executor.parser) + core.AssertEmpty(t, executor.parser.basePath) +} + +func TestAX7_NewExecutor_Ugly(t *core.T) { + executor := NewExecutor("relative/base") + core.AssertNotNil(t, executor) + core.AssertEqual(t, "relative/base", executor.parser.basePath) + core.AssertNotNil(t, executor.clients) +} + +func TestAX7_Executor_SetVar_Good(t *core.T) { + executor := NewExecutor("/tmp") + executor.SetVar("answer", 42) + core.AssertEqual(t, 42, executor.vars["answer"]) + core.AssertLen(t, executor.vars, 1) +} + +func TestAX7_Executor_SetVar_Bad(t *core.T) { + executor := NewExecutor("/tmp") + executor.SetVar("", "empty") + core.AssertEqual(t, "empty", executor.vars[""]) + core.AssertTrue(t, executor.vars != nil) +} + +func TestAX7_Executor_SetVar_Ugly(t *core.T) { + executor := NewExecutor("/tmp") + executor.SetVar("nil", nil) + core.AssertContains(t, executor.vars, "nil") + core.AssertNil(t, executor.vars["nil"]) +} + +func TestAX7_Executor_SetInventoryDirect_Good(t *core.T) { + executor := NewExecutor("/tmp") + inv := ax7Inventory() + executor.SetInventoryDirect(inv) + core.AssertEqual(t, inv, executor.inventory) + core.AssertEmpty(t, executor.inventoryPath) +} + +func TestAX7_Executor_SetInventoryDirect_Bad(t *core.T) { + executor := NewExecutor("/tmp") + executor.SetInventoryDirect(nil) + core.AssertNil(t, executor.inventory) + core.AssertEmpty(t, executor.inventoryPath) +} + +func TestAX7_Executor_SetInventoryDirect_Ugly(t *core.T) { + executor := NewExecutor("/tmp") + first := ax7Inventory() + second := &Inventory{All: &InventoryGroup{}} + executor.SetInventoryDirect(first) + executor.SetInventoryDirect(second) + core.AssertEqual(t, second, executor.inventory) +} + +func TestAX7_Executor_SetInventory_Good(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "inventory.yml") + ax7WriteFile(t, path, "all:\n hosts:\n web1: {}\n") + executor := NewExecutor(dir) + err := executor.SetInventory(path) + core.AssertNoError(t, err) + core.AssertContains(t, executor.inventory.All.Hosts, "web1") +} + +func TestAX7_Executor_SetInventory_Bad(t *core.T) { + executor := NewExecutor(t.TempDir()) + err := executor.SetInventory("missing.yml") + core.AssertError(t, err) + core.AssertNil(t, executor.inventory) +} + +func TestAX7_Executor_SetInventory_Ugly(t *core.T) { + dir := t.TempDir() + ax7WriteFile(t, filepath.Join(dir, "hosts.yml"), "all:\n hosts:\n edge1: {}\n") + executor := NewExecutor(dir) + err := executor.SetInventory(dir) + core.AssertNoError(t, err) + core.AssertContains(t, executor.inventory.All.Hosts, "edge1") +} + +func TestAX7_Executor_SetMedium_Good(t *core.T) { + executor := NewExecutor("/tmp") + executor.SetMedium(coreio.Local) + core.AssertNotNil(t, executor.parser.configuredMedium()) + core.AssertEqual(t, coreio.Local, executor.parser.configuredMedium()) +} + +func TestAX7_Executor_SetMedium_Bad(t *core.T) { + var executor *Executor + core.AssertNotPanics(t, func() { executor.SetMedium(coreio.Local) }) + core.AssertNil(t, executor) +} + +func TestAX7_Executor_SetMedium_Ugly(t *core.T) { + executor := &Executor{} + core.AssertNotPanics(t, func() { executor.SetMedium(coreio.Local) }) + core.AssertNil(t, executor.parser) +} + +func TestAX7_Executor_Run_Good(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "site.yml") + ax7WriteFile(t, path, "- hosts: localhost\n gather_facts: false\n tasks: []\n") + executor := NewExecutor(dir) + err := executor.Run(context.Background(), path) + core.AssertNoError(t, err) +} + +func TestAX7_Executor_Run_Bad(t *core.T) { + executor := NewExecutor(t.TempDir()) + err := executor.Run(context.Background(), "missing.yml") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "parse playbook") +} + +func TestAX7_Executor_Run_Ugly(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "site.yml") + ax7WriteFile(t, path, "[]\n") + executor := NewExecutor(dir) + err := executor.Run(context.Background(), path) + core.AssertNoError(t, err) +} + +func TestAX7_Executor_Close_Good(t *core.T) { + executor := NewExecutor("/tmp") + executor.clients["local"] = newLocalClient() + executor.Close() + core.AssertNotNil(t, executor.clients) + core.AssertLen(t, executor.clients, 0) +} + +func TestAX7_Executor_Close_Bad(t *core.T) { + executor := NewExecutor("/tmp") + executor.Close() + core.AssertNotNil(t, executor.clients) + core.AssertLen(t, executor.clients, 0) +} + +func TestAX7_Executor_Close_Ugly(t *core.T) { + executor := &Executor{clients: nil} + core.AssertNotPanics(t, executor.Close) + core.AssertNotNil(t, executor.clients) + core.AssertLen(t, executor.clients, 0) +} + +func TestAX7_Executor_TemplateFile_Good(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "template.j2") + ax7WriteFile(t, path, "hello {{ name }}") + executor := NewExecutor(dir) + executor.SetVar("name", "world") + content, err := executor.TemplateFile(path, "", nil) + core.AssertNoError(t, err) + core.AssertEqual(t, "hello world", content) +} + +func TestAX7_Executor_TemplateFile_Bad(t *core.T) { + executor := NewExecutor(t.TempDir()) + content, err := executor.TemplateFile("", "", nil) + core.AssertError(t, err) + core.AssertEmpty(t, content) +} + +func TestAX7_Executor_TemplateFile_Ugly(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "template.j2") + ax7WriteFile(t, path, "hello {{ missing }}") + executor := NewExecutor(dir) + content, err := executor.TemplateFile(path, "", nil) + core.AssertNoError(t, err) + core.AssertEqual(t, "hello {{ missing }}", content) +} + +func TestAX7_NewParser_Bad(t *core.T) { + parser := NewParser("") + core.AssertNotNil(t, parser) + core.AssertEmpty(t, parser.basePath) + core.AssertNotNil(t, parser.vars) +} + +func TestAX7_NewParser_Ugly(t *core.T) { + parser := NewParser("relative/base") + core.AssertNotNil(t, parser) + core.AssertEqual(t, "relative/base", parser.basePath) + core.AssertNotNil(t, parser.vars) +} + +func TestAX7_Parser_SetMedium_Good(t *core.T) { + parser := NewParser("/tmp") + parser.SetMedium(coreio.Local) + core.AssertNotNil(t, parser.configuredMedium()) + core.AssertEqual(t, coreio.Local, parser.configuredMedium()) +} + +func TestAX7_Parser_SetMedium_Bad(t *core.T) { + var parser *Parser + core.AssertNotPanics(t, func() { parser.SetMedium(coreio.Local) }) + core.AssertNil(t, parser) +} + +func TestAX7_Parser_SetMedium_Ugly(t *core.T) { + parser := NewParser("/tmp") + parser.SetMedium(nil) + core.AssertNil(t, parser.configuredMedium()) + core.AssertNotNil(t, parser.vars) +} + +func TestAX7_Parser_ParsePlaybook_Good(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "site.yml") + ax7WriteFile(t, path, "- hosts: all\n tasks: []\n") + parser := NewParser(dir) + plays, err := parser.ParsePlaybook(path) + core.AssertNoError(t, err) + core.AssertLen(t, plays, 1) +} + +func TestAX7_Parser_ParsePlaybook_Bad(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "bad.yml") + ax7WriteFile(t, path, "not: [valid") + parser := NewParser(dir) + plays, err := parser.ParsePlaybook(path) + core.AssertError(t, err) + core.AssertNil(t, plays) +} + +func TestAX7_Parser_ParsePlaybook_Ugly(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "empty.yml") + ax7WriteFile(t, path, "[]\n") + parser := NewParser(dir) + plays, err := parser.ParsePlaybook(path) + core.AssertNoError(t, err) + core.AssertLen(t, plays, 0) +} + +func TestAX7_Parser_ParsePlaybookIter_Good(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "site.yml") + ax7WriteFile(t, path, "- hosts: all\n tasks: []\n") + parser := NewParser(dir) + seq, err := parser.ParsePlaybookIter(path) + core.AssertNoError(t, err) + var names []string + for play := range seq { + names = append(names, play.Hosts) + } + core.AssertEqual(t, []string{"all"}, names) +} + +func TestAX7_Parser_ParsePlaybookIter_Bad(t *core.T) { + parser := NewParser(t.TempDir()) + seq, err := parser.ParsePlaybookIter("missing.yml") + core.AssertError(t, err) + core.AssertNil(t, seq) +} + +func TestAX7_Parser_ParsePlaybookIter_Ugly(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "site.yml") + ax7WriteFile(t, path, "- hosts: one\n tasks: []\n- hosts: two\n tasks: []\n") + parser := NewParser(dir) + seq, err := parser.ParsePlaybookIter(path) + core.AssertNoError(t, err) + count := 0 + seq(func(Play) bool { + count++ + return false + }) + core.AssertEqual(t, 1, count) +} + +func TestAX7_Parser_ParseInventory_Good(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "inventory.yml") + ax7WriteFile(t, path, "all:\n hosts:\n web1: {}\n") + parser := NewParser(dir) + inv, err := parser.ParseInventory(path) + core.AssertNoError(t, err) + core.AssertContains(t, inv.All.Hosts, "web1") +} + +func TestAX7_Parser_ParseInventory_Bad(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "inventory.yml") + ax7WriteFile(t, path, "all: [") + parser := NewParser(dir) + inv, err := parser.ParseInventory(path) + core.AssertError(t, err) + core.AssertNil(t, inv) +} + +func TestAX7_Parser_ParseInventory_Ugly(t *core.T) { + dir := t.TempDir() + ax7WriteFile(t, filepath.Join(dir, "hosts.yml"), "all:\n hosts:\n db1: {}\n") + parser := NewParser(dir) + inv, err := parser.ParseInventory(dir) + core.AssertNoError(t, err) + core.AssertContains(t, inv.All.Hosts, "db1") +} + +func TestAX7_Parser_ParseTasks_Good(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "tasks.yml") + ax7WriteFile(t, path, "- name: hello\n shell: echo hello\n") + parser := NewParser(dir) + tasks, err := parser.ParseTasks(path) + core.AssertNoError(t, err) + core.AssertLen(t, tasks, 1) + core.AssertEqual(t, "shell", tasks[0].Module) +} + +func TestAX7_Parser_ParseTasks_Bad(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "tasks.yml") + ax7WriteFile(t, path, "not: [valid") + parser := NewParser(dir) + tasks, err := parser.ParseTasks(path) + core.AssertError(t, err) + core.AssertNil(t, tasks) +} + +func TestAX7_Parser_ParseTasks_Ugly(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "tasks.yml") + ax7WriteFile(t, path, "[]\n") + parser := NewParser(dir) + tasks, err := parser.ParseTasks(path) + core.AssertNoError(t, err) + core.AssertLen(t, tasks, 0) +} + +func TestAX7_Parser_ParseTasksFromDir_Good(t *core.T) { + dir := t.TempDir() + tasksDir := filepath.Join(dir, "tasks") + ax7WriteFile(t, filepath.Join(tasksDir, "main.yml"), "- debug:\n msg: ok\n") + parser := NewParser(dir) + tasks, err := parser.ParseTasksFromDir(tasksDir) + core.AssertNoError(t, err) + core.AssertLen(t, tasks, 1) +} + +func TestAX7_Parser_ParseTasksFromDir_Bad(t *core.T) { + parser := NewParser(t.TempDir()) + tasks, err := parser.ParseTasksFromDir("missing") + core.AssertError(t, err) + core.AssertNil(t, tasks) +} + +func TestAX7_Parser_ParseTasksFromDir_Ugly(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "tasks.yml") + ax7WriteFile(t, path, "- debug:\n msg: ok\n") + parser := NewParser(dir) + tasks, err := parser.ParseTasksFromDir(path) + core.AssertNoError(t, err) + core.AssertLen(t, tasks, 1) +} + +func TestAX7_Parser_ParseTasksIter_Good(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "tasks.yml") + ax7WriteFile(t, path, "- shell: echo one\n- shell: echo two\n") + parser := NewParser(dir) + seq, err := parser.ParseTasksIter(path) + core.AssertNoError(t, err) + count := 0 + for range seq { + count++ + } + core.AssertEqual(t, 2, count) +} + +func TestAX7_Parser_ParseTasksIter_Bad(t *core.T) { + parser := NewParser(t.TempDir()) + seq, err := parser.ParseTasksIter("missing.yml") + core.AssertError(t, err) + core.AssertNil(t, seq) +} + +func TestAX7_Parser_ParseTasksIter_Ugly(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "tasks.yml") + ax7WriteFile(t, path, "- shell: echo one\n- shell: echo two\n") + parser := NewParser(dir) + seq, err := parser.ParseTasksIter(path) + core.AssertNoError(t, err) + count := 0 + seq(func(Task) bool { + count++ + return false + }) + core.AssertEqual(t, 1, count) +} + +func TestAX7_Parser_ParseVarsFiles_Good(t *core.T) { + dir := t.TempDir() + path := filepath.Join(dir, "vars.yml") + ax7WriteFile(t, path, "answer: 42\n") + parser := NewParser(dir) + vars, err := parser.ParseVarsFiles(path) + core.AssertNoError(t, err) + core.AssertEqual(t, 42, vars["answer"]) +} + +func TestAX7_Parser_ParseVarsFiles_Bad(t *core.T) { + parser := NewParser(t.TempDir()) + vars, err := parser.ParseVarsFiles("*.missing") + core.AssertError(t, err) + core.AssertNil(t, vars) +} + +func TestAX7_Parser_ParseVarsFiles_Ugly(t *core.T) { + parser := NewParser(t.TempDir()) + vars, err := parser.ParseVarsFiles("") + core.AssertNoError(t, err) + core.AssertNil(t, vars) +} + +func TestAX7_Parser_ParseRoles_Good(t *core.T) { + dir := t.TempDir() + ax7WriteFile(t, filepath.Join(dir, "roles", "web", "tasks", "main.yml"), "- debug:\n msg: ok\n") + parser := NewParser(dir) + roles, err := parser.ParseRoles(filepath.Join(dir, "roles")) + core.AssertNoError(t, err) + core.AssertContains(t, roles, "web") +} + +func TestAX7_Parser_ParseRoles_Bad(t *core.T) { + parser := NewParser(t.TempDir()) + roles, err := parser.ParseRoles("missing") + core.AssertError(t, err) + core.AssertNil(t, roles) +} + +func TestAX7_Parser_ParseRoles_Ugly(t *core.T) { + dir := t.TempDir() + core.RequireNoError(t, os.MkdirAll(filepath.Join(dir, "roles"), 0o755)) + parser := NewParser(dir) + roles, err := parser.ParseRoles(filepath.Join(dir, "roles")) + core.AssertNoError(t, err) + core.AssertLen(t, roles, 0) +} + +func TestAX7_Parser_ParseRole_Good(t *core.T) { + dir := t.TempDir() + ax7WriteFile(t, filepath.Join(dir, "roles", "web", "tasks", "main.yml"), "- debug:\n msg: ok\n") + parser := NewParser(dir) + tasks, err := parser.ParseRole("web", "main.yml") + core.AssertNoError(t, err) + core.AssertLen(t, tasks, 1) +} + +func TestAX7_Parser_ParseRole_Bad(t *core.T) { + parser := NewParser(t.TempDir()) + tasks, err := parser.ParseRole("missing", "main.yml") + core.AssertError(t, err) + core.AssertNil(t, tasks) +} + +func TestAX7_Parser_ParseRole_Ugly(t *core.T) { + dir := t.TempDir() + ax7WriteFile(t, filepath.Join(dir, "roles", "web", "tasks", "alt.yml"), "- debug:\n msg: alt\n") + parser := NewParser(dir) + tasks, err := parser.ParseRole("web", "alt.yml") + core.AssertNoError(t, err) + core.AssertLen(t, tasks, 1) +} + +func TestAX7_NormalizeModule_Bad(t *core.T) { + module := NormalizeModule("custom.collection.module") + core.AssertEqual(t, "custom.collection.module", module) + core.AssertNotEqual(t, "ansible.builtin.custom.collection.module", module) +} + +func TestAX7_NormalizeModule_Ugly(t *core.T) { + module := NormalizeModule("ansible.legacy.shell") + core.AssertEqual(t, "ansible.builtin.shell", module) + core.AssertNotEqual(t, "ansible.legacy.shell", module) +} + +func TestAX7_GetHosts_Good(t *core.T) { + inv := ax7Inventory() + hosts := GetHosts(inv, "db") + core.AssertEqual(t, []string{"db1"}, hosts) + core.AssertContains(t, hosts, "db1") +} + +func TestAX7_GetHosts_Bad(t *core.T) { + inv := ax7Inventory() + hosts := GetHosts(inv, "missing") + core.AssertNil(t, hosts) + core.AssertLen(t, hosts, 0) +} + +func TestAX7_GetHosts_Ugly(t *core.T) { + inv := ax7Inventory() + hosts := GetHosts(inv, "all:!db") + core.AssertEqual(t, []string{"web1"}, hosts) + core.AssertNotContains(t, hosts, "db1") +} + +func TestAX7_GetHostsIter_Bad(t *core.T) { + inv := ax7Inventory() + seq := GetHostsIter(inv, "missing") + count := 0 + for range seq { + count++ + } + core.AssertEqual(t, 0, count) +} + +func TestAX7_GetHostsIter_Ugly(t *core.T) { + inv := ax7Inventory() + seq := GetHostsIter(inv, "all") + count := 0 + seq(func(string) bool { + count++ + return false + }) + core.AssertEqual(t, 1, count) +} + +func TestAX7_AllHostsIter_Bad(t *core.T) { + seq := AllHostsIter(nil) + count := 0 + for range seq { + count++ + } + core.AssertEqual(t, 0, count) +} + +func TestAX7_AllHostsIter_Ugly(t *core.T) { + seq := AllHostsIter(ax7Inventory().All) + count := 0 + seq(func(string) bool { + count++ + return false + }) + core.AssertEqual(t, 1, count) +} + +func TestAX7_GetHostVars_Good(t *core.T) { + inv := ax7Inventory() + vars := GetHostVars(inv, "db1") + core.AssertEqual(t, "test", vars["env"]) + core.AssertEqual(t, "database", vars["tier"]) + core.AssertEqual(t, "primary", vars["role"]) +} + +func TestAX7_GetHostVars_Bad(t *core.T) { + inv := ax7Inventory() + vars := GetHostVars(inv, "missing") + core.AssertLen(t, vars, 0) + core.AssertNotContains(t, vars, "role") +} + +func TestAX7_GetHostVars_Ugly(t *core.T) { + vars := GetHostVars(nil, "db1") + core.AssertNotNil(t, vars) + core.AssertLen(t, vars, 0) +} + +func TestAX7_Play_UnmarshalYAML_Good(t *core.T) { + var play Play + err := yaml.Unmarshal([]byte("hosts: all\nansible.builtin.import_playbook: child.yml\n"), &play) + core.AssertNoError(t, err) + core.AssertEqual(t, "all", play.Hosts) + core.AssertEqual(t, "child.yml", play.ImportPlaybook) +} + +func TestAX7_Play_UnmarshalYAML_Bad(t *core.T) { + var play Play + err := yaml.Unmarshal([]byte("hosts: ["), &play) + core.AssertError(t, err) + core.AssertEmpty(t, play.Hosts) +} + +func TestAX7_Play_UnmarshalYAML_Ugly(t *core.T) { + var play Play + err := yaml.Unmarshal([]byte("hosts: localhost\ngather_facts: false\n"), &play) + core.AssertNoError(t, err) + core.AssertNotNil(t, play.GatherFacts) + core.AssertFalse(t, *play.GatherFacts) +} + +func TestAX7_RoleRef_UnmarshalYAML_Good(t *core.T) { + var ref RoleRef + err := yaml.Unmarshal([]byte("web\n"), &ref) + core.AssertNoError(t, err) + core.AssertEqual(t, "web", ref.Role) +} + +func TestAX7_RoleRef_UnmarshalYAML_Bad(t *core.T) { + var ref RoleRef + err := yaml.Unmarshal([]byte("- web\n"), &ref) + core.AssertError(t, err) + core.AssertEmpty(t, ref.Role) +} + +func TestAX7_RoleRef_UnmarshalYAML_Ugly(t *core.T) { + var ref RoleRef + err := yaml.Unmarshal([]byte("name: db\ntags: [setup]\n"), &ref) + core.AssertNoError(t, err) + core.AssertEqual(t, "db", ref.Role) + core.AssertEqual(t, []string{"setup"}, ref.Tags) +} + +func TestAX7_Task_UnmarshalYAML_Good(t *core.T) { + var task Task + err := yaml.Unmarshal([]byte("name: hello\nshell: echo hi\n"), &task) + core.AssertNoError(t, err) + core.AssertEqual(t, "hello", task.Name) + core.AssertEqual(t, "shell", task.Module) +} + +func TestAX7_Task_UnmarshalYAML_Bad(t *core.T) { + var task Task + err := yaml.Unmarshal([]byte("42\n"), &task) + core.AssertError(t, err) + core.AssertEmpty(t, task.Module) +} + +func TestAX7_Task_UnmarshalYAML_Ugly(t *core.T) { + var task Task + err := yaml.Unmarshal([]byte("ansible.builtin.include_role:\n name: web\n"), &task) + core.AssertNoError(t, err) + core.AssertNotNil(t, task.IncludeRole) + core.AssertEqual(t, "web", task.IncludeRole.Role) +} + +func TestAX7_Inventory_UnmarshalYAML_Good(t *core.T) { + var inv Inventory + err := yaml.Unmarshal([]byte("all:\n hosts:\n web1: {}\n"), &inv) + core.AssertNoError(t, err) + core.AssertContains(t, inv.All.Hosts, "web1") +} + +func TestAX7_Inventory_UnmarshalYAML_Bad(t *core.T) { + var inv Inventory + err := yaml.Unmarshal([]byte("all: ["), &inv) + core.AssertError(t, err) + core.AssertNil(t, inv.All) +} + +func TestAX7_Inventory_UnmarshalYAML_Ugly(t *core.T) { + var inv Inventory + err := yaml.Unmarshal([]byte("web:\n hosts:\n web1: {}\nhost_vars:\n web1:\n role: app\n"), &inv) + core.AssertNoError(t, err) + core.AssertContains(t, inv.All.Children, "web") + core.AssertEqual(t, "app", inv.HostVars["web1"]["role"]) +} diff --git a/cmd/ansible/ansible.go b/cmd/ansible/ansible.go index 12b8549..596f806 100644 --- a/cmd/ansible/ansible.go +++ b/cmd/ansible/ansible.go @@ -8,7 +8,7 @@ import ( "strings" "time" - "dappco.re/go/core" + "dappco.re/go" "dappco.re/go/ansible" coreio "dappco.re/go/io" coreerr "dappco.re/go/log" @@ -342,7 +342,7 @@ func diffOutputLines(diff map[string]any) []string { func runPlaybookCommand(opts core.Options) core.Result { settings, err := buildPlaybookCommandSettings(opts, os.Args[1:]) if err != nil { - return core.Result{Value: err} + return core.Fail(err) } executor := ansible.NewExecutor(settings.basePath) @@ -366,7 +366,7 @@ func runPlaybookCommand(opts core.Options) core.Result { } if !coreio.Local.Exists(inventoryPath) { - return core.Result{Value: coreerr.E("runPlaybookCommand", sprintf("inventory not found: %s", inventoryPath), nil)} + return core.Fail(coreerr.E("runPlaybookCommand", sprintf("inventory not found: %s", inventoryPath), nil)) } if coreio.Local.IsDir(inventoryPath) { @@ -380,7 +380,7 @@ func runPlaybookCommand(opts core.Options) core.Result { } if err := executor.SetInventory(inventoryPath); err != nil { - return core.Result{Value: coreerr.E("runPlaybookCommand", "load inventory", err)} + return core.Fail(coreerr.E("runPlaybookCommand", "load inventory", err)) } } @@ -452,19 +452,19 @@ func runPlaybookCommand(opts core.Options) core.Result { print("Running playbook: %s", settings.playbookPath) if err := executor.Run(ctx, settings.playbookPath); err != nil { - return core.Result{Value: coreerr.E("runPlaybookCommand", "playbook failed", err)} + return core.Fail(coreerr.E("runPlaybookCommand", "playbook failed", err)) } print("") print("Playbook completed in %s", time.Since(start).Round(time.Millisecond)) - return core.Result{OK: true} + return core.Ok(nil) } func runSSHTestCommand(opts core.Options) core.Result { positional := positionalArgs(opts) if len(positional) < 1 { - return core.Result{Value: coreerr.E("runSSHTestCommand", "usage: ansible test ", nil)} + return core.Fail(coreerr.E("runSSHTestCommand", "usage: ansible test ", nil)) } host := positional[0] @@ -481,9 +481,13 @@ func runSSHTestCommand(opts core.Options) core.Result { client, err := ansible.NewSSHClient(config) if err != nil { - return core.Result{Value: coreerr.E("runSSHTestCommand", "create client", err)} + return core.Fail(coreerr.E("runSSHTestCommand", "create client", err)) } - defer func() { _ = client.Close() }() + defer func() { + if err := client.Close(); err != nil { + return + } + }() ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() @@ -491,7 +495,7 @@ func runSSHTestCommand(opts core.Options) core.Result { // Test connection start := time.Now() if err := client.Connect(ctx); err != nil { - return core.Result{Value: coreerr.E("runSSHTestCommand", "connect failed", err)} + return core.Fail(coreerr.E("runSSHTestCommand", "connect failed", err)) } connectTime := time.Since(start) @@ -538,5 +542,5 @@ func runSSHTestCommand(opts core.Options) core.Result { print("") print("SSH test passed") - return core.Result{OK: true} + return core.Ok(nil) } diff --git a/cmd/ansible/ansible_test.go b/cmd/ansible/ansible_test.go index 34a958c..ff02653 100644 --- a/cmd/ansible/ansible_test.go +++ b/cmd/ansible/ansible_test.go @@ -3,14 +3,11 @@ package ansiblecmd import ( "os" "path/filepath" - "testing" - "dappco.re/go/core" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + "dappco.re/go" ) -func TestExtraVars_Good_RepeatableAndCommaSeparated(t *testing.T) { +func TestExtraVars_Good_RepeatableAndCommaSeparated(t *core.T) { opts := core.NewOptions( core.Option{Key: "extra-vars", Value: "version=1.2.3,env=prod"}, core.Option{Key: "extra-vars", Value: "region=us-east-1"}, @@ -18,9 +15,9 @@ func TestExtraVars_Good_RepeatableAndCommaSeparated(t *testing.T) { ) vars, err := extraVars(opts) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Equal(t, map[string]any{ + core.AssertEqual(t, map[string]any{ "version": "1.2.3", "env": "prod", "region": "us-east-1", @@ -28,79 +25,81 @@ func TestExtraVars_Good_RepeatableAndCommaSeparated(t *testing.T) { }, vars) } -func TestExtraVars_Good_UsesShortAlias(t *testing.T) { +func TestExtraVars_Good_UsesShortAlias(t *core.T) { opts := core.NewOptions( core.Option{Key: "e", Value: "version=1.2.3,env=prod"}, ) vars, err := extraVars(opts) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Equal(t, map[string]any{ + core.AssertEqual(t, map[string]any{ "version": "1.2.3", "env": "prod", }, vars) } -func TestExtraVars_Good_TrimsWhitespaceAroundPairs(t *testing.T) { +func TestExtraVars_Good_TrimsWhitespaceAroundPairs(t *core.T) { opts := core.NewOptions( core.Option{Key: "extra-vars", Value: " version = 1.2.3 , env = prod , empty = "}, ) vars, err := extraVars(opts) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Equal(t, map[string]any{ + core.AssertEqual(t, map[string]any{ "version": "1.2.3", "env": "prod", "empty": "", }, vars) } -func TestExtraVars_Good_IgnoresMalformedPairs(t *testing.T) { +func TestExtraVars_Good_IgnoresMalformedPairs(t *core.T) { opts := core.NewOptions( core.Option{Key: "extra-vars", Value: "missing_equals,keep=this"}, core.Option{Key: "extra-vars", Value: "also_bad="}, ) vars, err := extraVars(opts) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Equal(t, map[string]any{ + core.AssertEqual(t, map[string]any{ "keep": "this", "also_bad": "", }, vars) } -func TestExtraVars_Good_ParsesYAMLScalarsInKeyValuePairs(t *testing.T) { +func TestExtraVars_Good_ParsesYAMLScalarsInKeyValuePairs(t *core.T) { opts := core.NewOptions( core.Option{Key: "extra-vars", Value: "enabled=true,count=42,threshold=3.5"}, ) vars, err := extraVars(opts) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Equal(t, map[string]any{ + core.AssertEqual(t, map[string]any{ "enabled": true, "count": 42, "threshold": 3.5, }, vars) } -func TestSplitCommaSeparatedOption_Good_TrimsWhitespace(t *testing.T) { - assert.Equal(t, []string{"deploy", "setup", "smoke"}, splitCommaSeparatedOption(" deploy, setup ,smoke ")) +func TestSplitCommaSeparatedOption_Good_TrimsWhitespace(t *core.T) { + result := splitCommaSeparatedOption(" deploy, setup ,smoke ") + core.AssertEqual(t, []string{"deploy", "setup", "smoke"}, result) + core.AssertLen(t, result, 3) } -func TestExtraVars_Good_SupportsStructuredYAMLAndJSON(t *testing.T) { +func TestExtraVars_Good_SupportsStructuredYAMLAndJSON(t *core.T) { opts := core.NewOptions( core.Option{Key: "extra-vars", Value: "app:\n port: 8080\n debug: true"}, core.Option{Key: "extra-vars", Value: `{"image":"nginx:latest","replicas":3}`}, ) vars, err := extraVars(opts) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Equal(t, map[string]any{ + core.AssertEqual(t, map[string]any{ "app": map[string]any{ "port": int(8080), "debug": true, @@ -110,73 +109,76 @@ func TestExtraVars_Good_SupportsStructuredYAMLAndJSON(t *testing.T) { }, vars) } -func TestExtraVars_Good_LoadsFileReferences(t *testing.T) { +func TestExtraVars_Good_LoadsFileReferences(t *core.T) { dir := t.TempDir() path := filepath.Join(dir, "vars.yml") - require.NoError(t, os.WriteFile(path, []byte("deploy_env: prod\nrelease: 42\n"), 0644)) + core.RequireNoError(t, os.WriteFile(path, []byte("deploy_env: prod\nrelease: 42\n"), 0644)) opts := core.NewOptions( core.Option{Key: "extra-vars", Value: "@" + path}, ) vars, err := extraVars(opts) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Equal(t, map[string]any{ + core.AssertEqual(t, map[string]any{ "deploy_env": "prod", "release": int(42), }, vars) } -func TestExtraVars_Bad_MissingFile(t *testing.T) { +func TestExtraVars_Bad_MissingFile(t *core.T) { opts := core.NewOptions( core.Option{Key: "extra-vars", Value: "@/definitely/missing/vars.yml"}, ) _, err := extraVars(opts) - require.Error(t, err) - assert.Contains(t, err.Error(), "read extra vars file") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "read extra vars file") } -func TestFirstString_Good_PrefersFirstNonEmptyKey(t *testing.T) { +func TestFirstString_Good_PrefersFirstNonEmptyKey(t *core.T) { opts := core.NewOptions( core.Option{Key: "inventory", Value: ""}, core.Option{Key: "i", Value: "/tmp/inventory.yml"}, ) - assert.Equal(t, "/tmp/inventory.yml", firstStringOption(opts, "inventory", "i")) + core.AssertEqual(t, "/tmp/inventory.yml", firstStringOption(opts, "inventory", "i")) } -func TestFirstBool_Good_UsesAlias(t *testing.T) { +func TestFirstBool_Good_UsesAlias(t *core.T) { opts := core.NewOptions( core.Option{Key: "v", Value: true}, ) - assert.True(t, firstBoolOption(opts, "verbose", "v")) + core.AssertTrue(t, firstBoolOption(opts, "verbose", "v")) } -func TestVerbosityLevel_Good_CountsStackedShortFlags(t *testing.T) { +func TestVerbosityLevel_Good_CountsStackedShortFlags(t *core.T) { opts := core.NewOptions() + result := verbosityLevel(opts, []string{"-vvv"}) - assert.Equal(t, 3, verbosityLevel(opts, []string{"-vvv"})) + core.AssertEqual(t, 3, result) } -func TestVerbosityLevel_Good_CountsLongForm(t *testing.T) { +func TestVerbosityLevel_Good_CountsLongForm(t *core.T) { opts := core.NewOptions() + result := verbosityLevel(opts, []string{"--verbose"}) - assert.Equal(t, 1, verbosityLevel(opts, []string{"--verbose"})) + core.AssertEqual(t, 1, result) } -func TestVerbosityLevel_Good_PreservesExplicitNumericLevel(t *testing.T) { +func TestVerbosityLevel_Good_PreservesExplicitNumericLevel(t *core.T) { opts := core.NewOptions(core.Option{Key: "verbose", Value: 2}) + result := verbosityLevel(opts, nil) - assert.Equal(t, 2, verbosityLevel(opts, nil)) + core.AssertEqual(t, 2, result) } -func TestBuildPlaybookCommandSettings_Good_AppliesFlags(t *testing.T) { +func TestBuildPlaybookCommandSettings_Good_AppliesFlags(t *core.T) { dir := t.TempDir() playbookPath := filepath.Join(dir, "site.yml") - require.NoError(t, os.WriteFile(playbookPath, []byte("- hosts: all\n tasks: []\n"), 0644)) + core.RequireNoError(t, os.WriteFile(playbookPath, []byte("- hosts: all\n tasks: []\n"), 0644)) opts := core.NewOptions( core.Option{Key: "_arg", Value: playbookPath}, @@ -189,23 +191,23 @@ func TestBuildPlaybookCommandSettings_Good_AppliesFlags(t *testing.T) { ) settings, err := buildPlaybookCommandSettings(opts, []string{"-vvv"}) - require.NoError(t, err) - - assert.Equal(t, playbookPath, settings.playbookPath) - assert.Equal(t, dir, settings.basePath) - assert.Equal(t, "web1", settings.limit) - assert.Equal(t, []string{"deploy", "setup"}, settings.tags) - assert.Equal(t, []string{"slow"}, settings.skipTags) - assert.Equal(t, 3, settings.verbose) - assert.True(t, settings.checkMode) - assert.True(t, settings.diff) - assert.Equal(t, map[string]any{"version": "1.2.3"}, settings.extraVars) + core.RequireNoError(t, err) + + core.AssertEqual(t, playbookPath, settings.playbookPath) + core.AssertEqual(t, dir, settings.basePath) + core.AssertEqual(t, "web1", settings.limit) + core.AssertEqual(t, []string{"deploy", "setup"}, settings.tags) + core.AssertEqual(t, []string{"slow"}, settings.skipTags) + core.AssertEqual(t, 3, settings.verbose) + core.AssertTrue(t, settings.checkMode) + core.AssertTrue(t, settings.diff) + core.AssertEqual(t, map[string]any{"version": "1.2.3"}, settings.extraVars) } -func TestBuildPlaybookCommandSettings_Good_MergesRepeatedListFlags(t *testing.T) { +func TestBuildPlaybookCommandSettings_Good_MergesRepeatedListFlags(t *core.T) { dir := t.TempDir() playbookPath := filepath.Join(dir, "site.yml") - require.NoError(t, os.WriteFile(playbookPath, []byte("- hosts: all\n tasks: []\n"), 0644)) + core.RequireNoError(t, os.WriteFile(playbookPath, []byte("- hosts: all\n tasks: []\n"), 0644)) opts := core.NewOptions( core.Option{Key: "_arg", Value: playbookPath}, @@ -218,28 +220,28 @@ func TestBuildPlaybookCommandSettings_Good_MergesRepeatedListFlags(t *testing.T) ) settings, err := buildPlaybookCommandSettings(opts, nil) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Equal(t, "web1,web2", settings.limit) - assert.Equal(t, []string{"deploy", "setup", "smoke"}, settings.tags) - assert.Equal(t, []string{"slow", "flaky", "experimental"}, settings.skipTags) + core.AssertEqual(t, "web1,web2", settings.limit) + core.AssertEqual(t, []string{"deploy", "setup", "smoke"}, settings.tags) + core.AssertEqual(t, []string{"slow", "flaky", "experimental"}, settings.skipTags) } -func TestBuildPlaybookCommandSettings_Bad_MissingPlaybook(t *testing.T) { +func TestBuildPlaybookCommandSettings_Bad_MissingPlaybook(t *core.T) { _, err := buildPlaybookCommandSettings(core.NewOptions(), nil) - require.Error(t, err) - assert.Contains(t, err.Error(), "usage: ansible ") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "usage: ansible ") } -func TestDiffOutputLines_Good_IncludesPathAndBeforeAfter(t *testing.T) { +func TestDiffOutputLines_Good_IncludesPathAndBeforeAfter(t *core.T) { lines := diffOutputLines(map[string]any{ "path": "/etc/nginx/conf.d/app.conf", "before": "server_name=old.example.com;", "after": "server_name=web01.example.com;", }) - assert.Equal(t, []string{ + core.AssertEqual(t, []string{ "diff:", "path: /etc/nginx/conf.d/app.conf", "- server_name=old.example.com;", @@ -247,125 +249,125 @@ func TestDiffOutputLines_Good_IncludesPathAndBeforeAfter(t *testing.T) { }, lines) } -func TestTestKeyFile_Good_PrefersExplicitKey(t *testing.T) { +func TestTestKeyFile_Good_PrefersExplicitKey(t *core.T) { opts := core.NewOptions( core.Option{Key: "key", Value: "/tmp/id_ed25519"}, core.Option{Key: "i", Value: "/tmp/ignored"}, ) - assert.Equal(t, "/tmp/id_ed25519", resolveSSHTestKeyFile(opts)) + core.AssertEqual(t, "/tmp/id_ed25519", resolveSSHTestKeyFile(opts)) } -func TestTestKeyFile_Good_FallsBackToShortAlias(t *testing.T) { +func TestTestKeyFile_Good_FallsBackToShortAlias(t *core.T) { opts := core.NewOptions( core.Option{Key: "i", Value: "/tmp/id_ed25519"}, ) - assert.Equal(t, "/tmp/id_ed25519", resolveSSHTestKeyFile(opts)) + core.AssertEqual(t, "/tmp/id_ed25519", resolveSSHTestKeyFile(opts)) } -func TestFirstString_Good_ResolvesShortUserAlias(t *testing.T) { +func TestFirstString_Good_ResolvesShortUserAlias(t *core.T) { opts := core.NewOptions( core.Option{Key: "u", Value: "deploy"}, ) cfgUser := firstStringOption(opts, "user", "u") - assert.Equal(t, "deploy", cfgUser) + core.AssertEqual(t, "deploy", cfgUser) } -func TestRegister_Good_RegistersAnsibleCommands(t *testing.T) { +func TestRegister_Good_RegistersAnsibleCommands(t *core.T) { app := core.New() Register(app) ansible := app.Command("ansible") - require.True(t, ansible.OK) + core.RequireTrue(t, ansible.OK) ansibleCmd := ansible.Value.(*core.Command) - assert.Equal(t, "ansible", ansibleCmd.Path) - assert.Equal(t, "ansible", ansibleCmd.Name) - assert.Equal(t, "Run Ansible playbooks natively (no Python required)", ansibleCmd.Description) - require.NotNil(t, ansibleCmd.Action) + core.AssertEqual(t, "ansible", ansibleCmd.Path) + core.AssertEqual(t, "ansible", ansibleCmd.Name) + core.AssertEqual(t, "Run Ansible playbooks natively (no Python required)", ansibleCmd.Description) + core.AssertNotNil(t, ansibleCmd.Action) test := app.Command("ansible/test") - require.True(t, test.OK) + core.RequireTrue(t, test.OK) testCmd := test.Value.(*core.Command) - assert.Equal(t, "ansible/test", testCmd.Path) - assert.Equal(t, "test", testCmd.Name) - assert.Equal(t, "Test SSH connectivity to a host", testCmd.Description) - require.NotNil(t, testCmd.Action) + core.AssertEqual(t, "ansible/test", testCmd.Path) + core.AssertEqual(t, "test", testCmd.Name) + core.AssertEqual(t, "Test SSH connectivity to a host", testCmd.Description) + core.AssertNotNil(t, testCmd.Action) paths := app.Commands() - assert.Contains(t, paths, "ansible") - assert.Contains(t, paths, "ansible/test") + core.AssertContains(t, paths, "ansible") + core.AssertContains(t, paths, "ansible/test") } -func TestRegister_Good_ExposesExpectedFlags(t *testing.T) { +func TestRegister_Good_ExposesExpectedFlags(t *core.T) { app := core.New() Register(app) ansibleCmd := app.Command("ansible").Value.(*core.Command) - assert.True(t, ansibleCmd.Flags.Has("inventory")) - assert.True(t, ansibleCmd.Flags.Has("i")) - assert.True(t, ansibleCmd.Flags.Has("limit")) - assert.True(t, ansibleCmd.Flags.Has("l")) - assert.True(t, ansibleCmd.Flags.Has("tags")) - assert.True(t, ansibleCmd.Flags.Has("t")) - assert.True(t, ansibleCmd.Flags.Has("skip-tags")) - assert.True(t, ansibleCmd.Flags.Has("extra-vars")) - assert.True(t, ansibleCmd.Flags.Has("e")) - assert.True(t, ansibleCmd.Flags.Has("verbose")) - assert.True(t, ansibleCmd.Flags.Has("v")) - assert.True(t, ansibleCmd.Flags.Has("check")) - assert.True(t, ansibleCmd.Flags.Has("diff")) - - assert.Equal(t, "", ansibleCmd.Flags.String("inventory")) - assert.Equal(t, "", ansibleCmd.Flags.String("i")) - assert.Equal(t, "", ansibleCmd.Flags.String("limit")) - assert.Equal(t, "", ansibleCmd.Flags.String("l")) - assert.Equal(t, "", ansibleCmd.Flags.String("tags")) - assert.Equal(t, "", ansibleCmd.Flags.String("t")) - assert.Equal(t, "", ansibleCmd.Flags.String("skip-tags")) - assert.Equal(t, "", ansibleCmd.Flags.String("extra-vars")) - assert.Equal(t, "", ansibleCmd.Flags.String("e")) - assert.Equal(t, 0, ansibleCmd.Flags.Int("verbose")) - assert.False(t, ansibleCmd.Flags.Bool("v")) - assert.False(t, ansibleCmd.Flags.Bool("check")) - assert.False(t, ansibleCmd.Flags.Bool("diff")) + core.AssertTrue(t, ansibleCmd.Flags.Has("inventory")) + core.AssertTrue(t, ansibleCmd.Flags.Has("i")) + core.AssertTrue(t, ansibleCmd.Flags.Has("limit")) + core.AssertTrue(t, ansibleCmd.Flags.Has("l")) + core.AssertTrue(t, ansibleCmd.Flags.Has("tags")) + core.AssertTrue(t, ansibleCmd.Flags.Has("t")) + core.AssertTrue(t, ansibleCmd.Flags.Has("skip-tags")) + core.AssertTrue(t, ansibleCmd.Flags.Has("extra-vars")) + core.AssertTrue(t, ansibleCmd.Flags.Has("e")) + core.AssertTrue(t, ansibleCmd.Flags.Has("verbose")) + core.AssertTrue(t, ansibleCmd.Flags.Has("v")) + core.AssertTrue(t, ansibleCmd.Flags.Has("check")) + core.AssertTrue(t, ansibleCmd.Flags.Has("diff")) + + core.AssertEqual(t, "", ansibleCmd.Flags.String("inventory")) + core.AssertEqual(t, "", ansibleCmd.Flags.String("i")) + core.AssertEqual(t, "", ansibleCmd.Flags.String("limit")) + core.AssertEqual(t, "", ansibleCmd.Flags.String("l")) + core.AssertEqual(t, "", ansibleCmd.Flags.String("tags")) + core.AssertEqual(t, "", ansibleCmd.Flags.String("t")) + core.AssertEqual(t, "", ansibleCmd.Flags.String("skip-tags")) + core.AssertEqual(t, "", ansibleCmd.Flags.String("extra-vars")) + core.AssertEqual(t, "", ansibleCmd.Flags.String("e")) + core.AssertEqual(t, 0, ansibleCmd.Flags.Int("verbose")) + core.AssertFalse(t, ansibleCmd.Flags.Bool("v")) + core.AssertFalse(t, ansibleCmd.Flags.Bool("check")) + core.AssertFalse(t, ansibleCmd.Flags.Bool("diff")) testCmd := app.Command("ansible/test").Value.(*core.Command) - assert.True(t, testCmd.Flags.Has("user")) - assert.True(t, testCmd.Flags.Has("u")) - assert.True(t, testCmd.Flags.Has("password")) - assert.True(t, testCmd.Flags.Has("key")) - assert.True(t, testCmd.Flags.Has("i")) - assert.True(t, testCmd.Flags.Has("port")) - - assert.Equal(t, "root", testCmd.Flags.String("user")) - assert.Equal(t, "root", testCmd.Flags.String("u")) - assert.Equal(t, "", testCmd.Flags.String("password")) - assert.Equal(t, "", testCmd.Flags.String("key")) - assert.Equal(t, "", testCmd.Flags.String("i")) - assert.Equal(t, 22, testCmd.Flags.Int("port")) + core.AssertTrue(t, testCmd.Flags.Has("user")) + core.AssertTrue(t, testCmd.Flags.Has("u")) + core.AssertTrue(t, testCmd.Flags.Has("password")) + core.AssertTrue(t, testCmd.Flags.Has("key")) + core.AssertTrue(t, testCmd.Flags.Has("i")) + core.AssertTrue(t, testCmd.Flags.Has("port")) + + core.AssertEqual(t, "root", testCmd.Flags.String("user")) + core.AssertEqual(t, "root", testCmd.Flags.String("u")) + core.AssertEqual(t, "", testCmd.Flags.String("password")) + core.AssertEqual(t, "", testCmd.Flags.String("key")) + core.AssertEqual(t, "", testCmd.Flags.String("i")) + core.AssertEqual(t, 22, testCmd.Flags.Int("port")) } -func TestRunAnsible_Bad_MissingPlaybook(t *testing.T) { +func TestRunAnsible_Bad_MissingPlaybook(t *core.T) { result := runPlaybookCommand(core.NewOptions()) - require.False(t, result.OK) + core.AssertFalse(t, result.OK) err, ok := result.Value.(error) - require.True(t, ok) - assert.Contains(t, err.Error(), "usage: ansible ") + core.RequireTrue(t, ok) + core.AssertContains(t, err.Error(), "usage: ansible ") } -func TestRunAnsibleTest_Bad_MissingHost(t *testing.T) { +func TestRunAnsibleTest_Bad_MissingHost(t *core.T) { result := runSSHTestCommand(core.NewOptions()) - require.False(t, result.OK) + core.AssertFalse(t, result.OK) err, ok := result.Value.(error) - require.True(t, ok) - assert.Contains(t, err.Error(), "usage: ansible test ") + core.RequireTrue(t, ok) + core.AssertContains(t, err.Error(), "usage: ansible test ") } diff --git a/cmd/ansible/ax7_register_test.go b/cmd/ansible/ax7_register_test.go new file mode 100644 index 0000000..3b67962 --- /dev/null +++ b/cmd/ansible/ax7_register_test.go @@ -0,0 +1,28 @@ +package ansiblecmd + +import core "dappco.re/go" + +func TestAX7_Register_Good(t *core.T) { + app := core.New() + Register(app) + ansible := app.Command("ansible") + core.AssertTrue(t, ansible.OK) + core.AssertNotNil(t, ansible.Value) +} + +func TestAX7_Register_Bad(t *core.T) { + var app *core.Core + core.AssertPanics(t, func() { + Register(app) + }) + core.AssertNil(t, app) +} + +func TestAX7_Register_Ugly(t *core.T) { + app := core.New() + Register(app) + Register(app) + testCommand := app.Command("ansible/test") + core.AssertTrue(t, testCommand.OK) + core.AssertNotNil(t, testCommand.Value) +} diff --git a/cmd/ansible/cmd.go b/cmd/ansible/cmd.go index 0c057fe..50dae22 100644 --- a/cmd/ansible/cmd.go +++ b/cmd/ansible/cmd.go @@ -1,15 +1,15 @@ package ansiblecmd import ( - "dappco.re/go/core" + "dappco.re/go" ) // Register registers the `ansible` command and its `ansible/test` subcommand. // // Example: // -// var app core.Core -// Register(&app) +// app := core.New() +// Register(app) func Register(c *core.Core) { c.Command("ansible", core.Command{ Description: "Run Ansible playbooks natively (no Python required)", diff --git a/cmd/ansible/core_primitives.go b/cmd/ansible/core_primitives.go index f9962c9..5f5ea22 100644 --- a/cmd/ansible/core_primitives.go +++ b/cmd/ansible/core_primitives.go @@ -4,7 +4,7 @@ import ( "unicode" "unicode/utf8" - "dappco.re/go/core" + "dappco.re/go" ) func absPath(path string) string { diff --git a/core_primitives.go b/core_primitives.go index c8ba482..a8c27ab 100644 --- a/core_primitives.go +++ b/core_primitives.go @@ -4,7 +4,7 @@ import ( "unicode" "unicode/utf8" - core "dappco.re/go/core" + core "dappco.re/go" ) type stringBuffer interface { diff --git a/executor.go b/executor.go index 9080af4..4bfd66a 100644 --- a/executor.go +++ b/executor.go @@ -2491,7 +2491,7 @@ func (e *Executor) getClient(host string, play *Play) (sshExecutorClient, error) cached.SetBecome(desiredBecome, desiredBecomeUser, desiredBecomePass) return cached, nil } - _ = cached.Close() + closeExecutorClient(cached) delete(e.clients, host) case *SSHClient: if !desiredLocal && @@ -2503,7 +2503,7 @@ func (e *Executor) getClient(host string, play *Play) (sshExecutorClient, error) cached.SetBecome(desiredBecome, desiredBecomeUser, desiredBecomePass) return cached, nil } - _ = cached.Close() + closeExecutorClient(cached) delete(e.clients, host) default: client.SetBecome(desiredBecome, desiredBecomeUser, desiredBecomePass) @@ -4511,7 +4511,7 @@ func (e *Executor) resetConnection(host string) { e.mu.Unlock() if ok { - _ = client.Close() + closeExecutorClient(client) } } @@ -4525,11 +4525,20 @@ func (e *Executor) Close() { defer e.mu.Unlock() for _, client := range e.clients { - _ = client.Close() + closeExecutorClient(client) } e.clients = make(map[string]sshExecutorClient) } +func closeExecutorClient(client sshExecutorClient) { + if client == nil { + return + } + if err := client.Close(); err != nil { + return + } +} + // TemplateFile processes a template file. // // Example: diff --git a/executor_become_test.go b/executor_become_test.go index f2fc5e6..12a5456 100644 --- a/executor_become_test.go +++ b/executor_become_test.go @@ -2,13 +2,10 @@ package ansible import ( "context" + core "dappco.re/go" "io" "io/fs" "sync" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) type becomeRecordingClient struct { @@ -75,7 +72,7 @@ func (c *becomeRecordingClient) Close() error { return nil } -func TestExecutor_RunTaskOnHost_Good_TaskBecomeFalseOverridesPlayBecome(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_TaskBecomeFalseOverridesPlayBecome(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -97,15 +94,15 @@ func TestExecutor_RunTaskOnHost_Good_TaskBecomeFalseOverridesPlayBecome(t *testi Become: func() *bool { v := false; return &v }(), } - require.NoError(t, e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, play)) - require.Len(t, client.runBecomeSeen, 1) - assert.False(t, client.runBecomeSeen[0]) - assert.True(t, client.become) - assert.Equal(t, "admin", client.becomeUser) - assert.Equal(t, "secret", client.becomePass) + core.RequireNoError(t, e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, play)) + core.AssertLen(t, client.runBecomeSeen, 1) + core.AssertFalse(t, client.runBecomeSeen[0]) + core.AssertTrue(t, client.become) + core.AssertEqual(t, "admin", client.becomeUser) + core.AssertEqual(t, "secret", client.becomePass) } -func TestExecutor_RunTaskOnHost_Good_TaskBecomeUsesInventoryPassword(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_TaskBecomeUsesInventoryPassword(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -129,9 +126,9 @@ func TestExecutor_RunTaskOnHost_Good_TaskBecomeUsesInventoryPassword(t *testing. Become: func() *bool { v := true; return &v }(), } - require.NoError(t, e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, play)) - require.Len(t, client.runBecomeSeen, 1) - assert.True(t, client.runBecomeSeen[0]) - require.Len(t, client.runBecomePass, 1) - assert.Equal(t, "secret", client.runBecomePass[0]) + core.RequireNoError(t, e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, play)) + core.AssertLen(t, client.runBecomeSeen, 1) + core.AssertTrue(t, client.runBecomeSeen[0]) + core.AssertLen(t, client.runBecomePass, 1) + core.AssertEqual(t, "secret", client.runBecomePass[0]) } diff --git a/executor_extra_test.go b/executor_extra_test.go index bb7ba59..395b5b3 100644 --- a/executor_extra_test.go +++ b/executor_extra_test.go @@ -2,11 +2,8 @@ package ansible import ( "context" + core "dappco.re/go" "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) // ============================================================ @@ -15,72 +12,72 @@ import ( // --- moduleDebug --- -func TestExecutorExtra_ModuleDebug_Good_Message(t *testing.T) { +func TestExecutorExtra_ModuleDebug_Good_Message(t *core.T) { e := NewExecutor("/tmp") result, err := e.moduleDebug("host1", nil, map[string]any{"msg": "Hello world"}) - require.NoError(t, err) - assert.False(t, result.Changed) - assert.Equal(t, "Hello world", result.Msg) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertEqual(t, "Hello world", result.Msg) } -func TestExecutorExtra_ModuleDebug_Good_Var(t *testing.T) { +func TestExecutorExtra_ModuleDebug_Good_Var(t *core.T) { e := NewExecutor("/tmp") e.setHostVars("host1", map[string]any{"my_version": "1.2.3"}) result, err := e.moduleDebug("host1", nil, map[string]any{"var": "my_version"}) - require.NoError(t, err) - assert.Contains(t, result.Msg, "1.2.3") + core.RequireNoError(t, err) + core.AssertContains(t, result.Msg, "1.2.3") } -func TestExecutorExtra_ModuleDebug_Good_EmptyArgs(t *testing.T) { +func TestExecutorExtra_ModuleDebug_Good_EmptyArgs(t *core.T) { e := NewExecutor("/tmp") result, err := e.moduleDebug("host1", nil, map[string]any{}) - require.NoError(t, err) - assert.Equal(t, "", result.Msg) + core.RequireNoError(t, err) + core.AssertEqual(t, "", result.Msg) } // --- moduleFail --- -func TestExecutorExtra_ModuleFail_Good_DefaultMessage(t *testing.T) { +func TestExecutorExtra_ModuleFail_Good_DefaultMessage(t *core.T) { e := NewExecutor("/tmp") result, err := e.moduleFail(map[string]any{}) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Equal(t, "Failed as requested", result.Msg) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertEqual(t, "Failed as requested", result.Msg) } -func TestExecutorExtra_ModuleFail_Good_CustomMessage(t *testing.T) { +func TestExecutorExtra_ModuleFail_Good_CustomMessage(t *core.T) { e := NewExecutor("/tmp") result, err := e.moduleFail(map[string]any{"msg": "deployment blocked"}) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Equal(t, "deployment blocked", result.Msg) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertEqual(t, "deployment blocked", result.Msg) } // --- modulePing --- -func TestExecutorExtra_ModulePing_Good_DefaultPong(t *testing.T) { +func TestExecutorExtra_ModulePing_Good_DefaultPong(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := executeModuleWithMock(e, mock, "host1", &Task{ Module: "ping", }) - require.NoError(t, err) - assert.False(t, result.Failed) - assert.False(t, result.Changed) - assert.Equal(t, "pong", result.Msg) - require.NotNil(t, result.Data) - assert.Equal(t, "pong", result.Data["ping"]) - assert.True(t, mock.hasExecuted(`^true$`)) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertFalse(t, result.Changed) + core.AssertEqual(t, "pong", result.Msg) + core.AssertNotNil(t, result.Data) + core.AssertEqual(t, "pong", result.Data["ping"]) + core.AssertTrue(t, mock.hasExecuted(`^true$`)) } -func TestExecutorExtra_ModulePing_Good_CustomData(t *testing.T) { +func TestExecutorExtra_ModulePing_Good_CustomData(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := executeModuleWithMock(e, mock, "host1", &Task{ @@ -90,14 +87,14 @@ func TestExecutorExtra_ModulePing_Good_CustomData(t *testing.T) { }, }) - require.NoError(t, err) - assert.False(t, result.Failed) - assert.Equal(t, "hello", result.Msg) - require.NotNil(t, result.Data) - assert.Equal(t, "hello", result.Data["ping"]) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, "hello", result.Msg) + core.AssertNotNil(t, result.Data) + core.AssertEqual(t, "hello", result.Data["ping"]) } -func TestExecutorExtra_ModuleSetFact_Good_ReturnsStructuredFacts(t *testing.T) { +func TestExecutorExtra_ModuleSetFact_Good_ReturnsStructuredFacts(t *core.T) { e := NewExecutor("/tmp") result, err := e.moduleSetFact("host1", map[string]any{ @@ -105,20 +102,20 @@ func TestExecutorExtra_ModuleSetFact_Good_ReturnsStructuredFacts(t *testing.T) { "cacheable": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - require.NotNil(t, result.Data) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertNotNil(t, result.Data) facts, ok := result.Data["ansible_facts"].(map[string]any) - require.True(t, ok) - assert.Equal(t, "1.2.3", facts["app_version"]) + core.RequireTrue(t, ok) + core.AssertEqual(t, "1.2.3", facts["app_version"]) _, cached := facts["cacheable"] - assert.False(t, cached) - assert.Equal(t, "1.2.3", e.hostScopedVars("host1")["app_version"]) + core.AssertFalse(t, cached) + core.AssertEqual(t, "1.2.3", e.hostScopedVars("host1")["app_version"]) _, cached = e.hostScopedVars("host1")["cacheable"] - assert.False(t, cached) + core.AssertFalse(t, cached) } -func TestExecutorExtra_ExecuteModule_Good_DelegateFactsStoresOnDelegateHost(t *testing.T) { +func TestExecutorExtra_ExecuteModule_Good_DelegateFactsStoresOnDelegateHost(t *core.T) { e := NewExecutor("/tmp") mock := NewMockSSHClient() @@ -130,15 +127,15 @@ func TestExecutorExtra_ExecuteModule_Good_DelegateFactsStoresOnDelegateHost(t *t } result, err := e.executeModule(context.Background(), "host1", mock, task, &Play{}) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "2.0.0", e.hostScopedVars("delegate1")["app_version"]) - assert.Nil(t, e.hostScopedVars("host1")) - assert.Equal(t, "2.0.0", e.hostFactsMap("delegate1")["app_version"]) - assert.Nil(t, e.hostFactsMap("host1")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "2.0.0", e.hostScopedVars("delegate1")["app_version"]) + core.AssertNil(t, e.hostScopedVars("host1")) + core.AssertEqual(t, "2.0.0", e.hostFactsMap("delegate1")["app_version"]) + core.AssertNil(t, e.hostFactsMap("host1")) } -func TestExecutorExtra_ExecuteModule_Good_LegacyNamespaceCommand(t *testing.T) { +func TestExecutorExtra_ExecuteModule_Good_LegacyNamespaceCommand(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("echo hello", "hello\n", "", 0) @@ -147,44 +144,44 @@ func TestExecutorExtra_ExecuteModule_Good_LegacyNamespaceCommand(t *testing.T) { Args: map[string]any{"_raw_params": "echo hello"}, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "hello\n", result.Stdout) - assert.True(t, mock.hasExecuted(`echo hello`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "hello\n", result.Stdout) + core.AssertTrue(t, mock.hasExecuted(`echo hello`)) } // --- moduleAssert --- -func TestExecutorExtra_ModuleAssert_Good_PassingAssertion(t *testing.T) { +func TestExecutorExtra_ModuleAssert_Good_PassingAssertion(t *core.T) { e := NewExecutor("/tmp") e.vars["enabled"] = true result, err := e.moduleAssert(map[string]any{"that": "enabled"}, "host1") - require.NoError(t, err) - assert.False(t, result.Failed) - assert.Equal(t, "All assertions passed", result.Msg) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, "All assertions passed", result.Msg) } -func TestExecutorExtra_ModuleAssert_Bad_FailingAssertion(t *testing.T) { +func TestExecutorExtra_ModuleAssert_Bad_FailingAssertion(t *core.T) { e := NewExecutor("/tmp") e.vars["enabled"] = false result, err := e.moduleAssert(map[string]any{"that": "enabled"}, "host1") - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, "Assertion failed") + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, "Assertion failed") } -func TestExecutorExtra_ModuleAssert_Bad_MissingThat(t *testing.T) { +func TestExecutorExtra_ModuleAssert_Bad_MissingThat(t *core.T) { e := NewExecutor("/tmp") _, err := e.moduleAssert(map[string]any{}, "host1") - assert.Error(t, err) + core.AssertError(t, err) } -func TestExecutorExtra_ModuleAssert_Good_CustomFailMsg(t *testing.T) { +func TestExecutorExtra_ModuleAssert_Good_CustomFailMsg(t *core.T) { e := NewExecutor("/tmp") e.vars["ready"] = false @@ -193,12 +190,12 @@ func TestExecutorExtra_ModuleAssert_Good_CustomFailMsg(t *testing.T) { "fail_msg": "Service not ready", }, "host1") - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Equal(t, "Service not ready", result.Msg) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertEqual(t, "Service not ready", result.Msg) } -func TestExecutorExtra_ModuleAssert_Good_MultipleConditions(t *testing.T) { +func TestExecutorExtra_ModuleAssert_Good_MultipleConditions(t *core.T) { e := NewExecutor("/tmp") e.vars["enabled"] = true e.vars["count"] = 5 @@ -207,13 +204,13 @@ func TestExecutorExtra_ModuleAssert_Good_MultipleConditions(t *testing.T) { "that": []any{"enabled", "count"}, }, "host1") - require.NoError(t, err) - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) } // --- moduleSetFact --- -func TestExecutorExtra_ModuleSetFact_Good(t *testing.T) { +func TestExecutorExtra_ModuleSetFact_Good(t *core.T) { e := NewExecutor("/tmp") result, err := e.moduleSetFact("host1", map[string]any{ @@ -221,14 +218,14 @@ func TestExecutorExtra_ModuleSetFact_Good(t *testing.T) { "deploy_env": "production", }) - require.NoError(t, err) - assert.True(t, result.Changed) - require.Contains(t, e.hostVars, "host1") - assert.Equal(t, "2.0.0", e.hostVars["host1"]["app_version"]) - assert.Equal(t, "production", e.hostVars["host1"]["deploy_env"]) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertContains(t, e.hostVars, "host1") + core.AssertEqual(t, "2.0.0", e.hostVars["host1"]["app_version"]) + core.AssertEqual(t, "production", e.hostVars["host1"]["deploy_env"]) } -func TestExecutorExtra_ModuleSetFact_Good_SkipsCacheable(t *testing.T) { +func TestExecutorExtra_ModuleSetFact_Good_SkipsCacheable(t *core.T) { e := NewExecutor("/tmp") e.moduleSetFact("host1", map[string]any{ @@ -236,52 +233,52 @@ func TestExecutorExtra_ModuleSetFact_Good_SkipsCacheable(t *testing.T) { "cacheable": true, }) - require.Contains(t, e.hostVars, "host1") - assert.Equal(t, "value", e.hostVars["host1"]["my_fact"]) + core.AssertContains(t, e.hostVars, "host1") + core.AssertEqual(t, "value", e.hostVars["host1"]["my_fact"]) _, hasCacheable := e.hostVars["host1"]["cacheable"] - assert.False(t, hasCacheable) + core.AssertFalse(t, hasCacheable) } -func TestExecutorExtra_ModuleSetFact_Good_HostScopedLookup(t *testing.T) { +func TestExecutorExtra_ModuleSetFact_Good_HostScopedLookup(t *core.T) { e := NewExecutor("/tmp") _, err := e.moduleSetFact("host1", map[string]any{ "build_id": "2026.04.02", }) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Equal(t, "2026.04.02", e.templateString("{{ build_id }}", "host1", nil)) - assert.Equal(t, "{{ build_id }}", e.templateString("{{ build_id }}", "host2", nil)) + core.AssertEqual(t, "2026.04.02", e.templateString("{{ build_id }}", "host1", nil)) + core.AssertEqual(t, "{{ build_id }}", e.templateString("{{ build_id }}", "host2", nil)) } -func TestExecutorExtra_ModuleSetFact_Good_ExposesAnsibleFacts(t *testing.T) { +func TestExecutorExtra_ModuleSetFact_Good_ExposesAnsibleFacts(t *core.T) { e := NewExecutor("/tmp") _, err := e.moduleSetFact("host1", map[string]any{ "app_version": "2.0.0", }) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Equal(t, "2.0.0", e.templateString("{{ ansible_facts.app_version }}", "host1", nil)) - assert.True(t, e.evalCondition("ansible_facts.app_version == '2.0.0'", "host1")) + core.AssertEqual(t, "2.0.0", e.templateString("{{ ansible_facts.app_version }}", "host1", nil)) + core.AssertTrue(t, e.evalCondition("ansible_facts.app_version == '2.0.0'", "host1")) } -func TestExecutorExtra_ClearFacts_Good_RemovesSetFacts(t *testing.T) { +func TestExecutorExtra_ClearFacts_Good_RemovesSetFacts(t *core.T) { e := NewExecutor("/tmp") _, err := e.moduleSetFact("host1", map[string]any{ "app_version": "2.0.0", }) - require.NoError(t, err) + core.RequireNoError(t, err) e.clearFacts([]string{"host1"}) - assert.Equal(t, "{{ ansible_facts.app_version }}", e.templateString("{{ ansible_facts.app_version }}", "host1", nil)) + core.AssertEqual(t, "{{ ansible_facts.app_version }}", e.templateString("{{ ansible_facts.app_version }}", "host1", nil)) } // --- moduleAddHost --- -func TestExecutorExtra_ModuleAddHost_Good_AddsHostAndGroups(t *testing.T) { +func TestExecutorExtra_ModuleAddHost_Good_AddsHostAndGroups(t *core.T) { e := NewExecutor("/tmp") result, err := e.moduleAddHost(map[string]any{ @@ -296,34 +293,34 @@ func TestExecutorExtra_ModuleAddHost_Good_AddsHostAndGroups(t *testing.T) { "custom_var": "custom-value", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "db1", result.Data["host"]) - assert.Contains(t, result.Msg, "db1") + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "db1", result.Data["host"]) + core.AssertContains(t, result.Msg, "db1") - require.NotNil(t, e.inventory) - require.NotNil(t, e.inventory.All) - require.NotNil(t, e.inventory.All.Hosts["db1"]) + core.AssertNotNil(t, e.inventory) + core.AssertNotNil(t, e.inventory.All) + core.AssertNotNil(t, e.inventory.All.Hosts["db1"]) host := e.inventory.All.Hosts["db1"] - assert.Equal(t, "10.0.0.5", host.AnsibleHost) - assert.Equal(t, 2222, host.AnsiblePort) - assert.Equal(t, "deploy", host.AnsibleUser) - assert.Equal(t, "ssh", host.AnsibleConnection) - assert.Equal(t, "secret", host.AnsibleBecomePassword) - assert.Equal(t, "custom-value", host.Vars["custom_var"]) + core.AssertEqual(t, "10.0.0.5", host.AnsibleHost) + core.AssertEqual(t, 2222, host.AnsiblePort) + core.AssertEqual(t, "deploy", host.AnsibleUser) + core.AssertEqual(t, "ssh", host.AnsibleConnection) + core.AssertEqual(t, "secret", host.AnsibleBecomePassword) + core.AssertEqual(t, "custom-value", host.Vars["custom_var"]) - require.NotNil(t, e.inventory.All.Children["databases"]) - require.NotNil(t, e.inventory.All.Children["production"]) - assert.Same(t, host, e.inventory.All.Children["databases"].Hosts["db1"]) - assert.Same(t, host, e.inventory.All.Children["production"].Hosts["db1"]) + core.AssertNotNil(t, e.inventory.All.Children["databases"]) + core.AssertNotNil(t, e.inventory.All.Children["production"]) + core.AssertSame(t, host, e.inventory.All.Children["databases"].Hosts["db1"]) + core.AssertSame(t, host, e.inventory.All.Children["production"].Hosts["db1"]) - assert.Equal(t, []string{"db1"}, GetHosts(e.inventory, "all")) - assert.Equal(t, []string{"db1"}, GetHosts(e.inventory, "databases")) - assert.Equal(t, []string{"db1"}, GetHosts(e.inventory, "production")) + core.AssertEqual(t, []string{"db1"}, GetHosts(e.inventory, "all")) + core.AssertEqual(t, []string{"db1"}, GetHosts(e.inventory, "databases")) + core.AssertEqual(t, []string{"db1"}, GetHosts(e.inventory, "production")) } -func TestExecutorExtra_ModuleAddHost_Good_IdempotentRepeat(t *testing.T) { +func TestExecutorExtra_ModuleAddHost_Good_IdempotentRepeat(t *core.T) { e := NewExecutor("/tmp") _, err := e.moduleAddHost(map[string]any{ @@ -331,20 +328,20 @@ func TestExecutorExtra_ModuleAddHost_Good_IdempotentRepeat(t *testing.T) { "groups": []any{"caches"}, "role": "redis", }) - require.NoError(t, err) + core.RequireNoError(t, err) result, err := e.moduleAddHost(map[string]any{ "name": "cache1", "groups": []any{"caches"}, "role": "redis", }) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.False(t, result.Changed) - assert.Equal(t, []string{"cache1"}, GetHosts(e.inventory, "caches")) + core.AssertFalse(t, result.Changed) + core.AssertEqual(t, []string{"cache1"}, GetHosts(e.inventory, "caches")) } -func TestExecutorExtra_ModuleAddHost_Good_ThroughDispatcher(t *testing.T) { +func TestExecutorExtra_ModuleAddHost_Good_ThroughDispatcher(t *core.T) { e := NewExecutor("/tmp") task := &Task{ Module: "add_host", @@ -357,18 +354,18 @@ func TestExecutorExtra_ModuleAddHost_Good_ThroughDispatcher(t *testing.T) { result, err := e.executeModule(context.Background(), "host1", &SSHClient{}, task, &Play{}) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "cache1", result.Data["host"]) - assert.Equal(t, []string{"caches"}, result.Data["groups"]) - assert.Equal(t, []string{"cache1"}, GetHosts(e.inventory, "all")) - assert.Equal(t, []string{"cache1"}, GetHosts(e.inventory, "caches")) - assert.Equal(t, "redis", e.inventory.All.Hosts["cache1"].Vars["role"]) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "cache1", result.Data["host"]) + core.AssertEqual(t, []string{"caches"}, result.Data["groups"]) + core.AssertEqual(t, []string{"cache1"}, GetHosts(e.inventory, "all")) + core.AssertEqual(t, []string{"cache1"}, GetHosts(e.inventory, "caches")) + core.AssertEqual(t, "redis", e.inventory.All.Hosts["cache1"].Vars["role"]) } // --- moduleGroupBy --- -func TestExecutorExtra_ModuleGroupBy_Good(t *testing.T) { +func TestExecutorExtra_ModuleGroupBy_Good(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -380,16 +377,16 @@ func TestExecutorExtra_ModuleGroupBy_Good(t *testing.T) { result, err := e.moduleGroupBy("web1", map[string]any{"key": "debian"}) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "web1", result.Data["host"]) - assert.Equal(t, "debian", result.Data["group"]) - assert.Contains(t, result.Msg, "web1") - assert.Contains(t, result.Msg, "debian") - assert.Equal(t, []string{"web1"}, GetHosts(e.inventory, "debian")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "web1", result.Data["host"]) + core.AssertEqual(t, "debian", result.Data["group"]) + core.AssertContains(t, result.Msg, "web1") + core.AssertContains(t, result.Msg, "debian") + core.AssertEqual(t, []string{"web1"}, GetHosts(e.inventory, "debian")) } -func TestExecutorExtra_ModuleGroupBy_Good_ThroughDispatcher(t *testing.T) { +func TestExecutorExtra_ModuleGroupBy_Good_ThroughDispatcher(t *core.T) { e, mock := newTestExecutorWithMock("host1") task := &Task{ Module: "group_by", @@ -400,175 +397,175 @@ func TestExecutorExtra_ModuleGroupBy_Good_ThroughDispatcher(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, []string{"host1"}, GetHosts(e.inventory, "linux")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, []string{"host1"}, GetHosts(e.inventory, "linux")) } -func TestExecutorExtra_ModuleGroupBy_Bad_MissingKey(t *testing.T) { +func TestExecutorExtra_ModuleGroupBy_Bad_MissingKey(t *core.T) { e := NewExecutor("/tmp") _, err := e.moduleGroupBy("host1", map[string]any{}) - assert.Error(t, err) - assert.Contains(t, err.Error(), "key required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "key required") } // --- moduleIncludeVars --- -func TestExecutorExtra_ModuleIncludeVars_Good_WithFile(t *testing.T) { +func TestExecutorExtra_ModuleIncludeVars_Good_WithFile(t *core.T) { dir := t.TempDir() path := joinPath(dir, "main.yml") - require.NoError(t, writeTestFile(path, []byte("app_name: demo\n"), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte("app_name: demo\n"), 0644)) e := NewExecutor("/tmp") result, err := e.moduleIncludeVars(map[string]any{"file": path}) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Contains(t, result.Msg, path) - assert.Equal(t, "demo", e.vars["app_name"]) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertContains(t, result.Msg, path) + core.AssertEqual(t, "demo", e.vars["app_name"]) } -func TestExecutorExtra_ModuleIncludeVars_Good_WithRawParams(t *testing.T) { +func TestExecutorExtra_ModuleIncludeVars_Good_WithRawParams(t *core.T) { dir := t.TempDir() path := joinPath(dir, "defaults.yml") - require.NoError(t, writeTestFile(path, []byte("app_port: 8080\n"), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte("app_port: 8080\n"), 0644)) e := NewExecutor("/tmp") result, err := e.moduleIncludeVars(map[string]any{"_raw_params": path}) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Contains(t, result.Msg, path) - assert.Equal(t, 8080, e.vars["app_port"]) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertContains(t, result.Msg, path) + core.AssertEqual(t, 8080, e.vars["app_port"]) } -func TestExecutorExtra_ModuleIncludeVars_Good_Empty(t *testing.T) { +func TestExecutorExtra_ModuleIncludeVars_Good_Empty(t *core.T) { e := NewExecutor("/tmp") result, err := e.moduleIncludeVars(map[string]any{}) - require.NoError(t, err) - assert.False(t, result.Changed) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) } // --- moduleMeta --- -func TestExecutorExtra_ModuleMeta_Good(t *testing.T) { +func TestExecutorExtra_ModuleMeta_Good(t *core.T) { e := NewExecutor("/tmp") result, err := e.moduleMeta(map[string]any{"_raw_params": "flush_handlers"}) - require.NoError(t, err) - assert.False(t, result.Changed) - require.NotNil(t, result.Data) - assert.Equal(t, "flush_handlers", result.Data["action"]) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertNotNil(t, result.Data) + core.AssertEqual(t, "flush_handlers", result.Data["action"]) } -func TestExecutorExtra_ModuleMeta_Good_ExplicitActionField(t *testing.T) { +func TestExecutorExtra_ModuleMeta_Good_ExplicitActionField(t *core.T) { e := NewExecutor("/tmp") result, err := e.moduleMeta(map[string]any{"action": "refresh_inventory"}) - require.NoError(t, err) - assert.False(t, result.Changed) - require.NotNil(t, result.Data) - assert.Equal(t, "refresh_inventory", result.Data["action"]) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertNotNil(t, result.Data) + core.AssertEqual(t, "refresh_inventory", result.Data["action"]) } -func TestExecutorExtra_ModuleMeta_Good_ClearFacts(t *testing.T) { +func TestExecutorExtra_ModuleMeta_Good_ClearFacts(t *core.T) { e := NewExecutor("/tmp") e.facts["host1"] = &Facts{Hostname: "web01"} result, err := e.moduleMeta(map[string]any{"_raw_params": "clear_facts"}) - require.NoError(t, err) - assert.True(t, result.Changed) - require.NotNil(t, result.Data) - assert.Equal(t, "clear_facts", result.Data["action"]) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertNotNil(t, result.Data) + core.AssertEqual(t, "clear_facts", result.Data["action"]) } -func TestExecutorExtra_ModuleMeta_Good_ResetConnection(t *testing.T) { +func TestExecutorExtra_ModuleMeta_Good_ResetConnection(t *core.T) { e := NewExecutor("/tmp") result, err := e.moduleMeta(map[string]any{"_raw_params": "reset_connection"}) - require.NoError(t, err) - assert.False(t, result.Changed) - require.NotNil(t, result.Data) - assert.Equal(t, "reset_connection", result.Data["action"]) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertNotNil(t, result.Data) + core.AssertEqual(t, "reset_connection", result.Data["action"]) } -func TestExecutorExtra_ModuleMeta_Good_EndHost(t *testing.T) { +func TestExecutorExtra_ModuleMeta_Good_EndHost(t *core.T) { e := NewExecutor("/tmp") result, err := e.moduleMeta(map[string]any{"_raw_params": "end_host"}) - require.NoError(t, err) - assert.False(t, result.Changed) - require.NotNil(t, result.Data) - assert.Equal(t, "end_host", result.Data["action"]) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertNotNil(t, result.Data) + core.AssertEqual(t, "end_host", result.Data["action"]) } -func TestExecutorExtra_ModuleMeta_Good_EndBatch(t *testing.T) { +func TestExecutorExtra_ModuleMeta_Good_EndBatch(t *core.T) { e := NewExecutor("/tmp") result, err := e.moduleMeta(map[string]any{"_raw_params": "end_batch"}) - require.NoError(t, err) - assert.False(t, result.Changed) - require.NotNil(t, result.Data) - assert.Equal(t, "end_batch", result.Data["action"]) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertNotNil(t, result.Data) + core.AssertEqual(t, "end_batch", result.Data["action"]) } -func TestExecutorExtra_HandleMetaAction_Good_ClearFacts(t *testing.T) { +func TestExecutorExtra_HandleMetaAction_Good_ClearFacts(t *core.T) { e := NewExecutor("/tmp") e.facts["host1"] = &Facts{Hostname: "web01"} e.facts["host2"] = &Facts{Hostname: "web02"} result := &TaskResult{Data: map[string]any{"action": "clear_facts"}} - require.NoError(t, e.handleMetaAction(context.Background(), "host1", []string{"host1"}, nil, result)) + core.RequireNoError(t, e.handleMetaAction(context.Background(), "host1", []string{"host1"}, nil, result)) _, ok := e.facts["host1"] - assert.False(t, ok) - require.NotNil(t, e.facts["host2"]) - assert.Equal(t, "web02", e.facts["host2"].Hostname) + core.AssertFalse(t, ok) + core.AssertNotNil(t, e.facts["host2"]) + core.AssertEqual(t, "web02", e.facts["host2"].Hostname) } -func TestExecutorExtra_HandleMetaAction_Good_EndHost(t *testing.T) { +func TestExecutorExtra_HandleMetaAction_Good_EndHost(t *core.T) { e := NewExecutor("/tmp") result := &TaskResult{Data: map[string]any{"action": "end_host"}} err := e.handleMetaAction(context.Background(), "host1", []string{"host1", "host2"}, nil, result) - require.ErrorIs(t, err, errEndHost) - assert.True(t, e.isHostEnded("host1")) - assert.False(t, e.isHostEnded("host2")) + core.AssertErrorIs(t, err, errEndHost) + core.AssertTrue(t, e.isHostEnded("host1")) + core.AssertFalse(t, e.isHostEnded("host2")) } -func TestExecutorExtra_HandleMetaAction_Good_EndBatch(t *testing.T) { +func TestExecutorExtra_HandleMetaAction_Good_EndBatch(t *core.T) { e := NewExecutor("/tmp") result := &TaskResult{Data: map[string]any{"action": "end_batch"}} err := e.handleMetaAction(context.Background(), "host1", []string{"host1", "host2"}, nil, result) - require.ErrorIs(t, err, errEndBatch) - assert.False(t, e.isHostEnded("host1")) - assert.False(t, e.isHostEnded("host2")) + core.AssertErrorIs(t, err, errEndBatch) + core.AssertFalse(t, e.isHostEnded("host1")) + core.AssertFalse(t, e.isHostEnded("host2")) } -func TestExecutorExtra_HandleMetaAction_Good_ResetConnection(t *testing.T) { +func TestExecutorExtra_HandleMetaAction_Good_ResetConnection(t *core.T) { e := NewExecutor("/tmp") mock := NewMockSSHClient() e.clients["host1"] = mock e.clients["host2"] = NewMockSSHClient() result := &TaskResult{Data: map[string]any{"action": "reset_connection"}} - require.NoError(t, e.handleMetaAction(context.Background(), "host1", []string{"host1", "host2"}, nil, result)) + core.RequireNoError(t, e.handleMetaAction(context.Background(), "host1", []string{"host1", "host2"}, nil, result)) _, ok := e.clients["host1"] - assert.False(t, ok) + core.AssertFalse(t, ok) _, ok = e.clients["host2"] - assert.True(t, ok) - assert.True(t, mock.closed) + core.AssertTrue(t, ok) + core.AssertTrue(t, mock.closed) } -func TestExecutorExtra_RunBlock_Bad_RescueFailurePropagates(t *testing.T) { +func TestExecutorExtra_RunBlock_Bad_RescueFailurePropagates(t *core.T) { e, _ := newTestExecutorWithMock("host1") task := &Task{ @@ -590,11 +587,11 @@ func TestExecutorExtra_RunBlock_Bad_RescueFailurePropagates(t *testing.T) { err := e.runBlock(context.Background(), []string{"host1"}, task, &Play{}) - require.Error(t, err) - assert.Contains(t, err.Error(), "rescue failed") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "rescue failed") } -func TestExecutorExtra_RunBlock_Good_RescueSuccessClearsBlockFailure(t *testing.T) { +func TestExecutorExtra_RunBlock_Good_RescueSuccessClearsBlockFailure(t *core.T) { e, _ := newTestExecutorWithMock("host1") task := &Task{ @@ -616,10 +613,10 @@ func TestExecutorExtra_RunBlock_Good_RescueSuccessClearsBlockFailure(t *testing. err := e.runBlock(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) } -func TestExecutorExtra_RunBlock_Good_InheritsBlockVars(t *testing.T) { +func TestExecutorExtra_RunBlock_Good_InheritsBlockVars(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("echo inherited", "inherited\n", "", 0) @@ -640,11 +637,11 @@ func TestExecutorExtra_RunBlock_Good_InheritsBlockVars(t *testing.T) { err := e.runBlock(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) - assert.True(t, mock.hasExecuted("echo inherited")) + core.RequireNoError(t, err) + core.AssertTrue(t, mock.hasExecuted("echo inherited")) } -func TestExecutorExtra_RunBlock_Good_InheritsBlockWhen(t *testing.T) { +func TestExecutorExtra_RunBlock_Good_InheritsBlockWhen(t *core.T) { e, mock := newTestExecutorWithMock("host1") task := &Task{ @@ -662,11 +659,11 @@ func TestExecutorExtra_RunBlock_Good_InheritsBlockWhen(t *testing.T) { err := e.runBlock(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) - assert.Equal(t, 0, mock.commandCount()) + core.RequireNoError(t, err) + core.AssertEqual(t, 0, mock.commandCount()) } -func TestExecutorExtra_RunTaskOnHosts_Good_EndHostSkipsFutureTasks(t *testing.T) { +func TestExecutorExtra_RunTaskOnHosts_Good_EndHostSkipsFutureTasks(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -691,23 +688,23 @@ func TestExecutorExtra_RunTaskOnHosts_Good_EndHostSkipsFutureTasks(t *testing.T) Args: map[string]any{"_raw_params": "end_host"}, When: "retire_host", } - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"host1", "host2"}, first, play)) - assert.True(t, e.isHostEnded("host1")) - assert.False(t, e.isHostEnded("host2")) + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"host1", "host2"}, first, play)) + core.AssertTrue(t, e.isHostEnded("host1")) + core.AssertFalse(t, e.isHostEnded("host2")) second := &Task{ Name: "Follow-up", Module: "debug", Args: map[string]any{"msg": "still running"}, } - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"host1", "host2"}, second, play)) + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"host1", "host2"}, second, play)) - assert.Contains(t, started, "host1:Retire host") - assert.Contains(t, started, "host2:Follow-up") - assert.NotContains(t, started, "host1:Follow-up") + core.AssertContains(t, started, "host1:Retire host") + core.AssertContains(t, started, "host2:Follow-up") + core.AssertNotContains(t, started, "host1:Follow-up") } -func TestExecutorExtra_RunPlay_Good_MetaEndBatchAdvancesToNextSerialBatch(t *testing.T) { +func TestExecutorExtra_RunPlay_Good_MetaEndBatchAdvancesToNextSerialBatch(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -748,34 +745,34 @@ func TestExecutorExtra_RunPlay_Good_MetaEndBatchAdvancesToNextSerialBatch(t *tes started = append(started, host+":"+task.Name) } - require.NoError(t, e.runPlay(context.Background(), play)) + core.RequireNoError(t, e.runPlay(context.Background(), play)) - assert.Contains(t, started, "host1:end current batch") - assert.NotContains(t, started, "host1:follow-up") - assert.Contains(t, started, "host2:follow-up") - assert.Contains(t, started, "host3:follow-up") + core.AssertContains(t, started, "host1:end current batch") + core.AssertNotContains(t, started, "host1:follow-up") + core.AssertContains(t, started, "host2:follow-up") + core.AssertContains(t, started, "host3:follow-up") } -func TestExecutorExtra_SplitSerialHosts_Good_ListValues(t *testing.T) { +func TestExecutorExtra_SplitSerialHosts_Good_ListValues(t *core.T) { batches := splitSerialHosts([]string{"host1", "host2", "host3", "host4"}, []any{1, "50%"}) - require.Len(t, batches, 3) - assert.Equal(t, []string{"host1"}, batches[0]) - assert.Equal(t, []string{"host2", "host3"}, batches[1]) - assert.Equal(t, []string{"host4"}, batches[2]) + core.AssertLen(t, batches, 3) + core.AssertEqual(t, []string{"host1"}, batches[0]) + core.AssertEqual(t, []string{"host2", "host3"}, batches[1]) + core.AssertEqual(t, []string{"host4"}, batches[2]) } -func TestExecutorExtra_SplitSerialHosts_Good_ListRepeatsLastValue(t *testing.T) { +func TestExecutorExtra_SplitSerialHosts_Good_ListRepeatsLastValue(t *core.T) { batches := splitSerialHosts([]string{"host1", "host2", "host3", "host4", "host5"}, []any{2, 1}) - require.Len(t, batches, 4) - assert.Equal(t, []string{"host1", "host2"}, batches[0]) - assert.Equal(t, []string{"host3"}, batches[1]) - assert.Equal(t, []string{"host4"}, batches[2]) - assert.Equal(t, []string{"host5"}, batches[3]) + core.AssertLen(t, batches, 4) + core.AssertEqual(t, []string{"host1", "host2"}, batches[0]) + core.AssertEqual(t, []string{"host3"}, batches[1]) + core.AssertEqual(t, []string{"host4"}, batches[2]) + core.AssertEqual(t, []string{"host5"}, batches[3]) } -func TestExecutorExtra_RunPlay_Good_ExposesPlayMagicVars(t *testing.T) { +func TestExecutorExtra_RunPlay_Good_ExposesPlayMagicVars(t *core.T) { e := NewExecutor("/tmp") gatherFacts := false e.SetInventoryDirect(&Inventory{ @@ -806,15 +803,15 @@ func TestExecutorExtra_RunPlay_Good_ExposesPlayMagicVars(t *testing.T) { }, } - require.NoError(t, e.runPlay(context.Background(), play)) + core.RequireNoError(t, e.runPlay(context.Background(), play)) - require.NotNil(t, e.results["host1"]["magic_vars"]) - assert.Equal(t, "Inspect play magic vars|[host1 host2]|[host1 host2]|[host1]", e.results["host1"]["magic_vars"].Msg) - require.NotNil(t, e.results["host2"]["magic_vars"]) - assert.Equal(t, "Inspect play magic vars|[host1 host2]|[host1 host2]|[host2]", e.results["host2"]["magic_vars"].Msg) + core.AssertNotNil(t, e.results["host1"]["magic_vars"]) + core.AssertEqual(t, "Inspect play magic vars|[host1 host2]|[host1 host2]|[host1]", e.results["host1"]["magic_vars"].Msg) + core.AssertNotNil(t, e.results["host2"]["magic_vars"]) + core.AssertEqual(t, "Inspect play magic vars|[host1 host2]|[host1 host2]|[host2]", e.results["host2"]["magic_vars"].Msg) } -func TestExecutorExtra_RunPlay_Good_ExposesLimitMagicVar(t *testing.T) { +func TestExecutorExtra_RunPlay_Good_ExposesLimitMagicVar(t *core.T) { gatherFacts := false e := NewExecutor(t.TempDir()) e.Limit = "host1" @@ -844,110 +841,110 @@ func TestExecutorExtra_RunPlay_Good_ExposesLimitMagicVar(t *testing.T) { }, } - require.NoError(t, e.runPlay(context.Background(), play)) + core.RequireNoError(t, e.runPlay(context.Background(), play)) - require.NotNil(t, e.results["host1"]["limit_var"]) - assert.Equal(t, "host1", e.results["host1"]["limit_var"].Msg) - assert.Nil(t, e.results["host2"]) + core.AssertNotNil(t, e.results["host1"]["limit_var"]) + core.AssertEqual(t, "host1", e.results["host1"]["limit_var"].Msg) + core.AssertNil(t, e.results["host2"]) } // ============================================================ // Tests for handleLookup (0% coverage) // ============================================================ -func TestExecutorExtra_HandleLookup_Good_EnvVar(t *testing.T) { +func TestExecutorExtra_HandleLookup_Good_EnvVar(t *core.T) { e := NewExecutor("/tmp") t.Setenv("TEST_ANSIBLE_LOOKUP", "found_it") result := e.handleLookup("lookup('env', 'TEST_ANSIBLE_LOOKUP')", "", nil) - assert.Equal(t, "found_it", result) + core.AssertEqual(t, "found_it", result) } -func TestExecutorExtra_HandleLookup_Good_EnvVarMissing(t *testing.T) { +func TestExecutorExtra_HandleLookup_Good_EnvVarMissing(t *core.T) { e := NewExecutor("/tmp") result := e.handleLookup("lookup('env', 'NONEXISTENT_VAR_12345')", "", nil) - assert.Equal(t, "", result) + core.AssertEqual(t, "", result) } -func TestExecutorExtra_HandleLookup_Good_FileLookupResolvesBasePath(t *testing.T) { +func TestExecutorExtra_HandleLookup_Good_FileLookupResolvesBasePath(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "vars.txt"), []byte("from base path"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "vars.txt"), []byte("from base path"), 0644)) e := NewExecutor(dir) result := e.handleLookup("lookup('file', 'vars.txt')", "", nil) - assert.Equal(t, "from base path", result) + core.AssertEqual(t, "from base path", result) } -func TestExecutorExtra_HandleLookup_Good_TemplateLookupResolvesBasePathAndVars(t *testing.T) { +func TestExecutorExtra_HandleLookup_Good_TemplateLookupResolvesBasePathAndVars(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "templates", "message.j2"), []byte("Hello {{ name }}"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "templates", "message.j2"), []byte("Hello {{ name }}"), 0644)) e := NewExecutor(dir) e.SetVar("name", "world") result := e.handleLookup("lookup('template', 'templates/message.j2')", "host1", nil) - assert.Equal(t, "Hello world", result) + core.AssertEqual(t, "Hello world", result) } -func TestExecutorExtra_HandleLookup_Good_VarsLookup(t *testing.T) { +func TestExecutorExtra_HandleLookup_Good_VarsLookup(t *core.T) { e := NewExecutor("/tmp") e.SetVar("lookup_value", "resolved from vars") result := e.handleLookup("lookup('vars', 'lookup_value')", "", nil) - assert.Equal(t, "resolved from vars", result) + core.AssertEqual(t, "resolved from vars", result) } -func TestExecutorExtra_HandleLookup_Good_PipeLookup(t *testing.T) { +func TestExecutorExtra_HandleLookup_Good_PipeLookup(t *core.T) { e := NewExecutor("/tmp") result := e.handleLookup("lookup('pipe', 'printf pipe-value')", "", nil) - assert.Equal(t, "pipe-value", result) + core.AssertEqual(t, "pipe-value", result) } -func TestExecutorExtra_HandleLookup_Good_FileGlobLookup(t *testing.T) { +func TestExecutorExtra_HandleLookup_Good_FileGlobLookup(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "files", "a.txt"), []byte("alpha"), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "files", "b.txt"), []byte("bravo"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "files", "a.txt"), []byte("alpha"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "files", "b.txt"), []byte("bravo"), 0644)) e := NewExecutor(dir) result := e.handleLookup("lookup('fileglob', 'files/*.txt')", "", nil) - assert.Equal(t, join(",", []string{ + core.AssertEqual(t, join(",", []string{ joinPath(dir, "files", "a.txt"), joinPath(dir, "files", "b.txt"), }), result) } -func TestExecutorExtra_HandleLookup_Good_PasswordLookupReadsExistingFile(t *testing.T) { +func TestExecutorExtra_HandleLookup_Good_PasswordLookupReadsExistingFile(t *core.T) { dir := t.TempDir() passPath := joinPath(dir, "secrets", "app.pass") - require.NoError(t, writeTestFile(passPath, []byte("s3cret\n"), 0600)) + core.RequireNoError(t, writeTestFile(passPath, []byte("s3cret\n"), 0600)) e := NewExecutor(dir) result := e.handleLookup("lookup('password', 'secrets/app.pass')", "", nil) - assert.Equal(t, "s3cret", result) + core.AssertEqual(t, "s3cret", result) } -func TestExecutorExtra_HandleLookup_Good_PasswordLookupCreatesFile(t *testing.T) { +func TestExecutorExtra_HandleLookup_Good_PasswordLookupCreatesFile(t *core.T) { dir := t.TempDir() passPath := joinPath(dir, "secrets", "generated.pass") e := NewExecutor(dir) result := e.handleLookup("lookup('password', 'secrets/generated.pass length=12 chars=digits')", "", nil) - require.Len(t, result, 12) + core.AssertLen(t, result, 12) content, err := readTestFile(passPath) - require.NoError(t, err) - assert.Equal(t, result, string(content)) - assert.Len(t, content, 12) + core.RequireNoError(t, err) + core.AssertEqual(t, result, string(content)) + core.AssertLen(t, content, 12) } -func TestExecutorExtra_HandleLookup_Good_PasswordLookupHonoursSeed(t *testing.T) { +func TestExecutorExtra_HandleLookup_Good_PasswordLookupHonoursSeed(t *core.T) { dir := t.TempDir() e := NewExecutor(dir) @@ -955,15 +952,15 @@ func TestExecutorExtra_HandleLookup_Good_PasswordLookupHonoursSeed(t *testing.T) second := e.handleLookup("lookup('password', '/dev/null length=16 chars=ascii_lowercase seed=inventory_hostname')", "host1", nil) other := e.handleLookup("lookup('password', '/dev/null length=16 chars=ascii_lowercase seed=inventory_hostname')", "host2", nil) - assert.Len(t, first, 16) - assert.Equal(t, first, second) - assert.NotEqual(t, first, other) + core.AssertLen(t, first, 16) + core.AssertEqual(t, first, second) + core.AssertNotEqual(t, first, other) } -func TestExecutorExtra_HandleLookup_Good_FirstFoundLookupReturnsFirstExistingPath(t *testing.T) { +func TestExecutorExtra_HandleLookup_Good_FirstFoundLookupReturnsFirstExistingPath(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "defaults", "common.yml"), []byte("common: true\n"), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "defaults", "production.yml"), []byte("env: prod\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "defaults", "common.yml"), []byte("common: true\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "defaults", "production.yml"), []byte("env: prod\n"), 0644)) e := NewExecutor(dir) e.SetVar("findme", map[string]any{ @@ -973,12 +970,12 @@ func TestExecutorExtra_HandleLookup_Good_FirstFoundLookupReturnsFirstExistingPat result := e.handleLookup("lookup('first_found', findme)", "", nil) - assert.Equal(t, joinPath(dir, "defaults", "production.yml"), result) + core.AssertEqual(t, joinPath(dir, "defaults", "production.yml"), result) } -func TestExecutorExtra_HandleLookup_Good_FirstFoundLookupAcceptsFQCN(t *testing.T) { +func TestExecutorExtra_HandleLookup_Good_FirstFoundLookupAcceptsFQCN(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "vars", "selected.yml"), []byte("selected: true\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "vars", "selected.yml"), []byte("selected: true\n"), 0644)) e := NewExecutor(dir) e.SetVar("findme", map[string]any{ @@ -988,13 +985,13 @@ func TestExecutorExtra_HandleLookup_Good_FirstFoundLookupAcceptsFQCN(t *testing. result := e.handleLookup("lookup('ansible.builtin.first_found', findme)", "", nil) - assert.Equal(t, joinPath(dir, "vars", "selected.yml"), result) + core.AssertEqual(t, joinPath(dir, "vars", "selected.yml"), result) } -func TestExecutorExtra_RunTaskOnHost_Good_LoopFromFileGlobLookup(t *testing.T) { +func TestExecutorExtra_RunTaskOnHost_Good_LoopFromFileGlobLookup(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "files", "a.txt"), []byte("alpha"), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "files", "b.txt"), []byte("bravo"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "files", "a.txt"), []byte("alpha"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "files", "b.txt"), []byte("bravo"), 0644)) e := NewExecutor(dir) task := &Task{ @@ -1006,26 +1003,26 @@ func TestExecutorExtra_RunTaskOnHost_Good_LoopFromFileGlobLookup(t *testing.T) { Register: "glob_lookup", } - require.NoError(t, e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, &Play{})) + core.RequireNoError(t, e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, &Play{})) result := e.results["host1"]["glob_lookup"] - require.NotNil(t, result) - require.Len(t, result.Results, 2) - assert.Equal(t, joinPath(dir, "files", "a.txt"), result.Results[0].Msg) - assert.Equal(t, joinPath(dir, "files", "b.txt"), result.Results[1].Msg) + core.AssertNotNil(t, result) + core.AssertLen(t, result.Results, 2) + core.AssertEqual(t, joinPath(dir, "files", "a.txt"), result.Results[0].Msg) + core.AssertEqual(t, joinPath(dir, "files", "b.txt"), result.Results[1].Msg) } -func TestExecutorExtra_HandleLookup_Bad_InvalidSyntax(t *testing.T) { +func TestExecutorExtra_HandleLookup_Bad_InvalidSyntax(t *core.T) { e := NewExecutor("/tmp") result := e.handleLookup("lookup(invalid)", "", nil) - assert.Equal(t, "", result) + core.AssertEqual(t, "", result) } // ============================================================ // Tests for SetInventory (0% coverage) // ============================================================ -func TestExecutorExtra_SetInventory_Good(t *testing.T) { +func TestExecutorExtra_SetInventory_Good(t *core.T) { dir := t.TempDir() invPath := joinPath(dir, "inventory.yml") yaml := `all: @@ -1035,20 +1032,20 @@ func TestExecutorExtra_SetInventory_Good(t *testing.T) { web2: ansible_host: 10.0.0.2 ` - require.NoError(t, writeTestFile(invPath, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(invPath, []byte(yaml), 0644)) e := NewExecutor(dir) err := e.SetInventory(invPath) - require.NoError(t, err) - assert.NotNil(t, e.inventory) - assert.Len(t, e.inventory.All.Hosts, 2) + core.RequireNoError(t, err) + core.AssertNotNil(t, e.inventory) + core.AssertLen(t, e.inventory.All.Hosts, 2) } -func TestExecutorExtra_SetInventory_Good_Directory(t *testing.T) { +func TestExecutorExtra_SetInventory_Good_Directory(t *core.T) { dir := t.TempDir() inventoryDir := joinPath(dir, "inventory") - require.NoError(t, os.MkdirAll(inventoryDir, 0755)) + core.RequireNoError(t, os.MkdirAll(inventoryDir, 0755)) invPath := joinPath(inventoryDir, "inventory.yml") yaml := `all: @@ -1056,27 +1053,27 @@ func TestExecutorExtra_SetInventory_Good_Directory(t *testing.T) { web1: ansible_host: 10.0.0.1 ` - require.NoError(t, writeTestFile(invPath, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(invPath, []byte(yaml), 0644)) e := NewExecutor(dir) err := e.SetInventory(inventoryDir) - require.NoError(t, err) - assert.NotNil(t, e.inventory) - assert.Contains(t, e.inventory.All.Hosts, "web1") + core.RequireNoError(t, err) + core.AssertNotNil(t, e.inventory) + core.AssertContains(t, e.inventory.All.Hosts, "web1") } -func TestExecutorExtra_SetInventory_Bad_FileNotFound(t *testing.T) { +func TestExecutorExtra_SetInventory_Bad_FileNotFound(t *core.T) { e := NewExecutor("/tmp") err := e.SetInventory("/nonexistent/inventory.yml") - assert.Error(t, err) + core.AssertError(t, err) } // ============================================================ // Tests for iterator functions (0% coverage) // ============================================================ -func TestExecutorExtra_ParsePlaybookIter_Good(t *testing.T) { +func TestExecutorExtra_ParsePlaybookIter_Good(t *core.T) { dir := t.TempDir() path := joinPath(dir, "playbook.yml") yaml := `- name: First play @@ -1091,27 +1088,29 @@ func TestExecutorExtra_ParsePlaybookIter_Good(t *testing.T) { - debug: msg: world ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) iter, err := p.ParsePlaybookIter(path) - require.NoError(t, err) + core.RequireNoError(t, err) var plays []Play for play := range iter { plays = append(plays, play) } - assert.Len(t, plays, 2) - assert.Equal(t, "First play", plays[0].Name) - assert.Equal(t, "Second play", plays[1].Name) + core.AssertLen(t, plays, 2) + core.AssertEqual(t, "First play", plays[0].Name) + core.AssertEqual(t, "Second play", plays[1].Name) } -func TestExecutorExtra_ParsePlaybookIter_Bad_InvalidFile(t *testing.T) { - _, err := NewParser("/tmp").ParsePlaybookIter("/nonexistent.yml") - assert.Error(t, err) +func TestExecutorExtra_ParsePlaybookIter_Bad_InvalidFile(t *core.T) { + parser := NewParser("/tmp") + seq, err := parser.ParsePlaybookIter("/nonexistent.yml") + core.AssertError(t, err) + core.AssertNil(t, seq) } -func TestExecutorExtra_ParseTasksIter_Good(t *testing.T) { +func TestExecutorExtra_ParseTasksIter_Good(t *core.T) { dir := t.TempDir() path := joinPath(dir, "tasks.yml") yaml := `- name: Task one @@ -1122,26 +1121,28 @@ func TestExecutorExtra_ParseTasksIter_Good(t *testing.T) { debug: msg: second ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) iter, err := p.ParseTasksIter(path) - require.NoError(t, err) + core.RequireNoError(t, err) var tasks []Task for task := range iter { tasks = append(tasks, task) } - assert.Len(t, tasks, 2) - assert.Equal(t, "Task one", tasks[0].Name) + core.AssertLen(t, tasks, 2) + core.AssertEqual(t, "Task one", tasks[0].Name) } -func TestExecutorExtra_ParseTasksIter_Bad_InvalidFile(t *testing.T) { - _, err := NewParser("/tmp").ParseTasksIter("/nonexistent.yml") - assert.Error(t, err) +func TestExecutorExtra_ParseTasksIter_Bad_InvalidFile(t *core.T) { + parser := NewParser("/tmp") + seq, err := parser.ParseTasksIter("/nonexistent.yml") + core.AssertError(t, err) + core.AssertNil(t, seq) } -func TestExecutorExtra_RunIncludeTasks_Good_RelativePath(t *testing.T) { +func TestExecutorExtra_RunIncludeTasks_Good_RelativePath(t *core.T) { dir := t.TempDir() includedPath := joinPath(dir, "included.yml") yaml := `- name: Included first task @@ -1152,7 +1153,7 @@ func TestExecutorExtra_RunIncludeTasks_Good_RelativePath(t *testing.T) { debug: msg: second ` - require.NoError(t, writeTestFile(includedPath, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(includedPath, []byte(yaml), 0644)) gatherFacts := false play := &Play{ @@ -1173,13 +1174,13 @@ func TestExecutorExtra_RunIncludeTasks_Good_RelativePath(t *testing.T) { started = append(started, host+":"+task.Name) } - require.NoError(t, e.runPlay(context.Background(), play)) + core.RequireNoError(t, e.runPlay(context.Background(), play)) - assert.Contains(t, started, "localhost:Included first task") - assert.Contains(t, started, "localhost:Included second task") + core.AssertContains(t, started, "localhost:Included first task") + core.AssertContains(t, started, "localhost:Included second task") } -func TestExecutorExtra_RunIncludeTasks_Good_InheritsTaskVars(t *testing.T) { +func TestExecutorExtra_RunIncludeTasks_Good_InheritsTaskVars(t *core.T) { dir := t.TempDir() includedPath := joinPath(dir, "included-vars.yml") yaml := `- name: Included var task @@ -1187,7 +1188,7 @@ func TestExecutorExtra_RunIncludeTasks_Good_InheritsTaskVars(t *testing.T) { msg: "{{ include_message }}" register: included_result ` - require.NoError(t, writeTestFile(includedPath, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(includedPath, []byte(yaml), 0644)) gatherFacts := false play := &Play{ @@ -1204,20 +1205,20 @@ func TestExecutorExtra_RunIncludeTasks_Good_InheritsTaskVars(t *testing.T) { } e := NewExecutor(dir) - require.NoError(t, e.runPlay(context.Background(), play)) + core.RequireNoError(t, e.runPlay(context.Background(), play)) - require.NotNil(t, e.results["localhost"]["included_result"]) - assert.Equal(t, "hello from include", e.results["localhost"]["included_result"].Msg) + core.AssertNotNil(t, e.results["localhost"]["included_result"]) + core.AssertEqual(t, "hello from include", e.results["localhost"]["included_result"].Msg) } -func TestExecutorExtra_RunIncludeTasks_Good_HostSpecificTemplate(t *testing.T) { +func TestExecutorExtra_RunIncludeTasks_Good_HostSpecificTemplate(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "web.yml"), []byte(`- name: Web included task + core.RequireNoError(t, writeTestFile(joinPath(dir, "web.yml"), []byte(`- name: Web included task debug: msg: web `), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "db.yml"), []byte(`- name: DB included task + core.RequireNoError(t, writeTestFile(joinPath(dir, "db.yml"), []byte(`- name: DB included task debug: msg: db `), 0644)) @@ -1255,23 +1256,23 @@ func TestExecutorExtra_RunIncludeTasks_Good_HostSpecificTemplate(t *testing.T) { started = append(started, host+":"+task.Name) } - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"web1", "db1"}, &Task{ + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"web1", "db1"}, &Task{ Name: "Load host-specific tasks", IncludeTasks: "{{ include_file }}", }, play)) - assert.Contains(t, started, "web1:Web included task") - assert.Contains(t, started, "db1:DB included task") + core.AssertContains(t, started, "web1:Web included task") + core.AssertContains(t, started, "db1:DB included task") } -func TestExecutorExtra_RunIncludeTasks_Good_HonoursWhen(t *testing.T) { +func TestExecutorExtra_RunIncludeTasks_Good_HonoursWhen(t *core.T) { dir := t.TempDir() includedPath := joinPath(dir, "conditional.yml") yaml := `- name: Conditional included task debug: msg: should not run ` - require.NoError(t, writeTestFile(includedPath, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(includedPath, []byte(yaml), 0644)) gatherFacts := false play := &Play{ @@ -1288,18 +1289,18 @@ func TestExecutorExtra_RunIncludeTasks_Good_HonoursWhen(t *testing.T) { started = append(started, host+":"+task.Name) } - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"localhost"}, &Task{ + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"localhost"}, &Task{ Name: "Load conditional tasks", IncludeTasks: "conditional.yml", When: "include_enabled", }, play)) - assert.Empty(t, started) + core.AssertEmpty(t, started) } -func TestExecutorExtra_RunIncludeTasks_Good_TemplatesVarsAndInheritsTags(t *testing.T) { +func TestExecutorExtra_RunIncludeTasks_Good_TemplatesVarsAndInheritsTags(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "tasks", "common.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "tasks", "common.yml"), []byte(`--- - name: Included tagged task debug: msg: "{{ include_message }}" @@ -1326,7 +1327,7 @@ func TestExecutorExtra_RunIncludeTasks_Good_TemplatesVarsAndInheritsTags(t *test GatherFacts: &gatherFacts, } - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"localhost"}, &Task{ + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"localhost"}, &Task{ Name: "Load included tasks", IncludeTasks: "tasks/common.yml", Tags: []string{"include-tag"}, @@ -1335,13 +1336,13 @@ func TestExecutorExtra_RunIncludeTasks_Good_TemplatesVarsAndInheritsTags(t *test }, }, play)) - require.NotNil(t, e.results["localhost"]["include_result"]) - assert.Equal(t, "production", e.results["localhost"]["include_result"].Msg) + core.AssertNotNil(t, e.results["localhost"]["include_result"]) + core.AssertEqual(t, "production", e.results["localhost"]["include_result"].Msg) } -func TestExecutorExtra_RunIncludeRole_Good_InheritsTaskVars(t *testing.T) { +func TestExecutorExtra_RunIncludeRole_Good_InheritsTaskVars(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "roles", "demo", "tasks", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "demo", "tasks", "main.yml"), []byte(`--- - name: Role var task debug: msg: "{{ role_message }}" @@ -1364,7 +1365,7 @@ func TestExecutorExtra_RunIncludeRole_Good_InheritsTaskVars(t *testing.T) { GatherFacts: &gatherFacts, } - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"localhost"}, &Task{ + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"localhost"}, &Task{ Name: "Load role", IncludeRole: &RoleRef{ Role: "demo", @@ -1372,13 +1373,13 @@ func TestExecutorExtra_RunIncludeRole_Good_InheritsTaskVars(t *testing.T) { Vars: map[string]any{"role_message": "hello from role"}, }, play)) - require.NotNil(t, e.results["localhost"]["role_result"]) - assert.Equal(t, "hello from role", e.results["localhost"]["role_result"].Msg) + core.AssertNotNil(t, e.results["localhost"]["role_result"]) + core.AssertEqual(t, "hello from role", e.results["localhost"]["role_result"].Msg) } -func TestExecutorExtra_RunIncludeRole_Good_AppliesRoleDefaults(t *testing.T) { +func TestExecutorExtra_RunIncludeRole_Good_AppliesRoleDefaults(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "roles", "app", "tasks", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "app", "tasks", "main.yml"), []byte(`--- - name: Applied role task vars: role_message: from-task @@ -1410,7 +1411,7 @@ func TestExecutorExtra_RunIncludeRole_Good_AppliesRoleDefaults(t *testing.T) { } // Re-run with callback attached so we can inspect the merged task state. - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"localhost"}, &Task{ + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"localhost"}, &Task{ Name: "Load role with apply", IncludeRole: &RoleRef{ Role: "app", @@ -1427,18 +1428,18 @@ func TestExecutorExtra_RunIncludeRole_Good_AppliesRoleDefaults(t *testing.T) { }, }, play)) - require.NotNil(t, started) - assert.Contains(t, started.Tags, "role-apply") - assert.Equal(t, "production", started.Environment["APP_ENV"]) - assert.Equal(t, "from-apply", started.Vars["apply_message"]) - assert.Equal(t, "from-task", started.Vars["role_message"]) - require.NotNil(t, e.results["localhost"]["role_result"]) - assert.Equal(t, "production|from-apply|from-task", e.results["localhost"]["role_result"].Stdout) + core.AssertNotNil(t, started) + core.AssertContains(t, started.Tags, "role-apply") + core.AssertEqual(t, "production", started.Environment["APP_ENV"]) + core.AssertEqual(t, "from-apply", started.Vars["apply_message"]) + core.AssertEqual(t, "from-task", started.Vars["role_message"]) + core.AssertNotNil(t, e.results["localhost"]["role_result"]) + core.AssertEqual(t, "production|from-apply|from-task", e.results["localhost"]["role_result"].Stdout) } -func TestExecutorExtra_RunIncludeRole_Good_AppliesRoleWhen(t *testing.T) { +func TestExecutorExtra_RunIncludeRole_Good_AppliesRoleWhen(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "roles", "app", "tasks", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "app", "tasks", "main.yml"), []byte(`--- - name: Conditional role task debug: msg: "role task ran" @@ -1458,7 +1459,7 @@ func TestExecutorExtra_RunIncludeRole_Good_AppliesRoleWhen(t *testing.T) { GatherFacts: &gatherFacts, } - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"localhost"}, &Task{ + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"localhost"}, &Task{ Name: "Load role with conditional apply", IncludeRole: &RoleRef{ Role: "app", @@ -1468,14 +1469,14 @@ func TestExecutorExtra_RunIncludeRole_Good_AppliesRoleWhen(t *testing.T) { }, }, play)) - require.NotNil(t, e.results["localhost"]["role_result"]) - assert.True(t, e.results["localhost"]["role_result"].Skipped) - assert.Equal(t, "Skipped due to when condition", e.results["localhost"]["role_result"].Msg) + core.AssertNotNil(t, e.results["localhost"]["role_result"]) + core.AssertTrue(t, e.results["localhost"]["role_result"].Skipped) + core.AssertEqual(t, "Skipped due to when condition", e.results["localhost"]["role_result"].Msg) } -func TestExecutorExtra_RunIncludeRole_Good_UsesRoleRefTagsForSelection(t *testing.T) { +func TestExecutorExtra_RunIncludeRole_Good_UsesRoleRefTagsForSelection(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "roles", "tagged", "tasks", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "tagged", "tasks", "main.yml"), []byte(`--- - name: Tagged role task debug: msg: "role task ran" @@ -1498,7 +1499,7 @@ func TestExecutorExtra_RunIncludeRole_Good_UsesRoleRefTagsForSelection(t *testin GatherFacts: &gatherFacts, } - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"host1"}, &Task{ + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"host1"}, &Task{ Name: "Load tagged role", IncludeRole: &RoleRef{ Role: "tagged", @@ -1506,13 +1507,13 @@ func TestExecutorExtra_RunIncludeRole_Good_UsesRoleRefTagsForSelection(t *testin }, }, play)) - require.NotNil(t, e.results["host1"]["role_result"]) - assert.Equal(t, "role task ran", e.results["host1"]["role_result"].Msg) + core.AssertNotNil(t, e.results["host1"]["role_result"]) + core.AssertEqual(t, "role task ran", e.results["host1"]["role_result"].Msg) } -func TestExecutorExtra_RunIncludeRole_Good_HonoursRoleRefWhen(t *testing.T) { +func TestExecutorExtra_RunIncludeRole_Good_HonoursRoleRefWhen(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "roles", "conditional", "tasks", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "conditional", "tasks", "main.yml"), []byte(`--- - name: Conditional role task debug: msg: "role task ran" @@ -1540,7 +1541,7 @@ func TestExecutorExtra_RunIncludeRole_Good_HonoursRoleRefWhen(t *testing.T) { started = append(started, task.Name) } - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"host1"}, &Task{ + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"host1"}, &Task{ Name: "Load conditional role", IncludeRole: &RoleRef{ Role: "conditional", @@ -1548,16 +1549,16 @@ func TestExecutorExtra_RunIncludeRole_Good_HonoursRoleRefWhen(t *testing.T) { }, }, play)) - assert.Empty(t, started) + core.AssertEmpty(t, started) if results := e.results["host1"]; results != nil { _, ok := results["role_result"] - assert.False(t, ok) + core.AssertFalse(t, ok) } } -func TestExecutorExtra_RunIncludeRole_Good_PublicVarsPersist(t *testing.T) { +func TestExecutorExtra_RunIncludeRole_Good_PublicVarsPersist(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "roles", "shared", "tasks", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "shared", "tasks", "main.yml"), []byte(`--- - name: Shared role task debug: msg: "{{ shared_message }}" @@ -1598,15 +1599,15 @@ func TestExecutorExtra_RunIncludeRole_Good_PublicVarsPersist(t *testing.T) { }, } - require.NoError(t, e.runPlay(context.Background(), play)) + core.RequireNoError(t, e.runPlay(context.Background(), play)) - require.NotNil(t, e.results["localhost"]["shared_role_result"]) - assert.Equal(t, "hello from public role", e.results["localhost"]["shared_role_result"].Msg) - require.NotNil(t, e.results["localhost"]["after_public_role"]) - assert.Equal(t, "hello from public role", e.results["localhost"]["after_public_role"].Msg) + core.AssertNotNil(t, e.results["localhost"]["shared_role_result"]) + core.AssertEqual(t, "hello from public role", e.results["localhost"]["shared_role_result"].Msg) + core.AssertNotNil(t, e.results["localhost"]["after_public_role"]) + core.AssertEqual(t, "hello from public role", e.results["localhost"]["after_public_role"].Msg) } -func TestExecutorExtra_RunPlay_Good_ModuleDefaultsApplyToTasks(t *testing.T) { +func TestExecutorExtra_RunPlay_Good_ModuleDefaultsApplyToTasks(t *core.T) { dir := t.TempDir() e := NewExecutor(dir) e.SetInventoryDirect(&Inventory{ @@ -1642,14 +1643,14 @@ func TestExecutorExtra_RunPlay_Good_ModuleDefaultsApplyToTasks(t *testing.T) { }, } - require.NoError(t, e.runPlay(context.Background(), play)) + core.RequireNoError(t, e.runPlay(context.Background(), play)) - require.NotNil(t, e.results["localhost"]["command_result"]) - assert.Equal(t, "/tmp/module-defaults\n", e.results["localhost"]["command_result"].Stdout) - assert.True(t, mock.hasExecuted(`cd "/tmp/module-defaults" && pwd`)) + core.AssertNotNil(t, e.results["localhost"]["command_result"]) + core.AssertEqual(t, "/tmp/module-defaults\n", e.results["localhost"]["command_result"].Stdout) + core.AssertTrue(t, mock.hasExecuted(`cd "/tmp/module-defaults" && pwd`)) } -func TestExecutorExtra_GetHostsIter_Good(t *testing.T) { +func TestExecutorExtra_GetHostsIter_Good(t *core.T) { inv := &Inventory{ All: &InventoryGroup{ Hosts: map[string]*Host{ @@ -1664,10 +1665,10 @@ func TestExecutorExtra_GetHostsIter_Good(t *testing.T) { for host := range GetHostsIter(inv, "all") { hosts = append(hosts, host) } - assert.Len(t, hosts, 3) + core.AssertLen(t, hosts, 3) } -func TestExecutorExtra_AllHostsIter_Good(t *testing.T) { +func TestExecutorExtra_AllHostsIter_Good(t *core.T) { group := &InventoryGroup{ Hosts: map[string]*Host{ "alpha": {}, @@ -1686,26 +1687,26 @@ func TestExecutorExtra_AllHostsIter_Good(t *testing.T) { for host := range AllHostsIter(group) { hosts = append(hosts, host) } - assert.Len(t, hosts, 3) + core.AssertLen(t, hosts, 3) // AllHostsIter sorts keys - assert.Equal(t, "alpha", hosts[0]) - assert.Equal(t, "beta", hosts[1]) - assert.Equal(t, "gamma", hosts[2]) + core.AssertEqual(t, "alpha", hosts[0]) + core.AssertEqual(t, "beta", hosts[1]) + core.AssertEqual(t, "gamma", hosts[2]) } -func TestExecutorExtra_AllHostsIter_Good_NilGroup(t *testing.T) { +func TestExecutorExtra_AllHostsIter_Good_NilGroup(t *core.T) { var count int for range AllHostsIter(nil) { count++ } - assert.Equal(t, 0, count) + core.AssertEqual(t, 0, count) } // ============================================================ // Tests for resolveExpr with registered vars (additional coverage) // ============================================================ -func TestExecutorExtra_ResolveExpr_Good_RegisteredVarFields(t *testing.T) { +func TestExecutorExtra_ResolveExpr_Good_RegisteredVarFields(t *core.T) { e := NewExecutor("/tmp") e.results["host1"] = map[string]*TaskResult{ "cmd_result": { @@ -1717,14 +1718,14 @@ func TestExecutorExtra_ResolveExpr_Good_RegisteredVarFields(t *testing.T) { }, } - assert.Equal(t, "output text", e.resolveExpr("cmd_result.stdout", "host1", nil)) - assert.Equal(t, "error text", e.resolveExpr("cmd_result.stderr", "host1", nil)) - assert.Equal(t, "0", e.resolveExpr("cmd_result.rc", "host1", nil)) - assert.Equal(t, "true", e.resolveExpr("cmd_result.changed", "host1", nil)) - assert.Equal(t, "false", e.resolveExpr("cmd_result.failed", "host1", nil)) + core.AssertEqual(t, "output text", e.resolveExpr("cmd_result.stdout", "host1", nil)) + core.AssertEqual(t, "error text", e.resolveExpr("cmd_result.stderr", "host1", nil)) + core.AssertEqual(t, "0", e.resolveExpr("cmd_result.rc", "host1", nil)) + core.AssertEqual(t, "true", e.resolveExpr("cmd_result.changed", "host1", nil)) + core.AssertEqual(t, "false", e.resolveExpr("cmd_result.failed", "host1", nil)) } -func TestExecutorExtra_ResolveExpr_Good_BareRegisteredVar(t *testing.T) { +func TestExecutorExtra_ResolveExpr_Good_BareRegisteredVar(t *core.T) { e := NewExecutor("/tmp") result := &TaskResult{Stdout: "output text", RC: 0, Changed: true} e.results["host1"] = map[string]*TaskResult{ @@ -1733,21 +1734,21 @@ func TestExecutorExtra_ResolveExpr_Good_BareRegisteredVar(t *testing.T) { value, ok := e.resolveExprValue("cmd_result", "host1", nil) - require.True(t, ok) - assert.Same(t, result, value) + core.RequireTrue(t, ok) + core.AssertSame(t, result, value) } -func TestExecutorExtra_ResolveExpr_Good_TaskVars(t *testing.T) { +func TestExecutorExtra_ResolveExpr_Good_TaskVars(t *core.T) { e := NewExecutor("/tmp") task := &Task{ Vars: map[string]any{"local_var": "local_value"}, } result := e.resolveExpr("local_var", "host1", task) - assert.Equal(t, "local_value", result) + core.AssertEqual(t, "local_value", result) } -func TestExecutorExtra_ResolveExpr_Good_HostVars(t *testing.T) { +func TestExecutorExtra_ResolveExpr_Good_HostVars(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -1758,10 +1759,10 @@ func TestExecutorExtra_ResolveExpr_Good_HostVars(t *testing.T) { }) result := e.resolveExpr("ansible_host", "host1", nil) - assert.Equal(t, "10.0.0.1", result) + core.AssertEqual(t, "10.0.0.1", result) } -func TestExecutorExtra_ResolveExpr_Good_Facts(t *testing.T) { +func TestExecutorExtra_ResolveExpr_Good_Facts(t *core.T) { e := NewExecutor("/tmp") e.facts["host1"] = &Facts{ Hostname: "web01", @@ -1772,73 +1773,77 @@ func TestExecutorExtra_ResolveExpr_Good_Facts(t *testing.T) { Kernel: "5.15.0", } - assert.Equal(t, "web01", e.resolveExpr("ansible_hostname", "host1", nil)) - assert.Equal(t, "web01.example.com", e.resolveExpr("ansible_fqdn", "host1", nil)) - assert.Equal(t, "ubuntu", e.resolveExpr("ansible_distribution", "host1", nil)) - assert.Equal(t, "22.04", e.resolveExpr("ansible_distribution_version", "host1", nil)) - assert.Equal(t, "x86_64", e.resolveExpr("ansible_architecture", "host1", nil)) - assert.Equal(t, "5.15.0", e.resolveExpr("ansible_kernel", "host1", nil)) + core.AssertEqual(t, "web01", e.resolveExpr("ansible_hostname", "host1", nil)) + core.AssertEqual(t, "web01.example.com", e.resolveExpr("ansible_fqdn", "host1", nil)) + core.AssertEqual(t, "ubuntu", e.resolveExpr("ansible_distribution", "host1", nil)) + core.AssertEqual(t, "22.04", e.resolveExpr("ansible_distribution_version", "host1", nil)) + core.AssertEqual(t, "x86_64", e.resolveExpr("ansible_architecture", "host1", nil)) + core.AssertEqual(t, "5.15.0", e.resolveExpr("ansible_kernel", "host1", nil)) } // --- applyFilter additional coverage --- -func TestExecutorExtra_ApplyFilter_Good_B64Decode(t *testing.T) { +func TestExecutorExtra_ApplyFilter_Good_B64Decode(t *core.T) { e := NewExecutor("/tmp") - assert.Equal(t, "hello", e.applyFilter("aGVsbG8=", "b64decode")) + result := e.applyFilter("aGVsbG8=", "b64decode") + core.AssertEqual(t, "hello", result) } -func TestExecutorExtra_ApplyFilter_Good_B64Encode(t *testing.T) { +func TestExecutorExtra_ApplyFilter_Good_B64Encode(t *core.T) { e := NewExecutor("/tmp") - assert.Equal(t, "aGVsbG8=", e.applyFilter("hello", "b64encode")) + result := e.applyFilter("hello", "b64encode") + core.AssertEqual(t, "aGVsbG8=", result) } -func TestExecutorExtra_ApplyFilter_Good_UnknownFilter(t *testing.T) { +func TestExecutorExtra_ApplyFilter_Good_UnknownFilter(t *core.T) { e := NewExecutor("/tmp") - assert.Equal(t, "value", e.applyFilter("value", "unknown_filter")) + result := e.applyFilter("value", "unknown_filter") + core.AssertEqual(t, "value", result) } // --- evalCondition with default filter --- -func TestExecutorExtra_EvalCondition_Good_DefaultFilter(t *testing.T) { +func TestExecutorExtra_EvalCondition_Good_DefaultFilter(t *core.T) { e := NewExecutor("/tmp") - assert.True(t, e.evalCondition("myvar | default('fallback')", "host1")) + result := e.evalCondition("myvar | default('fallback')", "host1") + core.AssertTrue(t, result) } -func TestExecutorExtra_EvalCondition_Good_UndefinedCheck(t *testing.T) { +func TestExecutorExtra_EvalCondition_Good_UndefinedCheck(t *core.T) { e := NewExecutor("/tmp") - assert.True(t, e.evalCondition("missing_var is not defined", "host1")) - assert.True(t, e.evalCondition("missing_var is undefined", "host1")) + core.AssertTrue(t, e.evalCondition("missing_var is not defined", "host1")) + core.AssertTrue(t, e.evalCondition("missing_var is undefined", "host1")) } -func TestExecutorExtra_EvalCondition_Good_BinaryOperators(t *testing.T) { +func TestExecutorExtra_EvalCondition_Good_BinaryOperators(t *core.T) { e := NewExecutor("/tmp") e.vars["count"] = 2 e.vars["limit"] = 5 e.vars["roles"] = []string{"web", "api"} - assert.True(t, e.evalCondition("count < limit", "host1")) - assert.True(t, e.evalCondition("count <= 2", "host1")) - assert.True(t, e.evalCondition("count<=2", "host1")) - assert.True(t, e.evalCondition("count!=limit", "host1")) - assert.True(t, e.evalCondition("limit >= count", "host1")) - assert.True(t, e.evalCondition("'web' in roles", "host1")) - assert.True(t, e.evalCondition("roles contains 'api'", "host1")) - assert.True(t, e.evalCondition("'db' not in roles", "host1")) - assert.False(t, e.evalCondition("count > limit", "host1")) - assert.False(t, e.evalCondition("count < missing_limit", "host1")) + core.AssertTrue(t, e.evalCondition("count < limit", "host1")) + core.AssertTrue(t, e.evalCondition("count <= 2", "host1")) + core.AssertTrue(t, e.evalCondition("count<=2", "host1")) + core.AssertTrue(t, e.evalCondition("count!=limit", "host1")) + core.AssertTrue(t, e.evalCondition("limit >= count", "host1")) + core.AssertTrue(t, e.evalCondition("'web' in roles", "host1")) + core.AssertTrue(t, e.evalCondition("roles contains 'api'", "host1")) + core.AssertTrue(t, e.evalCondition("'db' not in roles", "host1")) + core.AssertFalse(t, e.evalCondition("count > limit", "host1")) + core.AssertFalse(t, e.evalCondition("count < missing_limit", "host1")) } // --- resolveExpr with filter pipe --- -func TestExecutorExtra_ResolveExpr_Good_WithFilter(t *testing.T) { +func TestExecutorExtra_ResolveExpr_Good_WithFilter(t *core.T) { e := NewExecutor("/tmp") e.vars["raw_value"] = " trimmed " result := e.resolveExpr("raw_value | trim", "host1", nil) - assert.Equal(t, "trimmed", result) + core.AssertEqual(t, "trimmed", result) } -func TestExecutorExtra_ResolveExpr_Good_CommonFilters(t *testing.T) { +func TestExecutorExtra_ResolveExpr_Good_CommonFilters(t *core.T) { e := NewExecutor("/tmp") e.vars["name"] = "Hello" e.vars["path"] = "/tmp/example/nginx.conf" @@ -1848,23 +1853,23 @@ func TestExecutorExtra_ResolveExpr_Good_CommonFilters(t *testing.T) { e.vars["negative"] = -7 e.vars["values"] = []any{3, 1, 2} - assert.Equal(t, "HELLO", e.resolveExpr("name | upper", "host1", nil)) - assert.Equal(t, "hello", e.resolveExpr("name | lower", "host1", nil)) - assert.Equal(t, "nginx.conf", e.resolveExpr("path | basename", "host1", nil)) - assert.Equal(t, "/tmp/example", e.resolveExpr("path | dirname", "host1", nil)) - assert.Equal(t, "a,b", e.resolveExpr("parts | join(',')", "host1", nil)) - assert.Equal(t, "[a b c]", e.resolveExpr("csv | split(',')", "host1", nil)) - assert.Equal(t, "42", e.resolveExpr("count | int", "host1", nil)) - assert.Equal(t, "7", e.resolveExpr("negative | abs", "host1", nil)) - assert.Equal(t, "1", e.resolveExpr("values | min", "host1", nil)) - assert.Equal(t, "3", e.resolveExpr("values | max", "host1", nil)) - assert.Equal(t, "3", e.resolveExpr("values | length", "host1", nil)) + core.AssertEqual(t, "HELLO", e.resolveExpr("name | upper", "host1", nil)) + core.AssertEqual(t, "hello", e.resolveExpr("name | lower", "host1", nil)) + core.AssertEqual(t, "nginx.conf", e.resolveExpr("path | basename", "host1", nil)) + core.AssertEqual(t, "/tmp/example", e.resolveExpr("path | dirname", "host1", nil)) + core.AssertEqual(t, "a,b", e.resolveExpr("parts | join(',')", "host1", nil)) + core.AssertEqual(t, "[a b c]", e.resolveExpr("csv | split(',')", "host1", nil)) + core.AssertEqual(t, "42", e.resolveExpr("count | int", "host1", nil)) + core.AssertEqual(t, "7", e.resolveExpr("negative | abs", "host1", nil)) + core.AssertEqual(t, "1", e.resolveExpr("values | min", "host1", nil)) + core.AssertEqual(t, "3", e.resolveExpr("values | max", "host1", nil)) + core.AssertEqual(t, "3", e.resolveExpr("values | length", "host1", nil)) } -func TestExecutorExtra_ResolveExpr_Good_WithB64Encode(t *testing.T) { +func TestExecutorExtra_ResolveExpr_Good_WithB64Encode(t *core.T) { e := NewExecutor("/tmp") e.vars["raw_value"] = "hello" result := e.resolveExpr("raw_value | b64encode", "host1", nil) - assert.Equal(t, "aGVsbG8=", result) + core.AssertEqual(t, "aGVsbG8=", result) } diff --git a/executor_test.go b/executor_test.go index 0ac2417..cf65c43 100644 --- a/executor_test.go +++ b/executor_test.go @@ -2,13 +2,11 @@ package ansible import ( "context" + core "dappco.re/go" "os" "path/filepath" - "testing" "time" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "gopkg.in/yaml.v3" ) @@ -38,33 +36,33 @@ func boolPtr(v bool) *bool { // --- NewExecutor --- -func TestExecutor_NewExecutor_Good(t *testing.T) { +func TestExecutor_NewExecutor_Good(t *core.T) { e := NewExecutor("/some/path") - assert.NotNil(t, e) - assert.NotNil(t, e.parser) - assert.NotNil(t, e.vars) - assert.NotNil(t, e.facts) - assert.NotNil(t, e.results) - assert.NotNil(t, e.handlers) - assert.NotNil(t, e.notified) - assert.NotNil(t, e.clients) + core.AssertNotNil(t, e) + core.AssertNotNil(t, e.parser) + core.AssertNotNil(t, e.vars) + core.AssertNotNil(t, e.facts) + core.AssertNotNil(t, e.results) + core.AssertNotNil(t, e.handlers) + core.AssertNotNil(t, e.notified) + core.AssertNotNil(t, e.clients) } // --- SetVar --- -func TestExecutor_SetVar_Good(t *testing.T) { +func TestExecutor_SetVar_Good(t *core.T) { e := NewExecutor("/tmp") e.SetVar("foo", "bar") e.SetVar("count", 42) - assert.Equal(t, "bar", e.vars["foo"]) - assert.Equal(t, 42, e.vars["count"]) + core.AssertEqual(t, "bar", e.vars["foo"]) + core.AssertEqual(t, 42, e.vars["count"]) } // --- SetInventoryDirect --- -func TestExecutor_SetInventoryDirect_Good(t *testing.T) { +func TestExecutor_SetInventoryDirect_Good(t *core.T) { e := NewExecutor("/tmp") inv := &Inventory{ All: &InventoryGroup{ @@ -75,13 +73,13 @@ func TestExecutor_SetInventoryDirect_Good(t *testing.T) { } e.SetInventoryDirect(inv) - assert.Equal(t, inv, e.inventory) + core.AssertEqual(t, inv, e.inventory) } -func TestExecutor_Run_Good_UsesCachedClient(t *testing.T) { +func TestExecutor_Run_Good_UsesCachedClient(t *core.T) { dir := t.TempDir() playbookPath := filepath.Join(dir, "site.yml") - require.NoError(t, writeTestFile(playbookPath, []byte(`--- + core.RequireNoError(t, writeTestFile(playbookPath, []byte(`--- - hosts: localhost gather_facts: false tasks: @@ -95,19 +93,19 @@ func TestExecutor_Run_Good_UsesCachedClient(t *testing.T) { mock.expectCommand(`^echo ok$`, "ok\n", "", 0) e.clients["localhost"] = mock - require.NoError(t, e.Run(context.Background(), playbookPath)) + core.RequireNoError(t, e.Run(context.Background(), playbookPath)) - require.NotNil(t, e.results["localhost"]["shell_result"]) - assert.Equal(t, "ok\n", e.results["localhost"]["shell_result"].Stdout) - assert.True(t, e.results["localhost"]["shell_result"].Changed) - assert.Equal(t, 1, len(mock.executed)) - assert.Equal(t, "RunScript", mock.executed[0].Method) - assert.Equal(t, "echo ok", mock.executed[0].Cmd) + core.AssertNotNil(t, e.results["localhost"]["shell_result"]) + core.AssertEqual(t, "ok\n", e.results["localhost"]["shell_result"].Stdout) + core.AssertTrue(t, e.results["localhost"]["shell_result"].Changed) + core.AssertEqual(t, 1, len(mock.executed)) + core.AssertEqual(t, "RunScript", mock.executed[0].Method) + core.AssertEqual(t, "echo ok", mock.executed[0].Cmd) } // --- getHosts --- -func TestExecutor_GetHosts_Good_WithInventory(t *testing.T) { +func TestExecutor_GetHosts_Good_WithInventory(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -119,25 +117,25 @@ func TestExecutor_GetHosts_Good_WithInventory(t *testing.T) { }) hosts := e.getHosts("all") - assert.Len(t, hosts, 2) + core.AssertLen(t, hosts, 2) } -func TestExecutor_GetHosts_Good_Localhost(t *testing.T) { +func TestExecutor_GetHosts_Good_Localhost(t *core.T) { e := NewExecutor("/tmp") // No inventory set hosts := e.getHosts("localhost") - assert.Equal(t, []string{"localhost"}, hosts) + core.AssertEqual(t, []string{"localhost"}, hosts) } -func TestExecutor_GetHosts_Good_NoInventory(t *testing.T) { +func TestExecutor_GetHosts_Good_NoInventory(t *core.T) { e := NewExecutor("/tmp") hosts := e.getHosts("webservers") - assert.Nil(t, hosts) + core.AssertNil(t, hosts) } -func TestExecutor_GetHosts_Good_WithLimit(t *testing.T) { +func TestExecutor_GetHosts_Good_WithLimit(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -151,11 +149,11 @@ func TestExecutor_GetHosts_Good_WithLimit(t *testing.T) { e.Limit = "host2" hosts := e.getHosts("all") - assert.Len(t, hosts, 1) - assert.Contains(t, hosts, "host2") + core.AssertLen(t, hosts, 1) + core.AssertContains(t, hosts, "host2") } -func TestExecutor_GetClient_Good_PlayVarsOverrideInventoryVars(t *testing.T) { +func TestExecutor_GetClient_Good_PlayVarsOverrideInventoryVars(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -171,15 +169,15 @@ func TestExecutor_GetClient_Good_PlayVarsOverrideInventoryVars(t *testing.T) { e.SetVar("ansible_user", "play-user") client, err := e.getClient("host1", &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) sshClient, ok := client.(*SSHClient) - require.True(t, ok) - assert.Equal(t, "10.0.0.20", sshClient.host) - assert.Equal(t, "play-user", sshClient.user) + core.RequireTrue(t, ok) + core.AssertEqual(t, "10.0.0.20", sshClient.host) + core.AssertEqual(t, "play-user", sshClient.user) } -func TestExecutor_GetClient_Good_UsesInventoryBecomePassword(t *testing.T) { +func TestExecutor_GetClient_Good_UsesInventoryBecomePassword(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -193,17 +191,17 @@ func TestExecutor_GetClient_Good_UsesInventoryBecomePassword(t *testing.T) { }) client, err := e.getClient("host1", &Play{Become: true, BecomeUser: "admin"}) - require.NoError(t, err) + core.RequireNoError(t, err) sshClient, ok := client.(*SSHClient) - require.True(t, ok) + core.RequireTrue(t, ok) become, user, pass := sshClient.BecomeState() - assert.True(t, become) - assert.Equal(t, "admin", user) - assert.Equal(t, "secret", pass) + core.AssertTrue(t, become) + core.AssertEqual(t, "admin", user) + core.AssertEqual(t, "secret", pass) } -func TestExecutor_GetClient_Good_UpdatesCachedBecomeState(t *testing.T) { +func TestExecutor_GetClient_Good_UpdatesCachedBecomeState(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -218,102 +216,102 @@ func TestExecutor_GetClient_Good_UpdatesCachedBecomeState(t *testing.T) { play := &Play{Become: true, BecomeUser: "admin"} client, err := e.getClient("host1", play) - require.NoError(t, err) - require.Same(t, cached, client) + core.RequireNoError(t, err) + core.AssertSame(t, cached, client) become, user, pass := cached.BecomeState() - assert.True(t, become) - assert.Equal(t, "admin", user) - assert.Empty(t, pass) + core.AssertTrue(t, become) + core.AssertEqual(t, "admin", user) + core.AssertEmpty(t, pass) } // --- matchesTags --- -func TestExecutor_MatchesTags_Good_NoTagsFilter(t *testing.T) { +func TestExecutor_MatchesTags_Good_NoTagsFilter(t *core.T) { e := NewExecutor("/tmp") - assert.True(t, e.matchesTags(nil)) - assert.True(t, e.matchesTags([]string{"any", "tags"})) + core.AssertTrue(t, e.matchesTags(nil)) + core.AssertTrue(t, e.matchesTags([]string{"any", "tags"})) } -func TestExecutor_MatchesTags_Good_IncludeTag(t *testing.T) { +func TestExecutor_MatchesTags_Good_IncludeTag(t *core.T) { e := NewExecutor("/tmp") e.Tags = []string{"deploy"} - assert.True(t, e.matchesTags([]string{"deploy"})) - assert.True(t, e.matchesTags([]string{"setup", "deploy"})) - assert.False(t, e.matchesTags([]string{"other"})) + core.AssertTrue(t, e.matchesTags([]string{"deploy"})) + core.AssertTrue(t, e.matchesTags([]string{"setup", "deploy"})) + core.AssertFalse(t, e.matchesTags([]string{"other"})) } -func TestExecutor_MatchesTags_Good_SkipTag(t *testing.T) { +func TestExecutor_MatchesTags_Good_SkipTag(t *core.T) { e := NewExecutor("/tmp") e.SkipTags = []string{"slow"} - assert.True(t, e.matchesTags([]string{"fast"})) - assert.False(t, e.matchesTags([]string{"slow"})) - assert.False(t, e.matchesTags([]string{"fast", "slow"})) + core.AssertTrue(t, e.matchesTags([]string{"fast"})) + core.AssertFalse(t, e.matchesTags([]string{"slow"})) + core.AssertFalse(t, e.matchesTags([]string{"fast", "slow"})) } -func TestExecutor_MatchesTags_Good_AllTag(t *testing.T) { +func TestExecutor_MatchesTags_Good_AllTag(t *core.T) { e := NewExecutor("/tmp") e.Tags = []string{"all"} - assert.True(t, e.matchesTags([]string{"anything"})) + core.AssertTrue(t, e.matchesTags([]string{"anything"})) } -func TestExecutor_MatchesTags_Good_AlwaysTagIgnoresIncludeFilter(t *testing.T) { +func TestExecutor_MatchesTags_Good_AlwaysTagIgnoresIncludeFilter(t *core.T) { e := NewExecutor("/tmp") e.Tags = []string{"deploy"} - assert.True(t, e.matchesTags([]string{"always"})) - assert.True(t, e.matchesTags([]string{"always", "other"})) + core.AssertTrue(t, e.matchesTags([]string{"always"})) + core.AssertTrue(t, e.matchesTags([]string{"always", "other"})) } -func TestExecutor_MatchesTags_Good_AlwaysTagStillRespectsSkipFilter(t *testing.T) { +func TestExecutor_MatchesTags_Good_AlwaysTagStillRespectsSkipFilter(t *core.T) { e := NewExecutor("/tmp") e.Tags = []string{"deploy"} e.SkipTags = []string{"always"} - assert.False(t, e.matchesTags([]string{"always"})) + core.AssertFalse(t, e.matchesTags([]string{"always"})) } -func TestExecutor_MatchesTags_Good_NoTaskTags(t *testing.T) { +func TestExecutor_MatchesTags_Good_NoTaskTags(t *core.T) { e := NewExecutor("/tmp") e.Tags = []string{"deploy"} // Tasks with no tags should not match when include tags are set - assert.False(t, e.matchesTags(nil)) - assert.False(t, e.matchesTags([]string{})) + core.AssertFalse(t, e.matchesTags(nil)) + core.AssertFalse(t, e.matchesTags([]string{})) } // --- handleNotify --- -func TestExecutor_HandleNotify_Good_String(t *testing.T) { +func TestExecutor_HandleNotify_Good_String(t *core.T) { e := NewExecutor("/tmp") e.handleNotify("restart nginx") - assert.True(t, e.notified["restart nginx"]) + core.AssertTrue(t, e.notified["restart nginx"]) } -func TestExecutor_HandleNotify_Good_StringList(t *testing.T) { +func TestExecutor_HandleNotify_Good_StringList(t *core.T) { e := NewExecutor("/tmp") e.handleNotify([]string{"restart nginx", "reload config"}) - assert.True(t, e.notified["restart nginx"]) - assert.True(t, e.notified["reload config"]) + core.AssertTrue(t, e.notified["restart nginx"]) + core.AssertTrue(t, e.notified["reload config"]) } -func TestExecutor_HandleNotify_Good_AnyList(t *testing.T) { +func TestExecutor_HandleNotify_Good_AnyList(t *core.T) { e := NewExecutor("/tmp") e.handleNotify([]any{"restart nginx", "reload config"}) - assert.True(t, e.notified["restart nginx"]) - assert.True(t, e.notified["reload config"]) + core.AssertTrue(t, e.notified["restart nginx"]) + core.AssertTrue(t, e.notified["reload config"]) } // --- run_once --- -func TestExecutor_RunTaskOnHosts_Good_RunOnceSharesRegisteredResult(t *testing.T) { +func TestExecutor_RunTaskOnHosts_Good_RunOnceSharesRegisteredResult(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -338,18 +336,18 @@ func TestExecutor_RunTaskOnHosts_Good_RunOnceSharesRegisteredResult(t *testing.T } err := e.runTaskOnHosts(context.Background(), []string{"host1", "host2"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Len(t, started, 1) - assert.Len(t, e.results["host1"], 1) - assert.Len(t, e.results["host2"], 1) - require.NotNil(t, e.results["host1"]["debug_result"]) - require.NotNil(t, e.results["host2"]["debug_result"]) - assert.Equal(t, "hello", e.results["host1"]["debug_result"].Msg) - assert.Equal(t, "hello", e.results["host2"]["debug_result"].Msg) + core.AssertLen(t, started, 1) + core.AssertLen(t, e.results["host1"], 1) + core.AssertLen(t, e.results["host2"], 1) + core.AssertNotNil(t, e.results["host1"]["debug_result"]) + core.AssertNotNil(t, e.results["host2"]["debug_result"]) + core.AssertEqual(t, "hello", e.results["host1"]["debug_result"].Msg) + core.AssertEqual(t, "hello", e.results["host2"]["debug_result"].Msg) } -func TestExecutor_RunTaskOnHost_Good_DelegateToUsesDelegatedClient(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_DelegateToUsesDelegatedClient(t *core.T) { e, mock := newTestExecutorWithMock("host1") e.SetVar("delegate_host", "delegate1") e.inventory.All.Hosts["delegate1"] = &Host{AnsibleHost: "127.0.0.2"} @@ -365,15 +363,15 @@ func TestExecutor_RunTaskOnHost_Good_DelegateToUsesDelegatedClient(t *testing.T) } err := e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) - require.NotNil(t, e.results["host1"]["delegated_result"]) - assert.Equal(t, "delegated", e.results["host1"]["delegated_result"].Stdout) - assert.True(t, mock.hasExecuted(`echo delegated`)) - assert.Equal(t, 1, mock.commandCount()) + core.AssertNotNil(t, e.results["host1"]["delegated_result"]) + core.AssertEqual(t, "delegated", e.results["host1"]["delegated_result"].Stdout) + core.AssertTrue(t, mock.hasExecuted(`echo delegated`)) + core.AssertEqual(t, 1, mock.commandCount()) } -func TestExecutor_RunTaskOnHost_Good_DelegateToTemplatesInventoryHostname(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_DelegateToTemplatesInventoryHostname(t *core.T) { e := NewExecutor("/tmp") mock := NewMockSSHClient() e.clients["host1-delegate"] = mock @@ -387,46 +385,46 @@ func TestExecutor_RunTaskOnHost_Good_DelegateToTemplatesInventoryHostname(t *tes } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.True(t, mock.hasExecuted(`echo templated`)) + core.AssertTrue(t, mock.hasExecuted(`echo templated`)) _, leaked := e.vars["inventory_hostname"] - assert.False(t, leaked) + core.AssertFalse(t, leaked) } -func TestExecutor_RunTaskOnHost_Good_ActionAliasExecutesCommand(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_ActionAliasExecutesCommand(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`echo action-alias`, "action-alias", "", 0) var task Task - require.NoError(t, yaml.Unmarshal([]byte(` + core.RequireNoError(t, yaml.Unmarshal([]byte(` name: Legacy action action: command echo action-alias `), &task)) task.Register = "action_result" err := e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, &task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) - require.NotNil(t, e.results["host1"]["action_result"]) - assert.Equal(t, "action-alias", e.results["host1"]["action_result"].Stdout) - assert.True(t, mock.hasExecuted(`echo action-alias`)) + core.AssertNotNil(t, e.results["host1"]["action_result"]) + core.AssertEqual(t, "action-alias", e.results["host1"]["action_result"].Stdout) + core.AssertTrue(t, mock.hasExecuted(`echo action-alias`)) } -func TestExecutor_Run_Good_VarsFilesMergeIntoPlayVars(t *testing.T) { +func TestExecutor_Run_Good_VarsFilesMergeIntoPlayVars(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "vars", "common.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "vars", "common.yml"), []byte(`--- http_port: 8080 app_name: base environment: staging `), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "vars", "override.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "vars", "override.yml"), []byte(`--- app_name: demo `), 0644)) playbookPath := joinPath(dir, "playbook.yml") - require.NoError(t, writeTestFile(playbookPath, []byte(`--- + core.RequireNoError(t, writeTestFile(playbookPath, []byte(`--- - name: Vars files hosts: localhost gather_facts: false @@ -443,22 +441,22 @@ app_name: demo `), 0644)) e := NewExecutor(dir) - require.NoError(t, e.Run(context.Background(), playbookPath)) + core.RequireNoError(t, e.Run(context.Background(), playbookPath)) - require.NotNil(t, e.results["localhost"]) - require.NotNil(t, e.results["localhost"]["vars_result"]) - assert.Equal(t, "8080 demo prod", e.results["localhost"]["vars_result"].Msg) + core.AssertNotNil(t, e.results["localhost"]) + core.AssertNotNil(t, e.results["localhost"]["vars_result"]) + core.AssertEqual(t, "8080 demo prod", e.results["localhost"]["vars_result"].Msg) } -func TestExecutor_Run_Good_VarsFilesSupportTemplatedPaths(t *testing.T) { +func TestExecutor_Run_Good_VarsFilesSupportTemplatedPaths(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "vars", "prod.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "vars", "prod.yml"), []byte(`--- app_name: templated `), 0644)) playbookPath := joinPath(dir, "playbook.yml") - require.NoError(t, writeTestFile(playbookPath, []byte(`--- + core.RequireNoError(t, writeTestFile(playbookPath, []byte(`--- - name: Vars files templated path hosts: localhost gather_facts: false @@ -474,22 +472,22 @@ app_name: templated `), 0644)) e := NewExecutor(dir) - require.NoError(t, e.Run(context.Background(), playbookPath)) + core.RequireNoError(t, e.Run(context.Background(), playbookPath)) - require.NotNil(t, e.results["localhost"]) - require.NotNil(t, e.results["localhost"]["vars_result"]) - assert.Equal(t, "templated", e.results["localhost"]["vars_result"].Msg) + core.AssertNotNil(t, e.results["localhost"]) + core.AssertNotNil(t, e.results["localhost"]["vars_result"]) + core.AssertEqual(t, "templated", e.results["localhost"]["vars_result"].Msg) } -func TestExecutor_Run_Good_VarsFilesSupportPlaybookDirMagicVar(t *testing.T) { +func TestExecutor_Run_Good_VarsFilesSupportPlaybookDirMagicVar(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "vars", "prod.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "vars", "prod.yml"), []byte(`--- app_name: magic `), 0644)) playbookPath := joinPath(dir, "playbook.yml") - require.NoError(t, writeTestFile(playbookPath, []byte(`--- + core.RequireNoError(t, writeTestFile(playbookPath, []byte(`--- - name: Vars files playbook dir hosts: localhost gather_facts: false @@ -503,16 +501,16 @@ app_name: magic `), 0644)) e := NewExecutor(dir) - require.NoError(t, e.Run(context.Background(), playbookPath)) + core.RequireNoError(t, e.Run(context.Background(), playbookPath)) - require.NotNil(t, e.results["localhost"]) - require.NotNil(t, e.results["localhost"]["vars_result"]) - assert.Equal(t, "magic "+dir, e.results["localhost"]["vars_result"].Msg) + core.AssertNotNil(t, e.results["localhost"]) + core.AssertNotNil(t, e.results["localhost"]["vars_result"]) + core.AssertEqual(t, "magic "+dir, e.results["localhost"]["vars_result"].Msg) } -func TestExecutor_RunTaskOnHosts_Good_WithFileUsesFileContents(t *testing.T) { +func TestExecutor_RunTaskOnHosts_Good_WithFileUsesFileContents(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "fragments", "hello.txt"), []byte("hello from file"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "fragments", "hello.txt"), []byte("hello from file"), 0644)) e := NewExecutor(dir) mock := NewMockSSHClient() @@ -536,18 +534,18 @@ func TestExecutor_RunTaskOnHosts_Good_WithFileUsesFileContents(t *testing.T) { } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) - require.NotNil(t, e.results["host1"]) - require.NotNil(t, e.results["host1"]["debug_result"]) - require.Len(t, e.results["host1"]["debug_result"].Results, 1) - assert.Equal(t, "hello from file", e.results["host1"]["debug_result"].Results[0].Msg) + core.AssertNotNil(t, e.results["host1"]) + core.AssertNotNil(t, e.results["host1"]["debug_result"]) + core.AssertLen(t, e.results["host1"]["debug_result"].Results, 1) + core.AssertEqual(t, "hello from file", e.results["host1"]["debug_result"].Results[0].Msg) } -func TestExecutor_RunTaskOnHosts_Good_WithFileGlobExpandsMatches(t *testing.T) { +func TestExecutor_RunTaskOnHosts_Good_WithFileGlobExpandsMatches(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "fragments", "alpha.txt"), []byte("alpha"), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "fragments", "beta.txt"), []byte("beta"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "fragments", "alpha.txt"), []byte("alpha"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "fragments", "beta.txt"), []byte("beta"), 0644)) e := NewExecutor(dir) mock := NewMockSSHClient() @@ -573,12 +571,12 @@ func TestExecutor_RunTaskOnHosts_Good_WithFileGlobExpandsMatches(t *testing.T) { } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) - require.NotNil(t, e.results["host1"]) - require.NotNil(t, e.results["host1"]["glob_result"]) - require.Len(t, e.results["host1"]["glob_result"].Results, 2) - assert.Equal(t, []string{ + core.AssertNotNil(t, e.results["host1"]) + core.AssertNotNil(t, e.results["host1"]["glob_result"]) + core.AssertLen(t, e.results["host1"]["glob_result"].Results, 2) + core.AssertEqual(t, []string{ joinPath(dir, "fragments", "alpha.txt"), joinPath(dir, "fragments", "beta.txt"), }, []string{ @@ -587,7 +585,7 @@ func TestExecutor_RunTaskOnHosts_Good_WithFileGlobExpandsMatches(t *testing.T) { }) } -func TestExecutor_ExecuteModule_Good_ShortFormCommunityAlias(t *testing.T) { +func TestExecutor_ExecuteModule_Good_ShortFormCommunityAlias(t *core.T) { e := NewExecutor("/tmp") mock := NewMockSSHClient() @@ -601,15 +599,15 @@ func TestExecutor_ExecuteModule_Good_ShortFormCommunityAlias(t *testing.T) { } result, err := e.executeModule(context.Background(), "host1", mock, task, &Play{}) - require.NoError(t, err) - require.NotNil(t, result) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`getent passwd deploy`)) - assert.True(t, mock.hasExecuted(`authorized_keys`)) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`getent passwd deploy`)) + core.AssertTrue(t, mock.hasExecuted(`authorized_keys`)) } -func TestExecutor_RunTaskOnHost_Good_EnvironmentMergesForCommand(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_EnvironmentMergesForCommand(t *core.T) { e, mock := newTestExecutorWithMock("host1") play := &Play{ @@ -634,14 +632,14 @@ func TestExecutor_RunTaskOnHost_Good_EnvironmentMergesForCommand(t *testing.T) { mock.expectCommand(`export APP_ENV='task'; export PLAY_ONLY='from-play'; export TASK_ONLY='from-task'; echo`, "task:from-play:from-task\n", "", 0) err := e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, play) - require.NoError(t, err) + core.RequireNoError(t, err) - require.NotNil(t, e.results["host1"]["env_result"]) - assert.Equal(t, "task:from-play:from-task\n", e.results["host1"]["env_result"].Stdout) - assert.True(t, mock.hasExecuted(`export APP_ENV='task'; export PLAY_ONLY='from-play'; export TASK_ONLY='from-task'; echo`)) + core.AssertNotNil(t, e.results["host1"]["env_result"]) + core.AssertEqual(t, "task:from-play:from-task\n", e.results["host1"]["env_result"].Stdout) + core.AssertTrue(t, mock.hasExecuted(`export APP_ENV='task'; export PLAY_ONLY='from-play'; export TASK_ONLY='from-task'; echo`)) } -func TestExecutor_RunTaskOnHost_Good_EnvironmentAppliesToShellScript(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_EnvironmentAppliesToShellScript(t *core.T) { e, mock := newTestExecutorWithMock("host1") play := &Play{ @@ -664,14 +662,14 @@ func TestExecutor_RunTaskOnHost_Good_EnvironmentAppliesToShellScript(t *testing. mock.expectCommand(`export SHELL_ONLY='from-task'; echo`, "from-task\n", "", 0) err := e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, play) - require.NoError(t, err) + core.RequireNoError(t, err) - require.NotNil(t, e.results["host1"]["shell_env_result"]) - assert.Equal(t, "from-task\n", e.results["host1"]["shell_env_result"].Stdout) - assert.True(t, mock.hasExecuted(`export SHELL_ONLY='from-task'; echo`)) + core.AssertNotNil(t, e.results["host1"]["shell_env_result"]) + core.AssertEqual(t, "from-task\n", e.results["host1"]["shell_env_result"].Stdout) + core.AssertTrue(t, mock.hasExecuted(`export SHELL_ONLY='from-task'; echo`)) } -func TestExecutor_RunRole_Good_AppliesRoleTagsToTasks(t *testing.T) { +func TestExecutor_RunRole_Good_AppliesRoleTagsToTasks(t *core.T) { dir := t.TempDir() roleTasks := `--- - name: tagged role task @@ -679,7 +677,7 @@ func TestExecutor_RunRole_Good_AppliesRoleTagsToTasks(t *testing.T) { msg: role ran register: role_result ` - require.NoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "tasks", "main.yml"), []byte(roleTasks), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "tasks", "main.yml"), []byte(roleTasks), 0644)) e := NewExecutor(dir) e.Tags = []string{"web"} @@ -701,14 +699,14 @@ func TestExecutor_RunRole_Good_AppliesRoleTagsToTasks(t *testing.T) { Role: "webserver", Tags: []string{"web"}, }, &Play{}, nil) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Equal(t, []string{"host1:tagged role task"}, started) - require.NotNil(t, e.results["host1"]["role_result"]) - assert.Equal(t, "role ran", e.results["host1"]["role_result"].Msg) + core.AssertEqual(t, []string{"host1:tagged role task"}, started) + core.AssertNotNil(t, e.results["host1"]["role_result"]) + core.AssertEqual(t, "role ran", e.results["host1"]["role_result"].Msg) } -func TestExecutor_RunRole_Good_MetaEndRoleStopsRemainingRoleTasks(t *testing.T) { +func TestExecutor_RunRole_Good_MetaEndRoleStopsRemainingRoleTasks(t *core.T) { dir := t.TempDir() roleTasks := `--- - name: before end_role @@ -722,7 +720,7 @@ func TestExecutor_RunRole_Good_MetaEndRoleStopsRemainingRoleTasks(t *testing.T) msg: after register: after_result ` - require.NoError(t, writeTestFile(joinPath(dir, "roles", "deploy", "tasks", "main.yml"), []byte(roleTasks), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "deploy", "tasks", "main.yml"), []byte(roleTasks), 0644)) e := NewExecutor(dir) e.SetInventoryDirect(&Inventory{ @@ -743,27 +741,27 @@ func TestExecutor_RunRole_Good_MetaEndRoleStopsRemainingRoleTasks(t *testing.T) err := e.runRole(context.Background(), []string{"host1"}, &RoleRef{ Role: "deploy", }, play, nil) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Equal(t, []string{"before end_role", "stop role"}, executed) - require.NotNil(t, e.results["host1"]["before_result"]) + core.AssertEqual(t, []string{"before end_role", "stop role"}, executed) + core.AssertNotNil(t, e.results["host1"]["before_result"]) _, hasAfter := e.results["host1"]["after_result"] - assert.False(t, hasAfter) + core.AssertFalse(t, hasAfter) } -func TestExecutor_RunRole_Good_AppliesRoleDefaultsAndVars(t *testing.T) { +func TestExecutor_RunRole_Good_AppliesRoleDefaultsAndVars(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "tasks", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "tasks", "main.yml"), []byte(`--- - name: role var task debug: msg: "{{ role_value }}|{{ role_param }}" register: role_result `), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "defaults", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "defaults", "main.yml"), []byte(`--- role_value: default-value `), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "vars", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "vars", "main.yml"), []byte(`--- role_value: vars-value `), 0644)) @@ -785,34 +783,34 @@ role_value: vars-value "role_param": "include-value", }, }, play, nil) - require.NoError(t, err) + core.RequireNoError(t, err) - require.NotNil(t, e.results["host1"]["role_result"]) - assert.Equal(t, "vars-value|include-value", e.results["host1"]["role_result"].Msg) - assert.Equal(t, "outer", e.vars["outer_value"]) + core.AssertNotNil(t, e.results["host1"]["role_result"]) + core.AssertEqual(t, "vars-value|include-value", e.results["host1"]["role_result"].Msg) + core.AssertEqual(t, "outer", e.vars["outer_value"]) _, leaked := e.vars["role_value"] - assert.False(t, leaked) + core.AssertFalse(t, leaked) } -func TestExecutor_RunRole_Good_UsesCustomRoleDefaultsAndVarsFiles(t *testing.T) { +func TestExecutor_RunRole_Good_UsesCustomRoleDefaultsAndVarsFiles(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "tasks", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "tasks", "main.yml"), []byte(`--- - name: role file selector task debug: msg: "{{ role_value }}|{{ role_param }}" register: role_result `), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "defaults", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "defaults", "main.yml"), []byte(`--- role_value: default-main `), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "defaults", "custom.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "defaults", "custom.yml"), []byte(`--- role_value: default-custom `), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "vars", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "vars", "main.yml"), []byte(`--- role_value: vars-main `), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "vars", "custom.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "vars", "custom.yml"), []byte(`--- role_value: vars-custom `), 0644)) @@ -834,15 +832,15 @@ role_value: vars-custom "role_param": "include-value", }, }, &Play{Connection: "local"}, nil) - require.NoError(t, err) + core.RequireNoError(t, err) - require.NotNil(t, e.results["host1"]["role_result"]) - assert.Equal(t, "vars-custom|include-value", e.results["host1"]["role_result"].Msg) + core.AssertNotNil(t, e.results["host1"]["role_result"]) + core.AssertEqual(t, "vars-custom|include-value", e.results["host1"]["role_result"].Msg) } -func TestExecutor_RunIncludeRole_Good_TemplatesRoleName(t *testing.T) { +func TestExecutor_RunIncludeRole_Good_TemplatesRoleName(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "tasks", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "tasks", "main.yml"), []byte(`--- - name: templated role task debug: msg: role ran @@ -862,16 +860,16 @@ func TestExecutor_RunIncludeRole_Good_TemplatesRoleName(t *testing.T) { Role: "{{ role_name }}", }, }, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Equal(t, []string{"localhost:templated role task"}, started) - require.NotNil(t, e.results["localhost"]["role_result"]) - assert.Equal(t, "role ran", e.results["localhost"]["role_result"].Msg) + core.AssertEqual(t, []string{"localhost:templated role task"}, started) + core.AssertNotNil(t, e.results["localhost"]["role_result"]) + core.AssertEqual(t, "role ran", e.results["localhost"]["role_result"].Msg) } -func TestExecutor_RunIncludeTasks_Good_AppliesTaskDefaultsToChildren(t *testing.T) { +func TestExecutor_RunIncludeTasks_Good_AppliesTaskDefaultsToChildren(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "tasks", "child.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "tasks", "child.yml"), []byte(`--- - name: included shell task shell: echo "{{ included_value }}" register: child_result @@ -901,18 +899,18 @@ func TestExecutor_RunIncludeTasks_Good_AppliesTaskDefaultsToChildren(t *testing. BecomeUser: "root", }, }, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) - require.NotNil(t, e.results["host1"]["child_result"]) - assert.Equal(t, "from-apply\n", e.results["host1"]["child_result"].Stdout) - assert.True(t, mock.hasExecuted(`echo "from-apply"`)) - require.NotEmpty(t, mock.becomeCalls) - assert.Contains(t, mock.becomeCalls, becomeCall{become: true, user: "root", password: ""}) + core.AssertNotNil(t, e.results["host1"]["child_result"]) + core.AssertEqual(t, "from-apply\n", e.results["host1"]["child_result"].Stdout) + core.AssertTrue(t, mock.hasExecuted(`echo "from-apply"`)) + core.RequireNotEmpty(t, mock.becomeCalls) + core.AssertContains(t, mock.becomeCalls, becomeCall{become: true, user: "root", password: ""}) } -func TestExecutor_RunIncludeTasks_Good_ImportTasksReevaluatesWhenPerTask(t *testing.T) { +func TestExecutor_RunIncludeTasks_Good_ImportTasksReevaluatesWhenPerTask(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "tasks", "imported.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "tasks", "imported.yml"), []byte(`--- - name: set gate flag set_fact: gate_flag: true @@ -939,20 +937,20 @@ func TestExecutor_RunIncludeTasks_Good_ImportTasksReevaluatesWhenPerTask(t *test GatherFacts: &gatherFacts, } - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"localhost"}, &Task{ + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"localhost"}, &Task{ Name: "import child tasks", ImportTasks: "tasks/imported.yml", When: "not gate_flag", }, play)) - require.NotNil(t, e.results["localhost"]["first_result"]) - assert.True(t, e.results["localhost"]["first_result"].Changed) - require.NotNil(t, e.results["localhost"]["second_result"]) - assert.True(t, e.results["localhost"]["second_result"].Skipped) - assert.Equal(t, "Skipped due to when condition", e.results["localhost"]["second_result"].Msg) + core.AssertNotNil(t, e.results["localhost"]["first_result"]) + core.AssertTrue(t, e.results["localhost"]["first_result"].Changed) + core.AssertNotNil(t, e.results["localhost"]["second_result"]) + core.AssertTrue(t, e.results["localhost"]["second_result"].Skipped) + core.AssertEqual(t, "Skipped due to when condition", e.results["localhost"]["second_result"].Msg) } -func TestExecutor_RunPlay_Good_AppliesPlayTagsToTasks(t *testing.T) { +func TestExecutor_RunPlay_Good_AppliesPlayTagsToTasks(t *core.T) { e := NewExecutor("/tmp") e.Tags = []string{"deploy"} e.SetInventoryDirect(&Inventory{ @@ -983,14 +981,14 @@ func TestExecutor_RunPlay_Good_AppliesPlayTagsToTasks(t *testing.T) { } err := e.runPlay(context.Background(), play) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Equal(t, []string{"host1:tagged play task"}, started) - require.NotNil(t, e.results["host1"]["play_result"]) - assert.Equal(t, "play ran", e.results["host1"]["play_result"].Msg) + core.AssertEqual(t, []string{"host1:tagged play task"}, started) + core.AssertNotNil(t, e.results["host1"]["play_result"]) + core.AssertEqual(t, "play ran", e.results["host1"]["play_result"].Msg) } -func TestExecutor_RunRole_Good_HostSpecificWhen(t *testing.T) { +func TestExecutor_RunRole_Good_HostSpecificWhen(t *core.T) { dir := t.TempDir() roleTasks := `--- - name: gated role task @@ -998,7 +996,7 @@ func TestExecutor_RunRole_Good_HostSpecificWhen(t *testing.T) { msg: role ran register: gated_result ` - require.NoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "tasks", "main.yml"), []byte(roleTasks), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "tasks", "main.yml"), []byte(roleTasks), 0644)) e := NewExecutor(dir) e.SetInventoryDirect(&Inventory{ @@ -1021,17 +1019,17 @@ func TestExecutor_RunRole_Good_HostSpecificWhen(t *testing.T) { Role: "webserver", When: "enabled", }, &Play{}, nil) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Equal(t, []string{"host1:gated role task"}, started) - require.NotNil(t, e.results["host1"]["gated_result"]) + core.AssertEqual(t, []string{"host1:gated role task"}, started) + core.AssertNotNil(t, e.results["host1"]["gated_result"]) _, ok := e.results["host2"]["gated_result"] - assert.False(t, ok) + core.AssertFalse(t, ok) } -func TestExecutor_RunIncludeRole_Good_ImportRoleReevaluatesWhenPerTask(t *testing.T) { +func TestExecutor_RunIncludeRole_Good_ImportRoleReevaluatesWhenPerTask(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "tasks", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "tasks", "main.yml"), []byte(`--- - name: set role gate set_fact: role_gate: true @@ -1058,7 +1056,7 @@ func TestExecutor_RunIncludeRole_Good_ImportRoleReevaluatesWhenPerTask(t *testin GatherFacts: &gatherFacts, } - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"localhost"}, &Task{ + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"localhost"}, &Task{ Name: "import conditional role", ImportRole: &RoleRef{ Role: "webserver", @@ -1066,23 +1064,23 @@ func TestExecutor_RunIncludeRole_Good_ImportRoleReevaluatesWhenPerTask(t *testin }, }, play)) - require.NotNil(t, e.results["localhost"]["role_first_result"]) - assert.True(t, e.results["localhost"]["role_first_result"].Changed) - require.NotNil(t, e.results["localhost"]["role_second_result"]) - assert.True(t, e.results["localhost"]["role_second_result"].Skipped) - assert.Equal(t, "Skipped due to when condition", e.results["localhost"]["role_second_result"].Msg) + core.AssertNotNil(t, e.results["localhost"]["role_first_result"]) + core.AssertTrue(t, e.results["localhost"]["role_first_result"].Changed) + core.AssertNotNil(t, e.results["localhost"]["role_second_result"]) + core.AssertTrue(t, e.results["localhost"]["role_second_result"].Skipped) + core.AssertEqual(t, "Skipped due to when condition", e.results["localhost"]["role_second_result"].Msg) } -func TestExecutor_RunPlay_Good_LoadsRoleHandlers(t *testing.T) { +func TestExecutor_RunPlay_Good_LoadsRoleHandlers(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "roles", "demo", "tasks", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "demo", "tasks", "main.yml"), []byte(`--- - name: role task set_fact: role_triggered: true notify: role handler `), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "roles", "demo", "handlers", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "demo", "handlers", "main.yml"), []byte(`--- - name: role handler debug: msg: handler ran @@ -1114,24 +1112,24 @@ func TestExecutor_RunPlay_Good_LoadsRoleHandlers(t *testing.T) { } err := e.runPlay(context.Background(), play) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Contains(t, started, "localhost:role task") - assert.Contains(t, started, "localhost:role handler") - require.NotNil(t, e.results["localhost"]["role_handler_result"]) - assert.Equal(t, "handler ran", e.results["localhost"]["role_handler_result"].Msg) + core.AssertContains(t, started, "localhost:role task") + core.AssertContains(t, started, "localhost:role handler") + core.AssertNotNil(t, e.results["localhost"]["role_handler_result"]) + core.AssertEqual(t, "handler ran", e.results["localhost"]["role_handler_result"].Msg) } -func TestExecutor_RunRole_Good_UsesCustomRoleHandlersFile(t *testing.T) { +func TestExecutor_RunRole_Good_UsesCustomRoleHandlersFile(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "roles", "demo", "tasks", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "demo", "tasks", "main.yml"), []byte(`--- - name: role task set_fact: role_triggered: true notify: custom role handler `), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "roles", "demo", "handlers", "custom.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "demo", "handlers", "custom.yml"), []byte(`--- - name: custom role handler debug: msg: custom handler ran @@ -1163,15 +1161,15 @@ func TestExecutor_RunRole_Good_UsesCustomRoleHandlersFile(t *testing.T) { } err := e.runPlay(context.Background(), play) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.Contains(t, started, "localhost:role task") - assert.Contains(t, started, "localhost:custom role handler") - require.NotNil(t, e.results["localhost"]["custom_role_handler_result"]) - assert.Equal(t, "custom handler ran", e.results["localhost"]["custom_role_handler_result"].Msg) + core.AssertContains(t, started, "localhost:role task") + core.AssertContains(t, started, "localhost:custom role handler") + core.AssertNotNil(t, e.results["localhost"]["custom_role_handler_result"]) + core.AssertEqual(t, "custom handler ran", e.results["localhost"]["custom_role_handler_result"].Msg) } -func TestExecutor_RunPlay_Good_SerialBatchesHosts(t *testing.T) { +func TestExecutor_RunPlay_Good_SerialBatchesHosts(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -1199,9 +1197,9 @@ func TestExecutor_RunPlay_Good_SerialBatchesHosts(t *testing.T) { got = append(got, host+":"+task.Name) } - require.NoError(t, e.runPlay(context.Background(), play)) + core.RequireNoError(t, e.runPlay(context.Background(), play)) - assert.Equal(t, []string{ + core.AssertEqual(t, []string{ "host1:first", "host1:second", "host2:first", @@ -1211,7 +1209,7 @@ func TestExecutor_RunPlay_Good_SerialBatchesHosts(t *testing.T) { }, got) } -func TestExecutor_RunPlay_Good_RestoresPlayVarsBetweenPlays(t *testing.T) { +func TestExecutor_RunPlay_Good_RestoresPlayVarsBetweenPlays(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -1253,49 +1251,49 @@ func TestExecutor_RunPlay_Good_RestoresPlayVarsBetweenPlays(t *testing.T) { }, } - require.NoError(t, e.runPlay(context.Background(), first)) + core.RequireNoError(t, e.runPlay(context.Background(), first)) _, leaked := e.vars["play_var"] - assert.False(t, leaked) + core.AssertFalse(t, leaked) - require.NoError(t, e.runPlay(context.Background(), second)) - require.NotNil(t, e.results["localhost"]["first_result"]) - require.NotNil(t, e.results["localhost"]["second_result"]) - assert.Equal(t, "one", e.results["localhost"]["first_result"].Msg) - assert.Equal(t, "missing", e.results["localhost"]["second_result"].Msg) + core.RequireNoError(t, e.runPlay(context.Background(), second)) + core.AssertNotNil(t, e.results["localhost"]["first_result"]) + core.AssertNotNil(t, e.results["localhost"]["second_result"]) + core.AssertEqual(t, "one", e.results["localhost"]["first_result"].Msg) + core.AssertEqual(t, "missing", e.results["localhost"]["second_result"].Msg) } -func TestExecutor_Templating_Good_ExposesInventoryMagicVars(t *testing.T) { +func TestExecutor_Templating_Good_ExposesInventoryMagicVars(t *core.T) { dir := t.TempDir() inventoryPath := joinPath(dir, "inventory.yml") - require.NoError(t, writeTestFile(inventoryPath, []byte(`--- + core.RequireNoError(t, writeTestFile(inventoryPath, []byte(`--- all: hosts: host1: `), 0644)) e := NewExecutor(dir) - require.NoError(t, e.SetInventory(inventoryPath)) + core.RequireNoError(t, e.SetInventory(inventoryPath)) result := e.templateString("{{ inventory_file }}|{{ inventory_dir }}", "host1", nil) - assert.Equal(t, inventoryPath+"|"+dir, result) + core.AssertEqual(t, inventoryPath+"|"+dir, result) } -func TestExecutor_Templating_Good_ExposesModeMagicVars(t *testing.T) { +func TestExecutor_Templating_Good_ExposesModeMagicVars(t *core.T) { e := NewExecutor("/tmp") e.CheckMode = true e.Diff = true result := e.templateString("{{ ansible_check_mode }}|{{ ansible_diff_mode }}", "localhost", nil) - assert.Equal(t, "true|true", result) - assert.True(t, e.evalCondition("ansible_check_mode and ansible_diff_mode", "localhost")) + core.AssertEqual(t, "true|true", result) + core.AssertTrue(t, e.evalCondition("ansible_check_mode and ansible_diff_mode", "localhost")) } -func TestExecutor_RunPlay_Good_ExposesRoleContextVars(t *testing.T) { +func TestExecutor_RunPlay_Good_ExposesRoleContextVars(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "roles", "demo", "tasks", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "demo", "tasks", "main.yml"), []byte(`--- - name: role context debug: msg: "{{ role_name }}|{{ role_path }}" @@ -1322,13 +1320,13 @@ func TestExecutor_RunPlay_Good_ExposesRoleContextVars(t *testing.T) { }, } - require.NoError(t, e.runPlay(context.Background(), play)) + core.RequireNoError(t, e.runPlay(context.Background(), play)) - require.NotNil(t, e.results["localhost"]["role_context_result"]) - assert.Equal(t, "demo|"+joinPath(dir, "roles", "demo"), e.results["localhost"]["role_context_result"].Msg) + core.AssertNotNil(t, e.results["localhost"]["role_context_result"]) + core.AssertEqual(t, "demo|"+joinPath(dir, "roles", "demo"), e.results["localhost"]["role_context_result"].Msg) } -func TestExecutor_RunTaskOnHost_Good_LoopControlPause(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_LoopControlPause(t *core.T) { e := NewExecutor("/tmp") task := &Task{ Name: "Pause between loop items", @@ -1344,11 +1342,11 @@ func TestExecutor_RunTaskOnHost_Good_LoopControlPause(t *testing.T) { err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) elapsed := time.Since(start) - require.NoError(t, err) - assert.GreaterOrEqual(t, elapsed, 900*time.Millisecond) + core.RequireNoError(t, err) + core.AssertGreaterOrEqual(t, elapsed, 900*time.Millisecond) } -func TestExecutor_RunTaskOnHost_Good_LoopWhenEvaluatedPerItem(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_LoopWhenEvaluatedPerItem(t *core.T) { e := NewExecutor("/tmp") e.clients["host1"] = NewMockSSHClient() @@ -1364,18 +1362,18 @@ func TestExecutor_RunTaskOnHost_Good_LoopWhenEvaluatedPerItem(t *testing.T) { } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) result := e.results["host1"]["loop_result"] - require.NotNil(t, result) - require.Len(t, result.Results, 2) - assert.True(t, result.Results[0].Skipped) - assert.Equal(t, "Skipped due to when condition", result.Results[0].Msg) - assert.False(t, result.Results[1].Skipped) - assert.Equal(t, "run", result.Results[1].Msg) + core.AssertNotNil(t, result) + core.AssertLen(t, result.Results, 2) + core.AssertTrue(t, result.Results[0].Skipped) + core.AssertEqual(t, "Skipped due to when condition", result.Results[0].Msg) + core.AssertFalse(t, result.Results[1].Skipped) + core.AssertEqual(t, "run", result.Results[1].Msg) } -func TestExecutor_RunTaskOnHost_Good_LoopControlExtendedExposesMetadata(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_LoopControlExtendedExposesMetadata(t *core.T) { e := NewExecutor("/tmp") e.clients["host1"] = NewMockSSHClient() @@ -1394,16 +1392,16 @@ func TestExecutor_RunTaskOnHost_Good_LoopControlExtendedExposesMetadata(t *testi } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) result := e.results["host1"]["loop_result"] - require.NotNil(t, result) - require.Len(t, result.Results, 2) - assert.Equal(t, "one 0/2 first=true last=false", result.Results[0].Msg) - assert.Equal(t, "two 1/2 first=false last=true", result.Results[1].Msg) + core.AssertNotNil(t, result) + core.AssertLen(t, result.Results, 2) + core.AssertEqual(t, "one 0/2 first=true last=false", result.Results[0].Msg) + core.AssertEqual(t, "two 1/2 first=false last=true", result.Results[1].Msg) } -func TestExecutor_RunTaskOnHost_Good_LoopControlLabelWithoutExtended(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_LoopControlLabelWithoutExtended(t *core.T) { e := NewExecutor("/tmp") e.clients["host1"] = NewMockSSHClient() @@ -1421,16 +1419,16 @@ func TestExecutor_RunTaskOnHost_Good_LoopControlLabelWithoutExtended(t *testing. } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) result := e.results["host1"]["loop_result"] - require.NotNil(t, result) - require.Len(t, result.Results, 2) - assert.Equal(t, "one=one", result.Results[0].Msg) - assert.Equal(t, "two=two", result.Results[1].Msg) + core.AssertNotNil(t, result) + core.AssertLen(t, result.Results, 2) + core.AssertEqual(t, "one=one", result.Results[0].Msg) + core.AssertEqual(t, "two=two", result.Results[1].Msg) } -func TestExecutor_RunTaskOnHost_Good_LoopControlExtendedExposesNeighbourItems(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_LoopControlExtendedExposesNeighbourItems(t *core.T) { e := NewExecutor("/tmp") e.clients["host1"] = NewMockSSHClient() @@ -1448,16 +1446,16 @@ func TestExecutor_RunTaskOnHost_Good_LoopControlExtendedExposesNeighbourItems(t } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) result := e.results["host1"]["loop_result"] - require.NotNil(t, result) - require.Len(t, result.Results, 2) - assert.Equal(t, "prev=NONE next=two all=[one two]", result.Results[0].Msg) - assert.Equal(t, "prev=one next=NONE all=[one two]", result.Results[1].Msg) + core.AssertNotNil(t, result) + core.AssertLen(t, result.Results, 2) + core.AssertEqual(t, "prev=NONE next=two all=[one two]", result.Results[0].Msg) + core.AssertEqual(t, "prev=one next=NONE all=[one two]", result.Results[1].Msg) } -func TestExecutor_RunTaskOnHost_Good_LoopTemplateDefaultExpandsItems(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_LoopTemplateDefaultExpandsItems(t *core.T) { e := NewExecutor("/tmp") e.clients["host1"] = NewMockSSHClient() @@ -1472,16 +1470,16 @@ func TestExecutor_RunTaskOnHost_Good_LoopTemplateDefaultExpandsItems(t *testing. } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) result := e.results["host1"]["loop_result"] - require.NotNil(t, result) - require.Len(t, result.Results, 2) - assert.Equal(t, "alpha", result.Results[0].Msg) - assert.Equal(t, "beta", result.Results[1].Msg) + core.AssertNotNil(t, result) + core.AssertLen(t, result.Results, 2) + core.AssertEqual(t, "alpha", result.Results[0].Msg) + core.AssertEqual(t, "beta", result.Results[1].Msg) } -func TestExecutor_RunTaskOnHost_Good_LoopFromWithDictItems(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_LoopFromWithDictItems(t *core.T) { e := NewExecutor("/tmp") e.clients["host1"] = NewMockSSHClient() @@ -1499,16 +1497,16 @@ func TestExecutor_RunTaskOnHost_Good_LoopFromWithDictItems(t *testing.T) { } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) result := e.results["host1"]["dict_loop_result"] - require.NotNil(t, result) - require.Len(t, result.Results, 2) - assert.Equal(t, "alpha=one", result.Results[0].Msg) - assert.Equal(t, "beta=two", result.Results[1].Msg) + core.AssertNotNil(t, result) + core.AssertLen(t, result.Results, 2) + core.AssertEqual(t, "alpha=one", result.Results[0].Msg) + core.AssertEqual(t, "beta=two", result.Results[1].Msg) } -func TestExecutor_RunTaskOnHost_Good_LoopFromWithIndexedItems(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_LoopFromWithIndexedItems(t *core.T) { e := NewExecutor("/tmp") e.clients["host1"] = NewMockSSHClient() @@ -1526,16 +1524,16 @@ func TestExecutor_RunTaskOnHost_Good_LoopFromWithIndexedItems(t *testing.T) { } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) result := e.results["host1"]["indexed_loop_result"] - require.NotNil(t, result) - require.Len(t, result.Results, 2) - assert.Equal(t, "0=apple", result.Results[0].Msg) - assert.Equal(t, "1=banana", result.Results[1].Msg) + core.AssertNotNil(t, result) + core.AssertLen(t, result.Results, 2) + core.AssertEqual(t, "0=apple", result.Results[0].Msg) + core.AssertEqual(t, "1=banana", result.Results[1].Msg) } -func TestExecutor_RunTaskOnHost_Good_LoopFromWithSequence(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_LoopFromWithSequence(t *core.T) { e := NewExecutor("/tmp") e.clients["host1"] = NewMockSSHClient() @@ -1550,17 +1548,17 @@ func TestExecutor_RunTaskOnHost_Good_LoopFromWithSequence(t *testing.T) { } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) result := e.results["host1"]["sequence_loop_result"] - require.NotNil(t, result) - require.Len(t, result.Results, 3) - assert.Equal(t, "01", result.Results[0].Msg) - assert.Equal(t, "02", result.Results[1].Msg) - assert.Equal(t, "03", result.Results[2].Msg) + core.AssertNotNil(t, result) + core.AssertLen(t, result.Results, 3) + core.AssertEqual(t, "01", result.Results[0].Msg) + core.AssertEqual(t, "02", result.Results[1].Msg) + core.AssertEqual(t, "03", result.Results[2].Msg) } -func TestExecutor_RunTaskOnHost_Good_LoopFromWithNested(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_LoopFromWithNested(t *core.T) { e := NewExecutor("/tmp") e.clients["host1"] = NewMockSSHClient() @@ -1580,18 +1578,18 @@ func TestExecutor_RunTaskOnHost_Good_LoopFromWithNested(t *testing.T) { } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) result := e.results["host1"]["nested_loop_result"] - require.NotNil(t, result) - require.Len(t, result.Results, 4) - assert.Equal(t, "red-small", result.Results[0].Msg) - assert.Equal(t, "red-large", result.Results[1].Msg) - assert.Equal(t, "blue-small", result.Results[2].Msg) - assert.Equal(t, "blue-large", result.Results[3].Msg) + core.AssertNotNil(t, result) + core.AssertLen(t, result.Results, 4) + core.AssertEqual(t, "red-small", result.Results[0].Msg) + core.AssertEqual(t, "red-large", result.Results[1].Msg) + core.AssertEqual(t, "blue-small", result.Results[2].Msg) + core.AssertEqual(t, "blue-large", result.Results[3].Msg) } -func TestExecutor_RunTaskOnHost_Good_TemplatedLoopItems(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_TemplatedLoopItems(t *core.T) { e := NewExecutor("/tmp") e.clients["host1"] = NewMockSSHClient() e.vars["colour"] = "red" @@ -1610,16 +1608,16 @@ func TestExecutor_RunTaskOnHost_Good_TemplatedLoopItems(t *testing.T) { } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) result := e.results["host1"]["templated_loop_result"] - require.NotNil(t, result) - require.Len(t, result.Results, 2) - assert.Equal(t, "red", result.Results[0].Msg) - assert.Equal(t, "[red large]", result.Results[1].Msg) + core.AssertNotNil(t, result) + core.AssertLen(t, result.Results, 2) + core.AssertEqual(t, "red", result.Results[0].Msg) + core.AssertEqual(t, "[red large]", result.Results[1].Msg) } -func TestExecutor_RunTaskOnHost_Good_LoopFromWithTogether(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_LoopFromWithTogether(t *core.T) { e := NewExecutor("/tmp") e.clients["host1"] = NewMockSSHClient() @@ -1637,16 +1635,16 @@ func TestExecutor_RunTaskOnHost_Good_LoopFromWithTogether(t *testing.T) { } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) result := e.results["host1"]["together_loop_result"] - require.NotNil(t, result) - require.Len(t, result.Results, 2) - assert.Equal(t, "red=small", result.Results[0].Msg) - assert.Equal(t, "blue=large", result.Results[1].Msg) + core.AssertNotNil(t, result) + core.AssertLen(t, result.Results, 2) + core.AssertEqual(t, "red=small", result.Results[0].Msg) + core.AssertEqual(t, "blue=large", result.Results[1].Msg) } -func TestExecutor_RunTaskOnHost_Good_LoopFromWithSubelements(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_LoopFromWithSubelements(t *core.T) { e := NewExecutor("/tmp") e.clients["host1"] = NewMockSSHClient() e.vars["users"] = []any{ @@ -1671,17 +1669,17 @@ func TestExecutor_RunTaskOnHost_Good_LoopFromWithSubelements(t *testing.T) { } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) result := e.results["host1"]["subelements_loop_result"] - require.NotNil(t, result) - require.Len(t, result.Results, 3) - assert.Equal(t, "alice=ssh-rsa AAA", result.Results[0].Msg) - assert.Equal(t, "alice=ssh-ed25519 BBB", result.Results[1].Msg) - assert.Equal(t, "bob=ssh-rsa CCC", result.Results[2].Msg) + core.AssertNotNil(t, result) + core.AssertLen(t, result.Results, 3) + core.AssertEqual(t, "alice=ssh-rsa AAA", result.Results[0].Msg) + core.AssertEqual(t, "alice=ssh-ed25519 BBB", result.Results[1].Msg) + core.AssertEqual(t, "bob=ssh-rsa CCC", result.Results[2].Msg) } -func TestExecutor_RunTaskOnHost_Good_LoopFromWithSubelementsSkipMissing(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_LoopFromWithSubelementsSkipMissing(t *core.T) { e := NewExecutor("/tmp") e.clients["host1"] = NewMockSSHClient() e.vars["users"] = []any{ @@ -1705,16 +1703,16 @@ func TestExecutor_RunTaskOnHost_Good_LoopFromWithSubelementsSkipMissing(t *testi } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) result := e.results["host1"]["subelements_loop_skip_missing_result"] - require.NotNil(t, result) - require.Len(t, result.Results, 2) - assert.Equal(t, "alice=ssh-rsa AAA", result.Results[0].Msg) - assert.Equal(t, "alice=ssh-ed25519 BBB", result.Results[1].Msg) + core.AssertNotNil(t, result) + core.AssertLen(t, result.Results, 2) + core.AssertEqual(t, "alice=ssh-rsa AAA", result.Results[0].Msg) + core.AssertEqual(t, "alice=ssh-ed25519 BBB", result.Results[1].Msg) } -func TestExecutor_RunTaskOnHost_Bad_LoopFromWithSubelementsMissingSubelement(t *testing.T) { +func TestExecutor_RunTaskOnHost_Bad_LoopFromWithSubelementsMissingSubelement(t *core.T) { e := NewExecutor("/tmp") e.clients["host1"] = NewMockSSHClient() e.vars["users"] = []any{ @@ -1737,11 +1735,11 @@ func TestExecutor_RunTaskOnHost_Bad_LoopFromWithSubelementsMissingSubelement(t * } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.Error(t, err) - assert.Contains(t, err.Error(), "with_subelements missing subelement") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "with_subelements missing subelement") } -func TestExecutor_RunTaskOnHosts_Good_LoopNotifiesAndCallsCallback(t *testing.T) { +func TestExecutor_RunTaskOnHosts_Good_LoopNotifiesAndCallsCallback(t *core.T) { e := NewExecutor("/tmp") e.clients["host1"] = NewMockSSHClient() @@ -1770,15 +1768,15 @@ func TestExecutor_RunTaskOnHosts_Good_LoopNotifiesAndCallsCallback(t *testing.T) } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, play) - require.NoError(t, err) + core.RequireNoError(t, err) - require.NotNil(t, ended) - assert.True(t, ended.Changed) - assert.Len(t, ended.Results, 2) - assert.True(t, e.notified["restart app"]) + core.AssertNotNil(t, ended) + core.AssertTrue(t, ended.Changed) + core.AssertLen(t, ended.Results, 2) + core.AssertTrue(t, e.notified["restart app"]) } -func TestExecutor_RunTaskOnHosts_Bad_LoopFailurePropagates(t *testing.T) { +func TestExecutor_RunTaskOnHosts_Bad_LoopFailurePropagates(t *core.T) { e := NewExecutor("/tmp") e.clients["host1"] = NewMockSSHClient() @@ -1790,11 +1788,11 @@ func TestExecutor_RunTaskOnHosts_Bad_LoopFailurePropagates(t *testing.T) { } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.Error(t, err) - assert.Contains(t, err.Error(), "task failed") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "task failed") } -func TestExecutor_RunTaskWithRetries_Good_UntilSuccess(t *testing.T) { +func TestExecutor_RunTaskWithRetries_Good_UntilSuccess(t *core.T) { e := NewExecutor("/tmp") attempts := 0 @@ -1812,17 +1810,17 @@ func TestExecutor_RunTaskWithRetries_Good_UntilSuccess(t *testing.T) { return &TaskResult{Changed: true, Msg: "ok", RC: 0}, nil }) - require.NoError(t, err) - require.NotNil(t, result) - assert.Equal(t, 2, attempts) - assert.False(t, result.Failed) - assert.True(t, result.Changed) - assert.Equal(t, "ok", result.Msg) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertEqual(t, 2, attempts) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "ok", result.Msg) } // --- check mode --- -func TestExecutor_RunTaskOnHost_Good_CheckModeSkipsMutatingTask(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_CheckModeSkipsMutatingTask(t *core.T) { e := NewExecutor("/tmp") e.CheckMode = true @@ -1839,17 +1837,17 @@ func TestExecutor_RunTaskOnHost_Good_CheckModeSkipsMutatingTask(t *testing.T) { } err := e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) - require.NotNil(t, ended) - assert.True(t, ended.Skipped) - assert.False(t, ended.Changed) - assert.Equal(t, "Skipped in check mode", ended.Msg) - require.NotNil(t, e.results["host1"]["shell_result"]) - assert.True(t, e.results["host1"]["shell_result"].Skipped) + core.AssertNotNil(t, ended) + core.AssertTrue(t, ended.Skipped) + core.AssertFalse(t, ended.Changed) + core.AssertEqual(t, "Skipped in check mode", ended.Msg) + core.AssertNotNil(t, e.results["host1"]["shell_result"]) + core.AssertTrue(t, e.results["host1"]["shell_result"].Skipped) } -func TestExecutor_RunTaskOnHost_Good_TaskCheckModeOverridesExecutorCheckMode(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_TaskCheckModeOverridesExecutorCheckMode(t *core.T) { e := NewExecutor("/tmp") e.CheckMode = true e.SetInventoryDirect(&Inventory{ @@ -1870,14 +1868,14 @@ func TestExecutor_RunTaskOnHost_Good_TaskCheckModeOverridesExecutorCheckMode(t * } err := e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) - require.NotNil(t, e.results["host1"]["shell_result"]) - assert.False(t, e.results["host1"]["shell_result"].Skipped) - assert.True(t, e.results["host1"]["shell_result"].Changed) + core.AssertNotNil(t, e.results["host1"]["shell_result"]) + core.AssertFalse(t, e.results["host1"]["shell_result"].Skipped) + core.AssertTrue(t, e.results["host1"]["shell_result"].Changed) } -func TestExecutor_RunTaskOnHost_Good_TaskDiffOverridesExecutorDiff(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_TaskDiffOverridesExecutorDiff(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -1897,16 +1895,16 @@ func TestExecutor_RunTaskOnHost_Good_TaskDiffOverridesExecutorDiff(t *testing.T) } err := e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) - require.NotNil(t, e.results["host1"]) - require.NotNil(t, e.results["host1"]["diff_result"]) - assert.Equal(t, "true", e.results["host1"]["diff_result"].Msg) + core.AssertNotNil(t, e.results["host1"]) + core.AssertNotNil(t, e.results["host1"]["diff_result"]) + core.AssertEqual(t, "true", e.results["host1"]["diff_result"].Msg) } // --- no_log --- -func TestExecutor_RunTaskOnHost_Good_NoLogRedactsCallbackResult(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_NoLogRedactsCallbackResult(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -1931,18 +1929,18 @@ func TestExecutor_RunTaskOnHost_Good_NoLogRedactsCallbackResult(t *testing.T) { } err := e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) - require.NotNil(t, ended) - assert.Equal(t, "censored due to no_log", ended.Msg) - assert.Empty(t, ended.Stdout) - assert.Empty(t, ended.Stderr) - assert.Nil(t, ended.Data) - require.NotNil(t, e.results["host1"]["debug_result"]) - assert.Equal(t, "top secret", e.results["host1"]["debug_result"].Msg) + core.AssertNotNil(t, ended) + core.AssertEqual(t, "censored due to no_log", ended.Msg) + core.AssertEmpty(t, ended.Stdout) + core.AssertEmpty(t, ended.Stderr) + core.AssertNil(t, ended.Data) + core.AssertNotNil(t, e.results["host1"]["debug_result"]) + core.AssertEqual(t, "top secret", e.results["host1"]["debug_result"].Msg) } -func TestExecutor_RunTaskOnHost_Bad_NoLogHidesFailureMessage(t *testing.T) { +func TestExecutor_RunTaskOnHost_Bad_NoLogHidesFailureMessage(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -1966,23 +1964,24 @@ func TestExecutor_RunTaskOnHost_Bad_NoLogHidesFailureMessage(t *testing.T) { } err := e.runTaskOnHost(context.Background(), "host1", []string{"host1"}, task, &Play{}) - require.Error(t, err) - assert.Contains(t, err.Error(), "task failed") - assert.NotContains(t, err.Error(), "super secret") - require.NotNil(t, ended) - assert.Equal(t, "censored due to no_log", ended.Msg) + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "task failed") + core.AssertNotContains(t, err.Error(), "super secret") + core.AssertNotNil(t, ended) + core.AssertEqual(t, "censored due to no_log", ended.Msg) } // --- normalizeConditions --- -func TestExecutor_NormalizeConditions_Good_String(t *testing.T) { +func TestExecutor_NormalizeConditions_Good_String(t *core.T) { result := normalizeConditions("my_var is defined") - assert.Equal(t, []string{"my_var is defined"}, result) + core.AssertEqual(t, []string{"my_var is defined"}, result) + core.AssertLen(t, result, 1) } // --- meta flush handlers --- -func TestExecutor_RunTaskOnHosts_Good_MetaFlushesHandlers(t *testing.T) { +func TestExecutor_RunTaskOnHosts_Good_MetaFlushesHandlers(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -2014,21 +2013,21 @@ func TestExecutor_RunTaskOnHosts_Good_MetaFlushesHandlers(t *testing.T) { Args: map[string]any{"restart_required": true}, Notify: "restart app", } - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"host1"}, notifyTask, play)) - assert.True(t, e.notified["restart app"]) + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"host1"}, notifyTask, play)) + core.AssertTrue(t, e.notified["restart app"]) metaTask := &Task{ Name: "flush handlers", Module: "meta", Args: map[string]any{"_raw_params": "flush_handlers"}, } - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"host1"}, metaTask, play)) + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"host1"}, metaTask, play)) - assert.False(t, e.notified["restart app"]) - assert.Equal(t, []string{"change config", "flush handlers", "restart app"}, executed) + core.AssertFalse(t, e.notified["restart app"]) + core.AssertEqual(t, []string{"change config", "flush handlers", "restart app"}, executed) } -func TestExecutor_RunTaskOnHosts_Good_MetaFlushesHandlerListenAlias(t *testing.T) { +func TestExecutor_RunTaskOnHosts_Good_MetaFlushesHandlerListenAlias(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -2061,21 +2060,21 @@ func TestExecutor_RunTaskOnHosts_Good_MetaFlushesHandlerListenAlias(t *testing.T Args: map[string]any{"restart_required": true}, Notify: "reload app", } - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"host1"}, notifyTask, play)) - assert.True(t, e.notified["reload app"]) + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"host1"}, notifyTask, play)) + core.AssertTrue(t, e.notified["reload app"]) metaTask := &Task{ Name: "flush handlers", Module: "meta", Args: map[string]any{"_raw_params": "flush_handlers"}, } - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"host1"}, metaTask, play)) + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"host1"}, metaTask, play)) - assert.False(t, e.notified["reload app"]) - assert.Equal(t, []string{"change config", "flush handlers", "restart app"}, executed) + core.AssertFalse(t, e.notified["reload app"]) + core.AssertEqual(t, []string{"change config", "flush handlers", "restart app"}, executed) } -func TestExecutor_RunPlay_Good_ForceHandlersAfterFailure(t *testing.T) { +func TestExecutor_RunPlay_Good_ForceHandlersAfterFailure(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -2118,15 +2117,15 @@ func TestExecutor_RunPlay_Good_ForceHandlersAfterFailure(t *testing.T) { } err := e.runPlay(context.Background(), play) - require.Error(t, err) - assert.Contains(t, err.Error(), "task failed") - assert.False(t, e.notified["restart app"]) - assert.Equal(t, []string{"change config", "boom", "restart app"}, executed) - require.NotNil(t, e.results["host1"]["restart_result"]) - assert.Equal(t, "handler ran", e.results["host1"]["restart_result"].Msg) + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "task failed") + core.AssertFalse(t, e.notified["restart app"]) + core.AssertEqual(t, []string{"change config", "boom", "restart app"}, executed) + core.AssertNotNil(t, e.results["host1"]["restart_result"]) + core.AssertEqual(t, "handler ran", e.results["host1"]["restart_result"].Msg) } -func TestExecutor_HandleMetaAction_Good_ClearHostErrors(t *testing.T) { +func TestExecutor_HandleMetaAction_Good_ClearHostErrors(t *core.T) { e := NewExecutor("/tmp") e.batchFailedHosts = map[string]bool{ "host1": true, @@ -2137,38 +2136,38 @@ func TestExecutor_HandleMetaAction_Good_ClearHostErrors(t *testing.T) { Data: map[string]any{"action": "clear_host_errors"}, } - require.NoError(t, e.handleMetaAction(context.Background(), "host1", []string{"host1", "host2"}, &Play{}, result)) - assert.Empty(t, e.batchFailedHosts) + core.RequireNoError(t, e.handleMetaAction(context.Background(), "host1", []string{"host1", "host2"}, &Play{}, result)) + core.AssertEmpty(t, e.batchFailedHosts) } -func TestExecutor_HandleMetaAction_Good_RefreshInventory(t *testing.T) { +func TestExecutor_HandleMetaAction_Good_RefreshInventory(t *core.T) { dir := t.TempDir() path := filepath.Join(dir, "inventory.yml") initial := []byte("all:\n hosts:\n web1:\n ansible_host: 10.0.0.1\n") updated := []byte("all:\n hosts:\n web1:\n ansible_host: 10.0.0.2\n") - require.NoError(t, os.WriteFile(path, initial, 0644)) + core.RequireNoError(t, os.WriteFile(path, initial, 0644)) e := NewExecutor("/tmp") - require.NoError(t, e.SetInventory(path)) + core.RequireNoError(t, e.SetInventory(path)) e.clients["web1"] = &SSHClient{} - require.NoError(t, os.WriteFile(path, updated, 0644)) + core.RequireNoError(t, os.WriteFile(path, updated, 0644)) result := &TaskResult{ Data: map[string]any{"action": "refresh_inventory"}, } - require.NoError(t, e.handleMetaAction(context.Background(), "web1", []string{"web1"}, &Play{}, result)) - require.NotNil(t, e.inventory) - require.NotNil(t, e.inventory.All) - require.Contains(t, e.inventory.All.Hosts, "web1") - assert.Equal(t, "10.0.0.2", e.inventory.All.Hosts["web1"].AnsibleHost) - assert.Empty(t, e.clients) + core.RequireNoError(t, e.handleMetaAction(context.Background(), "web1", []string{"web1"}, &Play{}, result)) + core.AssertNotNil(t, e.inventory) + core.AssertNotNil(t, e.inventory.All) + core.AssertContains(t, e.inventory.All.Hosts, "web1") + core.AssertEqual(t, "10.0.0.2", e.inventory.All.Hosts["web1"].AnsibleHost) + core.AssertEmpty(t, e.clients) } -func TestExecutor_RunPlay_Good_MetaEndPlayStopsRemainingTasks(t *testing.T) { +func TestExecutor_RunPlay_Good_MetaEndPlayStopsRemainingTasks(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -2195,11 +2194,11 @@ func TestExecutor_RunPlay_Good_MetaEndPlayStopsRemainingTasks(t *testing.T) { executed = append(executed, task.Name) } - require.NoError(t, e.runPlay(context.Background(), play)) - assert.Equal(t, []string{"before", "stop"}, executed) + core.RequireNoError(t, e.runPlay(context.Background(), play)) + core.AssertEqual(t, []string{"before", "stop"}, executed) } -func TestExecutor_RunPlay_Bad_MaxFailPercentageStopsPlay(t *testing.T) { +func TestExecutor_RunPlay_Bad_MaxFailPercentageStopsPlay(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -2239,12 +2238,12 @@ func TestExecutor_RunPlay_Bad_MaxFailPercentageStopsPlay(t *testing.T) { } err := e.runPlay(context.Background(), play) - require.Error(t, err) - assert.Contains(t, err.Error(), "max fail percentage exceeded") - assert.Equal(t, []string{"host1:fail one host"}, executed) + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "max fail percentage exceeded") + core.AssertEqual(t, []string{"host1:fail one host"}, executed) } -func TestExecutor_RunPlay_Good_TaskFailureContinuesAcrossHosts(t *testing.T) { +func TestExecutor_RunPlay_Good_TaskFailureContinuesAcrossHosts(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -2281,8 +2280,8 @@ func TestExecutor_RunPlay_Good_TaskFailureContinuesAcrossHosts(t *testing.T) { executed = append(executed, host+":"+task.Name) } - require.NoError(t, e.runPlay(context.Background(), play)) - assert.Equal(t, []string{ + core.RequireNoError(t, e.runPlay(context.Background(), play)) + core.AssertEqual(t, []string{ "host1:maybe fail", "host2:maybe fail", "host1:after failure", @@ -2290,7 +2289,7 @@ func TestExecutor_RunPlay_Good_TaskFailureContinuesAcrossHosts(t *testing.T) { }, executed) } -func TestExecutor_RunPlay_Bad_AnyErrorsFatalStopsPlay(t *testing.T) { +func TestExecutor_RunPlay_Bad_AnyErrorsFatalStopsPlay(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -2329,59 +2328,62 @@ func TestExecutor_RunPlay_Bad_AnyErrorsFatalStopsPlay(t *testing.T) { } err := e.runPlay(context.Background(), play) - require.Error(t, err) - assert.Contains(t, err.Error(), "task failed") - assert.Equal(t, []string{"host1:maybe fail"}, executed) + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "task failed") + core.AssertEqual(t, []string{"host1:maybe fail"}, executed) } -func TestExecutor_NormalizeConditions_Good_StringSlice(t *testing.T) { +func TestExecutor_NormalizeConditions_Good_StringSlice(t *core.T) { result := normalizeConditions([]string{"cond1", "cond2"}) - assert.Equal(t, []string{"cond1", "cond2"}, result) + core.AssertEqual(t, []string{"cond1", "cond2"}, result) + core.AssertLen(t, result, 2) } -func TestExecutor_NormalizeConditions_Good_AnySlice(t *testing.T) { +func TestExecutor_NormalizeConditions_Good_AnySlice(t *core.T) { result := normalizeConditions([]any{"cond1", "cond2"}) - assert.Equal(t, []string{"cond1", "cond2"}, result) + core.AssertEqual(t, []string{"cond1", "cond2"}, result) + core.AssertLen(t, result, 2) } -func TestExecutor_NormalizeConditions_Good_Nil(t *testing.T) { +func TestExecutor_NormalizeConditions_Good_Nil(t *core.T) { result := normalizeConditions(nil) - assert.Nil(t, result) + core.AssertNil(t, result) + core.AssertEmpty(t, result) } // --- evaluateWhen --- -func TestExecutor_EvaluateWhen_Good_TrueLiteral(t *testing.T) { +func TestExecutor_EvaluateWhen_Good_TrueLiteral(t *core.T) { e := NewExecutor("/tmp") - assert.True(t, e.evaluateWhen("true", "host1", nil)) - assert.True(t, e.evaluateWhen("True", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("true", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("True", "host1", nil)) } -func TestExecutor_EvaluateWhen_Good_FalseLiteral(t *testing.T) { +func TestExecutor_EvaluateWhen_Good_FalseLiteral(t *core.T) { e := NewExecutor("/tmp") - assert.False(t, e.evaluateWhen("false", "host1", nil)) - assert.False(t, e.evaluateWhen("False", "host1", nil)) + core.AssertFalse(t, e.evaluateWhen("false", "host1", nil)) + core.AssertFalse(t, e.evaluateWhen("False", "host1", nil)) } -func TestExecutor_EvaluateWhen_Good_Negation(t *testing.T) { +func TestExecutor_EvaluateWhen_Good_Negation(t *core.T) { e := NewExecutor("/tmp") - assert.False(t, e.evaluateWhen("not true", "host1", nil)) - assert.True(t, e.evaluateWhen("not false", "host1", nil)) + core.AssertFalse(t, e.evaluateWhen("not true", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("not false", "host1", nil)) } -func TestExecutor_EvaluateWhen_Good_RegisteredVarDefined(t *testing.T) { +func TestExecutor_EvaluateWhen_Good_RegisteredVarDefined(t *core.T) { e := NewExecutor("/tmp") e.results["host1"] = map[string]*TaskResult{ "myresult": {Changed: true, Failed: false}, } - assert.True(t, e.evaluateWhen("myresult is defined", "host1", nil)) - assert.False(t, e.evaluateWhen("myresult is not defined", "host1", nil)) - assert.False(t, e.evaluateWhen("nonexistent is defined", "host1", nil)) - assert.True(t, e.evaluateWhen("nonexistent is not defined", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("myresult is defined", "host1", nil)) + core.AssertFalse(t, e.evaluateWhen("myresult is not defined", "host1", nil)) + core.AssertFalse(t, e.evaluateWhen("nonexistent is defined", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("nonexistent is not defined", "host1", nil)) } -func TestExecutor_EvaluateWhen_Good_RegisteredVarStatus(t *testing.T) { +func TestExecutor_EvaluateWhen_Good_RegisteredVarStatus(t *core.T) { e := NewExecutor("/tmp") e.results["host1"] = map[string]*TaskResult{ "success_result": {Changed: true, Failed: false}, @@ -2389,14 +2391,14 @@ func TestExecutor_EvaluateWhen_Good_RegisteredVarStatus(t *testing.T) { "skipped_result": {Skipped: true}, } - assert.True(t, e.evaluateWhen("success_result is success", "host1", nil)) - assert.True(t, e.evaluateWhen("success_result is succeeded", "host1", nil)) - assert.True(t, e.evaluateWhen("success_result is changed", "host1", nil)) - assert.True(t, e.evaluateWhen("failed_result is failed", "host1", nil)) - assert.True(t, e.evaluateWhen("skipped_result is skipped", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("success_result is success", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("success_result is succeeded", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("success_result is changed", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("failed_result is failed", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("skipped_result is skipped", "host1", nil)) } -func TestExecutor_EvaluateWhen_Good_VarTruthy(t *testing.T) { +func TestExecutor_EvaluateWhen_Good_VarTruthy(t *core.T) { e := NewExecutor("/tmp") e.vars["enabled"] = true e.vars["disabled"] = false @@ -2405,45 +2407,45 @@ func TestExecutor_EvaluateWhen_Good_VarTruthy(t *testing.T) { e.vars["count"] = 5 e.vars["zero"] = 0 - assert.True(t, e.evalCondition("enabled", "host1")) - assert.False(t, e.evalCondition("disabled", "host1")) - assert.True(t, e.evalCondition("name", "host1")) - assert.False(t, e.evalCondition("empty", "host1")) - assert.True(t, e.evalCondition("count", "host1")) - assert.False(t, e.evalCondition("zero", "host1")) + core.AssertTrue(t, e.evalCondition("enabled", "host1")) + core.AssertFalse(t, e.evalCondition("disabled", "host1")) + core.AssertTrue(t, e.evalCondition("name", "host1")) + core.AssertFalse(t, e.evalCondition("empty", "host1")) + core.AssertTrue(t, e.evalCondition("count", "host1")) + core.AssertFalse(t, e.evalCondition("zero", "host1")) } -func TestExecutor_EvaluateWhen_Good_MultipleConditions(t *testing.T) { +func TestExecutor_EvaluateWhen_Good_MultipleConditions(t *core.T) { e := NewExecutor("/tmp") e.vars["enabled"] = true // All conditions must be true (AND) - assert.True(t, e.evaluateWhen([]any{"true", "True"}, "host1", nil)) - assert.False(t, e.evaluateWhen([]any{"true", "false"}, "host1", nil)) + core.AssertTrue(t, e.evaluateWhen([]any{"true", "True"}, "host1", nil)) + core.AssertFalse(t, e.evaluateWhen([]any{"true", "false"}, "host1", nil)) } -func TestExecutor_EvaluateWhen_Good_LogicalAndOrExpressions(t *testing.T) { +func TestExecutor_EvaluateWhen_Good_LogicalAndOrExpressions(t *core.T) { e := NewExecutor("/tmp") e.vars["enabled"] = true e.vars["maintenance"] = false - assert.True(t, e.evaluateWhen("enabled and not maintenance", "host1", nil)) - assert.False(t, e.evaluateWhen("enabled and maintenance", "host1", nil)) - assert.True(t, e.evaluateWhen("enabled or maintenance", "host1", nil)) - assert.False(t, e.evaluateWhen("maintenance or false", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("enabled and not maintenance", "host1", nil)) + core.AssertFalse(t, e.evaluateWhen("enabled and maintenance", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("enabled or maintenance", "host1", nil)) + core.AssertFalse(t, e.evaluateWhen("maintenance or false", "host1", nil)) } -func TestExecutor_EvaluateWhen_Good_LogicalExpressionParentheses(t *testing.T) { +func TestExecutor_EvaluateWhen_Good_LogicalExpressionParentheses(t *core.T) { e := NewExecutor("/tmp") e.vars["enabled"] = true e.vars["maintenance"] = false e.vars["deployed"] = true - assert.True(t, e.evaluateWhen("(enabled and not maintenance) or deployed", "host1", nil)) - assert.False(t, e.evaluateWhen("enabled and (maintenance or false)", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("(enabled and not maintenance) or deployed", "host1", nil)) + core.AssertFalse(t, e.evaluateWhen("enabled and (maintenance or false)", "host1", nil)) } -func TestExecutor_EvaluateWhen_Good_NestedVarAccess(t *testing.T) { +func TestExecutor_EvaluateWhen_Good_NestedVarAccess(t *core.T) { e := NewExecutor("/tmp") e.vars["feature"] = map[string]any{ "enabled": true, @@ -2458,12 +2460,12 @@ func TestExecutor_EvaluateWhen_Good_NestedVarAccess(t *testing.T) { }, } - assert.True(t, e.evaluateWhen("feature.enabled", "host1", nil)) - assert.True(t, e.evaluateWhen(`feature.mode == "active"`, "host1", nil)) - assert.False(t, e.evaluateWhen("settings.ready", "host1", task)) + core.AssertTrue(t, e.evaluateWhen("feature.enabled", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen(`feature.mode == "active"`, "host1", nil)) + core.AssertFalse(t, e.evaluateWhen("settings.ready", "host1", task)) } -func TestExecutor_ApplyTaskResultConditions_Good_ChangedWhen(t *testing.T) { +func TestExecutor_ApplyTaskResultConditions_Good_ChangedWhen(t *core.T) { e := NewExecutor("/tmp") task := &Task{ ChangedWhen: "stdout == 'expected'", @@ -2475,10 +2477,10 @@ func TestExecutor_ApplyTaskResultConditions_Good_ChangedWhen(t *testing.T) { e.applyTaskResultConditions("host1", task, result) - assert.False(t, result.Changed) + core.AssertFalse(t, result.Changed) } -func TestExecutor_ApplyTaskResultConditions_Good_FailedWhen(t *testing.T) { +func TestExecutor_ApplyTaskResultConditions_Good_FailedWhen(t *core.T) { e := NewExecutor("/tmp") task := &Task{ FailedWhen: []any{"rc != 0", "stdout == 'expected'"}, @@ -2491,10 +2493,10 @@ func TestExecutor_ApplyTaskResultConditions_Good_FailedWhen(t *testing.T) { e.applyTaskResultConditions("host1", task, result) - assert.False(t, result.Failed) + core.AssertFalse(t, result.Failed) } -func TestExecutor_ApplyTaskResultConditions_Good_DottedResultAccess(t *testing.T) { +func TestExecutor_ApplyTaskResultConditions_Good_DottedResultAccess(t *core.T) { e := NewExecutor("/tmp") task := &Task{ ChangedWhen: "result.rc == 0", @@ -2506,49 +2508,49 @@ func TestExecutor_ApplyTaskResultConditions_Good_DottedResultAccess(t *testing.T e.applyTaskResultConditions("host1", task, result) - assert.True(t, result.Changed) + core.AssertTrue(t, result.Changed) } // --- templateString --- -func TestExecutor_TemplateString_Good_SimpleVar(t *testing.T) { +func TestExecutor_TemplateString_Good_SimpleVar(t *core.T) { e := NewExecutor("/tmp") e.vars["name"] = "world" result := e.templateString("hello {{ name }}", "", nil) - assert.Equal(t, "hello world", result) + core.AssertEqual(t, "hello world", result) } -func TestExecutor_TemplateString_Good_MultVars(t *testing.T) { +func TestExecutor_TemplateString_Good_MultVars(t *core.T) { e := NewExecutor("/tmp") e.vars["host"] = "example.com" e.vars["port"] = 8080 result := e.templateString("http://{{ host }}:{{ port }}", "", nil) - assert.Equal(t, "http://example.com:8080", result) + core.AssertEqual(t, "http://example.com:8080", result) } -func TestExecutor_TemplateString_Good_Unresolved(t *testing.T) { +func TestExecutor_TemplateString_Good_Unresolved(t *core.T) { e := NewExecutor("/tmp") result := e.templateString("{{ undefined_var }}", "", nil) - assert.Equal(t, "{{ undefined_var }}", result) + core.AssertEqual(t, "{{ undefined_var }}", result) } -func TestExecutor_TemplateString_Good_NoTemplate(t *testing.T) { +func TestExecutor_TemplateString_Good_NoTemplate(t *core.T) { e := NewExecutor("/tmp") result := e.templateString("plain string", "", nil) - assert.Equal(t, "plain string", result) + core.AssertEqual(t, "plain string", result) } -func TestExecutor_TemplateString_Good_InventoryHostnameShort(t *testing.T) { +func TestExecutor_TemplateString_Good_InventoryHostnameShort(t *core.T) { e := NewExecutor("/tmp") result := e.templateString("{{ inventory_hostname_short }}", "web01.example.com", nil) - assert.Equal(t, "web01", result) + core.AssertEqual(t, "web01", result) } -func TestExecutor_TemplateString_Good_GroupNames(t *testing.T) { +func TestExecutor_TemplateString_Good_GroupNames(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -2573,10 +2575,10 @@ func TestExecutor_TemplateString_Good_GroupNames(t *testing.T) { result := e.templateString("{{ group_names }}", "web01.example.com", nil) - assert.Equal(t, "[frontend production web]", result) + core.AssertEqual(t, "[frontend production web]", result) } -func TestExecutor_TemplateString_Good_Groups(t *testing.T) { +func TestExecutor_TemplateString_Good_Groups(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -2602,10 +2604,10 @@ func TestExecutor_TemplateString_Good_Groups(t *testing.T) { result := e.templateString("{{ groups.production }}", "web01", nil) - assert.Equal(t, "[web01 web02]", result) + core.AssertEqual(t, "[web01 web02]", result) } -func TestExecutor_TemplateString_Good_HostVars(t *testing.T) { +func TestExecutor_TemplateString_Good_HostVars(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -2623,16 +2625,17 @@ func TestExecutor_TemplateString_Good_HostVars(t *testing.T) { result := e.templateString("{{ hostvars.web01.ansible_host }}", "web01", nil) - assert.Equal(t, "10.0.0.10", result) + core.AssertEqual(t, "10.0.0.10", result) } -func TestExecutor_EvalCondition_Good_InventoryHostnameShort(t *testing.T) { +func TestExecutor_EvalCondition_Good_InventoryHostnameShort(t *core.T) { e := NewExecutor("/tmp") + result := e.evalCondition("inventory_hostname_short == 'web01'", "web01.example.com") - assert.True(t, e.evalCondition("inventory_hostname_short == 'web01'", "web01.example.com")) + core.AssertTrue(t, result) } -func TestExecutor_EvalCondition_Good_HostVars(t *testing.T) { +func TestExecutor_EvalCondition_Good_HostVars(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -2646,71 +2649,72 @@ func TestExecutor_EvalCondition_Good_HostVars(t *testing.T) { }, }) - assert.True(t, e.evalCondition("hostvars.web01.deploy_enabled", "web01")) + core.AssertTrue(t, e.evalCondition("hostvars.web01.deploy_enabled", "web01")) } // --- applyFilter --- -func TestExecutor_ApplyFilter_Good_Default(t *testing.T) { +func TestExecutor_ApplyFilter_Good_Default(t *core.T) { e := NewExecutor("/tmp") - assert.Equal(t, "hello", e.applyFilter("hello", "default('fallback')")) - assert.Equal(t, "fallback", e.applyFilter("", "default('fallback')")) + core.AssertEqual(t, "hello", e.applyFilter("hello", "default('fallback')")) + core.AssertEqual(t, "fallback", e.applyFilter("", "default('fallback')")) } -func TestExecutor_ApplyFilter_Good_Bool(t *testing.T) { +func TestExecutor_ApplyFilter_Good_Bool(t *core.T) { e := NewExecutor("/tmp") - assert.Equal(t, "true", e.applyFilter("true", "bool")) - assert.Equal(t, "true", e.applyFilter("yes", "bool")) - assert.Equal(t, "true", e.applyFilter("1", "bool")) - assert.Equal(t, "false", e.applyFilter("false", "bool")) - assert.Equal(t, "false", e.applyFilter("no", "bool")) - assert.Equal(t, "false", e.applyFilter("anything", "bool")) + core.AssertEqual(t, "true", e.applyFilter("true", "bool")) + core.AssertEqual(t, "true", e.applyFilter("yes", "bool")) + core.AssertEqual(t, "true", e.applyFilter("1", "bool")) + core.AssertEqual(t, "false", e.applyFilter("false", "bool")) + core.AssertEqual(t, "false", e.applyFilter("no", "bool")) + core.AssertEqual(t, "false", e.applyFilter("anything", "bool")) } -func TestExecutor_ApplyFilter_Good_Trim(t *testing.T) { +func TestExecutor_ApplyFilter_Good_Trim(t *core.T) { e := NewExecutor("/tmp") - assert.Equal(t, "hello", e.applyFilter(" hello ", "trim")) + result := e.applyFilter(" hello ", "trim") + core.AssertEqual(t, "hello", result) } -func TestExecutor_ApplyFilter_Good_RegexReplace(t *testing.T) { +func TestExecutor_ApplyFilter_Good_RegexReplace(t *core.T) { e := NewExecutor("/tmp") - assert.Equal(t, "web-01", e.applyFilter("web_01", "regex_replace('_', '-')")) - assert.Equal(t, "123", e.applyFilter("abc123", `regex_replace("\D+", "")`)) + core.AssertEqual(t, "web-01", e.applyFilter("web_01", "regex_replace('_', '-')")) + core.AssertEqual(t, "123", e.applyFilter("abc123", `regex_replace("\D+", "")`)) } -func TestExecutor_TemplateString_Good_ChainedFilters(t *testing.T) { +func TestExecutor_TemplateString_Good_ChainedFilters(t *core.T) { e := NewExecutor("/tmp") e.vars["padded"] = " web01 " result := e.templateString("{{ missing_var | default('fallback') | trim }} {{ padded | trim }}", "", nil) - assert.Equal(t, "fallback web01", result) + core.AssertEqual(t, "fallback web01", result) } // --- resolveLoop --- -func TestExecutor_ResolveLoop_Good_SliceAny(t *testing.T) { +func TestExecutor_ResolveLoop_Good_SliceAny(t *core.T) { e := NewExecutor("/tmp") items := e.resolveLoop([]any{"a", "b", "c"}, "host1") - assert.Len(t, items, 3) + core.AssertLen(t, items, 3) } -func TestExecutor_ResolveLoop_Good_SliceString(t *testing.T) { +func TestExecutor_ResolveLoop_Good_SliceString(t *core.T) { e := NewExecutor("/tmp") items := e.resolveLoop([]string{"a", "b", "c"}, "host1") - assert.Len(t, items, 3) + core.AssertLen(t, items, 3) } -func TestExecutor_ResolveLoop_Good_Nil(t *testing.T) { +func TestExecutor_ResolveLoop_Good_Nil(t *core.T) { e := NewExecutor("/tmp") items := e.resolveLoop(nil, "host1") - assert.Nil(t, items) + core.AssertNil(t, items) } -func TestExecutor_RunTaskOnHost_Good_LoopFromTemplatedListVariable(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_LoopFromTemplatedListVariable(t *core.T) { e := NewExecutor("/tmp") e.vars["items"] = []any{"alpha", "beta"} e.clients["host1"] = NewMockSSHClient() @@ -2726,18 +2730,18 @@ func TestExecutor_RunTaskOnHost_Good_LoopFromTemplatedListVariable(t *testing.T) } err := e.runTaskOnHosts(context.Background(), []string{"host1"}, task, &Play{}) - require.NoError(t, err) + core.RequireNoError(t, err) result := e.results["host1"]["loop_result"] - require.NotNil(t, result) - require.Len(t, result.Results, 2) - assert.Equal(t, "alpha", result.Results[0].Msg) - assert.Equal(t, "beta", result.Results[1].Msg) + core.AssertNotNil(t, result) + core.AssertLen(t, result.Results, 2) + core.AssertEqual(t, "alpha", result.Results[0].Msg) + core.AssertEqual(t, "beta", result.Results[1].Msg) } // --- templateArgs --- -func TestExecutor_TemplateArgs_Good(t *testing.T) { +func TestExecutor_TemplateArgs_Good(t *core.T) { e := NewExecutor("/tmp") e.vars["myvar"] = "resolved" @@ -2748,12 +2752,12 @@ func TestExecutor_TemplateArgs_Good(t *testing.T) { } result := e.templateArgs(args, "host1", nil) - assert.Equal(t, "no template", result["plain"]) - assert.Equal(t, "resolved", result["templated"]) - assert.Equal(t, 42, result["number"]) + core.AssertEqual(t, "no template", result["plain"]) + core.AssertEqual(t, "resolved", result["templated"]) + core.AssertEqual(t, 42, result["number"]) } -func TestExecutor_TemplateArgs_Good_NestedMap(t *testing.T) { +func TestExecutor_TemplateArgs_Good_NestedMap(t *core.T) { e := NewExecutor("/tmp") e.vars["port"] = "8080" @@ -2765,10 +2769,10 @@ func TestExecutor_TemplateArgs_Good_NestedMap(t *testing.T) { result := e.templateArgs(args, "host1", nil) nested := result["nested"].(map[string]any) - assert.Equal(t, "8080", nested["port"]) + core.AssertEqual(t, "8080", nested["port"]) } -func TestExecutor_TemplateArgs_Good_ArrayValues(t *testing.T) { +func TestExecutor_TemplateArgs_Good_ArrayValues(t *core.T) { e := NewExecutor("/tmp") e.vars["pkg"] = "nginx" @@ -2778,24 +2782,24 @@ func TestExecutor_TemplateArgs_Good_ArrayValues(t *testing.T) { result := e.templateArgs(args, "host1", nil) pkgs := result["packages"].([]any) - assert.Equal(t, "nginx", pkgs[0]) - assert.Equal(t, "curl", pkgs[1]) + core.AssertEqual(t, "nginx", pkgs[0]) + core.AssertEqual(t, "curl", pkgs[1]) } // --- Helper functions --- -func TestExecutor_GetStringArg_Good(t *testing.T) { +func TestExecutor_GetStringArg_Good(t *core.T) { args := map[string]any{ "name": "value", "number": 42, } - assert.Equal(t, "value", getStringArg(args, "name", "")) - assert.Equal(t, "42", getStringArg(args, "number", "")) - assert.Equal(t, "default", getStringArg(args, "missing", "default")) + core.AssertEqual(t, "value", getStringArg(args, "name", "")) + core.AssertEqual(t, "42", getStringArg(args, "number", "")) + core.AssertEqual(t, "default", getStringArg(args, "missing", "default")) } -func TestExecutor_GetBoolArg_Good(t *testing.T) { +func TestExecutor_GetBoolArg_Good(t *core.T) { args := map[string]any{ "enabled": true, "disabled": false, @@ -2805,21 +2809,21 @@ func TestExecutor_GetBoolArg_Good(t *testing.T) { "no_str": "no", } - assert.True(t, getBoolArg(args, "enabled", false)) - assert.False(t, getBoolArg(args, "disabled", true)) - assert.True(t, getBoolArg(args, "yes_str", false)) - assert.True(t, getBoolArg(args, "true_str", false)) - assert.True(t, getBoolArg(args, "one_str", false)) - assert.False(t, getBoolArg(args, "no_str", true)) - assert.True(t, getBoolArg(args, "missing", true)) - assert.False(t, getBoolArg(args, "missing", false)) + core.AssertTrue(t, getBoolArg(args, "enabled", false)) + core.AssertFalse(t, getBoolArg(args, "disabled", true)) + core.AssertTrue(t, getBoolArg(args, "yes_str", false)) + core.AssertTrue(t, getBoolArg(args, "true_str", false)) + core.AssertTrue(t, getBoolArg(args, "one_str", false)) + core.AssertFalse(t, getBoolArg(args, "no_str", true)) + core.AssertTrue(t, getBoolArg(args, "missing", true)) + core.AssertFalse(t, getBoolArg(args, "missing", false)) } // --- Close --- -func TestExecutor_Close_Good_EmptyClients(t *testing.T) { +func TestExecutor_Close_Good_EmptyClients(t *core.T) { e := NewExecutor("/tmp") // Should not panic with no clients e.Close() - assert.Empty(t, e.clients) + core.AssertEmpty(t, e.clients) } diff --git a/go.mod b/go.mod index e4fa872..3cc60a3 100644 --- a/go.mod +++ b/go.mod @@ -3,17 +3,15 @@ module dappco.re/go/ansible go 1.26.0 require ( - dappco.re/go/core v0.8.0-alpha.1 + dappco.re/go v0.9.0 dappco.re/go/io v0.8.0-alpha.1 dappco.re/go/log v0.8.0-alpha.1 - github.com/stretchr/testify v1.11.1 golang.org/x/crypto v0.50.0 gopkg.in/yaml.v3 v3.0.1 ) require ( - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + dappco.re/go/core v0.8.0-alpha.1 // indirect golang.org/x/sys v0.43.0 // indirect ) diff --git a/go.sum b/go.sum index 4961f40..038848c 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +dappco.re/go v0.9.0 h1:4ruZRNqKDDva8o6g65tYggjGVe42E6/lMZfVKXtr3p0= +dappco.re/go v0.9.0/go.mod h1:xapr7fLK4/9Pu2iSCr4qZuIuatmtx1j56zS/oPDbGyQ= dappco.re/go/core v0.8.0-alpha.1 h1:gj7+Scv+L63Z7wMxbJYHhaRFkHJo2u4MMPuUSv/Dhtk= dappco.re/go/core v0.8.0-alpha.1/go.mod h1:f2/tBZ3+3IqDrg2F5F598llv0nmb/4gJVCFzM5geE4A= github.com/dAppCore/go-io v0.8.0-alpha.1 h1:DWmaksBY7FpwoQnRHYDN/yPCGLMR794D8OcNdk0RyB8= diff --git a/local_client_test.go b/local_client_test.go index 7b45cdc..49df37a 100644 --- a/local_client_test.go +++ b/local_client_test.go @@ -2,51 +2,48 @@ package ansible import ( "context" + core "dappco.re/go" "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) -func TestLocalClient_Good_RunAndRunScript(t *testing.T) { +func TestLocalClient_Good_RunAndRunScript(t *core.T) { client := newLocalClient() stdout, stderr, rc, err := client.Run(context.Background(), "printf 'hello\\n'") - require.NoError(t, err) - assert.Equal(t, "hello\n", stdout) - assert.Equal(t, "", stderr) - assert.Equal(t, 0, rc) + core.RequireNoError(t, err) + core.AssertEqual(t, "hello\n", stdout) + core.AssertEqual(t, "", stderr) + core.AssertEqual(t, 0, rc) stdout, stderr, rc, err = client.RunScript(context.Background(), "printf 'script\\n'") - require.NoError(t, err) - assert.Equal(t, "script\n", stdout) - assert.Equal(t, "", stderr) - assert.Equal(t, 0, rc) + core.RequireNoError(t, err) + core.AssertEqual(t, "script\n", stdout) + core.AssertEqual(t, "", stderr) + core.AssertEqual(t, 0, rc) } -func TestLocalClient_Good_FileOperations(t *testing.T) { +func TestLocalClient_Good_FileOperations(t *core.T) { client := newLocalClient() dir := t.TempDir() path := filepath.Join(dir, "nested", "file.txt") - require.NoError(t, client.Upload(context.Background(), newReader("content"), path, 0o644)) + core.RequireNoError(t, client.Upload(context.Background(), newReader("content"), path, 0o644)) exists, err := client.FileExists(context.Background(), path) - require.NoError(t, err) - assert.True(t, exists) + core.RequireNoError(t, err) + core.AssertTrue(t, exists) info, err := client.Stat(context.Background(), path) - require.NoError(t, err) - assert.Equal(t, true, info["exists"]) - assert.Equal(t, false, info["isdir"]) + core.RequireNoError(t, err) + core.AssertEqual(t, true, info["exists"]) + core.AssertEqual(t, false, info["isdir"]) content, err := client.Download(context.Background(), path) - require.NoError(t, err) - assert.Equal(t, []byte("content"), content) + core.RequireNoError(t, err) + core.AssertEqual(t, []byte("content"), content) } -func TestExecutor_RunTaskOnHost_Good_LocalConnection(t *testing.T) { +func TestExecutor_RunTaskOnHost_Good_LocalConnection(t *core.T) { e := NewExecutor("/tmp") task := &Task{ @@ -57,56 +54,56 @@ func TestExecutor_RunTaskOnHost_Good_LocalConnection(t *testing.T) { } play := &Play{Connection: "local"} - require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"host1"}, task, play)) + core.RequireNoError(t, e.runTaskOnHosts(context.Background(), []string{"host1"}, task, play)) result := e.results["host1"]["local_result"] - require.NotNil(t, result) - assert.Equal(t, "local ok\n", result.Stdout) - assert.False(t, result.Failed) + core.AssertNotNil(t, result) + core.AssertEqual(t, "local ok\n", result.Stdout) + core.AssertFalse(t, result.Failed) _, ok := e.clients["host1"].(*localClient) - assert.True(t, ok) + core.AssertTrue(t, ok) } -func TestExecutor_GatherFacts_Good_LocalConnection(t *testing.T) { +func TestExecutor_GatherFacts_Good_LocalConnection(t *core.T) { e := NewExecutor("/tmp") - require.NoError(t, e.gatherFacts(context.Background(), "host1", &Play{Connection: "local"})) + core.RequireNoError(t, e.gatherFacts(context.Background(), "host1", &Play{Connection: "local"})) facts := e.facts["host1"] - require.NotNil(t, facts) - assert.NotEmpty(t, facts.Hostname) - assert.NotEmpty(t, facts.Kernel) + core.AssertNotNil(t, facts) + core.AssertNotEmpty(t, facts.Hostname) + core.AssertNotEmpty(t, facts.Kernel) } -func TestLocalClient_Good_SetBecomeResetsStateWhenDisabled(t *testing.T) { +func TestLocalClient_Good_SetBecomeResetsStateWhenDisabled(t *core.T) { client := newLocalClient() client.SetBecome(true, "admin", "secret") become, user, password := client.BecomeState() - assert.True(t, become) - assert.Equal(t, "admin", user) - assert.Equal(t, "secret", password) + core.AssertTrue(t, become) + core.AssertEqual(t, "admin", user) + core.AssertEqual(t, "secret", password) client.SetBecome(false, "", "") become, user, password = client.BecomeState() - assert.False(t, become) - assert.Empty(t, user) - assert.Empty(t, password) + core.AssertFalse(t, become) + core.AssertEmpty(t, user) + core.AssertEmpty(t, password) } -func TestAsyncClone_Good_DoesNotShareLocalClientState(t *testing.T) { +func TestAsyncClone_Good_DoesNotShareLocalClientState(t *core.T) { client := newLocalClient() client.SetBecome(true, "admin", "secret") cloned := cloneClientMap(map[string]sshExecutorClient{"host1": client}) clonedClient, ok := cloned["host1"].(*localClient) - require.True(t, ok) - assert.NotSame(t, client, clonedClient) + core.RequireTrue(t, ok) + core.AssertFalse(t, client == clonedClient) become, user, password := clonedClient.BecomeState() - assert.False(t, become) - assert.Empty(t, user) - assert.Empty(t, password) + core.AssertFalse(t, become) + core.AssertEmpty(t, user) + core.AssertEmpty(t, password) } diff --git a/mock_ssh_test.go b/mock_ssh_test.go index fca1a78..db892c7 100644 --- a/mock_ssh_test.go +++ b/mock_ssh_test.go @@ -12,7 +12,7 @@ import ( "sync" "time" - core "dappco.re/go/core" + core "dappco.re/go" ) // --- Mock SSH Client --- diff --git a/modules_adv_test.go b/modules_adv_test.go index dbc8b6d..328a0ea 100644 --- a/modules_adv_test.go +++ b/modules_adv_test.go @@ -2,11 +2,8 @@ package ansible import ( "context" - "testing" + core "dappco.re/go" "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) // ============================================================ @@ -17,7 +14,7 @@ import ( // --- user module --- -func TestModulesAdv_ModuleUser_Good_CreateNewUser(t *testing.T) { +func TestModulesAdv_ModuleUser_Good_CreateNewUser(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`id deploy >/dev/null 2>&1`, "", "no such user", 1) mock.expectCommand(`useradd`, "", "", 0) @@ -32,19 +29,19 @@ func TestModulesAdv_ModuleUser_Good_CreateNewUser(t *testing.T) { "create_home": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring("useradd")) - assert.True(t, mock.containsSubstring("-u 1500")) - assert.True(t, mock.containsSubstring("-g www-data")) - assert.True(t, mock.containsSubstring("-G docker,sudo")) - assert.True(t, mock.containsSubstring("-d /opt/deploy")) - assert.True(t, mock.containsSubstring("-s /bin/bash")) - assert.True(t, mock.containsSubstring("-m")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring("useradd")) + core.AssertTrue(t, mock.containsSubstring("-u 1500")) + core.AssertTrue(t, mock.containsSubstring("-g www-data")) + core.AssertTrue(t, mock.containsSubstring("-G docker,sudo")) + core.AssertTrue(t, mock.containsSubstring("-d /opt/deploy")) + core.AssertTrue(t, mock.containsSubstring("-s /bin/bash")) + core.AssertTrue(t, mock.containsSubstring("-m")) } -func TestModulesAdv_ModuleUser_Good_ModifyExistingUser(t *testing.T) { +func TestModulesAdv_ModuleUser_Good_ModifyExistingUser(t *core.T) { e, mock := newTestExecutorWithMock("host1") // id returns success meaning user exists, so usermod branch is taken mock.expectCommand(`id deploy >/dev/null 2>&1 && usermod`, "", "", 0) @@ -54,14 +51,14 @@ func TestModulesAdv_ModuleUser_Good_ModifyExistingUser(t *testing.T) { "shell": "/bin/zsh", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring("usermod")) - assert.True(t, mock.containsSubstring("-s /bin/zsh")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring("usermod")) + core.AssertTrue(t, mock.containsSubstring("-s /bin/zsh")) } -func TestModulesAdv_ModuleUser_Good_GroupListInput(t *testing.T) { +func TestModulesAdv_ModuleUser_Good_GroupListInput(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`id deploy >/dev/null 2>&1`, "", "no such user", 1) mock.expectCommand(`useradd`, "", "", 0) @@ -71,13 +68,13 @@ func TestModulesAdv_ModuleUser_Good_GroupListInput(t *testing.T) { "groups": []any{"docker", "sudo"}, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring("-G docker,sudo")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring("-G docker,sudo")) } -func TestModulesAdv_ModuleUser_Good_AppendSupplementaryGroups(t *testing.T) { +func TestModulesAdv_ModuleUser_Good_AppendSupplementaryGroups(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`id deploy >/dev/null 2>&1 && usermod -a -G docker,sudo deploy \|\| useradd -G docker,sudo deploy`, "", "", 0) @@ -88,14 +85,14 @@ func TestModulesAdv_ModuleUser_Good_AppendSupplementaryGroups(t *testing.T) { "create_home": false, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`usermod -a -G docker,sudo deploy`)) - assert.True(t, mock.hasExecuted(`useradd -G docker,sudo deploy`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`usermod -a -G docker,sudo deploy`)) + core.AssertTrue(t, mock.hasExecuted(`useradd -G docker,sudo deploy`)) } -func TestModulesAdv_ModuleUser_Good_RemoveUser(t *testing.T) { +func TestModulesAdv_ModuleUser_Good_RemoveUser(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`userdel -r deploy`, "", "", 0) @@ -104,12 +101,12 @@ func TestModulesAdv_ModuleUser_Good_RemoveUser(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`userdel -r deploy`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`userdel -r deploy`)) } -func TestModulesAdv_ModuleUser_Good_SystemUser(t *testing.T) { +func TestModulesAdv_ModuleUser_Good_SystemUser(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`id|useradd`, "", "", 0) @@ -120,20 +117,20 @@ func TestModulesAdv_ModuleUser_Good_SystemUser(t *testing.T) { "shell": "/usr/sbin/nologin", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) // system flag adds -r - assert.True(t, mock.containsSubstring("-r")) - assert.True(t, mock.containsSubstring("-s /usr/sbin/nologin")) + core.AssertTrue(t, mock.containsSubstring("-r")) + core.AssertTrue(t, mock.containsSubstring("-s /usr/sbin/nologin")) // create_home=false means -m should NOT be present // Actually, looking at the production code: getBoolArg(args, "create_home", true) — default is true // We set it to false explicitly, so -m should NOT appear cmd := mock.lastCommand() - assert.NotContains(t, cmd.Cmd, " -m ") + core.AssertNotContains(t, cmd.Cmd, " -m ") } -func TestModulesAdv_ModuleUser_Good_NoOptsUsesSimpleForm(t *testing.T) { +func TestModulesAdv_ModuleUser_Good_NoOptsUsesSimpleForm(t *core.T) { // When no options are provided, uses the simple "id || useradd" form e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`id testuser >/dev/null 2>&1 || useradd testuser`, "", "", 0) @@ -143,12 +140,12 @@ func TestModulesAdv_ModuleUser_Good_NoOptsUsesSimpleForm(t *testing.T) { "create_home": false, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) } -func TestModulesAdv_ModuleUser_Good_LocalModeUsesLocalCommands(t *testing.T) { +func TestModulesAdv_ModuleUser_Good_LocalModeUsesLocalCommands(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`id localuser >/dev/null 2>&1 && lusermod`, "", "", 0) @@ -160,16 +157,16 @@ func TestModulesAdv_ModuleUser_Good_LocalModeUsesLocalCommands(t *testing.T) { "append": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring("lusermod")) - assert.True(t, mock.containsSubstring("luseradd")) - assert.True(t, mock.containsSubstring("-s /bin/zsh")) - assert.True(t, mock.containsSubstring("-d /var/lib/localuser")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring("lusermod")) + core.AssertTrue(t, mock.containsSubstring("luseradd")) + core.AssertTrue(t, mock.containsSubstring("-s /bin/zsh")) + core.AssertTrue(t, mock.containsSubstring("-d /var/lib/localuser")) } -func TestModulesAdv_ModuleUser_Good_LocalModeRemovesLocalUser(t *testing.T) { +func TestModulesAdv_ModuleUser_Good_LocalModeRemovesLocalUser(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`luserdel -r localuser`, "", "", 0) @@ -179,13 +176,13 @@ func TestModulesAdv_ModuleUser_Good_LocalModeRemovesLocalUser(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`luserdel -r localuser`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`luserdel -r localuser`)) } -func TestModulesAdv_ModuleUser_Bad_MissingName(t *testing.T) { +func TestModulesAdv_ModuleUser_Bad_MissingName(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() @@ -193,11 +190,11 @@ func TestModulesAdv_ModuleUser_Bad_MissingName(t *testing.T) { "state": "present", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "name required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "name required") } -func TestModulesAdv_ModuleUser_Good_CommandFailure(t *testing.T) { +func TestModulesAdv_ModuleUser_Good_CommandFailure(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`id|useradd|usermod`, "", "useradd: Permission denied", 1) @@ -206,14 +203,14 @@ func TestModulesAdv_ModuleUser_Good_CommandFailure(t *testing.T) { "shell": "/bin/bash", }) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, "Permission denied") + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, "Permission denied") } // --- hostname module --- -func TestModulesAdv_ModuleHostname_Good_IdempotentWhenAlreadySet(t *testing.T) { +func TestModulesAdv_ModuleHostname_Good_IdempotentWhenAlreadySet(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`^hostname$`, "web01\n", "", 0) @@ -221,14 +218,14 @@ func TestModulesAdv_ModuleHostname_Good_IdempotentWhenAlreadySet(t *testing.T) { "name": "web01", }) - require.NoError(t, err) - assert.False(t, result.Changed) - assert.Equal(t, "hostname already set", result.Msg) - assert.True(t, mock.hasExecuted(`^hostname$`)) - assert.False(t, mock.hasExecuted(`hostnamectl set-hostname`)) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertEqual(t, "hostname already set", result.Msg) + core.AssertTrue(t, mock.hasExecuted(`^hostname$`)) + core.AssertFalse(t, mock.hasExecuted(`hostnamectl set-hostname`)) } -func TestModulesAdv_ModuleHostname_Good_ChangesWhenDifferent(t *testing.T) { +func TestModulesAdv_ModuleHostname_Good_ChangesWhenDifferent(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`^hostname$`, "old-host\n", "", 0) mock.expectCommand(`hostnamectl set-hostname "new-host" \|\| hostname "new-host"`, "", "", 0) @@ -238,15 +235,15 @@ func TestModulesAdv_ModuleHostname_Good_ChangesWhenDifferent(t *testing.T) { "name": "new-host", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`^hostname$`)) - assert.True(t, mock.hasExecuted(`hostnamectl set-hostname`)) - assert.True(t, mock.hasExecuted(`sed -i`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`^hostname$`)) + core.AssertTrue(t, mock.hasExecuted(`hostnamectl set-hostname`)) + core.AssertTrue(t, mock.hasExecuted(`sed -i`)) } -func TestModulesAdv_ModuleHostname_Good_HostnameAlias(t *testing.T) { +func TestModulesAdv_ModuleHostname_Good_HostnameAlias(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`^hostname$`, "old-host\n", "", 0) mock.expectCommand(`hostnamectl set-hostname "alias-host" \|\| hostname "alias-host"`, "", "", 0) @@ -256,16 +253,16 @@ func TestModulesAdv_ModuleHostname_Good_HostnameAlias(t *testing.T) { "hostname": "alias-host", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`hostnamectl set-hostname`)) - assert.True(t, mock.hasExecuted(`sed -i`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`hostnamectl set-hostname`)) + core.AssertTrue(t, mock.hasExecuted(`sed -i`)) } // --- group module --- -func TestModulesAdv_ModuleGroup_Good_CreateNewGroup(t *testing.T) { +func TestModulesAdv_ModuleGroup_Good_CreateNewGroup(t *core.T) { e, mock := newTestExecutorWithMock("host1") // getent fails → groupadd runs mock.expectCommand(`getent group appgroup`, "", "", 1) @@ -275,14 +272,14 @@ func TestModulesAdv_ModuleGroup_Good_CreateNewGroup(t *testing.T) { "name": "appgroup", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring("groupadd")) - assert.True(t, mock.containsSubstring("appgroup")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring("groupadd")) + core.AssertTrue(t, mock.containsSubstring("appgroup")) } -func TestModulesAdv_ModuleGroup_Good_GroupAlreadyExists(t *testing.T) { +func TestModulesAdv_ModuleGroup_Good_GroupAlreadyExists(t *core.T) { e, mock := newTestExecutorWithMock("host1") // getent succeeds → groupadd skipped (|| short-circuits) mock.expectCommand(`getent group docker >/dev/null 2>&1 || groupadd`, "", "", 0) @@ -291,12 +288,12 @@ func TestModulesAdv_ModuleGroup_Good_GroupAlreadyExists(t *testing.T) { "name": "docker", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) } -func TestModulesAdv_ModuleGroup_Good_RemoveGroup(t *testing.T) { +func TestModulesAdv_ModuleGroup_Good_RemoveGroup(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`groupdel oldgroup`, "", "", 0) @@ -305,12 +302,12 @@ func TestModulesAdv_ModuleGroup_Good_RemoveGroup(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`groupdel oldgroup`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`groupdel oldgroup`)) } -func TestModulesAdv_ModuleGroup_Good_SystemGroup(t *testing.T) { +func TestModulesAdv_ModuleGroup_Good_SystemGroup(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`getent group|groupadd`, "", "", 0) @@ -319,13 +316,13 @@ func TestModulesAdv_ModuleGroup_Good_SystemGroup(t *testing.T) { "system": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring("-r")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring("-r")) } -func TestModulesAdv_ModuleGroup_Good_CustomGID(t *testing.T) { +func TestModulesAdv_ModuleGroup_Good_CustomGID(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`getent group|groupadd`, "", "", 0) @@ -334,13 +331,13 @@ func TestModulesAdv_ModuleGroup_Good_CustomGID(t *testing.T) { "gid": "5000", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring("-g 5000")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring("-g 5000")) } -func TestModulesAdv_ModuleGroup_Good_LocalGroup(t *testing.T) { +func TestModulesAdv_ModuleGroup_Good_LocalGroup(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`getent group localusers`, "", "", 1) mock.expectCommand(`lgroupadd`, "", "", 0) @@ -350,13 +347,13 @@ func TestModulesAdv_ModuleGroup_Good_LocalGroup(t *testing.T) { "local": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring("lgroupadd")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring("lgroupadd")) } -func TestModulesAdv_ModuleGroup_Good_LocalGroupRemove(t *testing.T) { +func TestModulesAdv_ModuleGroup_Good_LocalGroupRemove(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`lgroupdel localusers`, "", "", 0) @@ -366,12 +363,12 @@ func TestModulesAdv_ModuleGroup_Good_LocalGroupRemove(t *testing.T) { "local": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`lgroupdel localusers`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`lgroupdel localusers`)) } -func TestModulesAdv_ModuleGroup_Good_NonUniqueGID(t *testing.T) { +func TestModulesAdv_ModuleGroup_Good_NonUniqueGID(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`getent group|groupadd`, "", "", 0) @@ -381,14 +378,14 @@ func TestModulesAdv_ModuleGroup_Good_NonUniqueGID(t *testing.T) { "non_unique": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring("-g 5000")) - assert.True(t, mock.containsSubstring("-o")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring("-g 5000")) + core.AssertTrue(t, mock.containsSubstring("-o")) } -func TestModulesAdv_ModuleGroup_Bad_MissingName(t *testing.T) { +func TestModulesAdv_ModuleGroup_Bad_MissingName(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() @@ -396,11 +393,11 @@ func TestModulesAdv_ModuleGroup_Bad_MissingName(t *testing.T) { "state": "present", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "name required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "name required") } -func TestModulesAdv_ModuleGroup_Good_CommandFailure(t *testing.T) { +func TestModulesAdv_ModuleGroup_Good_CommandFailure(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`getent group|groupadd`, "", "groupadd: Permission denied", 1) @@ -408,13 +405,13 @@ func TestModulesAdv_ModuleGroup_Good_CommandFailure(t *testing.T) { "name": "failgroup", }) - require.NoError(t, err) - assert.True(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) } // --- cron module --- -func TestModulesAdv_ModuleCron_Good_AddCronJob(t *testing.T) { +func TestModulesAdv_ModuleCron_Good_AddCronJob(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`crontab -u root`, "", "", 0) @@ -423,16 +420,16 @@ func TestModulesAdv_ModuleCron_Good_AddCronJob(t *testing.T) { "job": "/usr/local/bin/backup.sh", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) // Default schedule is * * * * * - assert.True(t, mock.containsSubstring("* * * * *")) - assert.True(t, mock.containsSubstring("/usr/local/bin/backup.sh")) - assert.True(t, mock.containsSubstring("# backup")) + core.AssertTrue(t, mock.containsSubstring("* * * * *")) + core.AssertTrue(t, mock.containsSubstring("/usr/local/bin/backup.sh")) + core.AssertTrue(t, mock.containsSubstring("# backup")) } -func TestModulesAdv_ModuleCron_Good_RemoveCronJob(t *testing.T) { +func TestModulesAdv_ModuleCron_Good_RemoveCronJob(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`crontab -u root -l`, "* * * * * /bin/backup # backup\n", "", 0) @@ -442,12 +439,12 @@ func TestModulesAdv_ModuleCron_Good_RemoveCronJob(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.containsSubstring("grep -v")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.containsSubstring("grep -v")) } -func TestModulesAdv_ModuleCron_Good_CustomSchedule(t *testing.T) { +func TestModulesAdv_ModuleCron_Good_CustomSchedule(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`crontab -u root`, "", "", 0) @@ -461,14 +458,14 @@ func TestModulesAdv_ModuleCron_Good_CustomSchedule(t *testing.T) { "weekday": "0", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring("30 2 1 6 0")) - assert.True(t, mock.containsSubstring("/opt/scripts/backup.sh")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring("30 2 1 6 0")) + core.AssertTrue(t, mock.containsSubstring("/opt/scripts/backup.sh")) } -func TestModulesAdv_ModuleCron_Good_CustomUser(t *testing.T) { +func TestModulesAdv_ModuleCron_Good_CustomUser(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`crontab -u www-data`, "", "", 0) @@ -480,14 +477,14 @@ func TestModulesAdv_ModuleCron_Good_CustomUser(t *testing.T) { "hour": "*/4", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring("crontab -u www-data")) - assert.True(t, mock.containsSubstring("0 */4 * * *")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring("crontab -u www-data")) + core.AssertTrue(t, mock.containsSubstring("0 */4 * * *")) } -func TestModulesAdv_ModuleCron_Good_SpecialTime(t *testing.T) { +func TestModulesAdv_ModuleCron_Good_SpecialTime(t *core.T) { e := NewExecutor("/tmp") mock := NewMockSSHClient() mock.expectCommand(`crontab -u root`, "", "", 0) @@ -498,13 +495,13 @@ func TestModulesAdv_ModuleCron_Good_SpecialTime(t *testing.T) { "special_time": "daily", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring(`@daily /usr/local/bin/backup.sh # daily-backup`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring(`@daily /usr/local/bin/backup.sh # daily-backup`)) } -func TestModulesAdv_ModuleCron_Good_BackupCreatesBackupFile(t *testing.T) { +func TestModulesAdv_ModuleCron_Good_BackupCreatesBackupFile(t *core.T) { e := NewExecutor("/tmp") mock := NewMockSSHClient() mock.expectCommand(`crontab -u root`, "", "", 0) @@ -518,22 +515,22 @@ func TestModulesAdv_ModuleCron_Good_BackupCreatesBackupFile(t *testing.T) { "backup": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - require.NotNil(t, result.Data) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertNotNil(t, result.Data) backupPath, ok := result.Data["backup_file"].(string) - require.True(t, ok) - assert.Contains(t, backupPath, "/tmp/ansible-cron-root-daily-backup.") - assert.Equal(t, 1, mock.uploadCount()) + core.RequireTrue(t, ok) + core.AssertContains(t, backupPath, "/tmp/ansible-cron-root-daily-backup.") + core.AssertEqual(t, 1, mock.uploadCount()) lastUpload := mock.lastUpload() - require.NotNil(t, lastUpload) - assert.Equal(t, backupPath, lastUpload.Remote) - assert.Equal(t, []byte("0 0 * * * /usr/local/bin/backup.sh # daily-backup\n"), lastUpload.Content) - assert.True(t, mock.containsSubstring("crontab -u root -l")) - assert.True(t, mock.containsSubstring("crontab -u root")) + core.AssertNotNil(t, lastUpload) + core.AssertEqual(t, backupPath, lastUpload.Remote) + core.AssertEqual(t, []byte("0 0 * * * /usr/local/bin/backup.sh # daily-backup\n"), lastUpload.Content) + core.AssertTrue(t, mock.containsSubstring("crontab -u root -l")) + core.AssertTrue(t, mock.containsSubstring("crontab -u root")) } -func TestModulesAdv_ModuleCron_Good_DisabledJobCommentsEntry(t *testing.T) { +func TestModulesAdv_ModuleCron_Good_DisabledJobCommentsEntry(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`crontab -u root`, "", "", 0) @@ -545,13 +542,13 @@ func TestModulesAdv_ModuleCron_Good_DisabledJobCommentsEntry(t *testing.T) { "disabled": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring(`# 15 1 * * * /usr/local/bin/backup.sh # backup`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring(`# 15 1 * * * /usr/local/bin/backup.sh # backup`)) } -func TestModulesAdv_ModuleCron_Good_AbsentWithNoName(t *testing.T) { +func TestModulesAdv_ModuleCron_Good_AbsentWithNoName(t *core.T) { // Absent with no name — changed but no grep command e, mock := newTestExecutorWithMock("host1") @@ -559,15 +556,15 @@ func TestModulesAdv_ModuleCron_Good_AbsentWithNoName(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // No commands should have run since name is empty - assert.Equal(t, 0, mock.commandCount()) + core.AssertEqual(t, 0, mock.commandCount()) } // --- authorized_key module --- -func TestModulesAdv_ModuleAuthorizedKey_Good_AddKey(t *testing.T) { +func TestModulesAdv_ModuleAuthorizedKey_Good_AddKey(t *core.T) { e, mock := newTestExecutorWithMock("host1") testKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDcT... user@host" mock.expectCommand(`getent passwd deploy`, "/home/deploy", "", 0) @@ -581,15 +578,15 @@ func TestModulesAdv_ModuleAuthorizedKey_Good_AddKey(t *testing.T) { "key": testKey, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring("mkdir -p")) - assert.True(t, mock.containsSubstring("chmod 700")) - assert.True(t, mock.containsSubstring("authorized_keys")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring("mkdir -p")) + core.AssertTrue(t, mock.containsSubstring("chmod 700")) + core.AssertTrue(t, mock.containsSubstring("authorized_keys")) } -func TestModulesAdv_ModuleAuthorizedKey_Good_ShortKeyDoesNotPanic(t *testing.T) { +func TestModulesAdv_ModuleAuthorizedKey_Good_ShortKeyDoesNotPanic(t *core.T) { e, mock := newTestExecutorWithMock("host1") testKey := "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA short@host" mock.expectCommand(`getent passwd deploy`, "/home/deploy", "", 0) @@ -602,13 +599,13 @@ func TestModulesAdv_ModuleAuthorizedKey_Good_ShortKeyDoesNotPanic(t *testing.T) "key": testKey, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`grep -qF`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`grep -qF`)) } -func TestModulesAdv_ModuleAuthorizedKey_Good_RemoveKey(t *testing.T) { +func TestModulesAdv_ModuleAuthorizedKey_Good_RemoveKey(t *core.T) { e, mock := newTestExecutorWithMock("host1") testKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDcT... user@host" mock.expectCommand(`getent passwd deploy`, "/home/deploy", "", 0) @@ -620,13 +617,13 @@ func TestModulesAdv_ModuleAuthorizedKey_Good_RemoveKey(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`sed -i`)) - assert.True(t, mock.containsSubstring("authorized_keys")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`sed -i`)) + core.AssertTrue(t, mock.containsSubstring("authorized_keys")) } -func TestModulesAdv_ModuleAuthorizedKey_Good_KeyAlreadyExists(t *testing.T) { +func TestModulesAdv_ModuleAuthorizedKey_Good_KeyAlreadyExists(t *core.T) { e, mock := newTestExecutorWithMock("host1") testKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDcT... user@host" mock.addFile("/home/deploy/.ssh/authorized_keys", []byte(testKey+"\n")) @@ -637,13 +634,13 @@ func TestModulesAdv_ModuleAuthorizedKey_Good_KeyAlreadyExists(t *testing.T) { "key": testKey, }) - require.NoError(t, err) - assert.False(t, result.Changed) - assert.False(t, result.Failed) - assert.Contains(t, result.Msg, "already up to date") + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertContains(t, result.Msg, "already up to date") } -func TestModulesAdv_ModuleAuthorizedKey_Good_RewritesKeyOptionsAndComment(t *testing.T) { +func TestModulesAdv_ModuleAuthorizedKey_Good_RewritesKeyOptionsAndComment(t *core.T) { e, mock := newTestExecutorWithMock("host1") testKey := "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA user@host" authPath := "/home/deploy/.ssh/authorized_keys" @@ -657,18 +654,18 @@ func TestModulesAdv_ModuleAuthorizedKey_Good_RewritesKeyOptionsAndComment(t *tes "comment": "backup access", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`chmod 600`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`chmod 600`)) content, err := mock.Download(context.Background(), authPath) - require.NoError(t, err) - assert.Contains(t, string(content), `command="/usr/local/bin/backup-only" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA backup access`) - assert.NotContains(t, string(content), testKey) + core.RequireNoError(t, err) + core.AssertContains(t, string(content), `command="/usr/local/bin/backup-only" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA backup access`) + core.AssertNotContains(t, string(content), testKey) } -func TestModulesAdv_ModuleAuthorizedKey_Good_ExclusiveRewritesFile(t *testing.T) { +func TestModulesAdv_ModuleAuthorizedKey_Good_ExclusiveRewritesFile(t *core.T) { e := NewExecutor("/tmp") mock := NewMockSSHClient() testKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDcT... user@host" @@ -683,16 +680,16 @@ func TestModulesAdv_ModuleAuthorizedKey_Good_ExclusiveRewritesFile(t *testing.T) "exclusive": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) content, err := mock.Download(context.Background(), "/home/deploy/.ssh/authorized_keys") - require.NoError(t, err) - assert.Equal(t, testKey+"\n", string(content)) - assert.False(t, mock.hasExecuted(`grep -qF`)) + core.RequireNoError(t, err) + core.AssertEqual(t, testKey+"\n", string(content)) + core.AssertFalse(t, mock.hasExecuted(`grep -qF`)) } -func TestModulesAdv_ModuleAuthorizedKey_Good_CustomPath(t *testing.T) { +func TestModulesAdv_ModuleAuthorizedKey_Good_CustomPath(t *core.T) { e, mock := newTestExecutorWithMock("host1") testKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDcT... user@host" mock.expectCommand(`getent passwd deploy`, "/home/deploy", "", 0) @@ -707,14 +704,14 @@ func TestModulesAdv_ModuleAuthorizedKey_Good_CustomPath(t *testing.T) { "path": "/srv/keys/deploy_keys", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring("/srv/keys/deploy_keys")) - assert.True(t, mock.hasExecuted(`mkdir -p "/srv/keys"`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring("/srv/keys/deploy_keys")) + core.AssertTrue(t, mock.hasExecuted(`mkdir -p "/srv/keys"`)) } -func TestModulesAdv_ModuleAuthorizedKey_Good_ManageDirDisabled(t *testing.T) { +func TestModulesAdv_ModuleAuthorizedKey_Good_ManageDirDisabled(t *core.T) { e, mock := newTestExecutorWithMock("host1") testKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDcT... user@host" mock.expectCommand(`getent passwd deploy`, "/home/deploy", "", 0) @@ -728,13 +725,13 @@ func TestModulesAdv_ModuleAuthorizedKey_Good_ManageDirDisabled(t *testing.T) { "manage_dir": false, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.False(t, mock.hasExecuted(`mkdir -p`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertFalse(t, mock.hasExecuted(`mkdir -p`)) } -func TestModulesAdv_ModuleAuthorizedKey_Good_RootUserFallback(t *testing.T) { +func TestModulesAdv_ModuleAuthorizedKey_Good_RootUserFallback(t *core.T) { e, mock := newTestExecutorWithMock("host1") testKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDcT... admin@host" // getent returns empty — falls back to /root for root user @@ -748,24 +745,24 @@ func TestModulesAdv_ModuleAuthorizedKey_Good_RootUserFallback(t *testing.T) { "key": testKey, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) // Should use /root/.ssh/authorized_keys - assert.True(t, mock.containsSubstring("/root/.ssh")) + core.AssertTrue(t, mock.containsSubstring("/root/.ssh")) } -func TestModulesAdv_ModuleAuthorizedKey_Bad_MissingUserAndKey(t *testing.T) { +func TestModulesAdv_ModuleAuthorizedKey_Bad_MissingUserAndKey(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() _, err := moduleAuthorizedKeyWithClient(e, mock, map[string]any{}) - assert.Error(t, err) - assert.Contains(t, err.Error(), "user and key required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "user and key required") } -func TestModulesAdv_ModuleAuthorizedKey_Bad_MissingKey(t *testing.T) { +func TestModulesAdv_ModuleAuthorizedKey_Bad_MissingKey(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() @@ -773,11 +770,11 @@ func TestModulesAdv_ModuleAuthorizedKey_Bad_MissingKey(t *testing.T) { "user": "deploy", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "user and key required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "user and key required") } -func TestModulesAdv_ModuleAuthorizedKey_Bad_MissingUser(t *testing.T) { +func TestModulesAdv_ModuleAuthorizedKey_Bad_MissingUser(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() @@ -785,13 +782,13 @@ func TestModulesAdv_ModuleAuthorizedKey_Bad_MissingUser(t *testing.T) { "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDcT...", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "user and key required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "user and key required") } // --- git module --- -func TestModulesAdv_ModuleGit_Good_FreshClone(t *testing.T) { +func TestModulesAdv_ModuleGit_Good_FreshClone(t *core.T) { e, mock := newTestExecutorWithMock("host1") // .git does not exist → fresh clone mock.expectCommand(`git clone`, "", "", 0) @@ -801,17 +798,17 @@ func TestModulesAdv_ModuleGit_Good_FreshClone(t *testing.T) { "dest": "/opt/app", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`git clone`)) - assert.True(t, mock.containsSubstring("https://github.com/example/app.git")) - assert.True(t, mock.containsSubstring("/opt/app")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`git clone`)) + core.AssertTrue(t, mock.containsSubstring("https://github.com/example/app.git")) + core.AssertTrue(t, mock.containsSubstring("/opt/app")) // Default version is HEAD - assert.True(t, mock.containsSubstring("git checkout")) + core.AssertTrue(t, mock.containsSubstring("git checkout")) } -func TestModulesAdv_ModuleGit_Good_UpdateExisting(t *testing.T) { +func TestModulesAdv_ModuleGit_Good_UpdateExisting(t *core.T) { e, mock := newTestExecutorWithMock("host1") // .git exists → fetch + checkout mock.addFile("/opt/app/.git", []byte("gitdir")) @@ -822,16 +819,16 @@ func TestModulesAdv_ModuleGit_Good_UpdateExisting(t *testing.T) { "dest": "/opt/app", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`git fetch --all`)) - assert.True(t, mock.containsSubstring("git checkout --force")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`git fetch --all`)) + core.AssertTrue(t, mock.containsSubstring("git checkout --force")) // Should NOT contain git clone - assert.False(t, mock.containsSubstring("git clone")) + core.AssertFalse(t, mock.containsSubstring("git clone")) } -func TestModulesAdv_ModuleGit_Good_CustomVersion(t *testing.T) { +func TestModulesAdv_ModuleGit_Good_CustomVersion(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`git clone`, "", "", 0) @@ -841,13 +838,13 @@ func TestModulesAdv_ModuleGit_Good_CustomVersion(t *testing.T) { "version": "v2.1.0", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring("v2.1.0")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring("v2.1.0")) } -func TestModulesAdv_ModuleGit_Good_UpdateWithBranch(t *testing.T) { +func TestModulesAdv_ModuleGit_Good_UpdateWithBranch(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/srv/myapp/.git", []byte("gitdir")) mock.expectCommand(`git fetch --all && git checkout`, "", "", 0) @@ -858,22 +855,22 @@ func TestModulesAdv_ModuleGit_Good_UpdateWithBranch(t *testing.T) { "version": "develop", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.containsSubstring("develop")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.containsSubstring("develop")) } -func TestModulesAdv_ModuleGit_Bad_MissingRepoAndDest(t *testing.T) { +func TestModulesAdv_ModuleGit_Bad_MissingRepoAndDest(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() _, err := moduleGitWithClient(e, mock, map[string]any{}) - assert.Error(t, err) - assert.Contains(t, err.Error(), "repo and dest required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "repo and dest required") } -func TestModulesAdv_ModuleGit_Bad_MissingRepo(t *testing.T) { +func TestModulesAdv_ModuleGit_Bad_MissingRepo(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() @@ -881,11 +878,11 @@ func TestModulesAdv_ModuleGit_Bad_MissingRepo(t *testing.T) { "dest": "/opt/app", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "repo and dest required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "repo and dest required") } -func TestModulesAdv_ModuleGit_Bad_MissingDest(t *testing.T) { +func TestModulesAdv_ModuleGit_Bad_MissingDest(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() @@ -893,11 +890,11 @@ func TestModulesAdv_ModuleGit_Bad_MissingDest(t *testing.T) { "repo": "https://github.com/example/app.git", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "repo and dest required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "repo and dest required") } -func TestModulesAdv_ModuleGit_Good_CloneFailure(t *testing.T) { +func TestModulesAdv_ModuleGit_Good_CloneFailure(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`git clone`, "", "fatal: repository not found", 128) @@ -906,18 +903,18 @@ func TestModulesAdv_ModuleGit_Good_CloneFailure(t *testing.T) { "dest": "/opt/app", }) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, "repository not found") + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, "repository not found") } // --- unarchive module --- -func TestModulesAdv_ModuleUnarchive_Good_ExtractTarGzLocal(t *testing.T) { +func TestModulesAdv_ModuleUnarchive_Good_ExtractTarGzLocal(t *core.T) { // Create a temporary "archive" file tmpDir := t.TempDir() archivePath := joinPath(tmpDir, "package.tar.gz") - require.NoError(t, writeTestFile(archivePath, []byte("fake-archive-content"), 0644)) + core.RequireNoError(t, writeTestFile(archivePath, []byte("fake-archive-content"), 0644)) e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`mkdir -p`, "", "", 0) @@ -929,19 +926,19 @@ func TestModulesAdv_ModuleUnarchive_Good_ExtractTarGzLocal(t *testing.T) { "dest": "/opt/app", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) // Should have uploaded the file - assert.Equal(t, 1, mock.uploadCount()) - assert.True(t, mock.containsSubstring("tar -xzf")) - assert.True(t, mock.containsSubstring("/opt/app")) + core.AssertEqual(t, 1, mock.uploadCount()) + core.AssertTrue(t, mock.containsSubstring("tar -xzf")) + core.AssertTrue(t, mock.containsSubstring("/opt/app")) } -func TestModulesAdv_ModuleUnarchive_Good_ExtractZipLocal(t *testing.T) { +func TestModulesAdv_ModuleUnarchive_Good_ExtractZipLocal(t *core.T) { tmpDir := t.TempDir() archivePath := joinPath(tmpDir, "release.zip") - require.NoError(t, writeTestFile(archivePath, []byte("fake-zip-content"), 0644)) + core.RequireNoError(t, writeTestFile(archivePath, []byte("fake-zip-content"), 0644)) e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`mkdir -p`, "", "", 0) @@ -953,14 +950,14 @@ func TestModulesAdv_ModuleUnarchive_Good_ExtractZipLocal(t *testing.T) { "dest": "/opt/releases", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.Equal(t, 1, mock.uploadCount()) - assert.True(t, mock.containsSubstring("unzip -o")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, 1, mock.uploadCount()) + core.AssertTrue(t, mock.containsSubstring("unzip -o")) } -func TestModulesAdv_ModuleUnarchive_Good_RemoteSource(t *testing.T) { +func TestModulesAdv_ModuleUnarchive_Good_RemoteSource(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`mkdir -p`, "", "", 0) mock.expectCommand(`tar -xzf`, "", "", 0) @@ -971,15 +968,15 @@ func TestModulesAdv_ModuleUnarchive_Good_RemoteSource(t *testing.T) { "remote_src": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) // No upload should happen for remote sources - assert.Equal(t, 0, mock.uploadCount()) - assert.True(t, mock.containsSubstring("tar -xzf")) + core.AssertEqual(t, 0, mock.uploadCount()) + core.AssertTrue(t, mock.containsSubstring("tar -xzf")) } -func TestModulesAdv_ModuleUnarchive_Good_TarXz(t *testing.T) { +func TestModulesAdv_ModuleUnarchive_Good_TarXz(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`mkdir -p`, "", "", 0) mock.expectCommand(`tar -xJf`, "", "", 0) @@ -990,12 +987,12 @@ func TestModulesAdv_ModuleUnarchive_Good_TarXz(t *testing.T) { "remote_src": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.containsSubstring("tar -xJf")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.containsSubstring("tar -xJf")) } -func TestModulesAdv_ModuleUnarchive_Good_TarBz2(t *testing.T) { +func TestModulesAdv_ModuleUnarchive_Good_TarBz2(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`mkdir -p`, "", "", 0) mock.expectCommand(`tar -xjf`, "", "", 0) @@ -1006,22 +1003,22 @@ func TestModulesAdv_ModuleUnarchive_Good_TarBz2(t *testing.T) { "remote_src": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.containsSubstring("tar -xjf")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.containsSubstring("tar -xjf")) } -func TestModulesAdv_ModuleUnarchive_Bad_MissingSrcAndDest(t *testing.T) { +func TestModulesAdv_ModuleUnarchive_Bad_MissingSrcAndDest(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() _, err := moduleUnarchiveWithClient(e, mock, map[string]any{}) - assert.Error(t, err) - assert.Contains(t, err.Error(), "src and dest required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "src and dest required") } -func TestModulesAdv_ModuleUnarchive_Bad_MissingSrc(t *testing.T) { +func TestModulesAdv_ModuleUnarchive_Bad_MissingSrc(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() @@ -1029,11 +1026,11 @@ func TestModulesAdv_ModuleUnarchive_Bad_MissingSrc(t *testing.T) { "dest": "/opt/app", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "src and dest required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "src and dest required") } -func TestModulesAdv_ModuleUnarchive_Bad_LocalFileNotFound(t *testing.T) { +func TestModulesAdv_ModuleUnarchive_Bad_LocalFileNotFound(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() mock.expectCommand(`mkdir -p`, "", "", 0) @@ -1043,13 +1040,13 @@ func TestModulesAdv_ModuleUnarchive_Bad_LocalFileNotFound(t *testing.T) { "dest": "/opt/app", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "read src") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "read src") } // --- pause module --- -func TestModulesAdv_ModulePause_Good_WaitsForSeconds(t *testing.T) { +func TestModulesAdv_ModulePause_Good_WaitsForSeconds(t *core.T) { e := NewExecutor("/tmp") start := time.Now() @@ -1058,13 +1055,13 @@ func TestModulesAdv_ModulePause_Good_WaitsForSeconds(t *testing.T) { }) elapsed := time.Since(start) - require.NoError(t, err) - assert.NotNil(t, result) - assert.False(t, result.Changed) - assert.GreaterOrEqual(t, elapsed, 900*time.Millisecond) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Changed) + core.AssertGreaterOrEqual(t, elapsed, 900*time.Millisecond) } -func TestModulesAdv_ModulePause_Good_PromptReturnsImmediatelyWithoutTTY(t *testing.T) { +func TestModulesAdv_ModulePause_Good_PromptReturnsImmediatelyWithoutTTY(t *core.T) { e := NewExecutor("/tmp") start := time.Now() @@ -1074,16 +1071,16 @@ func TestModulesAdv_ModulePause_Good_PromptReturnsImmediatelyWithoutTTY(t *testi }) elapsed := time.Since(start) - require.NoError(t, err) - assert.NotNil(t, result) - assert.False(t, result.Changed) - assert.Equal(t, "Press enter to continue", result.Msg) - assert.Less(t, elapsed, 250*time.Millisecond) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Changed) + core.AssertEqual(t, "Press enter to continue", result.Msg) + core.AssertLess(t, elapsed, 250*time.Millisecond) } // --- wait_for module --- -func TestModulesAdv_ModuleWaitFor_Good_WaitsForPathPresent(t *testing.T) { +func TestModulesAdv_ModuleWaitFor_Good_WaitsForPathPresent(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/tmp/ready", []byte("ok")) @@ -1091,13 +1088,13 @@ func TestModulesAdv_ModuleWaitFor_Good_WaitsForPathPresent(t *testing.T) { "path": "/tmp/ready", }) - require.NoError(t, err) - assert.NotNil(t, result) - assert.False(t, result.Failed) - assert.False(t, result.Changed) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Failed) + core.AssertFalse(t, result.Changed) } -func TestModulesAdv_ModuleWaitFor_Good_WaitsForPathAbsent(t *testing.T) { +func TestModulesAdv_ModuleWaitFor_Good_WaitsForPathAbsent(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/tmp/vanish", []byte("ok")) @@ -1116,14 +1113,14 @@ func TestModulesAdv_ModuleWaitFor_Good_WaitsForPathAbsent(t *testing.T) { }) elapsed := time.Since(start) - require.NoError(t, err) - assert.NotNil(t, result) - assert.False(t, result.Failed) - assert.False(t, result.Changed) - assert.GreaterOrEqual(t, elapsed, 150*time.Millisecond) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Failed) + core.AssertFalse(t, result.Changed) + core.AssertGreaterOrEqual(t, elapsed, 150*time.Millisecond) } -func TestModulesAdv_ModuleWaitFor_Good_WaitsForPathRegexMatch(t *testing.T) { +func TestModulesAdv_ModuleWaitFor_Good_WaitsForPathRegexMatch(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/tmp/config", []byte("ready=false\n")) @@ -1142,14 +1139,14 @@ func TestModulesAdv_ModuleWaitFor_Good_WaitsForPathRegexMatch(t *testing.T) { }) elapsed := time.Since(start) - require.NoError(t, err) - assert.NotNil(t, result) - assert.False(t, result.Failed) - assert.False(t, result.Changed) - assert.GreaterOrEqual(t, elapsed, 150*time.Millisecond) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Failed) + core.AssertFalse(t, result.Changed) + core.AssertGreaterOrEqual(t, elapsed, 150*time.Millisecond) } -func TestModulesAdv_ModuleWaitFor_Good_HonoursInitialDelay(t *testing.T) { +func TestModulesAdv_ModuleWaitFor_Good_HonoursInitialDelay(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/tmp/delayed", []byte("ready=false\n")) @@ -1168,14 +1165,14 @@ func TestModulesAdv_ModuleWaitFor_Good_HonoursInitialDelay(t *testing.T) { }) elapsed := time.Since(start) - require.NoError(t, err) - assert.NotNil(t, result) - assert.False(t, result.Failed) - assert.False(t, result.Changed) - assert.GreaterOrEqual(t, elapsed, 1*time.Second) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Failed) + core.AssertFalse(t, result.Changed) + core.AssertGreaterOrEqual(t, elapsed, 1*time.Second) } -func TestModulesAdv_ModuleWaitFor_Bad_CustomTimeoutMessage(t *testing.T) { +func TestModulesAdv_ModuleWaitFor_Bad_CustomTimeoutMessage(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/tmp/config", []byte("ready=false\n")) @@ -1186,13 +1183,13 @@ func TestModulesAdv_ModuleWaitFor_Bad_CustomTimeoutMessage(t *testing.T) { "msg": "service never became ready", }) - require.NoError(t, err) - assert.NotNil(t, result) - assert.True(t, result.Failed) - assert.Equal(t, "service never became ready", result.Msg) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertTrue(t, result.Failed) + core.AssertEqual(t, "service never became ready", result.Msg) } -func TestModulesAdv_ModuleWaitFor_Good_WaitsForPortAbsent(t *testing.T) { +func TestModulesAdv_ModuleWaitFor_Good_WaitsForPortAbsent(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`timeout 2 bash -c 'until ! nc -z 127.0.0.1 8080; do sleep 1; done'`, "", "", 0) @@ -1203,14 +1200,14 @@ func TestModulesAdv_ModuleWaitFor_Good_WaitsForPortAbsent(t *testing.T) { "timeout": 2, }) - require.NoError(t, err) - assert.NotNil(t, result) - assert.False(t, result.Failed) - assert.False(t, result.Changed) - assert.True(t, mock.hasExecuted(`until ! nc -z 127.0.0.1 8080`)) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Failed) + core.AssertFalse(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`until ! nc -z 127.0.0.1 8080`)) } -func TestModulesAdv_ModuleWaitFor_Good_WaitsForPortStopped(t *testing.T) { +func TestModulesAdv_ModuleWaitFor_Good_WaitsForPortStopped(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`timeout 2 bash -c 'until ! nc -z 127.0.0.1 8080; do sleep 1; done'`, "", "", 0) @@ -1221,14 +1218,14 @@ func TestModulesAdv_ModuleWaitFor_Good_WaitsForPortStopped(t *testing.T) { "timeout": 2, }) - require.NoError(t, err) - assert.NotNil(t, result) - assert.False(t, result.Failed) - assert.False(t, result.Changed) - assert.True(t, mock.hasExecuted(`until ! nc -z 127.0.0.1 8080`)) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Failed) + core.AssertFalse(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`until ! nc -z 127.0.0.1 8080`)) } -func TestModulesAdv_ModuleWaitFor_Good_WaitsForPortDrained(t *testing.T) { +func TestModulesAdv_ModuleWaitFor_Good_WaitsForPortDrained(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`timeout 2 bash -c 'until ! ss -Htan state established`, "", "", 0) @@ -1239,14 +1236,14 @@ func TestModulesAdv_ModuleWaitFor_Good_WaitsForPortDrained(t *testing.T) { "timeout": 2, }) - require.NoError(t, err) - assert.NotNil(t, result) - assert.False(t, result.Failed) - assert.False(t, result.Changed) - assert.True(t, mock.hasExecuted(`ss -Htan state established`)) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Failed) + core.AssertFalse(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`ss -Htan state established`)) } -func TestModulesAdv_ModuleWaitFor_Good_UsesCustomSleepInterval(t *testing.T) { +func TestModulesAdv_ModuleWaitFor_Good_UsesCustomSleepInterval(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/tmp/slow-ready", []byte("ready=false\n")) @@ -1266,14 +1263,14 @@ func TestModulesAdv_ModuleWaitFor_Good_UsesCustomSleepInterval(t *testing.T) { }) elapsed := time.Since(start) - require.NoError(t, err) - assert.NotNil(t, result) - assert.False(t, result.Failed) - assert.False(t, result.Changed) - assert.GreaterOrEqual(t, elapsed, 2*time.Second) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Failed) + core.AssertFalse(t, result.Changed) + core.AssertGreaterOrEqual(t, elapsed, 2*time.Second) } -func TestModulesAdv_ModuleWaitFor_Good_UsesCustomSleepInPortLoop(t *testing.T) { +func TestModulesAdv_ModuleWaitFor_Good_UsesCustomSleepInPortLoop(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`timeout 5 bash -c 'until nc -z 127.0.0.1 8080; do sleep 3; done'`, "", "", 0) @@ -1285,14 +1282,14 @@ func TestModulesAdv_ModuleWaitFor_Good_UsesCustomSleepInPortLoop(t *testing.T) { "sleep": 3, }) - require.NoError(t, err) - assert.NotNil(t, result) - assert.False(t, result.Failed) - assert.False(t, result.Changed) - assert.True(t, mock.hasExecuted(`sleep 3`)) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Failed) + core.AssertFalse(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`sleep 3`)) } -func TestModulesAdv_ModuleWaitFor_Good_AcceptsStringNumericArgs(t *testing.T) { +func TestModulesAdv_ModuleWaitFor_Good_AcceptsStringNumericArgs(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`timeout 0 bash -c 'until ! nc -z 127.0.0.1 8080; do sleep 1; done'`, "", "", 0) @@ -1303,11 +1300,11 @@ func TestModulesAdv_ModuleWaitFor_Good_AcceptsStringNumericArgs(t *testing.T) { "timeout": "0", }) - require.NoError(t, err) - assert.NotNil(t, result) - assert.False(t, result.Failed) - assert.False(t, result.Changed) - assert.True(t, mock.hasExecuted(`until ! nc -z 127.0.0.1 8080`)) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Failed) + core.AssertFalse(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`until ! nc -z 127.0.0.1 8080`)) } // --- wait_for_connection module --- @@ -1323,7 +1320,7 @@ func (c *deadlineAwareMockClient) Run(ctx context.Context, cmd string) (string, return c.MockSSHClient.Run(ctx, cmd) } -func TestModulesAdv_ModuleWaitForConnection_Good_ReturnsWhenHostIsReachable(t *testing.T) { +func TestModulesAdv_ModuleWaitForConnection_Good_ReturnsWhenHostIsReachable(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`^true$`, "", "", 0) @@ -1334,14 +1331,14 @@ func TestModulesAdv_ModuleWaitForConnection_Good_ReturnsWhenHostIsReachable(t *t }, }) - require.NoError(t, err) - assert.NotNil(t, result) - assert.False(t, result.Failed) - assert.False(t, result.Changed) - assert.True(t, mock.hasExecuted(`^true$`)) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Failed) + core.AssertFalse(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`^true$`)) } -func TestModulesAdv_ModuleWaitForConnection_Good_UsesConnectTimeout(t *testing.T) { +func TestModulesAdv_ModuleWaitForConnection_Good_UsesConnectTimeout(t *core.T) { e := NewExecutor("/tmp") client := &deadlineAwareMockClient{MockSSHClient: NewMockSSHClient()} @@ -1350,16 +1347,16 @@ func TestModulesAdv_ModuleWaitForConnection_Good_UsesConnectTimeout(t *testing.T "connect_timeout": 1, }) - require.NoError(t, err) - require.NotNil(t, result) - assert.False(t, result.Failed) - assert.False(t, result.Changed) - assert.True(t, client.hasExecuted(`^true$`)) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Failed) + core.AssertFalse(t, result.Changed) + core.AssertTrue(t, client.hasExecuted(`^true$`)) } -func TestModulesAdv_ModuleWaitForConnection_Bad_ImmediateFailure(t *testing.T) { +func TestModulesAdv_ModuleWaitForConnection_Bad_ImmediateFailure(t *core.T) { e, mock := newTestExecutorWithMock("host1") - mock.expectCommandError(`^true$`, assert.AnError) + mock.expectCommandError(`^true$`, core.AnError) result, err := executeModuleWithMock(e, mock, "host1", &Task{ Module: "ansible.builtin.wait_for_connection", @@ -1368,19 +1365,19 @@ func TestModulesAdv_ModuleWaitForConnection_Bad_ImmediateFailure(t *testing.T) { }, }) - require.NoError(t, err) - assert.NotNil(t, result) - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, assert.AnError.Error()) - assert.True(t, mock.hasExecuted(`^true$`)) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, core.AnError.Error()) + core.AssertTrue(t, mock.hasExecuted(`^true$`)) } // --- include_vars module --- -func TestModulesAdv_ModuleIncludeVars_Good_LoadSingleFile(t *testing.T) { +func TestModulesAdv_ModuleIncludeVars_Good_LoadSingleFile(t *core.T) { dir := t.TempDir() varsPath := joinPath(dir, "vars.yml") - require.NoError(t, writeTestFile(varsPath, []byte("app_name: demo\napp_port: 8080\nnested:\n enabled: true\n"), 0644)) + core.RequireNoError(t, writeTestFile(varsPath, []byte("app_name: demo\napp_port: 8080\nnested:\n enabled: true\n"), 0644)) e := NewExecutor("/tmp") @@ -1388,25 +1385,25 @@ func TestModulesAdv_ModuleIncludeVars_Good_LoadSingleFile(t *testing.T) { "file": varsPath, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.Contains(t, result.Msg, varsPath) - require.NotNil(t, result.Data) - require.Contains(t, result.Data, "ansible_included_var_files") - assert.Equal(t, []string{varsPath}, result.Data["ansible_included_var_files"]) - assert.Equal(t, "demo", e.vars["app_name"]) - assert.Equal(t, 8080, e.vars["app_port"]) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertContains(t, result.Msg, varsPath) + core.AssertNotNil(t, result.Data) + core.AssertContains(t, result.Data, "ansible_included_var_files") + core.AssertEqual(t, []string{varsPath}, result.Data["ansible_included_var_files"]) + core.AssertEqual(t, "demo", e.vars["app_name"]) + core.AssertEqual(t, 8080, e.vars["app_port"]) nested, ok := e.vars["nested"].(map[string]any) - require.True(t, ok) - assert.Equal(t, true, nested["enabled"]) + core.RequireTrue(t, ok) + core.AssertEqual(t, true, nested["enabled"]) } -func TestModulesAdv_ModuleIncludeVars_Good_LoadJSONFileByDefault(t *testing.T) { +func TestModulesAdv_ModuleIncludeVars_Good_LoadJSONFileByDefault(t *core.T) { dir := t.TempDir() varsPath := joinPath(dir, "vars.json") - require.NoError(t, writeTestFile(varsPath, []byte(`{"app_name":"demo","app_port":8080}`), 0644)) + core.RequireNoError(t, writeTestFile(varsPath, []byte(`{"app_name":"demo","app_port":8080}`), 0644)) e := NewExecutor("/tmp") @@ -1414,17 +1411,17 @@ func TestModulesAdv_ModuleIncludeVars_Good_LoadJSONFileByDefault(t *testing.T) { "file": varsPath, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.Equal(t, "demo", e.vars["app_name"]) - assert.Equal(t, 8080, e.vars["app_port"]) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, "demo", e.vars["app_name"]) + core.AssertEqual(t, 8080, e.vars["app_port"]) } -func TestModulesAdv_ModuleIncludeVars_Good_CustomExtensionsFilter(t *testing.T) { +func TestModulesAdv_ModuleIncludeVars_Good_CustomExtensionsFilter(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "01-ignored.yml"), []byte("ignored_value: false\n"), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "02-selected.vars"), []byte("selected_value: included\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "01-ignored.yml"), []byte("ignored_value: false\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "02-selected.vars"), []byte("selected_value: included\n"), 0644)) e := NewExecutor("/tmp") @@ -1433,19 +1430,19 @@ func TestModulesAdv_ModuleIncludeVars_Good_CustomExtensionsFilter(t *testing.T) "extensions": []any{"vars"}, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "included", e.vars["selected_value"]) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "included", e.vars["selected_value"]) _, hasIgnored := e.vars["ignored_value"] - assert.False(t, hasIgnored) - assert.Contains(t, result.Msg, joinPath(dir, "02-selected.vars")) - assert.NotContains(t, result.Msg, joinPath(dir, "01-ignored.yml")) + core.AssertFalse(t, hasIgnored) + core.AssertContains(t, result.Msg, joinPath(dir, "02-selected.vars")) + core.AssertNotContains(t, result.Msg, joinPath(dir, "01-ignored.yml")) } -func TestModulesAdv_ModuleIncludeVars_Good_LoadExtensionlessFilesWhenRequested(t *testing.T) { +func TestModulesAdv_ModuleIncludeVars_Good_LoadExtensionlessFilesWhenRequested(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "vars"), []byte("app_name: demo\n"), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "ignored.txt"), []byte("ignored_value: true\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "vars"), []byte("app_name: demo\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "ignored.txt"), []byte("ignored_value: true\n"), 0644)) e := NewExecutor("/tmp") @@ -1454,19 +1451,19 @@ func TestModulesAdv_ModuleIncludeVars_Good_LoadExtensionlessFilesWhenRequested(t "extensions": []any{"", "yml", "yaml", "json"}, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "demo", e.vars["app_name"]) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "demo", e.vars["app_name"]) _, hasIgnored := e.vars["ignored_value"] - assert.False(t, hasIgnored) - assert.Contains(t, result.Msg, joinPath(dir, "vars")) - assert.NotContains(t, result.Msg, joinPath(dir, "ignored.txt")) + core.AssertFalse(t, hasIgnored) + core.AssertContains(t, result.Msg, joinPath(dir, "vars")) + core.AssertNotContains(t, result.Msg, joinPath(dir, "ignored.txt")) } -func TestModulesAdv_ModuleIncludeVars_Good_LoadDirectoryWithMerge(t *testing.T) { +func TestModulesAdv_ModuleIncludeVars_Good_LoadDirectoryWithMerge(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "01-base.yml"), []byte("app_name: demo\nnested:\n a: 1\n"), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "02-override.yaml"), []byte("app_port: 8080\nnested:\n b: 2\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "01-base.yml"), []byte("app_name: demo\nnested:\n a: 1\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "02-override.yaml"), []byte("app_port: 8080\nnested:\n b: 2\n"), 0644)) e := NewExecutor("/tmp") @@ -1475,29 +1472,29 @@ func TestModulesAdv_ModuleIncludeVars_Good_LoadDirectoryWithMerge(t *testing.T) "hash_behaviour": "merge", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.Contains(t, result.Msg, joinPath(dir, "01-base.yml")) - assert.Contains(t, result.Msg, joinPath(dir, "02-override.yaml")) - require.NotNil(t, result.Data) - assert.Equal(t, []string{ + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertContains(t, result.Msg, joinPath(dir, "01-base.yml")) + core.AssertContains(t, result.Msg, joinPath(dir, "02-override.yaml")) + core.AssertNotNil(t, result.Data) + core.AssertEqual(t, []string{ joinPath(dir, "01-base.yml"), joinPath(dir, "02-override.yaml"), }, result.Data["ansible_included_var_files"]) - assert.Equal(t, "demo", e.vars["app_name"]) - assert.Equal(t, 8080, e.vars["app_port"]) + core.AssertEqual(t, "demo", e.vars["app_name"]) + core.AssertEqual(t, 8080, e.vars["app_port"]) nested, ok := e.vars["nested"].(map[string]any) - require.True(t, ok) - assert.Equal(t, 1, nested["a"]) - assert.Equal(t, 2, nested["b"]) + core.RequireTrue(t, ok) + core.AssertEqual(t, 1, nested["a"]) + core.AssertEqual(t, 2, nested["b"]) } -func TestModulesAdv_ModuleIncludeVars_Good_ResolvesRelativePathsAgainstBasePath(t *testing.T) { +func TestModulesAdv_ModuleIncludeVars_Good_ResolvesRelativePathsAgainstBasePath(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "vars.yml"), []byte("app_name: demo\n"), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "vars", "01-extra.yaml"), []byte("app_port: 8080\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "vars.yml"), []byte("app_name: demo\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "vars", "01-extra.yaml"), []byte("app_port: 8080\n"), 0644)) e := NewExecutor(dir) @@ -1506,19 +1503,19 @@ func TestModulesAdv_ModuleIncludeVars_Good_ResolvesRelativePathsAgainstBasePath( "dir": "vars", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Contains(t, result.Msg, "vars.yml") - assert.Contains(t, result.Msg, joinPath(dir, "vars", "01-extra.yaml")) - assert.Equal(t, "demo", e.vars["app_name"]) - assert.Equal(t, 8080, e.vars["app_port"]) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertContains(t, result.Msg, "vars.yml") + core.AssertContains(t, result.Msg, joinPath(dir, "vars", "01-extra.yaml")) + core.AssertEqual(t, "demo", e.vars["app_name"]) + core.AssertEqual(t, 8080, e.vars["app_port"]) } -func TestModulesAdv_ModuleIncludeVars_Good_RecursesIntoNestedDirectories(t *testing.T) { +func TestModulesAdv_ModuleIncludeVars_Good_RecursesIntoNestedDirectories(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "01-root.yml"), []byte("root_value: root\n"), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "nested", "02-child.yaml"), []byte("child_value: child\n"), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "nested", "deep", "03-grandchild.yml"), []byte("grandchild_value: grandchild\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "01-root.yml"), []byte("root_value: root\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "nested", "02-child.yaml"), []byte("child_value: child\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "nested", "deep", "03-grandchild.yml"), []byte("grandchild_value: grandchild\n"), 0644)) e := NewExecutor("/tmp") @@ -1526,21 +1523,21 @@ func TestModulesAdv_ModuleIncludeVars_Good_RecursesIntoNestedDirectories(t *test "dir": dir, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "root", e.vars["root_value"]) - assert.Equal(t, "child", e.vars["child_value"]) - assert.Equal(t, "grandchild", e.vars["grandchild_value"]) - assert.Contains(t, result.Msg, joinPath(dir, "01-root.yml")) - assert.Contains(t, result.Msg, joinPath(dir, "nested", "02-child.yaml")) - assert.Contains(t, result.Msg, joinPath(dir, "nested", "deep", "03-grandchild.yml")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "root", e.vars["root_value"]) + core.AssertEqual(t, "child", e.vars["child_value"]) + core.AssertEqual(t, "grandchild", e.vars["grandchild_value"]) + core.AssertContains(t, result.Msg, joinPath(dir, "01-root.yml")) + core.AssertContains(t, result.Msg, joinPath(dir, "nested", "02-child.yaml")) + core.AssertContains(t, result.Msg, joinPath(dir, "nested", "deep", "03-grandchild.yml")) } -func TestModulesAdv_ModuleIncludeVars_Good_RespectsDepthLimit(t *testing.T) { +func TestModulesAdv_ModuleIncludeVars_Good_RespectsDepthLimit(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "01-root.yml"), []byte("root_value: root\n"), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "nested", "02-child.yaml"), []byte("child_value: child\n"), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "nested", "deep", "03-grandchild.yml"), []byte("grandchild_value: grandchild\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "01-root.yml"), []byte("root_value: root\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "nested", "02-child.yaml"), []byte("child_value: child\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "nested", "deep", "03-grandchild.yml"), []byte("grandchild_value: grandchild\n"), 0644)) e := NewExecutor("/tmp") @@ -1549,20 +1546,20 @@ func TestModulesAdv_ModuleIncludeVars_Good_RespectsDepthLimit(t *testing.T) { "depth": 1, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "root", e.vars["root_value"]) - assert.Equal(t, "child", e.vars["child_value"]) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "root", e.vars["root_value"]) + core.AssertEqual(t, "child", e.vars["child_value"]) _, hasGrandchild := e.vars["grandchild_value"] - assert.False(t, hasGrandchild) - assert.NotContains(t, result.Msg, joinPath(dir, "nested", "deep", "03-grandchild.yml")) + core.AssertFalse(t, hasGrandchild) + core.AssertNotContains(t, result.Msg, joinPath(dir, "nested", "deep", "03-grandchild.yml")) } -func TestModulesAdv_ModuleIncludeVars_Good_FiltersFilesMatching(t *testing.T) { +func TestModulesAdv_ModuleIncludeVars_Good_FiltersFilesMatching(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "01-base.yml"), []byte("base_value: base\n"), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "02-extra.yaml"), []byte("extra_value: extra\n"), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "notes.txt"), []byte("ignored: true\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "01-base.yml"), []byte("base_value: base\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "02-extra.yaml"), []byte("extra_value: extra\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "notes.txt"), []byte("ignored: true\n"), 0644)) e := NewExecutor("/tmp") @@ -1571,20 +1568,20 @@ func TestModulesAdv_ModuleIncludeVars_Good_FiltersFilesMatching(t *testing.T) { "files_matching": `^02-.*\.ya?ml$`, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "extra", e.vars["extra_value"]) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "extra", e.vars["extra_value"]) _, hasBase := e.vars["base_value"] - assert.False(t, hasBase) - assert.Contains(t, result.Msg, joinPath(dir, "02-extra.yaml")) - assert.NotContains(t, result.Msg, joinPath(dir, "01-base.yml")) + core.AssertFalse(t, hasBase) + core.AssertContains(t, result.Msg, joinPath(dir, "02-extra.yaml")) + core.AssertNotContains(t, result.Msg, joinPath(dir, "01-base.yml")) } -func TestModulesAdv_ModuleIncludeVars_Good_IgnoresNamedFiles(t *testing.T) { +func TestModulesAdv_ModuleIncludeVars_Good_IgnoresNamedFiles(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "01-base.yml"), []byte("base_value: base\n"), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "02-skip.yml"), []byte("skip_value: skipped\n"), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "nested", "02-skip.yml"), []byte("nested_skip_value: skipped\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "01-base.yml"), []byte("base_value: base\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "02-skip.yml"), []byte("skip_value: skipped\n"), 0644)) + core.RequireNoError(t, writeTestFile(joinPath(dir, "nested", "02-skip.yml"), []byte("nested_skip_value: skipped\n"), 0644)) e := NewExecutor("/tmp") @@ -1593,21 +1590,21 @@ func TestModulesAdv_ModuleIncludeVars_Good_IgnoresNamedFiles(t *testing.T) { "ignore_files": []any{"02-skip.yml"}, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "base", e.vars["base_value"]) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "base", e.vars["base_value"]) _, hasSkip := e.vars["skip_value"] - assert.False(t, hasSkip) + core.AssertFalse(t, hasSkip) _, hasNestedSkip := e.vars["nested_skip_value"] - assert.False(t, hasNestedSkip) - assert.Contains(t, result.Msg, joinPath(dir, "01-base.yml")) - assert.NotContains(t, result.Msg, joinPath(dir, "02-skip.yml")) - assert.NotContains(t, result.Msg, joinPath(dir, "nested", "02-skip.yml")) + core.AssertFalse(t, hasNestedSkip) + core.AssertContains(t, result.Msg, joinPath(dir, "01-base.yml")) + core.AssertNotContains(t, result.Msg, joinPath(dir, "02-skip.yml")) + core.AssertNotContains(t, result.Msg, joinPath(dir, "nested", "02-skip.yml")) } // --- sysctl module --- -func TestModulesAdv_ModuleSysctl_Good_ReloadsAfterPersisting(t *testing.T) { +func TestModulesAdv_ModuleSysctl_Good_ReloadsAfterPersisting(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`sysctl -w net.ipv4.ip_forward=1`, "", "", 0) mock.expectCommand(`grep -q .*net.ipv4.ip_forward`, "", "", 0) @@ -1619,14 +1616,14 @@ func TestModulesAdv_ModuleSysctl_Good_ReloadsAfterPersisting(t *testing.T) { "reload": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`sysctl -w net.ipv4.ip_forward=1`)) - assert.True(t, mock.hasExecuted(`sysctl -p`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`sysctl -w net.ipv4.ip_forward=1`)) + core.AssertTrue(t, mock.hasExecuted(`sysctl -p`)) } -func TestModulesAdv_ModuleSysctl_Good_IgnoreErrorsAddsSysctlFlag(t *testing.T) { +func TestModulesAdv_ModuleSysctl_Good_IgnoreErrorsAddsSysctlFlag(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`sysctl -e -w net.ipv4.ip_forward=1`, "", "", 0) mock.expectCommand(`grep -q .*net.ipv4.ip_forward`, "", "", 0) @@ -1639,14 +1636,14 @@ func TestModulesAdv_ModuleSysctl_Good_IgnoreErrorsAddsSysctlFlag(t *testing.T) { "ignoreerrors": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`sysctl -e -w net.ipv4.ip_forward=1`)) - assert.True(t, mock.hasExecuted(`sysctl -e -p`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`sysctl -e -w net.ipv4.ip_forward=1`)) + core.AssertTrue(t, mock.hasExecuted(`sysctl -e -p`)) } -func TestModulesAdv_ModuleSysctl_Good_UsesCustomSysctlFile(t *testing.T) { +func TestModulesAdv_ModuleSysctl_Good_UsesCustomSysctlFile(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`sed -i '/net\\.ipv4\\.ip_forward/d' .*custom\.conf`, "", "", 0) @@ -1656,15 +1653,15 @@ func TestModulesAdv_ModuleSysctl_Good_UsesCustomSysctlFile(t *testing.T) { "sysctl_file": "/etc/sysctl.d/custom.conf", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`sed -i '/net\\.ipv4\\.ip_forward/d' .*custom\.conf`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`sed -i '/net\\.ipv4\\.ip_forward/d' .*custom\.conf`)) } // --- uri module --- -func TestModulesAdv_ModuleURI_Good_GetRequestDefault(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_GetRequestDefault(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl.*https://example.com/api/health`, "OK\n200", "", 0) @@ -1672,15 +1669,15 @@ func TestModulesAdv_ModuleURI_Good_GetRequestDefault(t *testing.T) { "url": "https://example.com/api/health", }) - require.NoError(t, err) - assert.False(t, result.Failed) - assert.False(t, result.Changed) // URI module does not set changed - assert.Equal(t, 200, result.RC) - assert.Equal(t, 200, result.Data["status"]) - assert.True(t, mock.containsSubstring("-L")) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertFalse(t, result.Changed) // URI module does not set changed + core.AssertEqual(t, 200, result.RC) + core.AssertEqual(t, 200, result.Data["status"]) + core.AssertTrue(t, mock.containsSubstring("-L")) } -func TestModulesAdv_ModuleURI_Good_DisablesRedirectFollowing(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_DisablesRedirectFollowing(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl.*https://example.com/api/health`, "OK\n200", "", 0) @@ -1689,16 +1686,16 @@ func TestModulesAdv_ModuleURI_Good_DisablesRedirectFollowing(t *testing.T) { "follow_redirects": "none", }) - require.NoError(t, err) - assert.False(t, result.Failed) - assert.False(t, result.Changed) - assert.Equal(t, 200, result.RC) - assert.Equal(t, 200, result.Data["status"]) - assert.True(t, mock.containsSubstring("--max-redirs 0")) - assert.False(t, mock.containsSubstring("-L")) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertFalse(t, result.Changed) + core.AssertEqual(t, 200, result.RC) + core.AssertEqual(t, 200, result.Data["status"]) + core.AssertTrue(t, mock.containsSubstring("--max-redirs 0")) + core.AssertFalse(t, mock.containsSubstring("-L")) } -func TestModulesAdv_ModuleURI_Good_PostWithBodyAndHeaders(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_PostWithBodyAndHeaders(t *core.T) { e, mock := newTestExecutorWithMock("host1") // Use a broad pattern since header order in map iteration is non-deterministic mock.expectCommand(`curl.*api\.example\.com`, "{\"id\":1}\n201", "", 0) @@ -1714,16 +1711,16 @@ func TestModulesAdv_ModuleURI_Good_PostWithBodyAndHeaders(t *testing.T) { }, }) - require.NoError(t, err) - assert.False(t, result.Failed) - assert.Equal(t, 201, result.RC) - assert.True(t, mock.containsSubstring("-X POST")) - assert.True(t, mock.containsSubstring("-d")) - assert.True(t, mock.containsSubstring("Content-Type")) - assert.True(t, mock.containsSubstring("Authorization")) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, 201, result.RC) + core.AssertTrue(t, mock.containsSubstring("-X POST")) + core.AssertTrue(t, mock.containsSubstring("-d")) + core.AssertTrue(t, mock.containsSubstring("Content-Type")) + core.AssertTrue(t, mock.containsSubstring("Authorization")) } -func TestModulesAdv_ModuleURI_Good_UsesBasicAuthFlags(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_UsesBasicAuthFlags(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl.*secure\.example\.com`, "OK\n200", "", 0) @@ -1734,14 +1731,14 @@ func TestModulesAdv_ModuleURI_Good_UsesBasicAuthFlags(t *testing.T) { "force_basic_auth": true, }) - require.NoError(t, err) - assert.False(t, result.Failed) - assert.Equal(t, 200, result.RC) - assert.True(t, mock.hasExecuted(`-u .*apiuser:apipass`)) - assert.True(t, mock.hasExecuted(`--basic`)) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, 200, result.RC) + core.AssertTrue(t, mock.hasExecuted(`-u .*apiuser:apipass`)) + core.AssertTrue(t, mock.hasExecuted(`--basic`)) } -func TestModulesAdv_ModuleURI_Good_UsesUnixSocket(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_UsesUnixSocket(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl.*http://localhost/_ping`, "OK\n200", "", 0) @@ -1750,13 +1747,13 @@ func TestModulesAdv_ModuleURI_Good_UsesUnixSocket(t *testing.T) { "unix_socket": "/var/run/docker.sock", }) - require.NoError(t, err) - assert.False(t, result.Failed) - assert.Equal(t, 200, result.RC) - assert.True(t, mock.hasExecuted(`--unix-socket '/var/run/docker.sock'`)) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, 200, result.RC) + core.AssertTrue(t, mock.hasExecuted(`--unix-socket '/var/run/docker.sock'`)) } -func TestModulesAdv_ModuleURI_Good_DisablesProxyUsage(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_DisablesProxyUsage(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl.*https://example.com/api/health`, "OK\n200", "", 0) @@ -1765,15 +1762,15 @@ func TestModulesAdv_ModuleURI_Good_DisablesProxyUsage(t *testing.T) { "use_proxy": false, }) - require.NoError(t, err) - assert.False(t, result.Failed) - assert.Equal(t, 200, result.RC) - assert.True(t, mock.hasExecuted(`--noproxy`)) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, 200, result.RC) + core.AssertTrue(t, mock.hasExecuted(`--noproxy`)) } -func TestModulesAdv_ModuleURI_Good_UsesSourceFileBody(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_UsesSourceFileBody(t *core.T) { e, mock := newTestExecutorWithMock("host1") - require.NoError(t, mock.Upload(context.Background(), newReader("alpha=1&beta=2"), "/tmp/request-body.txt", 0644)) + core.RequireNoError(t, mock.Upload(context.Background(), newReader("alpha=1&beta=2"), "/tmp/request-body.txt", 0644)) mock.expectCommand(`curl.*form\.example\.com`, "created\n201", "", 0) result, err := moduleURIWithClient(e, mock, map[string]any{ @@ -1784,14 +1781,14 @@ func TestModulesAdv_ModuleURI_Good_UsesSourceFileBody(t *testing.T) { "status_code": 201, }) - require.NoError(t, err) - assert.False(t, result.Failed) - assert.Equal(t, 201, result.RC) - assert.True(t, mock.containsSubstring(`-d "alpha=1&beta=2"`)) - assert.False(t, mock.containsSubstring("Content-Type: application/json")) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, 201, result.RC) + core.AssertTrue(t, mock.containsSubstring(`-d "alpha=1&beta=2"`)) + core.AssertFalse(t, mock.containsSubstring("Content-Type: application/json")) } -func TestModulesAdv_ModuleURI_Good_FormURLEncodedBody(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_FormURLEncodedBody(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl.*form\.example\.com`, "created\n201", "", 0) @@ -1806,14 +1803,14 @@ func TestModulesAdv_ModuleURI_Good_FormURLEncodedBody(t *testing.T) { "status_code": 201, }) - require.NoError(t, err) - assert.False(t, result.Failed) - assert.Equal(t, 201, result.RC) - assert.True(t, mock.containsSubstring(`-d "name=Alice+Example&scope=read&scope=write"`)) - assert.True(t, mock.containsSubstring("Content-Type: application/x-www-form-urlencoded")) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, 201, result.RC) + core.AssertTrue(t, mock.containsSubstring(`-d "name=Alice+Example&scope=read&scope=write"`)) + core.AssertTrue(t, mock.containsSubstring("Content-Type: application/x-www-form-urlencoded")) } -func TestModulesAdv_ModuleURI_Good_FormMultipartBody(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_FormMultipartBody(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl.*form\.example\.com`, "created\n201", "", 0) @@ -1828,17 +1825,17 @@ func TestModulesAdv_ModuleURI_Good_FormMultipartBody(t *testing.T) { "status_code": 201, }) - require.NoError(t, err) - assert.False(t, result.Failed) - assert.Equal(t, 201, result.RC) - assert.True(t, mock.containsSubstring(`-F "name=Alice Example"`)) - assert.True(t, mock.containsSubstring(`-F "scope=read"`)) - assert.True(t, mock.containsSubstring(`-F "scope=write"`)) - assert.False(t, mock.containsSubstring("Content-Type: application/json")) - assert.False(t, mock.containsSubstring("Content-Type: application/x-www-form-urlencoded")) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, 201, result.RC) + core.AssertTrue(t, mock.containsSubstring(`-F "name=Alice Example"`)) + core.AssertTrue(t, mock.containsSubstring(`-F "scope=read"`)) + core.AssertTrue(t, mock.containsSubstring(`-F "scope=write"`)) + core.AssertFalse(t, mock.containsSubstring("Content-Type: application/json")) + core.AssertFalse(t, mock.containsSubstring("Content-Type: application/x-www-form-urlencoded")) } -func TestModulesAdv_ModuleURI_Good_WrongStatusCode(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_WrongStatusCode(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl`, "Not Found\n404", "", 0) @@ -1846,25 +1843,25 @@ func TestModulesAdv_ModuleURI_Good_WrongStatusCode(t *testing.T) { "url": "https://example.com/missing", }) - require.NoError(t, err) - assert.True(t, result.Failed) // Expected 200, got 404 - assert.Equal(t, 404, result.RC) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) // Expected 200, got 404 + core.AssertEqual(t, 404, result.RC) } -func TestModulesAdv_ModuleURI_Good_CurlCommandFailure(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_CurlCommandFailure(t *core.T) { e, mock := newTestExecutorWithMock("host1") - mock.expectCommandError(`curl`, assert.AnError) + mock.expectCommandError(`curl`, core.AnError) result, err := moduleURIWithClient(e, mock, map[string]any{ "url": "https://unreachable.example.com", }) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, assert.AnError.Error()) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, core.AnError.Error()) } -func TestModulesAdv_ModuleURI_Good_CustomExpectedStatus(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_CustomExpectedStatus(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl`, "\n204", "", 0) @@ -1874,12 +1871,12 @@ func TestModulesAdv_ModuleURI_Good_CustomExpectedStatus(t *testing.T) { "status_code": 204, }) - require.NoError(t, err) - assert.False(t, result.Failed) - assert.Equal(t, 204, result.RC) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, 204, result.RC) } -func TestModulesAdv_ModuleURI_Good_ReturnContent(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_ReturnContent(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl`, "{\"ok\":true}\n200", "", 0) @@ -1889,14 +1886,14 @@ func TestModulesAdv_ModuleURI_Good_ReturnContent(t *testing.T) { "status_code": 200, }) - require.NoError(t, err) - assert.False(t, result.Failed) - require.NotNil(t, result.Data) - assert.Equal(t, "{\"ok\":true}", result.Data["content"]) - assert.Equal(t, 200, result.Data["status"]) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertNotNil(t, result.Data) + core.AssertEqual(t, "{\"ok\":true}", result.Data["content"]) + core.AssertEqual(t, 200, result.Data["status"]) } -func TestModulesAdv_ModuleURI_Good_WritesResponseToDest(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_WritesResponseToDest(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl`, "{\"ok\":true}\n200", "", 0) @@ -1905,18 +1902,18 @@ func TestModulesAdv_ModuleURI_Good_WritesResponseToDest(t *testing.T) { "dest": "/tmp/api-status.json", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - require.NotNil(t, result.Data) - assert.Equal(t, "/tmp/api-status.json", result.Data["dest"]) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertNotNil(t, result.Data) + core.AssertEqual(t, "/tmp/api-status.json", result.Data["dest"]) content, err := mock.Download(context.Background(), "/tmp/api-status.json") - require.NoError(t, err) - assert.Equal(t, []byte("{\"ok\":true}"), content) + core.RequireNoError(t, err) + core.AssertEqual(t, []byte("{\"ok\":true}"), content) } -func TestModulesAdv_ModuleURI_Good_JSONBodyFormat(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_JSONBodyFormat(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl`, "{\"created\":true}\n201", "", 0) @@ -1930,14 +1927,14 @@ func TestModulesAdv_ModuleURI_Good_JSONBodyFormat(t *testing.T) { "status_code": 201, }) - require.NoError(t, err) - assert.False(t, result.Failed) - assert.Equal(t, 201, result.RC) - assert.True(t, mock.containsSubstring(`-d "{\"name\":\"test\"}"`)) - assert.True(t, mock.containsSubstring("Content-Type: application/json")) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, 201, result.RC) + core.AssertTrue(t, mock.containsSubstring(`-d "{\"name\":\"test\"}"`)) + core.AssertTrue(t, mock.containsSubstring("Content-Type: application/json")) } -func TestModulesAdv_ModuleURI_Good_TimeoutAndInsecureSkipVerify(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_TimeoutAndInsecureSkipVerify(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl`, "OK\n200", "", 0) @@ -1947,14 +1944,14 @@ func TestModulesAdv_ModuleURI_Good_TimeoutAndInsecureSkipVerify(t *testing.T) { "validate_certs": false, }) - require.NoError(t, err) - assert.False(t, result.Failed) - assert.Equal(t, 200, result.RC) - assert.True(t, mock.containsSubstring("-k")) - assert.True(t, mock.containsSubstring("--max-time 15")) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, 200, result.RC) + core.AssertTrue(t, mock.containsSubstring("-k")) + core.AssertTrue(t, mock.containsSubstring("--max-time 15")) } -func TestModulesAdv_ModuleURI_Good_MultipleExpectedStatuses(t *testing.T) { +func TestModulesAdv_ModuleURI_Good_MultipleExpectedStatuses(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl`, "\n202", "", 0) @@ -1963,13 +1960,13 @@ func TestModulesAdv_ModuleURI_Good_MultipleExpectedStatuses(t *testing.T) { "status_code": []any{200, 202, 204}, }) - require.NoError(t, err) - assert.False(t, result.Failed) - assert.Equal(t, 202, result.RC) - assert.Equal(t, 202, result.Data["status"]) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, 202, result.RC) + core.AssertEqual(t, 202, result.Data["status"]) } -func TestModulesAdv_ModuleURI_Bad_MissingURL(t *testing.T) { +func TestModulesAdv_ModuleURI_Bad_MissingURL(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() @@ -1977,13 +1974,13 @@ func TestModulesAdv_ModuleURI_Bad_MissingURL(t *testing.T) { "method": "GET", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "url required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "url required") } // --- ufw module --- -func TestModulesAdv_ModuleUFW_Good_AllowRuleWithPort(t *testing.T) { +func TestModulesAdv_ModuleUFW_Good_AllowRuleWithPort(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`ufw allow 443/tcp`, "Rule added", "", 0) @@ -1992,13 +1989,13 @@ func TestModulesAdv_ModuleUFW_Good_AllowRuleWithPort(t *testing.T) { "port": "443", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`ufw allow 443/tcp`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`ufw allow 443/tcp`)) } -func TestModulesAdv_ModuleUFW_Good_EnableFirewall(t *testing.T) { +func TestModulesAdv_ModuleUFW_Good_EnableFirewall(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`ufw --force enable`, "Firewall is active", "", 0) @@ -2006,13 +2003,13 @@ func TestModulesAdv_ModuleUFW_Good_EnableFirewall(t *testing.T) { "state": "enabled", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`ufw --force enable`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`ufw --force enable`)) } -func TestModulesAdv_ModuleUFW_Good_DenyRuleWithProto(t *testing.T) { +func TestModulesAdv_ModuleUFW_Good_DenyRuleWithProto(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`ufw deny 53/udp`, "Rule added", "", 0) @@ -2022,13 +2019,13 @@ func TestModulesAdv_ModuleUFW_Good_DenyRuleWithProto(t *testing.T) { "proto": "udp", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`ufw deny 53/udp`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`ufw deny 53/udp`)) } -func TestModulesAdv_ModuleUFW_Good_ResetFirewall(t *testing.T) { +func TestModulesAdv_ModuleUFW_Good_ResetFirewall(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`ufw --force reset`, "Resetting", "", 0) @@ -2036,13 +2033,13 @@ func TestModulesAdv_ModuleUFW_Good_ResetFirewall(t *testing.T) { "state": "reset", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`ufw --force reset`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`ufw --force reset`)) } -func TestModulesAdv_ModuleUFW_Good_DisableFirewall(t *testing.T) { +func TestModulesAdv_ModuleUFW_Good_DisableFirewall(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`ufw disable`, "Firewall stopped", "", 0) @@ -2050,13 +2047,13 @@ func TestModulesAdv_ModuleUFW_Good_DisableFirewall(t *testing.T) { "state": "disabled", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`ufw disable`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`ufw disable`)) } -func TestModulesAdv_ModuleUFW_Good_ReloadFirewall(t *testing.T) { +func TestModulesAdv_ModuleUFW_Good_ReloadFirewall(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`ufw reload`, "Firewall reloaded", "", 0) @@ -2064,13 +2061,13 @@ func TestModulesAdv_ModuleUFW_Good_ReloadFirewall(t *testing.T) { "state": "reloaded", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`ufw reload`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`ufw reload`)) } -func TestModulesAdv_ModuleUFW_Good_LimitRule(t *testing.T) { +func TestModulesAdv_ModuleUFW_Good_LimitRule(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`ufw limit 22/tcp`, "Rule added", "", 0) @@ -2079,13 +2076,13 @@ func TestModulesAdv_ModuleUFW_Good_LimitRule(t *testing.T) { "port": "22", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`ufw limit 22/tcp`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`ufw limit 22/tcp`)) } -func TestModulesAdv_ModuleUFW_Good_DeleteRule(t *testing.T) { +func TestModulesAdv_ModuleUFW_Good_DeleteRule(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`ufw delete allow 443/tcp`, "Rule deleted", "", 0) @@ -2095,13 +2092,13 @@ func TestModulesAdv_ModuleUFW_Good_DeleteRule(t *testing.T) { "delete": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`ufw delete allow 443/tcp`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`ufw delete allow 443/tcp`)) } -func TestModulesAdv_ModuleUFW_Good_LoggingMode(t *testing.T) { +func TestModulesAdv_ModuleUFW_Good_LoggingMode(t *core.T) { e := NewExecutor("/tmp") mock := NewMockSSHClient() mock.expectCommand(`ufw logging high`, "Logging enabled\n", "", 0) @@ -2115,14 +2112,14 @@ func TestModulesAdv_ModuleUFW_Good_LoggingMode(t *testing.T) { result, err := e.executeModule(context.Background(), "host1", mock, task, &Play{}) - require.NoError(t, err) - require.NotNil(t, result) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`ufw logging high`)) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`ufw logging high`)) } -func TestModulesAdv_ModuleUFW_Good_BuiltinAliasDispatch(t *testing.T) { +func TestModulesAdv_ModuleUFW_Good_BuiltinAliasDispatch(t *core.T) { e := NewExecutor("/tmp") mock := NewMockSSHClient() mock.expectCommand(`ufw --force enable`, "", "", 0) @@ -2136,14 +2133,14 @@ func TestModulesAdv_ModuleUFW_Good_BuiltinAliasDispatch(t *testing.T) { result, err := e.executeModule(context.Background(), "host1", mock, task, &Play{}) - require.NoError(t, err) - require.NotNil(t, result) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`ufw --force enable`)) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`ufw --force enable`)) } -func TestModulesAdv_ModuleUFW_Good_StateCommandFailure(t *testing.T) { +func TestModulesAdv_ModuleUFW_Good_StateCommandFailure(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`ufw --force enable`, "", "ERROR: problem running ufw", 1) @@ -2151,13 +2148,13 @@ func TestModulesAdv_ModuleUFW_Good_StateCommandFailure(t *testing.T) { "state": "enabled", }) - require.NoError(t, err) - assert.True(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) } // --- docker_compose module --- -func TestModulesAdv_ModuleDockerCompose_Good_StatePresent(t *testing.T) { +func TestModulesAdv_ModuleDockerCompose_Good_StatePresent(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`docker compose up -d`, "Creating container_1\nCreating container_2\n", "", 0) @@ -2166,14 +2163,14 @@ func TestModulesAdv_ModuleDockerCompose_Good_StatePresent(t *testing.T) { "state": "present", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`docker compose up -d`)) - assert.True(t, mock.containsSubstring("/opt/myapp")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`docker compose up -d`)) + core.AssertTrue(t, mock.containsSubstring("/opt/myapp")) } -func TestModulesAdv_ModuleDockerCompose_Good_StateAbsent(t *testing.T) { +func TestModulesAdv_ModuleDockerCompose_Good_StateAbsent(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`docker compose down`, "Removing container_1\n", "", 0) @@ -2182,13 +2179,13 @@ func TestModulesAdv_ModuleDockerCompose_Good_StateAbsent(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`docker compose down`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`docker compose down`)) } -func TestModulesAdv_ModuleDockerCompose_Good_StateStopped(t *testing.T) { +func TestModulesAdv_ModuleDockerCompose_Good_StateStopped(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`docker compose stop`, "Stopping container_1\n", "", 0) @@ -2197,13 +2194,13 @@ func TestModulesAdv_ModuleDockerCompose_Good_StateStopped(t *testing.T) { "state": "stopped", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`docker compose stop`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`docker compose stop`)) } -func TestModulesAdv_ModuleDockerCompose_Good_AlreadyUpToDate(t *testing.T) { +func TestModulesAdv_ModuleDockerCompose_Good_AlreadyUpToDate(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`docker compose up -d`, "Container myapp-web-1 Up to date\n", "", 0) @@ -2212,12 +2209,12 @@ func TestModulesAdv_ModuleDockerCompose_Good_AlreadyUpToDate(t *testing.T) { "state": "present", }) - require.NoError(t, err) - assert.False(t, result.Changed) // "Up to date" in stdout → changed=false - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) // "Up to date" in stdout → changed=false + core.AssertFalse(t, result.Failed) } -func TestModulesAdv_ModuleDockerCompose_Good_StateRestarted(t *testing.T) { +func TestModulesAdv_ModuleDockerCompose_Good_StateRestarted(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`docker compose restart`, "Restarting container_1\n", "", 0) @@ -2226,13 +2223,13 @@ func TestModulesAdv_ModuleDockerCompose_Good_StateRestarted(t *testing.T) { "state": "restarted", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`docker compose restart`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`docker compose restart`)) } -func TestModulesAdv_ModuleDockerCompose_Bad_MissingProjectSrc(t *testing.T) { +func TestModulesAdv_ModuleDockerCompose_Bad_MissingProjectSrc(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() @@ -2240,11 +2237,11 @@ func TestModulesAdv_ModuleDockerCompose_Bad_MissingProjectSrc(t *testing.T) { "state": "present", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "project_src required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "project_src required") } -func TestModulesAdv_ModuleDockerCompose_Good_CommandFailure(t *testing.T) { +func TestModulesAdv_ModuleDockerCompose_Good_CommandFailure(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`docker compose up -d`, "", "Error response from daemon", 1) @@ -2253,12 +2250,12 @@ func TestModulesAdv_ModuleDockerCompose_Good_CommandFailure(t *testing.T) { "state": "present", }) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, "Error response from daemon") + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, "Error response from daemon") } -func TestModulesAdv_ModuleDockerCompose_Good_DefaultStateIsPresent(t *testing.T) { +func TestModulesAdv_ModuleDockerCompose_Good_DefaultStateIsPresent(t *core.T) { // When no state is specified, default is "present" e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`docker compose up -d`, "Starting\n", "", 0) @@ -2267,13 +2264,13 @@ func TestModulesAdv_ModuleDockerCompose_Good_DefaultStateIsPresent(t *testing.T) "project_src": "/opt/app", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`docker compose up -d`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`docker compose up -d`)) } -func TestModulesAdv_ModuleDockerCompose_Good_ProjectNameAndFiles(t *testing.T) { +func TestModulesAdv_ModuleDockerCompose_Good_ProjectNameAndFiles(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`docker compose -p 'demo-app' -f 'docker-compose.yml' -f 'docker-compose.prod.yml' up -d`, "Starting\n", "", 0) @@ -2283,13 +2280,13 @@ func TestModulesAdv_ModuleDockerCompose_Good_ProjectNameAndFiles(t *testing.T) { "files": []any{"docker-compose.yml", "docker-compose.prod.yml"}, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring("docker compose -p 'demo-app' -f 'docker-compose.yml' -f 'docker-compose.prod.yml' up -d")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring("docker compose -p 'demo-app' -f 'docker-compose.yml' -f 'docker-compose.prod.yml' up -d")) } -func TestModulesAdv_ModuleDockerCompose_Production_Good_AlreadyUpToDate(t *testing.T) { +func TestModulesAdv_ModuleDockerCompose_Production_Good_AlreadyUpToDate(t *core.T) { e := NewExecutor("/tmp") mock := NewMockSSHClient() mock.expectCommand(`docker compose up -d`, "Container myapp-web-1 Up to date\n", "", 0) @@ -2299,13 +2296,13 @@ func TestModulesAdv_ModuleDockerCompose_Production_Good_AlreadyUpToDate(t *testi "state": "present", }) - require.NoError(t, err) - assert.False(t, result.Changed) - assert.False(t, result.Failed) - assert.Equal(t, "Container myapp-web-1 Up to date\n", result.Stdout) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, "Container myapp-web-1 Up to date\n", result.Stdout) } -func TestModulesAdv_ModuleDockerCompose_Production_Good_ProjectNameAndFiles(t *testing.T) { +func TestModulesAdv_ModuleDockerCompose_Production_Good_ProjectNameAndFiles(t *core.T) { e := NewExecutor("/tmp") mock := NewMockSSHClient() mock.expectCommand(`docker compose -p 'demo-app' -f 'docker-compose.yml' -f 'docker-compose.prod.yml' up -d`, "Starting\n", "", 0) @@ -2316,15 +2313,15 @@ func TestModulesAdv_ModuleDockerCompose_Production_Good_ProjectNameAndFiles(t *t "files": []any{"docker-compose.yml", "docker-compose.prod.yml"}, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`docker compose -p 'demo-app' -f 'docker-compose.yml' -f 'docker-compose.prod.yml' up -d`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`docker compose -p 'demo-app' -f 'docker-compose.yml' -f 'docker-compose.prod.yml' up -d`)) } // --- Cross-module dispatch tests for advanced modules --- -func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchUser(t *testing.T) { +func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchUser(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`id|useradd|usermod`, "", "", 0) @@ -2338,11 +2335,11 @@ func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchUser(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) } -func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchGroup(t *testing.T) { +func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchGroup(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`getent group|groupadd`, "", "", 0) @@ -2355,11 +2352,11 @@ func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchGroup(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) } -func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchCron(t *testing.T) { +func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchCron(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`crontab`, "", "", 0) @@ -2373,11 +2370,11 @@ func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchCron(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) } -func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchGit(t *testing.T) { +func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchGit(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`git clone`, "", "", 0) @@ -2391,11 +2388,11 @@ func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchGit(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) } -func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchURI(t *testing.T) { +func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchURI(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl`, "OK\n200", "", 0) @@ -2408,11 +2405,11 @@ func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchURI(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Failed) } -func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchDockerCompose(t *testing.T) { +func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchDockerCompose(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`docker compose up -d`, "Creating\n", "", 0) @@ -2426,11 +2423,11 @@ func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchDockerCompose(t *testing. result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) } -func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchDockerComposeV2(t *testing.T) { +func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchDockerComposeV2(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`docker compose up -d`, "Creating\n", "", 0) @@ -2444,12 +2441,12 @@ func TestModulesAdv_ExecuteModuleWithMock_Good_DispatchDockerComposeV2(t *testin result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) } -func TestModulesAdv_ExecuteModule_Good_DispatchBuiltinDockerCompose(t *testing.T) { +func TestModulesAdv_ExecuteModule_Good_DispatchBuiltinDockerCompose(t *core.T) { e := NewExecutor("/tmp") mock := NewMockSSHClient() mock.expectCommand(`docker compose up -d`, "Creating\n", "", 0) @@ -2464,16 +2461,16 @@ func TestModulesAdv_ExecuteModule_Good_DispatchBuiltinDockerCompose(t *testing.T result, err := e.executeModule(context.Background(), "host1", mock, task, &Play{}) - require.NoError(t, err) - require.NotNil(t, result) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`docker compose up -d`)) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`docker compose up -d`)) } // --- reboot module --- -func TestModulesAdv_ModuleReboot_Good_WaitsForTestCommand(t *testing.T) { +func TestModulesAdv_ModuleReboot_Good_WaitsForTestCommand(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`sleep 2 && shutdown -r now 'Maintenance window' &`, "", "", 0) mock.expectCommand(`sleep 3`, "", "", 0) @@ -2487,16 +2484,16 @@ func TestModulesAdv_ModuleReboot_Good_WaitsForTestCommand(t *testing.T) { "test_command": "whoami", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "Reboot initiated", result.Msg) - assert.Equal(t, 3, mock.commandCount()) - assert.True(t, mock.hasExecuted(`sleep 2 && shutdown -r now 'Maintenance window' &`)) - assert.True(t, mock.hasExecuted(`sleep 3`)) - assert.True(t, mock.hasExecuted(`whoami`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "Reboot initiated", result.Msg) + core.AssertEqual(t, 3, mock.commandCount()) + core.AssertTrue(t, mock.hasExecuted(`sleep 2 && shutdown -r now 'Maintenance window' &`)) + core.AssertTrue(t, mock.hasExecuted(`sleep 3`)) + core.AssertTrue(t, mock.hasExecuted(`whoami`)) } -func TestModulesAdv_ModuleReboot_Good_CustomRebootCommand(t *testing.T) { +func TestModulesAdv_ModuleReboot_Good_CustomRebootCommand(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`sleep 1 && /sbin/reboot`, "", "", 0) mock.expectCommand(`whoami`, "root\n", "", 0) @@ -2507,15 +2504,15 @@ func TestModulesAdv_ModuleReboot_Good_CustomRebootCommand(t *testing.T) { "reboot_timeout": 5, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "Reboot initiated", result.Msg) - assert.Equal(t, 2, mock.commandCount()) - assert.True(t, mock.hasExecuted(`sleep 1 && /sbin/reboot`)) - assert.True(t, mock.hasExecuted(`whoami`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "Reboot initiated", result.Msg) + core.AssertEqual(t, 2, mock.commandCount()) + core.AssertTrue(t, mock.hasExecuted(`sleep 1 && /sbin/reboot`)) + core.AssertTrue(t, mock.hasExecuted(`whoami`)) } -func TestModulesAdv_ModuleReboot_Bad_TimesOutWaitingForTestCommand(t *testing.T) { +func TestModulesAdv_ModuleReboot_Bad_TimesOutWaitingForTestCommand(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`shutdown -r now 'Reboot initiated by Ansible' &`, "", "", 0) mock.expectCommand(`whoami`, "", "host unreachable", 1) @@ -2525,24 +2522,24 @@ func TestModulesAdv_ModuleReboot_Bad_TimesOutWaitingForTestCommand(t *testing.T) "test_command": "whoami", }) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, "timed out") - assert.Equal(t, "host unreachable", result.Stderr) - assert.Equal(t, 1, result.RC) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, "timed out") + core.AssertEqual(t, "host unreachable", result.Stderr) + core.AssertEqual(t, 1, result.RC) } -func TestModulesAdv_ModuleReboot_Bad_ReportsInitialShutdownFailure(t *testing.T) { +func TestModulesAdv_ModuleReboot_Bad_ReportsInitialShutdownFailure(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`shutdown -r now 'Reboot initiated by Ansible' &`, "", "permission denied", 1) result, err := e.moduleReboot(context.Background(), mock, map[string]any{}) - require.NoError(t, err) - require.NotNil(t, result) - assert.True(t, result.Failed) - assert.Equal(t, "permission denied", result.Msg) - assert.Equal(t, 1, result.RC) - assert.Equal(t, 1, mock.commandCount()) - assert.False(t, mock.hasExecuted(`whoami`)) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertTrue(t, result.Failed) + core.AssertEqual(t, "permission denied", result.Msg) + core.AssertEqual(t, 1, result.RC) + core.AssertEqual(t, 1, mock.commandCount()) + core.AssertFalse(t, mock.hasExecuted(`whoami`)) } diff --git a/modules_cmd_test.go b/modules_cmd_test.go index 5ac92cc..dfb2d96 100644 --- a/modules_cmd_test.go +++ b/modules_cmd_test.go @@ -2,10 +2,7 @@ package ansible import ( "context" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + core "dappco.re/go" ) // ============================================================ @@ -14,123 +11,123 @@ import ( // --- MockSSHClient basic tests --- -func TestModulesCmd_MockSSHClient_Good_RunRecordsExecution(t *testing.T) { +func TestModulesCmd_MockSSHClient_Good_RunRecordsExecution(t *core.T) { mock := NewMockSSHClient() mock.expectCommand("echo hello", "hello\n", "", 0) stdout, stderr, rc, err := mock.Run(nil, "echo hello") - assert.NoError(t, err) - assert.Equal(t, "hello\n", stdout) - assert.Equal(t, "", stderr) - assert.Equal(t, 0, rc) - assert.Equal(t, 1, mock.commandCount()) - assert.Equal(t, "Run", mock.lastCommand().Method) - assert.Equal(t, "echo hello", mock.lastCommand().Cmd) + core.AssertNoError(t, err) + core.AssertEqual(t, "hello\n", stdout) + core.AssertEqual(t, "", stderr) + core.AssertEqual(t, 0, rc) + core.AssertEqual(t, 1, mock.commandCount()) + core.AssertEqual(t, "Run", mock.lastCommand().Method) + core.AssertEqual(t, "echo hello", mock.lastCommand().Cmd) } -func TestModulesCmd_MockSSHClient_Good_RunScriptRecordsExecution(t *testing.T) { +func TestModulesCmd_MockSSHClient_Good_RunScriptRecordsExecution(t *core.T) { mock := NewMockSSHClient() mock.expectCommand("set -e", "ok", "", 0) stdout, _, rc, err := mock.RunScript(nil, "set -e\necho done") - assert.NoError(t, err) - assert.Equal(t, "ok", stdout) - assert.Equal(t, 0, rc) - assert.Equal(t, 1, mock.commandCount()) - assert.Equal(t, "RunScript", mock.lastCommand().Method) + core.AssertNoError(t, err) + core.AssertEqual(t, "ok", stdout) + core.AssertEqual(t, 0, rc) + core.AssertEqual(t, 1, mock.commandCount()) + core.AssertEqual(t, "RunScript", mock.lastCommand().Method) } -func TestModulesCmd_MockSSHClient_Good_DefaultSuccessResponse(t *testing.T) { +func TestModulesCmd_MockSSHClient_Good_DefaultSuccessResponse(t *core.T) { mock := NewMockSSHClient() // No expectations registered — should return empty success stdout, stderr, rc, err := mock.Run(nil, "anything") - assert.NoError(t, err) - assert.Equal(t, "", stdout) - assert.Equal(t, "", stderr) - assert.Equal(t, 0, rc) + core.AssertNoError(t, err) + core.AssertEqual(t, "", stdout) + core.AssertEqual(t, "", stderr) + core.AssertEqual(t, 0, rc) } -func TestModulesCmd_MockSSHClient_Good_LastMatchWins(t *testing.T) { +func TestModulesCmd_MockSSHClient_Good_LastMatchWins(t *core.T) { mock := NewMockSSHClient() mock.expectCommand("echo", "first", "", 0) mock.expectCommand("echo", "second", "", 0) stdout, _, _, _ := mock.Run(nil, "echo hello") - assert.Equal(t, "second", stdout) + core.AssertEqual(t, "second", stdout) } -func TestModulesCmd_MockSSHClient_Good_FileOperations(t *testing.T) { +func TestModulesCmd_MockSSHClient_Good_FileOperations(t *core.T) { mock := NewMockSSHClient() // File does not exist initially exists, err := mock.FileExists(nil, "/etc/config") - assert.NoError(t, err) - assert.False(t, exists) + core.AssertNoError(t, err) + core.AssertFalse(t, exists) // Add file mock.addFile("/etc/config", []byte("key=value")) // Now it exists exists, err = mock.FileExists(nil, "/etc/config") - assert.NoError(t, err) - assert.True(t, exists) + core.AssertNoError(t, err) + core.AssertTrue(t, exists) // Download it content, err := mock.Download(nil, "/etc/config") - assert.NoError(t, err) - assert.Equal(t, []byte("key=value"), content) + core.AssertNoError(t, err) + core.AssertEqual(t, []byte("key=value"), content) // Download non-existent file _, err = mock.Download(nil, "/nonexistent") - assert.Error(t, err) + core.AssertError(t, err) } -func TestModulesCmd_MockSSHClient_Good_StatWithExplicit(t *testing.T) { +func TestModulesCmd_MockSSHClient_Good_StatWithExplicit(t *core.T) { mock := NewMockSSHClient() mock.addStat("/var/log", map[string]any{"exists": true, "isdir": true}) info, err := mock.Stat(nil, "/var/log") - assert.NoError(t, err) - assert.Equal(t, true, info["exists"]) - assert.Equal(t, true, info["isdir"]) + core.AssertNoError(t, err) + core.AssertEqual(t, true, info["exists"]) + core.AssertEqual(t, true, info["isdir"]) } -func TestModulesCmd_MockSSHClient_Good_StatFallback(t *testing.T) { +func TestModulesCmd_MockSSHClient_Good_StatFallback(t *core.T) { mock := NewMockSSHClient() mock.addFile("/etc/hosts", []byte("127.0.0.1 localhost")) info, err := mock.Stat(nil, "/etc/hosts") - assert.NoError(t, err) - assert.Equal(t, true, info["exists"]) - assert.Equal(t, false, info["isdir"]) + core.AssertNoError(t, err) + core.AssertEqual(t, true, info["exists"]) + core.AssertEqual(t, false, info["isdir"]) info, err = mock.Stat(nil, "/nonexistent") - assert.NoError(t, err) - assert.Equal(t, false, info["exists"]) + core.AssertNoError(t, err) + core.AssertEqual(t, false, info["exists"]) } -func TestModulesCmd_MockSSHClient_Good_BecomeTracking(t *testing.T) { +func TestModulesCmd_MockSSHClient_Good_BecomeTracking(t *core.T) { mock := NewMockSSHClient() - assert.False(t, mock.become) - assert.Equal(t, "", mock.becomeUser) + core.AssertFalse(t, mock.become) + core.AssertEqual(t, "", mock.becomeUser) mock.SetBecome(true, "root", "secret") - assert.True(t, mock.become) - assert.Equal(t, "root", mock.becomeUser) - assert.Equal(t, "secret", mock.becomePass) + core.AssertTrue(t, mock.become) + core.AssertEqual(t, "root", mock.becomeUser) + core.AssertEqual(t, "secret", mock.becomePass) } -func TestModulesCmd_ModuleScript_Good_RelativePathResolvedAgainstBasePath(t *testing.T) { +func TestModulesCmd_ModuleScript_Good_RelativePathResolvedAgainstBasePath(t *core.T) { dir := t.TempDir() scriptPath := joinPath(dir, "scripts", "deploy.sh") - require.NoError(t, writeTestFile(scriptPath, []byte("echo deploy"), 0755)) + core.RequireNoError(t, writeTestFile(scriptPath, []byte("echo deploy"), 0755)) e := NewExecutor(dir) mock := NewMockSSHClient() @@ -140,53 +137,53 @@ func TestModulesCmd_ModuleScript_Good_RelativePathResolvedAgainstBasePath(t *tes "_raw_params": "scripts/deploy.sh", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "deploy\n", result.Stdout) - assert.True(t, mock.hasExecuted("echo deploy")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "deploy\n", result.Stdout) + core.AssertTrue(t, mock.hasExecuted("echo deploy")) } -func TestModulesCmd_MockSSHClient_Good_HasExecuted(t *testing.T) { +func TestModulesCmd_MockSSHClient_Good_HasExecuted(t *core.T) { mock := NewMockSSHClient() _, _, _, _ = mock.Run(nil, "systemctl restart nginx") _, _, _, _ = mock.Run(nil, "apt-get update") - assert.True(t, mock.hasExecuted("systemctl.*nginx")) - assert.True(t, mock.hasExecuted("apt-get")) - assert.False(t, mock.hasExecuted("yum")) + core.AssertTrue(t, mock.hasExecuted("systemctl.*nginx")) + core.AssertTrue(t, mock.hasExecuted("apt-get")) + core.AssertFalse(t, mock.hasExecuted("yum")) } -func TestModulesCmd_MockSSHClient_Good_HasExecutedMethod(t *testing.T) { +func TestModulesCmd_MockSSHClient_Good_HasExecutedMethod(t *core.T) { mock := NewMockSSHClient() _, _, _, _ = mock.Run(nil, "echo run") _, _, _, _ = mock.RunScript(nil, "echo script") - assert.True(t, mock.hasExecutedMethod("Run", "echo run")) - assert.True(t, mock.hasExecutedMethod("RunScript", "echo script")) - assert.False(t, mock.hasExecutedMethod("Run", "echo script")) - assert.False(t, mock.hasExecutedMethod("RunScript", "echo run")) + core.AssertTrue(t, mock.hasExecutedMethod("Run", "echo run")) + core.AssertTrue(t, mock.hasExecutedMethod("RunScript", "echo script")) + core.AssertFalse(t, mock.hasExecutedMethod("Run", "echo script")) + core.AssertFalse(t, mock.hasExecutedMethod("RunScript", "echo run")) } -func TestModulesCmd_MockSSHClient_Good_Reset(t *testing.T) { +func TestModulesCmd_MockSSHClient_Good_Reset(t *core.T) { mock := NewMockSSHClient() _, _, _, _ = mock.Run(nil, "echo hello") - assert.Equal(t, 1, mock.commandCount()) + core.AssertEqual(t, 1, mock.commandCount()) mock.reset() - assert.Equal(t, 0, mock.commandCount()) + core.AssertEqual(t, 0, mock.commandCount()) } -func TestModulesCmd_MockSSHClient_Good_ErrorExpectation(t *testing.T) { +func TestModulesCmd_MockSSHClient_Good_ErrorExpectation(t *core.T) { mock := NewMockSSHClient() - mock.expectCommandError("bad cmd", assert.AnError) + mock.expectCommandError("bad cmd", core.AnError) _, _, _, err := mock.Run(nil, "bad cmd") - assert.Error(t, err) + core.AssertError(t, err) } // --- command module --- -func TestModulesCmd_ModuleCommand_Good_BasicCommand(t *testing.T) { +func TestModulesCmd_ModuleCommand_Good_BasicCommand(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("ls -la /tmp", "total 0\n", "", 0) @@ -194,18 +191,18 @@ func TestModulesCmd_ModuleCommand_Good_BasicCommand(t *testing.T) { "_raw_params": "ls -la /tmp", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.Equal(t, "total 0\n", result.Stdout) - assert.Equal(t, 0, result.RC) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, "total 0\n", result.Stdout) + core.AssertEqual(t, 0, result.RC) // Verify it used Run (not RunScript) - assert.True(t, mock.hasExecutedMethod("Run", "ls -la /tmp")) - assert.False(t, mock.hasExecutedMethod("RunScript", ".*")) + core.AssertTrue(t, mock.hasExecutedMethod("Run", "ls -la /tmp")) + core.AssertFalse(t, mock.hasExecutedMethod("RunScript", ".*")) } -func TestModulesCmd_ModuleCommand_Good_CmdArg(t *testing.T) { +func TestModulesCmd_ModuleCommand_Good_CmdArg(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("whoami", "root\n", "", 0) @@ -213,13 +210,13 @@ func TestModulesCmd_ModuleCommand_Good_CmdArg(t *testing.T) { "cmd": "whoami", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "root\n", result.Stdout) - assert.True(t, mock.hasExecutedMethod("Run", "whoami")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "root\n", result.Stdout) + core.AssertTrue(t, mock.hasExecutedMethod("Run", "whoami")) } -func TestModulesCmd_ModuleCommand_Good_Argv(t *testing.T) { +func TestModulesCmd_ModuleCommand_Good_Argv(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`"echo".*"hello world"`, "hello world\n", "", 0) @@ -232,13 +229,13 @@ func TestModulesCmd_ModuleCommand_Good_Argv(t *testing.T) { result, err := e.executeModule(context.Background(), "host1", mock, task, &Play{}) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "hello world\n", result.Stdout) - assert.True(t, mock.hasExecuted(`hello world`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "hello world\n", result.Stdout) + core.AssertTrue(t, mock.hasExecuted(`hello world`)) } -func TestModulesCmd_ModuleCommand_Good_WithChdir(t *testing.T) { +func TestModulesCmd_ModuleCommand_Good_WithChdir(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`cd "/var/log" && ls`, "syslog\n", "", 0) @@ -247,16 +244,16 @@ func TestModulesCmd_ModuleCommand_Good_WithChdir(t *testing.T) { "chdir": "/var/log", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // The command should have been wrapped with cd last := mock.lastCommand() - assert.Equal(t, "Run", last.Method) - assert.Contains(t, last.Cmd, `cd "/var/log"`) - assert.Contains(t, last.Cmd, "ls") + core.AssertEqual(t, "Run", last.Method) + core.AssertContains(t, last.Cmd, `cd "/var/log"`) + core.AssertContains(t, last.Cmd, "ls") } -func TestModulesCmd_ModuleCommand_Good_WithStdin(t *testing.T) { +func TestModulesCmd_ModuleCommand_Good_WithStdin(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("cat", "input\n", "", 0) @@ -265,27 +262,27 @@ func TestModulesCmd_ModuleCommand_Good_WithStdin(t *testing.T) { "stdin": "payload", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "input\n", result.Stdout) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "input\n", result.Stdout) last := mock.lastCommand() - assert.Equal(t, "Run", last.Method) - assert.Contains(t, last.Cmd, "printf %s") - assert.Contains(t, last.Cmd, "| cat") - assert.Contains(t, last.Cmd, "payload\n") + core.AssertEqual(t, "Run", last.Method) + core.AssertContains(t, last.Cmd, "printf %s") + core.AssertContains(t, last.Cmd, "| cat") + core.AssertContains(t, last.Cmd, "payload\n") } -func TestModulesCmd_ModuleCommand_Bad_NoCommand(t *testing.T) { +func TestModulesCmd_ModuleCommand_Bad_NoCommand(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() _, err := moduleCommandWithClient(e, mock, map[string]any{}) - assert.Error(t, err) - assert.Contains(t, err.Error(), "no command specified") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "no command specified") } -func TestModulesCmd_ModuleCommand_Good_NonZeroRC(t *testing.T) { +func TestModulesCmd_ModuleCommand_Good_NonZeroRC(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("false", "", "error occurred", 1) @@ -293,27 +290,27 @@ func TestModulesCmd_ModuleCommand_Good_NonZeroRC(t *testing.T) { "_raw_params": "false", }) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Equal(t, 1, result.RC) - assert.Equal(t, "error occurred", result.Stderr) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertEqual(t, 1, result.RC) + core.AssertEqual(t, "error occurred", result.Stderr) } -func TestModulesCmd_ModuleCommand_Good_SSHError(t *testing.T) { +func TestModulesCmd_ModuleCommand_Good_SSHError(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() - mock.expectCommandError(".*", assert.AnError) + mock.expectCommandError(".*", core.AnError) result, err := moduleCommandWithClient(e, mock, map[string]any{ "_raw_params": "any command", }) - require.NoError(t, err) // Module wraps SSH errors into result.Failed - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, assert.AnError.Error()) + core.RequireNoError(t, err) // Module wraps SSH errors into result.Failed + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, core.AnError.Error()) } -func TestModulesCmd_ModuleCommand_Good_RawParamsTakesPrecedence(t *testing.T) { +func TestModulesCmd_ModuleCommand_Good_RawParamsTakesPrecedence(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("from_raw", "raw\n", "", 0) @@ -322,12 +319,12 @@ func TestModulesCmd_ModuleCommand_Good_RawParamsTakesPrecedence(t *testing.T) { "cmd": "from_cmd", }) - require.NoError(t, err) - assert.Equal(t, "raw\n", result.Stdout) - assert.True(t, mock.hasExecuted("from_raw")) + core.RequireNoError(t, err) + core.AssertEqual(t, "raw\n", result.Stdout) + core.AssertTrue(t, mock.hasExecuted("from_raw")) } -func TestModulesCmd_ModuleCommand_Good_SkipsWhenCreatesExists(t *testing.T) { +func TestModulesCmd_ModuleCommand_Good_SkipsWhenCreatesExists(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/tmp/output.txt", []byte("done")) @@ -340,12 +337,12 @@ func TestModulesCmd_ModuleCommand_Good_SkipsWhenCreatesExists(t *testing.T) { } result, err := e.executeModule(context.Background(), "host1", mock, task, &Play{}) - require.NoError(t, err) - assert.False(t, result.Changed) - assert.Equal(t, 0, mock.commandCount()) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertEqual(t, 0, mock.commandCount()) } -func TestModulesCmd_ModuleCommand_Good_SkipsWhenCreatesExistsUnderChdir(t *testing.T) { +func TestModulesCmd_ModuleCommand_Good_SkipsWhenCreatesExistsUnderChdir(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/app/build/output.txt", []byte("done")) @@ -360,14 +357,14 @@ func TestModulesCmd_ModuleCommand_Good_SkipsWhenCreatesExistsUnderChdir(t *testi result, err := e.executeModule(context.Background(), "host1", mock, task, &Play{}) - require.NoError(t, err) - assert.False(t, result.Changed) - assert.Equal(t, 0, mock.commandCount()) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertEqual(t, 0, mock.commandCount()) } // --- shell module --- -func TestModulesCmd_ModuleShell_Good_BasicShell(t *testing.T) { +func TestModulesCmd_ModuleShell_Good_BasicShell(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("echo hello", "hello\n", "", 0) @@ -375,17 +372,17 @@ func TestModulesCmd_ModuleShell_Good_BasicShell(t *testing.T) { "_raw_params": "echo hello", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.Equal(t, "hello\n", result.Stdout) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, "hello\n", result.Stdout) // Shell must use RunScript (not Run) - assert.True(t, mock.hasExecutedMethod("RunScript", "echo hello")) - assert.False(t, mock.hasExecutedMethod("Run", ".*")) + core.AssertTrue(t, mock.hasExecutedMethod("RunScript", "echo hello")) + core.AssertFalse(t, mock.hasExecutedMethod("Run", ".*")) } -func TestModulesCmd_ModuleShell_Good_CmdArg(t *testing.T) { +func TestModulesCmd_ModuleShell_Good_CmdArg(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("date", "Thu Feb 20\n", "", 0) @@ -393,12 +390,12 @@ func TestModulesCmd_ModuleShell_Good_CmdArg(t *testing.T) { "cmd": "date", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecutedMethod("RunScript", "date")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecutedMethod("RunScript", "date")) } -func TestModulesCmd_ModuleShell_Good_WithChdir(t *testing.T) { +func TestModulesCmd_ModuleShell_Good_WithChdir(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`cd "/app" && npm install`, "done\n", "", 0) @@ -407,15 +404,15 @@ func TestModulesCmd_ModuleShell_Good_WithChdir(t *testing.T) { "chdir": "/app", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) last := mock.lastCommand() - assert.Equal(t, "RunScript", last.Method) - assert.Contains(t, last.Cmd, `cd "/app"`) - assert.Contains(t, last.Cmd, "npm install") + core.AssertEqual(t, "RunScript", last.Method) + core.AssertContains(t, last.Cmd, `cd "/app"`) + core.AssertContains(t, last.Cmd, "npm install") } -func TestModulesCmd_ModuleShell_Good_ExecutableUsesRun(t *testing.T) { +func TestModulesCmd_ModuleShell_Good_ExecutableUsesRun(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`/bin/dash.*echo test`, "test\n", "", 0) @@ -424,28 +421,28 @@ func TestModulesCmd_ModuleShell_Good_ExecutableUsesRun(t *testing.T) { "executable": "/bin/dash", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) last := mock.lastCommand() - require.NotNil(t, last) - assert.Equal(t, "Run", last.Method) - assert.Contains(t, last.Cmd, "/bin/dash") - assert.Contains(t, last.Cmd, "-c") - assert.Contains(t, last.Cmd, "echo test") + core.AssertNotNil(t, last) + core.AssertEqual(t, "Run", last.Method) + core.AssertContains(t, last.Cmd, "/bin/dash") + core.AssertContains(t, last.Cmd, "-c") + core.AssertContains(t, last.Cmd, "echo test") } -func TestModulesCmd_ModuleShell_Bad_NoCommand(t *testing.T) { +func TestModulesCmd_ModuleShell_Bad_NoCommand(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() _, err := moduleShellWithClient(e, mock, map[string]any{}) - assert.Error(t, err) - assert.Contains(t, err.Error(), "no command specified") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "no command specified") } -func TestModulesCmd_ModuleShell_Good_NonZeroRC(t *testing.T) { +func TestModulesCmd_ModuleShell_Good_NonZeroRC(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("exit 2", "", "failed", 2) @@ -453,12 +450,12 @@ func TestModulesCmd_ModuleShell_Good_NonZeroRC(t *testing.T) { "_raw_params": "exit 2", }) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Equal(t, 2, result.RC) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertEqual(t, 2, result.RC) } -func TestModulesCmd_ModuleShell_Good_SkipsWhenRemovesMissing(t *testing.T) { +func TestModulesCmd_ModuleShell_Good_SkipsWhenRemovesMissing(t *core.T) { e, mock := newTestExecutorWithMock("host1") task := &Task{ @@ -470,25 +467,25 @@ func TestModulesCmd_ModuleShell_Good_SkipsWhenRemovesMissing(t *testing.T) { } result, err := e.executeModule(context.Background(), "host1", mock, task, &Play{}) - require.NoError(t, err) - assert.False(t, result.Changed) - assert.Equal(t, 0, mock.commandCount()) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertEqual(t, 0, mock.commandCount()) } -func TestModulesCmd_ModuleShell_Good_SSHError(t *testing.T) { +func TestModulesCmd_ModuleShell_Good_SSHError(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() - mock.expectCommandError(".*", assert.AnError) + mock.expectCommandError(".*", core.AnError) result, err := moduleShellWithClient(e, mock, map[string]any{ "_raw_params": "some command", }) - require.NoError(t, err) - assert.True(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) } -func TestModulesCmd_ModuleShell_Good_PipelineCommand(t *testing.T) { +func TestModulesCmd_ModuleShell_Good_PipelineCommand(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`cat /etc/passwd \| grep root`, "root:x:0:0\n", "", 0) @@ -496,15 +493,15 @@ func TestModulesCmd_ModuleShell_Good_PipelineCommand(t *testing.T) { "_raw_params": "cat /etc/passwd | grep root", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // Shell uses RunScript, so pipes work - assert.True(t, mock.hasExecutedMethod("RunScript", "cat /etc/passwd")) + core.AssertTrue(t, mock.hasExecutedMethod("RunScript", "cat /etc/passwd")) } // --- raw module --- -func TestModulesCmd_ModuleRaw_Good_BasicRaw(t *testing.T) { +func TestModulesCmd_ModuleRaw_Good_BasicRaw(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("uname -a", "Linux host1 5.15\n", "", 0) @@ -512,26 +509,26 @@ func TestModulesCmd_ModuleRaw_Good_BasicRaw(t *testing.T) { "_raw_params": "uname -a", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "Linux host1 5.15\n", result.Stdout) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "Linux host1 5.15\n", result.Stdout) // Raw must use Run (not RunScript) — no shell wrapping - assert.True(t, mock.hasExecutedMethod("Run", "uname -a")) - assert.False(t, mock.hasExecutedMethod("RunScript", ".*")) + core.AssertTrue(t, mock.hasExecutedMethod("Run", "uname -a")) + core.AssertFalse(t, mock.hasExecutedMethod("RunScript", ".*")) } -func TestModulesCmd_ModuleRaw_Bad_NoCommand(t *testing.T) { +func TestModulesCmd_ModuleRaw_Bad_NoCommand(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() _, err := moduleRawWithClient(e, mock, map[string]any{}) - assert.Error(t, err) - assert.Contains(t, err.Error(), "no command specified") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "no command specified") } -func TestModulesCmd_ModuleRaw_Good_NoChdir(t *testing.T) { +func TestModulesCmd_ModuleRaw_Good_NoChdir(t *core.T) { // Raw module does NOT support chdir — it should ignore it e, mock := newTestExecutorWithMock("host1") mock.expectCommand("echo test", "test\n", "", 0) @@ -541,15 +538,15 @@ func TestModulesCmd_ModuleRaw_Good_NoChdir(t *testing.T) { "chdir": "/should/be/ignored", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // The chdir should NOT appear in the command last := mock.lastCommand() - assert.Equal(t, "echo test", last.Cmd) - assert.NotContains(t, last.Cmd, "cd") + core.AssertEqual(t, "echo test", last.Cmd) + core.AssertNotContains(t, last.Cmd, "cd") } -func TestModulesCmd_ModuleRaw_Good_NonZeroRC(t *testing.T) { +func TestModulesCmd_ModuleRaw_Good_NonZeroRC(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("invalid", "", "not found", 127) @@ -557,26 +554,26 @@ func TestModulesCmd_ModuleRaw_Good_NonZeroRC(t *testing.T) { "_raw_params": "invalid", }) - require.NoError(t, err) + core.RequireNoError(t, err) // Note: raw module does NOT set Failed based on RC - assert.Equal(t, 127, result.RC) - assert.Equal(t, "not found", result.Stderr) + core.AssertEqual(t, 127, result.RC) + core.AssertEqual(t, "not found", result.Stderr) } -func TestModulesCmd_ModuleRaw_Good_SSHError(t *testing.T) { +func TestModulesCmd_ModuleRaw_Good_SSHError(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() - mock.expectCommandError(".*", assert.AnError) + mock.expectCommandError(".*", core.AnError) result, err := moduleRawWithClient(e, mock, map[string]any{ "_raw_params": "any", }) - require.NoError(t, err) - assert.True(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) } -func TestModulesCmd_ModuleRaw_Good_ExactCommandPassthrough(t *testing.T) { +func TestModulesCmd_ModuleRaw_Good_ExactCommandPassthrough(t *core.T) { // Raw should pass the command exactly as given — no wrapping e, mock := newTestExecutorWithMock("host1") complexCmd := `/usr/bin/python3 -c 'import sys; print(sys.version)'` @@ -586,20 +583,20 @@ func TestModulesCmd_ModuleRaw_Good_ExactCommandPassthrough(t *testing.T) { "_raw_params": complexCmd, }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) last := mock.lastCommand() - assert.Equal(t, complexCmd, last.Cmd) + core.AssertEqual(t, complexCmd, last.Cmd) } // --- script module --- -func TestModulesCmd_ModuleScript_Good_BasicScript(t *testing.T) { +func TestModulesCmd_ModuleScript_Good_BasicScript(t *core.T) { // Create a temporary script file tmpDir := t.TempDir() scriptPath := joinPath(tmpDir, "setup.sh") scriptContent := "#!/bin/bash\necho 'setup complete'\nexit 0" - require.NoError(t, writeTestFile(scriptPath, []byte(scriptContent), 0755)) + core.RequireNoError(t, writeTestFile(scriptPath, []byte(scriptContent), 0755)) e, mock := newTestExecutorWithMock("host1") mock.expectCommand("setup complete", "setup complete\n", "", 0) @@ -608,23 +605,23 @@ func TestModulesCmd_ModuleScript_Good_BasicScript(t *testing.T) { "_raw_params": scriptPath, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) // Script must use RunScript (not Run) — it sends the file content - assert.True(t, mock.hasExecutedMethod("RunScript", "setup complete")) - assert.False(t, mock.hasExecutedMethod("Run", ".*")) + core.AssertTrue(t, mock.hasExecutedMethod("RunScript", "setup complete")) + core.AssertFalse(t, mock.hasExecutedMethod("Run", ".*")) // Verify the full script content was sent last := mock.lastCommand() - assert.Equal(t, scriptContent, last.Cmd) + core.AssertEqual(t, scriptContent, last.Cmd) } -func TestModulesCmd_ModuleScript_Good_CreatesSkipsExecution(t *testing.T) { +func TestModulesCmd_ModuleScript_Good_CreatesSkipsExecution(t *core.T) { tmpDir := t.TempDir() scriptPath := joinPath(tmpDir, "setup.sh") - require.NoError(t, writeTestFile(scriptPath, []byte("echo should-not-run"), 0755)) + core.RequireNoError(t, writeTestFile(scriptPath, []byte("echo should-not-run"), 0755)) e, mock := newTestExecutorWithMock("host1") mock.addFile("/tmp/already-there", []byte("present")) @@ -634,16 +631,16 @@ func TestModulesCmd_ModuleScript_Good_CreatesSkipsExecution(t *testing.T) { "creates": "/tmp/already-there", }) - require.NoError(t, err) - require.NotNil(t, result) - assert.False(t, result.Changed) - assert.Equal(t, 0, mock.commandCount()) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Changed) + core.AssertEqual(t, 0, mock.commandCount()) } -func TestModulesCmd_ModuleScript_Good_ChdirPrefixesScript(t *testing.T) { +func TestModulesCmd_ModuleScript_Good_ChdirPrefixesScript(t *core.T) { tmpDir := t.TempDir() scriptPath := joinPath(tmpDir, "work.sh") - require.NoError(t, writeTestFile(scriptPath, []byte("pwd"), 0755)) + core.RequireNoError(t, writeTestFile(scriptPath, []byte("pwd"), 0755)) e, mock := newTestExecutorWithMock("host1") @@ -652,20 +649,20 @@ func TestModulesCmd_ModuleScript_Good_ChdirPrefixesScript(t *testing.T) { "chdir": "/opt/app", }) - require.NoError(t, err) - require.NotNil(t, result) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertTrue(t, result.Changed) last := mock.lastCommand() - require.NotNil(t, last) - assert.Equal(t, "RunScript", last.Method) - assert.Equal(t, `cd "/opt/app" && pwd`, last.Cmd) + core.AssertNotNil(t, last) + core.AssertEqual(t, "RunScript", last.Method) + core.AssertEqual(t, `cd "/opt/app" && pwd`, last.Cmd) } -func TestModulesCmd_ModuleScript_Good_ExecutableUsesRun(t *testing.T) { +func TestModulesCmd_ModuleScript_Good_ExecutableUsesRun(t *core.T) { tmpDir := t.TempDir() scriptPath := joinPath(tmpDir, "dash.sh") - require.NoError(t, writeTestFile(scriptPath, []byte("echo script works"), 0755)) + core.RequireNoError(t, writeTestFile(scriptPath, []byte("echo script works"), 0755)) e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`/bin/dash.*echo script works`, "script works\n", "", 0) @@ -675,29 +672,29 @@ func TestModulesCmd_ModuleScript_Good_ExecutableUsesRun(t *testing.T) { "executable": "/bin/dash", }) - require.NoError(t, err) - require.NotNil(t, result) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertTrue(t, result.Changed) last := mock.lastCommand() - require.NotNil(t, last) - assert.Equal(t, "Run", last.Method) - assert.Contains(t, last.Cmd, "/bin/dash") - assert.Contains(t, last.Cmd, "-c") - assert.Contains(t, last.Cmd, "echo script works") + core.AssertNotNil(t, last) + core.AssertEqual(t, "Run", last.Method) + core.AssertContains(t, last.Cmd, "/bin/dash") + core.AssertContains(t, last.Cmd, "-c") + core.AssertContains(t, last.Cmd, "echo script works") } -func TestModulesCmd_ModuleScript_Bad_NoScript(t *testing.T) { +func TestModulesCmd_ModuleScript_Bad_NoScript(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() _, err := moduleScriptWithClient(e, mock, map[string]any{}) - assert.Error(t, err) - assert.Contains(t, err.Error(), "no script specified") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "no script specified") } -func TestModulesCmd_ModuleScript_Bad_FileNotFound(t *testing.T) { +func TestModulesCmd_ModuleScript_Bad_FileNotFound(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() @@ -705,14 +702,14 @@ func TestModulesCmd_ModuleScript_Bad_FileNotFound(t *testing.T) { "_raw_params": "/nonexistent/script.sh", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "read script") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "read script") } -func TestModulesCmd_ModuleScript_Good_NonZeroRC(t *testing.T) { +func TestModulesCmd_ModuleScript_Good_NonZeroRC(t *core.T) { tmpDir := t.TempDir() scriptPath := joinPath(tmpDir, "fail.sh") - require.NoError(t, writeTestFile(scriptPath, []byte("exit 1"), 0755)) + core.RequireNoError(t, writeTestFile(scriptPath, []byte("exit 1"), 0755)) e, mock := newTestExecutorWithMock("host1") mock.expectCommand("exit 1", "", "script failed", 1) @@ -721,16 +718,16 @@ func TestModulesCmd_ModuleScript_Good_NonZeroRC(t *testing.T) { "_raw_params": scriptPath, }) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Equal(t, 1, result.RC) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertEqual(t, 1, result.RC) } -func TestModulesCmd_ModuleScript_Good_MultiLineScript(t *testing.T) { +func TestModulesCmd_ModuleScript_Good_MultiLineScript(t *core.T) { tmpDir := t.TempDir() scriptPath := joinPath(tmpDir, "multi.sh") scriptContent := "#!/bin/bash\nset -e\napt-get update\napt-get install -y nginx\nsystemctl start nginx" - require.NoError(t, writeTestFile(scriptPath, []byte(scriptContent), 0755)) + core.RequireNoError(t, writeTestFile(scriptPath, []byte(scriptContent), 0755)) e, mock := newTestExecutorWithMock("host1") mock.expectCommand("apt-get", "done\n", "", 0) @@ -739,57 +736,57 @@ func TestModulesCmd_ModuleScript_Good_MultiLineScript(t *testing.T) { "_raw_params": scriptPath, }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // Verify RunScript was called with the full content last := mock.lastCommand() - assert.Equal(t, "RunScript", last.Method) - assert.Equal(t, scriptContent, last.Cmd) + core.AssertEqual(t, "RunScript", last.Method) + core.AssertEqual(t, scriptContent, last.Cmd) } -func TestModulesCmd_ModuleScript_Good_SSHError(t *testing.T) { +func TestModulesCmd_ModuleScript_Good_SSHError(t *core.T) { tmpDir := t.TempDir() scriptPath := joinPath(tmpDir, "ok.sh") - require.NoError(t, writeTestFile(scriptPath, []byte("echo ok"), 0755)) + core.RequireNoError(t, writeTestFile(scriptPath, []byte("echo ok"), 0755)) e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() - mock.expectCommandError(".*", assert.AnError) + mock.expectCommandError(".*", core.AnError) result, err := moduleScriptWithClient(e, mock, map[string]any{ "_raw_params": scriptPath, }) - require.NoError(t, err) - assert.True(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) } // --- Cross-module differentiation tests --- -func TestModulesCmd_ModuleDifferentiation_Good_CommandUsesRun(t *testing.T) { +func TestModulesCmd_ModuleDifferentiation_Good_CommandUsesRun(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("echo test", "test\n", "", 0) _, _ = moduleCommandWithClient(e, mock, map[string]any{"_raw_params": "echo test"}) cmds := mock.executedCommands() - require.Len(t, cmds, 1) - assert.Equal(t, "Run", cmds[0].Method, "command module must use Run()") + core.AssertLen(t, cmds, 1) + core.AssertEqual(t, "Run", cmds[0].Method, "command module must use Run()") } -func TestModulesCmd_ModuleDifferentiation_Good_ShellUsesRunScript(t *testing.T) { +func TestModulesCmd_ModuleDifferentiation_Good_ShellUsesRunScript(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("echo test", "test\n", "", 0) _, _ = moduleShellWithClient(e, mock, map[string]any{"_raw_params": "echo test"}) cmds := mock.executedCommands() - require.Len(t, cmds, 1) - assert.Equal(t, "RunScript", cmds[0].Method, "shell module must use RunScript()") + core.AssertLen(t, cmds, 1) + core.AssertEqual(t, "RunScript", cmds[0].Method, "shell module must use RunScript()") } -func TestModulesCmd_ModuleDifferentiation_Good_ShellWithStdinStillUsesRunScript(t *testing.T) { +func TestModulesCmd_ModuleDifferentiation_Good_ShellWithStdinStillUsesRunScript(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("echo test", "test\n", "", 0) @@ -799,27 +796,27 @@ func TestModulesCmd_ModuleDifferentiation_Good_ShellWithStdinStillUsesRunScript( }) cmds := mock.executedCommands() - require.Len(t, cmds, 1) - assert.Equal(t, "RunScript", cmds[0].Method, "shell module must still use RunScript()") - assert.Contains(t, cmds[0].Cmd, "printf %s") - assert.Contains(t, cmds[0].Cmd, "| echo test") + core.AssertLen(t, cmds, 1) + core.AssertEqual(t, "RunScript", cmds[0].Method, "shell module must still use RunScript()") + core.AssertContains(t, cmds[0].Cmd, "printf %s") + core.AssertContains(t, cmds[0].Cmd, "| echo test") } -func TestModulesCmd_ModuleDifferentiation_Good_RawUsesRun(t *testing.T) { +func TestModulesCmd_ModuleDifferentiation_Good_RawUsesRun(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("echo test", "test\n", "", 0) _, _ = moduleRawWithClient(e, mock, map[string]any{"_raw_params": "echo test"}) cmds := mock.executedCommands() - require.Len(t, cmds, 1) - assert.Equal(t, "Run", cmds[0].Method, "raw module must use Run()") + core.AssertLen(t, cmds, 1) + core.AssertEqual(t, "Run", cmds[0].Method, "raw module must use Run()") } -func TestModulesCmd_ModuleDifferentiation_Good_ScriptUsesRunScript(t *testing.T) { +func TestModulesCmd_ModuleDifferentiation_Good_ScriptUsesRunScript(t *core.T) { tmpDir := t.TempDir() scriptPath := joinPath(tmpDir, "test.sh") - require.NoError(t, writeTestFile(scriptPath, []byte("echo test"), 0755)) + core.RequireNoError(t, writeTestFile(scriptPath, []byte("echo test"), 0755)) e, mock := newTestExecutorWithMock("host1") mock.expectCommand("echo test", "test\n", "", 0) @@ -827,13 +824,13 @@ func TestModulesCmd_ModuleDifferentiation_Good_ScriptUsesRunScript(t *testing.T) _, _ = moduleScriptWithClient(e, mock, map[string]any{"_raw_params": scriptPath}) cmds := mock.executedCommands() - require.Len(t, cmds, 1) - assert.Equal(t, "RunScript", cmds[0].Method, "script module must use RunScript()") + core.AssertLen(t, cmds, 1) + core.AssertEqual(t, "RunScript", cmds[0].Method, "script module must use RunScript()") } // --- executeModuleWithMock dispatch tests --- -func TestModulesCmd_ExecuteModuleWithMock_Good_DispatchCommand(t *testing.T) { +func TestModulesCmd_ExecuteModuleWithMock_Good_DispatchCommand(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("uptime", "up 5 days\n", "", 0) @@ -844,12 +841,12 @@ func TestModulesCmd_ExecuteModuleWithMock_Good_DispatchCommand(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "up 5 days\n", result.Stdout) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "up 5 days\n", result.Stdout) } -func TestModulesCmd_ExecuteModuleWithMock_Good_DispatchShell(t *testing.T) { +func TestModulesCmd_ExecuteModuleWithMock_Good_DispatchShell(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("ps aux", "root.*bash\n", "", 0) @@ -860,11 +857,11 @@ func TestModulesCmd_ExecuteModuleWithMock_Good_DispatchShell(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) } -func TestModulesCmd_ExecuteModuleWithMock_Good_DispatchRaw(t *testing.T) { +func TestModulesCmd_ExecuteModuleWithMock_Good_DispatchRaw(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("cat /etc/hostname", "web01\n", "", 0) @@ -875,15 +872,15 @@ func TestModulesCmd_ExecuteModuleWithMock_Good_DispatchRaw(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, "web01\n", result.Stdout) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, "web01\n", result.Stdout) } -func TestModulesCmd_ExecuteModuleWithMock_Good_DispatchScript(t *testing.T) { +func TestModulesCmd_ExecuteModuleWithMock_Good_DispatchScript(t *core.T) { tmpDir := t.TempDir() scriptPath := joinPath(tmpDir, "deploy.sh") - require.NoError(t, writeTestFile(scriptPath, []byte("echo deploying"), 0755)) + core.RequireNoError(t, writeTestFile(scriptPath, []byte("echo deploying"), 0755)) e, mock := newTestExecutorWithMock("host1") mock.expectCommand("deploying", "deploying\n", "", 0) @@ -895,11 +892,11 @@ func TestModulesCmd_ExecuteModuleWithMock_Good_DispatchScript(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) } -func TestModulesCmd_ExecuteModuleWithMock_Bad_UnsupportedModule(t *testing.T) { +func TestModulesCmd_ExecuteModuleWithMock_Bad_UnsupportedModule(t *core.T) { e, mock := newTestExecutorWithMock("host1") task := &Task{ @@ -909,14 +906,14 @@ func TestModulesCmd_ExecuteModuleWithMock_Bad_UnsupportedModule(t *testing.T) { _, err := executeModuleWithMock(e, mock, "host1", task) - assert.Error(t, err) - assert.Contains(t, err.Error(), "unsupported module") - assert.Contains(t, err.Error(), "ansible.builtin.hostname") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "unsupported module") + core.AssertContains(t, err.Error(), "ansible.builtin.hostname") } // --- Template integration tests --- -func TestModulesCmd_ModuleCommand_Good_TemplatedArgs(t *testing.T) { +func TestModulesCmd_ModuleCommand_Good_TemplatedArgs(t *core.T) { e, mock := newTestExecutorWithMock("host1") e.SetVar("service_name", "nginx") mock.expectCommand("systemctl status nginx", "active\n", "", 0) @@ -930,7 +927,7 @@ func TestModulesCmd_ModuleCommand_Good_TemplatedArgs(t *testing.T) { args := e.templateArgs(task.Args, "host1", task) result, err := moduleCommandWithClient(e, mock, args) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted("systemctl status nginx")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted("systemctl status nginx")) } diff --git a/modules_file_test.go b/modules_file_test.go index 40dbcdf..5a3f6e8 100644 --- a/modules_file_test.go +++ b/modules_file_test.go @@ -4,16 +4,13 @@ import ( "context" "crypto/sha256" "crypto/sha512" + core "dappco.re/go" "encoding/hex" "io" "io/fs" "regexp" "strings" "sync" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) type diffFileClient struct { @@ -148,7 +145,7 @@ func (c *diffFileClient) Close() error { return nil } // --- copy module --- -func TestModulesFile_ModuleCopy_Good_ContentUpload(t *testing.T) { +func TestModulesFile_ModuleCopy_Good_ContentUpload(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleCopyWithClient(e, mock, map[string]any{ @@ -156,23 +153,23 @@ func TestModulesFile_ModuleCopy_Good_ContentUpload(t *testing.T) { "dest": "/etc/app/config", }, "host1", &Task{}) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Contains(t, result.Msg, "copied to /etc/app/config") + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertContains(t, result.Msg, "copied to /etc/app/config") // Verify upload was performed - assert.Equal(t, 1, mock.uploadCount()) + core.AssertEqual(t, 1, mock.uploadCount()) up := mock.lastUpload() - require.NotNil(t, up) - assert.Equal(t, "/etc/app/config", up.Remote) - assert.Equal(t, []byte("server_name=web01"), up.Content) - assert.Equal(t, fs.FileMode(0644), up.Mode) + core.AssertNotNil(t, up) + core.AssertEqual(t, "/etc/app/config", up.Remote) + core.AssertEqual(t, []byte("server_name=web01"), up.Content) + core.AssertEqual(t, fs.FileMode(0644), up.Mode) } -func TestModulesFile_ModuleCopy_Good_SrcFile(t *testing.T) { +func TestModulesFile_ModuleCopy_Good_SrcFile(t *core.T) { tmpDir := t.TempDir() srcPath := joinPath(tmpDir, "nginx.conf") - require.NoError(t, writeTestFile(srcPath, []byte("worker_processes auto;"), 0644)) + core.RequireNoError(t, writeTestFile(srcPath, []byte("worker_processes auto;"), 0644)) e, mock := newTestExecutorWithMock("host1") @@ -181,16 +178,16 @@ func TestModulesFile_ModuleCopy_Good_SrcFile(t *testing.T) { "dest": "/etc/nginx/nginx.conf", }, "host1", &Task{}) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) up := mock.lastUpload() - require.NotNil(t, up) - assert.Equal(t, "/etc/nginx/nginx.conf", up.Remote) - assert.Equal(t, []byte("worker_processes auto;"), up.Content) + core.AssertNotNil(t, up) + core.AssertEqual(t, "/etc/nginx/nginx.conf", up.Remote) + core.AssertEqual(t, []byte("worker_processes auto;"), up.Content) } -func TestModulesFile_ModuleCopy_Good_RemoteSrc(t *testing.T) { +func TestModulesFile_ModuleCopy_Good_RemoteSrc(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/tmp/remote-source.txt", []byte("remote payload")) @@ -200,16 +197,16 @@ func TestModulesFile_ModuleCopy_Good_RemoteSrc(t *testing.T) { "remote_src": true, }, "host1", &Task{}) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) up := mock.lastUpload() - require.NotNil(t, up) - assert.Equal(t, "/etc/app/remote.txt", up.Remote) - assert.Equal(t, []byte("remote payload"), up.Content) + core.AssertNotNil(t, up) + core.AssertEqual(t, "/etc/app/remote.txt", up.Remote) + core.AssertEqual(t, []byte("remote payload"), up.Content) } -func TestModulesFile_ModuleCopy_Good_OwnerGroup(t *testing.T) { +func TestModulesFile_ModuleCopy_Good_OwnerGroup(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleCopyWithClient(e, mock, map[string]any{ @@ -219,16 +216,16 @@ func TestModulesFile_ModuleCopy_Good_OwnerGroup(t *testing.T) { "group": "appgroup", }, "host1", &Task{}) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // Upload + chown + chgrp = 1 upload + 2 Run calls - assert.Equal(t, 1, mock.uploadCount()) - assert.True(t, mock.hasExecuted(`chown appuser "/opt/app/data.txt"`)) - assert.True(t, mock.hasExecuted(`chgrp appgroup "/opt/app/data.txt"`)) + core.AssertEqual(t, 1, mock.uploadCount()) + core.AssertTrue(t, mock.hasExecuted(`chown appuser "/opt/app/data.txt"`)) + core.AssertTrue(t, mock.hasExecuted(`chgrp appgroup "/opt/app/data.txt"`)) } -func TestModulesFile_ModuleCopy_Good_CustomMode(t *testing.T) { +func TestModulesFile_ModuleCopy_Good_CustomMode(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleCopyWithClient(e, mock, map[string]any{ @@ -237,37 +234,37 @@ func TestModulesFile_ModuleCopy_Good_CustomMode(t *testing.T) { "mode": "0755", }, "host1", &Task{}) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) up := mock.lastUpload() - require.NotNil(t, up) - assert.Equal(t, fs.FileMode(0755), up.Mode) + core.AssertNotNil(t, up) + core.AssertEqual(t, fs.FileMode(0755), up.Mode) } -func TestModulesFile_ModuleCopy_Bad_MissingDest(t *testing.T) { +func TestModulesFile_ModuleCopy_Bad_MissingDest(t *core.T) { e, mock := newTestExecutorWithMock("host1") _, err := moduleCopyWithClient(e, mock, map[string]any{ "content": "data", }, "host1", &Task{}) - assert.Error(t, err) - assert.Contains(t, err.Error(), "dest required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "dest required") } -func TestModulesFile_ModuleCopy_Bad_MissingSrcAndContent(t *testing.T) { +func TestModulesFile_ModuleCopy_Bad_MissingSrcAndContent(t *core.T) { e, mock := newTestExecutorWithMock("host1") _, err := moduleCopyWithClient(e, mock, map[string]any{ "dest": "/tmp/out", }, "host1", &Task{}) - assert.Error(t, err) - assert.Contains(t, err.Error(), "src or content required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "src or content required") } -func TestModulesFile_ModuleCopy_Bad_SrcFileNotFound(t *testing.T) { +func TestModulesFile_ModuleCopy_Bad_SrcFileNotFound(t *core.T) { e, mock := newTestExecutorWithMock("host1") _, err := moduleCopyWithClient(e, mock, map[string]any{ @@ -275,11 +272,11 @@ func TestModulesFile_ModuleCopy_Bad_SrcFileNotFound(t *testing.T) { "dest": "/tmp/out", }, "host1", &Task{}) - assert.Error(t, err) - assert.Contains(t, err.Error(), "read src") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "read src") } -func TestModulesFile_ModuleCopy_Good_ContentTakesPrecedenceOverSrc(t *testing.T) { +func TestModulesFile_ModuleCopy_Good_ContentTakesPrecedenceOverSrc(t *core.T) { // When both content and src are given, src is checked first in the implementation // but if src is empty string, content is used e, mock := newTestExecutorWithMock("host1") @@ -289,13 +286,13 @@ func TestModulesFile_ModuleCopy_Good_ContentTakesPrecedenceOverSrc(t *testing.T) "dest": "/tmp/out", }, "host1", &Task{}) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) up := mock.lastUpload() - assert.Equal(t, []byte("from_content"), up.Content) + core.AssertEqual(t, []byte("from_content"), up.Content) } -func TestModulesFile_ModuleCopy_Good_SkipsUnchangedContent(t *testing.T) { +func TestModulesFile_ModuleCopy_Good_SkipsUnchangedContent(t *core.T) { e, mock := newTestExecutorWithMock("host1") e.Diff = true mock.addFile("/etc/app/config", []byte("server_name=web01")) @@ -305,13 +302,13 @@ func TestModulesFile_ModuleCopy_Good_SkipsUnchangedContent(t *testing.T) { "dest": "/etc/app/config", }, "host1", &Task{}) - require.NoError(t, err) - assert.False(t, result.Changed) - assert.Equal(t, 0, mock.uploadCount()) - assert.Contains(t, result.Msg, "already up to date") + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertEqual(t, 0, mock.uploadCount()) + core.AssertContains(t, result.Msg, "already up to date") } -func TestModulesFile_ModuleCopy_Good_ForceFalseSkipsExistingDest(t *testing.T) { +func TestModulesFile_ModuleCopy_Good_ForceFalseSkipsExistingDest(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/etc/app/config", []byte("server_name=old")) @@ -321,13 +318,13 @@ func TestModulesFile_ModuleCopy_Good_ForceFalseSkipsExistingDest(t *testing.T) { "force": false, }, "host1", &Task{}) - require.NoError(t, err) - assert.False(t, result.Changed) - assert.Equal(t, 0, mock.uploadCount()) - assert.Contains(t, result.Msg, "skipped existing destination") + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertEqual(t, 0, mock.uploadCount()) + core.AssertContains(t, result.Msg, "skipped existing destination") } -func TestModulesFile_ModuleCopy_Good_BackupExistingDest(t *testing.T) { +func TestModulesFile_ModuleCopy_Good_BackupExistingDest(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/etc/app/config", []byte("server_name=old")) @@ -337,22 +334,22 @@ func TestModulesFile_ModuleCopy_Good_BackupExistingDest(t *testing.T) { "backup": true, }, "host1", &Task{}) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) - require.NotNil(t, result.Data) + core.AssertNotNil(t, result.Data) backupPath, ok := result.Data["backup_file"].(string) - require.True(t, ok) - assert.Contains(t, backupPath, "/etc/app/config.") - assert.Equal(t, 2, mock.uploadCount()) + core.RequireTrue(t, ok) + core.AssertContains(t, backupPath, "/etc/app/config.") + core.AssertEqual(t, 2, mock.uploadCount()) backupContent, err := mock.Download(context.Background(), backupPath) - require.NoError(t, err) - assert.Equal(t, []byte("server_name=old"), backupContent) + core.RequireNoError(t, err) + core.AssertEqual(t, []byte("server_name=old"), backupContent) } // --- file module --- -func TestModulesFile_ModuleFile_Good_StateDirectory(t *testing.T) { +func TestModulesFile_ModuleFile_Good_StateDirectory(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleFileWithClient(e, mock, map[string]any{ @@ -360,15 +357,15 @@ func TestModulesFile_ModuleFile_Good_StateDirectory(t *testing.T) { "state": "directory", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // Should execute mkdir -p with default mode 0755 - assert.True(t, mock.hasExecuted(`mkdir -p "/var/lib/app"`)) - assert.True(t, mock.hasExecuted(`chmod 0755`)) + core.AssertTrue(t, mock.hasExecuted(`mkdir -p "/var/lib/app"`)) + core.AssertTrue(t, mock.hasExecuted(`chmod 0755`)) } -func TestModulesFile_ModuleFile_Good_StateDirectoryCustomMode(t *testing.T) { +func TestModulesFile_ModuleFile_Good_StateDirectoryCustomMode(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleFileWithClient(e, mock, map[string]any{ @@ -377,12 +374,12 @@ func TestModulesFile_ModuleFile_Good_StateDirectoryCustomMode(t *testing.T) { "mode": "0700", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`mkdir -p "/opt/data" && chmod 0700 "/opt/data"`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`mkdir -p "/opt/data" && chmod 0700 "/opt/data"`)) } -func TestModulesFile_ModuleFile_Good_StateAbsent(t *testing.T) { +func TestModulesFile_ModuleFile_Good_StateAbsent(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleFileWithClient(e, mock, map[string]any{ @@ -390,12 +387,12 @@ func TestModulesFile_ModuleFile_Good_StateAbsent(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`rm -rf "/tmp/old-dir"`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`rm -rf "/tmp/old-dir"`)) } -func TestModulesFile_ModuleFile_Good_StateTouch(t *testing.T) { +func TestModulesFile_ModuleFile_Good_StateTouch(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleFileWithClient(e, mock, map[string]any{ @@ -403,12 +400,12 @@ func TestModulesFile_ModuleFile_Good_StateTouch(t *testing.T) { "state": "touch", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`touch "/var/log/app.log"`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`touch "/var/log/app.log"`)) } -func TestModulesFile_ModuleFile_Good_StateLink(t *testing.T) { +func TestModulesFile_ModuleFile_Good_StateLink(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleFileWithClient(e, mock, map[string]any{ @@ -417,12 +414,12 @@ func TestModulesFile_ModuleFile_Good_StateLink(t *testing.T) { "src": "/opt/node/bin/node", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`ln -sf "/opt/node/bin/node" "/usr/local/bin/node"`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`ln -sf "/opt/node/bin/node" "/usr/local/bin/node"`)) } -func TestModulesFile_ModuleFile_Good_StateHard(t *testing.T) { +func TestModulesFile_ModuleFile_Good_StateHard(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleFileWithClient(e, mock, map[string]any{ @@ -431,12 +428,12 @@ func TestModulesFile_ModuleFile_Good_StateHard(t *testing.T) { "src": "/opt/node/bin/node", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`ln -f "/opt/node/bin/node" "/usr/local/bin/node"`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`ln -f "/opt/node/bin/node" "/usr/local/bin/node"`)) } -func TestModulesFile_ModuleFile_Bad_StateHardMissingSrc(t *testing.T) { +func TestModulesFile_ModuleFile_Bad_StateHardMissingSrc(t *core.T) { e, mock := newTestExecutorWithMock("host1") _, err := moduleFileWithClient(e, mock, map[string]any{ @@ -444,11 +441,11 @@ func TestModulesFile_ModuleFile_Bad_StateHardMissingSrc(t *testing.T) { "state": "hard", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "src required for hard state") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "src required for hard state") } -func TestModulesFile_ModuleFile_Bad_LinkMissingSrc(t *testing.T) { +func TestModulesFile_ModuleFile_Bad_LinkMissingSrc(t *core.T) { e, mock := newTestExecutorWithMock("host1") _, err := moduleFileWithClient(e, mock, map[string]any{ @@ -456,11 +453,11 @@ func TestModulesFile_ModuleFile_Bad_LinkMissingSrc(t *testing.T) { "state": "link", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "src required for link state") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "src required for link state") } -func TestModulesFile_ModuleFile_Good_OwnerGroupMode(t *testing.T) { +func TestModulesFile_ModuleFile_Good_OwnerGroupMode(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleFileWithClient(e, mock, map[string]any{ @@ -471,16 +468,16 @@ func TestModulesFile_ModuleFile_Good_OwnerGroupMode(t *testing.T) { "mode": "0775", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // Should have mkdir, chmod in the directory command, then chown and chgrp - assert.True(t, mock.hasExecuted(`mkdir -p "/var/lib/app/data" && chmod 0775 "/var/lib/app/data"`)) - assert.True(t, mock.hasExecuted(`chown www-data "/var/lib/app/data"`)) - assert.True(t, mock.hasExecuted(`chgrp www-data "/var/lib/app/data"`)) + core.AssertTrue(t, mock.hasExecuted(`mkdir -p "/var/lib/app/data" && chmod 0775 "/var/lib/app/data"`)) + core.AssertTrue(t, mock.hasExecuted(`chown www-data "/var/lib/app/data"`)) + core.AssertTrue(t, mock.hasExecuted(`chgrp www-data "/var/lib/app/data"`)) } -func TestModulesFile_ModuleFile_Good_RecurseOwner(t *testing.T) { +func TestModulesFile_ModuleFile_Good_RecurseOwner(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleFileWithClient(e, mock, map[string]any{ @@ -490,15 +487,15 @@ func TestModulesFile_ModuleFile_Good_RecurseOwner(t *testing.T) { "recurse": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // Should have both regular chown and recursive chown - assert.True(t, mock.hasExecuted(`chown www-data "/var/www"`)) - assert.True(t, mock.hasExecuted(`chown -R www-data "/var/www"`)) + core.AssertTrue(t, mock.hasExecuted(`chown www-data "/var/www"`)) + core.AssertTrue(t, mock.hasExecuted(`chown -R www-data "/var/www"`)) } -func TestModulesFile_ModuleFile_Good_RecurseGroupAndMode(t *testing.T) { +func TestModulesFile_ModuleFile_Good_RecurseGroupAndMode(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleFileWithClient(e, mock, map[string]any{ @@ -509,26 +506,26 @@ func TestModulesFile_ModuleFile_Good_RecurseGroupAndMode(t *testing.T) { "recurse": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) - assert.True(t, mock.hasExecuted(`chgrp appgroup "/srv/app"`)) - assert.True(t, mock.hasExecuted(`chgrp -R appgroup "/srv/app"`)) - assert.True(t, mock.hasExecuted(`chmod -R 0770 "/srv/app"`)) + core.AssertTrue(t, mock.hasExecuted(`chgrp appgroup "/srv/app"`)) + core.AssertTrue(t, mock.hasExecuted(`chgrp -R appgroup "/srv/app"`)) + core.AssertTrue(t, mock.hasExecuted(`chmod -R 0770 "/srv/app"`)) } -func TestModulesFile_ModuleFile_Bad_MissingPath(t *testing.T) { +func TestModulesFile_ModuleFile_Bad_MissingPath(t *core.T) { e, mock := newTestExecutorWithMock("host1") _, err := moduleFileWithClient(e, mock, map[string]any{ "state": "directory", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "path required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "path required") } -func TestModulesFile_ModuleFile_Good_DestAliasForPath(t *testing.T) { +func TestModulesFile_ModuleFile_Good_DestAliasForPath(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleFileWithClient(e, mock, map[string]any{ @@ -536,12 +533,12 @@ func TestModulesFile_ModuleFile_Good_DestAliasForPath(t *testing.T) { "state": "directory", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`mkdir -p "/opt/myapp"`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`mkdir -p "/opt/myapp"`)) } -func TestModulesFile_ModuleFile_Good_StateFileWithMode(t *testing.T) { +func TestModulesFile_ModuleFile_Good_StateFileWithMode(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleFileWithClient(e, mock, map[string]any{ @@ -550,12 +547,12 @@ func TestModulesFile_ModuleFile_Good_StateFileWithMode(t *testing.T) { "mode": "0600", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`chmod 0600 "/etc/config.yml"`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`chmod 0600 "/etc/config.yml"`)) } -func TestModulesFile_ModuleFile_Good_DirectoryCommandFailure(t *testing.T) { +func TestModulesFile_ModuleFile_Good_DirectoryCommandFailure(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("mkdir", "", "permission denied", 1) @@ -564,14 +561,14 @@ func TestModulesFile_ModuleFile_Good_DirectoryCommandFailure(t *testing.T) { "state": "directory", }) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, "permission denied") + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, "permission denied") } // --- lineinfile module --- -func TestModulesFile_ModuleLineinfile_Good_InsertLine(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_InsertLine(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleLineinfileWithClient(e, mock, map[string]any{ @@ -579,15 +576,15 @@ func TestModulesFile_ModuleLineinfile_Good_InsertLine(t *testing.T) { "line": "192.168.1.100 web01", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // Should use grep -qxF to check and echo to append - assert.True(t, mock.hasExecuted(`grep -qxF`)) - assert.True(t, mock.hasExecuted(`192.168.1.100 web01`)) + core.AssertTrue(t, mock.hasExecuted(`grep -qxF`)) + core.AssertTrue(t, mock.hasExecuted(`192.168.1.100 web01`)) } -func TestModulesFile_ModuleLineinfile_Good_ReplaceRegexp(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_ReplaceRegexp(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleLineinfileWithClient(e, mock, map[string]any{ @@ -596,14 +593,14 @@ func TestModulesFile_ModuleLineinfile_Good_ReplaceRegexp(t *testing.T) { "line": "PermitRootLogin no", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // Should use sed to replace - assert.True(t, mock.hasExecuted(`sed -i 's/\^#\?PermitRootLogin/PermitRootLogin no/'`)) + core.AssertTrue(t, mock.hasExecuted(`sed -i 's/\^#\?PermitRootLogin/PermitRootLogin no/'`)) } -func TestModulesFile_ModuleLineinfile_Good_RemoveLine(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_RemoveLine(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleLineinfileWithClient(e, mock, map[string]any{ @@ -612,15 +609,15 @@ func TestModulesFile_ModuleLineinfile_Good_RemoveLine(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // Should use sed to delete matching lines - assert.True(t, mock.hasExecuted(`sed -i '/\^192`)) - assert.True(t, mock.hasExecuted(`/d'`)) + core.AssertTrue(t, mock.hasExecuted(`sed -i '/\^192`)) + core.AssertTrue(t, mock.hasExecuted(`/d'`)) } -func TestModulesFile_ModuleLineinfile_Good_RegexpFallsBackToAppend(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_RegexpFallsBackToAppend(t *core.T) { e, mock := newTestExecutorWithMock("host1") // Simulate sed returning non-zero (pattern not found) mock.expectCommand("sed -i", "", "", 1) @@ -631,16 +628,16 @@ func TestModulesFile_ModuleLineinfile_Good_RegexpFallsBackToAppend(t *testing.T) "line": "setting=value", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // Should have attempted sed, then fallen back to echo append cmds := mock.executedCommands() - assert.GreaterOrEqual(t, len(cmds), 2) - assert.True(t, mock.hasExecuted(`echo`)) + core.AssertGreaterOrEqual(t, len(cmds), 2) + core.AssertTrue(t, mock.hasExecuted(`echo`)) } -func TestModulesFile_ModuleLineinfile_Good_CreateFile(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_CreateFile(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := e.moduleLineinfile(context.Background(), mock, map[string]any{ @@ -650,13 +647,13 @@ func TestModulesFile_ModuleLineinfile_Good_CreateFile(t *testing.T) { "create": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`touch "/etc/example\.conf"`)) - assert.True(t, mock.hasExecuted(`sed -i`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`touch "/etc/example\.conf"`)) + core.AssertTrue(t, mock.hasExecuted(`sed -i`)) } -func TestModulesFile_ModuleLineinfile_Good_BackrefsReplaceMatchOnly(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_BackrefsReplaceMatchOnly(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleLineinfileWithClient(e, mock, map[string]any{ @@ -666,19 +663,19 @@ func TestModulesFile_ModuleLineinfile_Good_BackrefsReplaceMatchOnly(t *testing.T "backrefs": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`grep -Eq`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`grep -Eq`)) cmd := mock.lastCommand() - assert.Equal(t, "Run", cmd.Method) - assert.Contains(t, cmd.Cmd, "sed -E -i") - assert.Contains(t, cmd.Cmd, "s/^(foo=).*$") - assert.Contains(t, cmd.Cmd, "\\1bar") - assert.Contains(t, cmd.Cmd, `"/etc/example.conf"`) - assert.False(t, mock.hasExecuted(`echo`)) + core.AssertEqual(t, "Run", cmd.Method) + core.AssertContains(t, cmd.Cmd, "sed -E -i") + core.AssertContains(t, cmd.Cmd, "s/^(foo=).*$") + core.AssertContains(t, cmd.Cmd, "\\1bar") + core.AssertContains(t, cmd.Cmd, `"/etc/example.conf"`) + core.AssertFalse(t, mock.hasExecuted(`echo`)) } -func TestModulesFile_ModuleLineinfile_Good_BackrefsNoMatchNoAppend(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_BackrefsNoMatchNoAppend(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("grep -Eq", "", "", 1) @@ -689,14 +686,14 @@ func TestModulesFile_ModuleLineinfile_Good_BackrefsNoMatchNoAppend(t *testing.T) "backrefs": true, }) - require.NoError(t, err) - assert.False(t, result.Changed) - assert.Equal(t, 1, mock.commandCount()) - assert.Contains(t, mock.lastCommand().Cmd, "grep -Eq") - assert.False(t, mock.hasExecuted(`echo`)) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertEqual(t, 1, mock.commandCount()) + core.AssertContains(t, mock.lastCommand().Cmd, "grep -Eq") + core.AssertFalse(t, mock.hasExecuted(`echo`)) } -func TestModulesFile_ModuleLineinfile_Good_InsertBeforeAnchor(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_InsertBeforeAnchor(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := e.moduleLineinfile(context.Background(), mock, map[string]any{ @@ -706,13 +703,13 @@ func TestModulesFile_ModuleLineinfile_Good_InsertBeforeAnchor(t *testing.T) { "firstmatch": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`grep -Eq`)) - assert.True(t, mock.hasExecuted(regexp.QuoteMeta("print line; done=1 } print"))) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`grep -Eq`)) + core.AssertTrue(t, mock.hasExecuted(regexp.QuoteMeta("print line; done=1 } print"))) } -func TestModulesFile_ModuleLineinfile_Good_InsertAfterAnchor(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_InsertAfterAnchor(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := e.moduleLineinfile(context.Background(), mock, map[string]any{ @@ -722,13 +719,13 @@ func TestModulesFile_ModuleLineinfile_Good_InsertAfterAnchor(t *testing.T) { "firstmatch": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`grep -Eq`)) - assert.True(t, mock.hasExecuted(regexp.QuoteMeta("print; if (!done && $0 ~ re) { print line; done=1 }"))) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`grep -Eq`)) + core.AssertTrue(t, mock.hasExecuted(regexp.QuoteMeta("print; if (!done && $0 ~ re) { print line; done=1 }"))) } -func TestModulesFile_ModuleLineinfile_Good_InsertAfterAnchor_DefaultUsesLastMatch(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_InsertAfterAnchor_DefaultUsesLastMatch(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := e.moduleLineinfile(context.Background(), mock, map[string]any{ @@ -737,25 +734,25 @@ func TestModulesFile_ModuleLineinfile_Good_InsertAfterAnchor_DefaultUsesLastMatc "insertafter": "^# managed settings", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`grep -Eq`)) - assert.True(t, mock.hasExecuted("pos=NR")) - assert.False(t, mock.hasExecuted("done=1")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`grep -Eq`)) + core.AssertTrue(t, mock.hasExecuted("pos=NR")) + core.AssertFalse(t, mock.hasExecuted("done=1")) } -func TestModulesFile_ModuleLineinfile_Bad_MissingPath(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Bad_MissingPath(t *core.T) { e, mock := newTestExecutorWithMock("host1") _, err := moduleLineinfileWithClient(e, mock, map[string]any{ "line": "test", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "path required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "path required") } -func TestModulesFile_ModuleLineinfile_Good_DestAliasForPath(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_DestAliasForPath(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleLineinfileWithClient(e, mock, map[string]any{ @@ -763,12 +760,12 @@ func TestModulesFile_ModuleLineinfile_Good_DestAliasForPath(t *testing.T) { "line": "key=value", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`/etc/config`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`/etc/config`)) } -func TestModulesFile_ModuleLineinfile_Good_AbsentWithNoRegexp(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_AbsentWithNoRegexp(t *core.T) { // When state=absent but no regexp, nothing happens (no commands) e, mock := newTestExecutorWithMock("host1") @@ -777,12 +774,12 @@ func TestModulesFile_ModuleLineinfile_Good_AbsentWithNoRegexp(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, 0, mock.commandCount()) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, 0, mock.commandCount()) } -func TestModulesFile_ModuleLineinfile_Good_LineWithSlashes(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_LineWithSlashes(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleLineinfileWithClient(e, mock, map[string]any{ @@ -791,14 +788,14 @@ func TestModulesFile_ModuleLineinfile_Good_LineWithSlashes(t *testing.T) { "line": "root /var/www/html;", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // Slashes in the line should be escaped - assert.True(t, mock.hasExecuted(`root \\/var\\/www\\/html;`)) + core.AssertTrue(t, mock.hasExecuted(`root \\/var\\/www\\/html;`)) } -func TestModulesFile_ModuleLineinfile_Good_ExactLineAlreadyPresentIsNoOp(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_ExactLineAlreadyPresentIsNoOp(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/etc/example.conf", []byte("setting=value\nother=1\n")) @@ -807,13 +804,13 @@ func TestModulesFile_ModuleLineinfile_Good_ExactLineAlreadyPresentIsNoOp(t *test "line": "setting=value", }) - require.NoError(t, err) - assert.False(t, result.Changed) - assert.Contains(t, result.Msg, "already up to date") - assert.Equal(t, 0, mock.commandCount()) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertContains(t, result.Msg, "already up to date") + core.AssertEqual(t, 0, mock.commandCount()) } -func TestModulesFile_ModuleLineinfile_Good_SearchStringReplacesMatchingLine(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_SearchStringReplacesMatchingLine(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/etc/ssh/sshd_config", []byte("PermitRootLogin yes\nPasswordAuthentication yes\n")) @@ -823,15 +820,15 @@ func TestModulesFile_ModuleLineinfile_Good_SearchStringReplacesMatchingLine(t *t "line": "PermitRootLogin no", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) after, err := mock.Download(context.Background(), "/etc/ssh/sshd_config") - require.NoError(t, err) - assert.Equal(t, "PermitRootLogin no\nPasswordAuthentication yes\n", string(after)) + core.RequireNoError(t, err) + core.AssertEqual(t, "PermitRootLogin no\nPasswordAuthentication yes\n", string(after)) } -func TestModulesFile_ModuleLineinfile_Good_SearchStringRemovesMatchingLine(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_SearchStringRemovesMatchingLine(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/etc/ssh/sshd_config", []byte("PermitRootLogin yes\nPasswordAuthentication yes\n")) @@ -841,15 +838,15 @@ func TestModulesFile_ModuleLineinfile_Good_SearchStringRemovesMatchingLine(t *te "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) after, err := mock.Download(context.Background(), "/etc/ssh/sshd_config") - require.NoError(t, err) - assert.Equal(t, "PasswordAuthentication yes\n", string(after)) + core.RequireNoError(t, err) + core.AssertEqual(t, "PasswordAuthentication yes\n", string(after)) } -func TestModulesFile_ModuleLineinfile_Good_BackupExistingFile(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_BackupExistingFile(t *core.T) { e, mock := newTestExecutorWithMock("host1") path := "/etc/example.conf" mock.addFile(path, []byte("setting=old\n")) @@ -860,20 +857,20 @@ func TestModulesFile_ModuleLineinfile_Good_BackupExistingFile(t *testing.T) { "backup": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - require.NotNil(t, result.Data) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertNotNil(t, result.Data) backupPath, ok := result.Data["backup_file"].(string) - require.True(t, ok) - assert.Contains(t, backupPath, "/etc/example.conf.") + core.RequireTrue(t, ok) + core.AssertContains(t, backupPath, "/etc/example.conf.") backupContent, err := mock.Download(context.Background(), backupPath) - require.NoError(t, err) - assert.Equal(t, []byte("setting=old\n"), backupContent) + core.RequireNoError(t, err) + core.AssertEqual(t, []byte("setting=old\n"), backupContent) } -func TestModulesFile_ModuleLineinfile_Good_DiffData(t *testing.T) { +func TestModulesFile_ModuleLineinfile_Good_DiffData(t *core.T) { e := NewExecutor("/tmp") e.Diff = true @@ -886,20 +883,20 @@ func TestModulesFile_ModuleLineinfile_Good_DiffData(t *testing.T) { "line": "setting=new", }) - require.NoError(t, err) - assert.True(t, result.Changed) - require.NotNil(t, result.Data) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertNotNil(t, result.Data) diff, ok := result.Data["diff"].(map[string]any) - require.True(t, ok) - assert.Equal(t, "/etc/example.conf", diff["path"]) - assert.Equal(t, "setting=old\n", diff["before"]) - assert.Contains(t, diff["after"], "setting=new") + core.RequireTrue(t, ok) + core.AssertEqual(t, "/etc/example.conf", diff["path"]) + core.AssertEqual(t, "setting=old\n", diff["before"]) + core.AssertContains(t, diff["after"], "setting=new") } // --- replace module --- -func TestModulesFile_ModuleReplace_Good_RegexpReplacementWithBackupAndDiff(t *testing.T) { +func TestModulesFile_ModuleReplace_Good_RegexpReplacementWithBackupAndDiff(t *core.T) { e := NewExecutor("/tmp") e.Diff = true client := newDiffFileClient(map[string]string{ @@ -913,24 +910,24 @@ func TestModulesFile_ModuleReplace_Good_RegexpReplacementWithBackupAndDiff(t *te "backup": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - require.NotNil(t, result.Data) - assert.Contains(t, result.Data, "backup_file") - assert.Contains(t, result.Data, "diff") + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertNotNil(t, result.Data) + core.AssertContains(t, result.Data, "backup_file") + core.AssertContains(t, result.Data, "diff") after, err := client.Download(context.Background(), "/etc/app.conf") - require.NoError(t, err) - assert.Equal(t, "port=9090\nmode=prod\n", string(after)) + core.RequireNoError(t, err) + core.AssertEqual(t, "port=9090\nmode=prod\n", string(after)) backupPath, _ := result.Data["backup_file"].(string) - require.NotEmpty(t, backupPath) + core.RequireNotEmpty(t, backupPath) backup, err := client.Download(context.Background(), backupPath) - require.NoError(t, err) - assert.Equal(t, "port=8080\nmode=prod\n", string(backup)) + core.RequireNoError(t, err) + core.AssertEqual(t, "port=8080\nmode=prod\n", string(backup)) } -func TestModulesFile_ModuleReplace_Good_NoOpWhenPatternMissing(t *testing.T) { +func TestModulesFile_ModuleReplace_Good_NoOpWhenPatternMissing(t *core.T) { e := NewExecutor("/tmp") client := newDiffFileClient(map[string]string{ "/etc/app.conf": "port=8080\n", @@ -942,12 +939,12 @@ func TestModulesFile_ModuleReplace_Good_NoOpWhenPatternMissing(t *testing.T) { "replace": "mode=prod", }) - require.NoError(t, err) - assert.False(t, result.Changed) - assert.Contains(t, result.Msg, "already up to date") + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertContains(t, result.Msg, "already up to date") } -func TestModulesFile_ModuleReplace_Bad_MissingPath(t *testing.T) { +func TestModulesFile_ModuleReplace_Bad_MissingPath(t *core.T) { e := NewExecutor("/tmp") client := newDiffFileClient(nil) @@ -956,13 +953,13 @@ func TestModulesFile_ModuleReplace_Bad_MissingPath(t *testing.T) { "replace": "mode=prod", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "path required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "path required") } // --- blockinfile module --- -func TestModulesFile_ModuleBlockinfile_Good_InsertBlock(t *testing.T) { +func TestModulesFile_ModuleBlockinfile_Good_InsertBlock(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleBlockinfileWithClient(e, mock, map[string]any{ @@ -970,16 +967,16 @@ func TestModulesFile_ModuleBlockinfile_Good_InsertBlock(t *testing.T) { "block": "server 10.0.0.1:8080;\nserver 10.0.0.2:8080;", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // Should use RunScript for the heredoc approach - assert.True(t, mock.hasExecutedMethod("RunScript", "BEGIN ANSIBLE MANAGED BLOCK")) - assert.True(t, mock.hasExecutedMethod("RunScript", "END ANSIBLE MANAGED BLOCK")) - assert.True(t, mock.hasExecutedMethod("RunScript", "10\\.0\\.0\\.1")) + core.AssertTrue(t, mock.hasExecutedMethod("RunScript", "BEGIN ANSIBLE MANAGED BLOCK")) + core.AssertTrue(t, mock.hasExecutedMethod("RunScript", "END ANSIBLE MANAGED BLOCK")) + core.AssertTrue(t, mock.hasExecutedMethod("RunScript", "10\\.0\\.0\\.1")) } -func TestModulesFile_ModuleBlockinfile_Good_CustomMarkers(t *testing.T) { +func TestModulesFile_ModuleBlockinfile_Good_CustomMarkers(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleBlockinfileWithClient(e, mock, map[string]any{ @@ -988,15 +985,15 @@ func TestModulesFile_ModuleBlockinfile_Good_CustomMarkers(t *testing.T) { "marker": "# {mark} managed by devops", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // Should use custom markers instead of default - assert.True(t, mock.hasExecutedMethod("RunScript", "# BEGIN managed by devops")) - assert.True(t, mock.hasExecutedMethod("RunScript", "# END managed by devops")) + core.AssertTrue(t, mock.hasExecutedMethod("RunScript", "# BEGIN managed by devops")) + core.AssertTrue(t, mock.hasExecutedMethod("RunScript", "# END managed by devops")) } -func TestModulesFile_ModuleBlockinfile_Good_CustomMarkerBeginAndEnd(t *testing.T) { +func TestModulesFile_ModuleBlockinfile_Good_CustomMarkerBeginAndEnd(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := e.moduleBlockinfile(context.Background(), mock, map[string]any{ @@ -1007,13 +1004,13 @@ func TestModulesFile_ModuleBlockinfile_Good_CustomMarkerBeginAndEnd(t *testing.T "marker_end": "STOP", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecutedMethod("RunScript", "# START managed by app")) - assert.True(t, mock.hasExecutedMethod("RunScript", "# STOP managed by app")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecutedMethod("RunScript", "# START managed by app")) + core.AssertTrue(t, mock.hasExecutedMethod("RunScript", "# STOP managed by app")) } -func TestModulesFile_ModuleBlockinfile_Good_NewlinePadding(t *testing.T) { +func TestModulesFile_ModuleBlockinfile_Good_NewlinePadding(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleBlockinfileWithClient(e, mock, map[string]any{ @@ -1023,14 +1020,14 @@ func TestModulesFile_ModuleBlockinfile_Good_NewlinePadding(t *testing.T) { "append_newline": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) cmd := mock.lastCommand().Cmd - assert.Contains(t, cmd, "\n\n# BEGIN ANSIBLE MANAGED BLOCK\n10.0.0.5 db01\n# END ANSIBLE MANAGED BLOCK\n") + core.AssertContains(t, cmd, "\n\n# BEGIN ANSIBLE MANAGED BLOCK\n10.0.0.5 db01\n# END ANSIBLE MANAGED BLOCK\n") } -func TestModulesFile_ModuleBlockinfile_Good_RemoveBlock(t *testing.T) { +func TestModulesFile_ModuleBlockinfile_Good_RemoveBlock(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleBlockinfileWithClient(e, mock, map[string]any{ @@ -1038,14 +1035,14 @@ func TestModulesFile_ModuleBlockinfile_Good_RemoveBlock(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // Should use sed to remove the block between markers - assert.True(t, mock.hasExecuted(`sed -i '/.*BEGIN ANSIBLE MANAGED BLOCK/,/.*END ANSIBLE MANAGED BLOCK/d'`)) + core.AssertTrue(t, mock.hasExecuted(`sed -i '/.*BEGIN ANSIBLE MANAGED BLOCK/,/.*END ANSIBLE MANAGED BLOCK/d'`)) } -func TestModulesFile_ModuleBlockinfile_Good_RemoveBlockWithBackup(t *testing.T) { +func TestModulesFile_ModuleBlockinfile_Good_RemoveBlockWithBackup(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/etc/config", []byte("before\n# BEGIN ANSIBLE MANAGED BLOCK\nmanaged\n# END ANSIBLE MANAGED BLOCK\nafter\n")) @@ -1055,20 +1052,20 @@ func TestModulesFile_ModuleBlockinfile_Good_RemoveBlockWithBackup(t *testing.T) "backup": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - require.NotNil(t, result.Data) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertNotNil(t, result.Data) backupPath, ok := result.Data["backup_file"].(string) - require.True(t, ok) - assert.Contains(t, backupPath, "/etc/config.") + core.RequireTrue(t, ok) + core.AssertContains(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) + core.RequireNoError(t, err) + core.AssertEqual(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) { +func TestModulesFile_ModuleBlockinfile_Good_RemoveBlockWithCustomMarkerBeginAndEnd(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := e.moduleBlockinfile(context.Background(), mock, map[string]any{ @@ -1079,12 +1076,12 @@ func TestModulesFile_ModuleBlockinfile_Good_RemoveBlockWithCustomMarkerBeginAndE "marker_end": "STOP", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`sed -i '/.*START managed by app/,/.*STOP managed by app/d'`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`sed -i '/.*START managed by app/,/.*STOP managed by app/d'`)) } -func TestModulesFile_ModuleBlockinfile_Good_CreateFile(t *testing.T) { +func TestModulesFile_ModuleBlockinfile_Good_CreateFile(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleBlockinfileWithClient(e, mock, map[string]any{ @@ -1093,14 +1090,14 @@ func TestModulesFile_ModuleBlockinfile_Good_CreateFile(t *testing.T) { "create": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // Should touch the file first when create=true - assert.True(t, mock.hasExecuted(`touch "/etc/new-config"`)) + core.AssertTrue(t, mock.hasExecuted(`touch "/etc/new-config"`)) } -func TestModulesFile_ModuleBlockinfile_Good_BackupExistingDest(t *testing.T) { +func TestModulesFile_ModuleBlockinfile_Good_BackupExistingDest(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/etc/config", []byte("old block contents")) @@ -1110,21 +1107,21 @@ func TestModulesFile_ModuleBlockinfile_Good_BackupExistingDest(t *testing.T) { "backup": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - require.NotNil(t, result.Data) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertNotNil(t, result.Data) backupPath, ok := result.Data["backup_file"].(string) - require.True(t, ok) - assert.Contains(t, backupPath, "/etc/config.") - assert.Equal(t, 1, mock.uploadCount()) + core.RequireTrue(t, ok) + core.AssertContains(t, backupPath, "/etc/config.") + core.AssertEqual(t, 1, mock.uploadCount()) backupContent, err := mock.Download(context.Background(), backupPath) - require.NoError(t, err) - assert.Equal(t, []byte("old block contents"), backupContent) + core.RequireNoError(t, err) + core.AssertEqual(t, []byte("old block contents"), backupContent) } -func TestModulesFile_ModuleBlockinfile_Good_DiffData(t *testing.T) { +func TestModulesFile_ModuleBlockinfile_Good_DiffData(t *core.T) { e := NewExecutor("/tmp") e.Diff = true @@ -1137,29 +1134,29 @@ func TestModulesFile_ModuleBlockinfile_Good_DiffData(t *testing.T) { "block": "new block contents", }) - require.NoError(t, err) - assert.True(t, result.Changed) - require.NotNil(t, result.Data) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertNotNil(t, result.Data) diff, ok := result.Data["diff"].(map[string]any) - require.True(t, ok) - assert.Equal(t, "/etc/config", diff["path"]) - assert.Equal(t, "old block contents\n", diff["before"]) - assert.Contains(t, diff["after"], "new block contents") + core.RequireTrue(t, ok) + core.AssertEqual(t, "/etc/config", diff["path"]) + core.AssertEqual(t, "old block contents\n", diff["before"]) + core.AssertContains(t, diff["after"], "new block contents") } -func TestModulesFile_ModuleBlockinfile_Bad_MissingPath(t *testing.T) { +func TestModulesFile_ModuleBlockinfile_Bad_MissingPath(t *core.T) { e, mock := newTestExecutorWithMock("host1") _, err := moduleBlockinfileWithClient(e, mock, map[string]any{ "block": "content", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "path required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "path required") } -func TestModulesFile_ModuleBlockinfile_Good_DestAliasForPath(t *testing.T) { +func TestModulesFile_ModuleBlockinfile_Good_DestAliasForPath(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleBlockinfileWithClient(e, mock, map[string]any{ @@ -1167,11 +1164,11 @@ func TestModulesFile_ModuleBlockinfile_Good_DestAliasForPath(t *testing.T) { "block": "data", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) } -func TestModulesFile_ModuleBlockinfile_Good_ScriptFailure(t *testing.T) { +func TestModulesFile_ModuleBlockinfile_Good_ScriptFailure(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand("BLOCK_EOF", "", "write error", 1) @@ -1180,14 +1177,14 @@ func TestModulesFile_ModuleBlockinfile_Good_ScriptFailure(t *testing.T) { "block": "data", }) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, "write error") + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, "write error") } // --- stat module --- -func TestModulesFile_ModuleStat_Good_ExistingFile(t *testing.T) { +func TestModulesFile_ModuleStat_Good_ExistingFile(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addStat("/etc/nginx/nginx.conf", map[string]any{ "exists": true, @@ -1202,35 +1199,35 @@ func TestModulesFile_ModuleStat_Good_ExistingFile(t *testing.T) { "path": "/etc/nginx/nginx.conf", }) - require.NoError(t, err) - assert.False(t, result.Changed) // stat never changes anything - require.NotNil(t, result.Data) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) // stat never changes anything + core.AssertNotNil(t, result.Data) stat, ok := result.Data["stat"].(map[string]any) - require.True(t, ok) - assert.Equal(t, true, stat["exists"]) - assert.Equal(t, false, stat["isdir"]) - assert.Equal(t, "0644", stat["mode"]) - assert.Equal(t, 1234, stat["size"]) + core.RequireTrue(t, ok) + core.AssertEqual(t, true, stat["exists"]) + core.AssertEqual(t, false, stat["isdir"]) + core.AssertEqual(t, "0644", stat["mode"]) + core.AssertEqual(t, 1234, stat["size"]) } -func TestModulesFile_ModuleStat_Good_MissingFile(t *testing.T) { +func TestModulesFile_ModuleStat_Good_MissingFile(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleStatWithClient(e, mock, map[string]any{ "path": "/nonexistent/file.txt", }) - require.NoError(t, err) - assert.False(t, result.Changed) - require.NotNil(t, result.Data) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertNotNil(t, result.Data) stat, ok := result.Data["stat"].(map[string]any) - require.True(t, ok) - assert.Equal(t, false, stat["exists"]) + core.RequireTrue(t, ok) + core.AssertEqual(t, false, stat["exists"]) } -func TestModulesFile_ModuleStat_Good_Directory(t *testing.T) { +func TestModulesFile_ModuleStat_Good_Directory(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addStat("/var/log", map[string]any{ "exists": true, @@ -1242,13 +1239,13 @@ func TestModulesFile_ModuleStat_Good_Directory(t *testing.T) { "path": "/var/log", }) - require.NoError(t, err) + core.RequireNoError(t, err) stat := result.Data["stat"].(map[string]any) - assert.Equal(t, true, stat["exists"]) - assert.Equal(t, true, stat["isdir"]) + core.AssertEqual(t, true, stat["exists"]) + core.AssertEqual(t, true, stat["isdir"]) } -func TestModulesFile_ModuleStat_Good_FallbackFromFileSystem(t *testing.T) { +func TestModulesFile_ModuleStat_Good_FallbackFromFileSystem(t *core.T) { e, mock := newTestExecutorWithMock("host1") // No explicit stat, but add a file — stat falls back to file existence mock.addFile("/etc/hosts", []byte("127.0.0.1 localhost")) @@ -1257,27 +1254,27 @@ func TestModulesFile_ModuleStat_Good_FallbackFromFileSystem(t *testing.T) { "path": "/etc/hosts", }) - require.NoError(t, err) + core.RequireNoError(t, err) stat := result.Data["stat"].(map[string]any) - assert.Equal(t, true, stat["exists"]) - assert.Equal(t, false, stat["isdir"]) + core.AssertEqual(t, true, stat["exists"]) + core.AssertEqual(t, false, stat["isdir"]) } -func TestModulesFile_ModuleStat_Bad_MissingPath(t *testing.T) { +func TestModulesFile_ModuleStat_Bad_MissingPath(t *core.T) { e, mock := newTestExecutorWithMock("host1") _, err := moduleStatWithClient(e, mock, map[string]any{}) - assert.Error(t, err) - assert.Contains(t, err.Error(), "path required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "path required") } // --- template module --- -func TestModulesFile_ModuleTemplate_Good_BasicTemplate(t *testing.T) { +func TestModulesFile_ModuleTemplate_Good_BasicTemplate(t *core.T) { tmpDir := t.TempDir() srcPath := joinPath(tmpDir, "app.conf.j2") - require.NoError(t, writeTestFile(srcPath, []byte("server_name={{ server_name }};"), 0644)) + core.RequireNoError(t, writeTestFile(srcPath, []byte("server_name={{ server_name }};"), 0644)) e, mock := newTestExecutorWithMock("host1") e.SetVar("server_name", "web01.example.com") @@ -1287,23 +1284,23 @@ func TestModulesFile_ModuleTemplate_Good_BasicTemplate(t *testing.T) { "dest": "/etc/nginx/conf.d/app.conf", }, "host1", &Task{}) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Contains(t, result.Msg, "templated to /etc/nginx/conf.d/app.conf") + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertContains(t, result.Msg, "templated to /etc/nginx/conf.d/app.conf") // Verify upload was performed with templated content - assert.Equal(t, 1, mock.uploadCount()) + core.AssertEqual(t, 1, mock.uploadCount()) up := mock.lastUpload() - require.NotNil(t, up) - assert.Equal(t, "/etc/nginx/conf.d/app.conf", up.Remote) + core.AssertNotNil(t, up) + core.AssertEqual(t, "/etc/nginx/conf.d/app.conf", up.Remote) // Template replaces {{ var }} — the TemplateFile does Jinja2 to Go conversion - assert.Contains(t, string(up.Content), "web01.example.com") + core.AssertContains(t, string(up.Content), "web01.example.com") } -func TestModulesFile_ModuleTemplate_Good_AnsibleFactsMapTemplate(t *testing.T) { +func TestModulesFile_ModuleTemplate_Good_AnsibleFactsMapTemplate(t *core.T) { tmpDir := t.TempDir() srcPath := joinPath(tmpDir, "facts.conf.j2") - require.NoError(t, writeTestFile(srcPath, []byte("host={{ ansible_facts.ansible_hostname }}"), 0644)) + core.RequireNoError(t, writeTestFile(srcPath, []byte("host={{ ansible_facts.ansible_hostname }}"), 0644)) e, mock := newTestExecutorWithMock("host1") e.facts["host1"] = &Facts{ @@ -1316,18 +1313,18 @@ func TestModulesFile_ModuleTemplate_Good_AnsibleFactsMapTemplate(t *testing.T) { "dest": "/etc/app/facts.conf", }, "host1", &Task{}) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) up := mock.lastUpload() - require.NotNil(t, up) - assert.Contains(t, string(up.Content), "host=web01") + core.AssertNotNil(t, up) + core.AssertContains(t, string(up.Content), "host=web01") } -func TestModulesFile_ModuleTemplate_Good_TaskVarsAndHostMagicVars(t *testing.T) { +func TestModulesFile_ModuleTemplate_Good_TaskVarsAndHostMagicVars(t *core.T) { tmpDir := t.TempDir() srcPath := joinPath(tmpDir, "context.conf.j2") - require.NoError(t, writeTestFile(srcPath, []byte("short={{ inventory_hostname_short }} local={{ local_value }}"), 0644)) + core.RequireNoError(t, writeTestFile(srcPath, []byte("short={{ inventory_hostname_short }} local={{ local_value }}"), 0644)) e, mock := newTestExecutorWithMock("web01.example.com") task := &Task{ @@ -1341,19 +1338,19 @@ func TestModulesFile_ModuleTemplate_Good_TaskVarsAndHostMagicVars(t *testing.T) "dest": "/etc/app/context.conf", }, "web01.example.com", task) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) up := mock.lastUpload() - require.NotNil(t, up) - assert.Contains(t, string(up.Content), "short=web01") - assert.Contains(t, string(up.Content), "local=from-task") + core.AssertNotNil(t, up) + core.AssertContains(t, string(up.Content), "short=web01") + core.AssertContains(t, string(up.Content), "local=from-task") } -func TestModulesFile_ModuleTemplate_Good_CustomMode(t *testing.T) { +func TestModulesFile_ModuleTemplate_Good_CustomMode(t *core.T) { tmpDir := t.TempDir() srcPath := joinPath(tmpDir, "script.sh.j2") - require.NoError(t, writeTestFile(srcPath, []byte("#!/bin/bash\necho done"), 0644)) + core.RequireNoError(t, writeTestFile(srcPath, []byte("#!/bin/bash\necho done"), 0644)) e, mock := newTestExecutorWithMock("host1") @@ -1363,18 +1360,18 @@ func TestModulesFile_ModuleTemplate_Good_CustomMode(t *testing.T) { "mode": "0755", }, "host1", &Task{}) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) up := mock.lastUpload() - require.NotNil(t, up) - assert.Equal(t, fs.FileMode(0755), up.Mode) + core.AssertNotNil(t, up) + core.AssertEqual(t, fs.FileMode(0755), up.Mode) } -func TestModulesFile_ModuleTemplate_Good_ForceFalseSkipsExistingDest(t *testing.T) { +func TestModulesFile_ModuleTemplate_Good_ForceFalseSkipsExistingDest(t *core.T) { tmpDir := t.TempDir() srcPath := joinPath(tmpDir, "config.tmpl") - require.NoError(t, writeTestFile(srcPath, []byte("server_name={{ inventory_hostname }}"), 0644)) + core.RequireNoError(t, writeTestFile(srcPath, []byte("server_name={{ inventory_hostname }}"), 0644)) e, mock := newTestExecutorWithMock("host1") mock.addFile("/etc/app/config", []byte("server_name=old")) @@ -1385,16 +1382,16 @@ func TestModulesFile_ModuleTemplate_Good_ForceFalseSkipsExistingDest(t *testing. "force": false, }, "host1", &Task{}) - require.NoError(t, err) - assert.False(t, result.Changed) - assert.Equal(t, 0, mock.uploadCount()) - assert.Contains(t, result.Msg, "skipped existing destination") + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertEqual(t, 0, mock.uploadCount()) + core.AssertContains(t, result.Msg, "skipped existing destination") } -func TestModulesFile_ModuleTemplate_Good_BackupExistingDest(t *testing.T) { +func TestModulesFile_ModuleTemplate_Good_BackupExistingDest(t *core.T) { tmpDir := t.TempDir() srcPath := joinPath(tmpDir, "config.tmpl") - require.NoError(t, writeTestFile(srcPath, []byte("server_name={{ inventory_hostname }}"), 0644)) + core.RequireNoError(t, writeTestFile(srcPath, []byte("server_name={{ inventory_hostname }}"), 0644)) e, mock := newTestExecutorWithMock("host1") mock.addFile("/etc/app/config", []byte("server_name=old")) @@ -1405,42 +1402,42 @@ func TestModulesFile_ModuleTemplate_Good_BackupExistingDest(t *testing.T) { "backup": true, }, "host1", &Task{}) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) - require.NotNil(t, result.Data) + core.AssertNotNil(t, result.Data) backupPath, ok := result.Data["backup_file"].(string) - require.True(t, ok) - assert.Contains(t, backupPath, "/etc/app/config.") - assert.Equal(t, 2, mock.uploadCount()) + core.RequireTrue(t, ok) + core.AssertContains(t, backupPath, "/etc/app/config.") + core.AssertEqual(t, 2, mock.uploadCount()) backupContent, err := mock.Download(context.Background(), backupPath) - require.NoError(t, err) - assert.Equal(t, []byte("server_name=old"), backupContent) + core.RequireNoError(t, err) + core.AssertEqual(t, []byte("server_name=old"), backupContent) } -func TestModulesFile_ModuleTemplate_Bad_MissingSrc(t *testing.T) { +func TestModulesFile_ModuleTemplate_Bad_MissingSrc(t *core.T) { e, mock := newTestExecutorWithMock("host1") _, err := moduleTemplateWithClient(e, mock, map[string]any{ "dest": "/tmp/out", }, "host1", &Task{}) - assert.Error(t, err) - assert.Contains(t, err.Error(), "src and dest required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "src and dest required") } -func TestModulesFile_ModuleTemplate_Bad_MissingDest(t *testing.T) { +func TestModulesFile_ModuleTemplate_Bad_MissingDest(t *core.T) { e, mock := newTestExecutorWithMock("host1") _, err := moduleTemplateWithClient(e, mock, map[string]any{ "src": "/tmp/in.j2", }, "host1", &Task{}) - assert.Error(t, err) - assert.Contains(t, err.Error(), "src and dest required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "src and dest required") } -func TestModulesFile_ModuleTemplate_Bad_SrcFileNotFound(t *testing.T) { +func TestModulesFile_ModuleTemplate_Bad_SrcFileNotFound(t *core.T) { e, mock := newTestExecutorWithMock("host1") _, err := moduleTemplateWithClient(e, mock, map[string]any{ @@ -1448,15 +1445,15 @@ func TestModulesFile_ModuleTemplate_Bad_SrcFileNotFound(t *testing.T) { "dest": "/tmp/out", }, "host1", &Task{}) - assert.Error(t, err) - assert.Contains(t, err.Error(), "template") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "template") } -func TestModulesFile_ModuleTemplate_Good_PlainTextNoVars(t *testing.T) { +func TestModulesFile_ModuleTemplate_Good_PlainTextNoVars(t *core.T) { tmpDir := t.TempDir() srcPath := joinPath(tmpDir, "static.conf") content := "listen 80;\nserver_name localhost;" - require.NoError(t, writeTestFile(srcPath, []byte(content), 0644)) + core.RequireNoError(t, writeTestFile(srcPath, []byte(content), 0644)) e, mock := newTestExecutorWithMock("host1") @@ -1465,18 +1462,18 @@ func TestModulesFile_ModuleTemplate_Good_PlainTextNoVars(t *testing.T) { "dest": "/etc/config", }, "host1", &Task{}) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) up := mock.lastUpload() - require.NotNil(t, up) - assert.Equal(t, content, string(up.Content)) + core.AssertNotNil(t, up) + core.AssertEqual(t, content, string(up.Content)) } -func TestModulesFile_ModuleTemplate_Good_DiffData(t *testing.T) { +func TestModulesFile_ModuleTemplate_Good_DiffData(t *core.T) { tmpDir := t.TempDir() srcPath := joinPath(tmpDir, "app.conf.j2") - require.NoError(t, writeTestFile(srcPath, []byte("server_name={{ server_name }};"), 0644)) + core.RequireNoError(t, writeTestFile(srcPath, []byte("server_name={{ server_name }};"), 0644)) e, mock := newTestExecutorWithMock("host1") e.Diff = true @@ -1488,20 +1485,20 @@ func TestModulesFile_ModuleTemplate_Good_DiffData(t *testing.T) { "dest": "/etc/nginx/conf.d/app.conf", }, "host1", &Task{}) - require.NoError(t, err) - assert.True(t, result.Changed) - require.NotNil(t, result.Data) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertNotNil(t, result.Data) diff, ok := result.Data["diff"].(map[string]any) - require.True(t, ok) - assert.Equal(t, "/etc/nginx/conf.d/app.conf", diff["path"]) - assert.Equal(t, "server_name=old.example.com;", diff["before"]) - assert.Contains(t, diff["after"], "web01.example.com") + core.RequireTrue(t, ok) + core.AssertEqual(t, "/etc/nginx/conf.d/app.conf", diff["path"]) + core.AssertEqual(t, "server_name=old.example.com;", diff["before"]) + core.AssertContains(t, diff["after"], "web01.example.com") } // --- Cross-module dispatch tests for file modules --- -func TestModulesFile_ExecuteModuleWithMock_Good_DispatchCopy(t *testing.T) { +func TestModulesFile_ExecuteModuleWithMock_Good_DispatchCopy(t *core.T) { e, mock := newTestExecutorWithMock("host1") task := &Task{ @@ -1514,12 +1511,12 @@ func TestModulesFile_ExecuteModuleWithMock_Good_DispatchCopy(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, 1, mock.uploadCount()) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, 1, mock.uploadCount()) } -func TestModulesFile_ExecuteModuleWithMock_Good_DispatchFile(t *testing.T) { +func TestModulesFile_ExecuteModuleWithMock_Good_DispatchFile(t *core.T) { e, mock := newTestExecutorWithMock("host1") task := &Task{ @@ -1532,12 +1529,12 @@ func TestModulesFile_ExecuteModuleWithMock_Good_DispatchFile(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted("mkdir")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted("mkdir")) } -func TestModulesFile_ExecuteModuleWithMock_Good_DispatchStat(t *testing.T) { +func TestModulesFile_ExecuteModuleWithMock_Good_DispatchStat(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addStat("/etc/hosts", map[string]any{"exists": true, "isdir": false}) @@ -1550,13 +1547,13 @@ func TestModulesFile_ExecuteModuleWithMock_Good_DispatchStat(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.False(t, result.Changed) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) stat := result.Data["stat"].(map[string]any) - assert.Equal(t, true, stat["exists"]) + core.AssertEqual(t, true, stat["exists"]) } -func TestModulesFile_ExecuteModuleWithMock_Good_DispatchLineinfile(t *testing.T) { +func TestModulesFile_ExecuteModuleWithMock_Good_DispatchLineinfile(t *core.T) { e, mock := newTestExecutorWithMock("host1") task := &Task{ @@ -1569,11 +1566,11 @@ func TestModulesFile_ExecuteModuleWithMock_Good_DispatchLineinfile(t *testing.T) result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) } -func TestModulesFile_ExecuteModuleWithMock_Good_DispatchBlockinfile(t *testing.T) { +func TestModulesFile_ExecuteModuleWithMock_Good_DispatchBlockinfile(t *core.T) { e, mock := newTestExecutorWithMock("host1") task := &Task{ @@ -1586,14 +1583,14 @@ func TestModulesFile_ExecuteModuleWithMock_Good_DispatchBlockinfile(t *testing.T result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) } -func TestModulesFile_ExecuteModuleWithMock_Good_DispatchTemplate(t *testing.T) { +func TestModulesFile_ExecuteModuleWithMock_Good_DispatchTemplate(t *core.T) { tmpDir := t.TempDir() srcPath := joinPath(tmpDir, "test.j2") - require.NoError(t, writeTestFile(srcPath, []byte("static content"), 0644)) + core.RequireNoError(t, writeTestFile(srcPath, []byte("static content"), 0644)) e, mock := newTestExecutorWithMock("host1") @@ -1607,14 +1604,14 @@ func TestModulesFile_ExecuteModuleWithMock_Good_DispatchTemplate(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, 1, mock.uploadCount()) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, 1, mock.uploadCount()) } // --- Template variable resolution integration --- -func TestModulesFile_ModuleCopy_Good_TemplatedArgs(t *testing.T) { +func TestModulesFile_ModuleCopy_Good_TemplatedArgs(t *core.T) { e, mock := newTestExecutorWithMock("host1") e.SetVar("deploy_path", "/opt/myapp") @@ -1630,15 +1627,15 @@ func TestModulesFile_ModuleCopy_Good_TemplatedArgs(t *testing.T) { args := e.templateArgs(task.Args, "host1", task) result, err := moduleCopyWithClient(e, mock, args, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) up := mock.lastUpload() - require.NotNil(t, up) - assert.Equal(t, "/opt/myapp/config.yml", up.Remote) + core.AssertNotNil(t, up) + core.AssertEqual(t, "/opt/myapp/config.yml", up.Remote) } -func TestModulesFile_ModuleFile_Good_TemplatedPath(t *testing.T) { +func TestModulesFile_ModuleFile_Good_TemplatedPath(t *core.T) { e, mock := newTestExecutorWithMock("host1") e.SetVar("app_dir", "/var/www/html") @@ -1654,13 +1651,13 @@ func TestModulesFile_ModuleFile_Good_TemplatedPath(t *testing.T) { args := e.templateArgs(task.Args, "host1", task) result, err := moduleFileWithClient(e, mock, args) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`mkdir -p "/var/www/html/uploads"`)) - assert.True(t, mock.hasExecuted(`chown www-data "/var/www/html/uploads"`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`mkdir -p "/var/www/html/uploads"`)) + core.AssertTrue(t, mock.hasExecuted(`chown www-data "/var/www/html/uploads"`)) } -func TestModulesFile_ModuleGetURL_Good_Checksum(t *testing.T) { +func TestModulesFile_ModuleGetURL_Good_Checksum(t *core.T) { e, mock := newTestExecutorWithMock("host1") payload := "downloaded artifact" mock.expectCommand(`curl.*https://downloads\.example\.com/app\.tgz`, payload, "", 0) @@ -1673,18 +1670,18 @@ func TestModulesFile_ModuleGetURL_Good_Checksum(t *testing.T) { "mode": "0600", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, 1, mock.uploadCount()) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, 1, mock.uploadCount()) up := mock.lastUpload() - require.NotNil(t, up) - assert.Equal(t, "/tmp/app.tgz", up.Remote) - assert.Equal(t, []byte(payload), up.Content) - assert.Equal(t, fs.FileMode(0600), up.Mode) + core.AssertNotNil(t, up) + core.AssertEqual(t, "/tmp/app.tgz", up.Remote) + core.AssertEqual(t, []byte(payload), up.Content) + core.AssertEqual(t, fs.FileMode(0600), up.Mode) } -func TestModulesFile_ModuleGetURL_Good_Sha512Checksum(t *testing.T) { +func TestModulesFile_ModuleGetURL_Good_Sha512Checksum(t *core.T) { e, mock := newTestExecutorWithMock("host1") payload := "downloaded artifact" mock.expectCommand(`curl.*https://downloads\.example\.com/app\.tgz`, payload, "", 0) @@ -1696,17 +1693,17 @@ func TestModulesFile_ModuleGetURL_Good_Sha512Checksum(t *testing.T) { "checksum": "sha512:" + hex.EncodeToString(sum[:]), }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, 1, mock.uploadCount()) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, 1, mock.uploadCount()) up := mock.lastUpload() - require.NotNil(t, up) - assert.Equal(t, "/tmp/app.tgz", up.Remote) - assert.Equal(t, []byte(payload), up.Content) + core.AssertNotNil(t, up) + core.AssertEqual(t, "/tmp/app.tgz", up.Remote) + core.AssertEqual(t, []byte(payload), up.Content) } -func TestModulesFile_ModuleGetURL_Good_ChecksumFileURL(t *testing.T) { +func TestModulesFile_ModuleGetURL_Good_ChecksumFileURL(t *core.T) { e, mock := newTestExecutorWithMock("host1") payload := "downloaded artifact" sum := sha256.Sum256([]byte(payload)) @@ -1721,17 +1718,17 @@ func TestModulesFile_ModuleGetURL_Good_ChecksumFileURL(t *testing.T) { "checksum": "sha256:" + checksumURL, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, 1, mock.uploadCount()) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, 1, mock.uploadCount()) up := mock.lastUpload() - require.NotNil(t, up) - assert.Equal(t, "/tmp/app.tgz", up.Remote) - assert.Equal(t, []byte(payload), up.Content) + core.AssertNotNil(t, up) + core.AssertEqual(t, "/tmp/app.tgz", up.Remote) + core.AssertEqual(t, []byte(payload), up.Content) } -func TestModulesFile_ModuleGetURL_Good_ForceFalseSkipsExistingDestination(t *testing.T) { +func TestModulesFile_ModuleGetURL_Good_ForceFalseSkipsExistingDestination(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.addFile("/tmp/app.tgz", []byte("existing artifact")) @@ -1741,14 +1738,14 @@ func TestModulesFile_ModuleGetURL_Good_ForceFalseSkipsExistingDestination(t *tes "force": false, }) - require.NoError(t, err) - assert.False(t, result.Changed) - assert.Equal(t, "skipped existing destination: /tmp/app.tgz", result.Msg) - assert.Equal(t, 0, mock.commandCount()) - assert.Equal(t, 0, mock.uploadCount()) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertEqual(t, "skipped existing destination: /tmp/app.tgz", result.Msg) + core.AssertEqual(t, 0, mock.commandCount()) + core.AssertEqual(t, 0, mock.uploadCount()) } -func TestModulesFile_ModuleGetURL_Good_DisablesProxyUsage(t *testing.T) { +func TestModulesFile_ModuleGetURL_Good_DisablesProxyUsage(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl.*https://downloads\.example\.com/app\.tgz`, "downloaded artifact", "", 0) @@ -1758,13 +1755,13 @@ func TestModulesFile_ModuleGetURL_Good_DisablesProxyUsage(t *testing.T) { "use_proxy": false, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`--noproxy`)) - assert.True(t, mock.hasExecuted(`wget --no-proxy`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`--noproxy`)) + core.AssertTrue(t, mock.hasExecuted(`wget --no-proxy`)) } -func TestModulesFile_ModuleGetURL_Bad_ChecksumMismatch(t *testing.T) { +func TestModulesFile_ModuleGetURL_Bad_ChecksumMismatch(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl.*https://downloads\.example\.com/app\.tgz`, "downloaded artifact", "", 0) @@ -1774,8 +1771,8 @@ func TestModulesFile_ModuleGetURL_Bad_ChecksumMismatch(t *testing.T) { "checksum": "sha256:deadbeef", }) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, "checksum mismatch") - assert.Equal(t, 0, mock.uploadCount()) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, "checksum mismatch") + core.AssertEqual(t, 0, mock.uploadCount()) } diff --git a/modules_infra_test.go b/modules_infra_test.go index 10f0ac4..1d6a4ff 100644 --- a/modules_infra_test.go +++ b/modules_infra_test.go @@ -2,11 +2,8 @@ package ansible import ( "context" - "testing" + core "dappco.re/go" "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) type slowFactsClient struct{} @@ -20,7 +17,7 @@ func (slowFactsClient) Run(ctx context.Context, cmd string) (string, string, int // 1. Error Propagation — getHosts // =========================================================================== -func TestModulesInfra_GetHosts_Good_AllPattern(t *testing.T) { +func TestModulesInfra_GetHosts_Good_AllPattern(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -33,13 +30,13 @@ func TestModulesInfra_GetHosts_Good_AllPattern(t *testing.T) { }) hosts := e.getHosts("all") - assert.Len(t, hosts, 3) - assert.Contains(t, hosts, "web1") - assert.Contains(t, hosts, "web2") - assert.Contains(t, hosts, "db1") + core.AssertLen(t, hosts, 3) + core.AssertContains(t, hosts, "web1") + core.AssertContains(t, hosts, "web2") + core.AssertContains(t, hosts, "db1") } -func TestModulesInfra_GetHosts_Good_SpecificHost(t *testing.T) { +func TestModulesInfra_GetHosts_Good_SpecificHost(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -51,10 +48,10 @@ func TestModulesInfra_GetHosts_Good_SpecificHost(t *testing.T) { }) hosts := e.getHosts("web1") - assert.Equal(t, []string{"web1"}, hosts) + core.AssertEqual(t, []string{"web1"}, hosts) } -func TestModulesInfra_GetHosts_Good_GroupName(t *testing.T) { +func TestModulesInfra_GetHosts_Good_GroupName(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -75,26 +72,26 @@ func TestModulesInfra_GetHosts_Good_GroupName(t *testing.T) { }) hosts := e.getHosts("webservers") - assert.Len(t, hosts, 2) - assert.Contains(t, hosts, "web1") - assert.Contains(t, hosts, "web2") + core.AssertLen(t, hosts, 2) + core.AssertContains(t, hosts, "web1") + core.AssertContains(t, hosts, "web2") } -func TestModulesInfra_GetHosts_Good_Localhost(t *testing.T) { +func TestModulesInfra_GetHosts_Good_Localhost(t *core.T) { e := NewExecutor("/tmp") // No inventory at all hosts := e.getHosts("localhost") - assert.Equal(t, []string{"localhost"}, hosts) + core.AssertEqual(t, []string{"localhost"}, hosts) } -func TestModulesInfra_GetHosts_Bad_NilInventory(t *testing.T) { +func TestModulesInfra_GetHosts_Bad_NilInventory(t *core.T) { e := NewExecutor("/tmp") // inventory is nil, non-localhost pattern hosts := e.getHosts("webservers") - assert.Nil(t, hosts) + core.AssertNil(t, hosts) } -func TestModulesInfra_GetHosts_Bad_NonexistentHost(t *testing.T) { +func TestModulesInfra_GetHosts_Bad_NonexistentHost(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -105,10 +102,10 @@ func TestModulesInfra_GetHosts_Bad_NonexistentHost(t *testing.T) { }) hosts := e.getHosts("nonexistent") - assert.Empty(t, hosts) + core.AssertEmpty(t, hosts) } -func TestModulesInfra_GetHosts_Good_LimitFiltering(t *testing.T) { +func TestModulesInfra_GetHosts_Good_LimitFiltering(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -122,11 +119,11 @@ func TestModulesInfra_GetHosts_Good_LimitFiltering(t *testing.T) { e.Limit = "web1" hosts := e.getHosts("all") - assert.Len(t, hosts, 1) - assert.Contains(t, hosts, "web1") + core.AssertLen(t, hosts, 1) + core.AssertContains(t, hosts, "web1") } -func TestModulesInfra_GetHosts_Good_LimitExactMatchDoesNotSubstringMatch(t *testing.T) { +func TestModulesInfra_GetHosts_Good_LimitExactMatchDoesNotSubstringMatch(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -140,180 +137,184 @@ func TestModulesInfra_GetHosts_Good_LimitExactMatchDoesNotSubstringMatch(t *test e.Limit = "prod-web-01" hosts := e.getHosts("all") - assert.Equal(t, []string{"prod-web-01"}, hosts) + core.AssertEqual(t, []string{"prod-web-01"}, hosts) } // =========================================================================== // 1. Error Propagation — matchesTags // =========================================================================== -func TestModulesInfra_MatchesTags_Good_NoFiltersNoTags(t *testing.T) { +func TestModulesInfra_MatchesTags_Good_NoFiltersNoTags(t *core.T) { e := NewExecutor("/tmp") // No Tags, no SkipTags set - assert.True(t, e.matchesTags(nil)) + result := e.matchesTags(nil) + core.AssertTrue(t, result) } -func TestModulesInfra_MatchesTags_Good_NoFiltersWithTaskTags(t *testing.T) { +func TestModulesInfra_MatchesTags_Good_NoFiltersWithTaskTags(t *core.T) { e := NewExecutor("/tmp") - assert.True(t, e.matchesTags([]string{"deploy", "config"})) + result := e.matchesTags([]string{"deploy", "config"}) + core.AssertTrue(t, result) } -func TestModulesInfra_MatchesTags_Good_IncludeMatchesOneOfMultiple(t *testing.T) { +func TestModulesInfra_MatchesTags_Good_IncludeMatchesOneOfMultiple(t *core.T) { e := NewExecutor("/tmp") e.Tags = []string{"deploy"} // Task has deploy among its tags - assert.True(t, e.matchesTags([]string{"setup", "deploy", "config"})) + core.AssertTrue(t, e.matchesTags([]string{"setup", "deploy", "config"})) } -func TestModulesInfra_MatchesTags_Bad_IncludeNoMatch(t *testing.T) { +func TestModulesInfra_MatchesTags_Bad_IncludeNoMatch(t *core.T) { e := NewExecutor("/tmp") e.Tags = []string{"deploy"} - assert.False(t, e.matchesTags([]string{"build", "test"})) + core.AssertFalse(t, e.matchesTags([]string{"build", "test"})) } -func TestModulesInfra_MatchesTags_Good_SkipOverridesInclude(t *testing.T) { +func TestModulesInfra_MatchesTags_Good_SkipOverridesInclude(t *core.T) { e := NewExecutor("/tmp") e.SkipTags = []string{"slow"} // Even with no include tags, skip tags filter out matching tasks - assert.False(t, e.matchesTags([]string{"deploy", "slow"})) - assert.True(t, e.matchesTags([]string{"deploy", "fast"})) + core.AssertFalse(t, e.matchesTags([]string{"deploy", "slow"})) + core.AssertTrue(t, e.matchesTags([]string{"deploy", "fast"})) } -func TestModulesInfra_MatchesTags_Bad_IncludeFilterNoTaskTags(t *testing.T) { +func TestModulesInfra_MatchesTags_Bad_IncludeFilterNoTaskTags(t *core.T) { e := NewExecutor("/tmp") e.Tags = []string{"deploy"} // Tasks with no tags should not run when include tags are active - assert.False(t, e.matchesTags(nil)) - assert.False(t, e.matchesTags([]string{})) + core.AssertFalse(t, e.matchesTags(nil)) + core.AssertFalse(t, e.matchesTags([]string{})) } -func TestModulesInfra_MatchesTags_Good_AllTagMatchesEverything(t *testing.T) { +func TestModulesInfra_MatchesTags_Good_AllTagMatchesEverything(t *core.T) { e := NewExecutor("/tmp") e.Tags = []string{"all"} - assert.True(t, e.matchesTags([]string{"deploy"})) - assert.True(t, e.matchesTags([]string{"config", "slow"})) + core.AssertTrue(t, e.matchesTags([]string{"deploy"})) + core.AssertTrue(t, e.matchesTags([]string{"config", "slow"})) } // =========================================================================== // 1. Error Propagation — evaluateWhen // =========================================================================== -func TestModulesInfra_EvaluateWhen_Good_DefinedCheck(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_DefinedCheck(t *core.T) { e := NewExecutor("/tmp") e.results["host1"] = map[string]*TaskResult{ "myresult": {Changed: true}, } - assert.True(t, e.evaluateWhen("myresult is defined", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("myresult is defined", "host1", nil)) } -func TestModulesInfra_EvaluateWhen_Good_NotDefinedCheck(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_NotDefinedCheck(t *core.T) { e := NewExecutor("/tmp") // No results registered for host1 - assert.True(t, e.evaluateWhen("missing_var is not defined", "host1", nil)) + result := e.evaluateWhen("missing_var is not defined", "host1", nil) + core.AssertTrue(t, result) } -func TestModulesInfra_EvaluateWhen_Good_UndefinedAlias(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_UndefinedAlias(t *core.T) { e := NewExecutor("/tmp") - assert.True(t, e.evaluateWhen("some_var is undefined", "host1", nil)) + result := e.evaluateWhen("some_var is undefined", "host1", nil) + core.AssertTrue(t, result) } -func TestModulesInfra_EvaluateWhen_Good_SucceededCheck(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_SucceededCheck(t *core.T) { e := NewExecutor("/tmp") e.results["host1"] = map[string]*TaskResult{ "result": {Failed: false, Changed: true}, } - assert.True(t, e.evaluateWhen("result is success", "host1", nil)) - assert.True(t, e.evaluateWhen("result is succeeded", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("result is success", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("result is succeeded", "host1", nil)) } -func TestModulesInfra_EvaluateWhen_Good_FailedCheck(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_FailedCheck(t *core.T) { e := NewExecutor("/tmp") e.results["host1"] = map[string]*TaskResult{ "result": {Failed: true}, } - assert.True(t, e.evaluateWhen("result is failed", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("result is failed", "host1", nil)) } -func TestModulesInfra_EvaluateWhen_Good_ChangedCheck(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_ChangedCheck(t *core.T) { e := NewExecutor("/tmp") e.results["host1"] = map[string]*TaskResult{ "result": {Changed: true}, } - assert.True(t, e.evaluateWhen("result is changed", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("result is changed", "host1", nil)) } -func TestModulesInfra_EvaluateWhen_Good_SkippedCheck(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_SkippedCheck(t *core.T) { e := NewExecutor("/tmp") e.results["host1"] = map[string]*TaskResult{ "result": {Skipped: true}, } - assert.True(t, e.evaluateWhen("result is skipped", "host1", nil)) + core.AssertTrue(t, e.evaluateWhen("result is skipped", "host1", nil)) } -func TestModulesInfra_EvaluateWhen_Good_BoolVarTruthy(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_BoolVarTruthy(t *core.T) { e := NewExecutor("/tmp") e.vars["my_flag"] = true - assert.True(t, e.evalCondition("my_flag", "host1")) + core.AssertTrue(t, e.evalCondition("my_flag", "host1")) } -func TestModulesInfra_EvaluateWhen_Good_BoolVarFalsy(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_BoolVarFalsy(t *core.T) { e := NewExecutor("/tmp") e.vars["my_flag"] = false - assert.False(t, e.evalCondition("my_flag", "host1")) + core.AssertFalse(t, e.evalCondition("my_flag", "host1")) } -func TestModulesInfra_EvaluateWhen_Good_StringVarTruthy(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_StringVarTruthy(t *core.T) { e := NewExecutor("/tmp") e.vars["my_str"] = "hello" - assert.True(t, e.evalCondition("my_str", "host1")) + core.AssertTrue(t, e.evalCondition("my_str", "host1")) } -func TestModulesInfra_EvaluateWhen_Good_StringVarEmptyFalsy(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_StringVarEmptyFalsy(t *core.T) { e := NewExecutor("/tmp") e.vars["my_str"] = "" - assert.False(t, e.evalCondition("my_str", "host1")) + core.AssertFalse(t, e.evalCondition("my_str", "host1")) } -func TestModulesInfra_EvaluateWhen_Good_StringVarFalseLiteral(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_StringVarFalseLiteral(t *core.T) { e := NewExecutor("/tmp") e.vars["my_str"] = "false" - assert.False(t, e.evalCondition("my_str", "host1")) + core.AssertFalse(t, e.evalCondition("my_str", "host1")) e.vars["my_str2"] = "False" - assert.False(t, e.evalCondition("my_str2", "host1")) + core.AssertFalse(t, e.evalCondition("my_str2", "host1")) } -func TestModulesInfra_EvaluateWhen_Good_IntVarNonZero(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_IntVarNonZero(t *core.T) { e := NewExecutor("/tmp") e.vars["count"] = 42 - assert.True(t, e.evalCondition("count", "host1")) + core.AssertTrue(t, e.evalCondition("count", "host1")) } -func TestModulesInfra_EvaluateWhen_Good_IntVarZero(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_IntVarZero(t *core.T) { e := NewExecutor("/tmp") e.vars["count"] = 0 - assert.False(t, e.evalCondition("count", "host1")) + core.AssertFalse(t, e.evalCondition("count", "host1")) } -func TestModulesInfra_EvaluateWhen_Good_Negation(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_Negation(t *core.T) { e := NewExecutor("/tmp") - assert.False(t, e.evalCondition("not true", "host1")) - assert.True(t, e.evalCondition("not false", "host1")) + core.AssertFalse(t, e.evalCondition("not true", "host1")) + core.AssertTrue(t, e.evalCondition("not false", "host1")) } -func TestModulesInfra_EvaluateWhen_Good_MultipleConditionsAllTrue(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_MultipleConditionsAllTrue(t *core.T) { e := NewExecutor("/tmp") e.vars["enabled"] = true e.results["host1"] = map[string]*TaskResult{ @@ -321,117 +322,118 @@ func TestModulesInfra_EvaluateWhen_Good_MultipleConditionsAllTrue(t *testing.T) } // Both conditions must be true (AND semantics) - assert.True(t, e.evaluateWhen([]any{"enabled", "prev is success"}, "host1", nil)) + core.AssertTrue(t, e.evaluateWhen([]any{"enabled", "prev is success"}, "host1", nil)) } -func TestModulesInfra_EvaluateWhen_Bad_MultipleConditionsOneFails(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Bad_MultipleConditionsOneFails(t *core.T) { e := NewExecutor("/tmp") e.vars["enabled"] = true // "false" literal fails - assert.False(t, e.evaluateWhen([]any{"enabled", "false"}, "host1", nil)) + core.AssertFalse(t, e.evaluateWhen([]any{"enabled", "false"}, "host1", nil)) } -func TestModulesInfra_EvaluateWhen_Good_DefaultFilterInCondition(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_DefaultFilterInCondition(t *core.T) { e := NewExecutor("/tmp") // Condition with default filter should be satisfied - assert.True(t, e.evalCondition("my_var | default(true)", "host1")) + result := e.evalCondition("my_var | default(true)", "host1") + core.AssertTrue(t, result) } -func TestModulesInfra_EvaluateWhen_Good_RegisteredVarTruthy(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Good_RegisteredVarTruthy(t *core.T) { e := NewExecutor("/tmp") e.results["host1"] = map[string]*TaskResult{ "check_result": {Failed: false, Skipped: false}, } // Just referencing a registered var name evaluates truthy if not failed/skipped - assert.True(t, e.evalCondition("check_result", "host1")) + core.AssertTrue(t, e.evalCondition("check_result", "host1")) } -func TestModulesInfra_EvaluateWhen_Bad_RegisteredVarFailedFalsy(t *testing.T) { +func TestModulesInfra_EvaluateWhen_Bad_RegisteredVarFailedFalsy(t *core.T) { e := NewExecutor("/tmp") e.results["host1"] = map[string]*TaskResult{ "check_result": {Failed: true}, } // A failed registered var should be falsy - assert.False(t, e.evalCondition("check_result", "host1")) + core.AssertFalse(t, e.evalCondition("check_result", "host1")) } // =========================================================================== // 1. Error Propagation — templateString // =========================================================================== -func TestModulesInfra_TemplateString_Good_SimpleSubstitution(t *testing.T) { +func TestModulesInfra_TemplateString_Good_SimpleSubstitution(t *core.T) { e := NewExecutor("/tmp") e.vars["app_name"] = "myapp" result := e.templateString("Deploying {{ app_name }}", "", nil) - assert.Equal(t, "Deploying myapp", result) + core.AssertEqual(t, "Deploying myapp", result) } -func TestModulesInfra_TemplateString_Good_MultipleVars(t *testing.T) { +func TestModulesInfra_TemplateString_Good_MultipleVars(t *core.T) { e := NewExecutor("/tmp") e.vars["host"] = "db.example.com" e.vars["port"] = 5432 result := e.templateString("postgresql://{{ host }}:{{ port }}/mydb", "", nil) - assert.Equal(t, "postgresql://db.example.com:5432/mydb", result) + core.AssertEqual(t, "postgresql://db.example.com:5432/mydb", result) } -func TestModulesInfra_TemplateString_Good_Unresolved(t *testing.T) { +func TestModulesInfra_TemplateString_Good_Unresolved(t *core.T) { e := NewExecutor("/tmp") result := e.templateString("{{ missing_var }}", "", nil) - assert.Equal(t, "{{ missing_var }}", result) + core.AssertEqual(t, "{{ missing_var }}", result) } -func TestModulesInfra_TemplateString_Good_NoTemplateMarkup(t *testing.T) { +func TestModulesInfra_TemplateString_Good_NoTemplateMarkup(t *core.T) { e := NewExecutor("/tmp") result := e.templateString("just a plain string", "", nil) - assert.Equal(t, "just a plain string", result) + core.AssertEqual(t, "just a plain string", result) } -func TestModulesInfra_TemplateString_Good_RegisteredVarStdout(t *testing.T) { +func TestModulesInfra_TemplateString_Good_RegisteredVarStdout(t *core.T) { e := NewExecutor("/tmp") e.results["host1"] = map[string]*TaskResult{ "cmd_result": {Stdout: "42"}, } result := e.templateString("{{ cmd_result.stdout }}", "host1", nil) - assert.Equal(t, "42", result) + core.AssertEqual(t, "42", result) } -func TestModulesInfra_TemplateString_Good_RegisteredVarRC(t *testing.T) { +func TestModulesInfra_TemplateString_Good_RegisteredVarRC(t *core.T) { e := NewExecutor("/tmp") e.results["host1"] = map[string]*TaskResult{ "cmd_result": {RC: 0}, } result := e.templateString("{{ cmd_result.rc }}", "host1", nil) - assert.Equal(t, "0", result) + core.AssertEqual(t, "0", result) } -func TestModulesInfra_TemplateString_Good_RegisteredVarChanged(t *testing.T) { +func TestModulesInfra_TemplateString_Good_RegisteredVarChanged(t *core.T) { e := NewExecutor("/tmp") e.results["host1"] = map[string]*TaskResult{ "cmd_result": {Changed: true}, } result := e.templateString("{{ cmd_result.changed }}", "host1", nil) - assert.Equal(t, "true", result) + core.AssertEqual(t, "true", result) } -func TestModulesInfra_TemplateString_Good_RegisteredVarFailed(t *testing.T) { +func TestModulesInfra_TemplateString_Good_RegisteredVarFailed(t *core.T) { e := NewExecutor("/tmp") e.results["host1"] = map[string]*TaskResult{ "cmd_result": {Failed: true}, } result := e.templateString("{{ cmd_result.failed }}", "host1", nil) - assert.Equal(t, "true", result) + core.AssertEqual(t, "true", result) } -func TestModulesInfra_TemplateString_Good_TaskVars(t *testing.T) { +func TestModulesInfra_TemplateString_Good_TaskVars(t *core.T) { e := NewExecutor("/tmp") task := &Task{ Vars: map[string]any{ @@ -440,10 +442,10 @@ func TestModulesInfra_TemplateString_Good_TaskVars(t *testing.T) { } result := e.templateString("{{ task_var }}", "host1", task) - assert.Equal(t, "task_value", result) + core.AssertEqual(t, "task_value", result) } -func TestModulesInfra_TemplateString_Good_FactsResolution(t *testing.T) { +func TestModulesInfra_TemplateString_Good_FactsResolution(t *core.T) { e := NewExecutor("/tmp") e.facts["host1"] = &Facts{ Hostname: "web1", @@ -454,249 +456,260 @@ func TestModulesInfra_TemplateString_Good_FactsResolution(t *testing.T) { Kernel: "6.5.0", } - assert.Equal(t, "web1", e.templateString("{{ ansible_hostname }}", "host1", nil)) - assert.Equal(t, "web1.example.com", e.templateString("{{ ansible_fqdn }}", "host1", nil)) - assert.Equal(t, "ubuntu", e.templateString("{{ ansible_distribution }}", "host1", nil)) - assert.Equal(t, "24.04", e.templateString("{{ ansible_distribution_version }}", "host1", nil)) - assert.Equal(t, "x86_64", e.templateString("{{ ansible_architecture }}", "host1", nil)) - assert.Equal(t, "6.5.0", e.templateString("{{ ansible_kernel }}", "host1", nil)) + core.AssertEqual(t, "web1", e.templateString("{{ ansible_hostname }}", "host1", nil)) + core.AssertEqual(t, "web1.example.com", e.templateString("{{ ansible_fqdn }}", "host1", nil)) + core.AssertEqual(t, "ubuntu", e.templateString("{{ ansible_distribution }}", "host1", nil)) + core.AssertEqual(t, "24.04", e.templateString("{{ ansible_distribution_version }}", "host1", nil)) + core.AssertEqual(t, "x86_64", e.templateString("{{ ansible_architecture }}", "host1", nil)) + core.AssertEqual(t, "6.5.0", e.templateString("{{ ansible_kernel }}", "host1", nil)) } // =========================================================================== // 1. Error Propagation — applyFilter // =========================================================================== -func TestModulesInfra_ApplyFilter_Good_DefaultWithValue(t *testing.T) { +func TestModulesInfra_ApplyFilter_Good_DefaultWithValue(t *core.T) { e := NewExecutor("/tmp") // When value is non-empty, default is not applied - assert.Equal(t, "hello", e.applyFilter("hello", "default('fallback')")) + result := e.applyFilter("hello", "default('fallback')") + core.AssertEqual(t, "hello", result) } -func TestModulesInfra_ApplyFilter_Good_DefaultWithEmpty(t *testing.T) { +func TestModulesInfra_ApplyFilter_Good_DefaultWithEmpty(t *core.T) { e := NewExecutor("/tmp") // When value is empty, default IS applied - assert.Equal(t, "fallback", e.applyFilter("", "default('fallback')")) + result := e.applyFilter("", "default('fallback')") + core.AssertEqual(t, "fallback", result) } -func TestModulesInfra_ApplyFilter_Good_DefaultWithDoubleQuotes(t *testing.T) { +func TestModulesInfra_ApplyFilter_Good_DefaultWithDoubleQuotes(t *core.T) { e := NewExecutor("/tmp") - assert.Equal(t, "fallback", e.applyFilter("", `default("fallback")`)) + result := e.applyFilter("", `default("fallback")`) + core.AssertEqual(t, "fallback", result) } -func TestModulesInfra_ApplyFilter_Good_BoolFilterTrue(t *testing.T) { +func TestModulesInfra_ApplyFilter_Good_BoolFilterTrue(t *core.T) { e := NewExecutor("/tmp") - assert.Equal(t, "true", e.applyFilter("true", "bool")) - assert.Equal(t, "true", e.applyFilter("True", "bool")) - assert.Equal(t, "true", e.applyFilter("yes", "bool")) - assert.Equal(t, "true", e.applyFilter("Yes", "bool")) - assert.Equal(t, "true", e.applyFilter("1", "bool")) + core.AssertEqual(t, "true", e.applyFilter("true", "bool")) + core.AssertEqual(t, "true", e.applyFilter("True", "bool")) + core.AssertEqual(t, "true", e.applyFilter("yes", "bool")) + core.AssertEqual(t, "true", e.applyFilter("Yes", "bool")) + core.AssertEqual(t, "true", e.applyFilter("1", "bool")) } -func TestModulesInfra_ApplyFilter_Good_BoolFilterFalse(t *testing.T) { +func TestModulesInfra_ApplyFilter_Good_BoolFilterFalse(t *core.T) { e := NewExecutor("/tmp") - assert.Equal(t, "false", e.applyFilter("false", "bool")) - assert.Equal(t, "false", e.applyFilter("no", "bool")) - assert.Equal(t, "false", e.applyFilter("0", "bool")) - assert.Equal(t, "false", e.applyFilter("random", "bool")) + core.AssertEqual(t, "false", e.applyFilter("false", "bool")) + core.AssertEqual(t, "false", e.applyFilter("no", "bool")) + core.AssertEqual(t, "false", e.applyFilter("0", "bool")) + core.AssertEqual(t, "false", e.applyFilter("random", "bool")) } -func TestModulesInfra_ApplyFilter_Good_TrimFilter(t *testing.T) { +func TestModulesInfra_ApplyFilter_Good_TrimFilter(t *core.T) { e := NewExecutor("/tmp") - assert.Equal(t, "hello", e.applyFilter(" hello ", "trim")) - assert.Equal(t, "no spaces", e.applyFilter("no spaces", "trim")) - assert.Equal(t, "", e.applyFilter(" ", "trim")) + core.AssertEqual(t, "hello", e.applyFilter(" hello ", "trim")) + core.AssertEqual(t, "no spaces", e.applyFilter("no spaces", "trim")) + core.AssertEqual(t, "", e.applyFilter(" ", "trim")) } -func TestModulesInfra_ApplyFilter_Good_RegexReplaceFilter(t *testing.T) { +func TestModulesInfra_ApplyFilter_Good_RegexReplaceFilter(t *core.T) { e := NewExecutor("/tmp") - assert.Equal(t, "app-01", e.applyFilter("app_01", "regex_replace('_', '-')")) - assert.Equal(t, "42", e.applyFilter("v42", `regex_replace("^v", "")`)) + core.AssertEqual(t, "app-01", e.applyFilter("app_01", "regex_replace('_', '-')")) + core.AssertEqual(t, "42", e.applyFilter("v42", `regex_replace("^v", "")`)) } -func TestModulesInfra_ApplyFilter_Good_B64Decode(t *testing.T) { +func TestModulesInfra_ApplyFilter_Good_B64Decode(t *core.T) { e := NewExecutor("/tmp") - assert.Equal(t, "test", e.applyFilter("dGVzdA==", "b64decode")) + result := e.applyFilter("dGVzdA==", "b64decode") + core.AssertEqual(t, "test", result) } -func TestModulesInfra_ApplyFilter_Good_UnknownFilter(t *testing.T) { +func TestModulesInfra_ApplyFilter_Good_UnknownFilter(t *core.T) { e := NewExecutor("/tmp") // Unknown filters return value unchanged - assert.Equal(t, "hello", e.applyFilter("hello", "nonexistent_filter")) + result := e.applyFilter("hello", "nonexistent_filter") + core.AssertEqual(t, "hello", result) } -func TestModulesInfra_TemplateString_Good_FilterInTemplate(t *testing.T) { +func TestModulesInfra_TemplateString_Good_FilterInTemplate(t *core.T) { e := NewExecutor("/tmp") // When a var is defined, the filter passes through e.vars["defined_var"] = "hello" result := e.templateString("{{ defined_var | default('fallback') }}", "", nil) - assert.Equal(t, "hello", result) + core.AssertEqual(t, "hello", result) } -func TestModulesInfra_TemplateString_Good_DefaultFilterMissingVar(t *testing.T) { +func TestModulesInfra_TemplateString_Good_DefaultFilterMissingVar(t *core.T) { e := NewExecutor("/tmp") result := e.templateString("{{ missing_var | default('fallback') }}", "", nil) - assert.Equal(t, "fallback", result) + core.AssertEqual(t, "fallback", result) } -func TestModulesInfra_TemplateString_Good_DefaultFilterEmptyVar(t *testing.T) { +func TestModulesInfra_TemplateString_Good_DefaultFilterEmptyVar(t *core.T) { e := NewExecutor("/tmp") e.vars["empty_var"] = "" // When var is empty string, default filter applies result := e.applyFilter("", "default('fallback')") - assert.Equal(t, "fallback", result) + core.AssertEqual(t, "fallback", result) } -func TestModulesInfra_TemplateString_Good_BoolFilterInTemplate(t *testing.T) { +func TestModulesInfra_TemplateString_Good_BoolFilterInTemplate(t *core.T) { e := NewExecutor("/tmp") e.vars["flag"] = "yes" result := e.templateString("{{ flag | bool }}", "", nil) - assert.Equal(t, "true", result) + core.AssertEqual(t, "true", result) } -func TestModulesInfra_TemplateString_Good_TrimFilterInTemplate(t *testing.T) { +func TestModulesInfra_TemplateString_Good_TrimFilterInTemplate(t *core.T) { e := NewExecutor("/tmp") e.vars["padded"] = " trimmed " result := e.templateString("{{ padded | trim }}", "", nil) - assert.Equal(t, "trimmed", result) + core.AssertEqual(t, "trimmed", result) } // =========================================================================== // 1. Error Propagation — resolveLoop // =========================================================================== -func TestModulesInfra_ResolveLoop_Good_SliceAny(t *testing.T) { +func TestModulesInfra_ResolveLoop_Good_SliceAny(t *core.T) { e := NewExecutor("/tmp") items := e.resolveLoop([]any{"a", "b", "c"}, "host1") - assert.Len(t, items, 3) - assert.Equal(t, "a", items[0]) - assert.Equal(t, "b", items[1]) - assert.Equal(t, "c", items[2]) + core.AssertLen(t, items, 3) + core.AssertEqual(t, "a", items[0]) + core.AssertEqual(t, "b", items[1]) + core.AssertEqual(t, "c", items[2]) } -func TestModulesInfra_ResolveLoop_Good_SliceString(t *testing.T) { +func TestModulesInfra_ResolveLoop_Good_SliceString(t *core.T) { e := NewExecutor("/tmp") items := e.resolveLoop([]string{"x", "y"}, "host1") - assert.Len(t, items, 2) - assert.Equal(t, "x", items[0]) - assert.Equal(t, "y", items[1]) + core.AssertLen(t, items, 2) + core.AssertEqual(t, "x", items[0]) + core.AssertEqual(t, "y", items[1]) } -func TestModulesInfra_ResolveLoop_Good_NilLoop(t *testing.T) { +func TestModulesInfra_ResolveLoop_Good_NilLoop(t *core.T) { e := NewExecutor("/tmp") items := e.resolveLoop(nil, "host1") - assert.Nil(t, items) + core.AssertNil(t, items) } -func TestModulesInfra_ResolveLoop_Good_VarReference(t *testing.T) { +func TestModulesInfra_ResolveLoop_Good_VarReference(t *core.T) { e := NewExecutor("/tmp") e.vars["my_list"] = []any{"item1", "item2", "item3"} // A templated loop source should resolve to the underlying list value. items := e.resolveLoop("{{ my_list }}", "host1") - require.Len(t, items, 3) - assert.Equal(t, "item1", items[0]) - assert.Equal(t, "item2", items[1]) - assert.Equal(t, "item3", items[2]) + core.AssertLen(t, items, 3) + core.AssertEqual(t, "item1", items[0]) + core.AssertEqual(t, "item2", items[1]) + core.AssertEqual(t, "item3", items[2]) } -func TestModulesInfra_ResolveLoop_Good_MixedTypes(t *testing.T) { +func TestModulesInfra_ResolveLoop_Good_MixedTypes(t *core.T) { e := NewExecutor("/tmp") items := e.resolveLoop([]any{"str", 42, true, map[string]any{"key": "val"}}, "host1") - assert.Len(t, items, 4) - assert.Equal(t, "str", items[0]) - assert.Equal(t, 42, items[1]) - assert.Equal(t, true, items[2]) + core.AssertLen(t, items, 4) + core.AssertEqual(t, "str", items[0]) + core.AssertEqual(t, 42, items[1]) + core.AssertEqual(t, true, items[2]) } // =========================================================================== // 1. Error Propagation — handleNotify // =========================================================================== -func TestModulesInfra_HandleNotify_Good_SingleString(t *testing.T) { +func TestModulesInfra_HandleNotify_Good_SingleString(t *core.T) { e := NewExecutor("/tmp") e.handleNotify("restart nginx") - assert.True(t, e.notified["restart nginx"]) - assert.False(t, e.notified["restart apache"]) + core.AssertTrue(t, e.notified["restart nginx"]) + core.AssertFalse(t, e.notified["restart apache"]) } -func TestModulesInfra_HandleNotify_Good_StringSlice(t *testing.T) { +func TestModulesInfra_HandleNotify_Good_StringSlice(t *core.T) { e := NewExecutor("/tmp") e.handleNotify([]string{"restart nginx", "reload haproxy"}) - assert.True(t, e.notified["restart nginx"]) - assert.True(t, e.notified["reload haproxy"]) + core.AssertTrue(t, e.notified["restart nginx"]) + core.AssertTrue(t, e.notified["reload haproxy"]) } -func TestModulesInfra_HandleNotify_Good_AnySlice(t *testing.T) { +func TestModulesInfra_HandleNotify_Good_AnySlice(t *core.T) { e := NewExecutor("/tmp") e.handleNotify([]any{"handler1", "handler2", "handler3"}) - assert.True(t, e.notified["handler1"]) - assert.True(t, e.notified["handler2"]) - assert.True(t, e.notified["handler3"]) + core.AssertTrue(t, e.notified["handler1"]) + core.AssertTrue(t, e.notified["handler2"]) + core.AssertTrue(t, e.notified["handler3"]) } -func TestModulesInfra_HandleNotify_Good_NilNotify(t *testing.T) { +func TestModulesInfra_HandleNotify_Good_NilNotify(t *core.T) { e := NewExecutor("/tmp") // Should not panic e.handleNotify(nil) - assert.Empty(t, e.notified) + core.AssertEmpty(t, e.notified) } -func TestModulesInfra_HandleNotify_Good_MultipleCallsAccumulate(t *testing.T) { +func TestModulesInfra_HandleNotify_Good_MultipleCallsAccumulate(t *core.T) { e := NewExecutor("/tmp") e.handleNotify("handler1") e.handleNotify("handler2") - assert.True(t, e.notified["handler1"]) - assert.True(t, e.notified["handler2"]) + core.AssertTrue(t, e.notified["handler1"]) + core.AssertTrue(t, e.notified["handler2"]) } // =========================================================================== // 1. Error Propagation — normalizeConditions // =========================================================================== -func TestModulesInfra_NormalizeConditions_Good_String(t *testing.T) { +func TestModulesInfra_NormalizeConditions_Good_String(t *core.T) { result := normalizeConditions("my_var is defined") - assert.Equal(t, []string{"my_var is defined"}, result) + core.AssertEqual(t, []string{"my_var is defined"}, result) + core.AssertLen(t, result, 1) } -func TestModulesInfra_NormalizeConditions_Good_StringSlice(t *testing.T) { +func TestModulesInfra_NormalizeConditions_Good_StringSlice(t *core.T) { result := normalizeConditions([]string{"cond1", "cond2"}) - assert.Equal(t, []string{"cond1", "cond2"}, result) + core.AssertEqual(t, []string{"cond1", "cond2"}, result) + core.AssertLen(t, result, 2) } -func TestModulesInfra_NormalizeConditions_Good_AnySlice(t *testing.T) { +func TestModulesInfra_NormalizeConditions_Good_AnySlice(t *core.T) { result := normalizeConditions([]any{"cond1", "cond2"}) - assert.Equal(t, []string{"cond1", "cond2"}, result) + core.AssertEqual(t, []string{"cond1", "cond2"}, result) + core.AssertLen(t, result, 2) } -func TestModulesInfra_NormalizeConditions_Good_Nil(t *testing.T) { +func TestModulesInfra_NormalizeConditions_Good_Nil(t *core.T) { result := normalizeConditions(nil) - assert.Nil(t, result) + core.AssertNil(t, result) + core.AssertEmpty(t, result) } -func TestModulesInfra_NormalizeConditions_Good_IntIgnored(t *testing.T) { +func TestModulesInfra_NormalizeConditions_Good_IntIgnored(t *core.T) { // Non-string types in any slice are silently skipped result := normalizeConditions([]any{"cond1", 42}) - assert.Equal(t, []string{"cond1"}, result) + core.AssertEqual(t, []string{"cond1"}, result) + core.AssertLen(t, result, 1) } -func TestModulesInfra_NormalizeConditions_Good_UnsupportedType(t *testing.T) { +func TestModulesInfra_NormalizeConditions_Good_UnsupportedType(t *core.T) { result := normalizeConditions(42) - assert.Nil(t, result) + core.AssertNil(t, result) + core.AssertEmpty(t, result) } // =========================================================================== // 2. Become/Sudo // =========================================================================== -func TestModulesInfra_Become_Good_SetBecomeTrue(t *testing.T) { +func TestModulesInfra_Become_Good_SetBecomeTrue(t *core.T) { cfg := SSHConfig{ Host: "test-host", Port: 22, @@ -706,65 +719,65 @@ func TestModulesInfra_Become_Good_SetBecomeTrue(t *testing.T) { BecomePass: "secret", } client, err := NewSSHClient(cfg) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.True(t, client.become) - assert.Equal(t, "root", client.becomeUser) - assert.Equal(t, "secret", client.becomePass) + core.AssertTrue(t, client.become) + core.AssertEqual(t, "root", client.becomeUser) + core.AssertEqual(t, "secret", client.becomePass) } -func TestModulesInfra_Become_Good_SetBecomeFalse(t *testing.T) { +func TestModulesInfra_Become_Good_SetBecomeFalse(t *core.T) { cfg := SSHConfig{ Host: "test-host", Port: 22, User: "deploy", } client, err := NewSSHClient(cfg) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.False(t, client.become) - assert.Empty(t, client.becomeUser) - assert.Empty(t, client.becomePass) + core.AssertFalse(t, client.become) + core.AssertEmpty(t, client.becomeUser) + core.AssertEmpty(t, client.becomePass) } -func TestModulesInfra_Become_Good_SetBecomeMethod(t *testing.T) { +func TestModulesInfra_Become_Good_SetBecomeMethod(t *core.T) { cfg := SSHConfig{Host: "test-host"} client, err := NewSSHClient(cfg) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.False(t, client.become) + core.AssertFalse(t, client.become) client.SetBecome(true, "admin", "pass123") - assert.True(t, client.become) - assert.Equal(t, "admin", client.becomeUser) - assert.Equal(t, "pass123", client.becomePass) + core.AssertTrue(t, client.become) + core.AssertEqual(t, "admin", client.becomeUser) + core.AssertEqual(t, "pass123", client.becomePass) } -func TestModulesInfra_Become_Good_DisableAfterEnable(t *testing.T) { +func TestModulesInfra_Become_Good_DisableAfterEnable(t *core.T) { cfg := SSHConfig{Host: "test-host"} client, err := NewSSHClient(cfg) - require.NoError(t, err) + core.RequireNoError(t, err) client.SetBecome(true, "root", "secret") - assert.True(t, client.become) + core.AssertTrue(t, client.become) client.SetBecome(false, "", "") - assert.False(t, client.become) - assert.Empty(t, client.becomeUser) - assert.Empty(t, client.becomePass) + core.AssertFalse(t, client.become) + core.AssertEmpty(t, client.becomeUser) + core.AssertEmpty(t, client.becomePass) } -func TestModulesInfra_Become_Good_MockBecomeTracking(t *testing.T) { +func TestModulesInfra_Become_Good_MockBecomeTracking(t *core.T) { mock := NewMockSSHClient() - assert.False(t, mock.become) + core.AssertFalse(t, mock.become) mock.SetBecome(true, "root", "password") - assert.True(t, mock.become) - assert.Equal(t, "root", mock.becomeUser) - assert.Equal(t, "password", mock.becomePass) + core.AssertTrue(t, mock.become) + core.AssertEqual(t, "root", mock.becomeUser) + core.AssertEqual(t, "password", mock.becomePass) } -func TestModulesInfra_Become_Good_DefaultBecomeUserRoot(t *testing.T) { +func TestModulesInfra_Become_Good_DefaultBecomeUserRoot(t *core.T) { // When become is true but no user specified, it defaults to root in the Run method cfg := SSHConfig{ Host: "test-host", @@ -772,14 +785,14 @@ func TestModulesInfra_Become_Good_DefaultBecomeUserRoot(t *testing.T) { // BecomeUser not set } client, err := NewSSHClient(cfg) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.True(t, client.become) - assert.Empty(t, client.becomeUser) // Empty in config... + core.AssertTrue(t, client.become) + core.AssertEmpty(t, client.becomeUser) // Empty in config... // The Run() method defaults to "root" when becomeUser is empty } -func TestModulesInfra_Become_Good_PasswordlessBecome(t *testing.T) { +func TestModulesInfra_Become_Good_PasswordlessBecome(t *core.T) { cfg := SSHConfig{ Host: "test-host", Become: true, @@ -787,14 +800,14 @@ func TestModulesInfra_Become_Good_PasswordlessBecome(t *testing.T) { // No BecomePass and no Password — triggers sudo -n } client, err := NewSSHClient(cfg) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.True(t, client.become) - assert.Empty(t, client.becomePass) - assert.Empty(t, client.password) + core.AssertTrue(t, client.become) + core.AssertEmpty(t, client.becomePass) + core.AssertEmpty(t, client.password) } -func TestModulesInfra_Become_Good_ExecutorPlayBecome(t *testing.T) { +func TestModulesInfra_Become_Good_ExecutorPlayBecome(t *core.T) { // Test that getClient applies play-level become settings e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ @@ -815,15 +828,15 @@ func TestModulesInfra_Become_Good_ExecutorPlayBecome(t *testing.T) { // by checking the SSHConfig construction logic. // Since getClient creates real connections, we just verify // that the become fields are set on the play. - assert.True(t, play.Become) - assert.Equal(t, "admin", play.BecomeUser) + core.AssertTrue(t, play.Become) + core.AssertEqual(t, "admin", play.BecomeUser) } // =========================================================================== // 3. Fact Gathering // =========================================================================== -func TestModulesInfra_Facts_Good_UbuntuParsing(t *testing.T) { +func TestModulesInfra_Facts_Good_UbuntuParsing(t *core.T) { e, mock := newTestExecutorWithMock("web1") // Mock os-release output for Ubuntu @@ -861,22 +874,22 @@ func TestModulesInfra_Facts_Good_UbuntuParsing(t *testing.T) { e.facts["web1"] = facts - assert.Equal(t, "web1.example.com", facts.FQDN) - assert.Equal(t, "web1", facts.Hostname) - assert.Equal(t, "ubuntu", facts.Distribution) - assert.Equal(t, "24.04", facts.Version) - assert.Equal(t, "x86_64", facts.Architecture) - assert.Equal(t, "6.5.0-44-generic", facts.Kernel) + core.AssertEqual(t, "web1.example.com", facts.FQDN) + core.AssertEqual(t, "web1", facts.Hostname) + core.AssertEqual(t, "ubuntu", facts.Distribution) + core.AssertEqual(t, "24.04", facts.Version) + core.AssertEqual(t, "x86_64", facts.Architecture) + core.AssertEqual(t, "6.5.0-44-generic", facts.Kernel) // Now verify template resolution with these facts result := e.templateString("{{ ansible_hostname }}", "web1", nil) - assert.Equal(t, "web1", result) + core.AssertEqual(t, "web1", result) result = e.templateString("{{ ansible_distribution }}", "web1", nil) - assert.Equal(t, "ubuntu", result) + core.AssertEqual(t, "ubuntu", result) } -func TestModulesInfra_Facts_Good_CentOSParsing(t *testing.T) { +func TestModulesInfra_Facts_Good_CentOSParsing(t *core.T) { facts := &Facts{} osRelease := "ID=centos\nVERSION_ID=\"8\"\n" @@ -889,11 +902,11 @@ func TestModulesInfra_Facts_Good_CentOSParsing(t *testing.T) { } } - assert.Equal(t, "centos", facts.Distribution) - assert.Equal(t, "8", facts.Version) + core.AssertEqual(t, "centos", facts.Distribution) + core.AssertEqual(t, "8", facts.Version) } -func TestModulesInfra_Facts_Good_AlpineParsing(t *testing.T) { +func TestModulesInfra_Facts_Good_AlpineParsing(t *core.T) { facts := &Facts{} osRelease := "ID=alpine\nVERSION_ID=3.19.1\n" @@ -906,11 +919,11 @@ func TestModulesInfra_Facts_Good_AlpineParsing(t *testing.T) { } } - assert.Equal(t, "alpine", facts.Distribution) - assert.Equal(t, "3.19.1", facts.Version) + core.AssertEqual(t, "alpine", facts.Distribution) + core.AssertEqual(t, "3.19.1", facts.Version) } -func TestModulesInfra_Facts_Good_DebianParsing(t *testing.T) { +func TestModulesInfra_Facts_Good_DebianParsing(t *core.T) { facts := &Facts{} osRelease := "ID=debian\nVERSION_ID=\"12\"\n" @@ -923,50 +936,50 @@ func TestModulesInfra_Facts_Good_DebianParsing(t *testing.T) { } } - assert.Equal(t, "debian", facts.Distribution) - assert.Equal(t, "12", facts.Version) + core.AssertEqual(t, "debian", facts.Distribution) + core.AssertEqual(t, "12", facts.Version) } -func TestModulesInfra_Facts_Good_HostnameFromCommand(t *testing.T) { +func TestModulesInfra_Facts_Good_HostnameFromCommand(t *core.T) { e := NewExecutor("/tmp") e.facts["host1"] = &Facts{ Hostname: "myserver", FQDN: "myserver.example.com", } - assert.Equal(t, "myserver", e.templateString("{{ ansible_hostname }}", "host1", nil)) - assert.Equal(t, "myserver.example.com", e.templateString("{{ ansible_fqdn }}", "host1", nil)) + core.AssertEqual(t, "myserver", e.templateString("{{ ansible_hostname }}", "host1", nil)) + core.AssertEqual(t, "myserver.example.com", e.templateString("{{ ansible_fqdn }}", "host1", nil)) } -func TestModulesInfra_Facts_Good_ArchitectureResolution(t *testing.T) { +func TestModulesInfra_Facts_Good_ArchitectureResolution(t *core.T) { e := NewExecutor("/tmp") e.facts["host1"] = &Facts{ Architecture: "aarch64", } result := e.templateString("{{ ansible_architecture }}", "host1", nil) - assert.Equal(t, "aarch64", result) + core.AssertEqual(t, "aarch64", result) } -func TestModulesInfra_Facts_Good_KernelResolution(t *testing.T) { +func TestModulesInfra_Facts_Good_KernelResolution(t *core.T) { e := NewExecutor("/tmp") e.facts["host1"] = &Facts{ Kernel: "5.15.0-91-generic", } result := e.templateString("{{ ansible_kernel }}", "host1", nil) - assert.Equal(t, "5.15.0-91-generic", result) + core.AssertEqual(t, "5.15.0-91-generic", result) } -func TestModulesInfra_Facts_Good_NoFactsForHost(t *testing.T) { +func TestModulesInfra_Facts_Good_NoFactsForHost(t *core.T) { e := NewExecutor("/tmp") // No facts gathered for host1 result := e.templateString("{{ ansible_hostname }}", "host1", nil) // Should remain unresolved - assert.Equal(t, "{{ ansible_hostname }}", result) + core.AssertEqual(t, "{{ ansible_hostname }}", result) } -func TestModulesInfra_Facts_Good_LocalhostFacts(t *testing.T) { +func TestModulesInfra_Facts_Good_LocalhostFacts(t *core.T) { // When connection is local, gatherFacts sets minimal facts e := NewExecutor("/tmp") e.facts["localhost"] = &Facts{ @@ -974,10 +987,10 @@ func TestModulesInfra_Facts_Good_LocalhostFacts(t *testing.T) { } result := e.templateString("{{ ansible_hostname }}", "localhost", nil) - assert.Equal(t, "localhost", result) + core.AssertEqual(t, "localhost", result) } -func TestModulesInfra_Facts_Good_AnsibleFactsMapResolution(t *testing.T) { +func TestModulesInfra_Facts_Good_AnsibleFactsMapResolution(t *core.T) { e := NewExecutor("/tmp") e.facts["host1"] = &Facts{ Hostname: "web1", @@ -986,13 +999,13 @@ func TestModulesInfra_Facts_Good_AnsibleFactsMapResolution(t *testing.T) { Version: "12", } - assert.Equal(t, "web1", e.templateString("{{ ansible_facts.ansible_hostname }}", "host1", nil)) - assert.Equal(t, "debian", e.templateString("{{ ansible_facts.ansible_distribution }}", "host1", nil)) - assert.True(t, e.evalCondition("ansible_facts.ansible_hostname == 'web1'", "host1")) - assert.True(t, e.evalCondition("ansible_facts.ansible_distribution == 'debian'", "host1")) + core.AssertEqual(t, "web1", e.templateString("{{ ansible_facts.ansible_hostname }}", "host1", nil)) + core.AssertEqual(t, "debian", e.templateString("{{ ansible_facts.ansible_distribution }}", "host1", nil)) + core.AssertTrue(t, e.evalCondition("ansible_facts.ansible_hostname == 'web1'", "host1")) + core.AssertTrue(t, e.evalCondition("ansible_facts.ansible_distribution == 'debian'", "host1")) } -func TestModulesInfra_ModuleSetup_Good_GathersAndStoresFacts(t *testing.T) { +func TestModulesInfra_ModuleSetup_Good_GathersAndStoresFacts(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`hostname -f`, "web1.example.com\n", "", 0) @@ -1007,34 +1020,34 @@ func TestModulesInfra_ModuleSetup_Good_GathersAndStoresFacts(t *testing.T) { task := &Task{Module: "setup"} result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - require.NotNil(t, result) - assert.False(t, result.Changed) - assert.Equal(t, "facts gathered", result.Msg) - require.NotNil(t, result.Data) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Changed) + core.AssertEqual(t, "facts gathered", result.Msg) + core.AssertNotNil(t, result.Data) facts, ok := result.Data["ansible_facts"].(map[string]any) - require.True(t, ok) - assert.Equal(t, "web1", facts["ansible_hostname"]) - assert.Equal(t, "web1.example.com", facts["ansible_fqdn"]) - assert.Equal(t, "Debian", facts["ansible_os_family"]) - assert.Equal(t, "debian", facts["ansible_distribution"]) - assert.Equal(t, "12", facts["ansible_distribution_version"]) - assert.Equal(t, "x86_64", facts["ansible_architecture"]) - assert.Equal(t, "6.1.0", facts["ansible_kernel"]) - assert.EqualValues(t, 8, facts["ansible_processor_vcpus"]) - assert.EqualValues(t, 16384, facts["ansible_memtotal_mb"]) - assert.Equal(t, "10.0.0.11", facts["ansible_default_ipv4_address"]) - - require.NotNil(t, e.facts["host1"]) - assert.Equal(t, "web1", e.templateString("{{ ansible_hostname }}", "host1", nil)) - assert.Equal(t, "Debian", e.templateString("{{ ansible_os_family }}", "host1", nil)) - assert.Equal(t, "16384", e.templateString("{{ ansible_memtotal_mb }}", "host1", nil)) - assert.Equal(t, "8", e.templateString("{{ ansible_processor_vcpus }}", "host1", nil)) - assert.Equal(t, "10.0.0.11", e.templateString("{{ ansible_default_ipv4_address }}", "host1", nil)) -} - -func TestModulesInfra_ModuleSetup_Good_FilteredFacts(t *testing.T) { + core.RequireTrue(t, ok) + core.AssertEqual(t, "web1", facts["ansible_hostname"]) + core.AssertEqual(t, "web1.example.com", facts["ansible_fqdn"]) + core.AssertEqual(t, "Debian", facts["ansible_os_family"]) + core.AssertEqual(t, "debian", facts["ansible_distribution"]) + core.AssertEqual(t, "12", facts["ansible_distribution_version"]) + core.AssertEqual(t, "x86_64", facts["ansible_architecture"]) + core.AssertEqual(t, "6.1.0", facts["ansible_kernel"]) + core.AssertEqual(t, 8, facts["ansible_processor_vcpus"]) + core.AssertEqual(t, int64(16384), facts["ansible_memtotal_mb"]) + core.AssertEqual(t, "10.0.0.11", facts["ansible_default_ipv4_address"]) + + core.AssertNotNil(t, e.facts["host1"]) + core.AssertEqual(t, "web1", e.templateString("{{ ansible_hostname }}", "host1", nil)) + core.AssertEqual(t, "Debian", e.templateString("{{ ansible_os_family }}", "host1", nil)) + core.AssertEqual(t, "16384", e.templateString("{{ ansible_memtotal_mb }}", "host1", nil)) + core.AssertEqual(t, "8", e.templateString("{{ ansible_processor_vcpus }}", "host1", nil)) + core.AssertEqual(t, "10.0.0.11", e.templateString("{{ ansible_default_ipv4_address }}", "host1", nil)) +} + +func TestModulesInfra_ModuleSetup_Good_FilteredFacts(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`hostname -f`, "web1.example.com\n", "", 0) @@ -1054,24 +1067,24 @@ func TestModulesInfra_ModuleSetup_Good_FilteredFacts(t *testing.T) { } result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - require.NotNil(t, result) - assert.False(t, result.Changed) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Changed) facts, ok := result.Data["ansible_facts"].(map[string]any) - require.True(t, ok) - assert.Len(t, facts, 2) - assert.Equal(t, "web1", facts["ansible_hostname"]) - assert.Equal(t, "debian", facts["ansible_distribution"]) - assert.NotContains(t, facts, "ansible_os_family") + core.RequireTrue(t, ok) + core.AssertLen(t, facts, 2) + core.AssertEqual(t, "web1", facts["ansible_hostname"]) + core.AssertEqual(t, "debian", facts["ansible_distribution"]) + core.AssertNotContains(t, facts, "ansible_os_family") - require.NotNil(t, e.facts["host1"]) - assert.Equal(t, "web1", e.templateString("{{ ansible_hostname }}", "host1", nil)) - assert.Equal(t, "", e.facts["host1"].OS) - assert.Equal(t, "debian", e.facts["host1"].Distribution) + core.AssertNotNil(t, e.facts["host1"]) + core.AssertEqual(t, "web1", e.templateString("{{ ansible_hostname }}", "host1", nil)) + core.AssertEqual(t, "", e.facts["host1"].OS) + core.AssertEqual(t, "debian", e.facts["host1"].Distribution) } -func TestModulesInfra_ModuleSetup_Good_VirtualSubset(t *testing.T) { +func TestModulesInfra_ModuleSetup_Good_VirtualSubset(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`hostname -f`, "web1.example.com\n", "", 0) @@ -1092,25 +1105,25 @@ func TestModulesInfra_ModuleSetup_Good_VirtualSubset(t *testing.T) { } result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - require.NotNil(t, result) - assert.False(t, result.Changed) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Changed) facts, ok := result.Data["ansible_facts"].(map[string]any) - require.True(t, ok) - assert.Len(t, facts, 2) - assert.Equal(t, "guest", facts["ansible_virtualization_role"]) - assert.Equal(t, "docker", facts["ansible_virtualization_type"]) - assert.NotContains(t, facts, "ansible_hostname") + core.RequireTrue(t, ok) + core.AssertLen(t, facts, 2) + core.AssertEqual(t, "guest", facts["ansible_virtualization_role"]) + core.AssertEqual(t, "docker", facts["ansible_virtualization_type"]) + core.AssertNotContains(t, facts, "ansible_hostname") - require.NotNil(t, e.facts["host1"]) - assert.Equal(t, "guest", e.facts["host1"].VirtualizationRole) - assert.Equal(t, "docker", e.facts["host1"].VirtualizationType) - assert.Equal(t, "guest", e.templateString("{{ ansible_virtualization_role }}", "host1", nil)) - assert.Equal(t, "docker", e.templateString("{{ ansible_virtualization_type }}", "host1", nil)) + core.AssertNotNil(t, e.facts["host1"]) + core.AssertEqual(t, "guest", e.facts["host1"].VirtualizationRole) + core.AssertEqual(t, "docker", e.facts["host1"].VirtualizationType) + core.AssertEqual(t, "guest", e.templateString("{{ ansible_virtualization_role }}", "host1", nil)) + core.AssertEqual(t, "docker", e.templateString("{{ ansible_virtualization_type }}", "host1", nil)) } -func TestModulesInfra_ModuleSetup_Good_GatherSubset(t *testing.T) { +func TestModulesInfra_ModuleSetup_Good_GatherSubset(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`hostname -f`, "web1.example.com\n", "", 0) @@ -1130,25 +1143,25 @@ func TestModulesInfra_ModuleSetup_Good_GatherSubset(t *testing.T) { } result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - require.NotNil(t, result) - require.NotNil(t, result.Data) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertNotNil(t, result.Data) facts, ok := result.Data["ansible_facts"].(map[string]any) - require.True(t, ok) - assert.Len(t, facts, 1) - assert.Equal(t, "10.0.0.11", facts["ansible_default_ipv4_address"]) - assert.NotContains(t, facts, "ansible_hostname") - assert.NotContains(t, facts, "ansible_distribution") + core.RequireTrue(t, ok) + core.AssertLen(t, facts, 1) + core.AssertEqual(t, "10.0.0.11", facts["ansible_default_ipv4_address"]) + core.AssertNotContains(t, facts, "ansible_hostname") + core.AssertNotContains(t, facts, "ansible_distribution") - require.NotNil(t, e.facts["host1"]) - assert.Equal(t, "", e.facts["host1"].Hostname) - assert.Equal(t, "10.0.0.11", e.facts["host1"].IPv4) - assert.Equal(t, "", e.templateString("{{ ansible_hostname }}", "host1", nil)) - assert.Equal(t, "10.0.0.11", e.templateString("{{ ansible_default_ipv4_address }}", "host1", nil)) + core.AssertNotNil(t, e.facts["host1"]) + core.AssertEqual(t, "", e.facts["host1"].Hostname) + core.AssertEqual(t, "10.0.0.11", e.facts["host1"].IPv4) + core.AssertEqual(t, "", e.templateString("{{ ansible_hostname }}", "host1", nil)) + core.AssertEqual(t, "10.0.0.11", e.templateString("{{ ansible_default_ipv4_address }}", "host1", nil)) } -func TestModulesInfra_ModuleSetup_Good_RespectsGatherTimeout(t *testing.T) { +func TestModulesInfra_ModuleSetup_Good_RespectsGatherTimeout(t *core.T) { e := NewExecutor("/tmp") start := time.Now() @@ -1157,14 +1170,14 @@ func TestModulesInfra_ModuleSetup_Good_RespectsGatherTimeout(t *testing.T) { }) elapsed := time.Since(start) - require.NoError(t, err) - require.NotNil(t, result) - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, "context deadline exceeded") - assert.GreaterOrEqual(t, elapsed, time.Second) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, "context deadline exceeded") + core.AssertGreaterOrEqual(t, elapsed, time.Second) } -func TestModulesInfra_ModuleArchive_Good_CreateZipArchive(t *testing.T) { +func TestModulesInfra_ModuleArchive_Good_CreateZipArchive(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleArchiveWithClient(e, mock, map[string]any{ @@ -1173,19 +1186,19 @@ func TestModulesInfra_ModuleArchive_Good_CreateZipArchive(t *testing.T) { "format": "zip", }) - require.NoError(t, err) - require.NotNil(t, result) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`mkdir -p "/tmp"`)) - assert.True(t, mock.hasExecuted(`zip -r "/tmp/configs.zip" "/etc/nginx/nginx.conf" "/etc/hosts"`)) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`mkdir -p "/tmp"`)) + core.AssertTrue(t, mock.hasExecuted(`zip -r "/tmp/configs.zip" "/etc/nginx/nginx.conf" "/etc/hosts"`)) } // =========================================================================== // 4. Idempotency // =========================================================================== -func TestModulesInfra_Idempotency_Good_GroupAlreadyExists(t *testing.T) { +func TestModulesInfra_Idempotency_Good_GroupAlreadyExists(t *core.T) { _, mock := newTestExecutorWithMock("host1") // Mock: getent group docker succeeds (group exists) — the || means groupadd is skipped @@ -1200,17 +1213,17 @@ func TestModulesInfra_Idempotency_Good_GroupAlreadyExists(t *testing.T) { } result, err := moduleGroupWithClient(nil, mock, task.Args) - require.NoError(t, err) + core.RequireNoError(t, err) // The module runs the command: getent group docker >/dev/null 2>&1 || groupadd docker // Since getent succeeds (rc=0), groupadd is not executed by the shell. // However, the module always reports changed=true because it does not // check idempotency at the Go level. This tests the current behaviour. - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) } -func TestModulesInfra_Idempotency_Good_AuthorizedKeyAlreadyPresent(t *testing.T) { +func TestModulesInfra_Idempotency_Good_AuthorizedKeyAlreadyPresent(t *core.T) { _, mock := newTestExecutorWithMock("host1") testKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7xfG..." + @@ -1233,15 +1246,15 @@ func TestModulesInfra_Idempotency_Good_AuthorizedKeyAlreadyPresent(t *testing.T) "key": testKey, "state": "present", }) - require.NoError(t, err) + core.RequireNoError(t, err) // Module reports changed=true regardless (it doesn't check grep result at Go level) // The grep || echo construct handles idempotency at the shell level - assert.NotNil(t, result) - assert.False(t, result.Failed) + core.AssertNotNil(t, result) + core.AssertFalse(t, result.Failed) } -func TestModulesInfra_Idempotency_Good_DockerComposeUpToDate(t *testing.T) { +func TestModulesInfra_Idempotency_Good_DockerComposeUpToDate(t *core.T) { _, mock := newTestExecutorWithMock("host1") // Mock: docker compose up -d returns "Up to date" in stdout @@ -1251,15 +1264,15 @@ func TestModulesInfra_Idempotency_Good_DockerComposeUpToDate(t *testing.T) { "project_src": "/opt/myapp", "state": "present", }) - require.NoError(t, err) - require.NotNil(t, result) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) // When stdout contains "Up to date", changed should be false - assert.False(t, result.Changed) - assert.False(t, result.Failed) + core.AssertFalse(t, result.Changed) + core.AssertFalse(t, result.Failed) } -func TestModulesInfra_Idempotency_Good_DockerComposeChanged(t *testing.T) { +func TestModulesInfra_Idempotency_Good_DockerComposeChanged(t *core.T) { _, mock := newTestExecutorWithMock("host1") // Mock: docker compose up -d with actual changes @@ -1269,15 +1282,15 @@ func TestModulesInfra_Idempotency_Good_DockerComposeChanged(t *testing.T) { "project_src": "/opt/myapp", "state": "present", }) - require.NoError(t, err) - require.NotNil(t, result) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) // When stdout does NOT contain "Up to date", changed should be true - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) } -func TestModulesInfra_Idempotency_Good_DockerComposeUpToDateInStderr(t *testing.T) { +func TestModulesInfra_Idempotency_Good_DockerComposeUpToDateInStderr(t *core.T) { _, mock := newTestExecutorWithMock("host1") // Some versions of docker compose output status to stderr @@ -1287,14 +1300,14 @@ func TestModulesInfra_Idempotency_Good_DockerComposeUpToDateInStderr(t *testing. "project_src": "/opt/myapp", "state": "present", }) - require.NoError(t, err) - require.NotNil(t, result) + core.RequireNoError(t, err) + core.AssertNotNil(t, result) // The docker compose module checks both stdout and stderr for "Up to date" - assert.False(t, result.Changed) + core.AssertFalse(t, result.Changed) } -func TestModulesInfra_Idempotency_Good_GroupCreationWhenNew(t *testing.T) { +func TestModulesInfra_Idempotency_Good_GroupCreationWhenNew(t *core.T) { _, mock := newTestExecutorWithMock("host1") // Mock: getent fails (group does not exist), groupadd succeeds @@ -1307,13 +1320,13 @@ func TestModulesInfra_Idempotency_Good_GroupCreationWhenNew(t *testing.T) { "name": "newgroup", "state": "present", }) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) } -func TestModulesInfra_Idempotency_Good_ServiceStatChanged(t *testing.T) { +func TestModulesInfra_Idempotency_Good_ServiceStatChanged(t *core.T) { _, mock := newTestExecutorWithMock("host1") // Mock: stat reports the file exists @@ -1322,35 +1335,35 @@ func TestModulesInfra_Idempotency_Good_ServiceStatChanged(t *testing.T) { result, err := moduleStatWithClient(nil, mock, map[string]any{ "path": "/etc/config.conf", }) - require.NoError(t, err) + core.RequireNoError(t, err) // Stat module should always report changed=false - assert.False(t, result.Changed) - assert.NotNil(t, result.Data) + core.AssertFalse(t, result.Changed) + core.AssertNotNil(t, result.Data) stat := result.Data["stat"].(map[string]any) - assert.True(t, stat["exists"].(bool)) + core.AssertTrue(t, stat["exists"].(bool)) } -func TestModulesInfra_Idempotency_Good_StatFileNotFound(t *testing.T) { +func TestModulesInfra_Idempotency_Good_StatFileNotFound(t *core.T) { _, mock := newTestExecutorWithMock("host1") // No stat info added — will return exists=false from mock result, err := moduleStatWithClient(nil, mock, map[string]any{ "path": "/nonexistent/file", }) - require.NoError(t, err) + core.RequireNoError(t, err) - assert.False(t, result.Changed) - assert.NotNil(t, result.Data) + core.AssertFalse(t, result.Changed) + core.AssertNotNil(t, result.Data) stat := result.Data["stat"].(map[string]any) - assert.False(t, stat["exists"].(bool)) + core.AssertFalse(t, stat["exists"].(bool)) } // =========================================================================== // Additional cross-cutting edge cases // =========================================================================== -func TestModulesInfra_ResolveExpr_Good_HostVars(t *testing.T) { +func TestModulesInfra_ResolveExpr_Good_HostVars(t *core.T) { e := NewExecutor("/tmp") e.SetInventoryDirect(&Inventory{ All: &InventoryGroup{ @@ -1366,10 +1379,10 @@ func TestModulesInfra_ResolveExpr_Good_HostVars(t *testing.T) { }) result := e.templateString("{{ custom_var }}", "host1", nil) - assert.Equal(t, "custom_value", result) + core.AssertEqual(t, "custom_value", result) } -func TestModulesInfra_TemplateArgs_Good_InventoryHostname(t *testing.T) { +func TestModulesInfra_TemplateArgs_Good_InventoryHostname(t *core.T) { e := NewExecutor("/tmp") args := map[string]any{ @@ -1377,15 +1390,16 @@ func TestModulesInfra_TemplateArgs_Good_InventoryHostname(t *testing.T) { } result := e.templateArgs(args, "web1", nil) - assert.Equal(t, "web1", result["hostname"]) + core.AssertEqual(t, "web1", result["hostname"]) } -func TestModulesInfra_EvalCondition_Good_UnknownComparisonFailsClosed(t *testing.T) { +func TestModulesInfra_EvalCondition_Good_UnknownComparisonFailsClosed(t *core.T) { e := NewExecutor("/tmp") - assert.False(t, e.evalCondition("some_complex_expression == 'value'", "host1")) + result := e.evalCondition("some_complex_expression == 'value'", "host1") + core.AssertFalse(t, result) } -func TestModulesInfra_GetRegisteredVar_Good_DottedAccess(t *testing.T) { +func TestModulesInfra_GetRegisteredVar_Good_DottedAccess(t *core.T) { e := NewExecutor("/tmp") e.results["host1"] = map[string]*TaskResult{ "my_cmd": {Stdout: "output_text", RC: 0}, @@ -1394,18 +1408,18 @@ func TestModulesInfra_GetRegisteredVar_Good_DottedAccess(t *testing.T) { // getRegisteredVar parses dotted names result := e.getRegisteredVar("host1", "my_cmd.stdout") // getRegisteredVar only looks up the base name (before the dot) - assert.NotNil(t, result) - assert.Equal(t, "output_text", result.Stdout) + core.AssertNotNil(t, result) + core.AssertEqual(t, "output_text", result.Stdout) } -func TestModulesInfra_GetRegisteredVar_Bad_NotRegistered(t *testing.T) { +func TestModulesInfra_GetRegisteredVar_Bad_NotRegistered(t *core.T) { e := NewExecutor("/tmp") result := e.getRegisteredVar("host1", "nonexistent") - assert.Nil(t, result) + core.AssertNil(t, result) } -func TestModulesInfra_GetRegisteredVar_Bad_WrongHost(t *testing.T) { +func TestModulesInfra_GetRegisteredVar_Bad_WrongHost(t *core.T) { e := NewExecutor("/tmp") e.results["host1"] = map[string]*TaskResult{ "my_cmd": {Stdout: "output"}, @@ -1413,7 +1427,7 @@ func TestModulesInfra_GetRegisteredVar_Bad_WrongHost(t *testing.T) { // Different host has no results result := e.getRegisteredVar("host2", "my_cmd") - assert.Nil(t, result) + core.AssertNil(t, result) } // =========================================================================== diff --git a/modules_svc_test.go b/modules_svc_test.go index f1e0545..4446844 100644 --- a/modules_svc_test.go +++ b/modules_svc_test.go @@ -1,10 +1,7 @@ package ansible import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + core "dappco.re/go" ) // ============================================================ @@ -13,7 +10,7 @@ import ( // --- service module --- -func TestModulesSvc_ModuleService_Good_Start(t *testing.T) { +func TestModulesSvc_ModuleService_Good_Start(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`systemctl start nginx`, "Started", "", 0) @@ -22,14 +19,14 @@ func TestModulesSvc_ModuleService_Good_Start(t *testing.T) { "state": "started", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`systemctl start nginx`)) - assert.Equal(t, 1, mock.commandCount()) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`systemctl start nginx`)) + core.AssertEqual(t, 1, mock.commandCount()) } -func TestModulesSvc_ModuleService_Good_Stop(t *testing.T) { +func TestModulesSvc_ModuleService_Good_Stop(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`systemctl stop nginx`, "", "", 0) @@ -38,13 +35,13 @@ func TestModulesSvc_ModuleService_Good_Stop(t *testing.T) { "state": "stopped", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`systemctl stop nginx`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`systemctl stop nginx`)) } -func TestModulesSvc_ModuleService_Good_Restart(t *testing.T) { +func TestModulesSvc_ModuleService_Good_Restart(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`systemctl restart docker`, "", "", 0) @@ -53,13 +50,13 @@ func TestModulesSvc_ModuleService_Good_Restart(t *testing.T) { "state": "restarted", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`systemctl restart docker`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`systemctl restart docker`)) } -func TestModulesSvc_ModuleService_Good_Reload(t *testing.T) { +func TestModulesSvc_ModuleService_Good_Reload(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`systemctl reload nginx`, "", "", 0) @@ -68,13 +65,13 @@ func TestModulesSvc_ModuleService_Good_Reload(t *testing.T) { "state": "reloaded", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`systemctl reload nginx`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`systemctl reload nginx`)) } -func TestModulesSvc_ModuleService_Good_Enable(t *testing.T) { +func TestModulesSvc_ModuleService_Good_Enable(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`systemctl enable nginx`, "", "", 0) @@ -83,13 +80,13 @@ func TestModulesSvc_ModuleService_Good_Enable(t *testing.T) { "enabled": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`systemctl enable nginx`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`systemctl enable nginx`)) } -func TestModulesSvc_ModuleService_Good_Disable(t *testing.T) { +func TestModulesSvc_ModuleService_Good_Disable(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`systemctl disable nginx`, "", "", 0) @@ -98,13 +95,13 @@ func TestModulesSvc_ModuleService_Good_Disable(t *testing.T) { "enabled": false, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`systemctl disable nginx`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`systemctl disable nginx`)) } -func TestModulesSvc_ModuleService_Good_StartAndEnable(t *testing.T) { +func TestModulesSvc_ModuleService_Good_StartAndEnable(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`systemctl start nginx`, "", "", 0) mock.expectCommand(`systemctl enable nginx`, "", "", 0) @@ -115,15 +112,15 @@ func TestModulesSvc_ModuleService_Good_StartAndEnable(t *testing.T) { "enabled": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.Equal(t, 2, mock.commandCount()) - assert.True(t, mock.hasExecuted(`systemctl start nginx`)) - assert.True(t, mock.hasExecuted(`systemctl enable nginx`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, 2, mock.commandCount()) + core.AssertTrue(t, mock.hasExecuted(`systemctl start nginx`)) + core.AssertTrue(t, mock.hasExecuted(`systemctl enable nginx`)) } -func TestModulesSvc_ModuleService_Good_RestartAndDisable(t *testing.T) { +func TestModulesSvc_ModuleService_Good_RestartAndDisable(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`systemctl restart sshd`, "", "", 0) mock.expectCommand(`systemctl disable sshd`, "", "", 0) @@ -134,15 +131,15 @@ func TestModulesSvc_ModuleService_Good_RestartAndDisable(t *testing.T) { "enabled": false, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.Equal(t, 2, mock.commandCount()) - assert.True(t, mock.hasExecuted(`systemctl restart sshd`)) - assert.True(t, mock.hasExecuted(`systemctl disable sshd`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, 2, mock.commandCount()) + core.AssertTrue(t, mock.hasExecuted(`systemctl restart sshd`)) + core.AssertTrue(t, mock.hasExecuted(`systemctl disable sshd`)) } -func TestModulesSvc_ModuleService_Bad_MissingName(t *testing.T) { +func TestModulesSvc_ModuleService_Bad_MissingName(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() @@ -150,11 +147,11 @@ func TestModulesSvc_ModuleService_Bad_MissingName(t *testing.T) { "state": "started", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "name required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "name required") } -func TestModulesSvc_ModuleService_Good_NoStateNoEnabled(t *testing.T) { +func TestModulesSvc_ModuleService_Good_NoStateNoEnabled(t *core.T) { // When neither state nor enabled is provided, no commands run e, mock := newTestExecutorWithMock("host1") @@ -162,13 +159,13 @@ func TestModulesSvc_ModuleService_Good_NoStateNoEnabled(t *testing.T) { "name": "nginx", }) - require.NoError(t, err) - assert.False(t, result.Changed) - assert.False(t, result.Failed) - assert.Equal(t, 0, mock.commandCount()) + core.RequireNoError(t, err) + core.AssertFalse(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, 0, mock.commandCount()) } -func TestModulesSvc_ModuleService_Good_CommandFailure(t *testing.T) { +func TestModulesSvc_ModuleService_Good_CommandFailure(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`systemctl start.*`, "", "Failed to start nginx.service", 1) @@ -177,13 +174,13 @@ func TestModulesSvc_ModuleService_Good_CommandFailure(t *testing.T) { "state": "started", }) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, "Failed to start nginx.service") - assert.Equal(t, 1, result.RC) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, "Failed to start nginx.service") + core.AssertEqual(t, 1, result.RC) } -func TestModulesSvc_ModuleService_Good_FirstCommandFailsSkipsRest(t *testing.T) { +func TestModulesSvc_ModuleService_Good_FirstCommandFailsSkipsRest(t *core.T) { // When state command fails, enable should not run e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`systemctl start`, "", "unit not found", 5) @@ -194,16 +191,16 @@ func TestModulesSvc_ModuleService_Good_FirstCommandFailsSkipsRest(t *testing.T) "enabled": true, }) - require.NoError(t, err) - assert.True(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) // Only the start command should have been attempted - assert.Equal(t, 1, mock.commandCount()) - assert.False(t, mock.hasExecuted(`systemctl enable`)) + core.AssertEqual(t, 1, mock.commandCount()) + core.AssertFalse(t, mock.hasExecuted(`systemctl enable`)) } // --- systemd module --- -func TestModulesSvc_ModuleSystemd_Good_DaemonReloadThenStart(t *testing.T) { +func TestModulesSvc_ModuleSystemd_Good_DaemonReloadThenStart(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`systemctl daemon-reload`, "", "", 0) mock.expectCommand(`systemctl start nginx`, "", "", 0) @@ -214,18 +211,18 @@ func TestModulesSvc_ModuleSystemd_Good_DaemonReloadThenStart(t *testing.T) { "daemon_reload": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) // daemon-reload must run first, then start cmds := mock.executedCommands() - require.GreaterOrEqual(t, len(cmds), 2) - assert.Contains(t, cmds[0].Cmd, "daemon-reload") - assert.Contains(t, cmds[1].Cmd, "systemctl start nginx") + core.AssertGreaterOrEqual(t, len(cmds), 2) + core.AssertContains(t, cmds[0].Cmd, "daemon-reload") + core.AssertContains(t, cmds[1].Cmd, "systemctl start nginx") } -func TestModulesSvc_ModuleSystemd_Good_DaemonReloadOnly(t *testing.T) { +func TestModulesSvc_ModuleSystemd_Good_DaemonReloadOnly(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`systemctl daemon-reload`, "", "", 0) @@ -234,16 +231,16 @@ func TestModulesSvc_ModuleSystemd_Good_DaemonReloadOnly(t *testing.T) { "daemon_reload": true, }) - require.NoError(t, err) + core.RequireNoError(t, err) // daemon-reload runs, but no state/enabled means no further commands // Changed is false because moduleService returns Changed: len(cmds) > 0 // and no cmds were built (no state, no enabled) - assert.False(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`systemctl daemon-reload`)) + core.AssertFalse(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`systemctl daemon-reload`)) } -func TestModulesSvc_ModuleSystemd_Good_DelegationToService(t *testing.T) { +func TestModulesSvc_ModuleSystemd_Good_DelegationToService(t *core.T) { // Without daemon_reload, systemd delegates entirely to service e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`systemctl restart docker`, "", "", 0) @@ -253,15 +250,15 @@ func TestModulesSvc_ModuleSystemd_Good_DelegationToService(t *testing.T) { "state": "restarted", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`systemctl restart docker`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`systemctl restart docker`)) // No daemon-reload should have run - assert.False(t, mock.hasExecuted(`daemon-reload`)) + core.AssertFalse(t, mock.hasExecuted(`daemon-reload`)) } -func TestModulesSvc_ModuleSystemd_Good_DaemonReloadWithEnable(t *testing.T) { +func TestModulesSvc_ModuleSystemd_Good_DaemonReloadWithEnable(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`systemctl daemon-reload`, "", "", 0) mock.expectCommand(`systemctl enable myapp`, "", "", 0) @@ -272,16 +269,16 @@ func TestModulesSvc_ModuleSystemd_Good_DaemonReloadWithEnable(t *testing.T) { "daemon_reload": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`systemctl daemon-reload`)) - assert.True(t, mock.hasExecuted(`systemctl enable myapp`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`systemctl daemon-reload`)) + core.AssertTrue(t, mock.hasExecuted(`systemctl enable myapp`)) } // --- apt module --- -func TestModulesSvc_ModuleApt_Good_InstallPresent(t *testing.T) { +func TestModulesSvc_ModuleApt_Good_InstallPresent(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`apt-get install -y -qq nginx`, "installed", "", 0) @@ -290,13 +287,13 @@ func TestModulesSvc_ModuleApt_Good_InstallPresent(t *testing.T) { "state": "present", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`DEBIAN_FRONTEND=noninteractive apt-get install -y -qq nginx`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`DEBIAN_FRONTEND=noninteractive apt-get install -y -qq nginx`)) } -func TestModulesSvc_ModuleApt_Good_InstallInstalled(t *testing.T) { +func TestModulesSvc_ModuleApt_Good_InstallInstalled(t *core.T) { // state=installed is an alias for present e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`apt-get install -y -qq curl`, "", "", 0) @@ -306,13 +303,13 @@ func TestModulesSvc_ModuleApt_Good_InstallInstalled(t *testing.T) { "state": "installed", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`apt-get install -y -qq curl`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`apt-get install -y -qq curl`)) } -func TestModulesSvc_ModuleApt_Good_RemoveAbsent(t *testing.T) { +func TestModulesSvc_ModuleApt_Good_RemoveAbsent(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`apt-get remove -y -qq nginx`, "", "", 0) @@ -321,13 +318,13 @@ func TestModulesSvc_ModuleApt_Good_RemoveAbsent(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`DEBIAN_FRONTEND=noninteractive apt-get remove -y -qq nginx`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`DEBIAN_FRONTEND=noninteractive apt-get remove -y -qq nginx`)) } -func TestModulesSvc_ModuleApt_Good_RemoveRemoved(t *testing.T) { +func TestModulesSvc_ModuleApt_Good_RemoveRemoved(t *core.T) { // state=removed is an alias for absent e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`apt-get remove -y -qq nginx`, "", "", 0) @@ -337,12 +334,12 @@ func TestModulesSvc_ModuleApt_Good_RemoveRemoved(t *testing.T) { "state": "removed", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`apt-get remove -y -qq nginx`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`apt-get remove -y -qq nginx`)) } -func TestModulesSvc_ModuleApt_Good_UpgradeLatest(t *testing.T) { +func TestModulesSvc_ModuleApt_Good_UpgradeLatest(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`apt-get install -y -qq --only-upgrade nginx`, "", "", 0) @@ -351,13 +348,13 @@ func TestModulesSvc_ModuleApt_Good_UpgradeLatest(t *testing.T) { "state": "latest", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --only-upgrade nginx`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --only-upgrade nginx`)) } -func TestModulesSvc_ModuleApt_Good_UpdateCacheBeforeInstall(t *testing.T) { +func TestModulesSvc_ModuleApt_Good_UpdateCacheBeforeInstall(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`apt-get update`, "", "", 0) mock.expectCommand(`apt-get install -y -qq nginx`, "", "", 0) @@ -368,18 +365,18 @@ func TestModulesSvc_ModuleApt_Good_UpdateCacheBeforeInstall(t *testing.T) { "update_cache": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) // apt-get update must run before install cmds := mock.executedCommands() - require.GreaterOrEqual(t, len(cmds), 2) - assert.Contains(t, cmds[0].Cmd, "apt-get update") - assert.Contains(t, cmds[1].Cmd, "apt-get install") + core.AssertGreaterOrEqual(t, len(cmds), 2) + core.AssertContains(t, cmds[0].Cmd, "apt-get update") + core.AssertContains(t, cmds[1].Cmd, "apt-get install") } -func TestModulesSvc_ModuleApt_Good_UpdateCacheOnly(t *testing.T) { +func TestModulesSvc_ModuleApt_Good_UpdateCacheOnly(t *core.T) { // update_cache with no name means update only, no install e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`apt-get update`, "", "", 0) @@ -388,14 +385,14 @@ func TestModulesSvc_ModuleApt_Good_UpdateCacheOnly(t *testing.T) { "update_cache": true, }) - require.NoError(t, err) + core.RequireNoError(t, err) // No package to install → not changed (cmd is empty) - assert.False(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`apt-get update`)) + core.AssertFalse(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`apt-get update`)) } -func TestModulesSvc_ModuleApt_Good_CommandFailure(t *testing.T) { +func TestModulesSvc_ModuleApt_Good_CommandFailure(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`apt-get install`, "", "E: Unable to locate package badpkg", 100) @@ -404,13 +401,13 @@ func TestModulesSvc_ModuleApt_Good_CommandFailure(t *testing.T) { "state": "present", }) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, "Unable to locate package") - assert.Equal(t, 100, result.RC) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, "Unable to locate package") + core.AssertEqual(t, 100, result.RC) } -func TestModulesSvc_ModuleApt_Good_DefaultStateIsPresent(t *testing.T) { +func TestModulesSvc_ModuleApt_Good_DefaultStateIsPresent(t *core.T) { // If no state is given, default is "present" (install) e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`apt-get install -y -qq vim`, "", "", 0) @@ -419,12 +416,12 @@ func TestModulesSvc_ModuleApt_Good_DefaultStateIsPresent(t *testing.T) { "name": "vim", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`apt-get install -y -qq vim`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`apt-get install -y -qq vim`)) } -func TestModulesSvc_ModuleApt_Good_InstallMultiplePackages(t *testing.T) { +func TestModulesSvc_ModuleApt_Good_InstallMultiplePackages(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`apt-get install -y -qq nginx curl`, "", "", 0) @@ -432,14 +429,14 @@ func TestModulesSvc_ModuleApt_Good_InstallMultiplePackages(t *testing.T) { "name": []any{"nginx", "curl"}, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`apt-get install -y -qq nginx curl`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`apt-get install -y -qq nginx curl`)) } // --- apt_key module --- -func TestModulesSvc_ModuleAptKey_Good_AddWithKeyring(t *testing.T) { +func TestModulesSvc_ModuleAptKey_Good_AddWithKeyring(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl -fsSL.*gpg --dearmor`, "", "", 0) @@ -448,15 +445,15 @@ func TestModulesSvc_ModuleAptKey_Good_AddWithKeyring(t *testing.T) { "keyring": "/etc/apt/keyrings/example.gpg", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`curl -fsSL`)) - assert.True(t, mock.hasExecuted(`gpg --dearmor -o`)) - assert.True(t, mock.containsSubstring("/etc/apt/keyrings/example.gpg")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`curl -fsSL`)) + core.AssertTrue(t, mock.hasExecuted(`gpg --dearmor -o`)) + core.AssertTrue(t, mock.containsSubstring("/etc/apt/keyrings/example.gpg")) } -func TestModulesSvc_ModuleAptKey_Good_AddWithoutKeyring(t *testing.T) { +func TestModulesSvc_ModuleAptKey_Good_AddWithoutKeyring(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl -fsSL.*apt-key add -`, "", "", 0) @@ -464,13 +461,13 @@ func TestModulesSvc_ModuleAptKey_Good_AddWithoutKeyring(t *testing.T) { "url": "https://packages.example.com/key.gpg", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`apt-key add -`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`apt-key add -`)) } -func TestModulesSvc_ModuleAptKey_Good_RemoveKey(t *testing.T) { +func TestModulesSvc_ModuleAptKey_Good_RemoveKey(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleAptKeyWithClient(e, mock, map[string]any{ @@ -478,14 +475,14 @@ func TestModulesSvc_ModuleAptKey_Good_RemoveKey(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`rm -f`)) - assert.True(t, mock.containsSubstring("/etc/apt/keyrings/old.gpg")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`rm -f`)) + core.AssertTrue(t, mock.containsSubstring("/etc/apt/keyrings/old.gpg")) } -func TestModulesSvc_ModuleAptKey_Good_RemoveWithoutKeyring(t *testing.T) { +func TestModulesSvc_ModuleAptKey_Good_RemoveWithoutKeyring(t *core.T) { // Absent with no keyring — still succeeds, just no rm command e, mock := newTestExecutorWithMock("host1") @@ -493,12 +490,12 @@ func TestModulesSvc_ModuleAptKey_Good_RemoveWithoutKeyring(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.Equal(t, 0, mock.commandCount()) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertEqual(t, 0, mock.commandCount()) } -func TestModulesSvc_ModuleAptKey_Bad_MissingURL(t *testing.T) { +func TestModulesSvc_ModuleAptKey_Bad_MissingURL(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() @@ -506,11 +503,11 @@ func TestModulesSvc_ModuleAptKey_Bad_MissingURL(t *testing.T) { "state": "present", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "url required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "url required") } -func TestModulesSvc_ModuleAptKey_Good_CommandFailure(t *testing.T) { +func TestModulesSvc_ModuleAptKey_Good_CommandFailure(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl`, "", "curl: (22) 404 Not Found", 22) @@ -519,14 +516,14 @@ func TestModulesSvc_ModuleAptKey_Good_CommandFailure(t *testing.T) { "keyring": "/etc/apt/keyrings/bad.gpg", }) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, "404 Not Found") + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, "404 Not Found") } // --- apt_repository module --- -func TestModulesSvc_ModuleAptRepository_Good_AddRepository(t *testing.T) { +func TestModulesSvc_ModuleAptRepository_Good_AddRepository(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`echo.*sources\.list\.d`, "", "", 0) mock.expectCommand(`apt-get update`, "", "", 0) @@ -536,13 +533,13 @@ func TestModulesSvc_ModuleAptRepository_Good_AddRepository(t *testing.T) { "filename": "example", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.containsSubstring("/etc/apt/sources.list.d/example.list")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.containsSubstring("/etc/apt/sources.list.d/example.list")) } -func TestModulesSvc_ModuleAptRepository_Good_RemoveRepository(t *testing.T) { +func TestModulesSvc_ModuleAptRepository_Good_RemoveRepository(t *core.T) { e, mock := newTestExecutorWithMock("host1") result, err := moduleAptRepositoryWithClient(e, mock, map[string]any{ @@ -551,14 +548,14 @@ func TestModulesSvc_ModuleAptRepository_Good_RemoveRepository(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`rm -f`)) - assert.True(t, mock.containsSubstring("example.list")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`rm -f`)) + core.AssertTrue(t, mock.containsSubstring("example.list")) } -func TestModulesSvc_ModuleAptRepository_Good_AddWithUpdateCache(t *testing.T) { +func TestModulesSvc_ModuleAptRepository_Good_AddWithUpdateCache(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`echo`, "", "", 0) mock.expectCommand(`apt-get update`, "", "", 0) @@ -569,15 +566,15 @@ func TestModulesSvc_ModuleAptRepository_Good_AddWithUpdateCache(t *testing.T) { "update_cache": true, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) // update_cache defaults to true, so apt-get update should run - assert.True(t, mock.hasExecuted(`apt-get update`)) + core.AssertTrue(t, mock.hasExecuted(`apt-get update`)) } -func TestModulesSvc_ModuleAptRepository_Good_AddWithoutUpdateCache(t *testing.T) { +func TestModulesSvc_ModuleAptRepository_Good_AddWithoutUpdateCache(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`echo`, "", "", 0) @@ -587,15 +584,15 @@ func TestModulesSvc_ModuleAptRepository_Good_AddWithoutUpdateCache(t *testing.T) "update_cache": false, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) // update_cache=false, so no apt-get update - assert.False(t, mock.hasExecuted(`apt-get update`)) + core.AssertFalse(t, mock.hasExecuted(`apt-get update`)) } -func TestModulesSvc_ModuleAptRepository_Good_CustomFilename(t *testing.T) { +func TestModulesSvc_ModuleAptRepository_Good_CustomFilename(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`echo`, "", "", 0) mock.expectCommand(`apt-get update`, "", "", 0) @@ -605,12 +602,12 @@ func TestModulesSvc_ModuleAptRepository_Good_CustomFilename(t *testing.T) { "filename": "custom-ppa", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.containsSubstring("/etc/apt/sources.list.d/custom-ppa.list")) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.containsSubstring("/etc/apt/sources.list.d/custom-ppa.list")) } -func TestModulesSvc_ModuleAptRepository_Good_AutoGeneratedFilename(t *testing.T) { +func TestModulesSvc_ModuleAptRepository_Good_AutoGeneratedFilename(t *core.T) { // When no filename is given, it auto-generates from the repo string e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`echo`, "", "", 0) @@ -620,13 +617,13 @@ func TestModulesSvc_ModuleAptRepository_Good_AutoGeneratedFilename(t *testing.T) "repo": "deb https://example.com/repo main", }) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) // Filename should be derived from repo: spaces→dashes, slashes→dashes, colons removed - assert.True(t, mock.containsSubstring("/etc/apt/sources.list.d/")) + core.AssertTrue(t, mock.containsSubstring("/etc/apt/sources.list.d/")) } -func TestModulesSvc_ModuleAptRepository_Bad_MissingRepo(t *testing.T) { +func TestModulesSvc_ModuleAptRepository_Bad_MissingRepo(t *core.T) { e, _ := newTestExecutorWithMock("host1") mock := NewMockSSHClient() @@ -634,11 +631,11 @@ func TestModulesSvc_ModuleAptRepository_Bad_MissingRepo(t *testing.T) { "filename": "test", }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "repo required") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "repo required") } -func TestModulesSvc_ModuleAptRepository_Good_WriteFailure(t *testing.T) { +func TestModulesSvc_ModuleAptRepository_Good_WriteFailure(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`echo`, "", "permission denied", 1) @@ -647,14 +644,14 @@ func TestModulesSvc_ModuleAptRepository_Good_WriteFailure(t *testing.T) { "filename": "test", }) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, "permission denied") + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, "permission denied") } // --- package module --- -func TestModulesSvc_ModulePackage_Good_DetectAptAndDelegate(t *testing.T) { +func TestModulesSvc_ModulePackage_Good_DetectAptAndDelegate(t *core.T) { e, mock := newTestExecutorWithMock("host1") // First command: which apt-get returns the path mock.expectCommand(`which apt-get`, "/usr/bin/apt-get", "", 0) @@ -666,14 +663,14 @@ func TestModulesSvc_ModulePackage_Good_DetectAptAndDelegate(t *testing.T) { "state": "present", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`which apt-get`)) - assert.True(t, mock.hasExecuted(`apt-get install -y -qq htop`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`which apt-get`)) + core.AssertTrue(t, mock.hasExecuted(`apt-get install -y -qq htop`)) } -func TestModulesSvc_ModulePackage_Good_FallbackToApt(t *testing.T) { +func TestModulesSvc_ModulePackage_Good_FallbackToApt(t *core.T) { // When which returns nothing (no package manager found), still falls back to apt e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`which apt-get`, "", "", 1) @@ -684,13 +681,13 @@ func TestModulesSvc_ModulePackage_Good_FallbackToApt(t *testing.T) { "state": "present", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`apt-get install -y -qq vim`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`apt-get install -y -qq vim`)) } -func TestModulesSvc_ModulePackage_Good_RemovePackage(t *testing.T) { +func TestModulesSvc_ModulePackage_Good_RemovePackage(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`which apt-get`, "/usr/bin/apt-get", "", 0) mock.expectCommand(`apt-get remove -y -qq nano`, "", "", 0) @@ -700,12 +697,12 @@ func TestModulesSvc_ModulePackage_Good_RemovePackage(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`apt-get remove -y -qq nano`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`apt-get remove -y -qq nano`)) } -func TestModulesSvc_ModulePackage_Good_DetectYumAndDelegate(t *testing.T) { +func TestModulesSvc_ModulePackage_Good_DetectYumAndDelegate(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`which apt-get yum dnf`, "/usr/bin/yum", "", 0) mock.expectCommand(`yum install -y -q htop`, "", "", 0) @@ -715,13 +712,13 @@ func TestModulesSvc_ModulePackage_Good_DetectYumAndDelegate(t *testing.T) { "state": "present", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`yum install -y -q htop`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`yum install -y -q htop`)) } -func TestModulesSvc_ModulePackage_Good_DetectDnfAndDelegate(t *testing.T) { +func TestModulesSvc_ModulePackage_Good_DetectDnfAndDelegate(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`which apt-get yum dnf`, "/usr/bin/dnf", "", 0) mock.expectCommand(`dnf upgrade -y -q vim`, "", "", 0) @@ -731,13 +728,13 @@ func TestModulesSvc_ModulePackage_Good_DetectDnfAndDelegate(t *testing.T) { "state": "latest", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`dnf upgrade -y -q vim`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`dnf upgrade -y -q vim`)) } -func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchYum(t *testing.T) { +func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchYum(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`yum install -y -q htop`, "", "", 0) @@ -751,12 +748,12 @@ func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchYum(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`yum install -y -q htop`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`yum install -y -q htop`)) } -func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchDnf(t *testing.T) { +func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchDnf(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`dnf remove -y -q nano`, "", "", 0) @@ -770,12 +767,12 @@ func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchDnf(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`dnf remove -y -q nano`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`dnf remove -y -q nano`)) } -func TestModulesSvc_ModuleRpm_Good_InstallPackage(t *testing.T) { +func TestModulesSvc_ModuleRpm_Good_InstallPackage(t *core.T) { mock := NewMockSSHClient() mock.expectCommand(`rpm -ivh /tmp/nginx.rpm`, "", "", 0) @@ -784,13 +781,13 @@ func TestModulesSvc_ModuleRpm_Good_InstallPackage(t *testing.T) { "state": "present", }, "rpm") - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`rpm -ivh /tmp/nginx.rpm`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`rpm -ivh /tmp/nginx.rpm`)) } -func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchRpm(t *testing.T) { +func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchRpm(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`rpm -e nginx`, "", "", 0) @@ -804,14 +801,14 @@ func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchRpm(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`rpm -e nginx`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`rpm -e nginx`)) } // --- pip module --- -func TestModulesSvc_ModulePip_Good_InstallPresent(t *testing.T) { +func TestModulesSvc_ModulePip_Good_InstallPresent(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`pip3 install flask`, "Successfully installed", "", 0) @@ -820,13 +817,13 @@ func TestModulesSvc_ModulePip_Good_InstallPresent(t *testing.T) { "state": "present", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`pip3 install flask`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`pip3 install flask`)) } -func TestModulesSvc_ModulePip_Good_UninstallAbsent(t *testing.T) { +func TestModulesSvc_ModulePip_Good_UninstallAbsent(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`pip3 uninstall -y flask`, "Successfully uninstalled", "", 0) @@ -835,13 +832,13 @@ func TestModulesSvc_ModulePip_Good_UninstallAbsent(t *testing.T) { "state": "absent", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`pip3 uninstall -y flask`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`pip3 uninstall -y flask`)) } -func TestModulesSvc_ModulePip_Good_UpgradeLatest(t *testing.T) { +func TestModulesSvc_ModulePip_Good_UpgradeLatest(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`pip3 install --upgrade flask`, "Successfully installed", "", 0) @@ -850,13 +847,13 @@ func TestModulesSvc_ModulePip_Good_UpgradeLatest(t *testing.T) { "state": "latest", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`pip3 install --upgrade flask`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`pip3 install --upgrade flask`)) } -func TestModulesSvc_ModulePip_Good_CustomExecutable(t *testing.T) { +func TestModulesSvc_ModulePip_Good_CustomExecutable(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`/opt/venv/bin/pip install requests`, "", "", 0) @@ -866,13 +863,13 @@ func TestModulesSvc_ModulePip_Good_CustomExecutable(t *testing.T) { "executable": "/opt/venv/bin/pip", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`/opt/venv/bin/pip install requests`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`/opt/venv/bin/pip install requests`)) } -func TestModulesSvc_ModulePip_Good_RequirementsFile(t *testing.T) { +func TestModulesSvc_ModulePip_Good_RequirementsFile(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`pip3 install -r "/tmp/requirements.txt"`, "", "", 0) @@ -880,13 +877,13 @@ func TestModulesSvc_ModulePip_Good_RequirementsFile(t *testing.T) { "requirements": "/tmp/requirements.txt", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`pip3 install -r "/tmp/requirements.txt"`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`pip3 install -r "/tmp/requirements.txt"`)) } -func TestModulesSvc_ModulePip_Good_VirtualenvUsesVenvPip(t *testing.T) { +func TestModulesSvc_ModulePip_Good_VirtualenvUsesVenvPip(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`/opt/venv/bin/pip install requests`, "", "", 0) @@ -896,13 +893,13 @@ func TestModulesSvc_ModulePip_Good_VirtualenvUsesVenvPip(t *testing.T) { "virtualenv": "/opt/venv", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.True(t, mock.hasExecuted(`/opt/venv/bin/pip install requests`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertTrue(t, mock.hasExecuted(`/opt/venv/bin/pip install requests`)) } -func TestModulesSvc_ModulePip_Good_DefaultStateIsPresent(t *testing.T) { +func TestModulesSvc_ModulePip_Good_DefaultStateIsPresent(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`pip3 install django`, "", "", 0) @@ -910,12 +907,12 @@ func TestModulesSvc_ModulePip_Good_DefaultStateIsPresent(t *testing.T) { "name": "django", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`pip3 install django`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`pip3 install django`)) } -func TestModulesSvc_ModulePip_Good_InstallMultiplePackages(t *testing.T) { +func TestModulesSvc_ModulePip_Good_InstallMultiplePackages(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`pip3 install requests flask`, "", "", 0) @@ -923,12 +920,12 @@ func TestModulesSvc_ModulePip_Good_InstallMultiplePackages(t *testing.T) { "name": []any{"requests", "flask"}, }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`pip3 install requests flask`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`pip3 install requests flask`)) } -func TestModulesSvc_ModulePip_Good_CommandFailure(t *testing.T) { +func TestModulesSvc_ModulePip_Good_CommandFailure(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`pip3 install`, "", "ERROR: No matching distribution found", 1) @@ -937,12 +934,12 @@ func TestModulesSvc_ModulePip_Good_CommandFailure(t *testing.T) { "state": "present", }) - require.NoError(t, err) - assert.True(t, result.Failed) - assert.Contains(t, result.Msg, "No matching distribution found") + core.RequireNoError(t, err) + core.AssertTrue(t, result.Failed) + core.AssertContains(t, result.Msg, "No matching distribution found") } -func TestModulesSvc_ModulePip_Good_InstalledAlias(t *testing.T) { +func TestModulesSvc_ModulePip_Good_InstalledAlias(t *core.T) { // state=installed is an alias for present e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`pip3 install boto3`, "", "", 0) @@ -952,12 +949,12 @@ func TestModulesSvc_ModulePip_Good_InstalledAlias(t *testing.T) { "state": "installed", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`pip3 install boto3`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`pip3 install boto3`)) } -func TestModulesSvc_ModulePip_Good_RemovedAlias(t *testing.T) { +func TestModulesSvc_ModulePip_Good_RemovedAlias(t *core.T) { // state=removed is an alias for absent e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`pip3 uninstall -y boto3`, "", "", 0) @@ -967,14 +964,14 @@ func TestModulesSvc_ModulePip_Good_RemovedAlias(t *testing.T) { "state": "removed", }) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`pip3 uninstall -y boto3`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`pip3 uninstall -y boto3`)) } // --- Cross-module dispatch tests --- -func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchService(t *testing.T) { +func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchService(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`systemctl restart nginx`, "", "", 0) @@ -988,12 +985,12 @@ func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchService(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`systemctl restart nginx`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`systemctl restart nginx`)) } -func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchSystemd(t *testing.T) { +func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchSystemd(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`systemctl daemon-reload`, "", "", 0) mock.expectCommand(`systemctl start myapp`, "", "", 0) @@ -1009,13 +1006,13 @@ func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchSystemd(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`systemctl daemon-reload`)) - assert.True(t, mock.hasExecuted(`systemctl start myapp`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`systemctl daemon-reload`)) + core.AssertTrue(t, mock.hasExecuted(`systemctl start myapp`)) } -func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchApt(t *testing.T) { +func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchApt(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`apt-get install -y -qq nginx`, "", "", 0) @@ -1029,12 +1026,12 @@ func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchApt(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`apt-get install`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`apt-get install`)) } -func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchAptKey(t *testing.T) { +func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchAptKey(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`curl.*gpg`, "", "", 0) @@ -1048,11 +1045,11 @@ func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchAptKey(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) } -func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchAptRepository(t *testing.T) { +func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchAptRepository(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`echo`, "", "", 0) mock.expectCommand(`apt-get update`, "", "", 0) @@ -1067,11 +1064,11 @@ func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchAptRepository(t *testing. result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) } -func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchPackage(t *testing.T) { +func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchPackage(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`which apt-get`, "/usr/bin/apt-get", "", 0) mock.expectCommand(`apt-get install -y -qq git`, "", "", 0) @@ -1086,11 +1083,11 @@ func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchPackage(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) } -func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchPip(t *testing.T) { +func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchPip(t *core.T) { e, mock := newTestExecutorWithMock("host1") mock.expectCommand(`pip3 install ansible`, "", "", 0) @@ -1104,7 +1101,7 @@ func TestModulesSvc_ExecuteModuleWithMock_Good_DispatchPip(t *testing.T) { result, err := executeModuleWithMock(e, mock, "host1", task) - require.NoError(t, err) - assert.True(t, result.Changed) - assert.True(t, mock.hasExecuted(`pip3 install ansible`)) + core.RequireNoError(t, err) + core.AssertTrue(t, result.Changed) + core.AssertTrue(t, mock.hasExecuted(`pip3 install ansible`)) } diff --git a/parser.go b/parser.go index 60fca2f..53e1943 100644 --- a/parser.go +++ b/parser.go @@ -606,12 +606,16 @@ func (p *Parser) loadRoleDataFromPath(rolePath string, tasksFrom string, default defaults := make(map[string]any) if data, err := p.readFile(joinPath(rolePath, "defaults", defaultsFrom)); err == nil { - _ = yaml.Unmarshal([]byte(data), &defaults) + if err := yaml.Unmarshal([]byte(data), &defaults); err != nil { + defaults = make(map[string]any) + } } roleVars := make(map[string]any) if data, err := p.readFile(joinPath(rolePath, "vars", varsFrom)); err == nil { - _ = yaml.Unmarshal([]byte(data), &roleVars) + if err := yaml.Unmarshal([]byte(data), &roleVars); err != nil { + roleVars = make(map[string]any) + } } handlers, err := p.loadRoleHandlersFromPath(rolePath, handlersFrom) diff --git a/parser_test.go b/parser_test.go index d77a47e..05cb3db 100644 --- a/parser_test.go +++ b/parser_test.go @@ -1,17 +1,15 @@ package ansible import ( + core "dappco.re/go" "os" - "testing" coreio "dappco.re/go/io" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) // --- ParsePlaybook --- -func TestParser_ParsePlaybook_Good_SimplePlay(t *testing.T) { +func TestParser_ParsePlaybook_Good_SimplePlay(t *core.T) { dir := t.TempDir() path := joinPath(dir, "playbook.yml") @@ -25,24 +23,24 @@ func TestParser_ParsePlaybook_Good_SimplePlay(t *testing.T) { name: nginx state: present ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook(path) - require.NoError(t, err) - require.Len(t, plays, 1) - assert.Equal(t, "Configure webserver", plays[0].Name) - assert.Equal(t, "webservers", plays[0].Hosts) - assert.True(t, plays[0].Become) - require.Len(t, plays[0].Tasks, 1) - assert.Equal(t, "Install nginx", plays[0].Tasks[0].Name) - assert.Equal(t, "apt", plays[0].Tasks[0].Module) - assert.Equal(t, "nginx", plays[0].Tasks[0].Args["name"]) - assert.Equal(t, "present", plays[0].Tasks[0].Args["state"]) + core.RequireNoError(t, err) + core.AssertLen(t, plays, 1) + core.AssertEqual(t, "Configure webserver", plays[0].Name) + core.AssertEqual(t, "webservers", plays[0].Hosts) + core.AssertTrue(t, plays[0].Become) + core.AssertLen(t, plays[0].Tasks, 1) + core.AssertEqual(t, "Install nginx", plays[0].Tasks[0].Name) + core.AssertEqual(t, "apt", plays[0].Tasks[0].Module) + core.AssertEqual(t, "nginx", plays[0].Tasks[0].Args["name"]) + core.AssertEqual(t, "present", plays[0].Tasks[0].Args["state"]) } -func TestParser_ParsePlaybook_Good_MultiplePlays(t *testing.T) { +func TestParser_ParsePlaybook_Good_MultiplePlays(t *core.T) { dir := t.TempDir() path := joinPath(dir, "playbook.yml") @@ -62,21 +60,21 @@ func TestParser_ParsePlaybook_Good_MultiplePlays(t *testing.T) { debug: msg: "Goodbye" ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook(path) - require.NoError(t, err) - require.Len(t, plays, 2) - assert.Equal(t, "Play one", plays[0].Name) - assert.Equal(t, "all", plays[0].Hosts) - assert.Equal(t, "Play two", plays[1].Name) - assert.Equal(t, "localhost", plays[1].Hosts) - assert.Equal(t, "local", plays[1].Connection) + core.RequireNoError(t, err) + core.AssertLen(t, plays, 2) + core.AssertEqual(t, "Play one", plays[0].Name) + core.AssertEqual(t, "all", plays[0].Hosts) + core.AssertEqual(t, "Play two", plays[1].Name) + core.AssertEqual(t, "localhost", plays[1].Hosts) + core.AssertEqual(t, "local", plays[1].Connection) } -func TestParser_ParsePlaybook_Good_ImportPlaybook(t *testing.T) { +func TestParser_ParsePlaybook_Good_ImportPlaybook(t *core.T) { dir := t.TempDir() mainPath := joinPath(dir, "site.yml") importDir := joinPath(dir, "plays") @@ -107,24 +105,24 @@ func TestParser_ParsePlaybook_Good_ImportPlaybook(t *testing.T) { debug: msg: "imported" ` - require.NoError(t, os.MkdirAll(importDir, 0755)) - require.NoError(t, writeTestFile(mainPath, []byte(yamlMain), 0644)) - require.NoError(t, writeTestFile(importPath, []byte(yamlImported), 0644)) + core.RequireNoError(t, os.MkdirAll(importDir, 0755)) + core.RequireNoError(t, writeTestFile(mainPath, []byte(yamlMain), 0644)) + core.RequireNoError(t, writeTestFile(importPath, []byte(yamlImported), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook("site.yml") - require.NoError(t, err) - require.Len(t, plays, 3) - assert.Equal(t, "Before import", plays[0].Name) - assert.Equal(t, "Imported play", plays[1].Name) - assert.Equal(t, "After import", plays[2].Name) - assert.Equal(t, "webservers", plays[1].Hosts) - assert.Len(t, plays[1].Tasks, 1) - assert.Equal(t, "Say imported", plays[1].Tasks[0].Name) + core.RequireNoError(t, err) + core.AssertLen(t, plays, 3) + core.AssertEqual(t, "Before import", plays[0].Name) + core.AssertEqual(t, "Imported play", plays[1].Name) + core.AssertEqual(t, "After import", plays[2].Name) + core.AssertEqual(t, "webservers", plays[1].Hosts) + core.AssertLen(t, plays[1].Tasks, 1) + core.AssertEqual(t, "Say imported", plays[1].Tasks[0].Name) } -func TestParser_ParsePlaybook_Good_TemplatedImportPlaybook(t *testing.T) { +func TestParser_ParsePlaybook_Good_TemplatedImportPlaybook(t *core.T) { dir := t.TempDir() mainPath := joinPath(dir, "site.yml") importDir := joinPath(dir, "plays") @@ -141,22 +139,22 @@ func TestParser_ParsePlaybook_Good_TemplatedImportPlaybook(t *testing.T) { debug: msg: "imported" ` - require.NoError(t, os.MkdirAll(importDir, 0755)) - require.NoError(t, writeTestFile(mainPath, []byte(yamlMain), 0644)) - require.NoError(t, writeTestFile(importPath, []byte(yamlImported), 0644)) + core.RequireNoError(t, os.MkdirAll(importDir, 0755)) + core.RequireNoError(t, writeTestFile(mainPath, []byte(yamlMain), 0644)) + core.RequireNoError(t, writeTestFile(importPath, []byte(yamlImported), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook("site.yml") - require.NoError(t, err) - require.Len(t, plays, 1) - assert.Equal(t, "Imported play", plays[0].Name) - assert.Equal(t, "all", plays[0].Hosts) - require.NotNil(t, plays[0].Vars) - assert.Equal(t, dir, plays[0].Vars["playbook_dir"]) + core.RequireNoError(t, err) + core.AssertLen(t, plays, 1) + core.AssertEqual(t, "Imported play", plays[0].Name) + core.AssertEqual(t, "all", plays[0].Hosts) + core.AssertNotNil(t, plays[0].Vars) + core.AssertEqual(t, dir, plays[0].Vars["playbook_dir"]) } -func TestParser_ParsePlaybook_Good_FQCNImportPlaybook(t *testing.T) { +func TestParser_ParsePlaybook_Good_FQCNImportPlaybook(t *core.T) { dir := t.TempDir() mainPath := joinPath(dir, "site.yml") importDir := joinPath(dir, "plays") @@ -173,20 +171,20 @@ func TestParser_ParsePlaybook_Good_FQCNImportPlaybook(t *testing.T) { debug: msg: "imported" ` - require.NoError(t, os.MkdirAll(importDir, 0755)) - require.NoError(t, writeTestFile(mainPath, []byte(yamlMain), 0644)) - require.NoError(t, writeTestFile(importPath, []byte(yamlImported), 0644)) + core.RequireNoError(t, os.MkdirAll(importDir, 0755)) + core.RequireNoError(t, writeTestFile(mainPath, []byte(yamlMain), 0644)) + core.RequireNoError(t, writeTestFile(importPath, []byte(yamlImported), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook(mainPath) - require.NoError(t, err) - require.Len(t, plays, 1) - assert.Equal(t, "Imported play", plays[0].Name) - assert.Equal(t, "all", plays[0].Hosts) + core.RequireNoError(t, err) + core.AssertLen(t, plays, 1) + core.AssertEqual(t, "Imported play", plays[0].Name) + core.AssertEqual(t, "all", plays[0].Hosts) } -func TestParser_ParsePlaybook_Good_NestedImportPlaybookDirScope(t *testing.T) { +func TestParser_ParsePlaybook_Good_NestedImportPlaybookDirScope(t *core.T) { dir := t.TempDir() mainPath := joinPath(dir, "site.yml") outerDir := joinPath(dir, "plays") @@ -208,22 +206,22 @@ func TestParser_ParsePlaybook_Good_NestedImportPlaybookDirScope(t *testing.T) { debug: msg: "inner" ` - require.NoError(t, os.MkdirAll(innerDir, 0755)) - require.NoError(t, writeTestFile(mainPath, []byte(yamlMain), 0644)) - require.NoError(t, writeTestFile(outerPath, []byte(yamlOuter), 0644)) - require.NoError(t, writeTestFile(innerPath, []byte(yamlInner), 0644)) + core.RequireNoError(t, os.MkdirAll(innerDir, 0755)) + core.RequireNoError(t, writeTestFile(mainPath, []byte(yamlMain), 0644)) + core.RequireNoError(t, writeTestFile(outerPath, []byte(yamlOuter), 0644)) + core.RequireNoError(t, writeTestFile(innerPath, []byte(yamlInner), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook("site.yml") - require.NoError(t, err) - require.Len(t, plays, 1) - assert.Equal(t, "Inner play", plays[0].Name) - require.NotNil(t, plays[0].Vars) - assert.Equal(t, dir, plays[0].Vars["playbook_dir"]) + core.RequireNoError(t, err) + core.AssertLen(t, plays, 1) + core.AssertEqual(t, "Inner play", plays[0].Name) + core.AssertNotNil(t, plays[0].Vars) + core.AssertEqual(t, dir, plays[0].Vars["playbook_dir"]) } -func TestParser_ParsePlaybook_Good_WithVars(t *testing.T) { +func TestParser_ParsePlaybook_Good_WithVars(t *core.T) { dir := t.TempDir() path := joinPath(dir, "playbook.yml") @@ -238,18 +236,18 @@ func TestParser_ParsePlaybook_Good_WithVars(t *testing.T) { debug: msg: "Port is {{ http_port }}" ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook(path) - require.NoError(t, err) - require.Len(t, plays, 1) - assert.Equal(t, 8080, plays[0].Vars["http_port"]) - assert.Equal(t, "myapp", plays[0].Vars["app_name"]) + core.RequireNoError(t, err) + core.AssertLen(t, plays, 1) + core.AssertEqual(t, 8080, plays[0].Vars["http_port"]) + core.AssertEqual(t, "myapp", plays[0].Vars["app_name"]) } -func TestParser_ParsePlaybook_Good_PrePostTasks(t *testing.T) { +func TestParser_ParsePlaybook_Good_PrePostTasks(t *core.T) { dir := t.TempDir() path := joinPath(dir, "playbook.yml") @@ -269,22 +267,22 @@ func TestParser_ParsePlaybook_Good_PrePostTasks(t *testing.T) { debug: msg: "post" ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook(path) - require.NoError(t, err) - require.Len(t, plays, 1) - assert.Len(t, plays[0].PreTasks, 1) - assert.Len(t, plays[0].Tasks, 1) - assert.Len(t, plays[0].PostTasks, 1) - assert.Equal(t, "Pre task", plays[0].PreTasks[0].Name) - assert.Equal(t, "Main task", plays[0].Tasks[0].Name) - assert.Equal(t, "Post task", plays[0].PostTasks[0].Name) + core.RequireNoError(t, err) + core.AssertLen(t, plays, 1) + core.AssertLen(t, plays[0].PreTasks, 1) + core.AssertLen(t, plays[0].Tasks, 1) + core.AssertLen(t, plays[0].PostTasks, 1) + core.AssertEqual(t, "Pre task", plays[0].PreTasks[0].Name) + core.AssertEqual(t, "Main task", plays[0].Tasks[0].Name) + core.AssertEqual(t, "Post task", plays[0].PostTasks[0].Name) } -func TestParser_ParsePlaybook_Good_Handlers(t *testing.T) { +func TestParser_ParsePlaybook_Good_Handlers(t *core.T) { dir := t.TempDir() path := joinPath(dir, "playbook.yml") @@ -302,19 +300,19 @@ func TestParser_ParsePlaybook_Good_Handlers(t *testing.T) { name: nginx state: restarted ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook(path) - require.NoError(t, err) - require.Len(t, plays, 1) - assert.Len(t, plays[0].Handlers, 1) - assert.Equal(t, "restart nginx", plays[0].Handlers[0].Name) - assert.Equal(t, "service", plays[0].Handlers[0].Module) + core.RequireNoError(t, err) + core.AssertLen(t, plays, 1) + core.AssertLen(t, plays[0].Handlers, 1) + core.AssertEqual(t, "restart nginx", plays[0].Handlers[0].Name) + core.AssertEqual(t, "service", plays[0].Handlers[0].Module) } -func TestParser_ParsePlaybook_Good_ShellFreeForm(t *testing.T) { +func TestParser_ParsePlaybook_Good_ShellFreeForm(t *core.T) { dir := t.TempDir() path := joinPath(dir, "playbook.yml") @@ -327,20 +325,20 @@ func TestParser_ParsePlaybook_Good_ShellFreeForm(t *testing.T) { - name: Run raw command command: ls -la /tmp ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook(path) - require.NoError(t, err) - require.Len(t, plays[0].Tasks, 2) - assert.Equal(t, "shell", plays[0].Tasks[0].Module) - assert.Equal(t, "echo hello world", plays[0].Tasks[0].Args["_raw_params"]) - assert.Equal(t, "command", plays[0].Tasks[1].Module) - assert.Equal(t, "ls -la /tmp", plays[0].Tasks[1].Args["_raw_params"]) + core.RequireNoError(t, err) + core.AssertLen(t, plays[0].Tasks, 2) + core.AssertEqual(t, "shell", plays[0].Tasks[0].Module) + core.AssertEqual(t, "echo hello world", plays[0].Tasks[0].Args["_raw_params"]) + core.AssertEqual(t, "command", plays[0].Tasks[1].Module) + core.AssertEqual(t, "ls -la /tmp", plays[0].Tasks[1].Args["_raw_params"]) } -func TestParser_ParsePlaybook_Good_WithTags(t *testing.T) { +func TestParser_ParsePlaybook_Good_WithTags(t *core.T) { dir := t.TempDir() path := joinPath(dir, "playbook.yml") @@ -357,17 +355,17 @@ func TestParser_ParsePlaybook_Good_WithTags(t *testing.T) { - debug - always ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook(path) - require.NoError(t, err) - assert.Equal(t, []string{"setup"}, plays[0].Tags) - assert.Equal(t, []string{"debug", "always"}, plays[0].Tasks[0].Tags) + core.RequireNoError(t, err) + core.AssertEqual(t, []string{"setup"}, plays[0].Tags) + core.AssertEqual(t, []string{"debug", "always"}, plays[0].Tasks[0].Tags) } -func TestParser_ParsePlaybook_Good_BlockRescueAlways(t *testing.T) { +func TestParser_ParsePlaybook_Good_BlockRescueAlways(t *core.T) { dir := t.TempDir() path := joinPath(dir, "playbook.yml") @@ -388,22 +386,22 @@ func TestParser_ParsePlaybook_Good_BlockRescueAlways(t *testing.T) { debug: msg: "always" ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook(path) - require.NoError(t, err) + core.RequireNoError(t, err) task := plays[0].Tasks[0] - assert.Len(t, task.Block, 1) - assert.Len(t, task.Rescue, 1) - assert.Len(t, task.Always, 1) - assert.Equal(t, "Try this", task.Block[0].Name) - assert.Equal(t, "Handle error", task.Rescue[0].Name) - assert.Equal(t, "Always runs", task.Always[0].Name) + core.AssertLen(t, task.Block, 1) + core.AssertLen(t, task.Rescue, 1) + core.AssertLen(t, task.Always, 1) + core.AssertEqual(t, "Try this", task.Block[0].Name) + core.AssertEqual(t, "Handle error", task.Rescue[0].Name) + core.AssertEqual(t, "Always runs", task.Always[0].Name) } -func TestParser_ParsePlaybook_Good_WithLoop(t *testing.T) { +func TestParser_ParsePlaybook_Good_WithLoop(t *core.T) { dir := t.TempDir() path := joinPath(dir, "playbook.yml") @@ -420,20 +418,20 @@ func TestParser_ParsePlaybook_Good_WithLoop(t *testing.T) { - curl - git ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook(path) - require.NoError(t, err) + core.RequireNoError(t, err) task := plays[0].Tasks[0] - assert.Equal(t, "apt", task.Module) + core.AssertEqual(t, "apt", task.Module) items, ok := task.Loop.([]any) - require.True(t, ok) - assert.Len(t, items, 3) + core.RequireTrue(t, ok) + core.AssertLen(t, items, 3) } -func TestParser_ParsePlaybook_Good_RoleRefs(t *testing.T) { +func TestParser_ParsePlaybook_Good_RoleRefs(t *core.T) { dir := t.TempDir() path := joinPath(dir, "playbook.yml") @@ -448,20 +446,20 @@ func TestParser_ParsePlaybook_Good_RoleRefs(t *testing.T) { tags: - web ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook(path) - require.NoError(t, err) - require.Len(t, plays[0].Roles, 2) - assert.Equal(t, "common", plays[0].Roles[0].Role) - assert.Equal(t, "webserver", plays[0].Roles[1].Role) - assert.Equal(t, 80, plays[0].Roles[1].Vars["http_port"]) - assert.Equal(t, []string{"web"}, plays[0].Roles[1].Tags) + core.RequireNoError(t, err) + core.AssertLen(t, plays[0].Roles, 2) + core.AssertEqual(t, "common", plays[0].Roles[0].Role) + core.AssertEqual(t, "webserver", plays[0].Roles[1].Role) + core.AssertEqual(t, 80, plays[0].Roles[1].Vars["http_port"]) + core.AssertEqual(t, []string{"web"}, plays[0].Roles[1].Tags) } -func TestParser_ParsePlaybook_Good_FullyQualifiedModules(t *testing.T) { +func TestParser_ParsePlaybook_Good_FullyQualifiedModules(t *core.T) { dir := t.TempDir() path := joinPath(dir, "playbook.yml") @@ -476,19 +474,19 @@ func TestParser_ParsePlaybook_Good_FullyQualifiedModules(t *testing.T) { - name: Run shell ansible.builtin.shell: echo hello ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook(path) - require.NoError(t, err) - assert.Equal(t, "ansible.builtin.copy", plays[0].Tasks[0].Module) - assert.Equal(t, "/tmp/foo", plays[0].Tasks[0].Args["src"]) - assert.Equal(t, "ansible.builtin.shell", plays[0].Tasks[1].Module) - assert.Equal(t, "echo hello", plays[0].Tasks[1].Args["_raw_params"]) + core.RequireNoError(t, err) + core.AssertEqual(t, "ansible.builtin.copy", plays[0].Tasks[0].Module) + core.AssertEqual(t, "/tmp/foo", plays[0].Tasks[0].Args["src"]) + core.AssertEqual(t, "ansible.builtin.shell", plays[0].Tasks[1].Module) + core.AssertEqual(t, "echo hello", plays[0].Tasks[1].Args["_raw_params"]) } -func TestParser_ParsePlaybook_Good_RegisterAndWhen(t *testing.T) { +func TestParser_ParsePlaybook_Good_RegisterAndWhen(t *core.T) { dir := t.TempDir() path := joinPath(dir, "playbook.yml") @@ -505,51 +503,51 @@ func TestParser_ParsePlaybook_Good_RegisterAndWhen(t *testing.T) { msg: "File exists" when: nginx_conf.stat.exists ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook(path) - require.NoError(t, err) - assert.Equal(t, "nginx_conf", plays[0].Tasks[0].Register) - assert.NotNil(t, plays[0].Tasks[1].When) + core.RequireNoError(t, err) + core.AssertEqual(t, "nginx_conf", plays[0].Tasks[0].Register) + core.AssertNotNil(t, plays[0].Tasks[1].When) } -func TestParser_ParsePlaybook_Good_EmptyPlaybook(t *testing.T) { +func TestParser_ParsePlaybook_Good_EmptyPlaybook(t *core.T) { dir := t.TempDir() path := joinPath(dir, "playbook.yml") - require.NoError(t, writeTestFile(path, []byte("---\n[]"), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte("---\n[]"), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook(path) - require.NoError(t, err) - assert.Empty(t, plays) + core.RequireNoError(t, err) + core.AssertEmpty(t, plays) } -func TestParser_ParsePlaybook_Bad_InvalidYAML(t *testing.T) { +func TestParser_ParsePlaybook_Bad_InvalidYAML(t *core.T) { dir := t.TempDir() path := joinPath(dir, "bad.yml") - require.NoError(t, writeTestFile(path, []byte("{{invalid yaml}}"), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte("{{invalid yaml}}"), 0644)) p := NewParser(dir) _, err := p.ParsePlaybook(path) - assert.Error(t, err) - assert.Contains(t, err.Error(), "parse playbook") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "parse playbook") } -func TestParser_ParsePlaybook_Bad_FileNotFound(t *testing.T) { +func TestParser_ParsePlaybook_Bad_FileNotFound(t *core.T) { p := NewParser(t.TempDir()) _, err := p.ParsePlaybook("/nonexistent/playbook.yml") - assert.Error(t, err) - assert.Contains(t, err.Error(), "read playbook") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "read playbook") } -func TestParser_ParsePlaybook_Good_GatherFactsDisabled(t *testing.T) { +func TestParser_ParsePlaybook_Good_GatherFactsDisabled(t *core.T) { dir := t.TempDir() path := joinPath(dir, "playbook.yml") @@ -559,17 +557,17 @@ func TestParser_ParsePlaybook_Good_GatherFactsDisabled(t *testing.T) { gather_facts: false tasks: [] ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook(path) - require.NoError(t, err) - require.NotNil(t, plays[0].GatherFacts) - assert.False(t, *plays[0].GatherFacts) + core.RequireNoError(t, err) + core.AssertNotNil(t, plays[0].GatherFacts) + core.AssertFalse(t, *plays[0].GatherFacts) } -func TestParser_ParsePlaybook_Good_ForceHandlers(t *testing.T) { +func TestParser_ParsePlaybook_Good_ForceHandlers(t *core.T) { dir := t.TempDir() path := joinPath(dir, "playbook.yml") @@ -580,20 +578,20 @@ func TestParser_ParsePlaybook_Good_ForceHandlers(t *testing.T) { any_errors_fatal: true tasks: [] ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) plays, err := p.ParsePlaybook(path) - require.NoError(t, err) - require.Len(t, plays, 1) - assert.True(t, plays[0].ForceHandlers) - assert.True(t, plays[0].AnyErrorsFatal) + core.RequireNoError(t, err) + core.AssertLen(t, plays, 1) + core.AssertTrue(t, plays[0].ForceHandlers) + core.AssertTrue(t, plays[0].AnyErrorsFatal) } // --- ParseInventory --- -func TestParser_ParseInventory_Good_SimpleInventory(t *testing.T) { +func TestParser_ParseInventory_Good_SimpleInventory(t *core.T) { dir := t.TempDir() path := joinPath(dir, "inventory.yml") @@ -605,22 +603,22 @@ all: web2: ansible_host: 192.168.1.11 ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) inv, err := p.ParseInventory(path) - require.NoError(t, err) - require.NotNil(t, inv.All) - assert.Len(t, inv.All.Hosts, 2) - assert.Equal(t, "192.168.1.10", inv.All.Hosts["web1"].AnsibleHost) - assert.Equal(t, "192.168.1.11", inv.All.Hosts["web2"].AnsibleHost) + core.RequireNoError(t, err) + core.AssertNotNil(t, inv.All) + core.AssertLen(t, inv.All.Hosts, 2) + core.AssertEqual(t, "192.168.1.10", inv.All.Hosts["web1"].AnsibleHost) + core.AssertEqual(t, "192.168.1.11", inv.All.Hosts["web2"].AnsibleHost) } -func TestParser_ParseInventory_Good_DirectoryInventory(t *testing.T) { +func TestParser_ParseInventory_Good_DirectoryInventory(t *core.T) { dir := t.TempDir() inventoryDir := joinPath(dir, "inventory") - require.NoError(t, os.MkdirAll(inventoryDir, 0755)) + core.RequireNoError(t, os.MkdirAll(inventoryDir, 0755)) path := joinPath(inventoryDir, "hosts.yml") yaml := `--- @@ -629,18 +627,18 @@ all: web1: ansible_host: 192.168.1.10 ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) inv, err := p.ParseInventory(inventoryDir) - require.NoError(t, err) - require.NotNil(t, inv.All) - require.Contains(t, inv.All.Hosts, "web1") - assert.Equal(t, "192.168.1.10", inv.All.Hosts["web1"].AnsibleHost) + core.RequireNoError(t, err) + core.AssertNotNil(t, inv.All) + core.AssertContains(t, inv.All.Hosts, "web1") + core.AssertEqual(t, "192.168.1.10", inv.All.Hosts["web1"].AnsibleHost) } -func TestParser_ParseInventory_Good_WithGroups(t *testing.T) { +func TestParser_ParseInventory_Good_WithGroups(t *core.T) { dir := t.TempDir() path := joinPath(dir, "inventory.yml") @@ -658,19 +656,19 @@ all: db1: ansible_host: 10.0.1.1 ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) inv, err := p.ParseInventory(path) - require.NoError(t, err) - require.NotNil(t, inv.All.Children["webservers"]) - assert.Len(t, inv.All.Children["webservers"].Hosts, 2) - require.NotNil(t, inv.All.Children["databases"]) - assert.Len(t, inv.All.Children["databases"].Hosts, 1) + core.RequireNoError(t, err) + core.AssertNotNil(t, inv.All.Children["webservers"]) + core.AssertLen(t, inv.All.Children["webservers"].Hosts, 2) + core.AssertNotNil(t, inv.All.Children["databases"]) + core.AssertLen(t, inv.All.Children["databases"].Hosts, 1) } -func TestParser_ParseInventory_Good_TopLevelGroups(t *testing.T) { +func TestParser_ParseInventory_Good_TopLevelGroups(t *core.T) { dir := t.TempDir() path := joinPath(dir, "inventory.yml") @@ -688,24 +686,24 @@ databases: db1: ansible_host: 10.0.1.1 ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) inv, err := p.ParseInventory(path) - require.NoError(t, err) - require.NotNil(t, inv.All) - require.NotNil(t, inv.All.Children["webservers"]) - require.NotNil(t, inv.All.Children["databases"]) - assert.Len(t, inv.All.Children["webservers"].Hosts, 2) - assert.Len(t, inv.All.Children["databases"].Hosts, 1) - assert.Equal(t, "web", inv.All.Children["webservers"].Vars["tier"]) - assert.ElementsMatch(t, []string{"web1", "web2", "db1"}, GetHosts(inv, "all")) - assert.Equal(t, []string{"web1", "web2"}, GetHosts(inv, "webservers")) - assert.Equal(t, "web", GetHostVars(inv, "web1")["tier"]) + core.RequireNoError(t, err) + core.AssertNotNil(t, inv.All) + core.AssertNotNil(t, inv.All.Children["webservers"]) + core.AssertNotNil(t, inv.All.Children["databases"]) + core.AssertLen(t, inv.All.Children["webservers"].Hosts, 2) + core.AssertLen(t, inv.All.Children["databases"].Hosts, 1) + core.AssertEqual(t, "web", inv.All.Children["webservers"].Vars["tier"]) + core.AssertElementsMatch(t, []string{"web1", "web2", "db1"}, GetHosts(inv, "all")) + core.AssertEqual(t, []string{"web1", "web2"}, GetHosts(inv, "webservers")) + core.AssertEqual(t, "web", GetHostVars(inv, "web1")["tier"]) } -func TestParser_ParseInventory_Good_WithVars(t *testing.T) { +func TestParser_ParseInventory_Good_WithVars(t *core.T) { dir := t.TempDir() path := joinPath(dir, "inventory.yml") @@ -722,18 +720,18 @@ all: ansible_host: 10.0.0.1 ansible_port: 2222 ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) inv, err := p.ParseInventory(path) - require.NoError(t, err) - assert.Equal(t, "admin", inv.All.Vars["ansible_user"]) - assert.Equal(t, "prod", inv.All.Children["production"].Vars["env"]) - assert.Equal(t, 2222, inv.All.Children["production"].Hosts["prod1"].AnsiblePort) + core.RequireNoError(t, err) + core.AssertEqual(t, "admin", inv.All.Vars["ansible_user"]) + core.AssertEqual(t, "prod", inv.All.Children["production"].Vars["env"]) + core.AssertEqual(t, 2222, inv.All.Children["production"].Hosts["prod1"].AnsiblePort) } -func TestParser_ParseInventory_Good_HostVars(t *testing.T) { +func TestParser_ParseInventory_Good_HostVars(t *core.T) { dir := t.TempDir() path := joinPath(dir, "inventory.yml") @@ -749,45 +747,45 @@ host_vars: env: staging owner: ops ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) inv, err := p.ParseInventory(path) - require.NoError(t, err) - require.NotNil(t, inv.HostVars) - assert.Equal(t, "staging", inv.HostVars["web1"]["env"]) + core.RequireNoError(t, err) + core.AssertNotNil(t, inv.HostVars) + core.AssertEqual(t, "staging", inv.HostVars["web1"]["env"]) vars := GetHostVars(inv, "web1") - assert.Equal(t, "staging", vars["env"]) - assert.Equal(t, "ops", vars["owner"]) - assert.Equal(t, "192.168.1.10", vars["ansible_host"]) + core.AssertEqual(t, "staging", vars["env"]) + core.AssertEqual(t, "ops", vars["owner"]) + core.AssertEqual(t, "192.168.1.10", vars["ansible_host"]) } -func TestParser_ParseInventory_Bad_InvalidYAML(t *testing.T) { +func TestParser_ParseInventory_Bad_InvalidYAML(t *core.T) { dir := t.TempDir() path := joinPath(dir, "bad.yml") - require.NoError(t, writeTestFile(path, []byte("{{{bad"), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte("{{{bad"), 0644)) p := NewParser(dir) _, err := p.ParseInventory(path) - assert.Error(t, err) - assert.Contains(t, err.Error(), "parse inventory") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "parse inventory") } -func TestParser_ParseInventory_Bad_FileNotFound(t *testing.T) { +func TestParser_ParseInventory_Bad_FileNotFound(t *core.T) { p := NewParser(t.TempDir()) _, err := p.ParseInventory("/nonexistent/inventory.yml") - assert.Error(t, err) - assert.Contains(t, err.Error(), "read inventory") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "read inventory") } // --- ParseTasks --- -func TestParser_ParseTasks_Good_TaskFile(t *testing.T) { +func TestParser_ParseTasks_Good_TaskFile(t *core.T) { dir := t.TempDir() path := joinPath(dir, "tasks.yml") @@ -803,41 +801,41 @@ func TestParser_ParseTasks_Good_TaskFile(t *testing.T) { async: 30 poll: 0 ` - require.NoError(t, writeTestFile(path, []byte(yaml), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte(yaml), 0644)) p := NewParser(dir) tasks, err := p.ParseTasks(path) - require.NoError(t, err) - require.Len(t, tasks, 3) - assert.Equal(t, "shell", tasks[0].Module) - assert.Equal(t, "echo first", tasks[0].Args["_raw_params"]) - assert.Equal(t, "copy", tasks[1].Module) - assert.Equal(t, "/tmp/a", tasks[1].Args["src"]) - assert.Equal(t, "shell", tasks[2].Module) - assert.Equal(t, 30, tasks[2].Async) - assert.Equal(t, 0, tasks[2].Poll) + core.RequireNoError(t, err) + core.AssertLen(t, tasks, 3) + core.AssertEqual(t, "shell", tasks[0].Module) + core.AssertEqual(t, "echo first", tasks[0].Args["_raw_params"]) + core.AssertEqual(t, "copy", tasks[1].Module) + core.AssertEqual(t, "/tmp/a", tasks[1].Args["src"]) + core.AssertEqual(t, "shell", tasks[2].Module) + core.AssertEqual(t, 30, tasks[2].Async) + core.AssertEqual(t, 0, tasks[2].Poll) } -func TestParser_ParseTasks_Bad_InvalidYAML(t *testing.T) { +func TestParser_ParseTasks_Bad_InvalidYAML(t *core.T) { dir := t.TempDir() path := joinPath(dir, "bad.yml") - require.NoError(t, writeTestFile(path, []byte("not: [valid: tasks"), 0644)) + core.RequireNoError(t, writeTestFile(path, []byte("not: [valid: tasks"), 0644)) p := NewParser(dir) _, err := p.ParseTasks(path) - assert.Error(t, err) + core.AssertError(t, err) } -func TestParser_ParseTasksFromDir_Good_MainFallback(t *testing.T) { +func TestParser_ParseTasksFromDir_Good_MainFallback(t *core.T) { dir := t.TempDir() taskDir := joinPath(dir, "tasks") path := joinPath(taskDir, "main.yml") - require.NoError(t, os.MkdirAll(taskDir, 0o755)) - require.NoError(t, writeTestFile(path, []byte(`--- + core.RequireNoError(t, os.MkdirAll(taskDir, 0o755)) + core.RequireNoError(t, writeTestFile(path, []byte(`--- - name: From dir debug: msg: "ok" @@ -846,56 +844,56 @@ func TestParser_ParseTasksFromDir_Good_MainFallback(t *testing.T) { p := NewParser(dir) tasks, err := p.ParseTasksFromDir(taskDir) - require.NoError(t, err) - require.Len(t, tasks, 1) - assert.Equal(t, "From dir", tasks[0].Name) - assert.Equal(t, "debug", tasks[0].Module) + core.RequireNoError(t, err) + core.AssertLen(t, tasks, 1) + core.AssertEqual(t, "From dir", tasks[0].Name) + core.AssertEqual(t, "debug", tasks[0].Module) } -func TestParser_ParseVarsFiles_Good_GlobMerge(t *testing.T) { +func TestParser_ParseVarsFiles_Good_GlobMerge(t *core.T) { dir := t.TempDir() varsDir := joinPath(dir, "vars") - require.NoError(t, os.MkdirAll(varsDir, 0o755)) - require.NoError(t, writeTestFile(joinPath(varsDir, "01.yml"), []byte("a: 1\nb: one\n"), 0o644)) - require.NoError(t, writeTestFile(joinPath(varsDir, "02.yml"), []byte("b: two\nc: 3\n"), 0o644)) + core.RequireNoError(t, os.MkdirAll(varsDir, 0o755)) + core.RequireNoError(t, writeTestFile(joinPath(varsDir, "01.yml"), []byte("a: 1\nb: one\n"), 0o644)) + core.RequireNoError(t, writeTestFile(joinPath(varsDir, "02.yml"), []byte("b: two\nc: 3\n"), 0o644)) p := NewParser(dir) vars, err := p.ParseVarsFiles(joinPath(varsDir, "*.yml")) - require.NoError(t, err) - assert.Equal(t, 1, vars["a"]) - assert.Equal(t, "two", vars["b"]) - assert.Equal(t, 3, vars["c"]) + core.RequireNoError(t, err) + core.AssertEqual(t, 1, vars["a"]) + core.AssertEqual(t, "two", vars["b"]) + core.AssertEqual(t, 3, vars["c"]) } -func TestParser_ParseVarsFiles_Bad_WildcardWithNonLocalMedium(t *testing.T) { +func TestParser_ParseVarsFiles_Bad_WildcardWithNonLocalMedium(t *core.T) { medium := coreio.NewMemoryMedium() - require.NoError(t, medium.EnsureDir("vars")) - require.NoError(t, medium.Write("vars/01.yml", "a: 1\n")) + core.RequireNoError(t, medium.EnsureDir("vars")) + core.RequireNoError(t, medium.Write("vars/01.yml", "a: 1\n")) p := NewParser("") p.SetMedium(medium) _, err := p.ParseVarsFiles("vars/*.yml") - require.Error(t, err) - assert.Contains(t, err.Error(), "wildcard patterns require") + core.AssertError(t, err) + core.AssertContains(t, err.Error(), "wildcard patterns require") } -func TestParser_ParseRoles_Good_RoleDirectory(t *testing.T) { +func TestParser_ParseRoles_Good_RoleDirectory(t *core.T) { dir := t.TempDir() roleDir := joinPath(dir, "roles", "web") - require.NoError(t, os.MkdirAll(joinPath(roleDir, "tasks"), 0o755)) - require.NoError(t, os.MkdirAll(joinPath(roleDir, "defaults"), 0o755)) - require.NoError(t, os.MkdirAll(joinPath(roleDir, "vars"), 0o755)) - require.NoError(t, os.MkdirAll(joinPath(roleDir, "handlers"), 0o755)) - require.NoError(t, writeTestFile(joinPath(roleDir, "tasks", "main.yml"), []byte(`--- + core.RequireNoError(t, os.MkdirAll(joinPath(roleDir, "tasks"), 0o755)) + core.RequireNoError(t, os.MkdirAll(joinPath(roleDir, "defaults"), 0o755)) + core.RequireNoError(t, os.MkdirAll(joinPath(roleDir, "vars"), 0o755)) + core.RequireNoError(t, os.MkdirAll(joinPath(roleDir, "handlers"), 0o755)) + core.RequireNoError(t, writeTestFile(joinPath(roleDir, "tasks", "main.yml"), []byte(`--- - name: Role task debug: msg: "role" `), 0o644)) - require.NoError(t, writeTestFile(joinPath(roleDir, "defaults", "main.yml"), []byte("role_default: true\n"), 0o644)) - require.NoError(t, writeTestFile(joinPath(roleDir, "vars", "main.yml"), []byte("role_var: 42\n"), 0o644)) - require.NoError(t, writeTestFile(joinPath(roleDir, "handlers", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(roleDir, "defaults", "main.yml"), []byte("role_default: true\n"), 0o644)) + core.RequireNoError(t, writeTestFile(joinPath(roleDir, "vars", "main.yml"), []byte("role_var: 42\n"), 0o644)) + core.RequireNoError(t, writeTestFile(joinPath(roleDir, "handlers", "main.yml"), []byte(`--- - name: Role handler debug: msg: "handler" @@ -904,32 +902,32 @@ func TestParser_ParseRoles_Good_RoleDirectory(t *testing.T) { p := NewParser(dir) roles, err := p.ParseRoles("roles") - require.NoError(t, err) + core.RequireNoError(t, err) role, ok := roles["web"] - require.True(t, ok) - require.NotNil(t, role) - assert.Equal(t, "web", role.Name) - require.Len(t, role.Tasks, 1) - assert.Equal(t, "Role task", role.Tasks[0].Name) - assert.Equal(t, true, role.Defaults["role_default"]) - assert.Equal(t, 42, role.Vars["role_var"]) - require.Len(t, role.Handlers, 1) - assert.Equal(t, "Role handler", role.Handlers[0].Name) + core.RequireTrue(t, ok) + core.AssertNotNil(t, role) + core.AssertEqual(t, "web", role.Name) + core.AssertLen(t, role.Tasks, 1) + core.AssertEqual(t, "Role task", role.Tasks[0].Name) + core.AssertEqual(t, true, role.Defaults["role_default"]) + core.AssertEqual(t, 42, role.Vars["role_var"]) + core.AssertLen(t, role.Handlers, 1) + core.AssertEqual(t, "Role handler", role.Handlers[0].Name) } -func TestParser_ParseRole_Good_LoadsRoleVarsIntoParserContext(t *testing.T) { +func TestParser_ParseRole_Good_LoadsRoleVarsIntoParserContext(t *core.T) { dir := t.TempDir() - require.NoError(t, writeTestFile(joinPath(dir, "roles", "web", "tasks", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "web", "tasks", "main.yml"), []byte(`--- - name: Role task debug: msg: "{{ role_default }} {{ role_value }} {{ shared_value }}" `), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "roles", "web", "defaults", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "web", "defaults", "main.yml"), []byte(`--- role_default: default-value shared_value: default-shared `), 0644)) - require.NoError(t, writeTestFile(joinPath(dir, "roles", "web", "vars", "main.yml"), []byte(`--- + core.RequireNoError(t, writeTestFile(joinPath(dir, "roles", "web", "vars", "main.yml"), []byte(`--- role_value: vars-value shared_value: role-shared `), 0644)) @@ -939,18 +937,18 @@ shared_value: role-shared tasks, err := p.ParseRole("web", "main.yml") - require.NoError(t, err) - require.Len(t, tasks, 1) - assert.Equal(t, "debug", tasks[0].Module) - assert.Equal(t, "keep-me", p.vars["existing_value"]) - assert.Equal(t, "default-value", p.vars["role_default"]) - assert.Equal(t, "vars-value", p.vars["role_value"]) - assert.Equal(t, "role-shared", p.vars["shared_value"]) + core.RequireNoError(t, err) + core.AssertLen(t, tasks, 1) + core.AssertEqual(t, "debug", tasks[0].Module) + core.AssertEqual(t, "keep-me", p.vars["existing_value"]) + core.AssertEqual(t, "default-value", p.vars["role_default"]) + core.AssertEqual(t, "vars-value", p.vars["role_value"]) + core.AssertEqual(t, "role-shared", p.vars["shared_value"]) } // --- GetHosts --- -func TestParser_GetHosts_Good_AllPattern(t *testing.T) { +func TestParser_GetHosts_Good_AllPattern(t *core.T) { inv := &Inventory{ All: &InventoryGroup{ Hosts: map[string]*Host{ @@ -961,18 +959,18 @@ func TestParser_GetHosts_Good_AllPattern(t *testing.T) { } hosts := GetHosts(inv, "all") - assert.Len(t, hosts, 2) - assert.Contains(t, hosts, "host1") - assert.Contains(t, hosts, "host2") + core.AssertLen(t, hosts, 2) + core.AssertContains(t, hosts, "host1") + core.AssertContains(t, hosts, "host2") } -func TestParser_GetHosts_Good_LocalhostPattern(t *testing.T) { +func TestParser_GetHosts_Good_LocalhostPattern(t *core.T) { inv := &Inventory{All: &InventoryGroup{}} hosts := GetHosts(inv, "localhost") - assert.Equal(t, []string{"localhost"}, hosts) + core.AssertEqual(t, []string{"localhost"}, hosts) } -func TestParser_GetHosts_Good_GroupPattern(t *testing.T) { +func TestParser_GetHosts_Good_GroupPattern(t *core.T) { inv := &Inventory{ All: &InventoryGroup{ Children: map[string]*InventoryGroup{ @@ -992,12 +990,12 @@ func TestParser_GetHosts_Good_GroupPattern(t *testing.T) { } hosts := GetHosts(inv, "web") - assert.Len(t, hosts, 2) - assert.Contains(t, hosts, "web1") - assert.Contains(t, hosts, "web2") + core.AssertLen(t, hosts, 2) + core.AssertContains(t, hosts, "web1") + core.AssertContains(t, hosts, "web2") } -func TestParser_GetHosts_Good_SpecificHost(t *testing.T) { +func TestParser_GetHosts_Good_SpecificHost(t *core.T) { inv := &Inventory{ All: &InventoryGroup{ Children: map[string]*InventoryGroup{ @@ -1011,10 +1009,10 @@ func TestParser_GetHosts_Good_SpecificHost(t *testing.T) { } hosts := GetHosts(inv, "myhost") - assert.Equal(t, []string{"myhost"}, hosts) + core.AssertEqual(t, []string{"myhost"}, hosts) } -func TestParser_GetHosts_Good_ColonUnionIntersectionExclusion(t *testing.T) { +func TestParser_GetHosts_Good_ColonUnionIntersectionExclusion(t *core.T) { inv := &Inventory{ All: &InventoryGroup{ Children: map[string]*InventoryGroup{ @@ -1040,13 +1038,13 @@ func TestParser_GetHosts_Good_ColonUnionIntersectionExclusion(t *testing.T) { }, } - assert.Equal(t, []string{"web1", "web2", "db1"}, GetHosts(inv, "web:db")) - assert.Equal(t, []string{"web2"}, GetHosts(inv, "web:&db")) - assert.Equal(t, []string{"web1"}, GetHosts(inv, "web:!canary")) - assert.Equal(t, []string{"web1"}, GetHosts(inv, "web:db:!canary")) + core.AssertEqual(t, []string{"web1", "web2", "db1"}, GetHosts(inv, "web:db")) + core.AssertEqual(t, []string{"web2"}, GetHosts(inv, "web:&db")) + core.AssertEqual(t, []string{"web1"}, GetHosts(inv, "web:!canary")) + core.AssertEqual(t, []string{"web1"}, GetHosts(inv, "web:db:!canary")) } -func TestParser_GetHosts_Good_AllIncludesChildren(t *testing.T) { +func TestParser_GetHosts_Good_AllIncludesChildren(t *core.T) { inv := &Inventory{ All: &InventoryGroup{ Hosts: map[string]*Host{"top": {}}, @@ -1059,12 +1057,12 @@ func TestParser_GetHosts_Good_AllIncludesChildren(t *testing.T) { } hosts := GetHosts(inv, "all") - assert.Len(t, hosts, 2) - assert.Contains(t, hosts, "top") - assert.Contains(t, hosts, "child1") + core.AssertLen(t, hosts, 2) + core.AssertContains(t, hosts, "top") + core.AssertContains(t, hosts, "child1") } -func TestParser_GetHosts_Bad_NoMatch(t *testing.T) { +func TestParser_GetHosts_Bad_NoMatch(t *core.T) { inv := &Inventory{ All: &InventoryGroup{ Hosts: map[string]*Host{"host1": {}}, @@ -1072,18 +1070,18 @@ func TestParser_GetHosts_Bad_NoMatch(t *testing.T) { } hosts := GetHosts(inv, "nonexistent") - assert.Empty(t, hosts) + core.AssertEmpty(t, hosts) } -func TestParser_GetHosts_Bad_NilGroup(t *testing.T) { +func TestParser_GetHosts_Bad_NilGroup(t *core.T) { inv := &Inventory{All: nil} hosts := GetHosts(inv, "all") - assert.Empty(t, hosts) + core.AssertEmpty(t, hosts) } // --- GetHostVars --- -func TestParser_GetHostVars_Good_DirectHost(t *testing.T) { +func TestParser_GetHostVars_Good_DirectHost(t *core.T) { inv := &Inventory{ All: &InventoryGroup{ Vars: map[string]any{"global_var": "global"}, @@ -1099,14 +1097,14 @@ func TestParser_GetHostVars_Good_DirectHost(t *testing.T) { } vars := GetHostVars(inv, "myhost") - assert.Equal(t, "10.0.0.1", vars["ansible_host"]) - assert.Equal(t, 2222, vars["ansible_port"]) - assert.Equal(t, "deploy", vars["ansible_user"]) - assert.Equal(t, "secret", vars["ansible_become_password"]) - assert.Equal(t, "global", vars["global_var"]) + core.AssertEqual(t, "10.0.0.1", vars["ansible_host"]) + core.AssertEqual(t, 2222, vars["ansible_port"]) + core.AssertEqual(t, "deploy", vars["ansible_user"]) + core.AssertEqual(t, "secret", vars["ansible_become_password"]) + core.AssertEqual(t, "global", vars["global_var"]) } -func TestParser_GetHostVars_Good_InheritedGroupVars(t *testing.T) { +func TestParser_GetHostVars_Good_InheritedGroupVars(t *core.T) { inv := &Inventory{ All: &InventoryGroup{ Vars: map[string]any{"level": "all"}, @@ -1124,11 +1122,11 @@ func TestParser_GetHostVars_Good_InheritedGroupVars(t *testing.T) { } vars := GetHostVars(inv, "prod1") - assert.Equal(t, "10.0.0.1", vars["ansible_host"]) - assert.Equal(t, "prod", vars["env"]) + core.AssertEqual(t, "10.0.0.1", vars["ansible_host"]) + core.AssertEqual(t, "prod", vars["env"]) } -func TestParser_GetHostVars_Good_HostNotFound(t *testing.T) { +func TestParser_GetHostVars_Good_HostNotFound(t *core.T) { inv := &Inventory{ All: &InventoryGroup{ Hosts: map[string]*Host{"other": {}}, @@ -1136,86 +1134,89 @@ func TestParser_GetHostVars_Good_HostNotFound(t *testing.T) { } vars := GetHostVars(inv, "nonexistent") - assert.Empty(t, vars) + core.AssertEmpty(t, vars) } // --- isModule --- -func TestParser_IsModule_Good_KnownModules(t *testing.T) { - assert.True(t, isModule("shell")) - assert.True(t, isModule("command")) - assert.True(t, isModule("copy")) - assert.True(t, isModule("file")) - assert.True(t, isModule("apt")) - assert.True(t, isModule("service")) - assert.True(t, isModule("systemd")) - assert.True(t, isModule("rpm")) - assert.True(t, isModule("debug")) - assert.True(t, isModule("set_fact")) - assert.True(t, isModule("ping")) +func TestParser_IsModule_Good_KnownModules(t *core.T) { + core.AssertTrue(t, isModule("shell")) + core.AssertTrue(t, isModule("command")) + core.AssertTrue(t, isModule("copy")) + core.AssertTrue(t, isModule("file")) + core.AssertTrue(t, isModule("apt")) + core.AssertTrue(t, isModule("service")) + core.AssertTrue(t, isModule("systemd")) + core.AssertTrue(t, isModule("rpm")) + core.AssertTrue(t, isModule("debug")) + core.AssertTrue(t, isModule("set_fact")) + core.AssertTrue(t, isModule("ping")) } -func TestParser_IsModule_Good_FQCN(t *testing.T) { - assert.True(t, isModule("ansible.builtin.shell")) - assert.True(t, isModule("ansible.builtin.copy")) - assert.True(t, isModule("ansible.builtin.apt")) - assert.True(t, isModule("ansible.builtin.rpm")) +func TestParser_IsModule_Good_FQCN(t *core.T) { + core.AssertTrue(t, isModule("ansible.builtin.shell")) + core.AssertTrue(t, isModule("ansible.builtin.copy")) + core.AssertTrue(t, isModule("ansible.builtin.apt")) + core.AssertTrue(t, isModule("ansible.builtin.rpm")) } -func TestParser_IsModule_Good_DottedUnknown(t *testing.T) { +func TestParser_IsModule_Good_DottedUnknown(t *core.T) { // Any key with dots is considered a module - assert.True(t, isModule("community.general.ufw")) - assert.True(t, isModule("ansible.posix.authorized_key")) + core.AssertTrue(t, isModule("community.general.ufw")) + core.AssertTrue(t, isModule("ansible.posix.authorized_key")) + core.AssertTrue(t, isModule("custom.namespace.module")) } -func TestParser_IsModule_Bad_NotAModule(t *testing.T) { - assert.False(t, isModule("some_random_key")) - assert.False(t, isModule("foobar")) +func TestParser_IsModule_Bad_NotAModule(t *core.T) { + core.AssertFalse(t, isModule("some_random_key")) + core.AssertFalse(t, isModule("foobar")) + core.AssertFalse(t, isModule("with-hyphen")) } // --- NormalizeModule --- -func TestParser_NormalizeModule_Good(t *testing.T) { - assert.Equal(t, "ansible.builtin.shell", NormalizeModule("shell")) - assert.Equal(t, "ansible.builtin.copy", NormalizeModule("copy")) - assert.Equal(t, "ansible.builtin.apt", NormalizeModule("apt")) - assert.Equal(t, "ansible.builtin.rpm", NormalizeModule("rpm")) - assert.Equal(t, "ansible.builtin.ping", NormalizeModule("ping")) +func TestParser_NormalizeModule_Good(t *core.T) { + core.AssertEqual(t, "ansible.builtin.shell", NormalizeModule("shell")) + core.AssertEqual(t, "ansible.builtin.copy", NormalizeModule("copy")) + core.AssertEqual(t, "ansible.builtin.apt", NormalizeModule("apt")) + core.AssertEqual(t, "ansible.builtin.rpm", NormalizeModule("rpm")) + core.AssertEqual(t, "ansible.builtin.ping", NormalizeModule("ping")) } -func TestParser_NormalizeModule_Good_CommunityAliases(t *testing.T) { - assert.Equal(t, "ansible.posix.authorized_key", NormalizeModule("authorized_key")) - assert.Equal(t, "ansible.posix.authorized_key", NormalizeModule("ansible.builtin.authorized_key")) - assert.Equal(t, "community.general.ufw", NormalizeModule("ufw")) - assert.Equal(t, "community.general.ufw", NormalizeModule("ansible.builtin.ufw")) - assert.Equal(t, "community.docker.docker_compose", NormalizeModule("docker_compose")) - assert.Equal(t, "community.docker.docker_compose_v2", NormalizeModule("docker_compose_v2")) - assert.Equal(t, "community.docker.docker_compose", NormalizeModule("ansible.builtin.docker_compose")) - assert.Equal(t, "community.docker.docker_compose_v2", NormalizeModule("ansible.builtin.docker_compose_v2")) +func TestParser_NormalizeModule_Good_CommunityAliases(t *core.T) { + core.AssertEqual(t, "ansible.posix.authorized_key", NormalizeModule("authorized_key")) + core.AssertEqual(t, "ansible.posix.authorized_key", NormalizeModule("ansible.builtin.authorized_key")) + core.AssertEqual(t, "community.general.ufw", NormalizeModule("ufw")) + core.AssertEqual(t, "community.general.ufw", NormalizeModule("ansible.builtin.ufw")) + core.AssertEqual(t, "community.docker.docker_compose", NormalizeModule("docker_compose")) + core.AssertEqual(t, "community.docker.docker_compose_v2", NormalizeModule("docker_compose_v2")) + core.AssertEqual(t, "community.docker.docker_compose", NormalizeModule("ansible.builtin.docker_compose")) + core.AssertEqual(t, "community.docker.docker_compose_v2", NormalizeModule("ansible.builtin.docker_compose_v2")) } -func TestParser_NormalizeModule_Good_AlreadyFQCN(t *testing.T) { - assert.Equal(t, "ansible.builtin.shell", NormalizeModule("ansible.builtin.shell")) - assert.Equal(t, "community.general.ufw", NormalizeModule("community.general.ufw")) +func TestParser_NormalizeModule_Good_AlreadyFQCN(t *core.T) { + core.AssertEqual(t, "ansible.builtin.shell", NormalizeModule("ansible.builtin.shell")) + core.AssertEqual(t, "community.general.ufw", NormalizeModule("community.general.ufw")) + core.AssertEqual(t, "custom.namespace.module", NormalizeModule("custom.namespace.module")) } -func TestParser_IsModule_Good_AdditionalFQCN(t *testing.T) { - assert.True(t, isModule("ansible.builtin.hostname")) - assert.True(t, isModule("ansible.builtin.sysctl")) - assert.True(t, isModule("ansible.builtin.reboot")) +func TestParser_IsModule_Good_AdditionalFQCN(t *core.T) { + core.AssertTrue(t, isModule("ansible.builtin.hostname")) + core.AssertTrue(t, isModule("ansible.builtin.sysctl")) + core.AssertTrue(t, isModule("ansible.builtin.reboot")) } -func TestParser_NormalizeModule_Good_LegacyNamespace(t *testing.T) { - assert.Equal(t, "ansible.builtin.command", NormalizeModule("ansible.legacy.command")) - assert.Equal(t, "ansible.posix.authorized_key", NormalizeModule("ansible.legacy.authorized_key")) - assert.Equal(t, "community.general.ufw", NormalizeModule("ansible.legacy.ufw")) +func TestParser_NormalizeModule_Good_LegacyNamespace(t *core.T) { + core.AssertEqual(t, "ansible.builtin.command", NormalizeModule("ansible.legacy.command")) + core.AssertEqual(t, "ansible.posix.authorized_key", NormalizeModule("ansible.legacy.authorized_key")) + core.AssertEqual(t, "community.general.ufw", NormalizeModule("ansible.legacy.ufw")) } // --- NewParser --- -func TestParser_NewParser_Good(t *testing.T) { +func TestParser_NewParser_Good(t *core.T) { p := NewParser("/some/path") - assert.NotNil(t, p) - assert.Equal(t, "/some/path", p.basePath) - assert.NotNil(t, p.vars) + core.AssertNotNil(t, p) + core.AssertEqual(t, "/some/path", p.basePath) + core.AssertNotNil(t, p.vars) } diff --git a/ssh.go b/ssh.go index 6d734af..9de04c9 100644 --- a/ssh.go +++ b/ssh.go @@ -288,7 +288,9 @@ func (c *SSHClient) Run(ctx context.Context, cmd string) (stdout, stderr string, select { case <-ctx.Done(): - _ = session.Signal(ssh.SIGKILL) + if err := session.Signal(ssh.SIGKILL); err != nil && ctx.Err() == nil { + return "", "", -1, err + } return "", "", -1, ctx.Err() case err := <-done: exitCode = 0 diff --git a/ssh_test.go b/ssh_test.go index cf5fac2..a051311 100644 --- a/ssh_test.go +++ b/ssh_test.go @@ -1,13 +1,11 @@ package ansible import ( - "testing" + core "dappco.re/go" "time" - - "github.com/stretchr/testify/assert" ) -func TestSSH_NewSSHClient_Good_CustomConfig(t *testing.T) { +func TestSSH_NewSSHClient_Good_CustomConfig(t *core.T) { cfg := SSHConfig{ Host: "localhost", Port: 2222, @@ -15,38 +13,38 @@ func TestSSH_NewSSHClient_Good_CustomConfig(t *testing.T) { } client, err := NewSSHClient(cfg) - assert.NoError(t, err) - assert.NotNil(t, client) - assert.Equal(t, "localhost", client.host) - assert.Equal(t, 2222, client.port) - assert.Equal(t, "root", client.user) - assert.Equal(t, 30*time.Second, client.timeout) + core.AssertNoError(t, err) + core.AssertNotNil(t, client) + core.AssertEqual(t, "localhost", client.host) + core.AssertEqual(t, 2222, client.port) + core.AssertEqual(t, "root", client.user) + core.AssertEqual(t, 30*time.Second, client.timeout) } -func TestSSH_NewSSHClient_Good_Defaults(t *testing.T) { +func TestSSH_NewSSHClient_Good_Defaults(t *core.T) { cfg := SSHConfig{ Host: "localhost", } client, err := NewSSHClient(cfg) - assert.NoError(t, err) - assert.Equal(t, 22, client.port) - assert.Equal(t, "root", client.user) - assert.Equal(t, 30*time.Second, client.timeout) + core.AssertNoError(t, err) + core.AssertEqual(t, 22, client.port) + core.AssertEqual(t, "root", client.user) + core.AssertEqual(t, 30*time.Second, client.timeout) } -func TestSSH_SetBecome_Good_DisablesAndClearsState(t *testing.T) { +func TestSSH_SetBecome_Good_DisablesAndClearsState(t *core.T) { client := &SSHClient{} client.SetBecome(true, "admin", "secret") become, user, password := client.BecomeState() - assert.True(t, become) - assert.Equal(t, "admin", user) - assert.Equal(t, "secret", password) + core.AssertTrue(t, become) + core.AssertEqual(t, "admin", user) + core.AssertEqual(t, "secret", password) client.SetBecome(false, "", "") become, user, password = client.BecomeState() - assert.False(t, become) - assert.Empty(t, user) - assert.Empty(t, password) + core.AssertFalse(t, become) + core.AssertEmpty(t, user) + core.AssertEmpty(t, password) } diff --git a/types_test.go b/types_test.go index f189f0d..3446f4e 100644 --- a/types_test.go +++ b/types_test.go @@ -1,25 +1,23 @@ package ansible import ( - "testing" + core "dappco.re/go" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "gopkg.in/yaml.v3" ) // --- RoleRef UnmarshalYAML --- -func TestTypes_RoleRef_UnmarshalYAML_Good_StringForm(t *testing.T) { +func TestTypes_RoleRef_UnmarshalYAML_Good_StringForm(t *core.T) { input := `common` var ref RoleRef err := yaml.Unmarshal([]byte(input), &ref) - require.NoError(t, err) - assert.Equal(t, "common", ref.Role) + core.RequireNoError(t, err) + core.AssertEqual(t, "common", ref.Role) } -func TestTypes_RoleRef_UnmarshalYAML_Good_StructForm(t *testing.T) { +func TestTypes_RoleRef_UnmarshalYAML_Good_StructForm(t *core.T) { input := ` role: webserver vars: @@ -30,13 +28,13 @@ tags: var ref RoleRef err := yaml.Unmarshal([]byte(input), &ref) - require.NoError(t, err) - assert.Equal(t, "webserver", ref.Role) - assert.Equal(t, 80, ref.Vars["http_port"]) - assert.Equal(t, []string{"web"}, ref.Tags) + core.RequireNoError(t, err) + core.AssertEqual(t, "webserver", ref.Role) + core.AssertEqual(t, 80, ref.Vars["http_port"]) + core.AssertEqual(t, []string{"web"}, ref.Tags) } -func TestTypes_RoleRef_UnmarshalYAML_Good_NameField(t *testing.T) { +func TestTypes_RoleRef_UnmarshalYAML_Good_NameField(t *core.T) { // Some playbooks use "name:" instead of "role:" input := ` name: myapp @@ -45,12 +43,12 @@ tasks_from: install.yml var ref RoleRef err := yaml.Unmarshal([]byte(input), &ref) - require.NoError(t, err) - assert.Equal(t, "myapp", ref.Role) // Name is copied to Role - assert.Equal(t, "install.yml", ref.TasksFrom) + core.RequireNoError(t, err) + core.AssertEqual(t, "myapp", ref.Role) // Name is copied to Role + core.AssertEqual(t, "install.yml", ref.TasksFrom) } -func TestTypes_RoleRef_UnmarshalYAML_Good_WithWhen(t *testing.T) { +func TestTypes_RoleRef_UnmarshalYAML_Good_WithWhen(t *core.T) { input := ` role: conditional_role when: ansible_os_family == "Debian" @@ -58,12 +56,12 @@ when: ansible_os_family == "Debian" var ref RoleRef err := yaml.Unmarshal([]byte(input), &ref) - require.NoError(t, err) - assert.Equal(t, "conditional_role", ref.Role) - assert.NotNil(t, ref.When) + core.RequireNoError(t, err) + core.AssertEqual(t, "conditional_role", ref.Role) + core.AssertNotNil(t, ref.When) } -func TestTypes_RoleRef_UnmarshalYAML_Good_CustomRoleFiles(t *testing.T) { +func TestTypes_RoleRef_UnmarshalYAML_Good_CustomRoleFiles(t *core.T) { input := ` name: web tasks_from: setup.yml @@ -74,17 +72,17 @@ public: true var ref RoleRef err := yaml.Unmarshal([]byte(input), &ref) - require.NoError(t, err) - assert.Equal(t, "web", ref.Role) - assert.Equal(t, "setup.yml", ref.TasksFrom) - assert.Equal(t, "custom-defaults.yml", ref.DefaultsFrom) - assert.Equal(t, "custom-vars.yml", ref.VarsFrom) - assert.True(t, ref.Public) + core.RequireNoError(t, err) + core.AssertEqual(t, "web", ref.Role) + core.AssertEqual(t, "setup.yml", ref.TasksFrom) + core.AssertEqual(t, "custom-defaults.yml", ref.DefaultsFrom) + core.AssertEqual(t, "custom-vars.yml", ref.VarsFrom) + core.AssertTrue(t, ref.Public) } // --- Task UnmarshalYAML --- -func TestTypes_Task_UnmarshalYAML_Good_ModuleWithArgs(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_ModuleWithArgs(t *core.T) { input := ` name: Install nginx apt: @@ -94,14 +92,14 @@ apt: var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.Equal(t, "Install nginx", task.Name) - assert.Equal(t, "apt", task.Module) - assert.Equal(t, "nginx", task.Args["name"]) - assert.Equal(t, "present", task.Args["state"]) + core.RequireNoError(t, err) + core.AssertEqual(t, "Install nginx", task.Name) + core.AssertEqual(t, "apt", task.Module) + core.AssertEqual(t, "nginx", task.Args["name"]) + core.AssertEqual(t, "present", task.Args["state"]) } -func TestTypes_Task_UnmarshalYAML_Good_FreeFormModule(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_FreeFormModule(t *core.T) { input := ` name: Run command shell: echo hello world @@ -109,12 +107,12 @@ shell: echo hello world var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.Equal(t, "shell", task.Module) - assert.Equal(t, "echo hello world", task.Args["_raw_params"]) + core.RequireNoError(t, err) + core.AssertEqual(t, "shell", task.Module) + core.AssertEqual(t, "echo hello world", task.Args["_raw_params"]) } -func TestTypes_Task_UnmarshalYAML_Good_ModuleNoArgs(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_ModuleNoArgs(t *core.T) { input := ` name: Gather facts setup: @@ -122,12 +120,12 @@ setup: var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.Equal(t, "setup", task.Module) - assert.NotNil(t, task.Args) + core.RequireNoError(t, err) + core.AssertEqual(t, "setup", task.Module) + core.AssertNotNil(t, task.Args) } -func TestTypes_Task_UnmarshalYAML_Good_WithRegister(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_WithRegister(t *core.T) { input := ` name: Check file stat: @@ -137,12 +135,12 @@ register: stat_result var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.Equal(t, "stat_result", task.Register) - assert.Equal(t, "stat", task.Module) + core.RequireNoError(t, err) + core.AssertEqual(t, "stat_result", task.Register) + core.AssertEqual(t, "stat", task.Module) } -func TestTypes_Task_UnmarshalYAML_Good_WithWhen(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_WithWhen(t *core.T) { input := ` name: Conditional task debug: @@ -152,11 +150,11 @@ when: some_var is defined var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.NotNil(t, task.When) + core.RequireNoError(t, err) + core.AssertNotNil(t, task.When) } -func TestTypes_Task_UnmarshalYAML_Good_WithCheckModeAndDiff(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_WithCheckModeAndDiff(t *core.T) { input := ` name: Force a dry run shell: echo hello @@ -166,14 +164,14 @@ diff: true var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - require.NotNil(t, task.CheckMode) - require.NotNil(t, task.Diff) - assert.False(t, *task.CheckMode) - assert.True(t, *task.Diff) + core.RequireNoError(t, err) + core.AssertNotNil(t, task.CheckMode) + core.AssertNotNil(t, task.Diff) + core.AssertFalse(t, *task.CheckMode) + core.AssertTrue(t, *task.Diff) } -func TestTypes_Task_UnmarshalYAML_Good_WithLoop(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_WithLoop(t *core.T) { input := ` name: Install packages apt: @@ -186,13 +184,13 @@ loop: var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) + core.RequireNoError(t, err) items, ok := task.Loop.([]any) - require.True(t, ok) - assert.Len(t, items, 3) + core.RequireTrue(t, ok) + core.AssertLen(t, items, 3) } -func TestTypes_Task_UnmarshalYAML_Good_WithItems(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_WithItems(t *core.T) { // with_items should be converted to loop input := ` name: Old-style loop @@ -205,14 +203,14 @@ with_items: var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) + core.RequireNoError(t, err) // with_items should have been stored in Loop items, ok := task.Loop.([]any) - require.True(t, ok) - assert.Len(t, items, 2) + core.RequireTrue(t, ok) + core.AssertLen(t, items, 2) } -func TestTypes_Task_UnmarshalYAML_Good_WithDict(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_WithDict(t *core.T) { input := ` name: Old-style dict loop debug: @@ -224,23 +222,23 @@ with_dict: var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) + core.RequireNoError(t, err) items, ok := task.Loop.([]any) - require.True(t, ok) - require.Len(t, items, 2) + core.RequireTrue(t, ok) + core.AssertLen(t, items, 2) first, ok := items[0].(map[string]any) - require.True(t, ok) - assert.Equal(t, "alpha", first["key"]) - assert.Equal(t, "one", first["value"]) + core.RequireTrue(t, ok) + core.AssertEqual(t, "alpha", first["key"]) + core.AssertEqual(t, "one", first["value"]) second, ok := items[1].(map[string]any) - require.True(t, ok) - assert.Equal(t, "beta", second["key"]) - assert.Equal(t, "two", second["value"]) + core.RequireTrue(t, ok) + core.AssertEqual(t, "beta", second["key"]) + core.AssertEqual(t, "two", second["value"]) } -func TestTypes_Task_UnmarshalYAML_Good_WithIndexedItems(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_WithIndexedItems(t *core.T) { input := ` name: Indexed loop debug: @@ -252,23 +250,23 @@ with_indexed_items: var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) + core.RequireNoError(t, err) items, ok := task.Loop.([]any) - require.True(t, ok) - require.Len(t, items, 2) + core.RequireTrue(t, ok) + core.AssertLen(t, items, 2) first, ok := items[0].([]any) - require.True(t, ok) - assert.Equal(t, 0, first[0]) - assert.Equal(t, "apple", first[1]) + core.RequireTrue(t, ok) + core.AssertEqual(t, 0, first[0]) + core.AssertEqual(t, "apple", first[1]) second, ok := items[1].([]any) - require.True(t, ok) - assert.Equal(t, 1, second[0]) - assert.Equal(t, "banana", second[1]) + core.RequireTrue(t, ok) + core.AssertEqual(t, 1, second[0]) + core.AssertEqual(t, "banana", second[1]) } -func TestTypes_Task_UnmarshalYAML_Good_WithFile(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_WithFile(t *core.T) { input := ` name: Read files debug: @@ -280,14 +278,14 @@ with_file: var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - require.NotNil(t, task.WithFile) + core.RequireNoError(t, err) + core.AssertNotNil(t, task.WithFile) files, ok := task.WithFile.([]any) - require.True(t, ok) - assert.Equal(t, []any{"templates/a.txt", "templates/b.txt"}, files) + core.RequireTrue(t, ok) + core.AssertEqual(t, []any{"templates/a.txt", "templates/b.txt"}, files) } -func TestTypes_Task_UnmarshalYAML_Good_WithFileGlob(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_WithFileGlob(t *core.T) { input := ` name: Read globbed files debug: @@ -299,14 +297,14 @@ with_fileglob: var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - require.NotNil(t, task.WithFileGlob) + core.RequireNoError(t, err) + core.AssertNotNil(t, task.WithFileGlob) files, ok := task.WithFileGlob.([]any) - require.True(t, ok) - assert.Equal(t, []any{"templates/*.txt", "files/*.yml"}, files) + core.RequireTrue(t, ok) + core.AssertEqual(t, []any{"templates/*.txt", "files/*.yml"}, files) } -func TestTypes_Task_UnmarshalYAML_Good_WithSequence(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_WithSequence(t *core.T) { input := ` name: Read sequence values debug: @@ -316,14 +314,14 @@ with_sequence: "start=1 end=3 format=%02d" var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - require.NotNil(t, task.WithSequence) + core.RequireNoError(t, err) + core.AssertNotNil(t, task.WithSequence) sequence, ok := task.WithSequence.(string) - require.True(t, ok) - assert.Equal(t, "start=1 end=3 format=%02d", sequence) + core.RequireTrue(t, ok) + core.AssertEqual(t, "start=1 end=3 format=%02d", sequence) } -func TestTypes_Task_UnmarshalYAML_Good_ActionAlias(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_ActionAlias(t *core.T) { input := ` name: Legacy action action: command echo hello world @@ -331,13 +329,13 @@ action: command echo hello world var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.Equal(t, "command", task.Module) - require.NotNil(t, task.Args) - assert.Equal(t, "echo hello world", task.Args["_raw_params"]) + core.RequireNoError(t, err) + core.AssertEqual(t, "command", task.Module) + core.AssertNotNil(t, task.Args) + core.AssertEqual(t, "echo hello world", task.Args["_raw_params"]) } -func TestTypes_Task_UnmarshalYAML_Good_ActionAliasFQCN(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_ActionAliasFQCN(t *core.T) { input := ` name: Legacy action ansible.builtin.action: command echo hello world @@ -345,13 +343,13 @@ ansible.builtin.action: command echo hello world var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.Equal(t, "command", task.Module) - require.NotNil(t, task.Args) - assert.Equal(t, "echo hello world", task.Args["_raw_params"]) + core.RequireNoError(t, err) + core.AssertEqual(t, "command", task.Module) + core.AssertNotNil(t, task.Args) + core.AssertEqual(t, "echo hello world", task.Args["_raw_params"]) } -func TestTypes_Task_UnmarshalYAML_Good_ActionAliasKeyValue(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_ActionAliasKeyValue(t *core.T) { input := ` name: Legacy action with args action: module=copy src=/tmp/source dest=/tmp/dest mode=0644 @@ -359,15 +357,15 @@ action: module=copy src=/tmp/source dest=/tmp/dest mode=0644 var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.Equal(t, "copy", task.Module) - require.NotNil(t, task.Args) - assert.Equal(t, "/tmp/source", task.Args["src"]) - assert.Equal(t, "/tmp/dest", task.Args["dest"]) - assert.Equal(t, "0644", task.Args["mode"]) + core.RequireNoError(t, err) + core.AssertEqual(t, "copy", task.Module) + core.AssertNotNil(t, task.Args) + core.AssertEqual(t, "/tmp/source", task.Args["src"]) + core.AssertEqual(t, "/tmp/dest", task.Args["dest"]) + core.AssertEqual(t, "0644", task.Args["mode"]) } -func TestTypes_Task_UnmarshalYAML_Good_ActionAliasMixedArgs(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_ActionAliasMixedArgs(t *core.T) { input := ` name: Legacy action with mixed args action: command chdir=/tmp echo hello world @@ -375,14 +373,14 @@ action: command chdir=/tmp echo hello world var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.Equal(t, "command", task.Module) - require.NotNil(t, task.Args) - assert.Equal(t, "/tmp", task.Args["chdir"]) - assert.Equal(t, "echo hello world", task.Args["_raw_params"]) + core.RequireNoError(t, err) + core.AssertEqual(t, "command", task.Module) + core.AssertNotNil(t, task.Args) + core.AssertEqual(t, "/tmp", task.Args["chdir"]) + core.AssertEqual(t, "echo hello world", task.Args["_raw_params"]) } -func TestTypes_Task_UnmarshalYAML_Good_LocalAction(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_LocalAction(t *core.T) { input := ` name: Legacy local action local_action: shell echo local @@ -390,14 +388,14 @@ local_action: shell echo local var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.Equal(t, "shell", task.Module) - assert.Equal(t, "localhost", task.Delegate) - require.NotNil(t, task.Args) - assert.Equal(t, "echo local", task.Args["_raw_params"]) + core.RequireNoError(t, err) + core.AssertEqual(t, "shell", task.Module) + core.AssertEqual(t, "localhost", task.Delegate) + core.AssertNotNil(t, task.Args) + core.AssertEqual(t, "echo local", task.Args["_raw_params"]) } -func TestTypes_Task_UnmarshalYAML_Good_LocalActionFQCN(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_LocalActionFQCN(t *core.T) { input := ` name: Legacy local action ansible.legacy.local_action: shell echo local @@ -405,14 +403,14 @@ ansible.legacy.local_action: shell echo local var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.Equal(t, "shell", task.Module) - assert.Equal(t, "localhost", task.Delegate) - require.NotNil(t, task.Args) - assert.Equal(t, "echo local", task.Args["_raw_params"]) + core.RequireNoError(t, err) + core.AssertEqual(t, "shell", task.Module) + core.AssertEqual(t, "localhost", task.Delegate) + core.AssertNotNil(t, task.Args) + core.AssertEqual(t, "echo local", task.Args["_raw_params"]) } -func TestTypes_Task_UnmarshalYAML_Good_LocalActionKeyValue(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_LocalActionKeyValue(t *core.T) { input := ` name: Legacy local action with args local_action: module=command chdir=/tmp @@ -420,14 +418,14 @@ local_action: module=command chdir=/tmp var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.Equal(t, "command", task.Module) - assert.Equal(t, "localhost", task.Delegate) - require.NotNil(t, task.Args) - assert.Equal(t, "/tmp", task.Args["chdir"]) + core.RequireNoError(t, err) + core.AssertEqual(t, "command", task.Module) + core.AssertEqual(t, "localhost", task.Delegate) + core.AssertNotNil(t, task.Args) + core.AssertEqual(t, "/tmp", task.Args["chdir"]) } -func TestTypes_Task_UnmarshalYAML_Good_LocalActionMixedArgs(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_LocalActionMixedArgs(t *core.T) { input := ` name: Legacy local action with mixed args local_action: command chdir=/var/tmp echo local @@ -435,15 +433,15 @@ local_action: command chdir=/var/tmp echo local var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.Equal(t, "command", task.Module) - assert.Equal(t, "localhost", task.Delegate) - require.NotNil(t, task.Args) - assert.Equal(t, "/var/tmp", task.Args["chdir"]) - assert.Equal(t, "echo local", task.Args["_raw_params"]) + core.RequireNoError(t, err) + core.AssertEqual(t, "command", task.Module) + core.AssertEqual(t, "localhost", task.Delegate) + core.AssertNotNil(t, task.Args) + core.AssertEqual(t, "/var/tmp", task.Args["chdir"]) + core.AssertEqual(t, "echo local", task.Args["_raw_params"]) } -func TestTypes_Task_UnmarshalYAML_Good_WithNested(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_WithNested(t *core.T) { input := ` name: Nested loop values debug: @@ -457,29 +455,29 @@ with_nested: var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) + core.RequireNoError(t, err) items, ok := task.Loop.([]any) - require.True(t, ok) - require.Len(t, items, 4) + core.RequireTrue(t, ok) + core.AssertLen(t, items, 4) first, ok := items[0].([]any) - require.True(t, ok) - assert.Equal(t, []any{"red", "small"}, first) + core.RequireTrue(t, ok) + core.AssertEqual(t, []any{"red", "small"}, first) second, ok := items[1].([]any) - require.True(t, ok) - assert.Equal(t, []any{"red", "large"}, second) + core.RequireTrue(t, ok) + core.AssertEqual(t, []any{"red", "large"}, second) third, ok := items[2].([]any) - require.True(t, ok) - assert.Equal(t, []any{"blue", "small"}, third) + core.RequireTrue(t, ok) + core.AssertEqual(t, []any{"blue", "small"}, third) fourth, ok := items[3].([]any) - require.True(t, ok) - assert.Equal(t, []any{"blue", "large"}, fourth) + core.RequireTrue(t, ok) + core.AssertEqual(t, []any{"blue", "large"}, fourth) } -func TestTypes_Task_UnmarshalYAML_Good_WithTogether(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_WithTogether(t *core.T) { input := ` name: Together loop values debug: @@ -494,23 +492,23 @@ with_together: var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - require.NotNil(t, task.WithTogether) + core.RequireNoError(t, err) + core.AssertNotNil(t, task.WithTogether) items, ok := task.Loop.([]any) - require.True(t, ok) - require.Len(t, items, 2) + core.RequireTrue(t, ok) + core.AssertLen(t, items, 2) first, ok := items[0].([]any) - require.True(t, ok) - assert.Equal(t, []any{"red", "small"}, first) + core.RequireTrue(t, ok) + core.AssertEqual(t, []any{"red", "small"}, first) second, ok := items[1].([]any) - require.True(t, ok) - assert.Equal(t, []any{"blue", "large"}, second) + core.RequireTrue(t, ok) + core.AssertEqual(t, []any{"blue", "large"}, second) } -func TestTypes_Task_UnmarshalYAML_Good_WithSubelements(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_WithSubelements(t *core.T) { input := ` name: Subelement loop values debug: @@ -522,14 +520,14 @@ with_subelements: var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - require.NotNil(t, task.WithSubelements) + core.RequireNoError(t, err) + core.AssertNotNil(t, task.WithSubelements) values, ok := task.WithSubelements.([]any) - require.True(t, ok) - assert.Equal(t, []any{"users", "authorized"}, values) + core.RequireTrue(t, ok) + core.AssertEqual(t, []any{"users", "authorized"}, values) } -func TestTypes_Task_UnmarshalYAML_Good_WithNotify(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_WithNotify(t *core.T) { input := ` name: Install package apt: @@ -539,11 +537,11 @@ notify: restart nginx var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.Equal(t, "restart nginx", task.Notify) + core.RequireNoError(t, err) + core.AssertEqual(t, "restart nginx", task.Notify) } -func TestTypes_Task_UnmarshalYAML_Good_WithListen(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_WithListen(t *core.T) { input := ` name: Restart service debug: @@ -553,11 +551,11 @@ listen: reload nginx var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.Equal(t, "reload nginx", task.Listen) + core.RequireNoError(t, err) + core.AssertEqual(t, "reload nginx", task.Listen) } -func TestTypes_Task_UnmarshalYAML_Good_ShortFormSystemModules(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_ShortFormSystemModules(t *core.T) { cases := []struct { name string input string @@ -593,18 +591,18 @@ reboot: } for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { + t.Run(tc.name, func(t *core.T) { var task Task err := yaml.Unmarshal([]byte(tc.input), &task) - require.NoError(t, err) - assert.Equal(t, tc.wantModule, task.Module) - assert.NotNil(t, task.Args) + core.RequireNoError(t, err) + core.AssertEqual(t, tc.wantModule, task.Module) + core.AssertNotNil(t, task.Args) }) } } -func TestTypes_Task_UnmarshalYAML_Good_ShortFormCommunityModules(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_ShortFormCommunityModules(t *core.T) { cases := []struct { name string input string @@ -642,17 +640,17 @@ docker_compose: } for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { + t.Run(tc.name, func(t *core.T) { var task Task err := yaml.Unmarshal([]byte(tc.input), &task) - require.NoError(t, err) - assert.Equal(t, tc.wantModule, task.Module) + core.RequireNoError(t, err) + core.AssertEqual(t, tc.wantModule, task.Module) }) } } -func TestTypes_Task_UnmarshalYAML_Good_WithNotifyList(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_WithNotifyList(t *core.T) { input := ` name: Install package apt: @@ -664,13 +662,13 @@ notify: var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) + core.RequireNoError(t, err) notifyList, ok := task.Notify.([]any) - require.True(t, ok) - assert.Len(t, notifyList, 2) + core.RequireTrue(t, ok) + core.AssertLen(t, notifyList, 2) } -func TestTypes_Task_UnmarshalYAML_Good_IncludeTasks(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_IncludeTasks(t *core.T) { input := ` name: Include tasks include_tasks: other-tasks.yml @@ -678,11 +676,11 @@ include_tasks: other-tasks.yml var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.Equal(t, "other-tasks.yml", task.IncludeTasks) + core.RequireNoError(t, err) + core.AssertEqual(t, "other-tasks.yml", task.IncludeTasks) } -func TestTypes_Task_UnmarshalYAML_Good_IncludeTasksFQCN(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_IncludeTasksFQCN(t *core.T) { input := ` name: Include tasks ansible.builtin.include_tasks: other-tasks.yml @@ -690,11 +688,11 @@ ansible.builtin.include_tasks: other-tasks.yml var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.Equal(t, "other-tasks.yml", task.IncludeTasks) + core.RequireNoError(t, err) + core.AssertEqual(t, "other-tasks.yml", task.IncludeTasks) } -func TestTypes_Task_UnmarshalYAML_Good_IncludeTasksApply(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_IncludeTasksApply(t *core.T) { input := ` name: Include tasks include_tasks: other-tasks.yml @@ -710,17 +708,17 @@ apply: var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - require.NotNil(t, task.Apply) - assert.Equal(t, []string{"deploy"}, task.Apply.Tags) - require.NotNil(t, task.Apply.Become) - assert.True(t, *task.Apply.Become) - assert.Equal(t, "root", task.Apply.BecomeUser) - assert.True(t, task.Apply.DelegateFacts) - assert.Equal(t, "production", task.Apply.Environment["APP_ENV"]) + core.RequireNoError(t, err) + core.AssertNotNil(t, task.Apply) + core.AssertEqual(t, []string{"deploy"}, task.Apply.Tags) + core.AssertNotNil(t, task.Apply.Become) + core.AssertTrue(t, *task.Apply.Become) + core.AssertEqual(t, "root", task.Apply.BecomeUser) + core.AssertTrue(t, task.Apply.DelegateFacts) + core.AssertEqual(t, "production", task.Apply.Environment["APP_ENV"]) } -func TestTypes_Task_UnmarshalYAML_Good_DelegateFacts(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_DelegateFacts(t *core.T) { input := ` name: Gather delegated facts delegate_to: delegate1 @@ -730,11 +728,11 @@ setup: var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.True(t, task.DelegateFacts) + core.RequireNoError(t, err) + core.AssertTrue(t, task.DelegateFacts) } -func TestTypes_Task_UnmarshalYAML_Good_IncludeRole(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_IncludeRole(t *core.T) { input := ` name: Include role include_role: @@ -756,24 +754,24 @@ include_role: var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - require.NotNil(t, task.IncludeRole) - assert.Equal(t, "common", task.IncludeRole.Name) - assert.Equal(t, "setup.yml", task.IncludeRole.TasksFrom) - assert.Equal(t, "defaults.yml", task.IncludeRole.DefaultsFrom) - assert.Equal(t, "vars.yml", task.IncludeRole.VarsFrom) - assert.Equal(t, "handlers.yml", task.IncludeRole.HandlersFrom) - assert.True(t, task.IncludeRole.Public) - require.NotNil(t, task.IncludeRole.Apply) - assert.Equal(t, []string{"deploy"}, task.IncludeRole.Apply.Tags) - assert.Equal(t, "apply_enabled", task.IncludeRole.Apply.When) - require.NotNil(t, task.IncludeRole.Apply.Become) - assert.True(t, *task.IncludeRole.Apply.Become) - assert.Equal(t, "root", task.IncludeRole.Apply.BecomeUser) - assert.Equal(t, "production", task.IncludeRole.Apply.Environment["APP_ENV"]) + core.RequireNoError(t, err) + core.AssertNotNil(t, task.IncludeRole) + core.AssertEqual(t, "common", task.IncludeRole.Name) + core.AssertEqual(t, "setup.yml", task.IncludeRole.TasksFrom) + core.AssertEqual(t, "defaults.yml", task.IncludeRole.DefaultsFrom) + core.AssertEqual(t, "vars.yml", task.IncludeRole.VarsFrom) + core.AssertEqual(t, "handlers.yml", task.IncludeRole.HandlersFrom) + core.AssertTrue(t, task.IncludeRole.Public) + core.AssertNotNil(t, task.IncludeRole.Apply) + core.AssertEqual(t, []string{"deploy"}, task.IncludeRole.Apply.Tags) + core.AssertEqual(t, "apply_enabled", task.IncludeRole.Apply.When) + core.AssertNotNil(t, task.IncludeRole.Apply.Become) + core.AssertTrue(t, *task.IncludeRole.Apply.Become) + core.AssertEqual(t, "root", task.IncludeRole.Apply.BecomeUser) + core.AssertEqual(t, "production", task.IncludeRole.Apply.Environment["APP_ENV"]) } -func TestTypes_Task_UnmarshalYAML_Good_IncludeRoleStringForm(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_IncludeRoleStringForm(t *core.T) { input := ` name: Include role include_role: common @@ -781,12 +779,12 @@ include_role: common var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - require.NotNil(t, task.IncludeRole) - assert.Equal(t, "common", task.IncludeRole.Role) + core.RequireNoError(t, err) + core.AssertNotNil(t, task.IncludeRole) + core.AssertEqual(t, "common", task.IncludeRole.Role) } -func TestTypes_Task_UnmarshalYAML_Good_IncludeRoleFQCN(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_IncludeRoleFQCN(t *core.T) { input := ` name: Include role ansible.builtin.include_role: @@ -796,13 +794,13 @@ ansible.builtin.include_role: var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - require.NotNil(t, task.IncludeRole) - assert.Equal(t, "common", task.IncludeRole.Role) - assert.Equal(t, "setup.yml", task.IncludeRole.TasksFrom) + core.RequireNoError(t, err) + core.AssertNotNil(t, task.IncludeRole) + core.AssertEqual(t, "common", task.IncludeRole.Role) + core.AssertEqual(t, "setup.yml", task.IncludeRole.TasksFrom) } -func TestTypes_Task_UnmarshalYAML_Good_ImportRoleStringForm(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_ImportRoleStringForm(t *core.T) { input := ` name: Import role import_role: common @@ -810,12 +808,12 @@ import_role: common var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - require.NotNil(t, task.ImportRole) - assert.Equal(t, "common", task.ImportRole.Role) + core.RequireNoError(t, err) + core.AssertNotNil(t, task.ImportRole) + core.AssertEqual(t, "common", task.ImportRole.Role) } -func TestTypes_Task_UnmarshalYAML_Good_ImportRoleFQCN(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_ImportRoleFQCN(t *core.T) { input := ` name: Import role ansible.builtin.import_role: common @@ -823,12 +821,12 @@ ansible.builtin.import_role: common var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - require.NotNil(t, task.ImportRole) - assert.Equal(t, "common", task.ImportRole.Role) + core.RequireNoError(t, err) + core.AssertNotNil(t, task.ImportRole) + core.AssertEqual(t, "common", task.ImportRole.Role) } -func TestTypes_Task_UnmarshalYAML_Good_BecomeFields(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_BecomeFields(t *core.T) { input := ` name: Privileged task shell: systemctl restart nginx @@ -838,13 +836,13 @@ become_user: root var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - require.NotNil(t, task.Become) - assert.True(t, *task.Become) - assert.Equal(t, "root", task.BecomeUser) + core.RequireNoError(t, err) + core.AssertNotNil(t, task.Become) + core.AssertTrue(t, *task.Become) + core.AssertEqual(t, "root", task.BecomeUser) } -func TestTypes_Task_UnmarshalYAML_Good_IgnoreErrors(t *testing.T) { +func TestTypes_Task_UnmarshalYAML_Good_IgnoreErrors(t *core.T) { input := ` name: Might fail shell: some risky command @@ -853,13 +851,13 @@ ignore_errors: true var task Task err := yaml.Unmarshal([]byte(input), &task) - require.NoError(t, err) - assert.True(t, task.IgnoreErrors) + core.RequireNoError(t, err) + core.AssertTrue(t, task.IgnoreErrors) } // --- Inventory data structure --- -func TestTypes_Inventory_UnmarshalYAML_Good_Complex(t *testing.T) { +func TestTypes_Inventory_UnmarshalYAML_Good_Complex(t *core.T) { input := ` all: vars: @@ -887,29 +885,29 @@ all: var inv Inventory err := yaml.Unmarshal([]byte(input), &inv) - require.NoError(t, err) - require.NotNil(t, inv.All) + core.RequireNoError(t, err) + core.AssertNotNil(t, inv.All) // Check top-level vars - assert.Equal(t, "admin", inv.All.Vars["ansible_user"]) + core.AssertEqual(t, "admin", inv.All.Vars["ansible_user"]) // Check top-level hosts - require.NotNil(t, inv.All.Hosts["bastion"]) - assert.Equal(t, "1.2.3.4", inv.All.Hosts["bastion"].AnsibleHost) - assert.Equal(t, 4819, inv.All.Hosts["bastion"].AnsiblePort) + core.AssertNotNil(t, inv.All.Hosts["bastion"]) + core.AssertEqual(t, "1.2.3.4", inv.All.Hosts["bastion"].AnsibleHost) + core.AssertEqual(t, 4819, inv.All.Hosts["bastion"].AnsiblePort) // Check children - require.NotNil(t, inv.All.Children["webservers"]) - assert.Len(t, inv.All.Children["webservers"].Hosts, 2) - assert.Equal(t, 80, inv.All.Children["webservers"].Vars["http_port"]) + core.AssertNotNil(t, inv.All.Children["webservers"]) + core.AssertLen(t, inv.All.Children["webservers"].Hosts, 2) + core.AssertEqual(t, 80, inv.All.Children["webservers"].Vars["http_port"]) - require.NotNil(t, inv.All.Children["databases"]) - assert.Equal(t, "ssh", inv.All.Children["databases"].Hosts["db1"].AnsibleConnection) + core.AssertNotNil(t, inv.All.Children["databases"]) + core.AssertEqual(t, "ssh", inv.All.Children["databases"].Hosts["db1"].AnsibleConnection) } // --- Facts --- -func TestTypes_Facts_Good_Struct(t *testing.T) { +func TestTypes_Facts_Good_Struct(t *core.T) { facts := Facts{ Hostname: "web1", FQDN: "web1.example.com", @@ -925,19 +923,19 @@ func TestTypes_Facts_Good_Struct(t *testing.T) { IPv4: "10.0.0.1", } - assert.Equal(t, "web1", facts.Hostname) - assert.Equal(t, "web1.example.com", facts.FQDN) - assert.Equal(t, "ubuntu", facts.Distribution) - assert.Equal(t, "x86_64", facts.Architecture) - assert.Equal(t, "guest", facts.VirtualizationRole) - assert.Equal(t, "docker", facts.VirtualizationType) - assert.Equal(t, int64(16384), facts.Memory) - assert.Equal(t, 4, facts.CPUs) + core.AssertEqual(t, "web1", facts.Hostname) + core.AssertEqual(t, "web1.example.com", facts.FQDN) + core.AssertEqual(t, "ubuntu", facts.Distribution) + core.AssertEqual(t, "x86_64", facts.Architecture) + core.AssertEqual(t, "guest", facts.VirtualizationRole) + core.AssertEqual(t, "docker", facts.VirtualizationType) + core.AssertEqual(t, int64(16384), facts.Memory) + core.AssertEqual(t, 4, facts.CPUs) } // --- TaskResult --- -func TestTypes_TaskResult_Good_Struct(t *testing.T) { +func TestTypes_TaskResult_Good_Struct(t *core.T) { result := TaskResult{ Changed: true, Failed: false, @@ -948,13 +946,13 @@ func TestTypes_TaskResult_Good_Struct(t *testing.T) { RC: 0, } - assert.True(t, result.Changed) - assert.False(t, result.Failed) - assert.Equal(t, "task completed", result.Msg) - assert.Equal(t, 0, result.RC) + core.AssertTrue(t, result.Changed) + core.AssertFalse(t, result.Failed) + core.AssertEqual(t, "task completed", result.Msg) + core.AssertEqual(t, 0, result.RC) } -func TestTypes_TaskResult_Good_WithLoopResults(t *testing.T) { +func TestTypes_TaskResult_Good_WithLoopResults(t *core.T) { result := TaskResult{ Changed: true, Results: []TaskResult{ @@ -964,14 +962,14 @@ func TestTypes_TaskResult_Good_WithLoopResults(t *testing.T) { }, } - assert.Len(t, result.Results, 3) - assert.True(t, result.Results[0].Changed) - assert.False(t, result.Results[1].Changed) + core.AssertLen(t, result.Results, 3) + core.AssertTrue(t, result.Results[0].Changed) + core.AssertFalse(t, result.Results[1].Changed) } // --- KnownModules --- -func TestTypes_KnownModules_Good_ContainsExpected(t *testing.T) { +func TestTypes_KnownModules_Good_ContainsExpected(t *core.T) { // Verify both FQCN and short forms are present fqcnModules := []string{ "ansible.builtin.shell", @@ -996,7 +994,7 @@ func TestTypes_KnownModules_Good_ContainsExpected(t *testing.T) { "community.docker.docker_compose_v2", } for _, mod := range fqcnModules { - assert.Contains(t, KnownModules, mod, "expected FQCN module %s", mod) + core.AssertContains(t, KnownModules, mod, core.Sprintf("expected FQCN module %s", mod)) } shortModules := []string{ @@ -1004,6 +1002,6 @@ func TestTypes_KnownModules_Good_ContainsExpected(t *testing.T) { "systemd", "rpm", "debug", "set_fact", "ping", "template", "user", "group", } for _, mod := range shortModules { - assert.Contains(t, KnownModules, mod, "expected short-form module %s", mod) + core.AssertContains(t, KnownModules, mod, core.Sprintf("expected short-form module %s", mod)) } }