Skip to content

Commit d6717f3

Browse files
committed
Merge branch 'main' into light-theme
2 parents ef3c623 + e84d893 commit d6717f3

28 files changed

+576
-161
lines changed

cli/testdata/coder_list_--output_json.golden

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"worker_id": "[workspace build worker ID]",
3737
"file_id": "[workspace build file ID]",
3838
"tags": {
39+
"owner": "",
3940
"scope": "organization"
4041
},
4142
"queue_position": 0,

coderd/agentapi/activitybump_test.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ func Test_ActivityBumpWorkspace(t *testing.T) {
4343
templateTTL time.Duration
4444
templateDisallowsUserAutostop bool
4545
expectedBump time.Duration
46-
nextAutostart time.Time
46+
// If the tests get queued, we need to be able to set the next autostart
47+
// based on the actual time the unit test is running.
48+
nextAutostart func(now time.Time) time.Time
4749
}{
4850
{
4951
name: "NotFinishedYet",
@@ -93,7 +95,7 @@ func Test_ActivityBumpWorkspace(t *testing.T) {
9395
buildDeadlineOffset: ptr.Ref(-30 * time.Minute),
9496
workspaceTTL: 8 * time.Hour,
9597
expectedBump: 8*time.Hour + 30*time.Minute,
96-
nextAutostart: time.Now().Add(time.Minute * 30),
98+
nextAutostart: func(now time.Time) time.Time { return now.Add(time.Minute * 30) },
9799
},
98100
{
99101
name: "MaxDeadline",
@@ -127,20 +129,24 @@ func Test_ActivityBumpWorkspace(t *testing.T) {
127129
// by the template TTL instead.
128130
name: "TemplateDisallowsUserAutostop",
129131
transition: database.WorkspaceTransitionStart,
130-
jobCompletedAt: sql.NullTime{Valid: true, Time: dbtime.Now().Add(-7 * time.Hour)},
132+
jobCompletedAt: sql.NullTime{Valid: true, Time: dbtime.Now().Add(-3 * time.Hour)},
131133
buildDeadlineOffset: ptr.Ref(-30 * time.Minute),
132134
workspaceTTL: 2 * time.Hour,
133135
templateTTL: 10 * time.Hour,
134136
templateDisallowsUserAutostop: true,
135137
expectedBump: 10*time.Hour + (time.Minute * 30),
136-
nextAutostart: time.Now().Add(time.Minute * 30),
138+
nextAutostart: func(now time.Time) time.Time { return now.Add(time.Minute * 30) },
137139
},
138140
} {
139141
tt := tt
140142
for _, tz := range timezones {
141143
tz := tz
142144
t.Run(tt.name+"/"+tz, func(t *testing.T) {
143145
t.Parallel()
146+
nextAutostart := tt.nextAutostart
147+
if tt.nextAutostart == nil {
148+
nextAutostart = func(now time.Time) time.Time { return time.Time{} }
149+
}
144150

145151
var (
146152
now = dbtime.Now()
@@ -237,7 +243,7 @@ func Test_ActivityBumpWorkspace(t *testing.T) {
237243

238244
// Bump duration is measured from the time of the bump, so we measure from here.
239245
start := dbtime.Now()
240-
agentapi.ActivityBumpWorkspace(ctx, log, db, bld.WorkspaceID, tt.nextAutostart)
246+
agentapi.ActivityBumpWorkspace(ctx, log, db, bld.WorkspaceID, nextAutostart(start))
241247
end := dbtime.Now()
242248

243249
// Validate our state after bump

coderd/coderd.go

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"crypto/tls"
66
"crypto/x509"
7+
"database/sql"
78
"flag"
89
"fmt"
910
"io"
@@ -49,6 +50,7 @@ import (
4950
"github.com/coder/coder/v2/coderd/batchstats"
5051
"github.com/coder/coder/v2/coderd/database"
5152
"github.com/coder/coder/v2/coderd/database/dbauthz"
53+
"github.com/coder/coder/v2/coderd/database/dbtime"
5254
"github.com/coder/coder/v2/coderd/database/pubsub"
5355
"github.com/coder/coder/v2/coderd/externalauth"
5456
"github.com/coder/coder/v2/coderd/gitsshkey"
@@ -1178,22 +1180,32 @@ func (api *API) CreateInMemoryProvisionerDaemon(ctx context.Context, name string
11781180
}
11791181
}()
11801182

1181-
tags := provisionerdserver.Tags{
1182-
provisionersdk.TagScope: provisionersdk.ScopeOrganization,
1183+
//nolint:gocritic // in-memory provisioners are owned by system
1184+
daemon, err := api.Database.UpsertProvisionerDaemon(dbauthz.AsSystemRestricted(ctx), database.UpsertProvisionerDaemonParams{
1185+
Name: name,
1186+
CreatedAt: dbtime.Now(),
1187+
Provisioners: []database.ProvisionerType{
1188+
database.ProvisionerTypeEcho, database.ProvisionerTypeTerraform,
1189+
},
1190+
Tags: provisionersdk.MutateTags(uuid.Nil, nil),
1191+
LastSeenAt: sql.NullTime{Time: dbtime.Now(), Valid: true},
1192+
Version: buildinfo.Version(),
1193+
APIVersion: "1.0",
1194+
})
1195+
if err != nil {
1196+
return nil, xerrors.Errorf("failed to create in-memory provisioner daemon: %w", err)
11831197
}
11841198

11851199
mux := drpcmux.New()
11861200
api.Logger.Info(ctx, "starting in-memory provisioner daemon", slog.F("name", name))
11871201
logger := api.Logger.Named(fmt.Sprintf("inmem-provisionerd-%s", name))
11881202
srv, err := provisionerdserver.NewServer(
1189-
api.ctx,
1203+
api.ctx, // use the same ctx as the API
11901204
api.AccessURL,
1191-
uuid.New(),
1205+
daemon.ID,
11921206
logger,
1193-
[]database.ProvisionerType{
1194-
database.ProvisionerTypeEcho, database.ProvisionerTypeTerraform,
1195-
},
1196-
tags,
1207+
daemon.Provisioners,
1208+
provisionerdserver.Tags(daemon.Tags),
11971209
api.Database,
11981210
api.Pubsub,
11991211
api.Acquirer,

coderd/coderdtest/coderdtest.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ func NewProvisionerDaemon(t testing.TB, coderAPI *coderd.API) io.Closer {
533533
}()
534534

535535
daemon := provisionerd.New(func(ctx context.Context) (provisionerdproto.DRPCProvisionerDaemonClient, error) {
536-
return coderAPI.CreateInMemoryProvisionerDaemon(ctx, t.Name())
536+
return coderAPI.CreateInMemoryProvisionerDaemon(ctx, "test")
537537
}, &provisionerd.Options{
538538
Logger: coderAPI.Logger.Named("provisionerd").Leveled(slog.LevelDebug),
539539
UpdateInterval: 250 * time.Millisecond,

coderd/database/dbauthz/dbauthz.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ var (
232232
rbac.ResourceOrganization.Type: {rbac.ActionCreate},
233233
rbac.ResourceOrganizationMember.Type: {rbac.ActionCreate},
234234
rbac.ResourceOrgRoleAssignment.Type: {rbac.ActionCreate},
235+
rbac.ResourceProvisionerDaemon.Type: {rbac.ActionCreate, rbac.ActionUpdate},
235236
rbac.ResourceUser.Type: {rbac.ActionCreate, rbac.ActionUpdate, rbac.ActionDelete},
236237
rbac.ResourceUserData.Type: {rbac.ActionCreate, rbac.ActionUpdate},
237238
rbac.ResourceWorkspace.Type: {rbac.ActionUpdate},
@@ -2499,6 +2500,13 @@ func (q *querier) UpdateMemberRoles(ctx context.Context, arg database.UpdateMemb
24992500
return q.db.UpdateMemberRoles(ctx, arg)
25002501
}
25012502

2503+
func (q *querier) UpdateProvisionerDaemonLastSeenAt(ctx context.Context, arg database.UpdateProvisionerDaemonLastSeenAtParams) error {
2504+
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceProvisionerDaemon); err != nil {
2505+
return err
2506+
}
2507+
return q.db.UpdateProvisionerDaemonLastSeenAt(ctx, arg)
2508+
}
2509+
25022510
// TODO: We need to create a ProvisionerJob resource type
25032511
func (q *querier) UpdateProvisionerJobByID(ctx context.Context, arg database.UpdateProvisionerJobByIDParams) error {
25042512
// if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil {

coderd/database/dbauthz/dbauthz_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,6 +1592,18 @@ func (s *MethodTestSuite) TestExtraMethods() {
15921592
s.NoError(err, "insert provisioner daemon")
15931593
check.Args().Asserts(rbac.ResourceSystem, rbac.ActionDelete)
15941594
}))
1595+
s.Run("UpdateProvisionerDaemonLastSeenAt", s.Subtest(func(db database.Store, check *expects) {
1596+
d, err := db.UpsertProvisionerDaemon(context.Background(), database.UpsertProvisionerDaemonParams{
1597+
Tags: database.StringMap(map[string]string{
1598+
provisionersdk.TagScope: provisionersdk.ScopeOrganization,
1599+
}),
1600+
})
1601+
s.NoError(err, "insert provisioner daemon")
1602+
check.Args(database.UpdateProvisionerDaemonLastSeenAtParams{
1603+
ID: d.ID,
1604+
LastSeenAt: sql.NullTime{Time: dbtime.Now(), Valid: true},
1605+
}).Asserts(rbac.ResourceProvisionerDaemon, rbac.ActionUpdate)
1606+
}))
15951607
}
15961608

15971609
// All functions in this method test suite are not implemented in dbmem, but

coderd/database/dbauthz/setup_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import (
2828
"github.com/coder/coder/v2/coderd/util/slice"
2929
)
3030

31-
var errMatchAny = errors.New("match any error")
31+
var errMatchAny = xerrors.New("match any error")
3232

3333
var skipMethods = map[string]string{
3434
"InTx": "Not relevant",

coderd/database/dbmem/dbmem.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5945,6 +5945,28 @@ func (q *FakeQuerier) UpdateMemberRoles(_ context.Context, arg database.UpdateMe
59455945
return database.OrganizationMember{}, sql.ErrNoRows
59465946
}
59475947

5948+
func (q *FakeQuerier) UpdateProvisionerDaemonLastSeenAt(_ context.Context, arg database.UpdateProvisionerDaemonLastSeenAtParams) error {
5949+
err := validateDatabaseType(arg)
5950+
if err != nil {
5951+
return err
5952+
}
5953+
5954+
q.mutex.Lock()
5955+
defer q.mutex.Unlock()
5956+
5957+
for idx := range q.provisionerDaemons {
5958+
if q.provisionerDaemons[idx].ID != arg.ID {
5959+
continue
5960+
}
5961+
if q.provisionerDaemons[idx].LastSeenAt.Time.After(arg.LastSeenAt.Time) {
5962+
continue
5963+
}
5964+
q.provisionerDaemons[idx].LastSeenAt = arg.LastSeenAt
5965+
return nil
5966+
}
5967+
return sql.ErrNoRows
5968+
}
5969+
59485970
func (q *FakeQuerier) UpdateProvisionerJobByID(_ context.Context, arg database.UpdateProvisionerJobByIDParams) error {
59495971
if err := validateDatabaseType(arg); err != nil {
59505972
return err

coderd/database/dbmetrics/dbmetrics.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbmock/dbmock.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dump.sql

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
DROP INDEX IF EXISTS idx_provisioner_daemons_name_owner_key;
2+
3+
CREATE UNIQUE INDEX IF NOT EXISTS idx_provisioner_daemons_name_owner_key
4+
ON provisioner_daemons
5+
USING btree (name, lower((tags->>'owner')::text));
6+
7+
COMMENT ON INDEX idx_provisioner_daemons_name_owner_key
8+
IS 'Relax uniqueness constraint for provisioner daemon names';
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
DROP INDEX IF EXISTS idx_provisioner_daemons_name_owner_key;
2+
3+
CREATE UNIQUE INDEX IF NOT EXISTS idx_provisioner_daemons_name_owner_key
4+
ON provisioner_daemons
5+
USING btree (name, LOWER(COALESCE(tags->>'owner', '')::text));
6+
7+
COMMENT ON INDEX idx_provisioner_daemons_name_owner_key
8+
IS 'Allow unique provisioner daemon names by user';

coderd/database/querier.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries.sql.go

Lines changed: 21 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/provisionerdaemons.sql

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ VALUES (
3535
@last_seen_at,
3636
@version,
3737
@api_version
38-
) ON CONFLICT("name", lower((tags ->> 'owner'::text))) DO UPDATE SET
38+
) ON CONFLICT("name", LOWER(COALESCE(tags ->> 'owner'::text, ''::text))) DO UPDATE SET
3939
provisioners = @provisioners,
4040
tags = @tags,
4141
last_seen_at = @last_seen_at,
@@ -45,3 +45,12 @@ WHERE
4545
-- Only ones with the same tags are allowed clobber
4646
provisioner_daemons.tags <@ @tags :: jsonb
4747
RETURNING *;
48+
49+
-- name: UpdateProvisionerDaemonLastSeenAt :exec
50+
UPDATE provisioner_daemons
51+
SET
52+
last_seen_at = @last_seen_at
53+
WHERE
54+
id = @id
55+
AND
56+
last_seen_at <= @last_seen_at;

coderd/database/unique_constraint.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)