Skip to content

Commit

Permalink
Merge pull request #29624 from hashicorp/jbardin/no-block-to-attr
Browse files Browse the repository at this point in the history
skip FixUpBlockAttrs when we can detect types from a new SDK
  • Loading branch information
jbardin committed Sep 24, 2021
2 parents 50fac6a + 8706a18 commit c8cd0b1
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 0 deletions.
55 changes: 55 additions & 0 deletions internal/lang/blocktoattr/fixup.go
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -12,6 +14,10 @@ import (
// type in the schema to be written with HCL block syntax as multiple nested
// blocks with the attribute name as the block type.
//
// The fixup is only applied in the absence of structural attribute types. The
// presence of these types indicate the use of a provider which does not
// support mapping blocks to attributes.
//
// This partially restores some of the block/attribute confusion from HCL 1
// so that existing patterns that depended on that confusion can continue to
// be used in the short term while we settle on a longer-term strategy.
Expand All @@ -28,13 +34,62 @@ func FixUpBlockAttrs(body hcl.Body, schema *configschema.Block) hcl.Body {
schema = &configschema.Block{}
}

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
}

return &fixupBody{
original: body,
schema: schema,
names: ambiguousNames(schema),
}
}

// 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 {
if skipFixup(&block.Block) {
return true
}
}

return false
}

type fixupBody struct {
original hcl.Body
schema *configschema.Block
Expand Down
61 changes: 61 additions & 0 deletions internal/lang/blocktoattr/fixup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,67 @@ container {
}),
wantErrs: true,
},
"no fixup allowed with NestedType": {
src: `
container {
foo = "one"
}
`,
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"container": {
NestedType: &configschema.Object{
Nesting: configschema.NestingList,
Attributes: map[string]*configschema.Attribute{
"foo": {
Type: 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,
},
"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{
Expand Down

0 comments on commit c8cd0b1

Please sign in to comment.