Skip to content

Commit 6a61712

Browse files
committed
Pipe git auth providers to the schema
1 parent c64636b commit 6a61712

File tree

15 files changed

+1065
-517
lines changed

15 files changed

+1065
-517
lines changed

coderd/provisionerdserver/provisionerdserver.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ func (server *Server) includeLastVariableValues(ctx context.Context, templateVer
305305

306306
templateVersion, err := server.Database.GetTemplateVersionByID(ctx, templateVersionID)
307307
if err != nil {
308-
return nil, fmt.Errorf("get template version: %w", err)
308+
return nil, xerrors.Errorf("get template version: %w", err)
309309
}
310310

311311
if templateVersion.TemplateID.UUID == uuid.Nil {
@@ -314,7 +314,7 @@ func (server *Server) includeLastVariableValues(ctx context.Context, templateVer
314314

315315
template, err := server.Database.GetTemplateByID(ctx, templateVersion.TemplateID.UUID)
316316
if err != nil {
317-
return nil, fmt.Errorf("get template: %w", err)
317+
return nil, xerrors.Errorf("get template: %w", err)
318318
}
319319

320320
if template.ActiveVersionID == uuid.Nil {
@@ -323,7 +323,7 @@ func (server *Server) includeLastVariableValues(ctx context.Context, templateVer
323323

324324
templateVariables, err := server.Database.GetTemplateVersionVariables(ctx, template.ActiveVersionID)
325325
if err != nil && !xerrors.Is(err, sql.ErrNoRows) {
326-
return nil, fmt.Errorf("get template version variables: %w", err)
326+
return nil, xerrors.Errorf("get template version variables: %w", err)
327327
}
328328

329329
for _, templateVariable := range templateVariables {
@@ -810,6 +810,15 @@ func (server *Server) CompleteJob(ctx context.Context, completed *proto.Complete
810810
}
811811
}
812812

813+
err = server.Database.UpdateTemplateVersionGitAuthProvidersByJobID(ctx, database.UpdateTemplateVersionGitAuthProvidersByJobIDParams{
814+
JobID: jobID,
815+
GitAuthProviders: jobType.TemplateImport.GitAuthProviders,
816+
UpdatedAt: database.Now(),
817+
})
818+
if err != nil {
819+
return nil, xerrors.Errorf("update template version git auth providers: %w", err)
820+
}
821+
813822
err = server.Database.UpdateProvisionerJobWithCompleteByID(ctx, database.UpdateProvisionerJobWithCompleteByIDParams{
814823
ID: jobID,
815824
UpdatedAt: database.Now(),

coderd/provisionerdserver/provisionerdserver_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -734,10 +734,16 @@ func TestCompleteJob(t *testing.T) {
734734
t.Run("TemplateImport", func(t *testing.T) {
735735
t.Parallel()
736736
srv := setup(t, false)
737+
jobID := uuid.New()
738+
version, err := srv.Database.InsertTemplateVersion(ctx, database.InsertTemplateVersionParams{
739+
ID: uuid.New(),
740+
JobID: jobID,
741+
})
742+
require.NoError(t, err)
737743
job, err := srv.Database.InsertProvisionerJob(ctx, database.InsertProvisionerJobParams{
738-
ID: uuid.New(),
744+
ID: jobID,
739745
Provisioner: database.ProvisionerTypeEcho,
740-
Input: []byte(`{"template_version_id": "` + uuid.NewString() + `"}`),
746+
Input: []byte(`{"template_version_id": "` + version.ID.String() + `"}`),
741747
StorageMethod: database.ProvisionerStorageMethodFile,
742748
Type: database.ProvisionerJobTypeWorkspaceBuild,
743749
})

provisioner/terraform/executor.go

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l
223223
if err != nil {
224224
return nil, xerrors.Errorf("terraform plan: %w", err)
225225
}
226-
resources, parameters, err := e.planResources(ctx, killCtx, planfilePath)
226+
state, err := e.planResources(ctx, killCtx, planfilePath)
227227
if err != nil {
228228
return nil, err
229229
}
@@ -234,31 +234,32 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l
234234
return &proto.Provision_Response{
235235
Type: &proto.Provision_Response_Complete{
236236
Complete: &proto.Provision_Complete{
237-
Parameters: parameters,
238-
Resources: resources,
239-
Plan: planFileByt,
237+
Parameters: state.Parameters,
238+
Resources: state.Resources,
239+
GitAuthProviders: state.GitAuthProviders,
240+
Plan: planFileByt,
240241
},
241242
},
242243
}, nil
243244
}
244245

245246
// planResources must only be called while the lock is held.
246-
func (e *executor) planResources(ctx, killCtx context.Context, planfilePath string) ([]*proto.Resource, []*proto.RichParameter, error) {
247+
func (e *executor) planResources(ctx, killCtx context.Context, planfilePath string) (*ConvertedState, error) {
247248
plan, err := e.showPlan(ctx, killCtx, planfilePath)
248249
if err != nil {
249-
return nil, nil, xerrors.Errorf("show terraform plan file: %w", err)
250+
return nil, xerrors.Errorf("show terraform plan file: %w", err)
250251
}
251252

252253
rawGraph, err := e.graph(ctx, killCtx)
253254
if err != nil {
254-
return nil, nil, xerrors.Errorf("graph: %w", err)
255+
return nil, xerrors.Errorf("graph: %w", err)
255256
}
256257
modules := []*tfjson.StateModule{}
257258
if plan.PriorState != nil {
258259
modules = append(modules, plan.PriorState.Values.RootModule)
259260
}
260261
modules = append(modules, plan.PlannedValues.RootModule)
261-
return ConvertResourcesAndParameters(modules, rawGraph)
262+
return ConvertState(modules, rawGraph)
262263
}
263264

264265
// showPlan must only be called while the lock is held.
@@ -332,7 +333,7 @@ func (e *executor) apply(
332333
if err != nil {
333334
return nil, xerrors.Errorf("terraform apply: %w", err)
334335
}
335-
resources, parameters, err := e.stateResources(ctx, killCtx)
336+
state, err := e.stateResources(ctx, killCtx)
336337
if err != nil {
337338
return nil, err
338339
}
@@ -344,35 +345,35 @@ func (e *executor) apply(
344345
return &proto.Provision_Response{
345346
Type: &proto.Provision_Response_Complete{
346347
Complete: &proto.Provision_Complete{
347-
Parameters: parameters,
348-
Resources: resources,
349-
State: stateContent,
348+
Parameters: state.Parameters,
349+
Resources: state.Resources,
350+
GitAuthProviders: state.GitAuthProviders,
351+
State: stateContent,
350352
},
351353
},
352354
}, nil
353355
}
354356

355357
// stateResources must only be called while the lock is held.
356-
func (e *executor) stateResources(ctx, killCtx context.Context) ([]*proto.Resource, []*proto.RichParameter, error) {
358+
func (e *executor) stateResources(ctx, killCtx context.Context) (*ConvertedState, error) {
357359
state, err := e.state(ctx, killCtx)
358360
if err != nil {
359-
return nil, nil, err
361+
return nil, err
360362
}
361363
rawGraph, err := e.graph(ctx, killCtx)
362364
if err != nil {
363-
return nil, nil, xerrors.Errorf("get terraform graph: %w", err)
365+
return nil, xerrors.Errorf("get terraform graph: %w", err)
364366
}
365-
var resources []*proto.Resource
366-
var parameters []*proto.RichParameter
367+
var converted *ConvertedState
367368
if state.Values != nil {
368-
resources, parameters, err = ConvertResourcesAndParameters([]*tfjson.StateModule{
369+
converted, err = ConvertState([]*tfjson.StateModule{
369370
state.Values.RootModule,
370371
}, rawGraph)
371372
if err != nil {
372-
return nil, nil, err
373+
return nil, err
373374
}
374375
}
375-
return resources, parameters, nil
376+
return converted, nil
376377
}
377378

378379
// state must only be called while the lock is held.

provisioner/terraform/resources.go

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,17 +72,23 @@ type metadataItem struct {
7272
IsNull bool `mapstructure:"is_null"`
7373
}
7474

75-
// ConvertResourcesAndParameters consumes Terraform state and a GraphViz representation
75+
type ConvertedState struct {
76+
Resources []*proto.Resource
77+
Parameters []*proto.RichParameter
78+
GitAuthProviders []string
79+
}
80+
81+
// ConvertState consumes Terraform state and a GraphViz representation
7682
// produced by `terraform graph` to produce resources consumable by Coder.
7783
// nolint:gocyclo
78-
func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph string) ([]*proto.Resource, []*proto.RichParameter, error) {
84+
func ConvertState(modules []*tfjson.StateModule, rawGraph string) (*ConvertedState, error) {
7985
parsedGraph, err := gographviz.ParseString(rawGraph)
8086
if err != nil {
81-
return nil, nil, xerrors.Errorf("parse graph: %w", err)
87+
return nil, xerrors.Errorf("parse graph: %w", err)
8288
}
8389
graph, err := gographviz.NewAnalysedGraph(parsedGraph)
8490
if err != nil {
85-
return nil, nil, xerrors.Errorf("analyze graph: %w", err)
91+
return nil, xerrors.Errorf("analyze graph: %w", err)
8692
}
8793

8894
resources := make([]*proto.Resource, 0)
@@ -118,11 +124,11 @@ func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph strin
118124
var attrs agentAttributes
119125
err = mapstructure.Decode(tfResource.AttributeValues, &attrs)
120126
if err != nil {
121-
return nil, nil, xerrors.Errorf("decode agent attributes: %w", err)
127+
return nil, xerrors.Errorf("decode agent attributes: %w", err)
122128
}
123129

124130
if _, ok := agentNames[tfResource.Name]; ok {
125-
return nil, nil, xerrors.Errorf("duplicate agent name: %s", tfResource.Name)
131+
return nil, xerrors.Errorf("duplicate agent name: %s", tfResource.Name)
126132
}
127133
agentNames[tfResource.Name] = struct{}{}
128134

@@ -171,7 +177,7 @@ func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph strin
171177
break
172178
}
173179
if agentNode == nil {
174-
return nil, nil, xerrors.Errorf("couldn't find node on graph: %q", agentLabel)
180+
return nil, xerrors.Errorf("couldn't find node on graph: %q", agentLabel)
175181
}
176182

177183
var agentResource *graphResource
@@ -260,7 +266,7 @@ func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph strin
260266
var attrs agentAppAttributes
261267
err = mapstructure.Decode(resource.AttributeValues, &attrs)
262268
if err != nil {
263-
return nil, nil, xerrors.Errorf("decode app attributes: %w", err)
269+
return nil, xerrors.Errorf("decode app attributes: %w", err)
264270
}
265271

266272
// Default to the resource name if none is set!
@@ -277,11 +283,11 @@ func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph strin
277283
}
278284

279285
if !provisioner.AppSlugRegex.MatchString(attrs.Slug) {
280-
return nil, nil, xerrors.Errorf("invalid app slug %q, please update your coder/coder provider to the latest version and specify the slug property on each coder_app", attrs.Slug)
286+
return nil, xerrors.Errorf("invalid app slug %q, please update your coder/coder provider to the latest version and specify the slug property on each coder_app", attrs.Slug)
281287
}
282288

283289
if _, exists := appSlugs[attrs.Slug]; exists {
284-
return nil, nil, xerrors.Errorf("duplicate app slug, they must be unique per template: %q", attrs.Slug)
290+
return nil, xerrors.Errorf("duplicate app slug, they must be unique per template: %q", attrs.Slug)
285291
}
286292
appSlugs[attrs.Slug] = struct{}{}
287293

@@ -341,7 +347,7 @@ func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph strin
341347
var attrs metadataAttributes
342348
err = mapstructure.Decode(resource.AttributeValues, &attrs)
343349
if err != nil {
344-
return nil, nil, xerrors.Errorf("decode metadata attributes: %w", err)
350+
return nil, xerrors.Errorf("decode metadata attributes: %w", err)
345351
}
346352

347353
resourceLabel := convertAddressToLabel(resource.Address)
@@ -432,7 +438,7 @@ func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph strin
432438
var param provider.Parameter
433439
err = mapstructure.Decode(resource.AttributeValues, &param)
434440
if err != nil {
435-
return nil, nil, xerrors.Errorf("decode map values for coder_parameter.%s: %w", resource.Name, err)
441+
return nil, xerrors.Errorf("decode map values for coder_parameter.%s: %w", resource.Name, err)
436442
}
437443
protoParam := &proto.RichParameter{
438444
Name: param.Name,
@@ -464,7 +470,31 @@ func ConvertResourcesAndParameters(modules []*tfjson.StateModule, rawGraph strin
464470
}
465471
}
466472

467-
return resources, parameters, nil
473+
// A map is used to ensure we don't have duplicates!
474+
gitAuthProvidersMap := map[string]struct{}{}
475+
for _, tfResources := range tfResourcesByLabel {
476+
for _, resource := range tfResources {
477+
//
478+
if resource.Type != "coder_git_auth" {
479+
continue
480+
}
481+
id, ok := resource.AttributeValues["id"].(string)
482+
if !ok {
483+
return nil, xerrors.Errorf("git auth id is not a string")
484+
}
485+
gitAuthProvidersMap[id] = struct{}{}
486+
}
487+
}
488+
gitAuthProviders := make([]string, 0, len(gitAuthProvidersMap))
489+
for id := range gitAuthProvidersMap {
490+
gitAuthProviders = append(gitAuthProviders, id)
491+
}
492+
493+
return &ConvertedState{
494+
Resources: resources,
495+
Parameters: parameters,
496+
GitAuthProviders: gitAuthProviders,
497+
}, nil
468498
}
469499

470500
// convertAddressToLabel returns the Terraform address without the count

0 commit comments

Comments
 (0)