diff --git a/.changelog/11364.txt b/.changelog/11364.txt new file mode 100644 index 000000000..a394fc4e0 --- /dev/null +++ b/.changelog/11364.txt @@ -0,0 +1,3 @@ +```release-note:improvement +cli: Allow specifying namesapce and region in the `nomad ui` command +``` diff --git a/command/ui.go b/command/ui.go index c74f9b0fb..b3a0f1310 100644 --- a/command/ui.go +++ b/command/ui.go @@ -29,7 +29,7 @@ object. Supported identifiers are jobs, allocations and nodes. General Options: - ` + generalOptionsUsage(usageOptsDefault|usageOptsNoNamespace) + ` + ` + generalOptionsUsage(usageOptsDefault) + ` UI Options @@ -116,6 +116,17 @@ func (c *UiCommand) Run(args []string) int { return 1 } + // Set query params if necessary + qp := url.Query() + if ns := c.clientConfig().Namespace; ns != "" { + qp.Add("namespace", ns) + } + if region := c.clientConfig().Region; region != "" { + qp.Add("region", region) + } + url.RawQuery = qp.Encode() + + // Set one-time secret var ottSecret string if authenticate { ott, _, err := client.ACLTokens().UpsertOneTimeToken(nil) @@ -185,7 +196,9 @@ func (c *UiCommand) Run(args []string) int { var output string if authenticate && ottSecret != "" { output = fmt.Sprintf("Opening URL %q with one-time token", url.String()) - url.RawQuery = fmt.Sprintf("ott=%s", ottSecret) + qp := url.Query() + qp.Add("ott", ottSecret) + url.RawQuery = qp.Encode() } else { output = fmt.Sprintf("Opening URL %q", url.String()) } diff --git a/command/ui_test.go b/command/ui_test.go new file mode 100644 index 000000000..5e22b9376 --- /dev/null +++ b/command/ui_test.go @@ -0,0 +1,112 @@ +package command + +import ( + "fmt" + "strings" + "testing" + + "github.com/mitchellh/cli" + "github.com/stretchr/testify/require" +) + +func TestCommand_Ui(t *testing.T) { + t.Parallel() + + type testCaseSetupFn func(*testing.T) + + cases := []struct { + Name string + SetupFn testCaseSetupFn + Args []string + ExpectedURL string + }{ + { + Name: "default values", + ExpectedURL: "http://127.0.0.1:4646", + }, + { + Name: "set namespace via flag", + Args: []string{"-namespace=dev"}, + ExpectedURL: "http://127.0.0.1:4646?namespace=dev", + }, + { + Name: "set region via flag", + Args: []string{"-region=earth"}, + ExpectedURL: "http://127.0.0.1:4646?region=earth", + }, + { + Name: "set region and namespace via flag", + Args: []string{"-region=earth", "-namespace=dev"}, + ExpectedURL: "http://127.0.0.1:4646?namespace=dev®ion=earth", + }, + { + Name: "set namespace via env var", + SetupFn: func(t *testing.T) { + setEnv(t, "NOMAD_NAMESPACE", "dev") + }, + ExpectedURL: "http://127.0.0.1:4646?namespace=dev", + }, + { + Name: "set region via flag", + SetupFn: func(t *testing.T) { + setEnv(t, "NOMAD_REGION", "earth") + }, + ExpectedURL: "http://127.0.0.1:4646?region=earth", + }, + { + Name: "set region and namespace via flag", + SetupFn: func(t *testing.T) { + setEnv(t, "NOMAD_REGION", "earth") + setEnv(t, "NOMAD_NAMESPACE", "dev") + }, + ExpectedURL: "http://127.0.0.1:4646?namespace=dev®ion=earth", + }, + { + Name: "set region and namespace via flag", + SetupFn: func(t *testing.T) { + setEnv(t, "NOMAD_REGION", "earth") + setEnv(t, "NOMAD_NAMESPACE", "dev") + }, + ExpectedURL: "http://127.0.0.1:4646?namespace=dev®ion=earth", + }, + { + Name: "flags have higher precedence", + SetupFn: func(t *testing.T) { + setEnv(t, "NOMAD_REGION", "earth") + setEnv(t, "NOMAD_NAMESPACE", "dev") + }, + Args: []string{ + "-region=mars", + "-namespace=prod", + }, + ExpectedURL: "http://127.0.0.1:4646?namespace=prod®ion=mars", + }, + } + + for _, tc := range cases { + t.Run(tc.Name, func(t *testing.T) { + // Make sure environment variables are clean. + setEnv(t, "NOMAD_NAMESPACE", "") + setEnv(t, "NOMAD_REGION", "") + + // Setup fake CLI UI and test case + ui := cli.NewMockUi() + cmd := &UiCommand{Meta: Meta{Ui: ui}} + + if tc.SetupFn != nil { + tc.SetupFn(t) + } + + // Don't try to open a browser. + args := append(tc.Args, "-show-url") + + if code := cmd.Run(args); code != 0 { + require.Equal(t, 0, code, "expected exit code 0, got %d", code) + } + + got := ui.OutputWriter.String() + expected := fmt.Sprintf("URL for web UI: %s", tc.ExpectedURL) + require.Equal(t, expected, strings.TrimSpace(got)) + }) + } +} diff --git a/website/content/docs/commands/ui.mdx b/website/content/docs/commands/ui.mdx index 1ad5370ed..8c585e688 100644 --- a/website/content/docs/commands/ui.mdx +++ b/website/content/docs/commands/ui.mdx @@ -29,7 +29,7 @@ storage for authentication. ## General Options -@include 'general_options_no_namespace.mdx' +@include 'general_options.mdx' ## UI Options