diff --git a/cli/create.go b/cli/create.go index 4e0e47b43eaa4..3f52e59e8ad90 100644 --- a/cli/create.go +++ b/cli/create.go @@ -472,7 +472,12 @@ func promptPresetSelection(inv *serpent.Invocation, presets []codersdk.Preset) ( var presetOptions []string for _, preset := range presets { - option := preset.Name + var option string + if preset.Description == "" { + option = preset.Name + } else { + option = fmt.Sprintf("%s: %s", preset.Name, preset.Description) + } presetOptions = append(presetOptions, option) presetMap[option] = &preset } diff --git a/cli/create_test.go b/cli/create_test.go index 9db2e328c6ce9..dd26e450d3916 100644 --- a/cli/create_test.go +++ b/cli/create_test.go @@ -882,7 +882,8 @@ func TestCreateWithPreset(t *testing.T) { // Given: a template and a template version with two presets preset := proto.Preset{ - Name: "preset-test", + Name: "preset-test", + Description: "Preset Test.", Parameters: []*proto.PresetParameter{ {Name: firstParameterName, Value: secondOptionalParameterValue}, {Name: thirdParameterName, Value: thirdParameterValue}, diff --git a/cli/templatepresets.go b/cli/templatepresets.go index ab0d49725b99a..240abec313a16 100644 --- a/cli/templatepresets.go +++ b/cli/templatepresets.go @@ -41,12 +41,13 @@ func (r *RootCmd) templatePresets() *serpent.Command { func (r *RootCmd) templatePresetsList() *serpent.Command { defaultColumns := []string{ "name", + "description", "parameters", "default", "desired prebuild instances", } formatter := cliui.NewOutputFormatter( - cliui.TableFormat([]templatePresetRow{}, defaultColumns), + cliui.TableFormat([]TemplatePresetRow{}, defaultColumns), cliui.JSONFormat(), ) client := new(codersdk.Client) @@ -108,10 +109,13 @@ func (r *RootCmd) templatePresetsList() *serpent.Command { return nil } - cliui.Infof( - inv.Stdout, - "Showing presets for template %q and template version %q.\n", template.Name, version.Name, - ) + // Only display info message for table output + if formatter.FormatID() == "table" { + cliui.Infof( + inv.Stdout, + "Showing presets for template %q and template version %q.\n", template.Name, version.Name, + ) + } rows := templatePresetsToRows(presets...) out, err := formatter.Format(inv.Context(), rows) if err != nil { @@ -128,12 +132,13 @@ func (r *RootCmd) templatePresetsList() *serpent.Command { return cmd } -type templatePresetRow struct { - // For json format: +type TemplatePresetRow struct { + // For json format TemplatePreset codersdk.Preset `table:"-"` // For table format: Name string `json:"-" table:"name,default_sort"` + Description string `json:"-" table:"description"` Parameters string `json:"-" table:"parameters"` Default bool `json:"-" table:"default"` DesiredPrebuildInstances string `json:"-" table:"desired prebuild instances"` @@ -149,15 +154,19 @@ func formatPresetParameters(params []codersdk.PresetParameter) string { // templatePresetsToRows converts a list of presets to a list of rows // for outputting. -func templatePresetsToRows(presets ...codersdk.Preset) []templatePresetRow { - rows := make([]templatePresetRow, len(presets)) +func templatePresetsToRows(presets ...codersdk.Preset) []TemplatePresetRow { + rows := make([]TemplatePresetRow, len(presets)) for i, preset := range presets { prebuildInstances := "-" if preset.DesiredPrebuildInstances != nil { prebuildInstances = strconv.Itoa(*preset.DesiredPrebuildInstances) } - rows[i] = templatePresetRow{ + rows[i] = TemplatePresetRow{ + // For json format + TemplatePreset: preset, + // For table format Name: preset.Name, + Description: preset.Description, Parameters: formatPresetParameters(preset.Parameters), Default: preset.Default, DesiredPrebuildInstances: prebuildInstances, diff --git a/cli/templatepresets_test.go b/cli/templatepresets_test.go index 47d34af2dcf2d..3a8c8c39f0211 100644 --- a/cli/templatepresets_test.go +++ b/cli/templatepresets_test.go @@ -1,11 +1,14 @@ package cli_test import ( + "bytes" + "encoding/json" "fmt" "testing" "github.com/stretchr/testify/require" + "github.com/coder/coder/v2/cli" "github.com/coder/coder/v2/cli/clitest" "github.com/coder/coder/v2/coderd/coderdtest" "github.com/coder/coder/v2/codersdk" @@ -84,8 +87,9 @@ func TestTemplatePresets(t *testing.T) { }, }, { - Name: "preset-prebuilds", - Parameters: []*proto.PresetParameter{}, + Name: "preset-prebuilds", + Description: "Preset without parameters and 2 prebuild instances.", + Parameters: []*proto.PresetParameter{}, Prebuild: &proto.Prebuild{ Instances: 2, }, @@ -117,7 +121,7 @@ func TestTemplatePresets(t *testing.T) { pty.ExpectRegexMatch(`preset-default\s+k1=v2\s+true\s+0`) // The parameter order is not guaranteed in the output, so we match both possible orders pty.ExpectRegexMatch(`preset-multiple-params\s+(k1=v1,k2=v2)|(k2=v2,k1=v1)\s+false\s+-`) - pty.ExpectRegexMatch(`preset-prebuilds\s+\s+false\s+2`) + pty.ExpectRegexMatch(`preset-prebuilds\s+Preset without parameters and 2 prebuild instances.\s+\s+false\s+2`) }) t.Run("ListsPresetsForSpecifiedTemplateVersion", func(t *testing.T) { @@ -158,8 +162,9 @@ func TestTemplatePresets(t *testing.T) { }, }, { - Name: "preset-prebuilds", - Parameters: []*proto.PresetParameter{}, + Name: "preset-prebuilds", + Description: "Preset without parameters and 2 prebuild instances.", + Parameters: []*proto.PresetParameter{}, Prebuild: &proto.Prebuild{ Instances: 2, }, @@ -208,7 +213,69 @@ func TestTemplatePresets(t *testing.T) { pty.ExpectRegexMatch(`preset-default\s+k1=v2\s+true\s+0`) // The parameter order is not guaranteed in the output, so we match both possible orders pty.ExpectRegexMatch(`preset-multiple-params\s+(k1=v1,k2=v2)|(k2=v2,k1=v1)\s+false\s+-`) - pty.ExpectRegexMatch(`preset-prebuilds\s+\s+false\s+2`) + pty.ExpectRegexMatch(`preset-prebuilds\s+Preset without parameters and 2 prebuild instances.\s+\s+false\s+2`) + }) + + t.Run("ListsPresetsJSON", func(t *testing.T) { + t.Parallel() + + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) + owner := coderdtest.CreateFirstUser(t, client) + member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) + + // Given: an active template version that includes presets + preset := proto.Preset{ + Name: "preset-default", + Description: "Preset with parameters and 2 prebuild instances.", + Icon: "/emojis/1f60e.png", + Default: true, + Parameters: []*proto.PresetParameter{ + { + Name: "k1", + Value: "v2", + }, + }, + Prebuild: &proto.Prebuild{ + Instances: 2, + }, + } + + version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, templateWithPresets([]*proto.Preset{&preset})) + _ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) + template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID) + require.Equal(t, version.ID, template.ActiveVersionID) + + // When: listing presets for that template + inv, root := clitest.New(t, "templates", "presets", "list", template.Name, "-o", "json") + clitest.SetupConfig(t, member, root) + + buf := bytes.NewBuffer(nil) + inv.Stdout = buf + doneChan := make(chan struct{}) + var runErr error + go func() { + defer close(doneChan) + runErr = inv.Run() + }() + + <-doneChan + require.NoError(t, runErr) + + // Should: return the active version's preset + var jsonPresets []cli.TemplatePresetRow + err := json.Unmarshal(buf.Bytes(), &jsonPresets) + require.NoError(t, err, "unmarshal JSON output") + require.Len(t, jsonPresets, 1) + + jsonPreset := jsonPresets[0].TemplatePreset + require.Equal(t, preset.Name, jsonPreset.Name) + require.Equal(t, preset.Description, jsonPreset.Description) + require.Equal(t, preset.Icon, jsonPreset.Icon) + require.Equal(t, preset.Default, jsonPreset.Default) + require.Equal(t, len(preset.Parameters), len(jsonPreset.Parameters)) + require.Equal(t, preset.Parameters[0].Name, jsonPreset.Parameters[0].Name) + require.Equal(t, preset.Parameters[0].Value, jsonPreset.Parameters[0].Value) + require.Equal(t, int(preset.Prebuild.Instances), *jsonPreset.DesiredPrebuildInstances) }) } diff --git a/cli/testdata/coder_templates_presets_list_--help.golden b/cli/testdata/coder_templates_presets_list_--help.golden index 81445df03cc97..e64ef1ee36e96 100644 --- a/cli/testdata/coder_templates_presets_list_--help.golden +++ b/cli/testdata/coder_templates_presets_list_--help.golden @@ -10,7 +10,7 @@ OPTIONS: -O, --org string, $CODER_ORGANIZATION Select which organization (uuid or name) to use. - -c, --column [name|parameters|default|desired prebuild instances] (default: name,parameters,default,desired prebuild instances) + -c, --column [name|description|parameters|default|desired prebuild instances] (default: name,description,parameters,default,desired prebuild instances) Columns to display in table output. -o, --output table|json (default: table) diff --git a/docs/reference/cli/templates_presets_list.md b/docs/reference/cli/templates_presets_list.md index 69dd12faadc7b..5c2d26859f018 100644 --- a/docs/reference/cli/templates_presets_list.md +++ b/docs/reference/cli/templates_presets_list.md @@ -30,10 +30,10 @@ Select which organization (uuid or name) to use. ### -c, --column -| | | -|---------|----------------------------------------------------------------------| -| Type | [name\|parameters\|default\|desired prebuild instances] | -| Default | name,parameters,default,desired prebuild instances | +| | | +|---------|-----------------------------------------------------------------------------------| +| Type | [name\|description\|parameters\|default\|desired prebuild instances] | +| Default | name,description,parameters,default,desired prebuild instances | Columns to display in table output.