Skip to content

Commit 0dac269

Browse files
committed
combine edit flags
1 parent 64dd054 commit 0dac269

File tree

3 files changed

+376
-94
lines changed

3 files changed

+376
-94
lines changed

cli/templatecreate.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ func (r *RootCmd) templateCreate() *clibase.Cmd {
4747
r.InitClient(client),
4848
),
4949
Handler: func(inv *clibase.Invocation) error {
50+
<<<<<<< HEAD
5051
<<<<<<< HEAD
5152
isTemplateSchedulingOptionsSet := failureTTL != 0 || dormancyThreshold != 0 || dormancyAutoDeletion != 0 || maxTTL != 0
5253

@@ -83,6 +84,9 @@ func (r *RootCmd) templateCreate() *clibase.Cmd {
8384
}
8485
=======
8586
err := handleEntitlements(inv.Context(), handleEntitlementsArgs{
87+
=======
88+
err := createEntitlementsCheck(inv.Context(), handleEntitlementsArgs{
89+
>>>>>>> 3c377e5d3 (combine edit flags)
8690
client: client,
8791
requireActiveVersion: requireActiveVersion,
8892
defaultTTL: defaultTTL,
@@ -383,7 +387,7 @@ type handleEntitlementsArgs struct {
383387
maxTTL time.Duration
384388
}
385389

386-
func handleEntitlements(ctx context.Context, args handleEntitlementsArgs) error {
390+
func createEntitlementsCheck(ctx context.Context, args handleEntitlementsArgs) error {
387391
isTemplateSchedulingOptionsSet := args.failureTTL != 0 || args.dormancyThreshold != 0 || args.dormancyAutoDeletion != 0 || args.maxTTL != 0
388392

389393
if isTemplateSchedulingOptionsSet || args.requireActiveVersion {

cli/templateedit.go

Lines changed: 218 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cli
22

33
import (
4+
"context"
45
"fmt"
56
"net/http"
67
"strings"
@@ -46,6 +47,7 @@ func (r *RootCmd) templateEdit() *clibase.Cmd {
4647
),
4748
Short: "Edit the metadata of a template by name.",
4849
Handler: func(inv *clibase.Invocation) error {
50+
<<<<<<< HEAD
4951
// This clause can be removed when workspace_actions is no longer experimental
5052
if failureTTL != 0 || dormancyThreshold != 0 || dormancyAutoDeletion != 0 {
5153
experiments, exErr := client.Experiments(inv.Context())
@@ -89,6 +91,8 @@ func (r *RootCmd) templateEdit() *clibase.Cmd {
8991
}
9092
}
9193

94+
=======
95+
>>>>>>> 3c377e5d3 (combine edit flags)
9296
organization, err := CurrentOrganization(inv, client)
9397
if err != nil {
9498
return xerrors.Errorf("get current organization: %w", err)
@@ -98,71 +102,55 @@ func (r *RootCmd) templateEdit() *clibase.Cmd {
98102
return xerrors.Errorf("get workspace template: %w", err)
99103
}
100104

101-
// Copy the default value if the list is empty, or if the user
102-
// specified the "none" value clear the list.
103-
if len(autostopRequirementDaysOfWeek) == 0 {
104-
autostopRequirementDaysOfWeek = template.AutostopRequirement.DaysOfWeek
105-
}
106-
if len(autostartRequirementDaysOfWeek) == 1 && autostartRequirementDaysOfWeek[0] == "all" {
107-
// Set it to every day of the week
108-
autostartRequirementDaysOfWeek = []string{"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"}
109-
} else if len(autostartRequirementDaysOfWeek) == 0 {
110-
autostartRequirementDaysOfWeek = template.AutostartRequirement.DaysOfWeek
111-
}
112-
if unsetAutostopRequirementDaysOfWeek {
113-
autostopRequirementDaysOfWeek = []string{}
114-
}
115-
if failureTTL == 0 {
116-
failureTTL = time.Duration(template.FailureTTLMillis) * time.Millisecond
117-
}
118-
if dormancyThreshold == 0 {
119-
dormancyThreshold = time.Duration(template.TimeTilDormantMillis) * time.Millisecond
120-
}
121-
if dormancyAutoDeletion == 0 {
122-
dormancyAutoDeletion = time.Duration(template.TimeTilDormantAutoDeleteMillis) * time.Millisecond
123-
}
124-
125-
// Default values
126-
if !userSetOption(inv, "description") {
127-
description = template.Description
128-
}
105+
unsetAutostopRequirementDaysOfWeek, err := editTemplateEntitlementsCheck(inv.Context(), editTemplateEntitlementsArgs{
106+
client: client,
107+
inv: inv,
108+
template: template,
129109

130-
if !userSetOption(inv, "icon") {
131-
icon = template.Icon
132-
}
110+
name: name,
111+
displayName: displayName,
112+
description: description,
113+
icon: icon,
114+
defaultTTL: defaultTTL,
115+
maxTTL: maxTTL,
116+
autostopRequirementDaysOfWeek: autostopRequirementDaysOfWeek,
117+
autostopRequirementWeeks: autostopRequirementWeeks,
118+
autostartRequirementDaysOfWeek: autostartRequirementDaysOfWeek,
119+
failureTTL: failureTTL,
120+
dormancyThreshold: dormancyThreshold,
121+
dormancyAutoDeletion: dormancyAutoDeletion,
122+
allowUserCancelWorkspaceJobs: allowUserCancelWorkspaceJobs,
123+
allowUserAutostart: allowUserAutostart,
124+
allowUserAutostop: allowUserAutostop,
125+
requireActiveVersion: requireActiveVersion,
126+
deprecationMessage: deprecationMessage,
127+
disableEveryone: false, // TODO: Add new flag
128+
})
133129

134-
if !userSetOption(inv, "display-name") {
135-
displayName = template.DisplayName
136-
}
130+
req := updateTemplateMetaRequest(updateTemplateMetaArgs{
131+
client: client,
132+
inv: inv,
133+
template: template,
134+
unsetAutostopRequirementDaysOfWeek: unsetAutostopRequirementDaysOfWeek,
137135

138-
var deprecated *string
139-
if !userSetOption(inv, "deprecated") {
140-
deprecated = &deprecationMessage
141-
}
142-
143-
req := codersdk.UpdateTemplateMeta{
144-
Name: name,
145-
DisplayName: displayName,
146-
Description: description,
147-
Icon: icon,
148-
DefaultTTLMillis: defaultTTL.Milliseconds(),
149-
MaxTTLMillis: maxTTL.Milliseconds(),
150-
AutostopRequirement: &codersdk.TemplateAutostopRequirement{
151-
DaysOfWeek: autostopRequirementDaysOfWeek,
152-
Weeks: autostopRequirementWeeks,
153-
},
154-
AutostartRequirement: &codersdk.TemplateAutostartRequirement{
155-
DaysOfWeek: autostartRequirementDaysOfWeek,
156-
},
157-
FailureTTLMillis: failureTTL.Milliseconds(),
158-
TimeTilDormantMillis: dormancyThreshold.Milliseconds(),
159-
TimeTilDormantAutoDeleteMillis: dormancyAutoDeletion.Milliseconds(),
160-
AllowUserCancelWorkspaceJobs: allowUserCancelWorkspaceJobs,
161-
AllowUserAutostart: allowUserAutostart,
162-
AllowUserAutostop: allowUserAutostop,
163-
RequireActiveVersion: requireActiveVersion,
164-
DeprecationMessage: deprecated,
165-
}
136+
name: name,
137+
displayName: displayName,
138+
description: description,
139+
icon: icon,
140+
defaultTTL: defaultTTL,
141+
maxTTL: maxTTL,
142+
autostopRequirementDaysOfWeek: autostopRequirementDaysOfWeek,
143+
autostopRequirementWeeks: autostopRequirementWeeks,
144+
autostartRequirementDaysOfWeek: autostartRequirementDaysOfWeek,
145+
failureTTL: failureTTL,
146+
dormancyThreshold: dormancyThreshold,
147+
dormancyAutoDeletion: dormancyAutoDeletion,
148+
allowUserCancelWorkspaceJobs: allowUserCancelWorkspaceJobs,
149+
allowUserAutostart: allowUserAutostart,
150+
allowUserAutostop: allowUserAutostop,
151+
requireActiveVersion: requireActiveVersion,
152+
deprecationMessage: deprecationMessage,
153+
})
166154

167155
_, err = client.UpdateTemplateMeta(inv.Context(), template.ID, req)
168156
if err != nil {
@@ -297,3 +285,171 @@ func (r *RootCmd) templateEdit() *clibase.Cmd {
297285

298286
return cmd
299287
}
288+
289+
type editTemplateEntitlementsArgs struct {
290+
client *codersdk.Client
291+
inv *clibase.Invocation
292+
293+
defaultTTL time.Duration
294+
maxTTL time.Duration
295+
autostopRequirementDaysOfWeek []string
296+
autostopRequirementWeeks int64
297+
autostartRequirementDaysOfWeek []string
298+
failureTTL time.Duration
299+
dormancyThreshold time.Duration
300+
dormancyAutoDeletion time.Duration
301+
allowUserCancelWorkspaceJobs bool
302+
allowUserAutostart bool
303+
allowUserAutostop bool
304+
requireActiveVersion bool
305+
}
306+
307+
func editTemplateEntitlementsCheck(ctx context.Context, args editTemplateEntitlementsArgs) (bool, error) {
308+
// This clause can be removed when workspace_actions is no longer experimental
309+
if args.failureTTL != 0 || args.dormancyThreshold != 0 || args.dormancyAutoDeletion != 0 {
310+
experiments, exErr := args.client.Experiments(ctx)
311+
if exErr != nil {
312+
return false, xerrors.Errorf("get experiments: %w", exErr)
313+
}
314+
315+
if !experiments.Enabled(codersdk.ExperimentWorkspaceActions) {
316+
return false, xerrors.Errorf("--failure-ttl, --dormancy-threshold, and --dormancy-auto-deletion are experimental features. Use the workspace_actions CODER_EXPERIMENTS flag to set these configuration values.")
317+
}
318+
}
319+
320+
unsetAutostopRequirementDaysOfWeek := len(args.autostopRequirementDaysOfWeek) == 1 && args.autostopRequirementDaysOfWeek[0] == "none"
321+
requiresScheduling := (len(args.autostopRequirementDaysOfWeek) > 0 && !unsetAutostopRequirementDaysOfWeek) ||
322+
args.autostopRequirementWeeks > 0 ||
323+
!args.allowUserAutostart ||
324+
!args.allowUserAutostop ||
325+
args.maxTTL != 0 ||
326+
args.failureTTL != 0 ||
327+
args.dormancyThreshold != 0 ||
328+
args.dormancyAutoDeletion != 0 ||
329+
len(args.autostartRequirementDaysOfWeek) > 0
330+
331+
requiresEntitlement := requiresScheduling || args.requireActiveVersion
332+
if requiresEntitlement {
333+
entitlements, err := args.client.Entitlements(ctx)
334+
if cerr, ok := codersdk.AsError(err); ok && cerr.StatusCode() == http.StatusNotFound {
335+
return false, xerrors.Errorf("your deployment appears to be an AGPL deployment, so you cannot set enterprise-only flags")
336+
} else if err != nil {
337+
return false, xerrors.Errorf("get entitlements: %w", err)
338+
}
339+
340+
if requiresScheduling && !entitlements.Features[codersdk.FeatureAdvancedTemplateScheduling].Enabled {
341+
return false, xerrors.Errorf("your license is not entitled to use advanced template scheduling, so you cannot set --max-ttl, --failure-ttl, --inactivityTTL, --allow-user-autostart=false or --allow-user-autostop=false")
342+
}
343+
344+
if args.requireActiveVersion {
345+
if !entitlements.Features[codersdk.FeatureAccessControl].Enabled {
346+
return false, xerrors.Errorf("your license is not entitled to use enterprise access control, so you cannot set --require-active-version")
347+
}
348+
349+
experiments, exErr := args.client.Experiments(ctx)
350+
if exErr != nil {
351+
return false, xerrors.Errorf("get experiments: %w", exErr)
352+
}
353+
354+
if !experiments.Enabled(codersdk.ExperimentTemplateUpdatePolicies) {
355+
return false, xerrors.Errorf("--require-active-version is an experimental feature, contact an administrator to enable the 'template_update_policies' experiment on your Coder server")
356+
}
357+
}
358+
}
359+
360+
return unsetAutostopRequirementDaysOfWeek, nil
361+
}
362+
363+
type updateTemplateMetaArgs struct {
364+
client *codersdk.Client
365+
inv *clibase.Invocation
366+
template codersdk.Template
367+
unsetAutostopRequirementDaysOfWeek bool
368+
369+
name string
370+
displayName string
371+
description string
372+
icon string
373+
defaultTTL time.Duration
374+
maxTTL time.Duration
375+
autostopRequirementDaysOfWeek []string
376+
autostopRequirementWeeks int64
377+
autostartRequirementDaysOfWeek []string
378+
failureTTL time.Duration
379+
dormancyThreshold time.Duration
380+
dormancyAutoDeletion time.Duration
381+
allowUserCancelWorkspaceJobs bool
382+
allowUserAutostart bool
383+
allowUserAutostop bool
384+
requireActiveVersion bool
385+
deprecationMessage string
386+
disableEveryone bool
387+
}
388+
389+
func updateTemplateMetaRequest(args updateTemplateMetaArgs) codersdk.UpdateTemplateMeta {
390+
// Copy the default value if the list is empty, or if the user
391+
// specified the "none" value clear the list.
392+
if len(args.autostopRequirementDaysOfWeek) == 0 {
393+
args.autostopRequirementDaysOfWeek = args.template.AutostopRequirement.DaysOfWeek
394+
}
395+
if len(args.autostartRequirementDaysOfWeek) == 1 && args.autostartRequirementDaysOfWeek[0] == "all" {
396+
// Set it to every day of the week
397+
args.autostartRequirementDaysOfWeek = []string{"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"}
398+
} else if len(args.autostartRequirementDaysOfWeek) == 0 {
399+
args.autostartRequirementDaysOfWeek = args.template.AutostartRequirement.DaysOfWeek
400+
}
401+
if args.unsetAutostopRequirementDaysOfWeek {
402+
args.autostopRequirementDaysOfWeek = []string{}
403+
}
404+
if args.failureTTL == 0 {
405+
args.failureTTL = time.Duration(args.template.FailureTTLMillis) * time.Millisecond
406+
}
407+
if args.dormancyThreshold == 0 {
408+
args.dormancyThreshold = time.Duration(args.template.TimeTilDormantMillis) * time.Millisecond
409+
}
410+
if args.dormancyAutoDeletion == 0 {
411+
args.dormancyAutoDeletion = time.Duration(args.template.TimeTilDormantAutoDeleteMillis) * time.Millisecond
412+
}
413+
414+
// Default values
415+
if !userSetOption(args.inv, "description") {
416+
args.description = args.template.Description
417+
}
418+
419+
if !userSetOption(args.inv, "icon") {
420+
args.icon = args.template.Icon
421+
}
422+
423+
if !userSetOption(args.inv, "display-name") {
424+
args.displayName = args.template.DisplayName
425+
}
426+
427+
var deprecated *string
428+
if !userSetOption(args.inv, "deprecated") {
429+
deprecated = &args.deprecationMessage
430+
}
431+
432+
return codersdk.UpdateTemplateMeta{
433+
Name: args.name,
434+
DisplayName: args.displayName,
435+
Description: args.description,
436+
Icon: args.icon,
437+
DefaultTTLMillis: args.defaultTTL.Milliseconds(),
438+
MaxTTLMillis: args.maxTTL.Milliseconds(),
439+
AutostopRequirement: &codersdk.TemplateAutostopRequirement{
440+
DaysOfWeek: args.autostopRequirementDaysOfWeek,
441+
Weeks: args.autostopRequirementWeeks,
442+
},
443+
AutostartRequirement: &codersdk.TemplateAutostartRequirement{
444+
DaysOfWeek: args.autostartRequirementDaysOfWeek,
445+
},
446+
FailureTTLMillis: args.failureTTL.Milliseconds(),
447+
TimeTilDormantMillis: args.dormancyThreshold.Milliseconds(),
448+
TimeTilDormantAutoDeleteMillis: args.dormancyAutoDeletion.Milliseconds(),
449+
AllowUserCancelWorkspaceJobs: args.allowUserCancelWorkspaceJobs,
450+
AllowUserAutostart: args.allowUserAutostart,
451+
AllowUserAutostop: args.allowUserAutostop,
452+
RequireActiveVersion: args.requireActiveVersion,
453+
DeprecationMessage: deprecated,
454+
}
455+
}

0 commit comments

Comments
 (0)