@@ -17,11 +17,12 @@ import (
1717
1818func create () * cobra.Command {
1919 var (
20- parameterFile string
21- templateName string
22- startAt string
23- stopAfter time.Duration
24- workspaceName string
20+ parameterFile string
21+ richParameterFile string
22+ templateName string
23+ startAt string
24+ stopAfter time.Duration
25+ workspaceName string
2526 )
2627 cmd := & cobra.Command {
2728 Annotations : workspaceCommand ,
@@ -121,11 +122,12 @@ func create() *cobra.Command {
121122 schedSpec = ptr .Ref (sched .String ())
122123 }
123124
124- parameters , err := prepWorkspaceBuild (cmd , client , prepWorkspaceBuildArgs {
125- Template : template ,
126- ExistingParams : []codersdk.Parameter {},
127- ParameterFile : parameterFile ,
128- NewWorkspaceName : workspaceName ,
125+ buildParams , err := prepWorkspaceBuild (cmd , client , prepWorkspaceBuildArgs {
126+ Template : template ,
127+ ExistingParams : []codersdk.Parameter {},
128+ ParameterFile : parameterFile ,
129+ RichParameterFile : richParameterFile ,
130+ NewWorkspaceName : workspaceName ,
129131 })
130132 if err != nil {
131133 return err
@@ -140,11 +142,12 @@ func create() *cobra.Command {
140142 }
141143
142144 workspace , err := client .CreateWorkspace (cmd .Context (), organization .ID , codersdk .Me , codersdk.CreateWorkspaceRequest {
143- TemplateID : template .ID ,
144- Name : workspaceName ,
145- AutostartSchedule : schedSpec ,
146- TTLMillis : ptr .Ref (stopAfter .Milliseconds ()),
147- ParameterValues : parameters ,
145+ TemplateID : template .ID ,
146+ Name : workspaceName ,
147+ AutostartSchedule : schedSpec ,
148+ TTLMillis : ptr .Ref (stopAfter .Milliseconds ()),
149+ ParameterValues : buildParams .parameters ,
150+ RichParameterValues : buildParams .richParameters ,
148151 })
149152 if err != nil {
150153 return err
@@ -163,26 +166,40 @@ func create() *cobra.Command {
163166 cliui .AllowSkipPrompt (cmd )
164167 cliflag .StringVarP (cmd .Flags (), & templateName , "template" , "t" , "CODER_TEMPLATE_NAME" , "" , "Specify a template name." )
165168 cliflag .StringVarP (cmd .Flags (), & parameterFile , "parameter-file" , "" , "CODER_PARAMETER_FILE" , "" , "Specify a file path with parameter values." )
169+ cliflag .StringVarP (cmd .Flags (), & richParameterFile , "rich-parameter-file" , "" , "CODER_RICH_PARAMETER_FILE" , "" , "Specify a file path with values for rich parameters defined in the template." )
166170 cliflag .StringVarP (cmd .Flags (), & startAt , "start-at" , "" , "CODER_WORKSPACE_START_AT" , "" , "Specify the workspace autostart schedule. Check `coder schedule start --help` for the syntax." )
167171 cliflag .DurationVarP (cmd .Flags (), & stopAfter , "stop-after" , "" , "CODER_WORKSPACE_STOP_AFTER" , 8 * time .Hour , "Specify a duration after which the workspace should shut down (e.g. 8h)." )
168172 return cmd
169173}
170174
171175type prepWorkspaceBuildArgs struct {
172- Template codersdk.Template
173- ExistingParams []codersdk.Parameter
174- ParameterFile string
175- NewWorkspaceName string
176+ Template codersdk.Template
177+ ExistingParams []codersdk.Parameter
178+ ParameterFile string
179+ ExistingRichParams []codersdk.WorkspaceBuildParameter
180+ RichParameterFile string
181+ NewWorkspaceName string
182+
183+ UpdateWorkspace bool
184+ }
185+
186+ type buildParameters struct {
187+ // Parameters contains legacy parameters stored in /parameters.
188+ parameters []codersdk.CreateParameterRequest
189+ // Rich parameters stores values for build parameters annotated with description, icon, type, etc.
190+ richParameters []codersdk.WorkspaceBuildParameter
176191}
177192
178193// prepWorkspaceBuild will ensure a workspace build will succeed on the latest template version.
179- // Any missing params will be prompted to the user.
180- func prepWorkspaceBuild (cmd * cobra.Command , client * codersdk.Client , args prepWorkspaceBuildArgs ) ([]codersdk. CreateParameterRequest , error ) {
194+ // Any missing params will be prompted to the user. It supports legacy and rich parameters.
195+ func prepWorkspaceBuild (cmd * cobra.Command , client * codersdk.Client , args prepWorkspaceBuildArgs ) (* buildParameters , error ) {
181196 ctx := cmd .Context ()
182197 templateVersion , err := client .TemplateVersion (ctx , args .Template .ActiveVersionID )
183198 if err != nil {
184199 return nil , err
185200 }
201+
202+ // Legacy parameters
186203 parameterSchemas , err := client .TemplateVersionSchema (ctx , templateVersion .ID )
187204 if err != nil {
188205 return nil , err
@@ -200,7 +217,7 @@ func prepWorkspaceBuild(cmd *cobra.Command, client *codersdk.Client, args prepWo
200217 }
201218 }
202219 disclaimerPrinted := false
203- parameters := make ([]codersdk.CreateParameterRequest , 0 )
220+ legacyParameters := make ([]codersdk.CreateParameterRequest , 0 )
204221PromptParamLoop:
205222 for _ , parameterSchema := range parameterSchemas {
206223 if ! parameterSchema .AllowOverrideSource {
@@ -227,19 +244,76 @@ PromptParamLoop:
227244 return nil , err
228245 }
229246
230- parameters = append (parameters , codersdk.CreateParameterRequest {
247+ legacyParameters = append (legacyParameters , codersdk.CreateParameterRequest {
231248 Name : parameterSchema .Name ,
232249 SourceValue : parameterValue ,
233250 SourceScheme : codersdk .ParameterSourceSchemeData ,
234251 DestinationScheme : parameterSchema .DefaultDestinationScheme ,
235252 })
236253 }
237- _ , _ = fmt .Fprintln (cmd .OutOrStdout ())
254+
255+ if disclaimerPrinted {
256+ _ , _ = fmt .Fprintln (cmd .OutOrStdout ())
257+ }
258+
259+ // Rich parameters
260+ templateVersionParameters , err := client .TemplateVersionRichParameters (cmd .Context (), templateVersion .ID )
261+ if err != nil {
262+ return nil , xerrors .Errorf ("get template version rich parameters: %w" , err )
263+ }
264+
265+ parameterMapFromFile = map [string ]string {}
266+ useParamFile = false
267+ if args .RichParameterFile != "" {
268+ useParamFile = true
269+ _ , _ = fmt .Fprintln (cmd .OutOrStdout (), cliui .Styles .Paragraph .Render ("Attempting to read the variables from the rich parameter file." )+ "\r \n " )
270+ parameterMapFromFile , err = createParameterMapFromFile (args .RichParameterFile )
271+ if err != nil {
272+ return nil , err
273+ }
274+ }
275+ disclaimerPrinted = false
276+ richParameters := make ([]codersdk.WorkspaceBuildParameter , 0 )
277+ PromptRichParamLoop:
278+ for _ , templateVersionParameter := range templateVersionParameters {
279+ if ! disclaimerPrinted {
280+ _ , _ = fmt .Fprintln (cmd .OutOrStdout (), cliui .Styles .Paragraph .Render ("This template has customizable parameters. Values can be changed after create, but may have unintended side effects (like data loss)." )+ "\r \n " )
281+ disclaimerPrinted = true
282+ }
283+
284+ // Param file is all or nothing
285+ if ! useParamFile {
286+ for _ , e := range args .ExistingRichParams {
287+ if e .Name == templateVersionParameter .Name {
288+ // If the param already exists, we do not need to prompt it again.
289+ // The workspace scope will reuse params for each build.
290+ continue PromptRichParamLoop
291+ }
292+ }
293+ }
294+
295+ if args .UpdateWorkspace && ! templateVersionParameter .Mutable {
296+ _ , _ = fmt .Fprintln (cmd .OutOrStdout (), cliui .Styles .Warn .Render (fmt .Sprintf (`Parameter %q is not mutable, so can't be customized after workspace creation.` , templateVersionParameter .Name )))
297+ continue
298+ }
299+
300+ parameterValue , err := getWorkspaceBuildParameterValueFromMapOrInput (cmd , parameterMapFromFile , templateVersionParameter )
301+ if err != nil {
302+ return nil , err
303+ }
304+
305+ richParameters = append (richParameters , * parameterValue )
306+ }
307+
308+ if disclaimerPrinted {
309+ _ , _ = fmt .Fprintln (cmd .OutOrStdout ())
310+ }
238311
239312 // Run a dry-run with the given parameters to check correctness
240313 dryRun , err := client .CreateTemplateVersionDryRun (cmd .Context (), templateVersion .ID , codersdk.CreateTemplateVersionDryRunRequest {
241- WorkspaceName : args .NewWorkspaceName ,
242- ParameterValues : parameters ,
314+ WorkspaceName : args .NewWorkspaceName ,
315+ ParameterValues : legacyParameters ,
316+ RichParameterValues : richParameters ,
243317 })
244318 if err != nil {
245319 return nil , xerrors .Errorf ("begin workspace dry-run: %w" , err )
@@ -279,5 +353,8 @@ PromptParamLoop:
279353 return nil , err
280354 }
281355
282- return parameters , nil
356+ return & buildParameters {
357+ parameters : legacyParameters ,
358+ richParameters : richParameters ,
359+ }, nil
283360}
0 commit comments