mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
feat: enforce template-level constraints for TTL and autostart (#2018)
This PR adds fields to templates that constrain values for workspaces derived from that template. - Autostop: Adds a field max_ttl on the template which limits the maximum value of ttl on all workspaces derived from that template. Defaulting to 168 hours, enforced on edits to workspace metadata. New workspaces will default to the templates's `max_ttl` if not specified. - Autostart: Adds a field min_autostart_duration which limits the minimum duration between successive autostarts of a template, measured from a single reference time. Defaulting to 1 hour, enforced on edits to workspace metadata.
This commit is contained in:
@ -322,12 +322,16 @@ func CreateWorkspaceBuild(
|
||||
|
||||
// CreateTemplate creates a template with the "echo" provisioner for
|
||||
// compatibility with testing. The name assigned is randomly generated.
|
||||
func CreateTemplate(t *testing.T, client *codersdk.Client, organization uuid.UUID, version uuid.UUID) codersdk.Template {
|
||||
template, err := client.CreateTemplate(context.Background(), organization, codersdk.CreateTemplateRequest{
|
||||
func CreateTemplate(t *testing.T, client *codersdk.Client, organization uuid.UUID, version uuid.UUID, mutators ...func(*codersdk.CreateTemplateRequest)) codersdk.Template {
|
||||
req := codersdk.CreateTemplateRequest{
|
||||
Name: randomUsername(),
|
||||
Description: randomUsername(),
|
||||
VersionID: version,
|
||||
})
|
||||
}
|
||||
for _, mut := range mutators {
|
||||
mut(&req)
|
||||
}
|
||||
template, err := client.CreateTemplate(context.Background(), organization, req)
|
||||
require.NoError(t, err)
|
||||
return template
|
||||
}
|
||||
@ -400,7 +404,7 @@ func CreateWorkspace(t *testing.T, client *codersdk.Client, organization uuid.UU
|
||||
req := codersdk.CreateWorkspaceRequest{
|
||||
TemplateID: templateID,
|
||||
Name: randomUsername(),
|
||||
AutostartSchedule: ptr.Ref("CRON_TZ=US/Central * * * * *"),
|
||||
AutostartSchedule: ptr.Ref("CRON_TZ=US/Central 30 9 * * 1-5"),
|
||||
TTLMillis: ptr.Ref((8 * time.Hour).Milliseconds()),
|
||||
}
|
||||
for _, mutator := range mutators {
|
||||
@ -411,6 +415,42 @@ func CreateWorkspace(t *testing.T, client *codersdk.Client, organization uuid.UU
|
||||
return workspace
|
||||
}
|
||||
|
||||
// TransitionWorkspace is a convenience method for transitioning a workspace from one state to another.
|
||||
func MustTransitionWorkspace(t *testing.T, client *codersdk.Client, workspaceID uuid.UUID, from, to database.WorkspaceTransition) codersdk.Workspace {
|
||||
t.Helper()
|
||||
ctx := context.Background()
|
||||
workspace, err := client.Workspace(ctx, workspaceID)
|
||||
require.NoError(t, err, "unexpected error fetching workspace")
|
||||
require.Equal(t, workspace.LatestBuild.Transition, codersdk.WorkspaceTransition(from), "expected workspace state: %s got: %s", from, workspace.LatestBuild.Transition)
|
||||
|
||||
template, err := client.Template(ctx, workspace.TemplateID)
|
||||
require.NoError(t, err, "fetch workspace template")
|
||||
|
||||
build, err := client.CreateWorkspaceBuild(ctx, workspace.ID, codersdk.CreateWorkspaceBuildRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Transition: codersdk.WorkspaceTransition(to),
|
||||
})
|
||||
require.NoError(t, err, "unexpected error transitioning workspace to %s", to)
|
||||
|
||||
_ = AwaitWorkspaceBuildJob(t, client, build.ID)
|
||||
|
||||
updated := MustWorkspace(t, client, workspace.ID)
|
||||
require.Equal(t, codersdk.WorkspaceTransition(to), updated.LatestBuild.Transition, "expected workspace to be in state %s but got %s", to, updated.LatestBuild.Transition)
|
||||
return updated
|
||||
}
|
||||
|
||||
// MustWorkspace is a convenience method for fetching a workspace that should exist.
|
||||
func MustWorkspace(t *testing.T, client *codersdk.Client, workspaceID uuid.UUID) codersdk.Workspace {
|
||||
t.Helper()
|
||||
ctx := context.Background()
|
||||
ws, err := client.Workspace(ctx, workspaceID)
|
||||
if err != nil && strings.Contains(err.Error(), "status code 410") {
|
||||
ws, err = client.DeletedWorkspace(ctx, workspaceID)
|
||||
}
|
||||
require.NoError(t, err, "no workspace found with id %s", workspaceID)
|
||||
return ws
|
||||
}
|
||||
|
||||
// NewGoogleInstanceIdentity returns a metadata client and ID token validator for faking
|
||||
// instance authentication for Google Cloud.
|
||||
// nolint:revive
|
||||
|
Reference in New Issue
Block a user