mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix(provisioner/terraform/tfparse): evaluate coder_parameter defaults with variables (#15800)
- adds support for dynamic default values in coder_parameter data source
This commit is contained in:
@@ -172,7 +172,7 @@ func (p *Parser) WorkspaceTagDefaults(ctx context.Context) (map[string]string, e
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("load variable defaults: %w", err)
|
||||
}
|
||||
paramsDefaults, err := p.CoderParameterDefaults(ctx)
|
||||
paramsDefaults, err := p.CoderParameterDefaults(ctx, varsDefaults)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("load parameter defaults: %w", err)
|
||||
}
|
||||
@@ -268,7 +268,7 @@ func (p *Parser) VariableDefaults(ctx context.Context) (map[string]string, error
|
||||
|
||||
// CoderParameterDefaults returns the default values of all coder_parameter data sources
|
||||
// in the parsed module.
|
||||
func (p *Parser) CoderParameterDefaults(ctx context.Context) (map[string]string, error) {
|
||||
func (p *Parser) CoderParameterDefaults(ctx context.Context, varsDefaults map[string]string) (map[string]string, error) {
|
||||
defaultsM := make(map[string]string)
|
||||
var (
|
||||
skipped []string
|
||||
@@ -316,6 +316,7 @@ func (p *Parser) CoderParameterDefaults(ctx context.Context) (map[string]string,
|
||||
}
|
||||
|
||||
if _, ok := resContent.Attributes["default"]; !ok {
|
||||
p.logger.Warn(ctx, "coder_parameter data source does not have a default value", slog.F("name", dataResource.Name))
|
||||
defaultsM[dataResource.Name] = ""
|
||||
} else {
|
||||
expr := resContent.Attributes["default"].Expr
|
||||
@@ -323,7 +324,20 @@ func (p *Parser) CoderParameterDefaults(ctx context.Context) (map[string]string,
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("can't preview the resource file: %v", err)
|
||||
}
|
||||
defaultsM[dataResource.Name] = strings.Trim(value, `"`)
|
||||
// Issue #15795: the "default" value could also be an expression we need
|
||||
// to evaluate.
|
||||
// TODO: should we support coder_parameter default values that reference other coder_parameter data sources?
|
||||
evalCtx := buildEvalContext(varsDefaults, nil)
|
||||
val, diags := expr.Value(evalCtx)
|
||||
if diags.HasErrors() {
|
||||
return nil, xerrors.Errorf("failed to evaluate coder_parameter %q default value %q: %s", dataResource.Name, value, diags.Error())
|
||||
}
|
||||
// Do not use "val.AsString()" as it can panic
|
||||
strVal, err := ctyValueString(val)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to marshal coder_parameter %q default value %q as string: %s", dataResource.Name, value, err)
|
||||
}
|
||||
defaultsM[dataResource.Name] = strings.Trim(strVal, `"`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +114,73 @@ func Test_WorkspaceTagDefaultsFromFile(t *testing.T) {
|
||||
expectTags: map[string]string{"platform": "kubernetes", "cluster": "developers", "region": "us", "az": "a"},
|
||||
expectError: "",
|
||||
},
|
||||
{
|
||||
name: "main.tf with parameter that has default value from dynamic value",
|
||||
files: map[string]string{
|
||||
"main.tf": `
|
||||
provider "foo" {}
|
||||
resource "foo_bar" "baz" {}
|
||||
variable "region" {
|
||||
type = string
|
||||
default = "us"
|
||||
}
|
||||
variable "az" {
|
||||
type = string
|
||||
default = "${""}${"a"}"
|
||||
}
|
||||
data "base" "ours" {
|
||||
all = true
|
||||
}
|
||||
data "coder_parameter" "az" {
|
||||
name = "az"
|
||||
type = "string"
|
||||
default = var.az
|
||||
}
|
||||
data "coder_workspace_tags" "tags" {
|
||||
tags = {
|
||||
"platform" = "kubernetes",
|
||||
"cluster" = "${"devel"}${"opers"}"
|
||||
"region" = var.region
|
||||
"az" = data.coder_parameter.az.value
|
||||
}
|
||||
}`,
|
||||
},
|
||||
expectTags: map[string]string{"platform": "kubernetes", "cluster": "developers", "region": "us", "az": "a"},
|
||||
expectError: "",
|
||||
},
|
||||
{
|
||||
name: "main.tf with parameter that has default value from another parameter",
|
||||
files: map[string]string{
|
||||
"main.tf": `
|
||||
provider "foo" {}
|
||||
resource "foo_bar" "baz" {}
|
||||
variable "region" {
|
||||
type = string
|
||||
default = "us"
|
||||
}
|
||||
data "base" "ours" {
|
||||
all = true
|
||||
}
|
||||
data "coder_parameter" "az" {
|
||||
type = string
|
||||
default = "${""}${"a"}"
|
||||
}
|
||||
data "coder_parameter" "az2" {
|
||||
name = "az"
|
||||
type = "string"
|
||||
default = data.coder_parameter.az.value
|
||||
}
|
||||
data "coder_workspace_tags" "tags" {
|
||||
tags = {
|
||||
"platform" = "kubernetes",
|
||||
"cluster" = "${"devel"}${"opers"}"
|
||||
"region" = var.region
|
||||
"az" = data.coder_parameter.az2.value
|
||||
}
|
||||
}`,
|
||||
},
|
||||
expectError: "Unknown variable; There is no variable named \"data\".",
|
||||
},
|
||||
{
|
||||
name: "main.tf with multiple valid workspace tags",
|
||||
files: map[string]string{
|
||||
|
||||
Reference in New Issue
Block a user