mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-31 11:17:25 -06:00
168d84b3c4
Previously we were fetching these from the provider but then immediately discarding the version numbers because the schema API had nowhere to put them. To avoid a late-breaking change to the internal structure of terraform.ProviderSchema (which is constructed directly all over the tests) we're retaining the resource type schemas in a new map alongside the existing one with the same keys, rather than just switching to using the providers.Schema struct directly there. The methods that return resource type schemas now return two arguments, intentionally creating a little API friction here so each new caller can be reminded to think about whether they need to do something with the schema version, though it can be ignored by many callers. Since this was a breaking change to the Schemas API anyway, this also fixes another API wart where there was a separate method for fetching managed vs. data resource types and thus every caller ended up having a switch statement on "mode". Now we just accept mode as an argument and do the switch statement within the single SchemaForResourceType method.
68 lines
2.0 KiB
Go
68 lines
2.0 KiB
Go
package terraform
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/hcl2/hcl"
|
|
|
|
"github.com/hashicorp/terraform/addrs"
|
|
"github.com/hashicorp/terraform/configs/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:
|
|
schema, _ = providerSchema.SchemaForResourceAddr(tAddr)
|
|
case addrs.ResourceInstance:
|
|
schema, _ = providerSchema.SchemaForResourceAddr(tAddr.ContainingResource())
|
|
}
|
|
|
|
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()
|
|
}
|