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

@ -83,6 +83,7 @@ type Builder struct {
parameterValues *[]string
templateVersionPresetParameterValues *[]database.TemplateVersionPresetParameter
parameterRender dynamicparameters.Renderer
workspaceTags *map[string]string
prebuiltWorkspaceBuildStage sdkproto.PrebuiltWorkspaceBuildStage
verifyNoLegacyParametersOnce bool
@ -939,6 +940,76 @@ func (b *Builder) getLastBuildJob() (*database.ProvisionerJob, error) {
}
func (b *Builder) getProvisionerTags() (map[string]string, error) {
if b.workspaceTags != nil {
return *b.workspaceTags, nil
}
var tags map[string]string
var err error
if b.usingDynamicParameters() {
tags, err = b.getDynamicProvisionerTags()
} else {
tags, err = b.getClassicProvisionerTags()
}
if err != nil {
return nil, xerrors.Errorf("get provisioner tags: %w", err)
}
b.workspaceTags = &tags
return *b.workspaceTags, nil
}
func (b *Builder) getDynamicProvisionerTags() (map[string]string, error) {
// Step 1: Mutate template manually set version tags
templateVersionJob, err := b.getTemplateVersionJob()
if err != nil {
return nil, BuildError{http.StatusInternalServerError, "failed to fetch template version job", err}
}
annotationTags := provisionersdk.MutateTags(b.workspace.OwnerID, templateVersionJob.Tags)
tags := map[string]string{}
for name, value := range annotationTags {
tags[name] = value
}
// Step 2: Fetch tags from the template
render, err := b.getDynamicParameterRenderer()
if err != nil {
return nil, BuildError{http.StatusInternalServerError, "failed to get dynamic parameter renderer", err}
}
names, values, err := b.getParameters()
if err != nil {
return nil, xerrors.Errorf("tags render: %w", err)
}
vals := make(map[string]string, len(names))
for i, name := range names {
if i >= len(values) {
return nil, BuildError{
http.StatusInternalServerError,
fmt.Sprintf("parameter names and values mismatch, %d names & %d values", len(names), len(values)),
xerrors.New("names and values mismatch"),
}
}
vals[name] = values[i]
}
output, diags := render.Render(b.ctx, b.workspace.OwnerID, vals)
tagErr := dynamicparameters.CheckTags(output, diags)
if tagErr != nil {
return nil, tagErr
}
for k, v := range output.WorkspaceTags.Tags() {
tags[k] = v
}
return tags, nil
}
func (b *Builder) getClassicProvisionerTags() (map[string]string, error) {
// Step 1: Mutate template version tags
templateVersionJob, err := b.getTemplateVersionJob()
if err != nil {