Skip to content

Commit f8e2b3a

Browse files
authored
Merge pull request #31154 from hashicorp/alisdair/module-variable-optional-default
Add inline defaults to optional object attribute type constraints
2 parents 82f47ca + e2a3042 commit f8e2b3a

File tree

17 files changed

+1238
-1227
lines changed

17 files changed

+1238
-1227
lines changed

internal/configs/named_values.go

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type Variable struct {
2727
// ConstraintType is used for decoding and type conversions, and may
2828
// contain nested ObjectWithOptionalAttr types.
2929
ConstraintType cty.Type
30+
TypeDefaults *typeexpr.Defaults
3031

3132
ParsingMode VariableParsingMode
3233
Validations []*CheckRule
@@ -102,9 +103,10 @@ func decodeVariableBlock(block *hcl.Block, override bool) (*Variable, hcl.Diagno
102103
}
103104

104105
if attr, exists := content.Attributes["type"]; exists {
105-
ty, parseMode, tyDiags := decodeVariableType(attr.Expr)
106+
ty, tyDefaults, parseMode, tyDiags := decodeVariableType(attr.Expr)
106107
diags = append(diags, tyDiags...)
107108
v.ConstraintType = ty
109+
v.TypeDefaults = tyDefaults
108110
v.Type = ty.WithoutOptionalAttributesDeep()
109111
v.ParsingMode = parseMode
110112
}
@@ -137,6 +139,11 @@ func decodeVariableBlock(block *hcl.Block, override bool) (*Variable, hcl.Diagno
137139
// the type might not be set; we'll catch that during merge.
138140
if v.ConstraintType != cty.NilType {
139141
var err error
142+
// If the type constraint has defaults, we must apply those
143+
// defaults to the variable default value before type conversion.
144+
if v.TypeDefaults != nil {
145+
val = v.TypeDefaults.Apply(val)
146+
}
140147
val, err = convert.Convert(val, v.ConstraintType)
141148
if err != nil {
142149
diags = append(diags, &hcl.Diagnostic{
@@ -179,7 +186,7 @@ func decodeVariableBlock(block *hcl.Block, override bool) (*Variable, hcl.Diagno
179186
return v, diags
180187
}
181188

182-
func decodeVariableType(expr hcl.Expression) (cty.Type, VariableParsingMode, hcl.Diagnostics) {
189+
func decodeVariableType(expr hcl.Expression) (cty.Type, *typeexpr.Defaults, VariableParsingMode, hcl.Diagnostics) {
183190
if exprIsNativeQuotedString(expr) {
184191
// If a user provides the pre-0.12 form of variable type argument where
185192
// the string values "string", "list" and "map" are accepted, we
@@ -190,7 +197,7 @@ func decodeVariableType(expr hcl.Expression) (cty.Type, VariableParsingMode, hcl
190197
// in the normal codepath below.
191198
val, diags := expr.Value(nil)
192199
if diags.HasErrors() {
193-
return cty.DynamicPseudoType, VariableParseHCL, diags
200+
return cty.DynamicPseudoType, nil, VariableParseHCL, diags
194201
}
195202
str := val.AsString()
196203
switch str {
@@ -201,25 +208,25 @@ func decodeVariableType(expr hcl.Expression) (cty.Type, VariableParsingMode, hcl
201208
Detail: "Terraform 0.11 and earlier required type constraints to be given in quotes, but that form is now deprecated and will be removed in a future version of Terraform. Remove the quotes around \"string\".",
202209
Subject: expr.Range().Ptr(),
203210
})
204-
return cty.DynamicPseudoType, VariableParseLiteral, diags
211+
return cty.DynamicPseudoType, nil, VariableParseLiteral, diags
205212
case "list":
206213
diags = append(diags, &hcl.Diagnostic{
207214
Severity: hcl.DiagError,
208215
Summary: "Invalid quoted type constraints",
209216
Detail: "Terraform 0.11 and earlier required type constraints to be given in quotes, but that form is now deprecated and will be removed in a future version of Terraform. Remove the quotes around \"list\" and write list(string) instead to explicitly indicate that the list elements are strings.",
210217
Subject: expr.Range().Ptr(),
211218
})
212-
return cty.DynamicPseudoType, VariableParseHCL, diags
219+
return cty.DynamicPseudoType, nil, VariableParseHCL, diags
213220
case "map":
214221
diags = append(diags, &hcl.Diagnostic{
215222
Severity: hcl.DiagError,
216223
Summary: "Invalid quoted type constraints",
217224
Detail: "Terraform 0.11 and earlier required type constraints to be given in quotes, but that form is now deprecated and will be removed in a future version of Terraform. Remove the quotes around \"map\" and write map(string) instead to explicitly indicate that the map elements are strings.",
218225
Subject: expr.Range().Ptr(),
219226
})
220-
return cty.DynamicPseudoType, VariableParseHCL, diags
227+
return cty.DynamicPseudoType, nil, VariableParseHCL, diags
221228
default:
222-
return cty.DynamicPseudoType, VariableParseHCL, hcl.Diagnostics{{
229+
return cty.DynamicPseudoType, nil, VariableParseHCL, hcl.Diagnostics{{
223230
Severity: hcl.DiagError,
224231
Summary: "Invalid legacy variable type hint",
225232
Detail: `To provide a full type expression, remove the surrounding quotes and give the type expression directly.`,
@@ -234,23 +241,23 @@ func decodeVariableType(expr hcl.Expression) (cty.Type, VariableParsingMode, hcl
234241
// elements are consistent. This is the same as list(any) or map(any).
235242
switch hcl.ExprAsKeyword(expr) {
236243
case "list":
237-
return cty.List(cty.DynamicPseudoType), VariableParseHCL, nil
244+
return cty.List(cty.DynamicPseudoType), nil, VariableParseHCL, nil
238245
case "map":
239-
return cty.Map(cty.DynamicPseudoType), VariableParseHCL, nil
246+
return cty.Map(cty.DynamicPseudoType), nil, VariableParseHCL, nil
240247
}
241248

242-
ty, diags := typeexpr.TypeConstraint(expr)
249+
ty, typeDefaults, diags := typeexpr.TypeConstraintWithDefaults(expr)
243250
if diags.HasErrors() {
244-
return cty.DynamicPseudoType, VariableParseHCL, diags
251+
return cty.DynamicPseudoType, nil, VariableParseHCL, diags
245252
}
246253

247254
switch {
248255
case ty.IsPrimitiveType():
249256
// Primitive types use literal parsing.
250-
return ty, VariableParseLiteral, diags
257+
return ty, typeDefaults, VariableParseLiteral, diags
251258
default:
252259
// Everything else uses HCL parsing
253-
return ty, VariableParseHCL, diags
260+
return ty, typeDefaults, VariableParseHCL, diags
254261
}
255262
}
256263

internal/configs/testdata/warning-files/object-optional-attrs-experiment.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ terraform {
77
variable "a" {
88
type = object({
99
foo = optional(string)
10+
bar = optional(bool, true)
1011
})
1112
}
1213

0 commit comments

Comments
 (0)