diff --git a/cli/cliui/parameter.go b/cli/cliui/parameter.go
index 789ce0c033..897ddec4de 100644
--- a/cli/cliui/parameter.go
+++ b/cli/cliui/parameter.go
@@ -10,7 +10,7 @@ import (
"github.com/coder/serpent"
)
-func RichParameter(inv *serpent.Invocation, templateVersionParameter codersdk.TemplateVersionParameter) (string, error) {
+func RichParameter(inv *serpent.Invocation, templateVersionParameter codersdk.TemplateVersionParameter, defaultOverrides map[string]string) (string, error) {
label := templateVersionParameter.Name
if templateVersionParameter.DisplayName != "" {
label = templateVersionParameter.DisplayName
@@ -26,6 +26,11 @@ func RichParameter(inv *serpent.Invocation, templateVersionParameter codersdk.Te
_, _ = fmt.Fprintln(inv.Stdout, " "+strings.TrimSpace(strings.Join(strings.Split(templateVersionParameter.DescriptionPlaintext, "\n"), "\n "))+"\n")
}
+ defaultValue := templateVersionParameter.DefaultValue
+ if v, ok := defaultOverrides[templateVersionParameter.Name]; ok {
+ defaultValue = v
+ }
+
var err error
var value string
if templateVersionParameter.Type == "list(string)" {
@@ -58,7 +63,7 @@ func RichParameter(inv *serpent.Invocation, templateVersionParameter codersdk.Te
var richParameterOption *codersdk.TemplateVersionParameterOption
richParameterOption, err = RichSelect(inv, RichSelectOptions{
Options: templateVersionParameter.Options,
- Default: templateVersionParameter.DefaultValue,
+ Default: defaultValue,
HideSearch: true,
})
if err == nil {
@@ -69,7 +74,7 @@ func RichParameter(inv *serpent.Invocation, templateVersionParameter codersdk.Te
} else {
text := "Enter a value"
if !templateVersionParameter.Required {
- text += fmt.Sprintf(" (default: %q)", templateVersionParameter.DefaultValue)
+ text += fmt.Sprintf(" (default: %q)", defaultValue)
}
text += ":"
@@ -87,7 +92,7 @@ func RichParameter(inv *serpent.Invocation, templateVersionParameter codersdk.Te
// If they didn't specify anything, use the default value if set.
if len(templateVersionParameter.Options) == 0 && value == "" {
- value = templateVersionParameter.DefaultValue
+ value = defaultValue
}
return value, nil
diff --git a/cli/create.go b/cli/create.go
index 4aff56992d..ab9a204fad 100644
--- a/cli/create.go
+++ b/cli/create.go
@@ -165,6 +165,11 @@ func (r *RootCmd) create() *serpent.Command {
return xerrors.Errorf("can't parse given parameter values: %w", err)
}
+ cliBuildParameterDefaults, err := asWorkspaceBuildParameters(parameterFlags.richParameterDefaults)
+ if err != nil {
+ return xerrors.Errorf("can't parse given parameter defaults: %w", err)
+ }
+
var sourceWorkspaceParameters []codersdk.WorkspaceBuildParameter
if copyParametersFrom != "" {
sourceWorkspaceParameters, err = client.WorkspaceBuildParameters(inv.Context(), sourceWorkspace.LatestBuild.ID)
@@ -178,8 +183,9 @@ func (r *RootCmd) create() *serpent.Command {
TemplateVersionID: templateVersionID,
NewWorkspaceName: workspaceName,
- RichParameterFile: parameterFlags.richParameterFile,
- RichParameters: cliBuildParameters,
+ RichParameterFile: parameterFlags.richParameterFile,
+ RichParameters: cliBuildParameters,
+ RichParameterDefaults: cliBuildParameterDefaults,
SourceWorkspaceParameters: sourceWorkspaceParameters,
})
@@ -262,6 +268,7 @@ func (r *RootCmd) create() *serpent.Command {
cliui.SkipPromptOption(),
)
cmd.Options = append(cmd.Options, parameterFlags.cliParameters()...)
+ cmd.Options = append(cmd.Options, parameterFlags.cliParameterDefaults()...)
return cmd
}
@@ -276,9 +283,10 @@ type prepWorkspaceBuildArgs struct {
PromptBuildOptions bool
BuildOptions []codersdk.WorkspaceBuildParameter
- PromptRichParameters bool
- RichParameters []codersdk.WorkspaceBuildParameter
- RichParameterFile string
+ PromptRichParameters bool
+ RichParameters []codersdk.WorkspaceBuildParameter
+ RichParameterFile string
+ RichParameterDefaults []codersdk.WorkspaceBuildParameter
}
// prepWorkspaceBuild will ensure a workspace build will succeed on the latest template version.
@@ -311,7 +319,8 @@ func prepWorkspaceBuild(inv *serpent.Invocation, client *codersdk.Client, args p
WithBuildOptions(args.BuildOptions).
WithPromptRichParameters(args.PromptRichParameters).
WithRichParameters(args.RichParameters).
- WithRichParametersFile(parameterFile)
+ WithRichParametersFile(parameterFile).
+ WithRichParametersDefaults(args.RichParameterDefaults)
buildParameters, err := resolver.Resolve(inv, args.Action, templateVersionParameters)
if err != nil {
return nil, err
diff --git a/cli/create_test.go b/cli/create_test.go
index 639f23c2e7..b6294f50b4 100644
--- a/cli/create_test.go
+++ b/cli/create_test.go
@@ -315,6 +315,68 @@ func TestCreateWithRichParameters(t *testing.T) {
<-doneChan
})
+ t.Run("ParametersDefaults", 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)
+ version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, echoResponses)
+ coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
+
+ template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
+
+ inv, root := clitest.New(t, "create", "my-workspace", "--template", template.Name,
+ "--parameter-default", fmt.Sprintf("%s=%s", firstParameterName, firstParameterValue),
+ "--parameter-default", fmt.Sprintf("%s=%s", secondParameterName, secondParameterValue),
+ "--parameter-default", fmt.Sprintf("%s=%s", immutableParameterName, immutableParameterValue))
+ clitest.SetupConfig(t, member, root)
+ doneChan := make(chan struct{})
+ pty := ptytest.New(t).Attach(inv)
+ go func() {
+ defer close(doneChan)
+ err := inv.Run()
+ assert.NoError(t, err)
+ }()
+
+ matches := []string{
+ firstParameterDescription, firstParameterValue,
+ secondParameterDescription, secondParameterValue,
+ immutableParameterDescription, immutableParameterValue,
+ }
+ for i := 0; i < len(matches); i += 2 {
+ match := matches[i]
+ defaultValue := matches[i+1]
+
+ pty.ExpectMatch(match)
+ pty.ExpectMatch(`Enter a value (default: "` + defaultValue + `")`)
+ pty.WriteLine("")
+ }
+ pty.ExpectMatch("Confirm create?")
+ pty.WriteLine("yes")
+ <-doneChan
+
+ // Verify that the expected default values were used.
+ ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
+ defer cancel()
+
+ workspaces, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{
+ Name: "my-workspace",
+ })
+ require.NoError(t, err, "can't list available workspaces")
+ require.Len(t, workspaces.Workspaces, 1)
+
+ workspaceLatestBuild := workspaces.Workspaces[0].LatestBuild
+ require.Equal(t, version.ID, workspaceLatestBuild.TemplateVersionID)
+
+ buildParameters, err := client.WorkspaceBuildParameters(ctx, workspaceLatestBuild.ID)
+ require.NoError(t, err)
+ require.Len(t, buildParameters, 3)
+ require.Contains(t, buildParameters, codersdk.WorkspaceBuildParameter{Name: firstParameterName, Value: firstParameterValue})
+ require.Contains(t, buildParameters, codersdk.WorkspaceBuildParameter{Name: secondParameterName, Value: secondParameterValue})
+ require.Contains(t, buildParameters, codersdk.WorkspaceBuildParameter{Name: immutableParameterName, Value: immutableParameterValue})
+ })
+
t.Run("RichParametersFile", func(t *testing.T) {
t.Parallel()
diff --git a/cli/parameter.go b/cli/parameter.go
index 0070c47e5b..e9b1ca581a 100644
--- a/cli/parameter.go
+++ b/cli/parameter.go
@@ -18,14 +18,16 @@ type workspaceParameterFlags struct {
promptBuildOptions bool
buildOptions []string
- richParameterFile string
- richParameters []string
+ richParameterFile string
+ richParameters []string
+ richParameterDefaults []string
promptRichParameters bool
}
func (wpf *workspaceParameterFlags) allOptions() []serpent.Option {
options := append(wpf.cliBuildOptions(), wpf.cliParameters()...)
+ options = append(options, wpf.cliParameterDefaults()...)
return append(options, wpf.alwaysPrompt())
}
@@ -62,6 +64,17 @@ func (wpf *workspaceParameterFlags) cliParameters() []serpent.Option {
}
}
+func (wpf *workspaceParameterFlags) cliParameterDefaults() []serpent.Option {
+ return serpent.OptionSet{
+ serpent.Option{
+ Flag: "parameter-default",
+ Env: "CODER_RICH_PARAMETER_DEFAULT",
+ Description: `Rich parameter default values in the format "name=value".`,
+ Value: serpent.StringArrayOf(&wpf.richParameterDefaults),
+ },
+ }
+}
+
func (wpf *workspaceParameterFlags) alwaysPrompt() serpent.Option {
return serpent.Option{
Flag: "always-prompt",
diff --git a/cli/parameterresolver.go b/cli/parameterresolver.go
index 3e1e70d1cc..437b4bd407 100644
--- a/cli/parameterresolver.go
+++ b/cli/parameterresolver.go
@@ -26,9 +26,10 @@ type ParameterResolver struct {
lastBuildParameters []codersdk.WorkspaceBuildParameter
sourceWorkspaceParameters []codersdk.WorkspaceBuildParameter
- richParameters []codersdk.WorkspaceBuildParameter
- richParametersFile map[string]string
- buildOptions []codersdk.WorkspaceBuildParameter
+ richParameters []codersdk.WorkspaceBuildParameter
+ richParametersDefaults map[string]string
+ richParametersFile map[string]string
+ buildOptions []codersdk.WorkspaceBuildParameter
promptRichParameters bool
promptBuildOptions bool
@@ -59,6 +60,16 @@ func (pr *ParameterResolver) WithRichParametersFile(fileMap map[string]string) *
return pr
}
+func (pr *ParameterResolver) WithRichParametersDefaults(params []codersdk.WorkspaceBuildParameter) *ParameterResolver {
+ if pr.richParametersDefaults == nil {
+ pr.richParametersDefaults = make(map[string]string)
+ }
+ for _, p := range params {
+ pr.richParametersDefaults[p.Name] = p.Value
+ }
+ return pr
+}
+
func (pr *ParameterResolver) WithPromptRichParameters(promptRichParameters bool) *ParameterResolver {
pr.promptRichParameters = promptRichParameters
return pr
@@ -227,7 +238,7 @@ func (pr *ParameterResolver) resolveWithInput(resolved []codersdk.WorkspaceBuild
(action == WorkspaceUpdate && tvp.Mutable && tvp.Required) ||
(action == WorkspaceUpdate && !tvp.Mutable && firstTimeUse) ||
(tvp.Mutable && !tvp.Ephemeral && pr.promptRichParameters) {
- parameterValue, err := cliui.RichParameter(inv, tvp)
+ parameterValue, err := cliui.RichParameter(inv, tvp, pr.richParametersDefaults)
if err != nil {
return nil, err
}
diff --git a/cli/start.go b/cli/start.go
index b0f0a4be4b..89f15b95c4 100644
--- a/cli/start.go
+++ b/cli/start.go
@@ -99,7 +99,12 @@ func buildWorkspaceStartRequest(inv *serpent.Invocation, client *codersdk.Client
cliRichParameters, err := asWorkspaceBuildParameters(parameterFlags.richParameters)
if err != nil {
- return codersdk.CreateWorkspaceBuildRequest{}, xerrors.Errorf("unable to parse build options: %w", err)
+ return codersdk.CreateWorkspaceBuildRequest{}, xerrors.Errorf("unable to parse rich parameters: %w", err)
+ }
+
+ cliRichParameterDefaults, err := asWorkspaceBuildParameters(parameterFlags.richParameterDefaults)
+ if err != nil {
+ return codersdk.CreateWorkspaceBuildRequest{}, xerrors.Errorf("unable to parse rich parameter defaults: %w", err)
}
buildParameters, err := prepWorkspaceBuild(inv, client, prepWorkspaceBuildArgs{
@@ -108,11 +113,12 @@ func buildWorkspaceStartRequest(inv *serpent.Invocation, client *codersdk.Client
NewWorkspaceName: workspace.Name,
LastBuildParameters: lastBuildParameters,
- PromptBuildOptions: parameterFlags.promptBuildOptions,
- BuildOptions: buildOptions,
- PromptRichParameters: parameterFlags.promptRichParameters,
- RichParameters: cliRichParameters,
- RichParameterFile: parameterFlags.richParameterFile,
+ PromptBuildOptions: parameterFlags.promptBuildOptions,
+ BuildOptions: buildOptions,
+ PromptRichParameters: parameterFlags.promptRichParameters,
+ RichParameters: cliRichParameters,
+ RichParameterFile: parameterFlags.richParameterFile,
+ RichParameterDefaults: cliRichParameterDefaults,
})
if err != nil {
return codersdk.CreateWorkspaceBuildRequest{}, err
diff --git a/cli/testdata/coder_create_--help.golden b/cli/testdata/coder_create_--help.golden
index 7662ecd7ed..9edadd5500 100644
--- a/cli/testdata/coder_create_--help.golden
+++ b/cli/testdata/coder_create_--help.golden
@@ -20,6 +20,9 @@ OPTIONS:
--parameter string-array, $CODER_RICH_PARAMETER
Rich parameter value in the format "name=value".
+ --parameter-default string-array, $CODER_RICH_PARAMETER_DEFAULT
+ Rich parameter default values in the format "name=value".
+
--rich-parameter-file string, $CODER_RICH_PARAMETER_FILE
Specify a file path with values for rich parameters defined in the
template.
diff --git a/cli/testdata/coder_restart_--help.golden b/cli/testdata/coder_restart_--help.golden
index b274812f7f..b0b036929c 100644
--- a/cli/testdata/coder_restart_--help.golden
+++ b/cli/testdata/coder_restart_--help.golden
@@ -19,6 +19,9 @@ OPTIONS:
--parameter string-array, $CODER_RICH_PARAMETER
Rich parameter value in the format "name=value".
+ --parameter-default string-array, $CODER_RICH_PARAMETER_DEFAULT
+ Rich parameter default values in the format "name=value".
+
--rich-parameter-file string, $CODER_RICH_PARAMETER_FILE
Specify a file path with values for rich parameters defined in the
template.
diff --git a/cli/testdata/coder_start_--help.golden b/cli/testdata/coder_start_--help.golden
index 10df0d5bc4..4985930b62 100644
--- a/cli/testdata/coder_start_--help.golden
+++ b/cli/testdata/coder_start_--help.golden
@@ -19,6 +19,9 @@ OPTIONS:
--parameter string-array, $CODER_RICH_PARAMETER
Rich parameter value in the format "name=value".
+ --parameter-default string-array, $CODER_RICH_PARAMETER_DEFAULT
+ Rich parameter default values in the format "name=value".
+
--rich-parameter-file string, $CODER_RICH_PARAMETER_FILE
Specify a file path with values for rich parameters defined in the
template.
diff --git a/cli/testdata/coder_update_--help.golden b/cli/testdata/coder_update_--help.golden
index 896747ca7f..bff9086846 100644
--- a/cli/testdata/coder_update_--help.golden
+++ b/cli/testdata/coder_update_--help.golden
@@ -21,6 +21,9 @@ OPTIONS:
--parameter string-array, $CODER_RICH_PARAMETER
Rich parameter value in the format "name=value".
+ --parameter-default string-array, $CODER_RICH_PARAMETER_DEFAULT
+ Rich parameter default values in the format "name=value".
+
--rich-parameter-file string, $CODER_RICH_PARAMETER_FILE
Specify a file path with values for rich parameters defined in the
template.
diff --git a/docs/cli/create.md b/docs/cli/create.md
index 8eeb90ebbe..53f9075151 100644
--- a/docs/cli/create.md
+++ b/docs/cli/create.md
@@ -91,3 +91,12 @@ Rich parameter value in the format "name=value".
| Environment | $CODER_RICH_PARAMETER_FILE |
Specify a file path with values for rich parameters defined in the template.
+
+### --parameter-default
+
+| | |
+| ----------- | ------------------------------------------ |
+| Type | string-array |
+| Environment | $CODER_RICH_PARAMETER_DEFAULT |
+
+Rich parameter default values in the format "name=value".
diff --git a/docs/cli/restart.md b/docs/cli/restart.md
index a2eb033e80..215917a8e0 100644
--- a/docs/cli/restart.md
+++ b/docs/cli/restart.md
@@ -55,6 +55,15 @@ Rich parameter value in the format "name=value".
Specify a file path with values for rich parameters defined in the template.
+### --parameter-default
+
+| | |
+| ----------- | ------------------------------------------ |
+| Type | string-array |
+| Environment | $CODER_RICH_PARAMETER_DEFAULT |
+
+Rich parameter default values in the format "name=value".
+
### --always-prompt
| | |
diff --git a/docs/cli/start.md b/docs/cli/start.md
index 44796fa817..0852ec5b57 100644
--- a/docs/cli/start.md
+++ b/docs/cli/start.md
@@ -55,6 +55,15 @@ Rich parameter value in the format "name=value".
Specify a file path with values for rich parameters defined in the template.
+### --parameter-default
+
+| | |
+| ----------- | ------------------------------------------ |
+| Type | string-array |
+| Environment | $CODER_RICH_PARAMETER_DEFAULT |
+
+Rich parameter default values in the format "name=value".
+
### --always-prompt
| | |
diff --git a/docs/cli/update.md b/docs/cli/update.md
index 89d6693d0c..562d32f8fd 100644
--- a/docs/cli/update.md
+++ b/docs/cli/update.md
@@ -53,6 +53,15 @@ Rich parameter value in the format "name=value".
Specify a file path with values for rich parameters defined in the template.
+### --parameter-default
+
+| | |
+| ----------- | ------------------------------------------ |
+| Type | string-array |
+| Environment | $CODER_RICH_PARAMETER_DEFAULT |
+
+Rich parameter default values in the format "name=value".
+
### --always-prompt
| | |