mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
feat: add --use-parameter-defaults flag (#21119)
This is like `--yes`, but for parameter prompts.
This commit is contained in:
+2
-11
@@ -10,12 +10,8 @@ import (
|
|||||||
"github.com/coder/serpent"
|
"github.com/coder/serpent"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RichParameter(inv *serpent.Invocation, templateVersionParameter codersdk.TemplateVersionParameter, defaultOverrides map[string]string) (string, error) {
|
func RichParameter(inv *serpent.Invocation, templateVersionParameter codersdk.TemplateVersionParameter, name, defaultValue string) (string, error) {
|
||||||
label := templateVersionParameter.Name
|
label := name
|
||||||
if templateVersionParameter.DisplayName != "" {
|
|
||||||
label = templateVersionParameter.DisplayName
|
|
||||||
}
|
|
||||||
|
|
||||||
if templateVersionParameter.Ephemeral {
|
if templateVersionParameter.Ephemeral {
|
||||||
label += pretty.Sprint(DefaultStyles.Warn, " (build option)")
|
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")
|
_, _ = 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 err error
|
||||||
var value string
|
var value string
|
||||||
switch {
|
switch {
|
||||||
|
|||||||
+2
-2
@@ -32,12 +32,12 @@ type PromptOptions struct {
|
|||||||
const skipPromptFlag = "yes"
|
const skipPromptFlag = "yes"
|
||||||
|
|
||||||
// SkipPromptOption adds a "--yes/-y" flag to the cmd that can be used to skip
|
// SkipPromptOption adds a "--yes/-y" flag to the cmd that can be used to skip
|
||||||
// prompts.
|
// confirmation prompts.
|
||||||
func SkipPromptOption() serpent.Option {
|
func SkipPromptOption() serpent.Option {
|
||||||
return serpent.Option{
|
return serpent.Option{
|
||||||
Flag: skipPromptFlag,
|
Flag: skipPromptFlag,
|
||||||
FlagShorthand: "y",
|
FlagShorthand: "y",
|
||||||
Description: "Bypass prompts.",
|
Description: "Bypass confirmation prompts.",
|
||||||
// Discard
|
// Discard
|
||||||
Value: serpent.BoolOf(new(bool)),
|
Value: serpent.BoolOf(new(bool)),
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-2
@@ -45,6 +45,7 @@ func (r *RootCmd) Create(opts CreateOptions) *serpent.Command {
|
|||||||
parameterFlags workspaceParameterFlags
|
parameterFlags workspaceParameterFlags
|
||||||
autoUpdates string
|
autoUpdates string
|
||||||
copyParametersFrom string
|
copyParametersFrom string
|
||||||
|
useParameterDefaults bool
|
||||||
// Organization context is only required if more than 1 template
|
// Organization context is only required if more than 1 template
|
||||||
// shares the same name across multiple organizations.
|
// shares the same name across multiple organizations.
|
||||||
orgContext = NewOrganizationContext()
|
orgContext = NewOrganizationContext()
|
||||||
@@ -308,7 +309,7 @@ func (r *RootCmd) Create(opts CreateOptions) *serpent.Command {
|
|||||||
displayAppliedPreset(inv, preset, presetParameters)
|
displayAppliedPreset(inv, preset, presetParameters)
|
||||||
} else {
|
} else {
|
||||||
// Inform the user that no preset was applied
|
// 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 {
|
if opts.BeforeCreate != nil {
|
||||||
@@ -329,6 +330,8 @@ func (r *RootCmd) Create(opts CreateOptions) *serpent.Command {
|
|||||||
RichParameterDefaults: cliBuildParameterDefaults,
|
RichParameterDefaults: cliBuildParameterDefaults,
|
||||||
|
|
||||||
SourceWorkspaceParameters: sourceWorkspaceParameters,
|
SourceWorkspaceParameters: sourceWorkspaceParameters,
|
||||||
|
|
||||||
|
UseParameterDefaults: useParameterDefaults,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("prepare build: %w", err)
|
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.",
|
Description: "Specify the source workspace name to copy parameters from.",
|
||||||
Value: serpent.StringOf(©ParametersFrom),
|
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(),
|
cliui.SkipPromptOption(),
|
||||||
)
|
)
|
||||||
cmd.Options = append(cmd.Options, parameterFlags.cliParameters()...)
|
cmd.Options = append(cmd.Options, parameterFlags.cliParameters()...)
|
||||||
@@ -459,6 +468,8 @@ type prepWorkspaceBuildArgs struct {
|
|||||||
RichParameters []codersdk.WorkspaceBuildParameter
|
RichParameters []codersdk.WorkspaceBuildParameter
|
||||||
RichParameterFile string
|
RichParameterFile string
|
||||||
RichParameterDefaults []codersdk.WorkspaceBuildParameter
|
RichParameterDefaults []codersdk.WorkspaceBuildParameter
|
||||||
|
|
||||||
|
UseParameterDefaults bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolvePreset returns the preset matching the given presetName (if specified),
|
// 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).
|
WithPromptRichParameters(args.PromptRichParameters).
|
||||||
WithRichParameters(args.RichParameters).
|
WithRichParameters(args.RichParameters).
|
||||||
WithRichParametersFile(parameterFile).
|
WithRichParametersFile(parameterFile).
|
||||||
WithRichParametersDefaults(args.RichParameterDefaults)
|
WithRichParametersDefaults(args.RichParameterDefaults).
|
||||||
|
WithUseParameterDefaults(args.UseParameterDefaults)
|
||||||
buildParameters, err := resolver.Resolve(inv, args.Action, templateVersionParameters)
|
buildParameters, err := resolver.Resolve(inv, args.Action, templateVersionParameters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
+406
-322
@@ -318,121 +318,420 @@ func prepareEchoResponses(parameters []*proto.RichParameter, presets ...*proto.P
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type param struct {
|
||||||
|
name string
|
||||||
|
ptype string
|
||||||
|
value string
|
||||||
|
mutable bool
|
||||||
|
}
|
||||||
|
|
||||||
func TestCreateWithRichParameters(t *testing.T) {
|
func TestCreateWithRichParameters(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
const (
|
// Default parameters and their expected values.
|
||||||
firstParameterName = "first_parameter"
|
params := []param{
|
||||||
firstParameterDescription = "This is first parameter"
|
{
|
||||||
firstParameterValue = "1"
|
name: "number_param",
|
||||||
|
ptype: "number",
|
||||||
secondParameterName = "second_parameter"
|
value: "777",
|
||||||
secondParameterDisplayName = "Second Parameter"
|
mutable: true,
|
||||||
secondParameterDescription = "This is second parameter"
|
},
|
||||||
secondParameterValue = "2"
|
{
|
||||||
|
name: "string_param",
|
||||||
immutableParameterName = "third_parameter"
|
ptype: "string",
|
||||||
immutableParameterDescription = "This is not mutable parameter"
|
value: "qux",
|
||||||
immutableParameterValue = "4"
|
mutable: true,
|
||||||
)
|
},
|
||||||
|
{
|
||||||
echoResponses := func() *echo.Responses {
|
name: "bool_param",
|
||||||
return prepareEchoResponses([]*proto.RichParameter{
|
// TODO: Setting the type breaks booleans. It claims the default is false
|
||||||
{Name: firstParameterName, Description: firstParameterDescription, Mutable: true},
|
// but when you then accept this default it errors saying that the value
|
||||||
{Name: secondParameterName, DisplayName: secondParameterDisplayName, Description: secondParameterDescription, Mutable: true},
|
// must be true or false. For now, use a string.
|
||||||
{Name: immutableParameterName, Description: immutableParameterDescription, Mutable: false},
|
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) {
|
type testContext struct {
|
||||||
t.Parallel()
|
client *codersdk.Client
|
||||||
|
member *codersdk.Client
|
||||||
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
owner codersdk.CreateFirstUserResponse
|
||||||
owner := coderdtest.CreateFirstUser(t, client)
|
template codersdk.Template
|
||||||
member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
|
workspaceName string
|
||||||
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)
|
|
||||||
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,
|
|
||||||
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)
|
|
||||||
|
|
||||||
if value != "" {
|
tests := []struct {
|
||||||
pty.WriteLine(value)
|
name string
|
||||||
}
|
// setup runs before the command is started and return arguments that will
|
||||||
}
|
// be appended to the create command.
|
||||||
<-doneChan
|
setup func() []string
|
||||||
})
|
// handlePty optionally runs after the command is started. It should handle
|
||||||
|
// all expected prompts from the pty.
|
||||||
t.Run("ParametersDefaults", func(t *testing.T) {
|
handlePty func(pty *ptytest.PTY)
|
||||||
t.Parallel()
|
// 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
|
||||||
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
// workspace tests).
|
||||||
owner := coderdtest.CreateFirstUser(t, client)
|
postRun func(t *testing.T, args testContext) string
|
||||||
member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
|
// errors contains expected errors. The workspace will not be verified if
|
||||||
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, echoResponses())
|
// errors are expected.
|
||||||
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
errors []string
|
||||||
|
// inputParameters overrides the default parameters.
|
||||||
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
|
inputParameters []param
|
||||||
|
// expectedParameters defaults to inputParameters.
|
||||||
inv, root := clitest.New(t, "create", "my-workspace", "--template", template.Name,
|
expectedParameters []param
|
||||||
"--parameter-default", fmt.Sprintf("%s=%s", firstParameterName, firstParameterValue),
|
// withDefaults sets DefaultValue to each parameter's value.
|
||||||
"--parameter-default", fmt.Sprintf("%s=%s", secondParameterName, secondParameterValue),
|
withDefaults bool
|
||||||
"--parameter-default", fmt.Sprintf("%s=%s", immutableParameterName, immutableParameterValue))
|
}{
|
||||||
clitest.SetupConfig(t, member, root)
|
{
|
||||||
doneChan := make(chan struct{})
|
name: "ValuesFromPrompt",
|
||||||
pty := ptytest.New(t).Attach(inv)
|
handlePty: func(pty *ptytest.PTY) {
|
||||||
go func() {
|
// Enter the value for each parameter as prompted.
|
||||||
defer close(doneChan)
|
for _, param := range params {
|
||||||
err := inv.Run()
|
pty.ExpectMatch(param.name)
|
||||||
assert.NoError(t, err)
|
pty.WriteLine(param.value)
|
||||||
}()
|
|
||||||
|
|
||||||
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("")
|
|
||||||
}
|
}
|
||||||
|
// Confirm the creation.
|
||||||
pty.ExpectMatch("Confirm create?")
|
pty.ExpectMatch("Confirm create?")
|
||||||
pty.WriteLine("yes")
|
pty.WriteLine("yes")
|
||||||
<-doneChan
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
// Verify that the expected default values were used.
|
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)
|
||||||
|
|
||||||
|
// 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")
|
||||||
|
|
||||||
|
// 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",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
parameters := params
|
||||||
|
if len(tt.inputParameters) > 0 {
|
||||||
|
parameters = tt.inputParameters
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
|
||||||
|
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
||||||
|
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// The test may do something with the pty.
|
||||||
|
if tt.handlePty != nil {
|
||||||
|
tt.handlePty(pty)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the command to exit.
|
||||||
|
err := <-doneChan
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
workspaces, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{
|
workspaces, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{Name: workspaceName})
|
||||||
Name: "my-workspace",
|
require.NoError(t, err, "expected to find created workspace")
|
||||||
})
|
|
||||||
require.NoError(t, err, "can't list available workspaces")
|
|
||||||
require.Len(t, workspaces.Workspaces, 1)
|
require.Len(t, workspaces.Workspaces, 1)
|
||||||
|
|
||||||
workspaceLatestBuild := workspaces.Workspaces[0].LatestBuild
|
workspaceLatestBuild := workspaces.Workspaces[0].LatestBuild
|
||||||
@@ -440,231 +739,16 @@ func TestCreateWithRichParameters(t *testing.T) {
|
|||||||
|
|
||||||
buildParameters, err := client.WorkspaceBuildParameters(ctx, workspaceLatestBuild.ID)
|
buildParameters, err := client.WorkspaceBuildParameters(ctx, workspaceLatestBuild.ID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, buildParameters, 3)
|
if len(tt.expectedParameters) > 0 {
|
||||||
require.Contains(t, buildParameters, codersdk.WorkspaceBuildParameter{Name: firstParameterName, Value: firstParameterValue})
|
parameters = tt.expectedParameters
|
||||||
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 {
|
require.Len(t, buildParameters, len(parameters))
|
||||||
match := matches[i]
|
for _, param := range parameters {
|
||||||
value := matches[i+1]
|
require.Contains(t, buildParameters, codersdk.WorkspaceBuildParameter{Name: param.name, Value: param.value})
|
||||||
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) {
|
func TestCreateWithPreset(t *testing.T) {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ type ParameterResolver struct {
|
|||||||
|
|
||||||
promptRichParameters bool
|
promptRichParameters bool
|
||||||
promptEphemeralParameters bool
|
promptEphemeralParameters bool
|
||||||
|
useParameterDefaults bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pr *ParameterResolver) WithLastBuildParameters(params []codersdk.WorkspaceBuildParameter) *ParameterResolver {
|
func (pr *ParameterResolver) WithLastBuildParameters(params []codersdk.WorkspaceBuildParameter) *ParameterResolver {
|
||||||
@@ -86,8 +87,21 @@ func (pr *ParameterResolver) WithPromptEphemeralParameters(promptEphemeralParame
|
|||||||
return pr
|
return pr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve gathers workspace build parameters in a layered fashion, applying values from various sources
|
func (pr *ParameterResolver) WithUseParameterDefaults(useParameterDefaults bool) *ParameterResolver {
|
||||||
// in order of precedence: parameter file < CLI/ENV < source build < last build < preset < user input.
|
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) {
|
func (pr *ParameterResolver) Resolve(inv *serpent.Invocation, action WorkspaceCLIAction, templateVersionParameters []codersdk.TemplateVersionParameter) ([]codersdk.WorkspaceBuildParameter, error) {
|
||||||
var staged []codersdk.WorkspaceBuildParameter
|
var staged []codersdk.WorkspaceBuildParameter
|
||||||
var err error
|
var err error
|
||||||
@@ -262,10 +276,26 @@ func (pr *ParameterResolver) resolveWithInput(resolved []codersdk.WorkspaceBuild
|
|||||||
(action == WorkspaceUpdate && tvp.Mutable && tvp.Required) ||
|
(action == WorkspaceUpdate && tvp.Mutable && tvp.Required) ||
|
||||||
(action == WorkspaceUpdate && !tvp.Mutable && firstTimeUse) ||
|
(action == WorkspaceUpdate && !tvp.Mutable && firstTimeUse) ||
|
||||||
(tvp.Mutable && !tvp.Ephemeral && pr.promptRichParameters) {
|
(tvp.Mutable && !tvp.Ephemeral && pr.promptRichParameters) {
|
||||||
parameterValue, err := cliui.RichParameter(inv, tvp, pr.richParametersDefaults)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resolved = append(resolved, codersdk.WorkspaceBuildParameter{
|
resolved = append(resolved, codersdk.WorkspaceBuildParameter{
|
||||||
Name: tvp.Name,
|
Name: tvp.Name,
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ USAGE:
|
|||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -55,7 +55,7 @@ OPTIONS:
|
|||||||
configured in the workspace template is used.
|
configured in the workspace template is used.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+4
-1
@@ -49,8 +49,11 @@ OPTIONS:
|
|||||||
--template-version string, $CODER_TEMPLATE_VERSION
|
--template-version string, $CODER_TEMPLATE_VERSION
|
||||||
Specify a template version name.
|
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
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ OPTIONS:
|
|||||||
resources.
|
resources.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ OPTIONS:
|
|||||||
empty, will use $HOME.
|
empty, will use $HOME.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ USAGE:
|
|||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ USAGE:
|
|||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ OPTIONS:
|
|||||||
Reads stdin for the json role definition to upload.
|
Reads stdin for the json role definition to upload.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ OPTIONS:
|
|||||||
Reads stdin for the json role definition to upload.
|
Reads stdin for the json role definition to upload.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ OPTIONS:
|
|||||||
services it's registered with.
|
services it's registered with.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ USAGE:
|
|||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -39,7 +39,7 @@ OPTIONS:
|
|||||||
pairs for the parameters.
|
pairs for the parameters.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -42,7 +42,7 @@ OPTIONS:
|
|||||||
pairs for the parameters.
|
pairs for the parameters.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ USAGE:
|
|||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ OPTIONS:
|
|||||||
example, if you need to troubleshoot a specific Coder replica.
|
example, if you need to troubleshoot a specific Coder replica.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ USAGE:
|
|||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ OPTIONS:
|
|||||||
versions are archived.
|
versions are archived.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -68,7 +68,7 @@ OPTIONS:
|
|||||||
Specify a file path with values for Terraform-managed variables.
|
Specify a file path with values for Terraform-managed variables.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ OPTIONS:
|
|||||||
Select which organization (uuid or name) to use.
|
Select which organization (uuid or name) to use.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -91,7 +91,7 @@ OPTIONS:
|
|||||||
for more details.
|
for more details.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ OPTIONS:
|
|||||||
the template version to pull.
|
the template version to pull.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
--zip bool
|
--zip bool
|
||||||
Output the template as a zip archive to stdout.
|
Output the template as a zip archive to stdout.
|
||||||
|
|||||||
+1
-1
@@ -48,7 +48,7 @@ OPTIONS:
|
|||||||
Specify a file path with values for Terraform-managed variables.
|
Specify a file path with values for Terraform-managed variables.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ OPTIONS:
|
|||||||
Select which organization (uuid or name) to use.
|
Select which organization (uuid or name) to use.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ OPTIONS:
|
|||||||
Select which organization (uuid or name) to use.
|
Select which organization (uuid or name) to use.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ OPTIONS:
|
|||||||
the user may have.
|
the user may have.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
Generated
+1
-1
@@ -17,4 +17,4 @@ coder autoupdate [flags] <workspace> <always|never>
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|||||||
Generated
+1
-1
@@ -114,4 +114,4 @@ Disable starting the workspace automatically when connecting via SSH.
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|||||||
Generated
+10
-1
@@ -83,13 +83,22 @@ Specify automatic updates setting for the workspace (accepts 'always' or 'never'
|
|||||||
|
|
||||||
Specify the source workspace name to copy parameters from.
|
Specify the source workspace name to copy parameters from.
|
||||||
|
|
||||||
|
### --use-parameter-defaults
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|-------------|------------------------------------------------------|
|
||||||
|
| Type | <code>bool</code> |
|
||||||
|
| Environment | <code>$CODER_WORKSPACE_USE_PARAMETER_DEFAULTS</code> |
|
||||||
|
|
||||||
|
Automatically accept parameter defaults when no value is provided.
|
||||||
|
|
||||||
### -y, --yes
|
### -y, --yes
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### --parameter
|
### --parameter
|
||||||
|
|
||||||
|
|||||||
Generated
+1
-1
@@ -37,4 +37,4 @@ Delete a workspace without deleting its resources. This can delete a workspace i
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|||||||
Generated
+1
-1
@@ -52,4 +52,4 @@ Specifies the directory for the dotfiles repository, relative to global config d
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|||||||
+10
-1
@@ -83,13 +83,22 @@ Specify automatic updates setting for the workspace (accepts 'always' or 'never'
|
|||||||
|
|
||||||
Specify the source workspace name to copy parameters from.
|
Specify the source workspace name to copy parameters from.
|
||||||
|
|
||||||
|
### --use-parameter-defaults
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|-------------|------------------------------------------------------|
|
||||||
|
| Type | <code>bool</code> |
|
||||||
|
| Environment | <code>$CODER_WORKSPACE_USE_PARAMETER_DEFAULTS</code> |
|
||||||
|
|
||||||
|
Automatically accept parameter defaults when no value is provided.
|
||||||
|
|
||||||
### -y, --yes
|
### -y, --yes
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### --parameter
|
### --parameter
|
||||||
|
|
||||||
|
|||||||
Generated
+1
-1
@@ -17,4 +17,4 @@ coder logout [flags]
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|||||||
+1
-1
@@ -17,4 +17,4 @@ coder organizations create [flags] <organization name>
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ coder organizations roles create [flags] <role_name>
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### --dry-run
|
### --dry-run
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ coder organizations roles update [flags] <role_name>
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### --dry-run
|
### --dry-run
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ coder provisioner keys delete [flags] <name>
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### -O, --org
|
### -O, --org
|
||||||
|
|
||||||
|
|||||||
Generated
+1
-1
@@ -29,4 +29,4 @@ Regenerate your public key. This will require updating the key on any services i
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|||||||
Generated
+1
-1
@@ -17,4 +17,4 @@ coder rename [flags] <workspace> <new name>
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|||||||
Generated
+1
-1
@@ -17,7 +17,7 @@ coder restart [flags] <workspace>
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### --build-option
|
### --build-option
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -45,4 +45,4 @@ Keys required to decrypt existing data. Must be a comma-separated list of base64
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|||||||
+1
-1
@@ -40,4 +40,4 @@ Type of auth to use when connecting to postgres.
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|||||||
+1
-1
@@ -54,4 +54,4 @@ The old external token encryption keys. Must be a comma-separated list of base64
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|||||||
Generated
+1
-1
@@ -25,7 +25,7 @@ Return immediately after starting the workspace.
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### --build-option
|
### --build-option
|
||||||
|
|
||||||
|
|||||||
Generated
+1
-1
@@ -17,4 +17,4 @@ coder stop [flags] <workspace>
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|||||||
Generated
+1
-1
@@ -23,7 +23,7 @@ This command generates a file containing detailed troubleshooting information ab
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### -O, --output-file
|
### -O, --output-file
|
||||||
|
|
||||||
|
|||||||
Generated
+1
-1
@@ -37,4 +37,4 @@ coder task delete [flags] <task> [<task> ...]
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|||||||
Generated
+1
-1
@@ -17,7 +17,7 @@ coder templates archive [flags] [template-name...]
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### --all
|
### --all
|
||||||
|
|
||||||
|
|||||||
Generated
+1
-1
@@ -102,7 +102,7 @@ Requires workspace builds to use the active template version. This setting does
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### -O, --org
|
### -O, --org
|
||||||
|
|
||||||
|
|||||||
Generated
+1
-1
@@ -21,7 +21,7 @@ coder templates delete [flags] [name...]
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### -O, --org
|
### -O, --org
|
||||||
|
|
||||||
|
|||||||
Generated
+1
-1
@@ -169,7 +169,7 @@ Disable the default behavior of granting template access to the 'everyone' group
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### -O, --org
|
### -O, --org
|
||||||
|
|
||||||
|
|||||||
Generated
+1
-1
@@ -41,7 +41,7 @@ The name of the template version to pull. Use 'active' to pull the active versio
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### -O, --org
|
### -O, --org
|
||||||
|
|
||||||
|
|||||||
Generated
+1
-1
@@ -74,7 +74,7 @@ Whether the new template will be marked active.
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### -d, --directory
|
### -d, --directory
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@ coder templates versions archive [flags] <template-name> [template-version-names
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### -O, --org
|
### -O, --org
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@ coder templates versions unarchive [flags] <template-name> [template-version-nam
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### -O, --org
|
### -O, --org
|
||||||
|
|
||||||
|
|||||||
Generated
+1
-1
@@ -17,7 +17,7 @@ coder users edit-roles [flags] <username|user_id>
|
|||||||
|------|-------------------|
|
|------|-------------------|
|
||||||
| Type | <code>bool</code> |
|
| Type | <code>bool</code> |
|
||||||
|
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
### --roles
|
### --roles
|
||||||
|
|
||||||
|
|||||||
@@ -49,8 +49,11 @@ OPTIONS:
|
|||||||
--template-version string, $CODER_TEMPLATE_VERSION
|
--template-version string, $CODER_TEMPLATE_VERSION
|
||||||
Specify a template version name.
|
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
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ OPTIONS:
|
|||||||
Select which organization (uuid or name) to use.
|
Select which organization (uuid or name) to use.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ OPTIONS:
|
|||||||
The connection URL for the Postgres database.
|
The connection URL for the Postgres database.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ OPTIONS:
|
|||||||
The connection URL for the Postgres database.
|
The connection URL for the Postgres database.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ OPTIONS:
|
|||||||
The connection URL for the Postgres database.
|
The connection URL for the Postgres database.
|
||||||
|
|
||||||
-y, --yes bool
|
-y, --yes bool
|
||||||
Bypass prompts.
|
Bypass confirmation prompts.
|
||||||
|
|
||||||
———
|
———
|
||||||
Run `coder --help` for a list of global options.
|
Run `coder --help` for a list of global options.
|
||||||
|
|||||||
@@ -660,7 +660,15 @@ data "coder_parameter" "{{ .Name }}" {
|
|||||||
ephemeral = {{ .Ephemeral }}
|
ephemeral = {{ .Ephemeral }}
|
||||||
order = {{ .Order }}
|
order = {{ .Order }}
|
||||||
{{- if .DefaultValue }}
|
{{- if .DefaultValue }}
|
||||||
|
{{- if eq .Type "list(string)" }}
|
||||||
|
default = jsonencode({{ .DefaultValue }})
|
||||||
|
{{else if eq .Type "bool"}}
|
||||||
default = {{ .DefaultValue }}
|
default = {{ .DefaultValue }}
|
||||||
|
{{else if eq .Type "number"}}
|
||||||
|
default = {{ .DefaultValue }}
|
||||||
|
{{else}}
|
||||||
|
default = "{{ .DefaultValue }}"
|
||||||
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Type }}
|
{{- if .Type }}
|
||||||
type = "{{ .Type }}"
|
type = "{{ .Type }}"
|
||||||
|
|||||||
Reference in New Issue
Block a user