@@ -17,11 +17,12 @@ import (
17
17
18
18
func create () * cobra.Command {
19
19
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
25
26
)
26
27
cmd := & cobra.Command {
27
28
Annotations : workspaceCommand ,
@@ -121,11 +122,12 @@ func create() *cobra.Command {
121
122
schedSpec = ptr .Ref (sched .String ())
122
123
}
123
124
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 ,
129
131
})
130
132
if err != nil {
131
133
return err
@@ -140,11 +142,12 @@ func create() *cobra.Command {
140
142
}
141
143
142
144
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 ,
148
151
})
149
152
if err != nil {
150
153
return err
@@ -163,26 +166,40 @@ func create() *cobra.Command {
163
166
cliui .AllowSkipPrompt (cmd )
164
167
cliflag .StringVarP (cmd .Flags (), & templateName , "template" , "t" , "CODER_TEMPLATE_NAME" , "" , "Specify a template name." )
165
168
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." )
166
170
cliflag .StringVarP (cmd .Flags (), & startAt , "start-at" , "" , "CODER_WORKSPACE_START_AT" , "" , "Specify the workspace autostart schedule. Check `coder schedule start --help` for the syntax." )
167
171
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)." )
168
172
return cmd
169
173
}
170
174
171
175
type 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
176
191
}
177
192
178
193
// 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 ) {
181
196
ctx := cmd .Context ()
182
197
templateVersion , err := client .TemplateVersion (ctx , args .Template .ActiveVersionID )
183
198
if err != nil {
184
199
return nil , err
185
200
}
201
+
202
+ // Legacy parameters
186
203
parameterSchemas , err := client .TemplateVersionSchema (ctx , templateVersion .ID )
187
204
if err != nil {
188
205
return nil , err
@@ -200,7 +217,7 @@ func prepWorkspaceBuild(cmd *cobra.Command, client *codersdk.Client, args prepWo
200
217
}
201
218
}
202
219
disclaimerPrinted := false
203
- parameters := make ([]codersdk.CreateParameterRequest , 0 )
220
+ legacyParameters := make ([]codersdk.CreateParameterRequest , 0 )
204
221
PromptParamLoop:
205
222
for _ , parameterSchema := range parameterSchemas {
206
223
if ! parameterSchema .AllowOverrideSource {
@@ -227,19 +244,76 @@ PromptParamLoop:
227
244
return nil , err
228
245
}
229
246
230
- parameters = append (parameters , codersdk.CreateParameterRequest {
247
+ legacyParameters = append (legacyParameters , codersdk.CreateParameterRequest {
231
248
Name : parameterSchema .Name ,
232
249
SourceValue : parameterValue ,
233
250
SourceScheme : codersdk .ParameterSourceSchemeData ,
234
251
DestinationScheme : parameterSchema .DefaultDestinationScheme ,
235
252
})
236
253
}
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
+ }
238
311
239
312
// Run a dry-run with the given parameters to check correctness
240
313
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 ,
243
317
})
244
318
if err != nil {
245
319
return nil , xerrors .Errorf ("begin workspace dry-run: %w" , err )
@@ -279,5 +353,8 @@ PromptParamLoop:
279
353
return nil , err
280
354
}
281
355
282
- return parameters , nil
356
+ return & buildParameters {
357
+ parameters : legacyParameters ,
358
+ richParameters : richParameters ,
359
+ }, nil
283
360
}
0 commit comments