From 9f86b5cb95463af1b3663fcaf7923ccb984a21bb Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 00:27:36 +0000 Subject: [PATCH] feat(ansible): add short flag aliases --- cmd/ansible/ansible.go | 33 +++++++++++++++++++++++++----- cmd/ansible/ansible_test.go | 40 +++++++++++++++++++++++++++++++++++++ cmd/ansible/cmd.go | 6 ++++++ 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/cmd/ansible/ansible.go b/cmd/ansible/ansible.go index bac2d57..c7a9c6e 100644 --- a/cmd/ansible/ansible.go +++ b/cmd/ansible/ansible.go @@ -23,12 +23,32 @@ 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 { + for _, key := range keys { + if value := opts.String(key); value != "" { + return value + } + } + return "" +} + +// firstBool returns true when any of the provided keys is set to true. +func firstBool(opts core.Options, keys ...string) bool { + for _, key := range keys { + if opts.Bool(key) { + return true + } + } + return false +} + // extraVars collects all repeated extra-vars values from Options. func extraVars(opts core.Options) map[string]string { vars := make(map[string]string) for _, o := range opts.Items() { - if o.Key != "extra-vars" { + if o.Key != "extra-vars" && o.Key != "e" { continue } @@ -96,12 +116,15 @@ func runAnsible(opts core.Options) core.Result { defer executor.Close() // Set options - executor.Limit = opts.String("limit") + executor.Limit = firstString(opts, "limit", "l") executor.CheckMode = opts.Bool("check") executor.Diff = opts.Bool("diff") executor.Verbose = opts.Int("verbose") + if firstBool(opts, "v") && executor.Verbose < 1 { + executor.Verbose = 1 + } - if tags := opts.String("tags"); tags != "" { + if tags := firstString(opts, "tags", "t"); tags != "" { executor.Tags = split(tags, ",") } if skipTags := opts.String("skip-tags"); skipTags != "" { @@ -114,7 +137,7 @@ func runAnsible(opts core.Options) core.Result { } // Load inventory - if invPath := opts.String("inventory"); invPath != "" { + if invPath := firstString(opts, "inventory", "i"); invPath != "" { if !pathIsAbs(invPath) { invPath = absPath(invPath) } @@ -231,7 +254,7 @@ func runAnsibleTest(opts core.Options) core.Result { cfg := ansible.SSHConfig{ Host: host, Port: opts.Int("port"), - User: opts.String("user"), + User: firstString(opts, "user", "u"), Password: opts.String("password"), KeyFile: testKeyFile(opts), Timeout: 30 * time.Second, diff --git a/cmd/ansible/ansible_test.go b/cmd/ansible/ansible_test.go index 4aeb177..4fa3e1c 100644 --- a/cmd/ansible/ansible_test.go +++ b/cmd/ansible/ansible_test.go @@ -24,6 +24,19 @@ func TestExtraVars_Good_RepeatableAndCommaSeparated(t *testing.T) { }, vars) } +func TestExtraVars_Good_UsesShortAlias(t *testing.T) { + opts := core.NewOptions( + core.Option{Key: "e", Value: "version=1.2.3,env=prod"}, + ) + + vars := extraVars(opts) + + assert.Equal(t, map[string]string{ + "version": "1.2.3", + "env": "prod", + }, vars) +} + func TestExtraVars_Good_IgnoresMalformedPairs(t *testing.T) { opts := core.NewOptions( core.Option{Key: "extra-vars", Value: "missing_equals,keep=this"}, @@ -38,6 +51,23 @@ func TestExtraVars_Good_IgnoresMalformedPairs(t *testing.T) { }, vars) } +func TestFirstString_Good_PrefersFirstNonEmptyKey(t *testing.T) { + opts := core.NewOptions( + core.Option{Key: "inventory", Value: ""}, + core.Option{Key: "i", Value: "/tmp/inventory.yml"}, + ) + + assert.Equal(t, "/tmp/inventory.yml", firstString(opts, "inventory", "i")) +} + +func TestFirstBool_Good_UsesAlias(t *testing.T) { + opts := core.NewOptions( + core.Option{Key: "v", Value: true}, + ) + + assert.True(t, firstBool(opts, "verbose", "v")) +} + func TestTestKeyFile_Good_PrefersExplicitKey(t *testing.T) { opts := core.NewOptions( core.Option{Key: "key", Value: "/tmp/id_ed25519"}, @@ -54,3 +84,13 @@ func TestTestKeyFile_Good_FallsBackToShortAlias(t *testing.T) { assert.Equal(t, "/tmp/id_ed25519", testKeyFile(opts)) } + +func TestFirstString_Good_ResolvesShortUserAlias(t *testing.T) { + opts := core.NewOptions( + core.Option{Key: "u", Value: "deploy"}, + ) + + cfgUser := firstString(opts, "user", "u") + + assert.Equal(t, "deploy", cfgUser) +} diff --git a/cmd/ansible/cmd.go b/cmd/ansible/cmd.go index 8dd1b4c..04a25a1 100644 --- a/cmd/ansible/cmd.go +++ b/cmd/ansible/cmd.go @@ -16,11 +16,16 @@ func Register(c *core.Core) { Action: runAnsible, Flags: core.NewOptions( core.Option{Key: "inventory", Value: ""}, + core.Option{Key: "i", Value: ""}, core.Option{Key: "limit", Value: ""}, + core.Option{Key: "l", Value: ""}, core.Option{Key: "tags", Value: ""}, + core.Option{Key: "t", Value: ""}, core.Option{Key: "skip-tags", Value: ""}, core.Option{Key: "extra-vars", Value: ""}, + core.Option{Key: "e", Value: ""}, core.Option{Key: "verbose", Value: 0}, + core.Option{Key: "v", Value: false}, core.Option{Key: "check", Value: false}, core.Option{Key: "diff", Value: false}, ), @@ -31,6 +36,7 @@ func Register(c *core.Core) { Action: runAnsibleTest, Flags: core.NewOptions( core.Option{Key: "user", Value: "root"}, + core.Option{Key: "u", Value: "root"}, core.Option{Key: "password", Value: ""}, core.Option{Key: "key", Value: ""}, core.Option{Key: "i", Value: ""},