refactor(ansible): rename cli helpers for clarity
Some checks are pending
CI / test (push) Waiting to run
CI / auto-fix (push) Waiting to run
CI / auto-merge (push) Waiting to run

This commit is contained in:
Virgil 2026-04-03 11:11:17 +00:00
parent 103b5ed255
commit 8ebfafd6cc
5 changed files with 42 additions and 42 deletions

View file

@ -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 <playbook>", nil)}
return core.Result{Value: coreerr.E("runPlaybookCommand", "usage: ansible <playbook>", 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 <host>", nil)}
return core.Result{Value: coreerr.E("runSSHTestCommand", "usage: ansible test <host>", 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)

View file

@ -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)

View file

@ -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"},

View file

@ -1,4 +1,4 @@
package anscmd
package ansiblecmd
import (
"unicode"

View file

@ -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 |
| --- | --- | --- | --- |