Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc2837a6

Browse files
authored
feat: evaluate provisioner tags (#13333)
1 parentfa9edc1 commitc2837a6

File tree

2 files changed

+252
-20
lines changed

2 files changed

+252
-20
lines changed

‎coderd/wsbuilder/wsbuilder.go

Lines changed: 130 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import (
1010
"net/http"
1111
"time"
1212

13+
"github.com/hashicorp/hcl/v2"
14+
"github.com/hashicorp/hcl/v2/hclsyntax"
15+
"github.com/zclconf/go-cty/cty"
16+
1317
"github.com/coder/coder/v2/coderd/rbac/policy"
1418
"github.com/coder/coder/v2/provisionersdk"
1519

@@ -55,14 +59,17 @@ type Builder struct {
5559
store database.Store
5660

5761
// cache of objects, so we only fetch once
58-
template*database.Template
59-
templateVersion*database.TemplateVersion
60-
templateVersionJob*database.ProvisionerJob
61-
templateVersionParameters*[]database.TemplateVersionParameter
62-
lastBuild*database.WorkspaceBuild
63-
lastBuildErr*error
64-
lastBuildParameters*[]database.WorkspaceBuildParameter
65-
lastBuildJob*database.ProvisionerJob
62+
template*database.Template
63+
templateVersion*database.TemplateVersion
64+
templateVersionJob*database.ProvisionerJob
65+
templateVersionParameters*[]database.TemplateVersionParameter
66+
templateVersionWorkspaceTags*[]database.TemplateVersionWorkspaceTag
67+
lastBuild*database.WorkspaceBuild
68+
lastBuildErr*error
69+
lastBuildParameters*[]database.WorkspaceBuildParameter
70+
lastBuildJob*database.ProvisionerJob
71+
parameterNames*[]string
72+
parameterValues*[]string
6673

6774
verifyNoLegacyParametersOncebool
6875
}
@@ -297,7 +304,11 @@ func (b *Builder) buildTx(authFunc func(action policy.Action, object rbac.Object
297304
iferr!=nil {
298305
returnnil,nil,BuildError{http.StatusInternalServerError,"marshal metadata",err}
299306
}
300-
tags:=provisionersdk.MutateTags(b.workspace.OwnerID,templateVersionJob.Tags)
307+
308+
tags,err:=b.getProvisionerTags()
309+
iferr!=nil {
310+
returnnil,nil,err// already wrapped BuildError
311+
}
301312

302313
now:=dbtime.Now()
303314
provisionerJob,err:=b.store.InsertProvisionerJob(b.ctx, database.InsertProvisionerJobParams{
@@ -364,6 +375,7 @@ func (b *Builder) buildTx(authFunc func(action policy.Action, object rbac.Object
364375
// getParameters already wraps errors in BuildError
365376
returnerr
366377
}
378+
367379
err=store.InsertWorkspaceBuildParameters(b.ctx, database.InsertWorkspaceBuildParametersParams{
368380
WorkspaceBuildID:workspaceBuildID,
369381
Name:names,
@@ -502,6 +514,10 @@ func (b *Builder) getState() ([]byte, error) {
502514
}
503515

504516
func (b*Builder)getParameters() (names,values []string,errerror) {
517+
ifb.parameterNames!=nil {
518+
return*b.parameterNames,*b.parameterValues,nil
519+
}
520+
505521
templateVersionParameters,err:=b.getTemplateVersionParameters()
506522
iferr!=nil {
507523
returnnil,nil,BuildError{http.StatusInternalServerError,"failed to fetch template version parameters",err}
@@ -535,6 +551,9 @@ func (b *Builder) getParameters() (names, values []string, err error) {
535551
names=append(names,templateVersionParameter.Name)
536552
values=append(values,value)
537553
}
554+
555+
b.parameterNames=&names
556+
b.parameterValues=&values
538557
returnnames,values,nil
539558
}
540559

@@ -632,6 +651,108 @@ func (b *Builder) getLastBuildJob() (*database.ProvisionerJob, error) {
632651
returnb.lastBuildJob,nil
633652
}
634653

654+
func (b*Builder)getProvisionerTags() (map[string]string,error) {
655+
// Step 1: Mutate template version tags
656+
templateVersionJob,err:=b.getTemplateVersionJob()
657+
iferr!=nil {
658+
returnnil,BuildError{http.StatusInternalServerError,"failed to fetch template version job",err}
659+
}
660+
annotationTags:=provisionersdk.MutateTags(b.workspace.OwnerID,templateVersionJob.Tags)
661+
662+
tags:=map[string]string{}
663+
forname,value:=rangeannotationTags {
664+
tags[name]=value
665+
}
666+
667+
// Step 2: Mutate workspace tags
668+
workspaceTags,err:=b.getTemplateVersionWorkspaceTags()
669+
iferr!=nil {
670+
returnnil,BuildError{http.StatusInternalServerError,"failed to fetch template version workspace tags",err}
671+
}
672+
parameterNames,parameterValues,err:=b.getParameters()
673+
iferr!=nil {
674+
returnnil,err// already wrapped BuildError
675+
}
676+
677+
evalCtx:=buildParametersEvalContext(parameterNames,parameterValues)
678+
for_,workspaceTag:=rangeworkspaceTags {
679+
expr,diags:=hclsyntax.ParseExpression([]byte(workspaceTag.Value),"expression.hcl",hcl.InitialPos)
680+
ifdiags.HasErrors() {
681+
returnnil,BuildError{http.StatusBadRequest,"failed to parse workspace tag value",xerrors.Errorf(diags.Error())}
682+
}
683+
684+
val,diags:=expr.Value(evalCtx)
685+
ifdiags.HasErrors() {
686+
returnnil,BuildError{http.StatusBadRequest,"failed to evaluate workspace tag value",xerrors.Errorf(diags.Error())}
687+
}
688+
689+
// Do not use "val.AsString()" as it can panic
690+
str,err:=ctyValueString(val)
691+
iferr!=nil {
692+
returnnil,BuildError{http.StatusBadRequest,"failed to marshal cty.Value as string",err}
693+
}
694+
tags[workspaceTag.Key]=str
695+
}
696+
returntags,nil
697+
}
698+
699+
funcbuildParametersEvalContext(names,values []string)*hcl.EvalContext {
700+
m:=map[string]cty.Value{}
701+
fori,name:=rangenames {
702+
m[name]=cty.MapVal(map[string]cty.Value{
703+
"value":cty.StringVal(values[i]),
704+
})
705+
}
706+
707+
iflen(m)==0 {
708+
returnnil// otherwise, panic: must not call MapVal with empty map
709+
}
710+
711+
return&hcl.EvalContext{
712+
Variables:map[string]cty.Value{
713+
"data":cty.MapVal(map[string]cty.Value{
714+
"coder_parameter":cty.MapVal(m),
715+
}),
716+
},
717+
}
718+
}
719+
720+
funcctyValueString(val cty.Value) (string,error) {
721+
switchval.Type() {
722+
casecty.Bool:
723+
ifval.True() {
724+
return"true",nil
725+
}else {
726+
return"false",nil
727+
}
728+
casecty.Number:
729+
returnval.AsBigFloat().String(),nil
730+
casecty.String:
731+
returnval.AsString(),nil
732+
default:
733+
return"",xerrors.Errorf("only primitive types are supported - bool, number, and string")
734+
}
735+
}
736+
737+
func (b*Builder)getTemplateVersionWorkspaceTags() ([]database.TemplateVersionWorkspaceTag,error) {
738+
ifb.templateVersionWorkspaceTags!=nil {
739+
return*b.templateVersionWorkspaceTags,nil
740+
}
741+
742+
templateVersion,err:=b.getTemplateVersion()
743+
iferr!=nil {
744+
returnnil,xerrors.Errorf("get template version: %w",err)
745+
}
746+
747+
workspaceTags,err:=b.store.GetTemplateVersionWorkspaceTags(b.ctx,templateVersion.ID)
748+
iferr!=nil&&!xerrors.Is(err,sql.ErrNoRows) {
749+
returnnil,xerrors.Errorf("get template version workspace tags: %w",err)
750+
}
751+
752+
b.templateVersionWorkspaceTags=&workspaceTags
753+
return*b.templateVersionWorkspaceTags,nil
754+
}
755+
635756
// authorize performs build authorization pre-checks using the provided authFunc
636757
func (b*Builder)authorize(authFuncfunc(action policy.Action,object rbac.Objecter)bool)error {
637758
// Doing this up front saves a lot of work if the user doesn't have permission.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp