Skip to content

feat: add template activity_bump property #11734

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 10 commits into from
Feb 13, 2024
Merged
23 changes: 17 additions & 6 deletions cli/templateedit.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func (r *RootCmd) templateEdit() *clibase.Cmd {
description string
icon string
defaultTTL time.Duration
activityBump time.Duration
maxTTL time.Duration
autostopRequirementDaysOfWeek []string
autostopRequirementWeeks int64
Expand Down Expand Up @@ -108,6 +109,10 @@ func (r *RootCmd) templateEdit() *clibase.Cmd {
defaultTTL = time.Duration(template.DefaultTTLMillis) * time.Millisecond
}

if !userSetOption(inv, "activity-bump") {
activityBump = time.Duration(template.ActivityBumpMillis) * time.Millisecond
}

if !userSetOption(inv, "allow-user-autostop") {
allowUserAutostop = template.AllowUserAutostop
}
Expand Down Expand Up @@ -168,12 +173,13 @@ func (r *RootCmd) templateEdit() *clibase.Cmd {
}

req := codersdk.UpdateTemplateMeta{
Name: name,
DisplayName: displayName,
Description: description,
Icon: icon,
DefaultTTLMillis: defaultTTL.Milliseconds(),
MaxTTLMillis: maxTTL.Milliseconds(),
Name: name,
DisplayName: displayName,
Description: description,
Icon: icon,
DefaultTTLMillis: defaultTTL.Milliseconds(),
ActivityBumpMillis: activityBump.Milliseconds(),
MaxTTLMillis: maxTTL.Milliseconds(),
AutostopRequirement: &codersdk.TemplateAutostopRequirement{
DaysOfWeek: autostopRequirementDaysOfWeek,
Weeks: autostopRequirementWeeks,
Expand Down Expand Up @@ -233,6 +239,11 @@ func (r *RootCmd) templateEdit() *clibase.Cmd {
Description: "Edit the template default time before shutdown - workspaces created from this template default to this value. Maps to \"Default autostop\" in the UI.",
Value: clibase.DurationOf(&defaultTTL),
},
{
Flag: "activity-bump",
Description: "Edit the template activity bump - workspaces created from this template will have their shutdown time bumped by this value when activity is detected. Maps to \"Activity bump\" in the UI.",
Value: clibase.DurationOf(&activityBump),
},
{
Flag: "max-ttl",
Description: "Edit the template maximum time before shutdown - workspaces created from this template must shutdown within the given duration after starting, regardless of user activity. This is an enterprise-only feature. Maps to \"Max lifetime\" in the UI.",
Expand Down
1 change: 1 addition & 0 deletions cli/templateedit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ func TestTemplateEdit(t *testing.T) {
"--description", template.Description,
"--icon", template.Icon,
"--default-ttl", (time.Duration(template.DefaultTTLMillis) * time.Millisecond).String(),
"--activity-bump", (time.Duration(template.ActivityBumpMillis) * time.Millisecond).String(),
"--allow-user-cancel-workspace-jobs=" + strconv.FormatBool(template.AllowUserCancelWorkspaceJobs),
}
inv, root := clitest.New(t, cmdArgs...)
Expand Down
5 changes: 5 additions & 0 deletions cli/testdata/coder_templates_edit_--help.golden
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ USAGE:
Edit the metadata of a template by name.

OPTIONS:
--activity-bump duration
Edit the template activity bump - workspaces created from this
template will have their shutdown time bumped by this value when
activity is detected. Maps to "Activity bump" in the UI.

--allow-user-autostart bool (default: true)
Allow users to configure autostart for workspaces on this template.
This can only be disabled in enterprise.
Expand Down
29 changes: 29 additions & 0 deletions coderd/agentapi/activitybump_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func Test_ActivityBumpWorkspace(t *testing.T) {
maxDeadlineOffset *time.Duration
workspaceTTL time.Duration
templateTTL time.Duration
templateActivityBump time.Duration
templateDisallowsUserAutostop bool
expectedBump time.Duration
// If the tests get queued, we need to be able to set the next autostart
Expand Down Expand Up @@ -137,6 +138,26 @@ func Test_ActivityBumpWorkspace(t *testing.T) {
expectedBump: 10*time.Hour + (time.Minute * 30),
nextAutostart: func(now time.Time) time.Time { return now.Add(time.Minute * 30) },
},
{
// Custom activity bump duration specified on the template.
name: "TemplateCustomActivityBump",
transition: database.WorkspaceTransitionStart,
jobCompletedAt: sql.NullTime{Valid: true, Time: dbtime.Now().Add(-30 * time.Minute)},
buildDeadlineOffset: ptr.Ref(-30 * time.Minute),
workspaceTTL: 8 * time.Hour,
templateActivityBump: 5 * time.Hour, // instead of default 1h
expectedBump: 5 * time.Hour,
},
{
// Activity bump duration is 0.
name: "TemplateCustomActivityBumpZero",
transition: database.WorkspaceTransitionStart,
jobCompletedAt: sql.NullTime{Valid: true, Time: dbtime.Now().Add(-30 * time.Minute)},
buildDeadlineOffset: ptr.Ref(-30 * time.Minute),
workspaceTTL: 8 * time.Hour,
templateActivityBump: -1, // negative values get changed to 0 in the test
expectedBump: 0,
},
} {
tt := tt
for _, tz := range timezones {
Expand Down Expand Up @@ -186,11 +207,19 @@ func Test_ActivityBumpWorkspace(t *testing.T) {
buildID = uuid.New()
)

activityBump := 1 * time.Hour
if tt.templateActivityBump < 0 {
// less than 0 => 0
activityBump = 0
} else if tt.templateActivityBump != 0 {
activityBump = tt.templateActivityBump
}
require.NoError(t, db.UpdateTemplateScheduleByID(ctx, database.UpdateTemplateScheduleByIDParams{
ID: template.ID,
UpdatedAt: dbtime.Now(),
AllowUserAutostop: !tt.templateDisallowsUserAutostop,
DefaultTTL: int64(tt.templateTTL),
ActivityBump: int64(activityBump),
}), "unexpected error updating template schedule")

var buildNumber int32 = 1
Expand Down
7 changes: 7 additions & 0 deletions coderd/apidoc/docs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions coderd/apidoc/swagger.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions coderd/database/dbmem/dbmem.go
Original file line number Diff line number Diff line change
Expand Up @@ -841,10 +841,14 @@ func (q *FakeQuerier) ActivityBumpWorkspace(ctx context.Context, arg database.Ac
if err != nil {
return err
}
if template.ActivityBump == 0 {
return nil
}
activityBump := time.Duration(template.ActivityBump)

var ttlDur time.Duration
if now.Add(time.Hour).After(arg.NextAutostart) && arg.NextAutostart.After(now) {
// Extend to TTL
if now.Add(activityBump).After(arg.NextAutostart) && arg.NextAutostart.After(now) {
// Extend to TTL (NOT activity bump)
add := arg.NextAutostart.Sub(now)
if workspace.Ttl.Valid && template.AllowUserAutostop {
add += time.Duration(workspace.Ttl.Int64)
Expand All @@ -853,7 +857,8 @@ func (q *FakeQuerier) ActivityBumpWorkspace(ctx context.Context, arg database.Ac
}
ttlDur = add
} else {
ttlDur = time.Hour
// Otherwise, default to regular activity bump duration.
ttlDur = activityBump
}

// Only bump if 5% of the deadline has passed.
Expand Down Expand Up @@ -6543,6 +6548,7 @@ func (q *FakeQuerier) UpdateTemplateScheduleByID(_ context.Context, arg database
tpl.AllowUserAutostop = arg.AllowUserAutostop
tpl.UpdatedAt = dbtime.Now()
tpl.DefaultTTL = arg.DefaultTTL
tpl.ActivityBump = arg.ActivityBump
tpl.UseMaxTtl = arg.UseMaxTtl
tpl.MaxTTL = arg.MaxTTL
tpl.AutostopRequirementDaysOfWeek = arg.AutostopRequirementDaysOfWeek
Expand Down
4 changes: 3 additions & 1 deletion coderd/database/dump.sql

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
DROP VIEW template_with_users;

ALTER TABLE templates DROP COLUMN activity_bump;

CREATE VIEW
template_with_users
AS
SELECT
templates.*,
coalesce(visible_users.avatar_url, '') AS created_by_avatar_url,
coalesce(visible_users.username, '') AS created_by_username
FROM
templates
LEFT JOIN
visible_users
ON
templates.created_by = visible_users.id;

COMMENT ON VIEW template_with_users IS 'Joins in the username + avatar url of the created by user.';
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
ALTER TABLE templates ADD COLUMN activity_bump bigint DEFAULT '3600000000000'::bigint NOT NULL; -- 1 hour

DROP VIEW template_with_users;

CREATE VIEW
template_with_users
AS
SELECT
templates.*,
coalesce(visible_users.avatar_url, '') AS created_by_avatar_url,
coalesce(visible_users.username, '') AS created_by_username
FROM
templates
LEFT JOIN
visible_users
ON
templates.created_by = visible_users.id;

COMMENT ON VIEW template_with_users IS 'Joins in the username + avatar url of the created by user.';
1 change: 1 addition & 0 deletions coderd/database/modelqueries.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ func (q *sqlQuerier) GetAuthorizedTemplates(ctx context.Context, arg GetTemplate
&i.RequireActiveVersion,
&i.Deprecated,
&i.UseMaxTtl,
&i.ActivityBump,
&i.CreatedByAvatarURL,
&i.CreatedByUsername,
); err != nil {
Expand Down
6 changes: 4 additions & 2 deletions coderd/database/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 7 additions & 5 deletions coderd/database/querier.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading