Skip to content

Commit e97287f

Browse files
committed
Add user local provisioner daemons
1 parent b1ce65b commit e97287f

18 files changed

+137
-19
lines changed

coderd/autobuild/executor/lifecycle_executor.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ func build(ctx context.Context, store database.Store, workspace database.Workspa
277277
Type: database.ProvisionerJobTypeWorkspaceBuild,
278278
StorageMethod: priorJob.StorageMethod,
279279
FileID: priorJob.FileID,
280+
Tags: priorJob.Tags,
280281
Input: input,
281282
})
282283
if err != nil {

coderd/coderd.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"crypto/tls"
66
"crypto/x509"
7+
"encoding/json"
78
"fmt"
89
"io"
910
"net/http"
@@ -36,6 +37,7 @@ import (
3637
"github.com/coder/coder/coderd/audit"
3738
"github.com/coder/coder/coderd/awsidentity"
3839
"github.com/coder/coder/coderd/database"
40+
"github.com/coder/coder/coderd/database/dbtype"
3941
"github.com/coder/coder/coderd/gitauth"
4042
"github.com/coder/coder/coderd/gitsshkey"
4143
"github.com/coder/coder/coderd/httpapi"
@@ -659,11 +661,19 @@ func (api *API) CreateInMemoryProvisionerDaemon(ctx context.Context) (client pro
659661
CreatedAt: database.Now(),
660662
Name: name,
661663
Provisioners: []database.ProvisionerType{database.ProvisionerTypeEcho, database.ProvisionerTypeTerraform},
664+
Tags: dbtype.Map{
665+
provisionerdserver.TagScope: provisionerdserver.ScopeOrganization,
666+
},
662667
})
663668
if err != nil {
664669
return nil, xerrors.Errorf("insert provisioner daemon %q: %w", name, err)
665670
}
666671

672+
tags, err := json.Marshal(daemon.Tags)
673+
if err != nil {
674+
return nil, xerrors.Errorf("marshal tags: %w", err)
675+
}
676+
667677
mux := drpcmux.New()
668678
err = proto.DRPCRegisterProvisionerDaemon(mux, &provisionerdserver.Server{
669679
AccessURL: api.AccessURL,
@@ -672,6 +682,7 @@ func (api *API) CreateInMemoryProvisionerDaemon(ctx context.Context) (client pro
672682
Pubsub: api.Pubsub,
673683
Provisioners: daemon.Provisioners,
674684
Telemetry: api.Telemetry,
685+
Tags: tags,
675686
Logger: api.Logger.Named(fmt.Sprintf("provisionerd-%s", daemon.Name)),
676687
})
677688
if err != nil {

coderd/database/databasefake/databasefake.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package databasefake
33
import (
44
"context"
55
"database/sql"
6-
"reflect"
6+
"encoding/json"
77
"sort"
88
"strings"
99
"sync"
@@ -147,7 +147,27 @@ func (q *fakeQuerier) AcquireProvisionerJob(_ context.Context, arg database.Acqu
147147
if !found {
148148
continue
149149
}
150-
if !reflect.DeepEqual(arg.Tags, provisionerJob.Tags) {
150+
tags := map[string]string{}
151+
if arg.Tags != nil {
152+
err := json.Unmarshal(arg.Tags, &tags)
153+
if err != nil {
154+
return provisionerJob, xerrors.Errorf("unmarshal: %w", err)
155+
}
156+
}
157+
158+
missing := false
159+
for key, value := range provisionerJob.Tags {
160+
provided, found := tags[key]
161+
if !found {
162+
missing = true
163+
break
164+
}
165+
if provided != value {
166+
missing = true
167+
break
168+
}
169+
}
170+
if missing {
151171
continue
152172
}
153173
provisionerJob.StartedAt = arg.StartedAt
@@ -2291,6 +2311,7 @@ func (q *fakeQuerier) InsertProvisionerJob(_ context.Context, arg database.Inser
22912311
FileID: arg.FileID,
22922312
Type: arg.Type,
22932313
Input: arg.Input,
2314+
Tags: arg.Tags,
22942315
}
22952316
q.provisionerJobs = append(q.provisionerJobs, job)
22962317
return job, nil

coderd/database/dump.sql

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
ALTER TABLE provisioner_daemons ADD COLUMN tags jsonb NOT NULL DEFAULT '{}';
2-
ALTER TABLE provisioner_jobs ADD COLUMN tags jsonb NOT NULL DEFAULT '{}';
2+
3+
-- We must add the organization scope by default, otherwise pending jobs
4+
-- could be provisioned on new daemons that don't match the tags.
5+
ALTER TABLE provisioner_jobs ADD COLUMN tags jsonb NOT NULL DEFAULT '{"scope":"organization"}';

coderd/provisionerdserver/provisionerdserver.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type Server struct {
3232
ID uuid.UUID
3333
Logger slog.Logger
3434
Provisioners []database.ProvisionerType
35+
Tags json.RawMessage
3536
Database database.Store
3637
Pubsub database.Pubsub
3738
Telemetry telemetry.Reporter
@@ -50,6 +51,7 @@ func (server *Server) AcquireJob(ctx context.Context, _ *proto.Empty) (*proto.Ac
5051
Valid: true,
5152
},
5253
Types: server.Provisioners,
54+
Tags: server.Tags,
5355
})
5456
if errors.Is(err, sql.ErrNoRows) {
5557
// The provisioner daemon assumes no jobs are available if
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package provisionerdserver
2+
3+
import "github.com/google/uuid"
4+
5+
const (
6+
TagScope = "scope"
7+
TagOwner = "owner"
8+
9+
ScopeUser = "user"
10+
ScopeOrganization = "organization"
11+
)
12+
13+
// MutateTags adjusts the "owner" tag dependent on the "scope".
14+
// If the scope is "user", the "owner" is changed to the user ID.
15+
// This is for user-scoped provisioner daemons, where users should
16+
// own their own operations.
17+
func MutateTags(userID uuid.UUID, tags map[string]string) map[string]string {
18+
if tags == nil {
19+
tags = map[string]string{}
20+
}
21+
_, ok := tags[TagScope]
22+
if !ok {
23+
tags[TagScope] = ScopeOrganization
24+
}
25+
switch tags[TagScope] {
26+
case ScopeUser:
27+
tags[TagOwner] = userID.String()
28+
case ScopeOrganization:
29+
default:
30+
tags[TagScope] = ScopeOrganization
31+
}
32+
return tags
33+
}

coderd/provisionerjobs.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ func convertProvisionerJob(provisionerJob database.ProvisionerJob) codersdk.Prov
311311
CreatedAt: provisionerJob.CreatedAt,
312312
Error: provisionerJob.Error.String,
313313
FileID: provisionerJob.FileID,
314+
Tags: provisionerJob.Tags,
314315
}
315316
// Applying values optional to the struct.
316317
if provisionerJob.StartedAt.Valid {

coderd/templateversions.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,8 @@ func (api *API) postTemplateVersionDryRun(rw http.ResponseWriter, r *http.Reques
288288
FileID: job.FileID,
289289
Type: database.ProvisionerJobTypeTemplateVersionDryRun,
290290
Input: input,
291+
// Copy tags from the previous run.
292+
Tags: job.Tags,
291293
})
292294
if err != nil {
293295
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
@@ -717,6 +719,9 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
717719
return
718720
}
719721

722+
// Ensures the "owner" is properly applied.
723+
tags := provisionerdserver.MutateTags(apiKey.UserID, req.ProvisionerTags)
724+
720725
file, err := api.Database.GetFileByID(ctx, req.FileID)
721726
if errors.Is(err, sql.ErrNoRows) {
722727
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
@@ -815,6 +820,7 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
815820
FileID: file.ID,
816821
Type: database.ProvisionerJobTypeTemplateVersionImport,
817822
Input: []byte{'{', '}'},
823+
Tags: tags,
818824
})
819825
if err != nil {
820826
return xerrors.Errorf("insert provisioner job: %w", err)

coderd/templateversions_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/coder/coder/coderd/audit"
1414
"github.com/coder/coder/coderd/coderdtest"
1515
"github.com/coder/coder/coderd/database"
16+
"github.com/coder/coder/coderd/provisionerdserver"
1617
"github.com/coder/coder/codersdk"
1718
"github.com/coder/coder/provisioner/echo"
1819
"github.com/coder/coder/provisionersdk/proto"
@@ -122,6 +123,7 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) {
122123
})
123124
require.NoError(t, err)
124125
require.Equal(t, "bananas", version.Name)
126+
require.Equal(t, provisionerdserver.ScopeOrganization, version.Job.Tags[provisionerdserver.TagScope])
125127

126128
require.Len(t, auditor.AuditLogs, 1)
127129
assert.Equal(t, database.AuditActionCreate, auditor.AuditLogs[0].Action)

0 commit comments

Comments
 (0)