diff --git a/cli/cliui/parameter.go b/cli/cliui/parameter.go index d972e346bf..772b78cc55 100644 --- a/cli/cliui/parameter.go +++ b/cli/cliui/parameter.go @@ -10,12 +10,8 @@ import ( "github.com/coder/serpent" ) -func RichParameter(inv *serpent.Invocation, templateVersionParameter codersdk.TemplateVersionParameter, defaultOverrides map[string]string) (string, error) { - label := templateVersionParameter.Name - if templateVersionParameter.DisplayName != "" { - label = templateVersionParameter.DisplayName - } - +func RichParameter(inv *serpent.Invocation, templateVersionParameter codersdk.TemplateVersionParameter, name, defaultValue string) (string, error) { + label := name if templateVersionParameter.Ephemeral { label += pretty.Sprint(DefaultStyles.Warn, " (build option)") } @@ -26,11 +22,6 @@ 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 switch { diff --git a/cli/cliui/prompt.go b/cli/cliui/prompt.go index 264ebf2939..661c256db5 100644 --- a/cli/cliui/prompt.go +++ b/cli/cliui/prompt.go @@ -32,12 +32,12 @@ type PromptOptions struct { const skipPromptFlag = "yes" // SkipPromptOption adds a "--yes/-y" flag to the cmd that can be used to skip -// prompts. +// confirmation prompts. func SkipPromptOption() serpent.Option { return serpent.Option{ Flag: skipPromptFlag, FlagShorthand: "y", - Description: "Bypass prompts.", + Description: "Bypass confirmation prompts.", // Discard Value: serpent.BoolOf(new(bool)), } diff --git a/cli/create.go b/cli/create.go index 79f9c8e2df..5b96652c44 100644 --- a/cli/create.go +++ b/cli/create.go @@ -42,9 +42,10 @@ func (r *RootCmd) Create(opts CreateOptions) *serpent.Command { stopAfter time.Duration workspaceName string - parameterFlags workspaceParameterFlags - autoUpdates string - copyParametersFrom string + parameterFlags workspaceParameterFlags + autoUpdates string + copyParametersFrom string + useParameterDefaults bool // Organization context is only required if more than 1 template // shares the same name across multiple organizations. orgContext = NewOrganizationContext() @@ -308,7 +309,7 @@ func (r *RootCmd) Create(opts CreateOptions) *serpent.Command { displayAppliedPreset(inv, preset, presetParameters) } else { // Inform the user that no preset was applied - _, _ = fmt.Fprintf(inv.Stdout, "%s", cliui.Bold("No preset applied.")) + _, _ = fmt.Fprintf(inv.Stdout, "%s\n", cliui.Bold("No preset applied.")) } if opts.BeforeCreate != nil { @@ -329,6 +330,8 @@ func (r *RootCmd) Create(opts CreateOptions) *serpent.Command { RichParameterDefaults: cliBuildParameterDefaults, SourceWorkspaceParameters: sourceWorkspaceParameters, + + UseParameterDefaults: useParameterDefaults, }) if err != nil { return xerrors.Errorf("prepare build: %w", err) @@ -435,6 +438,12 @@ func (r *RootCmd) Create(opts CreateOptions) *serpent.Command { Description: "Specify the source workspace name to copy parameters from.", Value: serpent.StringOf(©ParametersFrom), }, + serpent.Option{ + Flag: "use-parameter-defaults", + Env: "CODER_WORKSPACE_USE_PARAMETER_DEFAULTS", + Description: "Automatically accept parameter defaults when no value is provided.", + Value: serpent.BoolOf(&useParameterDefaults), + }, cliui.SkipPromptOption(), ) cmd.Options = append(cmd.Options, parameterFlags.cliParameters()...) @@ -459,6 +468,8 @@ type prepWorkspaceBuildArgs struct { RichParameters []codersdk.WorkspaceBuildParameter RichParameterFile string RichParameterDefaults []codersdk.WorkspaceBuildParameter + + UseParameterDefaults bool } // resolvePreset returns the preset matching the given presetName (if specified), @@ -561,7 +572,8 @@ func prepWorkspaceBuild(inv *serpent.Invocation, client *codersdk.Client, args p WithPromptRichParameters(args.PromptRichParameters). WithRichParameters(args.RichParameters). WithRichParametersFile(parameterFile). - WithRichParametersDefaults(args.RichParameterDefaults) + WithRichParametersDefaults(args.RichParameterDefaults). + WithUseParameterDefaults(args.UseParameterDefaults) 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 6a508d149b..f603cd4379 100644 --- a/cli/create_test.go +++ b/cli/create_test.go @@ -318,353 +318,437 @@ func prepareEchoResponses(parameters []*proto.RichParameter, presets ...*proto.P } } +type param struct { + name string + ptype string + value string + mutable bool +} + func TestCreateWithRichParameters(t *testing.T) { t.Parallel() - const ( - firstParameterName = "first_parameter" - firstParameterDescription = "This is first parameter" - firstParameterValue = "1" - - secondParameterName = "second_parameter" - secondParameterDisplayName = "Second Parameter" - secondParameterDescription = "This is second parameter" - secondParameterValue = "2" - - immutableParameterName = "third_parameter" - immutableParameterDescription = "This is not mutable parameter" - immutableParameterValue = "4" - ) - - echoResponses := func() *echo.Responses { - return prepareEchoResponses([]*proto.RichParameter{ - {Name: firstParameterName, Description: firstParameterDescription, Mutable: true}, - {Name: secondParameterName, DisplayName: secondParameterDisplayName, Description: secondParameterDescription, Mutable: true}, - {Name: immutableParameterName, Description: immutableParameterDescription, Mutable: false}, - }) + // Default parameters and their expected values. + params := []param{ + { + name: "number_param", + ptype: "number", + value: "777", + mutable: true, + }, + { + name: "string_param", + ptype: "string", + value: "qux", + mutable: true, + }, + { + name: "bool_param", + // TODO: Setting the type breaks booleans. It claims the default is false + // but when you then accept this default it errors saying that the value + // must be true or false. For now, use a string. + ptype: "string", + value: "false", + mutable: true, + }, + { + name: "immutable_string_param", + ptype: "string", + value: "i am eternal", + mutable: false, + }, } - t.Run("InputParameters", func(t *testing.T) { - t.Parallel() + type testContext struct { + client *codersdk.Client + member *codersdk.Client + owner codersdk.CreateFirstUserResponse + template codersdk.Template + workspaceName string + } - 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) + tests := []struct { + name string + // setup runs before the command is started and return arguments that will + // be appended to the create command. + setup func() []string + // handlePty optionally runs after the command is started. It should handle + // all expected prompts from the pty. + handlePty func(pty *ptytest.PTY) + // postRun runs after the command has finished but before the workspace is + // verified. It must return the workspace name to check (used for the copy + // workspace tests). + postRun func(t *testing.T, args testContext) string + // errors contains expected errors. The workspace will not be verified if + // errors are expected. + errors []string + // inputParameters overrides the default parameters. + inputParameters []param + // expectedParameters defaults to inputParameters. + expectedParameters []param + // withDefaults sets DefaultValue to each parameter's value. + withDefaults bool + }{ + { + name: "ValuesFromPrompt", + handlePty: func(pty *ptytest.PTY) { + // Enter the value for each parameter as prompted. + for _, param := range params { + pty.ExpectMatch(param.name) + pty.WriteLine(param.value) + } + // Confirm the creation. + pty.ExpectMatch("Confirm create?") + pty.WriteLine("yes") + }, + }, + { + name: "ValuesFromDefaultFlags", + setup: func() []string { + // Provide the defaults on the command line. + args := []string{} + for _, param := range params { + args = append(args, "--parameter-default", fmt.Sprintf("%s=%s", param.name, param.value)) + } + return args + }, + handlePty: func(pty *ptytest.PTY) { + // Simply accept the defaults. + for _, param := range params { + pty.ExpectMatch(param.name) + pty.ExpectMatch(`Enter a value (default: "` + param.value + `")`) + pty.WriteLine("") + } + // Confirm the creation. + pty.ExpectMatch("Confirm create?") + pty.WriteLine("yes") + }, + }, + { + name: "ValuesFromFile", + setup: func() []string { + // Create a file with the values. + tempDir := t.TempDir() + removeTmpDirUntilSuccessAfterTest(t, tempDir) + parameterFile, _ := os.CreateTemp(tempDir, "testParameterFile*.yaml") + for _, param := range params { + _, err := parameterFile.WriteString(fmt.Sprintf("%s: %s\n", param.name, param.value)) + require.NoError(t, err) + } - template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID) + return []string{"--rich-parameter-file", parameterFile.Name()} + }, + handlePty: func(pty *ptytest.PTY) { + // No prompts, we only need to confirm. + pty.ExpectMatch("Confirm create?") + pty.WriteLine("yes") + }, + }, + { + name: "ValuesFromFlags", + setup: func() []string { + // Provide the values on the command line. + var args []string + for _, param := range params { + args = append(args, "--parameter", fmt.Sprintf("%s=%s", param.name, param.value)) + } + return args + }, + handlePty: func(pty *ptytest.PTY) { + // No prompts, we only need to confirm. + pty.ExpectMatch("Confirm create?") + pty.WriteLine("yes") + }, + }, + { + name: "MisspelledParameter", + setup: func() []string { + // Provide the values on the command line. + args := []string{} + for i, param := range params { + if i == 0 { + // Slightly misspell the first parameter with an extra character. + args = append(args, "--parameter", fmt.Sprintf("n%s=%s", param.name, param.value)) + } else { + args = append(args, "--parameter", fmt.Sprintf("%s=%s", param.name, param.value)) + } + } + return args + }, + errors: []string{ + "parameter \"n" + params[0].name + "\" is not present in the template", + "Did you mean: " + params[0].name, + }, + }, + { + name: "ValuesFromWorkspace", + setup: func() []string { + // Provide the values on the command line. + args := []string{"-y"} + for _, param := range params { + args = append(args, "--parameter", fmt.Sprintf("%s=%s", param.name, param.value)) + } + return args + }, + postRun: func(t *testing.T, tctx testContext) string { + inv, root := clitest.New(t, "create", "--copy-parameters-from", tctx.workspaceName, "other-workspace", "-y") + clitest.SetupConfig(t, tctx.member, root) + pty := ptytest.New(t).Attach(inv) + inv.Stdout = pty.Output() + inv.Stderr = pty.Output() + err := inv.Run() + require.NoError(t, err, "failed to create a workspace based on the source workspace") + return "other-workspace" + }, + }, + { + name: "ValuesFromOutdatedWorkspace", + setup: func() []string { + // Provide the values on the command line. + args := []string{"-y"} + for _, param := range params { + args = append(args, "--parameter", fmt.Sprintf("%s=%s", param.name, param.value)) + } + return args + }, + postRun: func(t *testing.T, tctx testContext) string { + // Update the template to a new version. + version2 := coderdtest.CreateTemplateVersion(t, tctx.client, tctx.owner.OrganizationID, prepareEchoResponses([]*proto.RichParameter{ + {Name: "another_parameter", Type: "string", DefaultValue: "not-relevant"}, + }), func(ctvr *codersdk.CreateTemplateVersionRequest) { + ctvr.TemplateID = tctx.template.ID + }) + coderdtest.AwaitTemplateVersionJobCompleted(t, tctx.client, version2.ID) + coderdtest.UpdateActiveTemplateVersion(t, tctx.client, tctx.template.ID, version2.ID) - inv, root := clitest.New(t, "create", "my-workspace", "--template", template.Name) - 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) - }() + // Then create the copy. It should use the old template version. + inv, root := clitest.New(t, "create", "--copy-parameters-from", tctx.workspaceName, "other-workspace", "-y") + clitest.SetupConfig(t, tctx.member, root) + pty := ptytest.New(t).Attach(inv) + inv.Stdout = pty.Output() + inv.Stderr = pty.Output() + err := inv.Run() + require.NoError(t, err, "failed to create a workspace based on the source workspace") + return "other-workspace" + }, + }, + { + name: "ValuesFromTemplateDefaults", + handlePty: func(pty *ptytest.PTY) { + // Simply accept the defaults. + for _, param := range params { + pty.ExpectMatch(param.name) + pty.ExpectMatch(`Enter a value (default: "` + param.value + `")`) + pty.WriteLine("") + } + // Confirm the creation. + pty.ExpectMatch("Confirm create?") + pty.WriteLine("yes") + }, + withDefaults: true, + }, + { + name: "ValuesFromTemplateDefaultsNoPrompt", + setup: func() []string { + return []string{"--use-parameter-defaults"} + }, + handlePty: func(pty *ptytest.PTY) { + // Default values should get printed. + for _, param := range params { + pty.ExpectMatch(fmt.Sprintf("%s: '%s'", param.name, param.value)) + } + // No prompts, we only need to confirm. + pty.ExpectMatch("Confirm create?") + pty.WriteLine("yes") + }, + withDefaults: true, + }, + { + name: "ValuesFromDefaultFlagsNoPrompt", + setup: func() []string { + // Provide the defaults on the command line. + args := []string{"--use-parameter-defaults"} + for _, param := range params { + args = append(args, "--parameter-default", fmt.Sprintf("%s=%s", param.name, param.value)) + } + return args + }, + handlePty: func(pty *ptytest.PTY) { + // Default values should get printed. + for _, param := range params { + pty.ExpectMatch(fmt.Sprintf("%s: '%s'", param.name, param.value)) + } + // No prompts, we only need to confirm. + pty.ExpectMatch("Confirm create?") + pty.WriteLine("yes") + }, + }, + { + // File and flags should override template defaults. Additionally, if a + // value has no default value we should still get a prompt for it. + name: "ValuesFromMultipleSources", + setup: func() []string { + tempDir := t.TempDir() + removeTmpDirUntilSuccessAfterTest(t, tempDir) + parameterFile, _ := os.CreateTemp(tempDir, "testParameterFile*.yaml") + _, err := parameterFile.WriteString(` +file_param: from file +cli_param: from file`) + require.NoError(t, err) + return []string{ + "--use-parameter-defaults", + "--rich-parameter-file", parameterFile.Name(), + "--parameter-default", "file_param=from cli default", + "--parameter-default", "cli_param=from cli default", + "--parameter", "cli_param=from cli", + } + }, + handlePty: func(pty *ptytest.PTY) { + // Should get prompted for the input param since it has no default. + pty.ExpectMatch("input_param") + pty.WriteLine("from input") - matches := []string{ - firstParameterDescription, firstParameterValue, - secondParameterDisplayName, "", - secondParameterDescription, secondParameterValue, - immutableParameterDescription, immutableParameterValue, - "Confirm create?", "yes", - } - for i := 0; i < len(matches); i += 2 { - match := matches[i] - value := matches[i+1] - pty.ExpectMatch(match) + // Confirm the creation. + pty.ExpectMatch("Confirm create?") + pty.WriteLine("yes") + }, + withDefaults: true, + inputParameters: []param{ + { + name: "template_param", + value: "from template default", + }, + { + name: "file_param", + value: "from template default", + }, + { + name: "cli_param", + value: "from template default", + }, + { + name: "input_param", + }, + }, + expectedParameters: []param{ + { + name: "template_param", + value: "from template default", + }, + { + name: "file_param", + value: "from file", + }, + { + name: "cli_param", + value: "from cli", + }, + { + name: "input_param", + value: "from input", + }, + }, + }, + } - if value != "" { - pty.WriteLine(value) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + parameters := params + if len(tt.inputParameters) > 0 { + parameters = tt.inputParameters } - } - <-doneChan - }) - t.Run("ParametersDefaults", func(t *testing.T) { - t.Parallel() + // Convert parameters for the echo provisioner response. + var rparams []*proto.RichParameter + for i, param := range parameters { + defaultValue := "" + if tt.withDefaults { + defaultValue = param.value + } + rparams = append(rparams, &proto.RichParameter{ + Name: param.name, + Type: param.ptype, + Mutable: param.mutable, + DefaultValue: defaultValue, + Order: int32(i), //nolint:gosec + }) + } - 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) + // Set up the template. + 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, prepareEchoResponses(rparams)) - template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID) + 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) - }() + // Run the command, possibly setting up values. + workspaceName := "my-workspace" + args := []string{"create", workspaceName, "--template", template.Name} + if tt.setup != nil { + args = append(args, tt.setup()...) + } + inv, root := clitest.New(t, args...) + clitest.SetupConfig(t, member, root) + doneChan := make(chan error) + pty := ptytest.New(t).Attach(inv) + go func() { + doneChan <- inv.Run() + }() - matches := []string{ - firstParameterDescription, firstParameterValue, - secondParameterDescription, secondParameterValue, - immutableParameterDescription, immutableParameterValue, - } - for i := 0; i < len(matches); i += 2 { - match := matches[i] - defaultValue := matches[i+1] + // The test may do something with the pty. + if tt.handlePty != nil { + tt.handlePty(pty) + } - pty.ExpectMatch(match) - pty.ExpectMatch(`Enter a value (default: "` + defaultValue + `")`) - pty.WriteLine("") - } - pty.ExpectMatch("Confirm create?") - pty.WriteLine("yes") - <-doneChan + // Wait for the command to exit. + err := <-doneChan - // Verify that the expected default values were used. - ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort) - defer cancel() + // The test may want to run additional setup like copying the workspace. + if tt.postRun != nil { + workspaceName = tt.postRun(t, testContext{ + client: client, + member: member, + owner: owner, + template: template, + workspaceName: workspaceName, + }) + } - workspaces, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{ - Name: "my-workspace", + if len(tt.errors) > 0 { + require.Error(t, err) + for _, errstr := range tt.errors { + assert.ErrorContains(t, err, errstr) + } + } else { + require.NoError(t, err) + + // Verify the workspace was created and has the right template and values. + ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort) + defer cancel() + + workspaces, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{Name: workspaceName}) + require.NoError(t, err, "expected to find created workspace") + 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) + if len(tt.expectedParameters) > 0 { + parameters = tt.expectedParameters + } + require.Len(t, buildParameters, len(parameters)) + for _, param := range parameters { + require.Contains(t, buildParameters, codersdk.WorkspaceBuildParameter{Name: param.name, Value: param.value}) + } + } }) - 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() - - 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) - - tempDir := t.TempDir() - removeTmpDirUntilSuccessAfterTest(t, tempDir) - parameterFile, _ := os.CreateTemp(tempDir, "testParameterFile*.yaml") - _, _ = parameterFile.WriteString( - firstParameterName + ": " + firstParameterValue + "\n" + - secondParameterName + ": " + secondParameterValue + "\n" + - immutableParameterName + ": " + immutableParameterValue) - inv, root := clitest.New(t, "create", "my-workspace", "--template", template.Name, "--rich-parameter-file", parameterFile.Name()) - 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{ - "Confirm create?", "yes", - } - for i := 0; i < len(matches); i += 2 { - match := matches[i] - value := matches[i+1] - pty.ExpectMatch(match) - pty.WriteLine(value) - } - <-doneChan - }) - - t.Run("ParameterFlags", 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", fmt.Sprintf("%s=%s", firstParameterName, firstParameterValue), - "--parameter", fmt.Sprintf("%s=%s", secondParameterName, secondParameterValue), - "--parameter", 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{ - "Confirm create?", "yes", - } - for i := 0; i < len(matches); i += 2 { - match := matches[i] - value := matches[i+1] - pty.ExpectMatch(match) - pty.WriteLine(value) - } - <-doneChan - }) - - t.Run("WrongParameterName/DidYouMean", 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) - - wrongFirstParameterName := "frst-prameter" - inv, root := clitest.New(t, "create", "my-workspace", "--template", template.Name, - "--parameter", fmt.Sprintf("%s=%s", wrongFirstParameterName, firstParameterValue), - "--parameter", fmt.Sprintf("%s=%s", secondParameterName, secondParameterValue), - "--parameter", fmt.Sprintf("%s=%s", immutableParameterName, immutableParameterValue)) - clitest.SetupConfig(t, member, root) - pty := ptytest.New(t).Attach(inv) - inv.Stdout = pty.Output() - inv.Stderr = pty.Output() - err := inv.Run() - assert.ErrorContains(t, err, "parameter \""+wrongFirstParameterName+"\" is not present in the template") - assert.ErrorContains(t, err, "Did you mean: "+firstParameterName) - }) - - t.Run("CopyParameters", 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) - - // Firstly, create a regular workspace using template with parameters. - inv, root := clitest.New(t, "create", "my-workspace", "--template", template.Name, "-y", - "--parameter", fmt.Sprintf("%s=%s", firstParameterName, firstParameterValue), - "--parameter", fmt.Sprintf("%s=%s", secondParameterName, secondParameterValue), - "--parameter", fmt.Sprintf("%s=%s", immutableParameterName, immutableParameterValue)) - clitest.SetupConfig(t, member, root) - pty := ptytest.New(t).Attach(inv) - inv.Stdout = pty.Output() - inv.Stderr = pty.Output() - err := inv.Run() - require.NoError(t, err, "can't create first workspace") - - // Secondly, create a new workspace using parameters from the previous workspace. - const otherWorkspace = "other-workspace" - - inv, root = clitest.New(t, "create", "--copy-parameters-from", "my-workspace", otherWorkspace, "-y") - clitest.SetupConfig(t, member, root) - pty = ptytest.New(t).Attach(inv) - inv.Stdout = pty.Output() - inv.Stderr = pty.Output() - err = inv.Run() - require.NoError(t, err, "can't create a workspace based on the source workspace") - - // Verify if the new workspace uses expected parameters. - ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort) - defer cancel() - - workspaces, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{ - Name: otherWorkspace, - }) - require.NoError(t, err, "can't list available workspaces") - require.Len(t, workspaces.Workspaces, 1) - - otherWorkspaceLatestBuild := workspaces.Workspaces[0].LatestBuild - - buildParameters, err := client.WorkspaceBuildParameters(ctx, otherWorkspaceLatestBuild.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("CopyParametersFromNotUpdatedWorkspace", 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) - - // Firstly, create a regular workspace using template with parameters. - inv, root := clitest.New(t, "create", "my-workspace", "--template", template.Name, "-y", - "--parameter", fmt.Sprintf("%s=%s", firstParameterName, firstParameterValue), - "--parameter", fmt.Sprintf("%s=%s", secondParameterName, secondParameterValue), - "--parameter", fmt.Sprintf("%s=%s", immutableParameterName, immutableParameterValue)) - clitest.SetupConfig(t, member, root) - pty := ptytest.New(t).Attach(inv) - inv.Stdout = pty.Output() - inv.Stderr = pty.Output() - err := inv.Run() - require.NoError(t, err, "can't create first workspace") - - // Secondly, update the template to the newer version. - version2 := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, prepareEchoResponses([]*proto.RichParameter{ - {Name: "third_parameter", Type: "string", DefaultValue: "not-relevant"}, - }), func(ctvr *codersdk.CreateTemplateVersionRequest) { - ctvr.TemplateID = template.ID - }) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version2.ID) - coderdtest.UpdateActiveTemplateVersion(t, client, template.ID, version2.ID) - - // Thirdly, create a new workspace using parameters from the previous workspace. - const otherWorkspace = "other-workspace" - - inv, root = clitest.New(t, "create", "--copy-parameters-from", "my-workspace", otherWorkspace, "-y") - clitest.SetupConfig(t, member, root) - pty = ptytest.New(t).Attach(inv) - inv.Stdout = pty.Output() - inv.Stderr = pty.Output() - err = inv.Run() - require.NoError(t, err, "can't create a workspace based on the source workspace") - - // Verify if the new workspace uses expected parameters. - ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort) - defer cancel() - - workspaces, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{ - Name: otherWorkspace, - }) - require.NoError(t, err, "can't list available workspaces") - require.Len(t, workspaces.Workspaces, 1) - - otherWorkspaceLatestBuild := workspaces.Workspaces[0].LatestBuild - require.Equal(t, version.ID, otherWorkspaceLatestBuild.TemplateVersionID) - - buildParameters, err := client.WorkspaceBuildParameters(ctx, otherWorkspaceLatestBuild.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}) - }) + } } func TestCreateWithPreset(t *testing.T) { diff --git a/cli/parameterresolver.go b/cli/parameterresolver.go index cbd00fb596..aa239d85b6 100644 --- a/cli/parameterresolver.go +++ b/cli/parameterresolver.go @@ -34,6 +34,7 @@ type ParameterResolver struct { promptRichParameters bool promptEphemeralParameters bool + useParameterDefaults bool } func (pr *ParameterResolver) WithLastBuildParameters(params []codersdk.WorkspaceBuildParameter) *ParameterResolver { @@ -86,8 +87,21 @@ func (pr *ParameterResolver) WithPromptEphemeralParameters(promptEphemeralParame return pr } -// Resolve gathers workspace build parameters in a layered fashion, applying values from various sources -// in order of precedence: parameter file < CLI/ENV < source build < last build < preset < user input. +func (pr *ParameterResolver) WithUseParameterDefaults(useParameterDefaults bool) *ParameterResolver { + pr.useParameterDefaults = useParameterDefaults + return pr +} + +// Resolve gathers workspace build parameters in a layered fashion, applying +// values from various sources in order of precedence: +// 1. template defaults (if auto-accepting defaults) +// 2. cli parameter defaults (if auto-accepting defaults) +// 3. parameter file +// 4. CLI/ENV +// 5. source build +// 6. last build +// 7. preset +// 8. user input (unless auto-accepting defaults) func (pr *ParameterResolver) Resolve(inv *serpent.Invocation, action WorkspaceCLIAction, templateVersionParameters []codersdk.TemplateVersionParameter) ([]codersdk.WorkspaceBuildParameter, error) { var staged []codersdk.WorkspaceBuildParameter var err error @@ -262,9 +276,25 @@ 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, pr.richParametersDefaults) - if err != nil { - return nil, err + name := tvp.Name + if tvp.DisplayName != "" { + name = tvp.DisplayName + } + + parameterValue := tvp.DefaultValue + if v, ok := pr.richParametersDefaults[tvp.Name]; ok { + parameterValue = v + } + + // Auto-accept the default if there is one. + if pr.useParameterDefaults && parameterValue != "" { + _, _ = fmt.Fprintf(inv.Stdout, "Using default value for %s: '%s'\n", name, parameterValue) + } else { + var err error + parameterValue, err = cliui.RichParameter(inv, tvp, name, parameterValue) + if err != nil { + return nil, err + } } resolved = append(resolved, codersdk.WorkspaceBuildParameter{ diff --git a/cli/testdata/coder_autoupdate_--help.golden b/cli/testdata/coder_autoupdate_--help.golden index 96207daba5..04200fa58c 100644 --- a/cli/testdata/coder_autoupdate_--help.golden +++ b/cli/testdata/coder_autoupdate_--help.golden @@ -7,7 +7,7 @@ USAGE: OPTIONS: -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_config-ssh_--help.golden b/cli/testdata/coder_config-ssh_--help.golden index e2b03164d9..411e7607ff 100644 --- a/cli/testdata/coder_config-ssh_--help.golden +++ b/cli/testdata/coder_config-ssh_--help.golden @@ -55,7 +55,7 @@ OPTIONS: configured in the workspace template is used. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_create_--help.golden b/cli/testdata/coder_create_--help.golden index 47e809e8f5..1292af1777 100644 --- a/cli/testdata/coder_create_--help.golden +++ b/cli/testdata/coder_create_--help.golden @@ -49,8 +49,11 @@ OPTIONS: --template-version string, $CODER_TEMPLATE_VERSION Specify a template version name. + --use-parameter-defaults bool, $CODER_WORKSPACE_USE_PARAMETER_DEFAULTS + Automatically accept parameter defaults when no value is provided. + -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_delete_--help.golden b/cli/testdata/coder_delete_--help.golden index f9dfc9b9b9..d32acdd9c5 100644 --- a/cli/testdata/coder_delete_--help.golden +++ b/cli/testdata/coder_delete_--help.golden @@ -18,7 +18,7 @@ OPTIONS: resources. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_dotfiles_--help.golden b/cli/testdata/coder_dotfiles_--help.golden index 1499151212..1f62176089 100644 --- a/cli/testdata/coder_dotfiles_--help.golden +++ b/cli/testdata/coder_dotfiles_--help.golden @@ -24,7 +24,7 @@ OPTIONS: empty, will use $HOME. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_logout_--help.golden b/cli/testdata/coder_logout_--help.golden index 8ec08c2ad7..05b61005f4 100644 --- a/cli/testdata/coder_logout_--help.golden +++ b/cli/testdata/coder_logout_--help.golden @@ -7,7 +7,7 @@ USAGE: OPTIONS: -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_organizations_create_--help.golden b/cli/testdata/coder_organizations_create_--help.golden index 729ef373db..bb43fd6d65 100644 --- a/cli/testdata/coder_organizations_create_--help.golden +++ b/cli/testdata/coder_organizations_create_--help.golden @@ -7,7 +7,7 @@ USAGE: OPTIONS: -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_organizations_roles_create_--help.golden b/cli/testdata/coder_organizations_roles_create_--help.golden index fb38df9393..18d919d225 100644 --- a/cli/testdata/coder_organizations_roles_create_--help.golden +++ b/cli/testdata/coder_organizations_roles_create_--help.golden @@ -18,7 +18,7 @@ OPTIONS: Reads stdin for the json role definition to upload. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_organizations_roles_update_--help.golden b/cli/testdata/coder_organizations_roles_update_--help.golden index f0c28bd03d..a04767bcd7 100644 --- a/cli/testdata/coder_organizations_roles_update_--help.golden +++ b/cli/testdata/coder_organizations_roles_update_--help.golden @@ -23,7 +23,7 @@ OPTIONS: Reads stdin for the json role definition to upload. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_publickey_--help.golden b/cli/testdata/coder_publickey_--help.golden index 7346f89283..1c717d3e16 100644 --- a/cli/testdata/coder_publickey_--help.golden +++ b/cli/testdata/coder_publickey_--help.golden @@ -13,7 +13,7 @@ OPTIONS: services it's registered with. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_rename_--help.golden b/cli/testdata/coder_rename_--help.golden index 33f9c46000..b59f42f68b 100644 --- a/cli/testdata/coder_rename_--help.golden +++ b/cli/testdata/coder_rename_--help.golden @@ -7,7 +7,7 @@ USAGE: OPTIONS: -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_restart_--help.golden b/cli/testdata/coder_restart_--help.golden index 6208b73345..70c54104d9 100644 --- a/cli/testdata/coder_restart_--help.golden +++ b/cli/testdata/coder_restart_--help.golden @@ -39,7 +39,7 @@ OPTIONS: pairs for the parameters. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_start_--help.golden b/cli/testdata/coder_start_--help.golden index ce1134626c..096b94e74c 100644 --- a/cli/testdata/coder_start_--help.golden +++ b/cli/testdata/coder_start_--help.golden @@ -42,7 +42,7 @@ OPTIONS: pairs for the parameters. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_stop_--help.golden b/cli/testdata/coder_stop_--help.golden index 529c384846..fafa524bc9 100644 --- a/cli/testdata/coder_stop_--help.golden +++ b/cli/testdata/coder_stop_--help.golden @@ -7,7 +7,7 @@ USAGE: OPTIONS: -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_support_bundle_--help.golden b/cli/testdata/coder_support_bundle_--help.golden index 7b0a5bb18f..fd40548817 100644 --- a/cli/testdata/coder_support_bundle_--help.golden +++ b/cli/testdata/coder_support_bundle_--help.golden @@ -19,7 +19,7 @@ OPTIONS: example, if you need to troubleshoot a specific Coder replica. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_task_delete_--help.golden b/cli/testdata/coder_task_delete_--help.golden index b0169410a9..15bf1dce3a 100644 --- a/cli/testdata/coder_task_delete_--help.golden +++ b/cli/testdata/coder_task_delete_--help.golden @@ -21,7 +21,7 @@ USAGE: OPTIONS: -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_templates_archive_--help.golden b/cli/testdata/coder_templates_archive_--help.golden index ebad38db93..3e0ad40243 100644 --- a/cli/testdata/coder_templates_archive_--help.golden +++ b/cli/testdata/coder_templates_archive_--help.golden @@ -14,7 +14,7 @@ OPTIONS: versions are archived. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_templates_create_--help.golden b/cli/testdata/coder_templates_create_--help.golden index 80cccb24a5..c0370d93d2 100644 --- a/cli/testdata/coder_templates_create_--help.golden +++ b/cli/testdata/coder_templates_create_--help.golden @@ -68,7 +68,7 @@ OPTIONS: Specify a file path with values for Terraform-managed variables. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_templates_delete_--help.golden b/cli/testdata/coder_templates_delete_--help.golden index 4d15b7f343..557eef3539 100644 --- a/cli/testdata/coder_templates_delete_--help.golden +++ b/cli/testdata/coder_templates_delete_--help.golden @@ -12,7 +12,7 @@ OPTIONS: Select which organization (uuid or name) to use. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_templates_edit_--help.golden b/cli/testdata/coder_templates_edit_--help.golden index 76dee16cf9..baa7999604 100644 --- a/cli/testdata/coder_templates_edit_--help.golden +++ b/cli/testdata/coder_templates_edit_--help.golden @@ -91,7 +91,7 @@ OPTIONS: for more details. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_templates_pull_--help.golden b/cli/testdata/coder_templates_pull_--help.golden index 3a04c351f1..094f69994d 100644 --- a/cli/testdata/coder_templates_pull_--help.golden +++ b/cli/testdata/coder_templates_pull_--help.golden @@ -18,7 +18,7 @@ OPTIONS: the template version to pull. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. --zip bool Output the template as a zip archive to stdout. diff --git a/cli/testdata/coder_templates_push_--help.golden b/cli/testdata/coder_templates_push_--help.golden index edab61a3c5..1f1d7cdc42 100644 --- a/cli/testdata/coder_templates_push_--help.golden +++ b/cli/testdata/coder_templates_push_--help.golden @@ -48,7 +48,7 @@ OPTIONS: Specify a file path with values for Terraform-managed variables. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_templates_versions_archive_--help.golden b/cli/testdata/coder_templates_versions_archive_--help.golden index eae5a22ff3..ca79353671 100644 --- a/cli/testdata/coder_templates_versions_archive_--help.golden +++ b/cli/testdata/coder_templates_versions_archive_--help.golden @@ -11,7 +11,7 @@ OPTIONS: Select which organization (uuid or name) to use. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_templates_versions_unarchive_--help.golden b/cli/testdata/coder_templates_versions_unarchive_--help.golden index 6a641929fa..c1b381caf6 100644 --- a/cli/testdata/coder_templates_versions_unarchive_--help.golden +++ b/cli/testdata/coder_templates_versions_unarchive_--help.golden @@ -11,7 +11,7 @@ OPTIONS: Select which organization (uuid or name) to use. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/cli/testdata/coder_users_edit-roles_--help.golden b/cli/testdata/coder_users_edit-roles_--help.golden index 5a21c152e6..6af6e4fbef 100644 --- a/cli/testdata/coder_users_edit-roles_--help.golden +++ b/cli/testdata/coder_users_edit-roles_--help.golden @@ -11,7 +11,7 @@ OPTIONS: the user may have. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/docs/reference/cli/autoupdate.md b/docs/reference/cli/autoupdate.md index a025616e76..6446804c42 100644 --- a/docs/reference/cli/autoupdate.md +++ b/docs/reference/cli/autoupdate.md @@ -17,4 +17,4 @@ coder autoupdate [flags] |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. diff --git a/docs/reference/cli/config-ssh.md b/docs/reference/cli/config-ssh.md index 607aa86849..fbbf7ad61b 100644 --- a/docs/reference/cli/config-ssh.md +++ b/docs/reference/cli/config-ssh.md @@ -114,4 +114,4 @@ Disable starting the workspace automatically when connecting via SSH. |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. diff --git a/docs/reference/cli/create.md b/docs/reference/cli/create.md index d18b4ea5c8..c3a2cbe352 100644 --- a/docs/reference/cli/create.md +++ b/docs/reference/cli/create.md @@ -83,13 +83,22 @@ Specify automatic updates setting for the workspace (accepts 'always' or 'never' Specify the source workspace name to copy parameters from. +### --use-parameter-defaults + +| | | +|-------------|------------------------------------------------------| +| Type | bool | +| Environment | $CODER_WORKSPACE_USE_PARAMETER_DEFAULTS | + +Automatically accept parameter defaults when no value is provided. + ### -y, --yes | | | |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### --parameter diff --git a/docs/reference/cli/delete.md b/docs/reference/cli/delete.md index 9dc2ea6fa9..79d9401ccf 100644 --- a/docs/reference/cli/delete.md +++ b/docs/reference/cli/delete.md @@ -37,4 +37,4 @@ Delete a workspace without deleting its resources. This can delete a workspace i |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. diff --git a/docs/reference/cli/dotfiles.md b/docs/reference/cli/dotfiles.md index 57074497fe..81ef8386c6 100644 --- a/docs/reference/cli/dotfiles.md +++ b/docs/reference/cli/dotfiles.md @@ -52,4 +52,4 @@ Specifies the directory for the dotfiles repository, relative to global config d |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. diff --git a/docs/reference/cli/external-workspaces_create.md b/docs/reference/cli/external-workspaces_create.md index b0744387a1..6d1f21df8f 100644 --- a/docs/reference/cli/external-workspaces_create.md +++ b/docs/reference/cli/external-workspaces_create.md @@ -83,13 +83,22 @@ Specify automatic updates setting for the workspace (accepts 'always' or 'never' Specify the source workspace name to copy parameters from. +### --use-parameter-defaults + +| | | +|-------------|------------------------------------------------------| +| Type | bool | +| Environment | $CODER_WORKSPACE_USE_PARAMETER_DEFAULTS | + +Automatically accept parameter defaults when no value is provided. + ### -y, --yes | | | |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### --parameter diff --git a/docs/reference/cli/logout.md b/docs/reference/cli/logout.md index b35369ee36..a56ed9f52b 100644 --- a/docs/reference/cli/logout.md +++ b/docs/reference/cli/logout.md @@ -17,4 +17,4 @@ coder logout [flags] |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. diff --git a/docs/reference/cli/organizations_create.md b/docs/reference/cli/organizations_create.md index 14f40f55e0..414edd9488 100644 --- a/docs/reference/cli/organizations_create.md +++ b/docs/reference/cli/organizations_create.md @@ -17,4 +17,4 @@ coder organizations create [flags] |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. diff --git a/docs/reference/cli/organizations_roles_create.md b/docs/reference/cli/organizations_roles_create.md index 541584c06a..4a02babf36 100644 --- a/docs/reference/cli/organizations_roles_create.md +++ b/docs/reference/cli/organizations_roles_create.md @@ -25,7 +25,7 @@ coder organizations roles create [flags] |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### --dry-run diff --git a/docs/reference/cli/organizations_roles_update.md b/docs/reference/cli/organizations_roles_update.md index 7179617f76..9637f19cd8 100644 --- a/docs/reference/cli/organizations_roles_update.md +++ b/docs/reference/cli/organizations_roles_update.md @@ -25,7 +25,7 @@ coder organizations roles update [flags] |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### --dry-run diff --git a/docs/reference/cli/provisioner_keys_delete.md b/docs/reference/cli/provisioner_keys_delete.md index 4303491106..cbbbbb90c7 100644 --- a/docs/reference/cli/provisioner_keys_delete.md +++ b/docs/reference/cli/provisioner_keys_delete.md @@ -21,7 +21,7 @@ coder provisioner keys delete [flags] |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### -O, --org diff --git a/docs/reference/cli/publickey.md b/docs/reference/cli/publickey.md index ec68d813b1..557bdb7c9c 100644 --- a/docs/reference/cli/publickey.md +++ b/docs/reference/cli/publickey.md @@ -29,4 +29,4 @@ Regenerate your public key. This will require updating the key on any services i |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. diff --git a/docs/reference/cli/rename.md b/docs/reference/cli/rename.md index 511ccc60f8..11ffae03b5 100644 --- a/docs/reference/cli/rename.md +++ b/docs/reference/cli/rename.md @@ -17,4 +17,4 @@ coder rename [flags] |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. diff --git a/docs/reference/cli/restart.md b/docs/reference/cli/restart.md index 1c30e3e1ff..cc508dc1c8 100644 --- a/docs/reference/cli/restart.md +++ b/docs/reference/cli/restart.md @@ -17,7 +17,7 @@ coder restart [flags] |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### --build-option diff --git a/docs/reference/cli/server_dbcrypt_decrypt.md b/docs/reference/cli/server_dbcrypt_decrypt.md index 5126ef0fcc..a7e05b7fdd 100644 --- a/docs/reference/cli/server_dbcrypt_decrypt.md +++ b/docs/reference/cli/server_dbcrypt_decrypt.md @@ -45,4 +45,4 @@ Keys required to decrypt existing data. Must be a comma-separated list of base64 |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. diff --git a/docs/reference/cli/server_dbcrypt_delete.md b/docs/reference/cli/server_dbcrypt_delete.md index a5e7d16715..364386f2a8 100644 --- a/docs/reference/cli/server_dbcrypt_delete.md +++ b/docs/reference/cli/server_dbcrypt_delete.md @@ -40,4 +40,4 @@ Type of auth to use when connecting to postgres. |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. diff --git a/docs/reference/cli/server_dbcrypt_rotate.md b/docs/reference/cli/server_dbcrypt_rotate.md index 322a909a08..e2700c2631 100644 --- a/docs/reference/cli/server_dbcrypt_rotate.md +++ b/docs/reference/cli/server_dbcrypt_rotate.md @@ -54,4 +54,4 @@ The old external token encryption keys. Must be a comma-separated list of base64 |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. diff --git a/docs/reference/cli/start.md b/docs/reference/cli/start.md index 9f0f30cdfa..795057bf6f 100644 --- a/docs/reference/cli/start.md +++ b/docs/reference/cli/start.md @@ -25,7 +25,7 @@ Return immediately after starting the workspace. |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### --build-option diff --git a/docs/reference/cli/stop.md b/docs/reference/cli/stop.md index dba81c5cf7..a442448de4 100644 --- a/docs/reference/cli/stop.md +++ b/docs/reference/cli/stop.md @@ -17,4 +17,4 @@ coder stop [flags] |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. diff --git a/docs/reference/cli/support_bundle.md b/docs/reference/cli/support_bundle.md index 59b1fa4130..b6cf5ea6ac 100644 --- a/docs/reference/cli/support_bundle.md +++ b/docs/reference/cli/support_bundle.md @@ -23,7 +23,7 @@ This command generates a file containing detailed troubleshooting information ab |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### -O, --output-file diff --git a/docs/reference/cli/task_delete.md b/docs/reference/cli/task_delete.md index 0181ee0cea..2ab3e90b30 100644 --- a/docs/reference/cli/task_delete.md +++ b/docs/reference/cli/task_delete.md @@ -37,4 +37,4 @@ coder task delete [flags] [ ...] |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. diff --git a/docs/reference/cli/templates_archive.md b/docs/reference/cli/templates_archive.md index ef09707e5f..648568c9fe 100644 --- a/docs/reference/cli/templates_archive.md +++ b/docs/reference/cli/templates_archive.md @@ -17,7 +17,7 @@ coder templates archive [flags] [template-name...] |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### --all diff --git a/docs/reference/cli/templates_create.md b/docs/reference/cli/templates_create.md index cd3754e383..3f46f3e759 100644 --- a/docs/reference/cli/templates_create.md +++ b/docs/reference/cli/templates_create.md @@ -102,7 +102,7 @@ Requires workspace builds to use the active template version. This setting does |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### -O, --org diff --git a/docs/reference/cli/templates_delete.md b/docs/reference/cli/templates_delete.md index 9037a39d2b..45b15c5dcc 100644 --- a/docs/reference/cli/templates_delete.md +++ b/docs/reference/cli/templates_delete.md @@ -21,7 +21,7 @@ coder templates delete [flags] [name...] |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### -O, --org diff --git a/docs/reference/cli/templates_edit.md b/docs/reference/cli/templates_edit.md index 5d9f6f0a55..069e7d7a6b 100644 --- a/docs/reference/cli/templates_edit.md +++ b/docs/reference/cli/templates_edit.md @@ -169,7 +169,7 @@ Disable the default behavior of granting template access to the 'everyone' group |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### -O, --org diff --git a/docs/reference/cli/templates_pull.md b/docs/reference/cli/templates_pull.md index 529b110248..a5a4731807 100644 --- a/docs/reference/cli/templates_pull.md +++ b/docs/reference/cli/templates_pull.md @@ -41,7 +41,7 @@ The name of the template version to pull. Use 'active' to pull the active versio |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### -O, --org diff --git a/docs/reference/cli/templates_push.md b/docs/reference/cli/templates_push.md index 8c7901e86e..c27442f4f5 100644 --- a/docs/reference/cli/templates_push.md +++ b/docs/reference/cli/templates_push.md @@ -74,7 +74,7 @@ Whether the new template will be marked active. |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### -d, --directory diff --git a/docs/reference/cli/templates_versions_archive.md b/docs/reference/cli/templates_versions_archive.md index 1c7f4fd7d8..e4da6c4340 100644 --- a/docs/reference/cli/templates_versions_archive.md +++ b/docs/reference/cli/templates_versions_archive.md @@ -17,7 +17,7 @@ coder templates versions archive [flags] [template-version-names |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### -O, --org diff --git a/docs/reference/cli/templates_versions_unarchive.md b/docs/reference/cli/templates_versions_unarchive.md index c5351939bc..5013bda71a 100644 --- a/docs/reference/cli/templates_versions_unarchive.md +++ b/docs/reference/cli/templates_versions_unarchive.md @@ -17,7 +17,7 @@ coder templates versions unarchive [flags] [template-version-nam |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### -O, --org diff --git a/docs/reference/cli/users_edit-roles.md b/docs/reference/cli/users_edit-roles.md index 04f12ce701..2dda192e43 100644 --- a/docs/reference/cli/users_edit-roles.md +++ b/docs/reference/cli/users_edit-roles.md @@ -17,7 +17,7 @@ coder users edit-roles [flags] |------|-------------------| | Type | bool | -Bypass prompts. +Bypass confirmation prompts. ### --roles diff --git a/enterprise/cli/testdata/coder_external-workspaces_create_--help.golden b/enterprise/cli/testdata/coder_external-workspaces_create_--help.golden index 208d2cc229..9ec3834235 100644 --- a/enterprise/cli/testdata/coder_external-workspaces_create_--help.golden +++ b/enterprise/cli/testdata/coder_external-workspaces_create_--help.golden @@ -49,8 +49,11 @@ OPTIONS: --template-version string, $CODER_TEMPLATE_VERSION Specify a template version name. + --use-parameter-defaults bool, $CODER_WORKSPACE_USE_PARAMETER_DEFAULTS + Automatically accept parameter defaults when no value is provided. + -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_provisioner_keys_delete_--help.golden b/enterprise/cli/testdata/coder_provisioner_keys_delete_--help.golden index a8aea08c75..1aa538585a 100644 --- a/enterprise/cli/testdata/coder_provisioner_keys_delete_--help.golden +++ b/enterprise/cli/testdata/coder_provisioner_keys_delete_--help.golden @@ -12,7 +12,7 @@ OPTIONS: Select which organization (uuid or name) to use. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_server_dbcrypt_decrypt_--help.golden b/enterprise/cli/testdata/coder_server_dbcrypt_decrypt_--help.golden index 8f621ab10a..3618c3e881 100644 --- a/enterprise/cli/testdata/coder_server_dbcrypt_decrypt_--help.golden +++ b/enterprise/cli/testdata/coder_server_dbcrypt_decrypt_--help.golden @@ -17,7 +17,7 @@ OPTIONS: The connection URL for the Postgres database. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_server_dbcrypt_delete_--help.golden b/enterprise/cli/testdata/coder_server_dbcrypt_delete_--help.golden index 8d3eda851d..5b7325782d 100644 --- a/enterprise/cli/testdata/coder_server_dbcrypt_delete_--help.golden +++ b/enterprise/cli/testdata/coder_server_dbcrypt_delete_--help.golden @@ -15,7 +15,7 @@ OPTIONS: The connection URL for the Postgres database. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/enterprise/cli/testdata/coder_server_dbcrypt_rotate_--help.golden b/enterprise/cli/testdata/coder_server_dbcrypt_rotate_--help.golden index 5961ecebde..bd75ec9c82 100644 --- a/enterprise/cli/testdata/coder_server_dbcrypt_rotate_--help.golden +++ b/enterprise/cli/testdata/coder_server_dbcrypt_rotate_--help.golden @@ -20,7 +20,7 @@ OPTIONS: The connection URL for the Postgres database. -y, --yes bool - Bypass prompts. + Bypass confirmation prompts. ——— Run `coder --help` for a list of global options. diff --git a/provisioner/echo/serve.go b/provisioner/echo/serve.go index ced9f89586..f404b95825 100644 --- a/provisioner/echo/serve.go +++ b/provisioner/echo/serve.go @@ -660,7 +660,15 @@ data "coder_parameter" "{{ .Name }}" { ephemeral = {{ .Ephemeral }} order = {{ .Order }} {{- if .DefaultValue }} + {{- if eq .Type "list(string)" }} + default = jsonencode({{ .DefaultValue }}) + {{else if eq .Type "bool"}} default = {{ .DefaultValue }} + {{else if eq .Type "number"}} + default = {{ .DefaultValue }} + {{else}} + default = "{{ .DefaultValue }}" + {{- end }} {{- end }} {{- if .Type }} type = "{{ .Type }}"