Skip to content

feat: add controls to template for determining startup days #10226

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 14 commits into from
Oct 13, 2023
Prev Previous commit
Next Next commit
Add unit test to test blocking autostart with DaysOfWeek
  • Loading branch information
Emyrk committed Oct 13, 2023
commit db25e8456f577903bd4ed01846880a114a96960d
2 changes: 1 addition & 1 deletion coderd/schedule/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ var DaysOfWeek = []time.Weekday{

type TemplateAutostartRequirement struct {
// DaysOfWeek is a bitmap of which days of the week the workspace is allowed
// to be restarted. If fully zero, the workspace is not allowed to be restarted.
// to be auto started. If fully zero, the workspace is not allowed to be auto started.
//
// First bit is Monday, ..., seventh bit is Sunday, eighth bit is unused.
DaysOfWeek uint8
Expand Down
3 changes: 1 addition & 2 deletions enterprise/coderd/templates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,7 @@ func TestTemplates(t *testing.T) {
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
require.Equal(t, []string{"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"}, template.AutostartRequirement.DaysOfWeek)

// ctx := testutil.Context(t, testutil.WaitLong)
ctx := context.Background()
ctx := testutil.Context(t, testutil.WaitLong)
updated, err := client.UpdateTemplateMeta(ctx, template.ID, codersdk.UpdateTemplateMeta{
Name: template.Name,
DisplayName: template.DisplayName,
Expand Down
66 changes: 66 additions & 0 deletions enterprise/coderd/workspaces_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,65 @@ func TestWorkspaceAutobuild(t *testing.T) {
})
}

// Blocked by autostart requirements
func TestExecutorAutostartBlocked(t *testing.T) {
t.Parallel()

now := time.Now()
var allowed []string
for _, day := range agplschedule.DaysOfWeek {
// Skip the day the workspace was created on and if the next day is within 2
// hours, skip that too. The cron scheduler will start the workspace every hour,
// so it can span into the next day.
if day != now.UTC().Weekday() &&
day != now.UTC().Add(time.Hour*2).Weekday() {
allowed = append(allowed, day.String())
}
}

var (
sched = must(cron.Weekly("CRON_TZ=UTC 0 * * * *"))
tickCh = make(chan time.Time)
statsCh = make(chan autobuild.Stats)
client, owner = coderdenttest.New(t, &coderdenttest.Options{
Options: &coderdtest.Options{
AutobuildTicker: tickCh,
IncludeProvisionerDaemon: true,
AutobuildStats: statsCh,
TemplateScheduleStore: schedule.NewEnterpriseTemplateScheduleStore(agplUserQuietHoursScheduleStore()),
},
LicenseOptions: &coderdenttest.LicenseOptions{
Features: license.Features{codersdk.FeatureAdvancedTemplateScheduling: 1},
},
})
version = coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, nil)
template = coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID, func(request *codersdk.CreateTemplateRequest) {
request.AutostartRequirement = &codersdk.TemplateAutostartRequirement{
DaysOfWeek: allowed,
}
})
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
workspace = coderdtest.CreateWorkspace(t, client, owner.OrganizationID, template.ID, func(cwr *codersdk.CreateWorkspaceRequest) {
cwr.AutostartSchedule = ptr.Ref(sched.String())
})
_ = coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
)

// Given: workspace is stopped
workspace = coderdtest.MustTransitionWorkspace(t, client, workspace.ID, database.WorkspaceTransitionStart, database.WorkspaceTransitionStop)

// When: the autobuild executor ticks way into the future
go func() {
tickCh <- workspace.LatestBuild.CreatedAt.Add(24 * time.Hour)
close(tickCh)
}()

// Then: the workspace should not be started.
stats := <-statsCh
require.NoError(t, stats.Error)
require.Len(t, stats.Transitions, 0)
}

func TestWorkspacesFiltering(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -911,3 +970,10 @@ func TestWorkspaceLock(t *testing.T) {
require.True(t, workspace.LastUsedAt.After(lastUsedAt))
})
}

func must[T any](value T, err error) T {
if err != nil {
panic(err)
}
return value
}