From 9c3ec443798a6eddc14c4e98aaf9c2fefd3c937b Mon Sep 17 00:00:00 2001 From: Lucas Bajolet Date: Fri, 30 Aug 2024 14:02:30 -0400 Subject: [PATCH] hcl2template: use refString for local/data deps When registering dependencies for datasources and locals, we now use refString. This allows for the functions that detect dependencies to not only be able to register the same types as dependencies, but instead generalises it to any type that refString supports, so data, local and var. This can then be leveraged for orchestrating evaluation of those components in a non-phased way (i.e. with a DAG for dependency management). --- hcl2template/types.datasource.go | 1 + hcl2template/types.packer_config.go | 28 ++++++++++++++++++++-------- hcl2template/types.variables.go | 2 +- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/hcl2template/types.datasource.go b/hcl2template/types.datasource.go index 51719204c..d35294187 100644 --- a/hcl2template/types.datasource.go +++ b/hcl2template/types.datasource.go @@ -17,6 +17,7 @@ import ( type DatasourceBlock struct { Type string DSName string + Dependencies []refString value cty.Value block *hcl.Block diff --git a/hcl2template/types.packer_config.go b/hcl2template/types.packer_config.go index 70fade66f..ae27d4ecc 100644 --- a/hcl2template/types.packer_config.go +++ b/hcl2template/types.packer_config.go @@ -245,25 +245,27 @@ func (c *PackerConfig) evaluateLocalVariables(locals []*LocalBlock) hcl.Diagnost // attributes, as HCL2 expressions are not allowed in a block's labels. vars := FilterTraversalsByType(local.Expr.Variables(), "local") - var localDeps []*LocalBlock + var localDeps []refString for _, v := range vars { // Some local variables may be locally aliased as // `local`, which if len(v) < 2 { continue } - varName := v[1].(hcl.TraverseAttr).Name - block, err := c.localByName(varName) + + depRef, err := NewRefStringFromDep(v) if err != nil { diags = diags.Append(&hcl.Diagnostic{ Severity: hcl.DiagError, - Summary: "Missing variable dependency", - Detail: fmt.Sprintf("The expression for variable %q depends on local.%s, which is not defined.", - local.Name, varName), + Summary: "failed to extract dependency name from traversal ref", + Detail: fmt.Sprintf("while preparing for evaluation of local variable %q, "+ + "a dependency was unable to be converted to a refString. "+ + "This is likely a Packer bug, please consider reporting it.", local.Name), }) continue } - localDeps = append(localDeps, block) + + localDeps = append(localDeps, depRef) } local.dependencies = localDeps } @@ -325,7 +327,17 @@ func (c *PackerConfig) recursivelyEvaluateLocalVariable(local *LocalBlock, depth var diags hcl.Diagnostics for _, dep := range local.dependencies { - localDiags := c.recursivelyEvaluateLocalVariable(dep, depth+1) + locBlock, err := c.getComponentByRef(dep) + if err != nil { + return diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "failed to get local variable", + Detail: fmt.Sprintf("While evaluating %q, its dependency %q was not found, is it defined?", + local.Name, dep.String()), + }) + } + + localDiags := c.recursivelyEvaluateLocalVariable(locBlock.(*LocalBlock), depth+1) diags = diags.Extend(localDiags) } diff --git a/hcl2template/types.variables.go b/hcl2template/types.variables.go index 3e7f9e1cb..b9fb0776b 100644 --- a/hcl2template/types.variables.go +++ b/hcl2template/types.variables.go @@ -35,7 +35,7 @@ type LocalBlock struct { // // Only `local`/`locals` will be referenced here as we execute all the // same component types at once. - dependencies []*LocalBlock + dependencies []refString // evaluated toggles to true if it has been evaluated. // // We use this to determine if we're ready to get the value of the