From 8ebfafd6ccaee163015795435ef8addb026bab38 Mon Sep 17 00:00:00 2001 From: Virgil Date: Fri, 3 Apr 2026 11:11:17 +0000 Subject: [PATCH] refactor(ansible): rename cli helpers for clarity --- cmd/ansible/ansible.go | 56 +++++++++++++++++----------------- cmd/ansible/ansible_test.go | 16 +++++----- cmd/ansible/cmd.go | 8 ++--- cmd/ansible/core_primitives.go | 2 +- docs/api-contract.md | 2 +- 5 files changed, 42 insertions(+), 42 deletions(-) diff --git a/cmd/ansible/ansible.go b/cmd/ansible/ansible.go index 2f57da8..dd47cd6 100644 --- a/cmd/ansible/ansible.go +++ b/cmd/ansible/ansible.go @@ -1,4 +1,4 @@ -package anscmd +package ansiblecmd import ( "context" @@ -15,8 +15,8 @@ import ( "gopkg.in/yaml.v3" ) -// args extracts all positional arguments from Options. -func args(opts core.Options) []string { +// positionalArgs extracts all positional arguments from Options. +func positionalArgs(opts core.Options) []string { var out []string for _, o := range opts.Items() { if o.Key == "_arg" { @@ -28,8 +28,8 @@ func args(opts core.Options) []string { return out } -// firstString returns the first non-empty string for any of the provided keys. -func firstString(opts core.Options, keys ...string) string { +// firstStringOption returns the first non-empty string for any of the provided keys. +func firstStringOption(opts core.Options, keys ...string) string { for _, key := range keys { if value := opts.String(key); value != "" { return value @@ -38,8 +38,8 @@ func firstString(opts core.Options, keys ...string) string { return "" } -// firstBool returns true when any of the provided keys is set to true. -func firstBool(opts core.Options, keys ...string) bool { +// firstBoolOption returns true when any of the provided keys is set to true. +func firstBoolOption(opts core.Options, keys ...string) bool { for _, key := range keys { if opts.Bool(key) { return true @@ -53,7 +53,7 @@ func firstBool(opts core.Options, keys ...string) bool { // `-v` tokens, so we count them from os.Args as a fallback. func verbosityLevel(opts core.Options, rawArgs []string) int { level := opts.Int("verbose") - if firstBool(opts, "v") && level < 1 { + if firstBoolOption(opts, "v") && level < 1 { level = 1 } @@ -182,18 +182,18 @@ func parseKeyValueExtraVars(value string) map[string]any { return vars } -// testKeyFile resolves the SSH key flag used by the ansible test subcommand. -func testKeyFile(opts core.Options) string { +// resolveTestSSHKeyFile resolves the SSH key flag used by the ansible test subcommand. +func resolveTestSSHKeyFile(opts core.Options) string { if key := opts.String("key"); key != "" { return key } return opts.String("i") } -func runAnsible(opts core.Options) core.Result { - positional := args(opts) +func runPlaybookCommand(opts core.Options) core.Result { + positional := positionalArgs(opts) if len(positional) < 1 { - return core.Result{Value: coreerr.E("runAnsible", "usage: ansible ", nil)} + return core.Result{Value: coreerr.E("runPlaybookCommand", "usage: ansible ", nil)} } playbookPath := positional[0] @@ -203,7 +203,7 @@ func runAnsible(opts core.Options) core.Result { } if !coreio.Local.Exists(playbookPath) { - return core.Result{Value: coreerr.E("runAnsible", sprintf("playbook not found: %s", playbookPath), nil)} + return core.Result{Value: coreerr.E("runPlaybookCommand", sprintf("playbook not found: %s", playbookPath), nil)} } // Create executor @@ -212,12 +212,12 @@ func runAnsible(opts core.Options) core.Result { defer executor.Close() // Set options - executor.Limit = firstString(opts, "limit", "l") + executor.Limit = firstStringOption(opts, "limit", "l") executor.CheckMode = opts.Bool("check") executor.Diff = opts.Bool("diff") executor.Verbose = verbosityLevel(opts, os.Args[1:]) - if tags := firstString(opts, "tags", "t"); tags != "" { + if tags := firstStringOption(opts, "tags", "t"); tags != "" { executor.Tags = split(tags, ",") } if skipTags := opts.String("skip-tags"); skipTags != "" { @@ -227,20 +227,20 @@ func runAnsible(opts core.Options) core.Result { // Parse extra vars vars, err := extraVars(opts) if err != nil { - return core.Result{Value: coreerr.E("runAnsible", "parse extra vars", err)} + return core.Result{Value: coreerr.E("runPlaybookCommand", "parse extra vars", err)} } for key, value := range vars { executor.SetVar(key, value) } // Load inventory - if invPath := firstString(opts, "inventory", "i"); invPath != "" { + if invPath := firstStringOption(opts, "inventory", "i"); invPath != "" { if !pathIsAbs(invPath) { invPath = absPath(invPath) } if !coreio.Local.Exists(invPath) { - return core.Result{Value: coreerr.E("runAnsible", sprintf("inventory not found: %s", invPath), nil)} + return core.Result{Value: coreerr.E("runPlaybookCommand", sprintf("inventory not found: %s", invPath), nil)} } if coreio.Local.IsDir(invPath) { @@ -254,7 +254,7 @@ func runAnsible(opts core.Options) core.Result { } if err := executor.SetInventory(invPath); err != nil { - return core.Result{Value: coreerr.E("runAnsible", "load inventory", err)} + return core.Result{Value: coreerr.E("runPlaybookCommand", "load inventory", err)} } } @@ -330,7 +330,7 @@ func runAnsible(opts core.Options) core.Result { print("Running playbook: %s", playbookPath) if err := executor.Run(ctx, playbookPath); err != nil { - return core.Result{Value: coreerr.E("runAnsible", "playbook failed", err)} + return core.Result{Value: coreerr.E("runPlaybookCommand", "playbook failed", err)} } print("") @@ -339,10 +339,10 @@ func runAnsible(opts core.Options) core.Result { return core.Result{OK: true} } -func runAnsibleTest(opts core.Options) core.Result { - positional := args(opts) +func runSSHTestCommand(opts core.Options) core.Result { + positional := positionalArgs(opts) if len(positional) < 1 { - return core.Result{Value: coreerr.E("runAnsibleTest", "usage: ansible test ", nil)} + return core.Result{Value: coreerr.E("runSSHTestCommand", "usage: ansible test ", nil)} } host := positional[0] @@ -351,15 +351,15 @@ func runAnsibleTest(opts core.Options) core.Result { cfg := ansible.SSHConfig{ Host: host, Port: opts.Int("port"), - User: firstString(opts, "user", "u"), + User: firstStringOption(opts, "user", "u"), Password: opts.String("password"), - KeyFile: testKeyFile(opts), + KeyFile: resolveTestSSHKeyFile(opts), Timeout: 30 * time.Second, } client, err := ansible.NewSSHClient(cfg) if err != nil { - return core.Result{Value: coreerr.E("runAnsibleTest", "create client", err)} + return core.Result{Value: coreerr.E("runSSHTestCommand", "create client", err)} } defer func() { _ = client.Close() }() @@ -369,7 +369,7 @@ func runAnsibleTest(opts core.Options) core.Result { // Test connection start := time.Now() if err := client.Connect(ctx); err != nil { - return core.Result{Value: coreerr.E("runAnsibleTest", "connect failed", err)} + return core.Result{Value: coreerr.E("runSSHTestCommand", "connect failed", err)} } connectTime := time.Since(start) diff --git a/cmd/ansible/ansible_test.go b/cmd/ansible/ansible_test.go index 757ccbf..4cf4d19 100644 --- a/cmd/ansible/ansible_test.go +++ b/cmd/ansible/ansible_test.go @@ -1,4 +1,4 @@ -package anscmd +package ansiblecmd import ( "os" @@ -110,7 +110,7 @@ func TestFirstString_Good_PrefersFirstNonEmptyKey(t *testing.T) { core.Option{Key: "i", Value: "/tmp/inventory.yml"}, ) - assert.Equal(t, "/tmp/inventory.yml", firstString(opts, "inventory", "i")) + assert.Equal(t, "/tmp/inventory.yml", firstStringOption(opts, "inventory", "i")) } func TestFirstBool_Good_UsesAlias(t *testing.T) { @@ -118,7 +118,7 @@ func TestFirstBool_Good_UsesAlias(t *testing.T) { core.Option{Key: "v", Value: true}, ) - assert.True(t, firstBool(opts, "verbose", "v")) + assert.True(t, firstBoolOption(opts, "verbose", "v")) } func TestVerbosityLevel_Good_CountsStackedShortFlags(t *testing.T) { @@ -145,7 +145,7 @@ func TestTestKeyFile_Good_PrefersExplicitKey(t *testing.T) { core.Option{Key: "i", Value: "/tmp/ignored"}, ) - assert.Equal(t, "/tmp/id_ed25519", testKeyFile(opts)) + assert.Equal(t, "/tmp/id_ed25519", resolveTestSSHKeyFile(opts)) } func TestTestKeyFile_Good_FallsBackToShortAlias(t *testing.T) { @@ -153,7 +153,7 @@ func TestTestKeyFile_Good_FallsBackToShortAlias(t *testing.T) { core.Option{Key: "i", Value: "/tmp/id_ed25519"}, ) - assert.Equal(t, "/tmp/id_ed25519", testKeyFile(opts)) + assert.Equal(t, "/tmp/id_ed25519", resolveTestSSHKeyFile(opts)) } func TestFirstString_Good_ResolvesShortUserAlias(t *testing.T) { @@ -161,7 +161,7 @@ func TestFirstString_Good_ResolvesShortUserAlias(t *testing.T) { core.Option{Key: "u", Value: "deploy"}, ) - cfgUser := firstString(opts, "user", "u") + cfgUser := firstStringOption(opts, "user", "u") assert.Equal(t, "deploy", cfgUser) } @@ -245,7 +245,7 @@ func TestRegister_Good_ExposesExpectedFlags(t *testing.T) { } func TestRunAnsible_Bad_MissingPlaybook(t *testing.T) { - result := runAnsible(core.NewOptions()) + result := runPlaybookCommand(core.NewOptions()) require.False(t, result.OK) err, ok := result.Value.(error) @@ -254,7 +254,7 @@ func TestRunAnsible_Bad_MissingPlaybook(t *testing.T) { } func TestRunAnsibleTest_Bad_MissingHost(t *testing.T) { - result := runAnsibleTest(core.NewOptions()) + result := runSSHTestCommand(core.NewOptions()) require.False(t, result.OK) err, ok := result.Value.(error) diff --git a/cmd/ansible/cmd.go b/cmd/ansible/cmd.go index 04a25a1..0c057fe 100644 --- a/cmd/ansible/cmd.go +++ b/cmd/ansible/cmd.go @@ -1,10 +1,10 @@ -package anscmd +package ansiblecmd import ( "dappco.re/go/core" ) -// Register registers the 'ansible' command and all subcommands on the given Core instance. +// Register registers the `ansible` command and its `ansible/test` subcommand. // // Example: // @@ -13,7 +13,7 @@ import ( func Register(c *core.Core) { c.Command("ansible", core.Command{ Description: "Run Ansible playbooks natively (no Python required)", - Action: runAnsible, + Action: runPlaybookCommand, Flags: core.NewOptions( core.Option{Key: "inventory", Value: ""}, core.Option{Key: "i", Value: ""}, @@ -33,7 +33,7 @@ func Register(c *core.Core) { c.Command("ansible/test", core.Command{ Description: "Test SSH connectivity to a host", - Action: runAnsibleTest, + Action: runSSHTestCommand, Flags: core.NewOptions( core.Option{Key: "user", Value: "root"}, core.Option{Key: "u", Value: "root"}, diff --git a/cmd/ansible/core_primitives.go b/cmd/ansible/core_primitives.go index 683146d..f9962c9 100644 --- a/cmd/ansible/core_primitives.go +++ b/cmd/ansible/core_primitives.go @@ -1,4 +1,4 @@ -package anscmd +package ansiblecmd import ( "unicode" diff --git a/docs/api-contract.md b/docs/api-contract.md index c8f0b7f..ebe3dc1 100644 --- a/docs/api-contract.md +++ b/docs/api-contract.md @@ -69,7 +69,7 @@ Function and method coverage percentages below come from `go test -coverprofile= | `(*SSHClient).Stat` | `func (c *SSHClient) Stat(ctx context.Context, path string) (map[string]any, error)` | Returns a minimal remote stat map describing existence and directory state. | `0.0%`; no automated tests found. | | `(*SSHClient).SetBecome` | `func (c *SSHClient) SetBecome(become bool, user, password string)` | Updates the privilege-escalation settings stored on the client. | `100.0%`; covered by `modules_infra_test.go: TestBecome_Infra_Good_*`. | -## Package `anscmd`: CLI API +## Package `ansiblecmd`: CLI API | Name | Signature | Description | Test coverage | | --- | --- | --- | --- |