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

Commitaedc019

Browse files
authored
feat: include template variables in dynamic parameter rendering (#18819)
Closes#18671Template variables now loaded into dynamic parameters.
1 parent40a6367 commitaedc019

File tree

11 files changed

+328
-80
lines changed

11 files changed

+328
-80
lines changed

‎coderd/coderdtest/dynamicparameters.go‎

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ type DynamicParameterTemplateParams struct {
2929
// TemplateID is used to update an existing template instead of creating a new one.
3030
TemplateID uuid.UUID
3131

32-
Versionfunc(request*codersdk.CreateTemplateVersionRequest)
32+
Versionfunc(request*codersdk.CreateTemplateVersionRequest)
33+
Variables []codersdk.TemplateVersionVariable
3334
}
3435

3536
funcDynamicParameterTemplate(t*testing.T,client*codersdk.Client,org uuid.UUID,argsDynamicParameterTemplateParams) (codersdk.Template, codersdk.TemplateVersion) {
@@ -48,6 +49,32 @@ func DynamicParameterTemplate(t *testing.T, client *codersdk.Client, org uuid.UU
4849
},
4950
}}
5051

52+
userVars:=make([]codersdk.VariableValue,0,len(args.Variables))
53+
parseVars:=make([]*proto.TemplateVariable,0,len(args.Variables))
54+
for_,argv:=rangeargs.Variables {
55+
parseVars=append(parseVars,&proto.TemplateVariable{
56+
Name:argv.Name,
57+
Description:argv.Description,
58+
Type:argv.Type,
59+
DefaultValue:argv.DefaultValue,
60+
Required:argv.Required,
61+
Sensitive:argv.Sensitive,
62+
})
63+
64+
userVars=append(userVars, codersdk.VariableValue{
65+
Name:argv.Name,
66+
Value:argv.Value,
67+
})
68+
}
69+
70+
files.Parse= []*proto.Response{{
71+
Type:&proto.Response_Parse{
72+
Parse:&proto.ParseComplete{
73+
TemplateVariables:parseVars,
74+
},
75+
},
76+
}}
77+
5178
mime:=codersdk.ContentTypeTar
5279
ifargs.Zip {
5380
mime=codersdk.ContentTypeZip
@@ -59,6 +86,7 @@ func DynamicParameterTemplate(t *testing.T, client *codersdk.Client, org uuid.UU
5986
ifargs.Version!=nil {
6087
args.Version(request)
6188
}
89+
request.UserVariableValues=userVars
6290
})
6391
AwaitTemplateVersionJobCompleted(t,client,version.ID)
6492

‎coderd/dynamicparameters/render.go‎

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"time"
1010

1111
"github.com/google/uuid"
12+
"github.com/zclconf/go-cty/cty"
1213
"golang.org/x/xerrors"
1314

1415
"github.com/coder/coder/v2/apiversion"
@@ -41,9 +42,10 @@ type loader struct {
4142
templateVersionID uuid.UUID
4243

4344
// cache of objects
44-
templateVersion*database.TemplateVersion
45-
job*database.ProvisionerJob
46-
terraformValues*database.TemplateVersionTerraformValue
45+
templateVersion*database.TemplateVersion
46+
job*database.ProvisionerJob
47+
terraformValues*database.TemplateVersionTerraformValue
48+
templateVariableValues*[]database.TemplateVersionVariable
4749
}
4850

4951
// Prepare is the entrypoint for this package. It loads the necessary objects &
@@ -61,6 +63,12 @@ func Prepare(ctx context.Context, db database.Store, cache files.FileAcquirer, v
6163
returnl.Renderer(ctx,db,cache)
6264
}
6365

66+
funcWithTemplateVariableValues(vals []database.TemplateVersionVariable)func(r*loader) {
67+
returnfunc(r*loader) {
68+
r.templateVariableValues=&vals
69+
}
70+
}
71+
6472
funcWithTemplateVersion(tv database.TemplateVersion)func(r*loader) {
6573
returnfunc(r*loader) {
6674
iftv.ID==r.templateVersionID {
@@ -127,6 +135,14 @@ func (r *loader) loadData(ctx context.Context, db database.Store) error {
127135
r.terraformValues=&values
128136
}
129137

138+
ifr.templateVariableValues==nil {
139+
vals,err:=db.GetTemplateVersionVariables(ctx,r.templateVersion.ID)
140+
iferr!=nil&&!xerrors.Is(err,sql.ErrNoRows) {
141+
returnxerrors.Errorf("template version variables: %w",err)
142+
}
143+
r.templateVariableValues=&vals
144+
}
145+
130146
returnnil
131147
}
132148

@@ -160,13 +176,17 @@ func (r *loader) dynamicRenderer(ctx context.Context, db database.Store, cache *
160176
}
161177
}()
162178

179+
tfVarValues,err:=VariableValues(*r.templateVariableValues)
180+
iferr!=nil {
181+
returnnil,xerrors.Errorf("parse variable values: %w",err)
182+
}
183+
163184
// If they can read the template version, then they can read the file for
164185
// parameter loading purposes.
165186
//nolint:gocritic
166187
fileCtx:=dbauthz.AsFileReader(ctx)
167188

168189
vartemplateFS fs.FS
169-
varerrerror
170190

171191
templateFS,err=cache.Acquire(fileCtx,db,r.job.FileID)
172192
iferr!=nil {
@@ -189,6 +209,7 @@ func (r *loader) dynamicRenderer(ctx context.Context, db database.Store, cache *
189209
db:db,
190210
ownerErrors:make(map[uuid.UUID]error),
191211
close:cache.Close,
212+
tfvarValues:tfVarValues,
192213
},nil
193214
}
194215

@@ -199,6 +220,7 @@ type dynamicRenderer struct {
199220

200221
ownerErrorsmap[uuid.UUID]error
201222
currentOwner*previewtypes.WorkspaceOwner
223+
tfvarValuesmap[string]cty.Value
202224

203225
once sync.Once
204226
closefunc()
@@ -229,6 +251,7 @@ func (r *dynamicRenderer) Render(ctx context.Context, ownerID uuid.UUID, values
229251
PlanJSON:r.data.terraformValues.CachedPlan,
230252
ParameterValues:values,
231253
Owner:*r.currentOwner,
254+
TFVars:r.tfvarValues,
232255
// Do not emit parser logs to coderd output logs.
233256
// TODO: Returning this logs in the output would benefit the caller.
234257
// Unsure how large the logs can be, so for now we just discard them.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package dynamicparameters
2+
3+
import (
4+
"strconv"
5+
6+
"github.com/zclconf/go-cty/cty"
7+
"github.com/zclconf/go-cty/cty/json"
8+
"golang.org/x/xerrors"
9+
10+
"github.com/coder/coder/v2/coderd/database"
11+
)
12+
13+
// VariableValues is a helper function that converts a slice of TemplateVersionVariable
14+
// into a map of cty.Value for use in coder/preview.
15+
funcVariableValues(vals []database.TemplateVersionVariable) (map[string]cty.Value,error) {
16+
ctyVals:=make(map[string]cty.Value,len(vals))
17+
for_,v:=rangevals {
18+
value:=v.Value
19+
ifvalue==""&&v.DefaultValue!="" {
20+
value=v.DefaultValue
21+
}
22+
23+
ifvalue=="" {
24+
// Empty strings are unsupported I guess?
25+
continue// omit non-set vals
26+
}
27+
28+
varerrerror
29+
switchv.Type {
30+
// Defaulting the empty type to "string"
31+
// TODO: This does not match the terraform behavior, however it is too late
32+
// at this point in the code to determine this, as the database type stores all values
33+
// as strings. The code needs to be fixed in the `Parse` step of the provisioner.
34+
// That step should determine the type of the variable correctly and store it in the database.
35+
case"string","":
36+
ctyVals[v.Name]=cty.StringVal(value)
37+
case"number":
38+
ctyVals[v.Name],err=cty.ParseNumberVal(value)
39+
iferr!=nil {
40+
returnnil,xerrors.Errorf("parse variable %q: %w",v.Name,err)
41+
}
42+
case"bool":
43+
parsed,err:=strconv.ParseBool(value)
44+
iferr!=nil {
45+
returnnil,xerrors.Errorf("parse variable %q: %w",v.Name,err)
46+
}
47+
ctyVals[v.Name]=cty.BoolVal(parsed)
48+
default:
49+
// If it is a complex type, let the cty json code give it a try.
50+
// TODO: Ideally we parse `list` & `map` and build the type ourselves.
51+
ty,err:=json.ImpliedType([]byte(value))
52+
iferr!=nil {
53+
returnnil,xerrors.Errorf("implied type for variable %q: %w",v.Name,err)
54+
}
55+
56+
jv,err:=json.Unmarshal([]byte(value),ty)
57+
iferr!=nil {
58+
returnnil,xerrors.Errorf("unmarshal variable %q: %w",v.Name,err)
59+
}
60+
ctyVals[v.Name]=jv
61+
}
62+
}
63+
64+
returnctyVals,nil
65+
}

‎coderd/parameters_test.go‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,36 @@ func TestDynamicParametersWithTerraformValues(t *testing.T) {
343343
require.Len(t,preview.Diagnostics,1)
344344
require.Equal(t,preview.Diagnostics[0].Extra.Code,"owner_not_found")
345345
})
346+
347+
t.Run("TemplateVariables",func(t*testing.T) {
348+
t.Parallel()
349+
350+
dynamicParametersTerraformSource,err:=os.ReadFile("testdata/parameters/variables/main.tf")
351+
require.NoError(t,err)
352+
353+
setup:=setupDynamicParamsTest(t,setupDynamicParamsTestParams{
354+
provisionerDaemonVersion:provProto.CurrentVersion.String(),
355+
mainTF:dynamicParametersTerraformSource,
356+
variables: []codersdk.TemplateVersionVariable{
357+
{Name:"one",Value:"austin",DefaultValue:"alice",Type:"string"},
358+
},
359+
plan:nil,
360+
static:nil,
361+
})
362+
363+
ctx:=testutil.Context(t,testutil.WaitShort)
364+
stream:=setup.stream
365+
previews:=stream.Chan()
366+
367+
// Should see the output of the module represented
368+
preview:=testutil.RequireReceive(ctx,t,previews)
369+
require.Equal(t,-1,preview.ID)
370+
require.Empty(t,preview.Diagnostics)
371+
372+
require.Len(t,preview.Parameters,1)
373+
coderdtest.AssertParameter(t,"variable_values",preview.Parameters).
374+
Exists().Value("austin")
375+
})
346376
}
347377

348378
typesetupDynamicParamsTestParamsstruct {
@@ -355,6 +385,7 @@ type setupDynamicParamsTestParams struct {
355385

356386
static []*proto.RichParameter
357387
expectWebsocketErrorbool
388+
variables []codersdk.TemplateVersionVariable
358389
}
359390

360391
typedynamicParamsTeststruct {
@@ -380,6 +411,7 @@ func setupDynamicParamsTest(t *testing.T, args setupDynamicParamsTestParams) dyn
380411
Plan:args.plan,
381412
ModulesArchive:args.modulesArchive,
382413
StaticParams:args.static,
414+
Variables:args.variables,
383415
})
384416

385417
ctx:=testutil.Context(t,testutil.WaitShort)

‎coderd/templateversions.go‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/google/uuid"
1919
"github.com/moby/moby/pkg/namesgenerator"
2020
"github.com/sqlc-dev/pqtype"
21+
"github.com/zclconf/go-cty/cty"
2122
"golang.org/x/xerrors"
2223

2324
"cdr.dev/slog"
@@ -1585,7 +1586,7 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
15851586
varparsedTagsmap[string]string
15861587
varokbool
15871588
ifdynamicTemplate {
1588-
parsedTags,ok=api.dynamicTemplateVersionTags(ctx,rw,organization.ID,apiKey.UserID,file)
1589+
parsedTags,ok=api.dynamicTemplateVersionTags(ctx,rw,organization.ID,apiKey.UserID,file,req.UserVariableValues)
15891590
if!ok {
15901591
return
15911592
}
@@ -1762,7 +1763,7 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
17621763
warnings))
17631764
}
17641765

1765-
func (api*API)dynamicTemplateVersionTags(ctx context.Context,rw http.ResponseWriter,orgID uuid.UUID,owner uuid.UUID,file database.File) (map[string]string,bool) {
1766+
func (api*API)dynamicTemplateVersionTags(ctx context.Context,rw http.ResponseWriter,orgID uuid.UUID,owner uuid.UUID,file database.File,templateVariables []codersdk.VariableValue) (map[string]string,bool) {
17661767
ownerData,err:=dynamicparameters.WorkspaceOwner(ctx,api.Database,orgID,owner)
17671768
iferr!=nil {
17681769
ifhttpapi.Is404Error(err) {
@@ -1800,11 +1801,19 @@ func (api *API) dynamicTemplateVersionTags(ctx context.Context, rw http.Response
18001801
returnnil,false
18011802
}
18021803

1804+
// Pass in any manually specified template variables as TFVars.
1805+
// TODO: Does this break if the type is not a string?
1806+
tfVarValues:=make(map[string]cty.Value)
1807+
for_,variable:=rangetemplateVariables {
1808+
tfVarValues[variable.Name]=cty.StringVal(variable.Value)
1809+
}
1810+
18031811
output,diags:=preview.Preview(ctx, preview.Input{
18041812
PlanJSON:nil,// Template versions are before `terraform plan`
18051813
ParameterValues:nil,// No user-specified parameters
18061814
Owner:*ownerData,
18071815
Logger:stdslog.New(stdslog.DiscardHandler),
1816+
TFVars:tfVarValues,
18081817
},files)
18091818
tagErr:=dynamicparameters.CheckTags(output,diags)
18101819
iftagErr!=nil {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Base case for workspace tags + parameters.
2+
terraform {
3+
required_providers {
4+
coder={
5+
source="coder/coder"
6+
}
7+
docker={
8+
source="kreuzwerker/docker"
9+
version="3.0.2"
10+
}
11+
}
12+
}
13+
14+
variable"one" {
15+
default="alice"
16+
type=string
17+
}
18+
19+
20+
data"coder_parameter""variable_values" {
21+
name="variable_values"
22+
description="Just to show the variable values"
23+
type="string"
24+
default=var.one
25+
26+
option {
27+
name="one"
28+
value=var.one
29+
}
30+
}

‎coderd/wsbuilder/wsbuilder.go‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,10 +633,16 @@ func (b *Builder) getDynamicParameterRenderer() (dynamicparameters.Renderer, err
633633
returnnil,xerrors.Errorf("get template version terraform values: %w",err)
634634
}
635635

636+
variableValues,err:=b.getTemplateVersionVariables()
637+
iferr!=nil {
638+
returnnil,xerrors.Errorf("get template version variables: %w",err)
639+
}
640+
636641
renderer,err:=dynamicparameters.Prepare(b.ctx,b.store,b.fileCache,tv.ID,
637642
dynamicparameters.WithTemplateVersion(*tv),
638643
dynamicparameters.WithProvisionerJob(*job),
639644
dynamicparameters.WithTerraformValues(*tfVals),
645+
dynamicparameters.WithTemplateVariableValues(variableValues),
640646
)
641647
iferr!=nil {
642648
returnnil,xerrors.Errorf("get template version renderer: %w",err)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp