Skip to content

Commit 76adde9

Browse files
authored
fix(provisioner/terraform/tfparse): allow empty values in coder_workspace_tag defaults (#16303)
* chore(docs): update docs re workspace tag default values * chore(coderdenttest): use random name instead of t.Name() in newExternalProvisionerDaemon * fix(provisioner/terraform/tfparse): allow empty values in coder_workspace_tag defaults
1 parent f518669 commit 76adde9

File tree

8 files changed

+90
-32
lines changed

8 files changed

+90
-32
lines changed

coderd/templateversions_test.go

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -429,9 +429,8 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) {
429429
}
430430
}`,
431431
},
432-
reqTags: map[string]string{"a": "b"},
433-
// wantTags: map[string]string{"owner": "", "scope": "organization", "a": "b"},
434-
expectError: `provisioner tag "a" evaluated to an empty value`,
432+
reqTags: map[string]string{"a": "b"},
433+
wantTags: map[string]string{"owner": "", "scope": "organization", "a": "b"},
435434
},
436435
{
437436
name: "main.tf with disallowed workspace tag value",
@@ -568,6 +567,42 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) {
568567
},
569568
wantTags: map[string]string{"owner": "", "scope": "organization"},
570569
},
570+
{
571+
name: "main.tf with tags from parameter with default value from variable no default",
572+
files: map[string]string{
573+
`main.tf`: `
574+
variable "provisioner" {
575+
type = string
576+
}
577+
variable "default_provisioner" {
578+
type = string
579+
default = "" # intentionally blank, set on template creation
580+
}
581+
data "coder_parameter" "provisioner" {
582+
name = "provisioner"
583+
mutable = false
584+
default = var.default_provisioner
585+
dynamic "option" {
586+
for_each = toset(split(",", var.provisioner))
587+
content {
588+
name = option.value
589+
value = option.value
590+
}
591+
}
592+
}
593+
data "coder_workspace_tags" "tags" {
594+
tags = {
595+
"provisioner" : data.coder_parameter.provisioner.value
596+
}
597+
}`,
598+
},
599+
reqTags: map[string]string{
600+
"provisioner": "alpha",
601+
},
602+
wantTags: map[string]string{
603+
"provisioner": "alpha", "owner": "", "scope": "organization",
604+
},
605+
},
571606
} {
572607
tt := tt
573608
t.Run(tt.name, func(t *testing.T) {

docs/admin/templates/extending-templates/workspace-tags.md

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,6 @@ variables and parameters. This is illustrated in the table below:
6262

6363
## Constraints
6464

65-
### Default Values
66-
67-
All template variables and `coder_parameter` data sources **must** provide a
68-
default value. Failure to do so will result in an error.
69-
7065
### Tagged provisioners
7166

7267
It is possible to choose tag combinations that no provisioner can handle. This
@@ -127,6 +122,6 @@ variables, and references to other resources.
127122

128123
#### Not supported
129124

130-
- Function calls: `try(var.foo, "default")`
125+
- Function calls that reference files on disk: `abspath`, `file*`, `pathexpand`
131126
- Resources: `compute_instance.dev.name`
132127
- Data sources other than `coder_parameter`: `data.local_file.hostname.content`

enterprise/coderd/coderdenttest/coderdenttest.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ func newExternalProvisionerDaemon(t testing.TB, client *codersdk.Client, org uui
389389
daemon := provisionerd.New(func(ctx context.Context) (provisionerdproto.DRPCProvisionerDaemonClient, error) {
390390
return client.ServeProvisionerDaemon(ctx, codersdk.ServeProvisionerDaemonRequest{
391391
ID: uuid.New(),
392-
Name: t.Name(),
392+
Name: testutil.GetRandomName(t),
393393
Organization: org,
394394
Provisioners: []codersdk.ProvisionerType{provisionerType},
395395
Tags: tags,

enterprise/coderd/provisionerdaemons_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ func TestProvisionerDaemonServe(t *testing.T) {
285285
daemons, err := client.ProvisionerDaemons(context.Background())
286286
assert.NoError(t, err, "failed to get provisioner daemons")
287287
return len(daemons) > 0 &&
288-
assert.Equal(t, t.Name(), daemons[0].Name) &&
288+
assert.NotEmpty(t, daemons[0].Name) &&
289289
assert.Equal(t, provisionersdk.ScopeUser, daemons[0].Tags[provisionersdk.TagScope]) &&
290290
assert.Equal(t, user.UserID.String(), daemons[0].Tags[provisionersdk.TagOwner])
291291
}, testutil.WaitShort, testutil.IntervalMedium)

enterprise/coderd/workspaces_test.go

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,8 +1488,11 @@ func TestWorkspaceTagsTerraform(t *testing.T) {
14881488
createTemplateVersionRequestTags map[string]string
14891489
// the coder_workspace_tags bit of main.tf.
14901490
// you can add more stuff here if you need
1491-
tfWorkspaceTags string
1492-
skipCreateWorkspace bool
1491+
tfWorkspaceTags string
1492+
templateImportUserVariableValues []codersdk.VariableValue
1493+
// if we need to set parameters on workspace build
1494+
workspaceBuildParameters []codersdk.WorkspaceBuildParameter
1495+
skipCreateWorkspace bool
14931496
}{
14941497
{
14951498
name: "no tags",
@@ -1589,6 +1592,38 @@ func TestWorkspaceTagsTerraform(t *testing.T) {
15891592
// matching tag foo=bar.
15901593
skipCreateWorkspace: true,
15911594
},
1595+
{
1596+
name: "overrides with dynamic option from var",
1597+
provisionerTags: map[string]string{"foo": "bar"},
1598+
createTemplateVersionRequestTags: map[string]string{"foo": "bar"},
1599+
templateImportUserVariableValues: []codersdk.VariableValue{{Name: "default_foo", Value: "baz"}, {Name: "foo", Value: "bar,baz"}},
1600+
workspaceBuildParameters: []codersdk.WorkspaceBuildParameter{{Name: "foo", Value: "bar"}},
1601+
tfWorkspaceTags: `
1602+
variable "default_foo" {
1603+
type = string
1604+
}
1605+
variable "foo" {
1606+
type = string
1607+
}
1608+
data "coder_parameter" "foo" {
1609+
name = "foo"
1610+
type = "string"
1611+
default = var.default_foo
1612+
mutable = false
1613+
dynamic "option" {
1614+
for_each = toset(split(",", var.foo))
1615+
content {
1616+
name = option.value
1617+
value = option.value
1618+
}
1619+
}
1620+
}
1621+
data "coder_workspace_tags" "tags" {
1622+
tags = {
1623+
"foo" = data.coder_parameter.foo.value
1624+
}
1625+
}`,
1626+
},
15921627
} {
15931628
tc := tc
15941629
t.Run(tc.name, func(t *testing.T) {
@@ -1617,11 +1652,12 @@ func TestWorkspaceTagsTerraform(t *testing.T) {
16171652
fi, err := templateAdmin.Upload(ctx, "application/x-tar", bytes.NewReader(tarBytes))
16181653
require.NoError(t, err, "failed to upload file")
16191654
tv, err := templateAdmin.CreateTemplateVersion(ctx, owner.OrganizationID, codersdk.CreateTemplateVersionRequest{
1620-
Name: testutil.GetRandomName(t),
1621-
FileID: fi.ID,
1622-
StorageMethod: codersdk.ProvisionerStorageMethodFile,
1623-
Provisioner: codersdk.ProvisionerTypeTerraform,
1624-
ProvisionerTags: tc.createTemplateVersionRequestTags,
1655+
Name: testutil.GetRandomName(t),
1656+
FileID: fi.ID,
1657+
StorageMethod: codersdk.ProvisionerStorageMethodFile,
1658+
Provisioner: codersdk.ProvisionerTypeTerraform,
1659+
ProvisionerTags: tc.createTemplateVersionRequestTags,
1660+
UserVariableValues: tc.templateImportUserVariableValues,
16251661
})
16261662
require.NoError(t, err, "failed to create template version")
16271663
coderdtest.AwaitTemplateVersionJobCompleted(t, templateAdmin, tv.ID)
@@ -1630,8 +1666,9 @@ func TestWorkspaceTagsTerraform(t *testing.T) {
16301666
if !tc.skipCreateWorkspace {
16311667
// Creating a workspace as a non-privileged user must succeed
16321668
ws, err := member.CreateUserWorkspace(ctx, memberUser.Username, codersdk.CreateWorkspaceRequest{
1633-
TemplateID: tpl.ID,
1634-
Name: coderdtest.RandomUsername(t),
1669+
TemplateID: tpl.ID,
1670+
Name: coderdtest.RandomUsername(t),
1671+
RichParameterValues: tc.workspaceBuildParameters,
16351672
})
16361673
require.NoError(t, err, "failed to create workspace")
16371674
coderdtest.AwaitWorkspaceBuildJobCompleted(t, member, ws.LatestBuild.ID)

examples/workspace-tags/README.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ icon: /icon/docker.png
77

88
## Overview
99

10-
This Coder template presents use of [Workspace Tags](https://coder.com/docs/templates/workspace-tags) [Coder Parameters](https://coder.com/docs/templates/parameters).
10+
This Coder template presents use of [Workspace Tags](https://coder.com/docs/admin/templates/extending-templates/workspace-tags) and [Coder Parameters](https://coder.com/docs/templates/parameters).
1111

1212
## Use case
1313

@@ -18,10 +18,8 @@ By using `coder_workspace_tags` and `coder_parameter`s, template administrators
1818
## Notes
1919

2020
- You will need to have an [external provisioner](https://coder.com/docs/admin/provisioners#external-provisioners) with the correct tagset running in order to import this template.
21-
- When specifying values for the `coder_workspace_tags` data source, you are restricted to using a subset of Terraform's capabilities.
22-
- You must specify default values for all data sources and variables referenced by the `coder_workspace_tags` data source.
21+
- When specifying values for the `coder_workspace_tags` data source, you are restricted to using a subset of Terraform's capabilities. See [here](https://coder.com/docs/admin/templates/extending-templates/workspace-tags) for more details.
2322

24-
See [Workspace Tags](https://coder.com/docs/templates/workspace-tags) for more information.
2523

2624
## Development
2725

provisioner/terraform/tfparse/tfparse.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,6 @@ func (p *Parser) WorkspaceTagDefaults(ctx context.Context) (map[string]string, e
239239
return nil, xerrors.Errorf("eval provisioner tags: %w", err)
240240
}
241241

242-
// Ensure that none of the tag values are empty after evaluation.
243-
for k, v := range evalTags {
244-
if len(strings.TrimSpace(v)) > 0 {
245-
continue
246-
}
247-
return nil, xerrors.Errorf("provisioner tag %q evaluated to an empty value, please set a default value", k)
248-
}
249242
return evalTags, nil
250243
}
251244

provisioner/terraform/tfparse/tfparse_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ func Test_WorkspaceTagDefaultsFromFile(t *testing.T) {
268268
}
269269
}`,
270270
},
271-
expectError: `provisioner tag "az" evaluated to an empty value, please set a default value`,
271+
expectTags: map[string]string{"cluster": "developers", "az": "", "platform": "kubernetes", "region": "us"},
272272
},
273273
{
274274
name: "main.tf with missing parameter default value outside workspace tags",

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy