chore: remove max_ttl from templates (#12644)

* chore: remove max_ttl from templates

Completely removing max_ttl as a feature on template scheduling. Must use other template scheduling features to achieve autostop.
This commit is contained in:
Steven Masley
2024-03-20 10:37:57 -05:00
committed by GitHub
parent d82e20152b
commit d789a60d47
51 changed files with 151 additions and 1304 deletions
@@ -1039,248 +1039,6 @@ func TestCompleteJob(t *testing.T) {
require.False(t, job.Error.Valid)
})
// TODO(@dean): remove this legacy test for MaxTTL
t.Run("WorkspaceBuildLegacy", func(t *testing.T) {
t.Parallel()
cases := []struct {
name string
templateAllowAutostop bool
templateDefaultTTL time.Duration
templateMaxTTL time.Duration
workspaceTTL time.Duration
transition database.WorkspaceTransition
// The TTL is actually a deadline time on the workspace_build row,
// so during the test this will be compared to be within 15 seconds
// of the expected value.
expectedTTL time.Duration
expectedMaxTTL time.Duration
}{
{
name: "OK",
templateAllowAutostop: true,
templateDefaultTTL: 0,
templateMaxTTL: 0,
workspaceTTL: 0,
transition: database.WorkspaceTransitionStart,
expectedTTL: 0,
expectedMaxTTL: 0,
},
{
name: "Delete",
templateAllowAutostop: true,
templateDefaultTTL: 0,
templateMaxTTL: 0,
workspaceTTL: 0,
transition: database.WorkspaceTransitionDelete,
expectedTTL: 0,
expectedMaxTTL: 0,
},
{
name: "WorkspaceTTL",
templateAllowAutostop: true,
templateDefaultTTL: 0,
templateMaxTTL: 0,
workspaceTTL: time.Hour,
transition: database.WorkspaceTransitionStart,
expectedTTL: time.Hour,
expectedMaxTTL: 0,
},
{
name: "TemplateDefaultTTLIgnored",
templateAllowAutostop: true,
templateDefaultTTL: time.Hour,
templateMaxTTL: 0,
workspaceTTL: 0,
transition: database.WorkspaceTransitionStart,
expectedTTL: 0,
expectedMaxTTL: 0,
},
{
name: "WorkspaceTTLOverridesTemplateDefaultTTL",
templateAllowAutostop: true,
templateDefaultTTL: 2 * time.Hour,
templateMaxTTL: 0,
workspaceTTL: time.Hour,
transition: database.WorkspaceTransitionStart,
expectedTTL: time.Hour,
expectedMaxTTL: 0,
},
{
name: "TemplateMaxTTL",
templateAllowAutostop: true,
templateDefaultTTL: 0,
templateMaxTTL: time.Hour,
workspaceTTL: 0,
transition: database.WorkspaceTransitionStart,
expectedTTL: time.Hour,
expectedMaxTTL: time.Hour,
},
{
name: "TemplateMaxTTLOverridesWorkspaceTTL",
templateAllowAutostop: true,
templateDefaultTTL: 0,
templateMaxTTL: 2 * time.Hour,
workspaceTTL: 3 * time.Hour,
transition: database.WorkspaceTransitionStart,
expectedTTL: 2 * time.Hour,
expectedMaxTTL: 2 * time.Hour,
},
{
name: "TemplateMaxTTLOverridesTemplateDefaultTTL",
templateAllowAutostop: true,
templateDefaultTTL: 3 * time.Hour,
templateMaxTTL: 2 * time.Hour,
workspaceTTL: 0,
transition: database.WorkspaceTransitionStart,
expectedTTL: 2 * time.Hour,
expectedMaxTTL: 2 * time.Hour,
},
{
name: "TemplateBlockWorkspaceTTL",
templateAllowAutostop: false,
templateDefaultTTL: 3 * time.Hour,
templateMaxTTL: 6 * time.Hour,
workspaceTTL: 4 * time.Hour,
transition: database.WorkspaceTransitionStart,
expectedTTL: 3 * time.Hour,
expectedMaxTTL: 6 * time.Hour,
},
}
for _, c := range cases {
c := c
t.Run(c.name, func(t *testing.T) {
t.Parallel()
tss := &atomic.Pointer[schedule.TemplateScheduleStore]{}
srv, db, ps, pd := setup(t, false, &overrides{templateScheduleStore: tss})
var store schedule.TemplateScheduleStore = schedule.MockTemplateScheduleStore{
GetFn: func(_ context.Context, _ database.Store, _ uuid.UUID) (schedule.TemplateScheduleOptions, error) {
return schedule.TemplateScheduleOptions{
UserAutostartEnabled: false,
UserAutostopEnabled: c.templateAllowAutostop,
DefaultTTL: c.templateDefaultTTL,
MaxTTL: c.templateMaxTTL,
UseMaxTTL: true,
}, nil
},
}
tss.Store(&store)
user := dbgen.User(t, db, database.User{})
template := dbgen.Template(t, db, database.Template{
Name: "template",
Provisioner: database.ProvisionerTypeEcho,
OrganizationID: pd.OrganizationID,
})
version := dbgen.TemplateVersion(t, db, database.TemplateVersion{
OrganizationID: pd.OrganizationID,
TemplateID: uuid.NullUUID{
UUID: template.ID,
Valid: true,
},
JobID: uuid.New(),
})
err := db.UpdateTemplateScheduleByID(ctx, database.UpdateTemplateScheduleByIDParams{
ID: template.ID,
UpdatedAt: dbtime.Now(),
AllowUserAutostart: c.templateAllowAutostop,
DefaultTTL: int64(c.templateDefaultTTL),
MaxTTL: int64(c.templateMaxTTL),
})
require.NoError(t, err)
file := dbgen.File(t, db, database.File{CreatedBy: user.ID})
workspaceTTL := sql.NullInt64{}
if c.workspaceTTL != 0 {
workspaceTTL = sql.NullInt64{
Int64: int64(c.workspaceTTL),
Valid: true,
}
}
workspace := dbgen.Workspace(t, db, database.Workspace{
TemplateID: template.ID,
Ttl: workspaceTTL,
OrganizationID: pd.OrganizationID,
})
build := dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{
WorkspaceID: workspace.ID,
TemplateVersionID: version.ID,
Transition: c.transition,
Reason: database.BuildReasonInitiator,
})
job := dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{
OrganizationID: pd.OrganizationID,
FileID: file.ID,
Type: database.ProvisionerJobTypeWorkspaceBuild,
Input: must(json.Marshal(provisionerdserver.WorkspaceProvisionJob{
WorkspaceBuildID: build.ID,
})),
})
_, err = db.AcquireProvisionerJob(ctx, database.AcquireProvisionerJobParams{
OrganizationID: pd.OrganizationID,
WorkerID: uuid.NullUUID{
UUID: pd.ID,
Valid: true,
},
Types: []database.ProvisionerType{database.ProvisionerTypeEcho},
})
require.NoError(t, err)
publishedWorkspace := make(chan struct{})
closeWorkspaceSubscribe, err := ps.Subscribe(codersdk.WorkspaceNotifyChannel(build.WorkspaceID), func(_ context.Context, _ []byte) {
close(publishedWorkspace)
})
require.NoError(t, err)
defer closeWorkspaceSubscribe()
publishedLogs := make(chan struct{})
closeLogsSubscribe, err := ps.Subscribe(provisionersdk.ProvisionerJobLogsNotifyChannel(job.ID), func(_ context.Context, _ []byte) {
close(publishedLogs)
})
require.NoError(t, err)
defer closeLogsSubscribe()
_, err = srv.CompleteJob(ctx, &proto.CompletedJob{
JobId: job.ID.String(),
Type: &proto.CompletedJob_WorkspaceBuild_{
WorkspaceBuild: &proto.CompletedJob_WorkspaceBuild{
State: []byte{},
Resources: []*sdkproto.Resource{{
Name: "example",
Type: "aws_instance",
}},
},
},
})
require.NoError(t, err)
<-publishedWorkspace
<-publishedLogs
workspace, err = db.GetWorkspaceByID(ctx, workspace.ID)
require.NoError(t, err)
require.Equal(t, c.transition == database.WorkspaceTransitionDelete, workspace.Deleted)
workspaceBuild, err := db.GetWorkspaceBuildByID(ctx, build.ID)
require.NoError(t, err)
if c.expectedTTL == 0 {
require.True(t, workspaceBuild.Deadline.IsZero())
} else {
require.WithinDuration(t, time.Now().Add(c.expectedTTL), workspaceBuild.Deadline, 15*time.Second, "deadline does not match expected")
}
if c.expectedMaxTTL == 0 {
require.True(t, workspaceBuild.MaxDeadline.IsZero())
} else {
require.WithinDuration(t, time.Now().Add(c.expectedMaxTTL), workspaceBuild.MaxDeadline, 15*time.Second, "max deadline does not match expected")
require.GreaterOrEqual(t, workspaceBuild.MaxDeadline.Unix(), workspaceBuild.Deadline.Unix(), "max deadline is smaller than deadline")
}
})
}
})
t.Run("WorkspaceBuild", func(t *testing.T) {
t.Parallel()
@@ -1386,7 +1144,6 @@ func TestCompleteJob(t *testing.T) {
UserAutostartEnabled: false,
UserAutostopEnabled: true,
DefaultTTL: 0,
UseMaxTTL: false,
AutostopRequirement: c.templateAutostopRequirement,
}, nil
},