From 8706a18c4b69850cee1736f3af26869317313f3b Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 22 Sep 2021 15:59:25 -0400 Subject: [PATCH] refine the skipFixup heuristic We can also rule out some attribute types as indicating something other than the legacy SDK. - Tuple types were not generated at all. - There were no single objects types, the convention was to use a block list or set of length 1. - Maps of objects were not possible to generate, since named blocks were not implemented. - Nested collections were not supported, but when they were generated they would have primitive types. --- internal/lang/blocktoattr/fixup.go | 34 ++++++++++++++++++++++--- internal/lang/blocktoattr/fixup_test.go | 34 ++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/internal/lang/blocktoattr/fixup.go b/internal/lang/blocktoattr/fixup.go index 90eb260d7..5d05a86f2 100644 --- a/internal/lang/blocktoattr/fixup.go +++ b/internal/lang/blocktoattr/fixup.go @@ -1,6 +1,8 @@ package blocktoattr import ( + "log" + "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hcldec" "github.com/hashicorp/terraform/internal/configs/configschema" @@ -33,6 +35,10 @@ func FixUpBlockAttrs(body hcl.Body, schema *configschema.Block) hcl.Body { } if skipFixup(schema) { + // we don't have any context for the resource name or type, but + // hopefully this could help locate the evaluation in the logs if there + // were a problem + log.Println("[DEBUG] skipping FixUpBlockAttrs") return body } @@ -43,14 +49,36 @@ func FixUpBlockAttrs(body hcl.Body, schema *configschema.Block) hcl.Body { } } -// skipFixup detects any use of Attribute.NestedType. Because the fixup was -// only supported for the legacy SDK, there is no situation where structural -// attributes are used where the fixup is expected. +// skipFixup detects any use of Attribute.NestedType, or Types which could not +// be generate by the legacy SDK when taking SchemaConfigModeAttr into account. func skipFixup(schema *configschema.Block) bool { for _, attr := range schema.Attributes { if attr.NestedType != nil { return true } + ty := attr.Type + + // Lists and sets of objects could be generated by + // SchemaConfigModeAttr, but some other combinations can be ruled out. + + // Tuples and objects could not be generated at all. + if ty.IsTupleType() || ty.IsObjectType() { + return true + } + + // A map of objects was not possible. + if ty.IsMapType() && ty.ElementType().IsObjectType() { + return true + } + + // Nested collections were not really supported, but could be generated + // with string types (though we conservatively limit this to primitive types) + if ty.IsCollectionType() { + ety := ty.ElementType() + if ety.IsCollectionType() && !ety.ElementType().IsPrimitiveType() { + return true + } + } } for _, block := range schema.BlockTypes { diff --git a/internal/lang/blocktoattr/fixup_test.go b/internal/lang/blocktoattr/fixup_test.go index 92799394f..36ab48041 100644 --- a/internal/lang/blocktoattr/fixup_test.go +++ b/internal/lang/blocktoattr/fixup_test.go @@ -400,7 +400,7 @@ container { }), wantErrs: true, }, - "no fixup allowed": { + "no fixup allowed with NestedType": { src: ` container { foo = "one" @@ -429,6 +429,38 @@ container { }), wantErrs: true, }, + "no fixup allowed new types": { + src: ` + container { + foo = "one" + } + `, + schema: &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + // This could be a ConfigModeAttr fixup + "container": { + Type: cty.List(cty.Object(map[string]cty.Type{ + "foo": cty.String, + })), + }, + // But the presence of this type means it must have been + // declared by a new SDK + "new_type": { + Type: cty.Object(map[string]cty.Type{ + "boo": cty.String, + }), + }, + }, + }, + want: cty.ObjectVal(map[string]cty.Value{ + "container": cty.NullVal(cty.List( + cty.Object(map[string]cty.Type{ + "foo": cty.String, + }), + )), + }), + wantErrs: true, + }, } ctx := &hcl.EvalContext{