mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-30 10:47:14 -06:00
50a101afbd
The hcldec package has no awareness of the dynamic block extension, so the hcldec.Variables function misses any variables declared inside dynamic blocks. dynblock.VariablesHCLDec is a drop-in replacement for hcldec.Variables that _is_ aware of dynamic blocks, returning all of the same variables that hcldec would find naturally plus also any variables used inside the dynamic block "for_each" and "labels" arguments and inside the nested "content" block.
75 lines
2.6 KiB
Go
75 lines
2.6 KiB
Go
package lang
|
|
|
|
import (
|
|
"github.com/hashicorp/hcl2/ext/dynblock"
|
|
"github.com/hashicorp/hcl2/hcl"
|
|
"github.com/hashicorp/terraform/addrs"
|
|
"github.com/hashicorp/terraform/configs/configschema"
|
|
"github.com/hashicorp/terraform/tfdiags"
|
|
)
|
|
|
|
// References finds all of the references in the given set of traversals,
|
|
// returning diagnostics if any of the traversals cannot be interpreted as a
|
|
// reference.
|
|
//
|
|
// This function does not do any de-duplication of references, since references
|
|
// have source location information embedded in them and so any invalid
|
|
// references that are duplicated should have errors reported for each
|
|
// occurence.
|
|
//
|
|
// If the returned diagnostics contains errors then the result may be
|
|
// incomplete or invalid. Otherwise, the returned slice has one reference per
|
|
// given traversal, though it is not guaranteed that the references will
|
|
// appear in the same order as the given traversals.
|
|
func References(traversals []hcl.Traversal) ([]*addrs.Reference, tfdiags.Diagnostics) {
|
|
if len(traversals) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
var diags tfdiags.Diagnostics
|
|
refs := make([]*addrs.Reference, 0, len(traversals))
|
|
|
|
for _, traversal := range traversals {
|
|
ref, refDiags := addrs.ParseRef(traversal)
|
|
diags = diags.Append(refDiags)
|
|
if ref == nil {
|
|
continue
|
|
}
|
|
refs = append(refs, ref)
|
|
}
|
|
|
|
return refs, diags
|
|
}
|
|
|
|
// ReferencesInBlock is a helper wrapper around References that first searches
|
|
// the given body for traversals, before converting those traversals to
|
|
// references.
|
|
//
|
|
// A block schema must be provided so that this function can determine where in
|
|
// the body variables are expected.
|
|
func ReferencesInBlock(body hcl.Body, schema *configschema.Block) ([]*addrs.Reference, tfdiags.Diagnostics) {
|
|
if body == nil {
|
|
return nil, nil
|
|
}
|
|
spec := schema.DecoderSpec()
|
|
|
|
// We use dynblock.VariablesHCLDec instead of hcldec.Variables here because
|
|
// when we evaluate a block we'll apply the HCL dynamic block extension
|
|
// expansion to it first, and so we need this specialized version in order
|
|
// to properly understand what the dependencies will be once expanded.
|
|
// Otherwise, we'd miss references that only occur inside dynamic blocks.
|
|
traversals := dynblock.VariablesHCLDec(body, spec)
|
|
return References(traversals)
|
|
}
|
|
|
|
// ReferencesInExpr is a helper wrapper around References that first searches
|
|
// the given expression for traversals, before converting those traversals
|
|
// to references.
|
|
func ReferencesInExpr(expr hcl.Expression) ([]*addrs.Reference, tfdiags.Diagnostics) {
|
|
if expr == nil {
|
|
return nil, nil
|
|
}
|
|
traversals := expr.Variables()
|
|
return References(traversals)
|
|
}
|