mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-30 10:47:14 -06:00
b031e18332
EvalValidateSelfRef needs schema in order to extract references. It was previously expecting a *configschema.Block directly, but we weren't actually passing that in from anywhere except the tests because it's not available directly in that form during the evaltree for node_resource_validate. Instead, we now pass in the whole *ProviderSchema for the associated provider and have this EvalNode find the schema itself based on the address. This breaks some of the generality of this node (now only really works for resource addresses) but that's okay since we have no other use-case right now anyway.
78 lines
2.3 KiB
Go
78 lines
2.3 KiB
Go
package terraform
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/hcl2/hcl"
|
|
|
|
"github.com/hashicorp/terraform/addrs"
|
|
"github.com/hashicorp/terraform/config/configschema"
|
|
"github.com/hashicorp/terraform/lang"
|
|
"github.com/hashicorp/terraform/tfdiags"
|
|
)
|
|
|
|
// EvalValidateSelfRef is an EvalNode implementation that checks to ensure that
|
|
// expressions within a particular referencable block do not reference that
|
|
// same block.
|
|
type EvalValidateSelfRef struct {
|
|
Addr addrs.Referenceable
|
|
Config hcl.Body
|
|
ProviderSchema **ProviderSchema
|
|
}
|
|
|
|
func (n *EvalValidateSelfRef) Eval(ctx EvalContext) (interface{}, error) {
|
|
var diags tfdiags.Diagnostics
|
|
addr := n.Addr
|
|
|
|
addrStrs := make([]string, 0, 1)
|
|
addrStrs = append(addrStrs, addr.String())
|
|
switch tAddr := addr.(type) {
|
|
case addrs.ResourceInstance:
|
|
// A resource instance may not refer to its containing resource either.
|
|
addrStrs = append(addrStrs, tAddr.ContainingResource().String())
|
|
}
|
|
|
|
if n.ProviderSchema == nil || *n.ProviderSchema == nil {
|
|
return nil, fmt.Errorf("provider schema unavailable while validating %s for self-references; this is a bug in Terraform and should be reported", addr)
|
|
}
|
|
|
|
providerSchema := *n.ProviderSchema
|
|
var schema *configschema.Block
|
|
switch tAddr := addr.(type) {
|
|
case addrs.Resource:
|
|
switch tAddr.Mode {
|
|
case addrs.ManagedResourceMode:
|
|
schema = providerSchema.ResourceTypes[tAddr.Type]
|
|
case addrs.DataResourceMode:
|
|
schema = providerSchema.DataSources[tAddr.Type]
|
|
}
|
|
case addrs.ResourceInstance:
|
|
switch tAddr.Resource.Mode {
|
|
case addrs.ManagedResourceMode:
|
|
schema = providerSchema.ResourceTypes[tAddr.Resource.Type]
|
|
case addrs.DataResourceMode:
|
|
schema = providerSchema.DataSources[tAddr.Resource.Type]
|
|
}
|
|
}
|
|
|
|
if schema == nil {
|
|
return nil, fmt.Errorf("no schema available for %s to validate for self-references; this is a bug in Terraform and should be reported", addr)
|
|
}
|
|
|
|
refs, _ := lang.ReferencesInBlock(n.Config, schema)
|
|
for _, ref := range refs {
|
|
for _, addrStr := range addrStrs {
|
|
if ref.Subject.String() == addrStr {
|
|
diags = diags.Append(&hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Self-referential block",
|
|
Detail: fmt.Sprintf("Configuration for %s may not refer to itself.", addrStr),
|
|
Subject: ref.SourceRange.ToHCL().Ptr(),
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil, diags.NonFatalErr()
|
|
}
|