]>
Commit | Line | Data |
---|---|---|
bae9f6d2 JC |
1 | package terraform |
2 | ||
3 | import ( | |
4 | "fmt" | |
5 | ||
107c1cdb ND |
6 | "github.com/hashicorp/hcl2/hcl" |
7 | ||
8 | "github.com/hashicorp/terraform/addrs" | |
9 | "github.com/hashicorp/terraform/configs/configschema" | |
10 | "github.com/hashicorp/terraform/lang" | |
11 | "github.com/hashicorp/terraform/tfdiags" | |
bae9f6d2 JC |
12 | ) |
13 | ||
107c1cdb ND |
14 | // EvalValidateSelfRef is an EvalNode implementation that checks to ensure that |
15 | // expressions within a particular referencable block do not reference that | |
16 | // same block. | |
17 | type EvalValidateSelfRef struct { | |
18 | Addr addrs.Referenceable | |
19 | Config hcl.Body | |
20 | ProviderSchema **ProviderSchema | |
bae9f6d2 JC |
21 | } |
22 | ||
107c1cdb ND |
23 | func (n *EvalValidateSelfRef) Eval(ctx EvalContext) (interface{}, error) { |
24 | var diags tfdiags.Diagnostics | |
25 | addr := n.Addr | |
bae9f6d2 | 26 | |
107c1cdb ND |
27 | addrStrs := make([]string, 0, 1) |
28 | addrStrs = append(addrStrs, addr.String()) | |
29 | switch tAddr := addr.(type) { | |
30 | case addrs.ResourceInstance: | |
31 | // A resource instance may not refer to its containing resource either. | |
32 | addrStrs = append(addrStrs, tAddr.ContainingResource().String()) | |
33 | } | |
bae9f6d2 | 34 | |
107c1cdb ND |
35 | if n.ProviderSchema == nil || *n.ProviderSchema == nil { |
36 | return nil, fmt.Errorf("provider schema unavailable while validating %s for self-references; this is a bug in Terraform and should be reported", addr) | |
37 | } | |
bae9f6d2 | 38 | |
107c1cdb ND |
39 | providerSchema := *n.ProviderSchema |
40 | var schema *configschema.Block | |
41 | switch tAddr := addr.(type) { | |
42 | case addrs.Resource: | |
43 | schema, _ = providerSchema.SchemaForResourceAddr(tAddr) | |
44 | case addrs.ResourceInstance: | |
45 | schema, _ = providerSchema.SchemaForResourceAddr(tAddr.ContainingResource()) | |
bae9f6d2 JC |
46 | } |
47 | ||
107c1cdb ND |
48 | if schema == nil { |
49 | 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) | |
bae9f6d2 JC |
50 | } |
51 | ||
107c1cdb ND |
52 | refs, _ := lang.ReferencesInBlock(n.Config, schema) |
53 | for _, ref := range refs { | |
54 | for _, addrStr := range addrStrs { | |
55 | if ref.Subject.String() == addrStr { | |
56 | diags = diags.Append(&hcl.Diagnostic{ | |
57 | Severity: hcl.DiagError, | |
58 | Summary: "Self-referential block", | |
59 | Detail: fmt.Sprintf("Configuration for %s may not refer to itself.", addrStr), | |
60 | Subject: ref.SourceRange.ToHCL().Ptr(), | |
61 | }) | |
62 | } | |
63 | } | |
bae9f6d2 | 64 | } |
107c1cdb ND |
65 | |
66 | return nil, diags.NonFatalErr() | |
bae9f6d2 | 67 | } |