Skip to content

Commit

Permalink
Add option to override the config namespace for a command.
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewsomething committed Dec 7, 2023
1 parent 4ea0a63 commit 544b773
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 18 deletions.
33 changes: 20 additions & 13 deletions commands/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ type Command struct {
fmtCols []string

childCommands []*Command

// overrideNS specifies a namespace to use in config.
// Set using the overrideCmdNS cmdOption when calling CmdBuilder
overrideNS string
}

// AddCommand adds child commands and adds child commands for cobra as well.
Expand Down Expand Up @@ -72,19 +76,6 @@ func cmdBuilderWithInit(parent *Command, cr CmdRunner, cliText, shortdesc string
Use: cliText,
Short: shortdesc,
Long: longdesc,
Run: func(cmd *cobra.Command, args []string) {
c, err := NewCmdConfig(
cmdNS(cmd),
&doctl.LiveConfig{},
out,
args,
initCmd,
)
checkErr(err)

err = cr(c)
checkErr(err)
},
}

c := &Command{Command: cc}
Expand All @@ -97,6 +88,22 @@ func cmdBuilderWithInit(parent *Command, cr CmdRunner, cliText, shortdesc string
co(c)
}

// This must be defined after the options have been applied
// so that changes made by the options are accessible here.
c.Command.Run = func(cmd *cobra.Command, args []string) {
c, err := NewCmdConfig(
cmdNS(c),
&doctl.LiveConfig{},
out,
args,
initCmd,
)
checkErr(err)

err = cr(c)
checkErr(err)
}

if cols := c.fmtCols; cols != nil {
formatHelp := fmt.Sprintf("Columns for output in a comma-separated list. Possible values: `%s`.",
strings.Join(cols, "`"+", "+"`"))
Expand Down
10 changes: 10 additions & 0 deletions commands/command_option.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,13 @@ func hiddenCmd() cmdOption {
c.Hidden = true
}
}

// overrideCmdNS specifies a namespace to use in config overriding the
// normal usage of the parent command's name. This is useful in cases
// where deeply nested subcommands have conflicting names. See uptime_alerts.go
// for example usage.
func overrideCmdNS(ns string) cmdOption {
return func(c *Command) {
c.overrideNS = ns
}
}
15 changes: 12 additions & 3 deletions commands/doit.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,16 +326,25 @@ func AddDurationFlag(cmd *Command, name, shorthand string, def time.Duration, de

func flagName(cmd *Command, name string) string {
if cmd.Parent() != nil {
return fmt.Sprintf("%s.%s.%s", cmd.Parent().Name(), cmd.Name(), name)
p := cmd.Parent().Name()
if cmd.overrideNS != "" {
p = cmd.overrideNS
}
return fmt.Sprintf("%s.%s.%s", p, cmd.Name(), name)
}

return fmt.Sprintf("%s.%s", cmd.Name(), name)
}

func cmdNS(cmd *cobra.Command) string {
func cmdNS(cmd *Command) string {
if cmd.Parent() != nil {
if cmd.overrideNS != "" {
return fmt.Sprintf("%s.%s", cmd.overrideNS, cmd.Name())
}

return fmt.Sprintf("%s.%s", cmd.Parent().Name(), cmd.Name())
}
return fmt.Sprintf("%s", cmd.Name())
return cmd.Name()
}

func isTerminal(f *os.File) bool {
Expand Down
81 changes: 81 additions & 0 deletions commands/doit_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package commands

import (
"testing"

"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
)

func TestFlagName(t *testing.T) {
var flag = "thing"
testFn := func(c *CmdConfig) error {
return nil
}
parent := &Command{
Command: &cobra.Command{
Use: "doit",
Short: "Do the thing",
},
}

tests := []struct {
name string
cmd *Command
expected string
}{
{
name: "default",
cmd: CmdBuilder(parent, testFn, "run", "Run it", "", Writer),
expected: "doit.run.thing",
},
{
name: "overrideCmdNS",
cmd: CmdBuilder(parent, testFn, "run", "Run it", "", Writer, overrideCmdNS("doctl")),
expected: "doctl.run.thing",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
AddStringFlag(tt.cmd, flag, "", "", "the thing")

assert.Equal(t, tt.expected, flagName(tt.cmd, flag))
})
}
}

func TestCmdNS(t *testing.T) {
testFn := func(c *CmdConfig) error {
return nil
}
parent := &Command{
Command: &cobra.Command{
Use: "doit",
Short: "Do the thing",
},
}

tests := []struct {
name string
cmd *Command
expected string
}{
{
name: "default",
cmd: CmdBuilder(parent, testFn, "run", "Run it", "", Writer),
expected: "doit.run",
},
{
name: "overrideCmdNS",
cmd: CmdBuilder(parent, testFn, "run", "Run it", "", Writer, overrideCmdNS("doctl")),
expected: "doctl.run",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.expected, cmdNS(tt.cmd))
})
}
}
1 change: 1 addition & 0 deletions commands/monitoring.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ func RunCmdAlertPolicyCreate(c *CmdConfig) error {
if err != nil {
return err
}

err = validateAlertPolicyType(alertType)
if err != nil {
return err
Expand Down
5 changes: 3 additions & 2 deletions commands/uptime_alerts.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ and alert you when they're slow, unavailable, or SSL certificates are expiring.`
cmdUptimeAlertsCreate := CmdBuilder(cmd, RunUptimeAlertsCreate, "create <uptime-check-id>", "Create an uptime alert", `Use this command to create an uptime alert on your account.
You can use flags to specify the uptime alert, type, threshold, comparison, notifications, and period.`, Writer,
aliasOpt("c"), displayerType(&displayers.UptimeAlert{}))
aliasOpt("c"), displayerType(&displayers.UptimeAlert{}), overrideCmdNS("uptime-alert"))

AddStringFlag(cmdUptimeAlertsCreate, doctl.ArgUptimeAlertName, "", "", "Uptime alert name", requiredOpt())
AddStringFlag(cmdUptimeAlertsCreate, doctl.ArgUptimeAlertType, "", "", "Uptime alert type, must be one of latency, down, down_global or ssl_expiry", requiredOpt())
AddIntFlag(cmdUptimeAlertsCreate, doctl.ArgUptimeAlertThreshold, "", 0, "Uptime alert threshold at which the alert will enter a trigger state. The specific threshold is dependent on the alert type.")
Expand All @@ -61,7 +62,7 @@ You can use flags to specify the uptime alert, type, threshold, comparison, noti
cmdUptimeAlertsUpdate := CmdBuilder(cmd, RunUptimeAlertsUpdate, "update <uptime-check-id> <uptime-alert-id>", "Update an uptime alert", `Use this command to update an uptime alert on your account.
You can use flags to specify the uptime alert, type, threshold, comparison, notifications, and period.`, Writer,
aliasOpt("u"), displayerType(&displayers.UptimeAlert{}))
aliasOpt("u"), displayerType(&displayers.UptimeAlert{}), overrideCmdNS("uptime-alert"))
AddStringFlag(cmdUptimeAlertsUpdate, doctl.ArgUptimeAlertName, "", "", "Uptime alert name", requiredOpt())
AddStringFlag(cmdUptimeAlertsUpdate, doctl.ArgUptimeAlertType, "", "", "Uptime alert type, must be one of latency, down, down_global or ssl_expiry", requiredOpt())
AddIntFlag(cmdUptimeAlertsUpdate, doctl.ArgUptimeAlertThreshold, "", 0, "Uptime alert threshold at which the alert will enter a trigger state. The specific threshold is dependent on the alert type.")
Expand Down

0 comments on commit 544b773

Please sign in to comment.