- Notifications
You must be signed in to change notification settings - Fork948
feat(cli): add CLI support for creating a workspace with preset#18912
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
Changes fromall commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -21,10 +21,15 @@ import ( | ||
"github.com/coder/serpent" | ||
) | ||
// DefaultPresetName is used when a user runs `create --preset default`. | ||
// It instructs the CLI to use the default preset defined for the template version, if one exists. | ||
const DefaultPresetName = "default" | ||
ContributorAuthor
| ||
func (r *RootCmd) create() *serpent.Command { | ||
var ( | ||
templateName string | ||
templateVersion string | ||
presetName string | ||
startAt string | ||
stopAfter time.Duration | ||
workspaceName string | ||
@@ -263,11 +268,58 @@ func (r *RootCmd) create() *serpent.Command { | ||
} | ||
} | ||
// If a preset name is provided, resolve the preset to use. | ||
var preset *codersdk.Preset | ||
var presetParameters []codersdk.WorkspaceBuildParameter | ||
isDefaultPreset := false | ||
if len(presetName) > 0 { | ||
tvPresets, err := client.TemplateVersionPresets(inv.Context(), templateVersionID) | ||
if err != nil { | ||
return xerrors.Errorf("failed to get presets: %w", err) | ||
} | ||
for _, tvPreset := range tvPresets { | ||
// If the preset name is the special "default" keyword, | ||
// fetch the template version's default preset (if any). | ||
if presetName == DefaultPresetName && tvPreset.Default { | ||
preset = &tvPreset | ||
isDefaultPreset = true | ||
break | ||
} | ||
if tvPreset.Name == presetName { | ||
preset = &tvPreset | ||
break | ||
} | ||
} | ||
if preset == nil { | ||
return xerrors.Errorf("preset %q not found", presetName) | ||
} | ||
// Convert preset parameters into workspace build parameters. | ||
presetBuildParameters, err := presetParameterAsWorkspaceBuildParameters(preset.Parameters) | ||
if err != nil { | ||
return xerrors.Errorf("failed to parse preset parameters: %w", err) | ||
} | ||
presetParameters = append(presetParameters, presetBuildParameters...) | ||
// Inform the user which preset was applied and its parameters. | ||
presetLabel := fmt.Sprintf("Preset '%s'", preset.Name) | ||
if isDefaultPreset { | ||
presetLabel += " (default)" | ||
} | ||
_, _ = fmt.Fprintf(inv.Stdout, "%s applied:", cliui.Bold(presetLabel)) | ||
for _, p := range presetParameters { | ||
_, _ = fmt.Fprintf(inv.Stdout, " %s: '%s'\n", cliui.Bold(p.Name), p.Value) | ||
} | ||
} | ||
richParameters, err := prepWorkspaceBuild(inv, client, prepWorkspaceBuildArgs{ | ||
Action: WorkspaceCreate, | ||
TemplateVersionID: templateVersionID, | ||
NewWorkspaceName: workspaceName, | ||
PresetParameters: presetParameters, | ||
RichParameterFile: parameterFlags.richParameterFile, | ||
RichParameters: cliBuildParameters, | ||
RichParameterDefaults: cliBuildParameterDefaults, | ||
@@ -291,14 +343,21 @@ func (r *RootCmd) create() *serpent.Command { | ||
ttlMillis = ptr.Ref(stopAfter.Milliseconds()) | ||
} | ||
req := codersdk.CreateWorkspaceRequest{ | ||
TemplateVersionID: templateVersionID, | ||
Name: workspaceName, | ||
AutostartSchedule: schedSpec, | ||
TTLMillis: ttlMillis, | ||
RichParameterValues: richParameters, | ||
AutomaticUpdates: codersdk.AutomaticUpdates(autoUpdates), | ||
} | ||
// If a preset exists, update the create workspace request's preset ID | ||
if preset != nil { | ||
req.TemplateVersionPresetID = preset.ID | ||
} | ||
workspace, err := client.CreateUserWorkspace(inv.Context(), workspaceOwner, req) | ||
if err != nil { | ||
return xerrors.Errorf("create workspace: %w", err) | ||
} | ||
@@ -333,6 +392,12 @@ func (r *RootCmd) create() *serpent.Command { | ||
Description: "Specify a template version name.", | ||
Value: serpent.StringOf(&templateVersion), | ||
}, | ||
serpent.Option{ | ||
Flag: "preset", | ||
Env: "CODER_PRESET_NAME", | ||
Description: "Specify a template version preset name. Use 'default' to apply the default preset defined in the template version, if available.", | ||
Value: serpent.StringOf(&presetName), | ||
}, | ||
serpent.Option{ | ||
Flag: "start-at", | ||
Env: "CODER_WORKSPACE_START_AT", | ||
@@ -377,6 +442,7 @@ type prepWorkspaceBuildArgs struct { | ||
PromptEphemeralParameters bool | ||
EphemeralParameters []codersdk.WorkspaceBuildParameter | ||
PresetParameters []codersdk.WorkspaceBuildParameter | ||
PromptRichParameters bool | ||
RichParameters []codersdk.WorkspaceBuildParameter | ||
RichParameterFile string | ||
@@ -411,6 +477,7 @@ func prepWorkspaceBuild(inv *serpent.Invocation, client *codersdk.Client, args p | ||
WithSourceWorkspaceParameters(args.SourceWorkspaceParameters). | ||
WithPromptEphemeralParameters(args.PromptEphemeralParameters). | ||
WithEphemeralParameters(args.EphemeralParameters). | ||
WithPresetParameters(args.PresetParameters). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Should this not be last in the list? Otherwise we allow preset parameters to be overwritten. | ||
WithPromptRichParameters(args.PromptRichParameters). | ||
WithRichParameters(args.RichParameters). | ||
WithRichParametersFile(parameterFile). | ||
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.