diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/terraform/node_resource_abstract.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/terraform/node_resource_abstract.go | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/terraform/node_resource_abstract.go b/vendor/github.com/hashicorp/terraform/terraform/node_resource_abstract.go new file mode 100644 index 0000000..50bb707 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/terraform/node_resource_abstract.go | |||
@@ -0,0 +1,240 @@ | |||
1 | package terraform | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "strings" | ||
6 | |||
7 | "github.com/hashicorp/terraform/config" | ||
8 | "github.com/hashicorp/terraform/dag" | ||
9 | ) | ||
10 | |||
11 | // ConcreteResourceNodeFunc is a callback type used to convert an | ||
12 | // abstract resource to a concrete one of some type. | ||
13 | type ConcreteResourceNodeFunc func(*NodeAbstractResource) dag.Vertex | ||
14 | |||
15 | // GraphNodeResource is implemented by any nodes that represent a resource. | ||
16 | // The type of operation cannot be assumed, only that this node represents | ||
17 | // the given resource. | ||
18 | type GraphNodeResource interface { | ||
19 | ResourceAddr() *ResourceAddress | ||
20 | } | ||
21 | |||
22 | // NodeAbstractResource represents a resource that has no associated | ||
23 | // operations. It registers all the interfaces for a resource that common | ||
24 | // across multiple operation types. | ||
25 | type NodeAbstractResource struct { | ||
26 | Addr *ResourceAddress // Addr is the address for this resource | ||
27 | |||
28 | // The fields below will be automatically set using the Attach | ||
29 | // interfaces if you're running those transforms, but also be explicitly | ||
30 | // set if you already have that information. | ||
31 | |||
32 | Config *config.Resource // Config is the resource in the config | ||
33 | ResourceState *ResourceState // ResourceState is the ResourceState for this | ||
34 | |||
35 | Targets []ResourceAddress // Set from GraphNodeTargetable | ||
36 | } | ||
37 | |||
38 | func (n *NodeAbstractResource) Name() string { | ||
39 | return n.Addr.String() | ||
40 | } | ||
41 | |||
42 | // GraphNodeSubPath | ||
43 | func (n *NodeAbstractResource) Path() []string { | ||
44 | return n.Addr.Path | ||
45 | } | ||
46 | |||
47 | // GraphNodeReferenceable | ||
48 | func (n *NodeAbstractResource) ReferenceableName() []string { | ||
49 | // We always are referenceable as "type.name" as long as | ||
50 | // we have a config or address. Determine what that value is. | ||
51 | var id string | ||
52 | if n.Config != nil { | ||
53 | id = n.Config.Id() | ||
54 | } else if n.Addr != nil { | ||
55 | addrCopy := n.Addr.Copy() | ||
56 | addrCopy.Path = nil // ReferenceTransformer handles paths | ||
57 | addrCopy.Index = -1 // We handle indexes below | ||
58 | id = addrCopy.String() | ||
59 | } else { | ||
60 | // No way to determine our type.name, just return | ||
61 | return nil | ||
62 | } | ||
63 | |||
64 | var result []string | ||
65 | |||
66 | // Always include our own ID. This is primarily for backwards | ||
67 | // compatibility with states that didn't yet support the more | ||
68 | // specific dep string. | ||
69 | result = append(result, id) | ||
70 | |||
71 | // We represent all multi-access | ||
72 | result = append(result, fmt.Sprintf("%s.*", id)) | ||
73 | |||
74 | // We represent either a specific number, or all numbers | ||
75 | suffix := "N" | ||
76 | if n.Addr != nil { | ||
77 | idx := n.Addr.Index | ||
78 | if idx == -1 { | ||
79 | idx = 0 | ||
80 | } | ||
81 | |||
82 | suffix = fmt.Sprintf("%d", idx) | ||
83 | } | ||
84 | result = append(result, fmt.Sprintf("%s.%s", id, suffix)) | ||
85 | |||
86 | return result | ||
87 | } | ||
88 | |||
89 | // GraphNodeReferencer | ||
90 | func (n *NodeAbstractResource) References() []string { | ||
91 | // If we have a config, that is our source of truth | ||
92 | if c := n.Config; c != nil { | ||
93 | // Grab all the references | ||
94 | var result []string | ||
95 | result = append(result, c.DependsOn...) | ||
96 | result = append(result, ReferencesFromConfig(c.RawCount)...) | ||
97 | result = append(result, ReferencesFromConfig(c.RawConfig)...) | ||
98 | for _, p := range c.Provisioners { | ||
99 | if p.When == config.ProvisionerWhenCreate { | ||
100 | result = append(result, ReferencesFromConfig(p.ConnInfo)...) | ||
101 | result = append(result, ReferencesFromConfig(p.RawConfig)...) | ||
102 | } | ||
103 | } | ||
104 | |||
105 | return uniqueStrings(result) | ||
106 | } | ||
107 | |||
108 | // If we have state, that is our next source | ||
109 | if s := n.ResourceState; s != nil { | ||
110 | return s.Dependencies | ||
111 | } | ||
112 | |||
113 | return nil | ||
114 | } | ||
115 | |||
116 | // StateReferences returns the dependencies to put into the state for | ||
117 | // this resource. | ||
118 | func (n *NodeAbstractResource) StateReferences() []string { | ||
119 | self := n.ReferenceableName() | ||
120 | |||
121 | // Determine what our "prefix" is for checking for references to | ||
122 | // ourself. | ||
123 | addrCopy := n.Addr.Copy() | ||
124 | addrCopy.Index = -1 | ||
125 | selfPrefix := addrCopy.String() + "." | ||
126 | |||
127 | depsRaw := n.References() | ||
128 | deps := make([]string, 0, len(depsRaw)) | ||
129 | for _, d := range depsRaw { | ||
130 | // Ignore any variable dependencies | ||
131 | if strings.HasPrefix(d, "var.") { | ||
132 | continue | ||
133 | } | ||
134 | |||
135 | // If this has a backup ref, ignore those for now. The old state | ||
136 | // file never contained those and I'd rather store the rich types we | ||
137 | // add in the future. | ||
138 | if idx := strings.IndexRune(d, '/'); idx != -1 { | ||
139 | d = d[:idx] | ||
140 | } | ||
141 | |||
142 | // If we're referencing ourself, then ignore it | ||
143 | found := false | ||
144 | for _, s := range self { | ||
145 | if d == s { | ||
146 | found = true | ||
147 | } | ||
148 | } | ||
149 | if found { | ||
150 | continue | ||
151 | } | ||
152 | |||
153 | // If this is a reference to ourself and a specific index, we keep | ||
154 | // it. For example, if this resource is "foo.bar" and the reference | ||
155 | // is "foo.bar.0" then we keep it exact. Otherwise, we strip it. | ||
156 | if strings.HasSuffix(d, ".0") && !strings.HasPrefix(d, selfPrefix) { | ||
157 | d = d[:len(d)-2] | ||
158 | } | ||
159 | |||
160 | // This is sad. The dependencies are currently in the format of | ||
161 | // "module.foo.bar" (the full field). This strips the field off. | ||
162 | if strings.HasPrefix(d, "module.") { | ||
163 | parts := strings.SplitN(d, ".", 3) | ||
164 | d = strings.Join(parts[0:2], ".") | ||
165 | } | ||
166 | |||
167 | deps = append(deps, d) | ||
168 | } | ||
169 | |||
170 | return deps | ||
171 | } | ||
172 | |||
173 | // GraphNodeProviderConsumer | ||
174 | func (n *NodeAbstractResource) ProvidedBy() []string { | ||
175 | // If we have a config we prefer that above all else | ||
176 | if n.Config != nil { | ||
177 | return []string{resourceProvider(n.Config.Type, n.Config.Provider)} | ||
178 | } | ||
179 | |||
180 | // If we have state, then we will use the provider from there | ||
181 | if n.ResourceState != nil && n.ResourceState.Provider != "" { | ||
182 | return []string{n.ResourceState.Provider} | ||
183 | } | ||
184 | |||
185 | // Use our type | ||
186 | return []string{resourceProvider(n.Addr.Type, "")} | ||
187 | } | ||
188 | |||
189 | // GraphNodeProvisionerConsumer | ||
190 | func (n *NodeAbstractResource) ProvisionedBy() []string { | ||
191 | // If we have no configuration, then we have no provisioners | ||
192 | if n.Config == nil { | ||
193 | return nil | ||
194 | } | ||
195 | |||
196 | // Build the list of provisioners we need based on the configuration. | ||
197 | // It is okay to have duplicates here. | ||
198 | result := make([]string, len(n.Config.Provisioners)) | ||
199 | for i, p := range n.Config.Provisioners { | ||
200 | result[i] = p.Type | ||
201 | } | ||
202 | |||
203 | return result | ||
204 | } | ||
205 | |||
206 | // GraphNodeResource, GraphNodeAttachResourceState | ||
207 | func (n *NodeAbstractResource) ResourceAddr() *ResourceAddress { | ||
208 | return n.Addr | ||
209 | } | ||
210 | |||
211 | // GraphNodeAddressable, TODO: remove, used by target, should unify | ||
212 | func (n *NodeAbstractResource) ResourceAddress() *ResourceAddress { | ||
213 | return n.ResourceAddr() | ||
214 | } | ||
215 | |||
216 | // GraphNodeTargetable | ||
217 | func (n *NodeAbstractResource) SetTargets(targets []ResourceAddress) { | ||
218 | n.Targets = targets | ||
219 | } | ||
220 | |||
221 | // GraphNodeAttachResourceState | ||
222 | func (n *NodeAbstractResource) AttachResourceState(s *ResourceState) { | ||
223 | n.ResourceState = s | ||
224 | } | ||
225 | |||
226 | // GraphNodeAttachResourceConfig | ||
227 | func (n *NodeAbstractResource) AttachResourceConfig(c *config.Resource) { | ||
228 | n.Config = c | ||
229 | } | ||
230 | |||
231 | // GraphNodeDotter impl. | ||
232 | func (n *NodeAbstractResource) DotNode(name string, opts *dag.DotOpts) *dag.DotNode { | ||
233 | return &dag.DotNode{ | ||
234 | Name: name, | ||
235 | Attrs: map[string]string{ | ||
236 | "label": n.Name(), | ||
237 | "shape": "box", | ||
238 | }, | ||
239 | } | ||
240 | } | ||