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.
This commit is contained in:
Lucas Bajolet
2023-10-03 14:19:28 -04:00
parent 5bae773a28
commit febaada14e
+37 -11
View File
@@ -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 travs []hcl.Traversal
var vars []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()...)
}
}
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 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
}