Skip to content

Commit

Permalink
hcl2template: fix func to get vars from a config
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
lbajolet-hashicorp committed Oct 5, 2023
1 parent 1a3bc66 commit 0339c67
Showing 1 changed file with 39 additions and 13 deletions.
52 changes: 39 additions & 13 deletions hcl2template/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
}

0 comments on commit 0339c67

Please sign in to comment.