diff --git a/.changelog/16485.txt b/.changelog/16485.txt new file mode 100644 index 000000000..fe4beb372 --- /dev/null +++ b/.changelog/16485.txt @@ -0,0 +1,3 @@ +```release-note:improvement +cli: Added `-json` and `-t` flag to `quota status` command +``` diff --git a/command/quota_status.go b/command/quota_status.go index 3cf6448ba..ca36d4b57 100644 --- a/command/quota_status.go +++ b/command/quota_status.go @@ -26,13 +26,26 @@ Usage: nomad quota status [options] General Options: - ` + generalOptionsUsage(usageOptsDefault) + ` + generalOptionsUsage(usageOptsDefault) + ` + +Status Specific Options: + + -json + Output the latest quota status information in a JSON format. + + -t + Format and display quota status information using a Go template. +` return strings.TrimSpace(helpText) } func (c *QuotaStatusCommand) AutocompleteFlags() complete.Flags { - return c.Meta.AutocompleteFlags(FlagSetClient) + return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient), + complete.Flags{ + "-json": complete.PredictNothing, + "-t": complete.PredictAnything, + }) } func (c *QuotaStatusCommand) AutocompleteArgs() complete.Predictor { @@ -46,8 +59,13 @@ func (c *QuotaStatusCommand) Synopsis() string { func (c *QuotaStatusCommand) Name() string { return "quota status" } func (c *QuotaStatusCommand) Run(args []string) int { + var json bool + var tmpl string + flags := c.Meta.FlagSet(c.Name(), FlagSetClient) flags.Usage = func() { c.Ui.Output(c.Help()) } + flags.BoolVar(&json, "json", false, "") + flags.StringVar(&tmpl, "t", "", "") if err := flags.Parse(args); err != nil { return 1 @@ -83,6 +101,17 @@ func (c *QuotaStatusCommand) Run(args []string) int { return 1 } + if json || len(tmpl) > 0 { + out, err := Format(json, tmpl, spec) + if err != nil { + c.Ui.Error(err.Error()) + return 1 + } + + c.Ui.Output(out) + return 0 + } + // Format the basics c.Ui.Output(formatQuotaSpecBasics(spec)) diff --git a/command/quota_status_test.go b/command/quota_status_test.go index b580414bf..e01c1f7c2 100644 --- a/command/quota_status_test.go +++ b/command/quota_status_test.go @@ -41,7 +41,7 @@ func TestQuotaStatusCommand_Fails(t *testing.T) { ui.ErrorWriter.Reset() } -func TestQuotaStatusCommand_Good(t *testing.T) { +func TestQuotaStatusCommand_Run(t *testing.T) { ci.Parallel(t) // Create a server @@ -54,7 +54,7 @@ func TestQuotaStatusCommand_Good(t *testing.T) { // Create a quota to delete qs := testQuotaSpec() _, err := client.Quotas().Register(qs, nil) - assert.Nil(t, err) + must.NoError(t, err) // Delete a namespace if code := cmd.Run([]string{"-address=" + url, qs.Name}); code != 0 { @@ -63,14 +63,30 @@ func TestQuotaStatusCommand_Good(t *testing.T) { // Check for basic spec out := ui.OutputWriter.String() - if !strings.Contains(out, "= test") { - t.Fatalf("expected quota, got: %s", out) - } + must.StrContains(t, out, "= test") // Check for usage - if !strings.Contains(out, "0 / 100") { - t.Fatalf("expected quota, got: %s", out) - } + must.StrContains(t, out, "0 / 100") + + ui.OutputWriter.Reset() + + // List json + must.Zero(t, cmd.Run([]string{"-address=" + url, "-json", qs.Name})) + + outJson := api.QuotaSpec{} + err = json.Unmarshal(ui.OutputWriter.Bytes(), &outJson) + must.NoError(t, err) + + ui.OutputWriter.Reset() + + // Go template to format the output + code = cmd.Run([]string{"-address=" + url, "-t", "{{range .}}{{ .Name }}{{end}}", allocID}) + must.Zero(t, code) + + out = ui.OutputWriter.String() + must.StrContains(t, out, "test-quota") + + ui.OutputWriter.Reset() } func TestQuotaStatusCommand_AutocompleteArgs(t *testing.T) { @@ -86,12 +102,12 @@ func TestQuotaStatusCommand_AutocompleteArgs(t *testing.T) { // Create a quota qs := testQuotaSpec() _, err := client.Quotas().Register(qs, nil) - assert.Nil(err) + must.NoError(err) args := complete.Args{Last: "t"} predictor := cmd.AutocompleteArgs() res := predictor.Predict(args) - assert.Equal(1, len(res)) - assert.Equal(qs.Name, res[0]) + must.One(t, len(res)) + must.StrContains(t, qs.Name, res[0]) } diff --git a/website/content/docs/commands/quota/status.mdx b/website/content/docs/commands/quota/status.mdx index 45ea3a4ca..c9a8ec7db 100644 --- a/website/content/docs/commands/quota/status.mdx +++ b/website/content/docs/commands/quota/status.mdx @@ -27,6 +27,12 @@ capability and access to any namespaces that the quota is applied to. @include 'general_options.mdx' +## Inspect Options + +- `-json`: Output the quota specifications in a JSON format. + +- `-t`: Format and display the quota using a Go template. + ## Examples View the status of a quota specification: @@ -40,4 +46,36 @@ Limits = 1 Quota Limits Region CPU Usage Memory Usage Network Usage global 500 / 2500 256 / 2000 30 / 50 + ``` + +The `-json` flag can be used to get the quota status in json format: + +```shell-session +$ nomad quota inspect -json default-quota +{ + "CreateIndex": 8, + "Description": "Limit the shared default namespace", + "Limits": [ + { + "Hash": "NLOoV2WBU8ieJIrYXXx8NRb5C2xU61pVVWRDLEIMxlU=", + "Region": "global", + "RegionLimit": { + "CPU": 2500, + "DiskMB": 0, + "MemoryMB": 2000, + "Networks": null + } + } + ], + "ModifyIndex": 56, + "Name": "default-quota" +} +``` + +Or use the `-t` flag to format and display the quota status using a Go template: + +```shell-session +$ nomad quota inspect -t {{ .Description }} default-quota +Limit the shared default namespace +``` \ No newline at end of file