Skip to content

Commit

Permalink
Convert variable types before applying defaults (#1582)
Browse files Browse the repository at this point in the history
  • Loading branch information
wata727 committed Nov 5, 2022
1 parent 660965a commit a11f482
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 8 deletions.
16 changes: 8 additions & 8 deletions terraform/evaluator.go
Expand Up @@ -248,14 +248,6 @@ func (d *evaluationData) GetInputVariable(addr addrs.InputVariable, rng hcl.Rang
val = config.Default
}

// Apply defaults from the variable's type constraint to the value,
// unless the value is null. We do not apply defaults to top-level
// null values, as doing so could prevent assigning null to a nullable
// variable.
if config.TypeDefaults != nil && !val.IsNull() {
val = config.TypeDefaults.Apply(val)
}

var err error
val, err = convert.Convert(val, config.ConstraintType)
if err != nil {
Expand All @@ -268,6 +260,14 @@ func (d *evaluationData) GetInputVariable(addr addrs.InputVariable, rng hcl.Rang
val = cty.UnknownVal(config.Type)
}

// Apply defaults from the variable's type constraint to the value,
// unless the value is null. We do not apply defaults to top-level
// null values, as doing so could prevent assigning null to a nullable
// variable.
if config.TypeDefaults != nil && !val.IsNull() {
val = config.TypeDefaults.Apply(val)
}

// Mark if sensitive
if config.Sensitive {
val = val.Mark(marks.Sensitive)
Expand Down
96 changes: 96 additions & 0 deletions terraform/evaluator_test.go
Expand Up @@ -517,6 +517,102 @@ variable "foo" {
want: `cty.NullVal(cty.Object(map[string]cty.Type{"default":cty.Bool, "optional":cty.String, "required":cty.String}))`,
errCheck: neverHappend,
},
{
name: "module variable optional attributes with nested default optional",
config: `
variable "foo" {
type = set(object({
name = string
schedules = set(object({
name = string
cold_storage_after = optional(number, 10)
}))
}))
}`,
expr: expr(`var.foo`),
inputs: []InputValues{
{
"foo": {
Value: cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("test1"),
"schedules": cty.SetVal([]cty.Value{
cty.MapVal(map[string]cty.Value{
"name": cty.StringVal("daily"),
}),
}),
}),
cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("test2"),
"schedules": cty.SetVal([]cty.Value{
cty.MapVal(map[string]cty.Value{
"name": cty.StringVal("daily"),
}),
cty.MapVal(map[string]cty.Value{
"name": cty.StringVal("weekly"),
"cold_storage_after": cty.StringVal("0"),
}),
}),
}),
}),
},
},
},
ty: cty.Set(cty.Object(map[string]cty.Type{
"name": cty.String,
"schedules": cty.Set(cty.Object(map[string]cty.Type{
"name": cty.String,
"cold_storage_after": cty.Number,
})),
})),
want: `cty.SetVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{"name":cty.StringVal("test1"), "schedules":cty.SetVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{"cold_storage_after":cty.NumberIntVal(10), "name":cty.StringVal("daily")})})}), cty.ObjectVal(map[string]cty.Value{"name":cty.StringVal("test2"), "schedules":cty.SetVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{"cold_storage_after":cty.NumberIntVal(0), "name":cty.StringVal("weekly")}), cty.ObjectVal(map[string]cty.Value{"cold_storage_after":cty.NumberIntVal(10), "name":cty.StringVal("daily")})})})})`,
errCheck: neverHappend,
},
{
name: "module variable optional attributes with nested complex types",
config: `
variable "foo" {
type = object({
name = string
nested_object = object({
name = string
value = optional(string, "foo")
})
nested_object_with_default = optional(object({
name = string
value = optional(string, "bar")
}), {
name = "nested_object_with_default"
})
})
}`,
expr: expr(`var.foo`),
inputs: []InputValues{
{
"foo": {
Value: cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("object"),
"nested_object": cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("nested_object"),
}),
}),
},
},
},
ty: cty.Object(map[string]cty.Type{
"name": cty.String,
"nested_object": cty.Object(map[string]cty.Type{
"name": cty.String,
"value": cty.String,
}),
"nested_object_with_default": cty.Object(map[string]cty.Type{
"name": cty.String,
"value": cty.String,
}),
}),
want: `cty.ObjectVal(map[string]cty.Value{"name":cty.StringVal("object"), "nested_object":cty.ObjectVal(map[string]cty.Value{"name":cty.StringVal("nested_object"), "value":cty.StringVal("foo")}), "nested_object_with_default":cty.ObjectVal(map[string]cty.Value{"name":cty.StringVal("nested_object_with_default"), "value":cty.StringVal("bar")})})`,
errCheck: neverHappend,
},
{
name: "static local value",
config: `locals { foo = "bar" }`,
Expand Down

0 comments on commit a11f482

Please sign in to comment.