lang/blocktoattr: Apply fixup within already-fixed-up blocks too

When a top-level list-of-object contains an attribute that is also
list-of-object we need to do the fixup again inside the nested body (using
our synthetic attributes-only schema) so that the attr-as-blocks mechanism
can apply within the nested blocks too.
This commit is contained in:
Martin Atkins 2019-04-05 10:33:53 -07:00
parent 0d0a1128e4
commit ffcf9fc51b
3 changed files with 86 additions and 2 deletions

View File

@ -152,7 +152,8 @@ func (e *fixupBlocksExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostic
vals := make([]cty.Value, len(e.blocks)) vals := make([]cty.Value, len(e.blocks))
var diags hcl.Diagnostics var diags hcl.Diagnostics
for i, block := range e.blocks { for i, block := range e.blocks {
val, blockDiags := hcldec.Decode(block.Body, spec, ctx) body := FixUpBlockAttrs(block.Body, schema)
val, blockDiags := hcldec.Decode(body, spec, ctx)
diags = append(diags, blockDiags...) diags = append(diags, blockDiags...)
if val == cty.NilVal { if val == cty.NilVal {
val = cty.UnknownVal(e.ety) val = cty.UnknownVal(e.ety)

View File

@ -216,7 +216,7 @@ foo {
}), }),
}), }),
}, },
"nested fixup": { "fixup inside block": {
src: ` src: `
container { container {
foo { foo {
@ -262,6 +262,56 @@ container {
}), }),
}), }),
}, },
"fixup inside attribute-as-block": {
src: `
container {
foo {
bar = "baz"
}
foo {
bar = "boop"
}
}
container {
foo {
bar = beep
}
}
`,
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"container": {
Type: cty.List(cty.Object(map[string]cty.Type{
"foo": cty.List(cty.Object(map[string]cty.Type{
"bar": cty.String,
})),
})),
Optional: true,
},
},
},
want: cty.ObjectVal(map[string]cty.Value{
"container": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"foo": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"bar": cty.StringVal("baz"),
}),
cty.ObjectVal(map[string]cty.Value{
"bar": cty.StringVal("boop"),
}),
}),
}),
cty.ObjectVal(map[string]cty.Value{
"foo": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"bar": cty.StringVal("beep value"),
}),
}),
}),
}),
}),
},
"nested fixup with dynamic block generation": { "nested fixup with dynamic block generation": {
src: ` src: `
container { container {

View File

@ -77,6 +77,39 @@ foo {
}, },
}, },
}, },
"block syntax with nested blocks": {
src: `
foo {
bar {
boop = baz
}
}
`,
schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"foo": {
Type: cty.List(cty.Object(map[string]cty.Type{
"bar": cty.List(cty.Object(map[string]cty.Type{
"boop": cty.String,
})),
})),
Optional: true,
},
},
},
want: []hcl.Traversal{
{
hcl.TraverseRoot{
Name: "baz",
SrcRange: hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{Line: 4, Column: 12, Byte: 26},
End: hcl.Pos{Line: 4, Column: 15, Byte: 29},
},
},
},
},
},
"dynamic block syntax": { "dynamic block syntax": {
src: ` src: `
dynamic "foo" { dynamic "foo" {