Skip to content

feat: add workspace actions cleanup configuration flags to CLI template create and edit #7453

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 10, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
added cleanup flags on template create
  • Loading branch information
Kira-Pilot committed May 8, 2023
commit 4e46ecf8714776e35d37e18187857d560a76ace5
49 changes: 46 additions & 3 deletions cli/templatecreate.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"strings"
Expand All @@ -29,6 +30,8 @@ func (r *RootCmd) templateCreate() *clibase.Cmd {
variablesFile string
variables []string
defaultTTL time.Duration
failureTTL time.Duration
inactivityTTL time.Duration

uploadFlags templateUploadFlags
)
Expand All @@ -41,6 +44,28 @@ func (r *RootCmd) templateCreate() *clibase.Cmd {
r.InitClient(client),
),
Handler: func(inv *clibase.Invocation) error {
if failureTTL != 0 || inactivityTTL != 0 {
experiments, exErr := client.Experiments(inv.Context())
if exErr != nil {
return xerrors.Errorf("get experiments: %w", exErr)
}

if !experiments.Enabled(codersdk.ExperimentWorkspaceActions) {
return xerrors.Errorf("--failure-ttl and --inactivityTTL are experimental features. Use the workspace_actions CODER_EXPERIMENTS flag to set these configuration values.")
}
entitlements, err := client.Entitlements(inv.Context())
var sdkErr *codersdk.Error
if xerrors.As(err, &sdkErr) && sdkErr.StatusCode() == http.StatusNotFound {
return xerrors.Errorf("your deployment appears to be an AGPL deployment, so you cannot set --failure-ttl or --inactivityTTL")
} else if err != nil {
return xerrors.Errorf("get entitlements: %w", err)
}

if !entitlements.Features[codersdk.FeatureAdvancedTemplateScheduling].Enabled {
return xerrors.Errorf("your license is not entitled to use advanced template scheduling, so you cannot set --failure-ttl or --inactivityTTL")
}
}

organization, err := CurrentOrganization(inv, client)
if err != nil {
return err
Expand Down Expand Up @@ -95,10 +120,16 @@ func (r *RootCmd) templateCreate() *clibase.Cmd {
}
}

fmt.Println("defaultTTL as passed in", defaultTTL)
fmt.Println("failureTTL as passed in", failureTTL)
fmt.Println("inactivityTTL as passed in", inactivityTTL)

createReq := codersdk.CreateTemplateRequest{
Name: templateName,
VersionID: job.ID,
DefaultTTLMillis: ptr.Ref(defaultTTL.Milliseconds()),
Name: templateName,
VersionID: job.ID,
DefaultTTLMillis: ptr.Ref(defaultTTL.Milliseconds()),
FailureTTLMillis: ptr.Ref(failureTTL.Milliseconds()),
InactivityTTLMillis: ptr.Ref(inactivityTTL.Milliseconds()),
}

_, err = client.CreateTemplate(inv.Context(), organization.ID, createReq)
Expand Down Expand Up @@ -143,6 +174,18 @@ func (r *RootCmd) templateCreate() *clibase.Cmd {
Default: "24h",
Value: clibase.DurationOf(&defaultTTL),
},
{
Flag: "failure-ttl",
Description: "Specify a failure TTL for workspaces created from this template. This licensed feature's default is 0h (off).",
Default: "0h",
Value: clibase.DurationOf(&failureTTL),
},
{
Flag: "inactivity-ttl",
Description: "Specify an inactivity TTL for workspaces created from this template. This licensed feature's default is 0h (off).",
Default: "0h",
Value: clibase.DurationOf(&inactivityTTL),
},
uploadFlags.option(),
{
Flag: "test.provisioner",
Expand Down
25 changes: 22 additions & 3 deletions coderd/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,15 +214,23 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
}

var (
defaultTTL time.Duration
maxTTL time.Duration
defaultTTL time.Duration
maxTTL time.Duration
failureTTL time.Duration
inactivityTTL time.Duration
)
if createTemplate.DefaultTTLMillis != nil {
defaultTTL = time.Duration(*createTemplate.DefaultTTLMillis) * time.Millisecond
}
if createTemplate.MaxTTLMillis != nil {
maxTTL = time.Duration(*createTemplate.MaxTTLMillis) * time.Millisecond
}
if createTemplate.FailureTTLMillis != nil {
failureTTL = time.Duration(*createTemplate.FailureTTLMillis) * time.Millisecond
}
if createTemplate.InactivityTTLMillis != nil {
inactivityTTL = time.Duration(*createTemplate.InactivityTTLMillis) * time.Millisecond
}

var validErrs []codersdk.ValidationError
if defaultTTL < 0 {
Expand All @@ -234,6 +242,12 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
if maxTTL != 0 && defaultTTL > maxTTL {
validErrs = append(validErrs, codersdk.ValidationError{Field: "default_ttl_ms", Detail: "Must be less than or equal to max_ttl_ms if max_ttl_ms is set."})
}
if failureTTL < 0 {
validErrs = append(validErrs, codersdk.ValidationError{Field: "failure_ttl_ms", Detail: "Must be a positive integer."})
}
if inactivityTTL < 0 {
validErrs = append(validErrs, codersdk.ValidationError{Field: "inactivity_ttl_ms", Detail: "Must be a positive integer."})
}
if len(validErrs) > 0 {
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid create template request.",
Expand Down Expand Up @@ -279,7 +293,12 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
UserAutostartEnabled: allowUserAutostart,
UserAutostopEnabled: allowUserAutostop,
DefaultTTL: defaultTTL,
MaxTTL: maxTTL,
// Some of these values are enterprise-only, but the
// TemplateScheduleStore will handle avoiding setting them if
// unlicensed.
MaxTTL: maxTTL,
FailureTTL: failureTTL,
InactivityTTL: inactivityTTL,
})
if err != nil {
return xerrors.Errorf("set template schedule options: %s", err)
Expand Down
18 changes: 18 additions & 0 deletions docs/cli/templates_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,24 @@ Specify a default TTL for workspaces created from this template.

Specify the directory to create from, use '-' to read tar from stdin.

### --failure-ttl

| | |
| ------- | --------------------- |
| Type | <code>duration</code> |
| Default | <code>0h</code> |

Specify a failure TTL for workspaces created from this template. This licensed feature's default is 0h (off).

### --inactivity-ttl

| | |
| ------- | --------------------- |
| Type | <code>duration</code> |
| Default | <code>0h</code> |

Specify an inactivity TTL for workspaces created from this template. This licensed feature's default is 0h (off).

### --parameter-file

| | |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ export const getValidationSchema = (): Yup.AnyObjectSchema =>
i18next.t("maxTTLMaxError", { ns: "templateSettingsPage" }),
),
failure_ttl_ms: Yup.number()
.integer()
.min(0, "Failure cleanup days must not be less than 0.")
.test(
"positive-if-enabled",
Expand All @@ -80,7 +79,6 @@ export const getValidationSchema = (): Yup.AnyObjectSchema =>
},
),
inactivity_ttl_ms: Yup.number()
.integer()
.min(0, "Inactivity cleanup days must not be less than 0.")
.test(
"positive-if-enabled",
Expand Down Expand Up @@ -349,7 +347,7 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
)}
disabled={isSubmitting || !form.values.failure_cleanup_enabled}
fullWidth
inputProps={{ min: 0, step: 1 }}
inputProps={{ min: 0, step: "any" }}
label="Time until cleanup (days)"
variant="outlined"
type="number"
Expand Down Expand Up @@ -385,7 +383,7 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
isSubmitting || !form.values.inactivity_cleanup_enabled
}
fullWidth
inputProps={{ min: 0, step: 1 }}
inputProps={{ min: 0, step: "any" }}
label="Time until cleanup (days)"
variant="outlined"
type="number"
Expand Down