]>
Commit | Line | Data |
---|---|---|
bae9f6d2 JC |
1 | package terraform |
2 | ||
3 | import ( | |
4 | "github.com/hashicorp/terraform/dag" | |
5 | ) | |
6 | ||
7 | // NodeValidatableResource represents a resource that is used for validation | |
8 | // only. | |
9 | type NodeValidatableResource struct { | |
10 | *NodeAbstractCountResource | |
11 | } | |
12 | ||
13 | // GraphNodeEvalable | |
14 | func (n *NodeValidatableResource) EvalTree() EvalNode { | |
15 | // Ensure we're validating | |
16 | c := n.NodeAbstractCountResource | |
17 | c.Validate = true | |
18 | return c.EvalTree() | |
19 | } | |
20 | ||
21 | // GraphNodeDynamicExpandable | |
22 | func (n *NodeValidatableResource) DynamicExpand(ctx EvalContext) (*Graph, error) { | |
23 | // Grab the state which we read | |
24 | state, lock := ctx.State() | |
25 | lock.RLock() | |
26 | defer lock.RUnlock() | |
27 | ||
28 | // Expand the resource count which must be available by now from EvalTree | |
29 | count := 1 | |
30 | if n.Config.RawCount.Value() != unknownValue() { | |
31 | var err error | |
32 | count, err = n.Config.Count() | |
33 | if err != nil { | |
34 | return nil, err | |
35 | } | |
36 | } | |
37 | ||
38 | // The concrete resource factory we'll use | |
39 | concreteResource := func(a *NodeAbstractResource) dag.Vertex { | |
40 | // Add the config and state since we don't do that via transforms | |
41 | a.Config = n.Config | |
42 | ||
43 | return &NodeValidatableResourceInstance{ | |
44 | NodeAbstractResource: a, | |
45 | } | |
46 | } | |
47 | ||
48 | // Start creating the steps | |
49 | steps := []GraphTransformer{ | |
50 | // Expand the count. | |
51 | &ResourceCountTransformer{ | |
52 | Concrete: concreteResource, | |
53 | Count: count, | |
54 | Addr: n.ResourceAddr(), | |
55 | }, | |
56 | ||
57 | // Attach the state | |
58 | &AttachStateTransformer{State: state}, | |
59 | ||
60 | // Targeting | |
61 | &TargetsTransformer{ParsedTargets: n.Targets}, | |
62 | ||
63 | // Connect references so ordering is correct | |
64 | &ReferenceTransformer{}, | |
65 | ||
66 | // Make sure there is a single root | |
67 | &RootTransformer{}, | |
68 | } | |
69 | ||
70 | // Build the graph | |
71 | b := &BasicGraphBuilder{ | |
72 | Steps: steps, | |
73 | Validate: true, | |
74 | Name: "NodeValidatableResource", | |
75 | } | |
76 | ||
77 | return b.Build(ctx.Path()) | |
78 | } | |
79 | ||
80 | // This represents a _single_ resource instance to validate. | |
81 | type NodeValidatableResourceInstance struct { | |
82 | *NodeAbstractResource | |
83 | } | |
84 | ||
85 | // GraphNodeEvalable | |
86 | func (n *NodeValidatableResourceInstance) EvalTree() EvalNode { | |
87 | addr := n.NodeAbstractResource.Addr | |
88 | ||
89 | // Build the resource for eval | |
90 | resource := &Resource{ | |
91 | Name: addr.Name, | |
92 | Type: addr.Type, | |
93 | CountIndex: addr.Index, | |
94 | } | |
95 | if resource.CountIndex < 0 { | |
96 | resource.CountIndex = 0 | |
97 | } | |
98 | ||
99 | // Declare a bunch of variables that are used for state during | |
100 | // evaluation. Most of this are written to by-address below. | |
101 | var config *ResourceConfig | |
102 | var provider ResourceProvider | |
103 | ||
104 | seq := &EvalSequence{ | |
105 | Nodes: []EvalNode{ | |
106 | &EvalValidateResourceSelfRef{ | |
107 | Addr: &addr, | |
108 | Config: &n.Config.RawConfig, | |
109 | }, | |
110 | &EvalGetProvider{ | |
111 | Name: n.ProvidedBy()[0], | |
112 | Output: &provider, | |
113 | }, | |
114 | &EvalInterpolate{ | |
115 | Config: n.Config.RawConfig.Copy(), | |
116 | Resource: resource, | |
117 | Output: &config, | |
118 | }, | |
119 | &EvalValidateResource{ | |
120 | Provider: &provider, | |
121 | Config: &config, | |
122 | ResourceName: n.Config.Name, | |
123 | ResourceType: n.Config.Type, | |
124 | ResourceMode: n.Config.Mode, | |
125 | }, | |
126 | }, | |
127 | } | |
128 | ||
129 | // Validate all the provisioners | |
130 | for _, p := range n.Config.Provisioners { | |
131 | var provisioner ResourceProvisioner | |
132 | var connConfig *ResourceConfig | |
133 | seq.Nodes = append( | |
134 | seq.Nodes, | |
135 | &EvalGetProvisioner{ | |
136 | Name: p.Type, | |
137 | Output: &provisioner, | |
138 | }, | |
139 | &EvalInterpolate{ | |
140 | Config: p.RawConfig.Copy(), | |
141 | Resource: resource, | |
142 | Output: &config, | |
143 | }, | |
144 | &EvalInterpolate{ | |
145 | Config: p.ConnInfo.Copy(), | |
146 | Resource: resource, | |
147 | Output: &connConfig, | |
148 | }, | |
149 | &EvalValidateProvisioner{ | |
150 | Provisioner: &provisioner, | |
151 | Config: &config, | |
152 | ConnConfig: &connConfig, | |
153 | }, | |
154 | ) | |
155 | } | |
156 | ||
157 | return seq | |
158 | } |