From 0b83f17337a5e99f218ba58721e08eef236dac65 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 13 Mar 2024 10:23:27 -0500 Subject: [PATCH 01/14] chore: add org ID as optional param to AcquireJob It should be made mandatory in the future --- coderd/database/queries.sql.go | 25 +++++++++++++++------ coderd/database/queries/provisionerjobs.sql | 9 ++++++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 888515f49f404..68bf3bdb4a650 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -3941,14 +3941,23 @@ WHERE provisioner_jobs AS nested WHERE nested.started_at IS NULL + AND CASE + -- For backwards compatibility, the old provisionerd api did + -- not take organization_id as a parameter. In the future if + -- we scope provisioner auth to a given org, we can apply + -- this argument for the caller. + WHEN $3 :: uuid != '00000000-0000-0000-0000-000000000000'::uuid + THEN nested.organization_id = $3 + ELSE TRUE + END -- Ensure the caller has the correct provisioner. - AND nested.provisioner = ANY($3 :: provisioner_type [ ]) + AND nested.provisioner = ANY($4 :: provisioner_type [ ]) AND CASE -- Special case for untagged provisioners: only match untagged jobs. WHEN nested.tags :: jsonb = '{"scope": "organization", "owner": ""}' :: jsonb - THEN nested.tags :: jsonb = $4 :: jsonb + THEN nested.tags :: jsonb = $5 :: jsonb -- Ensure the caller satisfies all job tags. - ELSE nested.tags :: jsonb <@ $4 :: jsonb + ELSE nested.tags :: jsonb <@ $5 :: jsonb END ORDER BY nested.created_at @@ -3960,10 +3969,11 @@ WHERE ` type AcquireProvisionerJobParams struct { - StartedAt sql.NullTime `db:"started_at" json:"started_at"` - WorkerID uuid.NullUUID `db:"worker_id" json:"worker_id"` - Types []ProvisionerType `db:"types" json:"types"` - Tags json.RawMessage `db:"tags" json:"tags"` + StartedAt sql.NullTime `db:"started_at" json:"started_at"` + WorkerID uuid.NullUUID `db:"worker_id" json:"worker_id"` + OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"` + Types []ProvisionerType `db:"types" json:"types"` + Tags json.RawMessage `db:"tags" json:"tags"` } // Acquires the lock for a single job that isn't started, completed, @@ -3976,6 +3986,7 @@ func (q *sqlQuerier) AcquireProvisionerJob(ctx context.Context, arg AcquireProvi row := q.db.QueryRowContext(ctx, acquireProvisionerJob, arg.StartedAt, arg.WorkerID, + arg.OrganizationID, pq.Array(arg.Types), arg.Tags, ) diff --git a/coderd/database/queries/provisionerjobs.sql b/coderd/database/queries/provisionerjobs.sql index 1746cd1c59c5d..6ed8358e4af03 100644 --- a/coderd/database/queries/provisionerjobs.sql +++ b/coderd/database/queries/provisionerjobs.sql @@ -19,6 +19,15 @@ WHERE provisioner_jobs AS nested WHERE nested.started_at IS NULL + AND CASE + -- For backwards compatibility, the old provisionerd api did + -- not take organization_id as a parameter. In the future if + -- we scope provisioner auth to a given org, we can apply + -- this argument for the caller. + WHEN @organization_id :: uuid != '00000000-0000-0000-0000-000000000000'::uuid + THEN nested.organization_id = @organization_id + ELSE TRUE + END -- Ensure the caller has the correct provisioner. AND nested.provisioner = ANY(@types :: provisioner_type [ ]) AND CASE From eb7b156d7ef328949b223f6d43bf3e2cdc04c41b Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 13 Mar 2024 10:26:12 -0500 Subject: [PATCH 02/14] chore: plumb through organization id to provisioner daemons --- coderd/coderd.go | 1 + .../provisionerdserver/provisionerdserver.go | 3 +++ .../provisionerdserver_test.go | 19 ++++++++++++------- enterprise/coderd/provisionerdaemons.go | 1 + 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/coderd/coderd.go b/coderd/coderd.go index 759c9450d99f4..d6255ebf65a00 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -1271,6 +1271,7 @@ func (api *API) CreateInMemoryProvisionerDaemon(dialCtx context.Context, name st api.ctx, // use the same ctx as the API api.AccessURL, daemon.ID, + defaultOrg.ID, logger, daemon.Provisioners, provisionerdserver.Tags(daemon.Tags), diff --git a/coderd/provisionerdserver/provisionerdserver.go b/coderd/provisionerdserver/provisionerdserver.go index 8fd034b44659d..4d78cd7ab4948 100644 --- a/coderd/provisionerdserver/provisionerdserver.go +++ b/coderd/provisionerdserver/provisionerdserver.go @@ -81,6 +81,7 @@ type server struct { lifecycleCtx context.Context AccessURL *url.URL ID uuid.UUID + OrganizationID uuid.UUID Logger slog.Logger Provisioners []database.ProvisionerType ExternalAuthConfigs []*externalauth.Config @@ -134,6 +135,7 @@ func NewServer( lifecycleCtx context.Context, accessURL *url.URL, id uuid.UUID, + organizationID uuid.UUID, logger slog.Logger, provisioners []database.ProvisionerType, tags Tags, @@ -188,6 +190,7 @@ func NewServer( lifecycleCtx: lifecycleCtx, AccessURL: accessURL, ID: id, + OrganizationID: organizationID, Logger: logger, Provisioners: provisioners, ExternalAuthConfigs: options.ExternalAuthConfigs, diff --git a/coderd/provisionerdserver/provisionerdserver_test.go b/coderd/provisionerdserver/provisionerdserver_test.go index 095f5c30d3add..49e27b29f3d1d 100644 --- a/coderd/provisionerdserver/provisionerdserver_test.go +++ b/coderd/provisionerdserver/provisionerdserver_test.go @@ -1733,6 +1733,9 @@ func setup(t *testing.T, ignoreLogErrors bool, ov *overrides) (proto.DRPCProvisi logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) db := dbmem.New() ps := pubsub.NewInMemory() + defOrg, err := db.GetDefaultOrganization(context.Background()) + require.NoError(t, err, "default org not found") + deploymentValues := &codersdk.DeploymentValues{} var externalAuthConfigs []*externalauth.Config tss := testTemplateScheduleStore() @@ -1780,13 +1783,14 @@ func setup(t *testing.T, ignoreLogErrors bool, ov *overrides) (proto.DRPCProvisi pollDur = ov.acquireJobLongPollDuration daemon, err := db.UpsertProvisionerDaemon(ov.ctx, database.UpsertProvisionerDaemonParams{ - Name: "test", - CreatedAt: dbtime.Now(), - Provisioners: []database.ProvisionerType{database.ProvisionerTypeEcho}, - Tags: database.StringMap{}, - LastSeenAt: sql.NullTime{}, - Version: buildinfo.Version(), - APIVersion: proto.CurrentVersion.String(), + Name: "test", + CreatedAt: dbtime.Now(), + Provisioners: []database.ProvisionerType{database.ProvisionerTypeEcho}, + Tags: database.StringMap{}, + LastSeenAt: sql.NullTime{}, + Version: buildinfo.Version(), + APIVersion: proto.CurrentVersion.String(), + OrganizationID: defOrg.ID, }) require.NoError(t, err) @@ -1794,6 +1798,7 @@ func setup(t *testing.T, ignoreLogErrors bool, ov *overrides) (proto.DRPCProvisi ov.ctx, &url.URL{}, daemon.ID, + defOrg.ID, slogtest.Make(t, &slogtest.Options{IgnoreErrors: ignoreLogErrors}), []database.ProvisionerType{database.ProvisionerTypeEcho}, provisionerdserver.Tags(daemon.Tags), diff --git a/enterprise/coderd/provisionerdaemons.go b/enterprise/coderd/provisionerdaemons.go index 38d48bec62544..fdf03c2030807 100644 --- a/enterprise/coderd/provisionerdaemons.go +++ b/enterprise/coderd/provisionerdaemons.go @@ -317,6 +317,7 @@ func (api *API) provisionerDaemonServe(rw http.ResponseWriter, r *http.Request) srvCtx, api.AccessURL, daemon.ID, + organization.ID, logger, provisioners, tags, From d26216e240006adc29d2a00ffde234103f463a50 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 14 Mar 2024 12:43:20 -0500 Subject: [PATCH 03/14] add org id to provisioner domain key --- coderd/provisionerdserver/acquirer.go | 18 ++++++---- coderd/provisionerdserver/acquirer_test.go | 33 ++++++++++++------- .../provisionerdserver/provisionerdserver.go | 4 +-- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/coderd/provisionerdserver/acquirer.go b/coderd/provisionerdserver/acquirer.go index c9a43d660b671..439791dbbcc44 100644 --- a/coderd/provisionerdserver/acquirer.go +++ b/coderd/provisionerdserver/acquirer.go @@ -89,16 +89,17 @@ func NewAcquirer(ctx context.Context, logger slog.Logger, store AcquirerStore, p // done, or the database returns an error _other_ than that no jobs are available. // If no jobs are available, this method handles retrying as appropriate. func (a *Acquirer) AcquireJob( - ctx context.Context, worker uuid.UUID, pt []database.ProvisionerType, tags Tags, + ctx context.Context, organization uuid.UUID, worker uuid.UUID, pt []database.ProvisionerType, tags Tags, ) ( retJob database.ProvisionerJob, retErr error, ) { logger := a.logger.With( + slog.F("organization_id", organization), slog.F("worker_id", worker), slog.F("provisioner_types", pt), slog.F("tags", tags)) logger.Debug(ctx, "acquiring job") - dk := domainKey(pt, tags) + dk := domainKey(organization, pt, tags) dbTags, err := tags.ToJSON() if err != nil { return database.ProvisionerJob{}, err @@ -106,7 +107,7 @@ func (a *Acquirer) AcquireJob( // buffer of 1 so that cancel doesn't deadlock while writing to the channel clearance := make(chan struct{}, 1) for { - a.want(pt, tags, clearance) + a.want(organization, pt, tags, clearance) select { case <-ctx.Done(): err := ctx.Err() @@ -152,8 +153,8 @@ func (a *Acquirer) AcquireJob( } // want signals that an acquiree wants clearance to query for a job with the given dKey. -func (a *Acquirer) want(pt []database.ProvisionerType, tags Tags, clearance chan<- struct{}) { - dk := domainKey(pt, tags) +func (a *Acquirer) want(organization uuid.UUID, pt []database.ProvisionerType, tags Tags, clearance chan<- struct{}) { + dk := domainKey(organization, pt, tags) a.mu.Lock() defer a.mu.Unlock() cleared := false @@ -404,13 +405,16 @@ type dKey string // unprintable control character and won't show up in any "reasonable" set of // string tags, even in non-Latin scripts. It is important that Tags are // validated not to contain this control character prior to use. -func domainKey(pt []database.ProvisionerType, tags Tags) dKey { +func domainKey(orgID uuid.UUID, pt []database.ProvisionerType, tags Tags) dKey { + sb := strings.Builder{} + _, _ = sb.WriteString(orgID.String()) + _ = sb.WriteByte(0x00) + // make a copy of pt before sorting, so that we don't mutate the original // slice or underlying array. pts := make([]database.ProvisionerType, len(pt)) copy(pts, pt) slices.Sort(pts) - sb := strings.Builder{} for _, t := range pts { _, _ = sb.WriteString(string(t)) _ = sb.WriteByte(0x00) diff --git a/coderd/provisionerdserver/acquirer_test.go b/coderd/provisionerdserver/acquirer_test.go index 6d213f082d7b4..8f55313146efc 100644 --- a/coderd/provisionerdserver/acquirer_test.go +++ b/coderd/provisionerdserver/acquirer_test.go @@ -53,12 +53,13 @@ func TestAcquirer_Single(t *testing.T) { logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) uut := provisionerdserver.NewAcquirer(ctx, logger.Named("acquirer"), fs, ps) + orgID := uuid.New() workerID := uuid.New() pt := []database.ProvisionerType{database.ProvisionerTypeEcho} tags := provisionerdserver.Tags{ "environment": "on-prem", } - acquiree := newTestAcquiree(t, workerID, pt, tags) + acquiree := newTestAcquiree(t, orgID, workerID, pt, tags) jobID := uuid.New() err := fs.sendCtx(ctx, database.ProvisionerJob{ID: jobID}, nil) require.NoError(t, err) @@ -82,6 +83,7 @@ func TestAcquirer_MultipleSameDomain(t *testing.T) { acquirees := make([]*testAcquiree, 0, 10) jobIDs := make(map[uuid.UUID]bool) workerIDs := make(map[uuid.UUID]bool) + orgID := uuid.New() pt := []database.ProvisionerType{database.ProvisionerTypeEcho} tags := provisionerdserver.Tags{ "environment": "on-prem", @@ -89,7 +91,7 @@ func TestAcquirer_MultipleSameDomain(t *testing.T) { for i := 0; i < 10; i++ { wID := uuid.New() workerIDs[wID] = true - a := newTestAcquiree(t, wID, pt, tags) + a := newTestAcquiree(t, orgID, wID, pt, tags) acquirees = append(acquirees, a) a.startAcquire(ctx, uut) } @@ -124,12 +126,13 @@ func TestAcquirer_WaitsOnNoJobs(t *testing.T) { logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) uut := provisionerdserver.NewAcquirer(ctx, logger.Named("acquirer"), fs, ps) + orgID := uuid.New() workerID := uuid.New() pt := []database.ProvisionerType{database.ProvisionerTypeEcho} tags := provisionerdserver.Tags{ "environment": "on-prem", } - acquiree := newTestAcquiree(t, workerID, pt, tags) + acquiree := newTestAcquiree(t, orgID, workerID, pt, tags) jobID := uuid.New() err := fs.sendCtx(ctx, database.ProvisionerJob{}, sql.ErrNoRows) require.NoError(t, err) @@ -175,12 +178,13 @@ func TestAcquirer_RetriesPending(t *testing.T) { logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) uut := provisionerdserver.NewAcquirer(ctx, logger.Named("acquirer"), fs, ps) + orgID := uuid.New() workerID := uuid.New() pt := []database.ProvisionerType{database.ProvisionerTypeEcho} tags := provisionerdserver.Tags{ "environment": "on-prem", } - acquiree := newTestAcquiree(t, workerID, pt, tags) + acquiree := newTestAcquiree(t, orgID, workerID, pt, tags) jobID := uuid.New() acquiree.startAcquire(ctx, uut) @@ -217,17 +221,18 @@ func TestAcquirer_DifferentDomains(t *testing.T) { defer cancel() logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) + orgID := uuid.New() pt := []database.ProvisionerType{database.ProvisionerTypeEcho} worker0 := uuid.New() tags0 := provisionerdserver.Tags{ "worker": "0", } - acquiree0 := newTestAcquiree(t, worker0, pt, tags0) + acquiree0 := newTestAcquiree(t, orgID, worker0, pt, tags0) worker1 := uuid.New() tags1 := provisionerdserver.Tags{ "worker": "1", } - acquiree1 := newTestAcquiree(t, worker1, pt, tags1) + acquiree1 := newTestAcquiree(t, orgID, worker1, pt, tags1) jobID := uuid.New() fs.jobs = []database.ProvisionerJob{ {ID: jobID, Provisioner: database.ProvisionerTypeEcho, Tags: database.StringMap{"worker": "1"}}, @@ -268,11 +273,12 @@ func TestAcquirer_BackupPoll(t *testing.T) { ) workerID := uuid.New() + orgID := uuid.New() pt := []database.ProvisionerType{database.ProvisionerTypeEcho} tags := provisionerdserver.Tags{ "environment": "on-prem", } - acquiree := newTestAcquiree(t, workerID, pt, tags) + acquiree := newTestAcquiree(t, orgID, workerID, pt, tags) jobID := uuid.New() err := fs.sendCtx(ctx, database.ProvisionerJob{}, sql.ErrNoRows) require.NoError(t, err) @@ -294,13 +300,14 @@ func TestAcquirer_UnblockOnCancel(t *testing.T) { logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) pt := []database.ProvisionerType{database.ProvisionerTypeEcho} + orgID := uuid.New() worker0 := uuid.New() tags := provisionerdserver.Tags{ "environment": "on-prem", } - acquiree0 := newTestAcquiree(t, worker0, pt, tags) + acquiree0 := newTestAcquiree(t, orgID, worker0, pt, tags) worker1 := uuid.New() - acquiree1 := newTestAcquiree(t, worker1, pt, tags) + acquiree1 := newTestAcquiree(t, orgID, worker1, pt, tags) jobID := uuid.New() uut := provisionerdserver.NewAcquirer(ctx, logger.Named("acquirer"), fs, ps) @@ -486,7 +493,7 @@ func TestAcquirer_MatchTags(t *testing.T) { require.NoError(t, err) ptypes := []database.ProvisionerType{database.ProvisionerTypeEcho} acq := provisionerdserver.NewAcquirer(ctx, log, db, ps) - aj, err := acq.AcquireJob(ctx, uuid.New(), ptypes, tt.acquireJobTags) + aj, err := acq.AcquireJob(ctx, org.ID, uuid.New(), ptypes, tt.acquireJobTags) if tt.expectAcquire { assert.NoError(t, err) assert.Equal(t, pj.ID, aj.ID) @@ -659,6 +666,7 @@ jobLoop: // and asserting whether or not it returns, blocks, or is canceled. type testAcquiree struct { t *testing.T + orgID uuid.UUID workerID uuid.UUID pt []database.ProvisionerType tags provisionerdserver.Tags @@ -666,9 +674,10 @@ type testAcquiree struct { jc chan database.ProvisionerJob } -func newTestAcquiree(t *testing.T, workerID uuid.UUID, pt []database.ProvisionerType, tags provisionerdserver.Tags) *testAcquiree { +func newTestAcquiree(t *testing.T, orgID uuid.UUID, workerID uuid.UUID, pt []database.ProvisionerType, tags provisionerdserver.Tags) *testAcquiree { return &testAcquiree{ t: t, + orgID: orgID, workerID: workerID, pt: pt, tags: tags, @@ -679,7 +688,7 @@ func newTestAcquiree(t *testing.T, workerID uuid.UUID, pt []database.Provisioner func (a *testAcquiree) startAcquire(ctx context.Context, uut *provisionerdserver.Acquirer) { go func() { - j, e := uut.AcquireJob(ctx, a.workerID, a.pt, a.tags) + j, e := uut.AcquireJob(ctx, a.orgID, a.workerID, a.pt, a.tags) a.ec <- e a.jc <- j }() diff --git a/coderd/provisionerdserver/provisionerdserver.go b/coderd/provisionerdserver/provisionerdserver.go index 4d78cd7ab4948..8605cc5c84f38 100644 --- a/coderd/provisionerdserver/provisionerdserver.go +++ b/coderd/provisionerdserver/provisionerdserver.go @@ -290,7 +290,7 @@ func (s *server) AcquireJob(ctx context.Context, _ *proto.Empty) (*proto.Acquire // database. acqCtx, acqCancel := context.WithTimeout(ctx, s.acquireJobLongPollDur) defer acqCancel() - job, err := s.Acquirer.AcquireJob(acqCtx, s.ID, s.Provisioners, s.Tags) + job, err := s.Acquirer.AcquireJob(acqCtx, s.OrganizationID, s.ID, s.Provisioners, s.Tags) if xerrors.Is(err, context.DeadlineExceeded) { s.Logger.Debug(ctx, "successful cancel") return &proto.AcquiredJob{}, nil @@ -327,7 +327,7 @@ func (s *server) AcquireJobWithCancel(stream proto.DRPCProvisionerDaemon_Acquire }() jec := make(chan jobAndErr, 1) go func() { - job, err := s.Acquirer.AcquireJob(acqCtx, s.ID, s.Provisioners, s.Tags) + job, err := s.Acquirer.AcquireJob(acqCtx, s.OrganizationID, s.ID, s.Provisioners, s.Tags) jec <- jobAndErr{job: job, err: err} }() var recvErr error From 71489c244c07680277cba84e1459c64fa217693a Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 14 Mar 2024 12:53:15 -0500 Subject: [PATCH 04/14] enforce org id argument --- coderd/database/queries.sql.go | 10 +--------- coderd/database/queries/provisionerjobs.sql | 10 +--------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 68bf3bdb4a650..6f9ee9abe30f4 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -3941,15 +3941,7 @@ WHERE provisioner_jobs AS nested WHERE nested.started_at IS NULL - AND CASE - -- For backwards compatibility, the old provisionerd api did - -- not take organization_id as a parameter. In the future if - -- we scope provisioner auth to a given org, we can apply - -- this argument for the caller. - WHEN $3 :: uuid != '00000000-0000-0000-0000-000000000000'::uuid - THEN nested.organization_id = $3 - ELSE TRUE - END + AND nested.organization_id = $3 -- Ensure the caller has the correct provisioner. AND nested.provisioner = ANY($4 :: provisioner_type [ ]) AND CASE diff --git a/coderd/database/queries/provisionerjobs.sql b/coderd/database/queries/provisionerjobs.sql index 6ed8358e4af03..d1d5f68ce750e 100644 --- a/coderd/database/queries/provisionerjobs.sql +++ b/coderd/database/queries/provisionerjobs.sql @@ -19,15 +19,7 @@ WHERE provisioner_jobs AS nested WHERE nested.started_at IS NULL - AND CASE - -- For backwards compatibility, the old provisionerd api did - -- not take organization_id as a parameter. In the future if - -- we scope provisioner auth to a given org, we can apply - -- this argument for the caller. - WHEN @organization_id :: uuid != '00000000-0000-0000-0000-000000000000'::uuid - THEN nested.organization_id = @organization_id - ELSE TRUE - END + AND nested.organization_id = @organization_id -- Ensure the caller has the correct provisioner. AND nested.provisioner = ANY(@types :: provisioner_type [ ]) AND CASE From 752b86784f0f7f9e92d021edbaa5c1d142fa0a52 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 14 Mar 2024 13:20:56 -0500 Subject: [PATCH 05/14] use new org field --- coderd/database/dbfake/dbfake.go | 1 + coderd/database/dbgen/dbgen.go | 9 +++++---- coderd/database/dbmem/dbmem.go | 3 +++ coderd/database/querier_test.go | 1 + coderd/prometheusmetrics/prometheusmetrics_test.go | 1 + coderd/provisionerdserver/acquirer.go | 1 + 6 files changed, 12 insertions(+), 4 deletions(-) diff --git a/coderd/database/dbfake/dbfake.go b/coderd/database/dbfake/dbfake.go index b871089789096..5115ef96d9007 100644 --- a/coderd/database/dbfake/dbfake.go +++ b/coderd/database/dbfake/dbfake.go @@ -187,6 +187,7 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse { // import job as well for { j, err := b.db.AcquireProvisionerJob(ownerCtx, database.AcquireProvisionerJobParams{ + OrganizationID: job.OrganizationID, StartedAt: sql.NullTime{ Time: dbtime.Now(), Valid: true, diff --git a/coderd/database/dbgen/dbgen.go b/coderd/database/dbgen/dbgen.go index 59dbbb97154d3..63df3099ac343 100644 --- a/coderd/database/dbgen/dbgen.go +++ b/coderd/database/dbgen/dbgen.go @@ -418,10 +418,11 @@ func ProvisionerJob(t testing.TB, db database.Store, ps pubsub.Pubsub, orig data } if !orig.StartedAt.Time.IsZero() { job, err = db.AcquireProvisionerJob(genCtx, database.AcquireProvisionerJobParams{ - StartedAt: orig.StartedAt, - Types: []database.ProvisionerType{database.ProvisionerTypeEcho}, - Tags: must(json.Marshal(orig.Tags)), - WorkerID: uuid.NullUUID{}, + StartedAt: orig.StartedAt, + OrganizationID: job.OrganizationID, + Types: []database.ProvisionerType{database.ProvisionerTypeEcho}, + Tags: must(json.Marshal(orig.Tags)), + WorkerID: uuid.NullUUID{}, }) require.NoError(t, err) // There is no easy way to make sure we acquire the correct job. diff --git a/coderd/database/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go index 898d257790797..2fdfcc2eca54c 100644 --- a/coderd/database/dbmem/dbmem.go +++ b/coderd/database/dbmem/dbmem.go @@ -803,6 +803,9 @@ func (q *FakeQuerier) AcquireProvisionerJob(_ context.Context, arg database.Acqu defer q.mutex.Unlock() for index, provisionerJob := range q.provisionerJobs { + if provisionerJob.OrganizationID != arg.OrganizationID { + continue + } if provisionerJob.StartedAt.Valid { continue } diff --git a/coderd/database/querier_test.go b/coderd/database/querier_test.go index ae64260db35b4..c3e1f2e46b3db 100644 --- a/coderd/database/querier_test.go +++ b/coderd/database/querier_test.go @@ -363,6 +363,7 @@ func TestQueuePosition(t *testing.T) { } job, err := db.AcquireProvisionerJob(ctx, database.AcquireProvisionerJobParams{ + OrganizationID: org.ID, StartedAt: sql.NullTime{ Time: dbtime.Now(), Valid: true, diff --git a/coderd/prometheusmetrics/prometheusmetrics_test.go b/coderd/prometheusmetrics/prometheusmetrics_test.go index 47ddb830c4cfb..3992792266c65 100644 --- a/coderd/prometheusmetrics/prometheusmetrics_test.go +++ b/coderd/prometheusmetrics/prometheusmetrics_test.go @@ -134,6 +134,7 @@ func TestWorkspaces(t *testing.T) { require.NoError(t, err) // This marks the job as started. _, err = db.AcquireProvisionerJob(context.Background(), database.AcquireProvisionerJobParams{ + OrganizationID: job.OrganizationID, StartedAt: sql.NullTime{ Time: dbtime.Now(), Valid: true, diff --git a/coderd/provisionerdserver/acquirer.go b/coderd/provisionerdserver/acquirer.go index 439791dbbcc44..3bf99992c9d3d 100644 --- a/coderd/provisionerdserver/acquirer.go +++ b/coderd/provisionerdserver/acquirer.go @@ -121,6 +121,7 @@ func (a *Acquirer) AcquireJob( case <-clearance: logger.Debug(ctx, "got clearance to call database") job, err := a.store.AcquireProvisionerJob(ctx, database.AcquireProvisionerJobParams{ + OrganizationID: organization, StartedAt: sql.NullTime{ Time: dbtime.Now(), Valid: true, From f2a7432a452a047f37aa98d3bd18f9f2b9402c29 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 14 Mar 2024 15:13:24 -0500 Subject: [PATCH 06/14] fix authz test --- coderd/database/dbauthz/dbauthz_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/database/dbauthz/dbauthz_test.go b/coderd/database/dbauthz/dbauthz_test.go index 65b18b01fb2f1..140cfa87a65c9 100644 --- a/coderd/database/dbauthz/dbauthz_test.go +++ b/coderd/database/dbauthz/dbauthz_test.go @@ -2093,7 +2093,7 @@ func (s *MethodTestSuite) TestSystemFunctions() { j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ StartedAt: sql.NullTime{Valid: false}, }) - check.Args(database.AcquireProvisionerJobParams{Types: []database.ProvisionerType{j.Provisioner}, Tags: must(json.Marshal(j.Tags))}). + check.Args(database.AcquireProvisionerJobParams{OrganizationID: j.OrganizationID, Types: []database.ProvisionerType{j.Provisioner}, Tags: must(json.Marshal(j.Tags))}). Asserts( /*rbac.ResourceSystem, rbac.ActionUpdate*/ ) })) s.Run("UpdateProvisionerJobWithCompleteByID", s.Subtest(func(db database.Store, check *expects) { From baf1f280f146cbba0b17a0df03e78fe78d8764e8 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 14 Mar 2024 15:18:18 -0500 Subject: [PATCH 07/14] dbgen default to default org --- coderd/database/dbgen/dbgen.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/coderd/database/dbgen/dbgen.go b/coderd/database/dbgen/dbgen.go index 63df3099ac343..da5f214e7f314 100644 --- a/coderd/database/dbgen/dbgen.go +++ b/coderd/database/dbgen/dbgen.go @@ -387,6 +387,12 @@ func GroupMember(t testing.TB, db database.Store, orig database.GroupMember) dat func ProvisionerJob(t testing.TB, db database.Store, ps pubsub.Pubsub, orig database.ProvisionerJob) database.ProvisionerJob { t.Helper() + var defOrgID uuid.UUID + if orig.OrganizationID == uuid.Nil { + defOrg, _ := db.GetDefaultOrganization(genCtx) + defOrgID = defOrg.ID + } + jobID := takeFirst(orig.ID, uuid.New()) // Always set some tags to prevent Acquire from grabbing jobs it should not. if !orig.StartedAt.Time.IsZero() { @@ -401,7 +407,7 @@ func ProvisionerJob(t testing.TB, db database.Store, ps pubsub.Pubsub, orig data ID: jobID, CreatedAt: takeFirst(orig.CreatedAt, dbtime.Now()), UpdatedAt: takeFirst(orig.UpdatedAt, dbtime.Now()), - OrganizationID: takeFirst(orig.OrganizationID, uuid.New()), + OrganizationID: takeFirst(orig.OrganizationID, defOrgID, uuid.New()), InitiatorID: takeFirst(orig.InitiatorID, uuid.New()), Provisioner: takeFirst(orig.Provisioner, database.ProvisionerTypeEcho), StorageMethod: takeFirst(orig.StorageMethod, database.ProvisionerStorageMethodFile), From 71ea66fc776745c4ebb8c9e9513bbc68fa638736 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 14 Mar 2024 15:35:00 -0500 Subject: [PATCH 08/14] dbfake upsert provisioner fixed --- coderd/database/dbmem/dbmem.go | 19 +-- .../provisionerdserver_test.go | 131 ++++++++++-------- 2 files changed, 87 insertions(+), 63 deletions(-) diff --git a/coderd/database/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go index 2fdfcc2eca54c..81c284871b520 100644 --- a/coderd/database/dbmem/dbmem.go +++ b/coderd/database/dbmem/dbmem.go @@ -7874,15 +7874,16 @@ func (q *FakeQuerier) UpsertProvisionerDaemon(_ context.Context, arg database.Up } } d := database.ProvisionerDaemon{ - ID: uuid.New(), - CreatedAt: arg.CreatedAt, - Name: arg.Name, - Provisioners: arg.Provisioners, - Tags: maps.Clone(arg.Tags), - ReplicaID: uuid.NullUUID{}, - LastSeenAt: arg.LastSeenAt, - Version: arg.Version, - APIVersion: arg.APIVersion, + ID: uuid.New(), + CreatedAt: arg.CreatedAt, + Name: arg.Name, + Provisioners: arg.Provisioners, + Tags: maps.Clone(arg.Tags), + ReplicaID: uuid.NullUUID{}, + LastSeenAt: arg.LastSeenAt, + Version: arg.Version, + APIVersion: arg.APIVersion, + OrganizationID: arg.OrganizationID, } q.provisionerDaemons = append(q.provisionerDaemons, d) return d, nil diff --git a/coderd/provisionerdserver/provisionerdserver_test.go b/coderd/provisionerdserver/provisionerdserver_test.go index 49e27b29f3d1d..674ecc97f2889 100644 --- a/coderd/provisionerdserver/provisionerdserver_test.go +++ b/coderd/provisionerdserver/provisionerdserver_test.go @@ -65,7 +65,7 @@ func testUserQuietHoursScheduleStore() *atomic.Pointer[schedule.UserQuietHoursSc return ptr } -func TestAcquireJob_LongPoll(t *testing.T) { +func cTestAcquireJob_LongPoll(t *testing.T) { t.Parallel() //nolint:dogsled srv, _, _, _ := setup(t, false, &overrides{acquireJobLongPollDuration: time.Microsecond}) @@ -152,15 +152,17 @@ func TestAcquireJob(t *testing.T) { tc := tc t.Run(tc.name+"_InitiatorNotFound", func(t *testing.T) { t.Parallel() - srv, db, _, _ := setup(t, false, nil) + srv, db, _, pd := setup(t, false, nil) ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort) defer cancel() + _, err := db.InsertProvisionerJob(context.Background(), database.InsertProvisionerJobParams{ - ID: uuid.New(), - InitiatorID: uuid.New(), - Provisioner: database.ProvisionerTypeEcho, - StorageMethod: database.ProvisionerStorageMethodFile, - Type: database.ProvisionerJobTypeTemplateVersionDryRun, + OrganizationID: pd.ID, + ID: uuid.New(), + InitiatorID: uuid.New(), + Provisioner: database.ProvisionerTypeEcho, + StorageMethod: database.ProvisionerStorageMethodFile, + Type: database.ProvisionerJobTypeTemplateVersionDryRun, }) require.NoError(t, err) _, err = tc.acquire(ctx, srv) @@ -176,7 +178,7 @@ func TestAcquireJob(t *testing.T) { Id: "github", } - srv, db, ps, _ := setup(t, false, &overrides{ + srv, db, ps, pd := setup(t, false, &overrides{ deploymentValues: dv, externalAuthConfigs: []*externalauth.Config{{ ID: gitAuthProvider.Id, @@ -198,12 +200,14 @@ func TestAcquireJob(t *testing.T) { UserID: user.ID, }) template := dbgen.Template(t, db, database.Template{ - Name: "template", - Provisioner: database.ProvisionerTypeEcho, + Name: "template", + Provisioner: database.ProvisionerTypeEcho, + OrganizationID: pd.ID, }) file := dbgen.File(t, db, database.File{CreatedBy: user.ID}) versionFile := dbgen.File(t, db, database.File{CreatedBy: user.ID}) version := dbgen.TemplateVersion(t, db, database.TemplateVersion{ + OrganizationID: pd.ID, TemplateID: uuid.NullUUID{ UUID: template.ID, Valid: true, @@ -223,12 +227,13 @@ func TestAcquireJob(t *testing.T) { require.NoError(t, err) // Import version job _ = dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{ - ID: version.JobID, - InitiatorID: user.ID, - FileID: versionFile.ID, - Provisioner: database.ProvisionerTypeEcho, - StorageMethod: database.ProvisionerStorageMethodFile, - Type: database.ProvisionerJobTypeTemplateVersionImport, + OrganizationID: pd.ID, + ID: version.JobID, + InitiatorID: user.ID, + FileID: versionFile.ID, + Provisioner: database.ProvisionerTypeEcho, + StorageMethod: database.ProvisionerStorageMethodFile, + Type: database.ProvisionerJobTypeTemplateVersionImport, Input: must(json.Marshal(provisionerdserver.TemplateVersionImportJob{ TemplateVersionID: version.ID, UserVariableValues: []codersdk.VariableValue{ @@ -252,8 +257,9 @@ func TestAcquireJob(t *testing.T) { Sensitive: false, }) workspace := dbgen.Workspace(t, db, database.Workspace{ - TemplateID: template.ID, - OwnerID: user.ID, + TemplateID: template.ID, + OwnerID: user.ID, + OrganizationID: pd.ID, }) build := dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{ WorkspaceID: workspace.ID, @@ -264,12 +270,13 @@ func TestAcquireJob(t *testing.T) { Reason: database.BuildReasonInitiator, }) _ = dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{ - ID: build.ID, - InitiatorID: user.ID, - Provisioner: database.ProvisionerTypeEcho, - StorageMethod: database.ProvisionerStorageMethodFile, - FileID: file.ID, - Type: database.ProvisionerJobTypeWorkspaceBuild, + ID: build.ID, + OrganizationID: pd.ID, + InitiatorID: user.ID, + Provisioner: database.ProvisionerTypeEcho, + StorageMethod: database.ProvisionerStorageMethodFile, + FileID: file.ID, + Type: database.ProvisionerJobTypeWorkspaceBuild, Input: must(json.Marshal(provisionerdserver.WorkspaceProvisionJob{ WorkspaceBuildID: build.ID, })), @@ -900,15 +907,17 @@ func TestCompleteJob(t *testing.T) { // This test prevents runners from updating jobs they don't own! t.Run("NotOwner", func(t *testing.T) { t.Parallel() - srv, db, _, _ := setup(t, false, nil) + srv, db, _, pd := setup(t, false, nil) job, err := db.InsertProvisionerJob(ctx, database.InsertProvisionerJobParams{ - ID: uuid.New(), - Provisioner: database.ProvisionerTypeEcho, - StorageMethod: database.ProvisionerStorageMethodFile, - Type: database.ProvisionerJobTypeWorkspaceBuild, + ID: uuid.New(), + Provisioner: database.ProvisionerTypeEcho, + StorageMethod: database.ProvisionerStorageMethodFile, + Type: database.ProvisionerJobTypeWorkspaceBuild, + OrganizationID: pd.OrganizationID, }) require.NoError(t, err) _, err = db.AcquireProvisionerJob(ctx, database.AcquireProvisionerJobParams{ + OrganizationID: pd.OrganizationID, WorkerID: uuid.NullUUID{ UUID: uuid.New(), Valid: true, @@ -928,19 +937,22 @@ func TestCompleteJob(t *testing.T) { jobID := uuid.New() versionID := uuid.New() err := db.InsertTemplateVersion(ctx, database.InsertTemplateVersionParams{ - ID: versionID, - JobID: jobID, + ID: versionID, + JobID: jobID, + OrganizationID: pd.OrganizationID, }) require.NoError(t, err) job, err := db.InsertProvisionerJob(ctx, database.InsertProvisionerJobParams{ - ID: jobID, - Provisioner: database.ProvisionerTypeEcho, - Input: []byte(`{"template_version_id": "` + versionID.String() + `"}`), - StorageMethod: database.ProvisionerStorageMethodFile, - Type: database.ProvisionerJobTypeWorkspaceBuild, + ID: jobID, + Provisioner: database.ProvisionerTypeEcho, + Input: []byte(`{"template_version_id": "` + versionID.String() + `"}`), + StorageMethod: database.ProvisionerStorageMethodFile, + Type: database.ProvisionerJobTypeWorkspaceBuild, + OrganizationID: pd.OrganizationID, }) require.NoError(t, err) _, err = db.AcquireProvisionerJob(ctx, database.AcquireProvisionerJobParams{ + OrganizationID: pd.OrganizationID, WorkerID: uuid.NullUUID{ UUID: pd.ID, Valid: true, @@ -982,19 +994,22 @@ func TestCompleteJob(t *testing.T) { jobID := uuid.New() versionID := uuid.New() err := db.InsertTemplateVersion(ctx, database.InsertTemplateVersionParams{ - ID: versionID, - JobID: jobID, + ID: versionID, + JobID: jobID, + OrganizationID: pd.OrganizationID, }) require.NoError(t, err) job, err := db.InsertProvisionerJob(ctx, database.InsertProvisionerJobParams{ - ID: jobID, - Provisioner: database.ProvisionerTypeEcho, - Input: []byte(`{"template_version_id": "` + versionID.String() + `"}`), - StorageMethod: database.ProvisionerStorageMethodFile, - Type: database.ProvisionerJobTypeWorkspaceBuild, + OrganizationID: pd.OrganizationID, + ID: jobID, + Provisioner: database.ProvisionerTypeEcho, + Input: []byte(`{"template_version_id": "` + versionID.String() + `"}`), + StorageMethod: database.ProvisionerStorageMethodFile, + Type: database.ProvisionerJobTypeWorkspaceBuild, }) require.NoError(t, err) _, err = db.AcquireProvisionerJob(ctx, database.AcquireProvisionerJobParams{ + OrganizationID: pd.OrganizationID, WorkerID: uuid.NullUUID{ UUID: pd.ID, Valid: true, @@ -1155,14 +1170,14 @@ func TestCompleteJob(t *testing.T) { } tss.Store(&store) - org := dbgen.Organization(t, db, database.Organization{}) user := dbgen.User(t, db, database.User{}) template := dbgen.Template(t, db, database.Template{ Name: "template", Provisioner: database.ProvisionerTypeEcho, - OrganizationID: org.ID, + OrganizationID: pd.OrganizationID, }) version := dbgen.TemplateVersion(t, db, database.TemplateVersion{ + OrganizationID: pd.OrganizationID, TemplateID: uuid.NullUUID{ UUID: template.ID, Valid: true, @@ -1186,8 +1201,9 @@ func TestCompleteJob(t *testing.T) { } } workspace := dbgen.Workspace(t, db, database.Workspace{ - TemplateID: template.ID, - Ttl: workspaceTTL, + TemplateID: template.ID, + Ttl: workspaceTTL, + OrganizationID: pd.OrganizationID, }) build := dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{ WorkspaceID: workspace.ID, @@ -1196,13 +1212,15 @@ func TestCompleteJob(t *testing.T) { Reason: database.BuildReasonInitiator, }) job := dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{ - FileID: file.ID, - Type: database.ProvisionerJobTypeWorkspaceBuild, + 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, @@ -1400,8 +1418,9 @@ func TestCompleteJob(t *testing.T) { QuietHoursSchedule: c.userQuietHoursSchedule, }) template := dbgen.Template(t, db, database.Template{ - Name: "template", - Provisioner: database.ProvisionerTypeEcho, + Name: "template", + Provisioner: database.ProvisionerTypeEcho, + OrganizationID: pd.OrganizationID, }) err := db.UpdateTemplateScheduleByID(ctx, database.UpdateTemplateScheduleByIDParams{ ID: template.ID, @@ -1424,11 +1443,13 @@ func TestCompleteJob(t *testing.T) { } } workspace := dbgen.Workspace(t, db, database.Workspace{ - TemplateID: template.ID, - Ttl: workspaceTTL, - OwnerID: user.ID, + TemplateID: template.ID, + Ttl: workspaceTTL, + OwnerID: user.ID, + OrganizationID: pd.OrganizationID, }) version := dbgen.TemplateVersion(t, db, database.TemplateVersion{ + OrganizationID: pd.OrganizationID, TemplateID: uuid.NullUUID{ UUID: template.ID, Valid: true, @@ -1447,8 +1468,10 @@ func TestCompleteJob(t *testing.T) { Input: must(json.Marshal(provisionerdserver.WorkspaceProvisionJob{ WorkspaceBuildID: build.ID, })), + OrganizationID: pd.OrganizationID, }) _, err = db.AcquireProvisionerJob(ctx, database.AcquireProvisionerJobParams{ + OrganizationID: pd.OrganizationID, WorkerID: uuid.NullUUID{ UUID: pd.ID, Valid: true, From 7be30c953ba0fc4fb8454a4a3ad8473c5820de79 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 14 Mar 2024 17:13:30 -0500 Subject: [PATCH 09/14] typo --- coderd/provisionerdserver/provisionerdserver_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/provisionerdserver/provisionerdserver_test.go b/coderd/provisionerdserver/provisionerdserver_test.go index 674ecc97f2889..fc832ad6ca098 100644 --- a/coderd/provisionerdserver/provisionerdserver_test.go +++ b/coderd/provisionerdserver/provisionerdserver_test.go @@ -65,7 +65,7 @@ func testUserQuietHoursScheduleStore() *atomic.Pointer[schedule.UserQuietHoursSc return ptr } -func cTestAcquireJob_LongPoll(t *testing.T) { +func TestAcquireJob_LongPoll(t *testing.T) { t.Parallel() //nolint:dogsled srv, _, _, _ := setup(t, false, &overrides{acquireJobLongPollDuration: time.Microsecond}) From 5a5c7259111e4f954998347005957c94597c9d4b Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 15 Mar 2024 08:56:08 -0500 Subject: [PATCH 10/14] correct org id inserts --- coderd/provisionerdserver/provisionerdserver_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/coderd/provisionerdserver/provisionerdserver_test.go b/coderd/provisionerdserver/provisionerdserver_test.go index fc832ad6ca098..443d2ce018db3 100644 --- a/coderd/provisionerdserver/provisionerdserver_test.go +++ b/coderd/provisionerdserver/provisionerdserver_test.go @@ -157,7 +157,7 @@ func TestAcquireJob(t *testing.T) { defer cancel() _, err := db.InsertProvisionerJob(context.Background(), database.InsertProvisionerJobParams{ - OrganizationID: pd.ID, + OrganizationID: pd.OrganizationID, ID: uuid.New(), InitiatorID: uuid.New(), Provisioner: database.ProvisionerTypeEcho, @@ -202,12 +202,12 @@ func TestAcquireJob(t *testing.T) { template := dbgen.Template(t, db, database.Template{ Name: "template", Provisioner: database.ProvisionerTypeEcho, - OrganizationID: pd.ID, + OrganizationID: pd.OrganizationID, }) file := dbgen.File(t, db, database.File{CreatedBy: user.ID}) versionFile := dbgen.File(t, db, database.File{CreatedBy: user.ID}) version := dbgen.TemplateVersion(t, db, database.TemplateVersion{ - OrganizationID: pd.ID, + OrganizationID: pd.OrganizationID, TemplateID: uuid.NullUUID{ UUID: template.ID, Valid: true, @@ -227,7 +227,7 @@ func TestAcquireJob(t *testing.T) { require.NoError(t, err) // Import version job _ = dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{ - OrganizationID: pd.ID, + OrganizationID: pd.OrganizationID, ID: version.JobID, InitiatorID: user.ID, FileID: versionFile.ID, @@ -259,7 +259,7 @@ func TestAcquireJob(t *testing.T) { workspace := dbgen.Workspace(t, db, database.Workspace{ TemplateID: template.ID, OwnerID: user.ID, - OrganizationID: pd.ID, + OrganizationID: pd.OrganizationID, }) build := dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{ WorkspaceID: workspace.ID, @@ -271,7 +271,7 @@ func TestAcquireJob(t *testing.T) { }) _ = dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{ ID: build.ID, - OrganizationID: pd.ID, + OrganizationID: pd.OrganizationID, InitiatorID: user.ID, Provisioner: database.ProvisionerTypeEcho, StorageMethod: database.ProvisionerStorageMethodFile, From 1c7a624d1baffa461a5a439a5707093fdaac4b5f Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 15 Mar 2024 09:16:01 -0500 Subject: [PATCH 11/14] fix test org references, let dbgen choose --- enterprise/coderd/schedule/template_test.go | 56 ++++++++------------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/enterprise/coderd/schedule/template_test.go b/enterprise/coderd/schedule/template_test.go index 4df05c026496f..338d6cc6e8989 100644 --- a/enterprise/coderd/schedule/template_test.go +++ b/enterprise/coderd/schedule/template_test.go @@ -28,7 +28,6 @@ func TestTemplateUpdateBuildDeadlines(t *testing.T) { db, _ := dbtestutil.NewDB(t) var ( - org = dbgen.Organization(t, db, database.Organization{}) quietUser = dbgen.User(t, db, database.User{ Username: "quiet", }) @@ -39,17 +38,15 @@ func TestTemplateUpdateBuildDeadlines(t *testing.T) { CreatedBy: quietUser.ID, }) templateJob = dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{ - OrganizationID: org.ID, - FileID: file.ID, - InitiatorID: quietUser.ID, + FileID: file.ID, + InitiatorID: quietUser.ID, Tags: database.StringMap{ "foo": "bar", }, }) templateVersion = dbgen.TemplateVersion(t, db, database.TemplateVersion{ - OrganizationID: org.ID, - CreatedBy: quietUser.ID, - JobID: templateJob.ID, + CreatedBy: quietUser.ID, + JobID: templateJob.ID, }) ) @@ -204,20 +201,17 @@ func TestTemplateUpdateBuildDeadlines(t *testing.T) { var ( template = dbgen.Template(t, db, database.Template{ - OrganizationID: org.ID, ActiveVersionID: templateVersion.ID, CreatedBy: user.ID, }) ws = dbgen.Workspace(t, db, database.Workspace{ - OrganizationID: org.ID, - OwnerID: user.ID, - TemplateID: template.ID, + OwnerID: user.ID, + TemplateID: template.ID, }) job = dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{ - OrganizationID: org.ID, - FileID: file.ID, - InitiatorID: user.ID, - Provisioner: database.ProvisionerTypeEcho, + FileID: file.ID, + InitiatorID: user.ID, + Provisioner: database.ProvisionerTypeEcho, Tags: database.StringMap{ c.name: "yeah", }, @@ -236,6 +230,7 @@ func TestTemplateUpdateBuildDeadlines(t *testing.T) { require.NotEmpty(t, wsBuild.ProvisionerState, "provisioner state must not be empty") acquiredJob, err := db.AcquireProvisionerJob(ctx, database.AcquireProvisionerJobParams{ + OrganizationID: job.OrganizationID, StartedAt: sql.NullTime{ Time: buildTime, Valid: true, @@ -324,31 +319,26 @@ func TestTemplateUpdateBuildDeadlinesSkip(t *testing.T) { db, _ := dbtestutil.NewDB(t) var ( - org = dbgen.Organization(t, db, database.Organization{}) user = dbgen.User(t, db, database.User{}) file = dbgen.File(t, db, database.File{ CreatedBy: user.ID, }) templateJob = dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{ - OrganizationID: org.ID, - FileID: file.ID, - InitiatorID: user.ID, + FileID: file.ID, + InitiatorID: user.ID, Tags: database.StringMap{ "foo": "bar", }, }) templateVersion = dbgen.TemplateVersion(t, db, database.TemplateVersion{ - OrganizationID: org.ID, - CreatedBy: user.ID, - JobID: templateJob.ID, + CreatedBy: user.ID, + JobID: templateJob.ID, }) template = dbgen.Template(t, db, database.Template{ - OrganizationID: org.ID, ActiveVersionID: templateVersion.ID, CreatedBy: user.ID, }) otherTemplate = dbgen.Template(t, db, database.Template{ - OrganizationID: org.ID, ActiveVersionID: templateVersion.ID, CreatedBy: user.ID, }) @@ -356,9 +346,8 @@ func TestTemplateUpdateBuildDeadlinesSkip(t *testing.T) { // Create a workspace that will be shared by two builds. ws := dbgen.Workspace(t, db, database.Workspace{ - OrganizationID: org.ID, - OwnerID: user.ID, - TemplateID: template.ID, + OwnerID: user.ID, + TemplateID: template.ID, }) const userQuietHoursSchedule = "CRON_TZ=UTC 0 0 * * *" // midnight UTC @@ -473,17 +462,15 @@ func TestTemplateUpdateBuildDeadlinesSkip(t *testing.T) { wsID := b.workspaceID if wsID == uuid.Nil { ws := dbgen.Workspace(t, db, database.Workspace{ - OrganizationID: org.ID, - OwnerID: user.ID, - TemplateID: b.templateID, + OwnerID: user.ID, + TemplateID: b.templateID, }) wsID = ws.ID } job := dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{ - OrganizationID: org.ID, - FileID: file.ID, - InitiatorID: user.ID, - Provisioner: database.ProvisionerTypeEcho, + FileID: file.ID, + InitiatorID: user.ID, + Provisioner: database.ProvisionerTypeEcho, Tags: database.StringMap{ wsID.String(): "yeah", }, @@ -521,6 +508,7 @@ func TestTemplateUpdateBuildDeadlinesSkip(t *testing.T) { } acquiredJob, err := db.AcquireProvisionerJob(ctx, database.AcquireProvisionerJobParams{ + OrganizationID: job.OrganizationID, StartedAt: sql.NullTime{ Time: buildTime, Valid: true, From 7aee6c090ee8b9282245cefe7b802d2cdbe14b0f Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 15 Mar 2024 09:36:24 -0500 Subject: [PATCH 12/14] fix sql db foreign key relations --- enterprise/coderd/schedule/template_test.go | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/enterprise/coderd/schedule/template_test.go b/enterprise/coderd/schedule/template_test.go index 338d6cc6e8989..e789752b5e7cd 100644 --- a/enterprise/coderd/schedule/template_test.go +++ b/enterprise/coderd/schedule/template_test.go @@ -45,9 +45,11 @@ func TestTemplateUpdateBuildDeadlines(t *testing.T) { }, }) templateVersion = dbgen.TemplateVersion(t, db, database.TemplateVersion{ - CreatedBy: quietUser.ID, - JobID: templateJob.ID, + OrganizationID: templateJob.OrganizationID, + CreatedBy: quietUser.ID, + JobID: templateJob.ID, }) + organizationID = templateJob.OrganizationID ) const userQuietHoursSchedule = "CRON_TZ=UTC 0 0 * * *" // midnight UTC @@ -201,17 +203,20 @@ func TestTemplateUpdateBuildDeadlines(t *testing.T) { var ( template = dbgen.Template(t, db, database.Template{ + OrganizationID: organizationID, ActiveVersionID: templateVersion.ID, CreatedBy: user.ID, }) ws = dbgen.Workspace(t, db, database.Workspace{ - OwnerID: user.ID, - TemplateID: template.ID, + OrganizationID: organizationID, + OwnerID: user.ID, + TemplateID: template.ID, }) job = dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{ - FileID: file.ID, - InitiatorID: user.ID, - Provisioner: database.ProvisionerTypeEcho, + OrganizationID: organizationID, + FileID: file.ID, + InitiatorID: user.ID, + Provisioner: database.ProvisionerTypeEcho, Tags: database.StringMap{ c.name: "yeah", }, From a9774df9a738f3f7b33b599ef3498e866e0b9f0d Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 15 Mar 2024 16:13:20 -0500 Subject: [PATCH 13/14] ensure corect org in tests --- enterprise/coderd/schedule/template_test.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/enterprise/coderd/schedule/template_test.go b/enterprise/coderd/schedule/template_test.go index e789752b5e7cd..2eea5d0e9c12b 100644 --- a/enterprise/coderd/schedule/template_test.go +++ b/enterprise/coderd/schedule/template_test.go @@ -336,23 +336,27 @@ func TestTemplateUpdateBuildDeadlinesSkip(t *testing.T) { }, }) templateVersion = dbgen.TemplateVersion(t, db, database.TemplateVersion{ - CreatedBy: user.ID, - JobID: templateJob.ID, + CreatedBy: user.ID, + JobID: templateJob.ID, + OrganizationID: templateJob.OrganizationID, }) template = dbgen.Template(t, db, database.Template{ ActiveVersionID: templateVersion.ID, CreatedBy: user.ID, + OrganizationID: templateJob.OrganizationID, }) otherTemplate = dbgen.Template(t, db, database.Template{ ActiveVersionID: templateVersion.ID, CreatedBy: user.ID, + OrganizationID: templateJob.OrganizationID, }) ) // Create a workspace that will be shared by two builds. ws := dbgen.Workspace(t, db, database.Workspace{ - OwnerID: user.ID, - TemplateID: template.ID, + OwnerID: user.ID, + TemplateID: template.ID, + OrganizationID: templateJob.OrganizationID, }) const userQuietHoursSchedule = "CRON_TZ=UTC 0 0 * * *" // midnight UTC @@ -467,8 +471,9 @@ func TestTemplateUpdateBuildDeadlinesSkip(t *testing.T) { wsID := b.workspaceID if wsID == uuid.Nil { ws := dbgen.Workspace(t, db, database.Workspace{ - OwnerID: user.ID, - TemplateID: b.templateID, + OwnerID: user.ID, + TemplateID: b.templateID, + OrganizationID: templateJob.OrganizationID, }) wsID = ws.ID } @@ -479,6 +484,7 @@ func TestTemplateUpdateBuildDeadlinesSkip(t *testing.T) { Tags: database.StringMap{ wsID.String(): "yeah", }, + OrganizationID: templateJob.OrganizationID, }) wsBuild := dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{ WorkspaceID: wsID, From 6ca72652015666a02e8a296e57ebf278ed3e92fd Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 18 Mar 2024 12:19:10 -0500 Subject: [PATCH 14/14] add unit test vector for differing orgS --- coderd/provisionerdserver/acquirer_test.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/coderd/provisionerdserver/acquirer_test.go b/coderd/provisionerdserver/acquirer_test.go index 8f55313146efc..a916cb68fba1f 100644 --- a/coderd/provisionerdserver/acquirer_test.go +++ b/coderd/provisionerdserver/acquirer_test.go @@ -336,8 +336,10 @@ func TestAcquirer_MatchTags(t *testing.T) { testCases := []struct { name string provisionerJobTags map[string]string - acquireJobTags map[string]string - expectAcquire bool + + acquireJobTags map[string]string + unmatchedOrg bool // acquire will use a random org id + expectAcquire bool }{ { name: "untagged provisioner and untagged job", @@ -459,6 +461,13 @@ func TestAcquirer_MatchTags(t *testing.T) { acquireJobTags: map[string]string{"scope": "user", "owner": "aaa", "environment": "on-prem", "datacenter": "chicago"}, expectAcquire: false, }, + { + name: "matching tags with unmatched org", + provisionerJobTags: map[string]string{"scope": "organization", "owner": "", "environment": "on-prem"}, + acquireJobTags: map[string]string{"scope": "organization", "owner": "", "environment": "on-prem"}, + expectAcquire: false, + unmatchedOrg: true, + }, } for _, tt := range testCases { tt := tt @@ -493,7 +502,12 @@ func TestAcquirer_MatchTags(t *testing.T) { require.NoError(t, err) ptypes := []database.ProvisionerType{database.ProvisionerTypeEcho} acq := provisionerdserver.NewAcquirer(ctx, log, db, ps) - aj, err := acq.AcquireJob(ctx, org.ID, uuid.New(), ptypes, tt.acquireJobTags) + + acquireOrgID := org.ID + if tt.unmatchedOrg { + acquireOrgID = uuid.New() + } + aj, err := acq.AcquireJob(ctx, acquireOrgID, uuid.New(), ptypes, tt.acquireJobTags) if tt.expectAcquire { assert.NoError(t, err) assert.Equal(t, pj.ID, aj.ID)