]>
Commit | Line | Data |
---|---|---|
bae9f6d2 JC |
1 | package terraform |
2 | ||
3 | import ( | |
4 | "fmt" | |
5 | ||
6 | "github.com/hashicorp/terraform/config" | |
7 | ) | |
8 | ||
9 | // EvalValidateResourceSelfRef is an EvalNode implementation that validates that | |
10 | // a configuration doesn't contain a reference to the resource itself. | |
11 | // | |
12 | // This must be done prior to interpolating configuration in order to avoid | |
13 | // any infinite loop scenarios. | |
14 | type EvalValidateResourceSelfRef struct { | |
15 | Addr **ResourceAddress | |
16 | Config **config.RawConfig | |
17 | } | |
18 | ||
19 | func (n *EvalValidateResourceSelfRef) Eval(ctx EvalContext) (interface{}, error) { | |
20 | addr := *n.Addr | |
21 | conf := *n.Config | |
22 | ||
23 | // Go through the variables and find self references | |
24 | var errs []error | |
25 | for k, raw := range conf.Variables { | |
26 | rv, ok := raw.(*config.ResourceVariable) | |
27 | if !ok { | |
28 | continue | |
29 | } | |
30 | ||
31 | // Build an address from the variable | |
32 | varAddr := &ResourceAddress{ | |
33 | Path: addr.Path, | |
34 | Mode: rv.Mode, | |
35 | Type: rv.Type, | |
36 | Name: rv.Name, | |
37 | Index: rv.Index, | |
38 | InstanceType: TypePrimary, | |
39 | } | |
40 | ||
41 | // If the variable access is a multi-access (*), then we just | |
42 | // match the index so that we'll match our own addr if everything | |
43 | // else matches. | |
44 | if rv.Multi && rv.Index == -1 { | |
45 | varAddr.Index = addr.Index | |
46 | } | |
47 | ||
48 | // This is a weird thing where ResourceAddres has index "-1" when | |
49 | // index isn't set at all. This means index "0" for resource access. | |
50 | // So, if we have this scenario, just set our varAddr to -1 so it | |
51 | // matches. | |
52 | if addr.Index == -1 && varAddr.Index == 0 { | |
53 | varAddr.Index = -1 | |
54 | } | |
55 | ||
56 | // If the addresses match, then this is a self reference | |
57 | if varAddr.Equals(addr) && varAddr.Index == addr.Index { | |
58 | errs = append(errs, fmt.Errorf( | |
59 | "%s: self reference not allowed: %q", | |
60 | addr, k)) | |
61 | } | |
62 | } | |
63 | ||
64 | // If no errors, no errors! | |
65 | if len(errs) == 0 { | |
66 | return nil, nil | |
67 | } | |
68 | ||
69 | // Wrap the errors in the proper wrapper so we can handle validation | |
70 | // formatting properly upstream. | |
71 | return nil, &EvalValidateError{ | |
72 | Errors: errs, | |
73 | } | |
74 | } |