hcl2template: fix func to get vars from a config

The previous implementation of the GetVarsByType function worked only on
top-level attributes, ignoring the nested blocks in the structure.

This implies that if a datasource depends on another through an
expression within a nested block, we may not execute it first, and then
executing this datasource before its dependent is possible, resulting in
an error in the end.

This commit is an attempt at making this more reliable for HCL configs,
but only works on configs lifted from HCL files for now. We need to make
this more reliable for later iterations.
pull/12648/head
Lucas Bajolet 3 years ago
parent 1a3bc66708
commit 0339c670a7

@ -11,6 +11,7 @@ import (
"github.com/gobwas/glob"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/hashicorp/packer/hcl2template/repl"
hcl2shim "github.com/hashicorp/packer/hcl2template/shim"
"github.com/zclconf/go-cty/cty"
@ -187,22 +188,47 @@ func ConvertPluginConfigValueToHCLValue(v interface{}) (cty.Value, error) {
return buildValue, nil
}
// GetVarsByType walks through a hcl body, and gathers all the Traversals that
// have a root type matching one of the specified top-level labels.
//
// This will only work on finite, expanded, HCL bodies.
func GetVarsByType(block *hcl.Block, topLevelLabels ...string) []hcl.Traversal {
attributes, _ := block.Body.JustAttributes()
var vars []hcl.Traversal
for _, attr := range attributes {
for _, variable := range attr.Expr.Variables() {
rootLabel := variable.RootName()
for _, label := range topLevelLabels {
if label == rootLabel {
vars = append(vars, variable)
break
}
var travs []hcl.Traversal
switch body := block.Body.(type) {
case *hclsyntax.Body:
travs = getVarsByTypeForHCLSyntaxBody(body)
default:
attrs, _ := body.JustAttributes()
for _, attr := range attrs {
travs = append(travs, attr.Expr.Variables()...)
}
}
var rets []hcl.Traversal
for _, t := range travs {
varRootname := t.RootName()
for _, lbl := range topLevelLabels {
if varRootname == lbl {
rets = append(rets, t)
break
}
}
}
return vars
return rets
}
func getVarsByTypeForHCLSyntaxBody(body *hclsyntax.Body) []hcl.Traversal {
var rets []hcl.Traversal
for _, attr := range body.Attributes {
rets = append(rets, attr.Expr.Variables()...)
}
for _, block := range body.Blocks {
rets = append(rets, getVarsByTypeForHCLSyntaxBody(block.Body)...)
}
return rets
}

Loading…
Cancel
Save