| package terraform |
| |
| import ( |
| "fmt" |
| |
| "github.com/hashicorp/hcl/v2" |
| |
| "github.com/hashicorp/terraform/internal/addrs" |
| "github.com/hashicorp/terraform/internal/configs/configschema" |
| "github.com/hashicorp/terraform/internal/lang" |
| "github.com/hashicorp/terraform/internal/tfdiags" |
| ) |
| |
| // validateSelfRef checks to ensure that expressions within a particular |
| // referencable block do not reference that same block. |
| func validateSelfRef(addr addrs.Referenceable, config hcl.Body, providerSchema *ProviderSchema) tfdiags.Diagnostics { |
| var diags tfdiags.Diagnostics |
| |
| 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 providerSchema == nil { |
| diags = diags.Append(fmt.Errorf("provider schema unavailable while validating %s for self-references; this is a bug in Terraform and should be reported", addr)) |
| return diags |
| } |
| |
| 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 { |
| diags = diags.Append(fmt.Errorf("no schema available for %s to validate for self-references; this is a bug in Terraform and should be reported", addr)) |
| return diags |
| } |
| |
| refs, _ := lang.ReferencesInBlock(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 diags |
| } |