feat: use preview to compute workspace tags from terraform (#18720)

If using dynamic parameters, workspace tags are extracted using
`coder/preview`.
This commit is contained in:
Steven Masley
2025-07-03 14:35:44 -05:00
committed by GitHub
parent 4607e5113b
commit a099a8a25c
14 changed files with 1185 additions and 78 deletions

View File

@ -25,7 +25,9 @@ func TestDynamicParameterBuild(t *testing.T) {
t.Parallel()
owner, _, _, first := coderdenttest.NewWithAPI(t, &coderdenttest.Options{
Options: &coderdtest.Options{IncludeProvisionerDaemon: true},
Options: &coderdtest.Options{
IncludeProvisionerDaemon: true,
},
LicenseOptions: &coderdenttest.LicenseOptions{
Features: license.Features{
codersdk.FeatureTemplateRBAC: 1,
@ -355,6 +357,92 @@ func TestDynamicParameterBuild(t *testing.T) {
})
}
func TestDynamicWorkspaceTags(t *testing.T) {
t.Parallel()
owner, _, _, first := coderdenttest.NewWithAPI(t, &coderdenttest.Options{
Options: &coderdtest.Options{
IncludeProvisionerDaemon: true,
},
LicenseOptions: &coderdenttest.LicenseOptions{
Features: license.Features{
codersdk.FeatureTemplateRBAC: 1,
codersdk.FeatureExternalProvisionerDaemons: 1,
},
},
})
orgID := first.OrganizationID
templateAdmin, _ := coderdtest.CreateAnotherUser(t, owner, orgID, rbac.ScopedRoleOrgTemplateAdmin(orgID))
// create the template first, mark it as dynamic, then create the second version with the workspace tags.
// This ensures the template import uses the dynamic tags flow. The second step will happen in a test below.
workspaceTags, _ := coderdtest.DynamicParameterTemplate(t, templateAdmin, orgID, coderdtest.DynamicParameterTemplateParams{
MainTF: ``,
})
expectedTags := map[string]string{
"function": "param is foo",
"stringvar": "bar",
"numvar": "42",
"boolvar": "true",
"stringparam": "foo",
"numparam": "7",
"boolparam": "true",
"listparam": `["a","b"]`,
"static": "static value",
}
// A new provisioner daemon is required to make the template version.
importProvisioner := coderdenttest.NewExternalProvisionerDaemon(t, owner, first.OrganizationID, expectedTags)
defer importProvisioner.Close()
// This tests the template import's workspace tags extraction.
workspaceTags, workspaceTagsVersion := coderdtest.DynamicParameterTemplate(t, templateAdmin, orgID, coderdtest.DynamicParameterTemplateParams{
MainTF: string(must(os.ReadFile("testdata/parameters/workspacetags/main.tf"))),
TemplateID: workspaceTags.ID,
Version: func(request *codersdk.CreateTemplateVersionRequest) {
request.ProvisionerTags = map[string]string{
"static": "static value",
}
},
})
importProvisioner.Close() // No longer need this provisioner daemon, as the template import is done.
// Test the workspace create tag extraction.
expectedTags["function"] = "param is baz"
expectedTags["stringparam"] = "baz"
expectedTags["numparam"] = "8"
expectedTags["boolparam"] = "false"
workspaceProvisioner := coderdenttest.NewExternalProvisionerDaemon(t, owner, first.OrganizationID, expectedTags)
defer workspaceProvisioner.Close()
ctx := testutil.Context(t, testutil.WaitShort)
wrk, err := templateAdmin.CreateUserWorkspace(ctx, codersdk.Me, codersdk.CreateWorkspaceRequest{
TemplateVersionID: workspaceTagsVersion.ID,
Name: coderdtest.RandomUsername(t),
RichParameterValues: []codersdk.WorkspaceBuildParameter{
{Name: "stringparam", Value: "baz"},
{Name: "numparam", Value: "8"},
{Name: "boolparam", Value: "false"},
},
})
require.NoError(t, err)
build, err := templateAdmin.WorkspaceBuild(ctx, wrk.LatestBuild.ID)
require.NoError(t, err)
job, err := templateAdmin.OrganizationProvisionerJob(ctx, first.OrganizationID, build.Job.ID)
require.NoError(t, err)
// If the tags do no match, the await will fail.
// 'scope' and 'owner' tags are always included.
expectedTags["scope"] = "organization"
expectedTags["owner"] = ""
require.Equal(t, expectedTags, job.Tags)
coderdtest.AwaitWorkspaceBuildJobCompleted(t, templateAdmin, wrk.LatestBuild.ID)
}
// TestDynamicParameterTemplate uses a template with some dynamic elements, and
// tests the parameters, values, etc are all as expected.
func TestDynamicParameterTemplate(t *testing.T) {