diff options
author | Jake Champlin <jake.champlin.27@gmail.com> | 2017-06-06 12:40:07 -0400 |
---|---|---|
committer | Jake Champlin <jake.champlin.27@gmail.com> | 2017-06-06 12:40:07 -0400 |
commit | bae9f6d2fd5eb5bc80929bd393932b23f14d7c93 (patch) | |
tree | ca9ab12a7d78b1fc27a8f734729081357ce6d252 /vendor/github.com/hashicorp/terraform/config/raw_config.go | |
parent | 254c495b6bebab3fb72a243c4bce858d79e6ee99 (diff) | |
download | terraform-provider-statuscake-bae9f6d2fd5eb5bc80929bd393932b23f14d7c93.tar.gz terraform-provider-statuscake-bae9f6d2fd5eb5bc80929bd393932b23f14d7c93.tar.zst terraform-provider-statuscake-bae9f6d2fd5eb5bc80929bd393932b23f14d7c93.zip |
Initial transfer of provider code
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/config/raw_config.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/config/raw_config.go | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/config/raw_config.go b/vendor/github.com/hashicorp/terraform/config/raw_config.go new file mode 100644 index 0000000..f8498d8 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/config/raw_config.go | |||
@@ -0,0 +1,335 @@ | |||
1 | package config | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "encoding/gob" | ||
6 | "sync" | ||
7 | |||
8 | "github.com/hashicorp/hil" | ||
9 | "github.com/hashicorp/hil/ast" | ||
10 | "github.com/mitchellh/copystructure" | ||
11 | "github.com/mitchellh/reflectwalk" | ||
12 | ) | ||
13 | |||
14 | // UnknownVariableValue is a sentinel value that can be used | ||
15 | // to denote that the value of a variable is unknown at this time. | ||
16 | // RawConfig uses this information to build up data about | ||
17 | // unknown keys. | ||
18 | const UnknownVariableValue = "74D93920-ED26-11E3-AC10-0800200C9A66" | ||
19 | |||
20 | // RawConfig is a structure that holds a piece of configuration | ||
21 | // where the overall structure is unknown since it will be used | ||
22 | // to configure a plugin or some other similar external component. | ||
23 | // | ||
24 | // RawConfigs can be interpolated with variables that come from | ||
25 | // other resources, user variables, etc. | ||
26 | // | ||
27 | // RawConfig supports a query-like interface to request | ||
28 | // information from deep within the structure. | ||
29 | type RawConfig struct { | ||
30 | Key string | ||
31 | Raw map[string]interface{} | ||
32 | Interpolations []ast.Node | ||
33 | Variables map[string]InterpolatedVariable | ||
34 | |||
35 | lock sync.Mutex | ||
36 | config map[string]interface{} | ||
37 | unknownKeys []string | ||
38 | } | ||
39 | |||
40 | // NewRawConfig creates a new RawConfig structure and populates the | ||
41 | // publicly readable struct fields. | ||
42 | func NewRawConfig(raw map[string]interface{}) (*RawConfig, error) { | ||
43 | result := &RawConfig{Raw: raw} | ||
44 | if err := result.init(); err != nil { | ||
45 | return nil, err | ||
46 | } | ||
47 | |||
48 | return result, nil | ||
49 | } | ||
50 | |||
51 | // RawMap returns a copy of the RawConfig.Raw map. | ||
52 | func (r *RawConfig) RawMap() map[string]interface{} { | ||
53 | r.lock.Lock() | ||
54 | defer r.lock.Unlock() | ||
55 | |||
56 | m := make(map[string]interface{}) | ||
57 | for k, v := range r.Raw { | ||
58 | m[k] = v | ||
59 | } | ||
60 | return m | ||
61 | } | ||
62 | |||
63 | // Copy returns a copy of this RawConfig, uninterpolated. | ||
64 | func (r *RawConfig) Copy() *RawConfig { | ||
65 | if r == nil { | ||
66 | return nil | ||
67 | } | ||
68 | |||
69 | r.lock.Lock() | ||
70 | defer r.lock.Unlock() | ||
71 | |||
72 | newRaw := make(map[string]interface{}) | ||
73 | for k, v := range r.Raw { | ||
74 | newRaw[k] = v | ||
75 | } | ||
76 | |||
77 | result, err := NewRawConfig(newRaw) | ||
78 | if err != nil { | ||
79 | panic("copy failed: " + err.Error()) | ||
80 | } | ||
81 | |||
82 | result.Key = r.Key | ||
83 | return result | ||
84 | } | ||
85 | |||
86 | // Value returns the value of the configuration if this configuration | ||
87 | // has a Key set. If this does not have a Key set, nil will be returned. | ||
88 | func (r *RawConfig) Value() interface{} { | ||
89 | if c := r.Config(); c != nil { | ||
90 | if v, ok := c[r.Key]; ok { | ||
91 | return v | ||
92 | } | ||
93 | } | ||
94 | |||
95 | r.lock.Lock() | ||
96 | defer r.lock.Unlock() | ||
97 | return r.Raw[r.Key] | ||
98 | } | ||
99 | |||
100 | // Config returns the entire configuration with the variables | ||
101 | // interpolated from any call to Interpolate. | ||
102 | // | ||
103 | // If any interpolated variables are unknown (value set to | ||
104 | // UnknownVariableValue), the first non-container (map, slice, etc.) element | ||
105 | // will be removed from the config. The keys of unknown variables | ||
106 | // can be found using the UnknownKeys function. | ||
107 | // | ||
108 | // By pruning out unknown keys from the configuration, the raw | ||
109 | // structure will always successfully decode into its ultimate | ||
110 | // structure using something like mapstructure. | ||
111 | func (r *RawConfig) Config() map[string]interface{} { | ||
112 | r.lock.Lock() | ||
113 | defer r.lock.Unlock() | ||
114 | return r.config | ||
115 | } | ||
116 | |||
117 | // Interpolate uses the given mapping of variable values and uses | ||
118 | // those as the values to replace any variables in this raw | ||
119 | // configuration. | ||
120 | // | ||
121 | // Any prior calls to Interpolate are replaced with this one. | ||
122 | // | ||
123 | // If a variable key is missing, this will panic. | ||
124 | func (r *RawConfig) Interpolate(vs map[string]ast.Variable) error { | ||
125 | r.lock.Lock() | ||
126 | defer r.lock.Unlock() | ||
127 | |||
128 | config := langEvalConfig(vs) | ||
129 | return r.interpolate(func(root ast.Node) (interface{}, error) { | ||
130 | // None of the variables we need are computed, meaning we should | ||
131 | // be able to properly evaluate. | ||
132 | result, err := hil.Eval(root, config) | ||
133 | if err != nil { | ||
134 | return "", err | ||
135 | } | ||
136 | |||
137 | return result.Value, nil | ||
138 | }) | ||
139 | } | ||
140 | |||
141 | // Merge merges another RawConfig into this one (overriding any conflicting | ||
142 | // values in this config) and returns a new config. The original config | ||
143 | // is not modified. | ||
144 | func (r *RawConfig) Merge(other *RawConfig) *RawConfig { | ||
145 | r.lock.Lock() | ||
146 | defer r.lock.Unlock() | ||
147 | |||
148 | // Merge the raw configurations | ||
149 | raw := make(map[string]interface{}) | ||
150 | for k, v := range r.Raw { | ||
151 | raw[k] = v | ||
152 | } | ||
153 | for k, v := range other.Raw { | ||
154 | raw[k] = v | ||
155 | } | ||
156 | |||
157 | // Create the result | ||
158 | result, err := NewRawConfig(raw) | ||
159 | if err != nil { | ||
160 | panic(err) | ||
161 | } | ||
162 | |||
163 | // Merge the interpolated results | ||
164 | result.config = make(map[string]interface{}) | ||
165 | for k, v := range r.config { | ||
166 | result.config[k] = v | ||
167 | } | ||
168 | for k, v := range other.config { | ||
169 | result.config[k] = v | ||
170 | } | ||
171 | |||
172 | // Build the unknown keys | ||
173 | if len(r.unknownKeys) > 0 || len(other.unknownKeys) > 0 { | ||
174 | unknownKeys := make(map[string]struct{}) | ||
175 | for _, k := range r.unknownKeys { | ||
176 | unknownKeys[k] = struct{}{} | ||
177 | } | ||
178 | for _, k := range other.unknownKeys { | ||
179 | unknownKeys[k] = struct{}{} | ||
180 | } | ||
181 | |||
182 | result.unknownKeys = make([]string, 0, len(unknownKeys)) | ||
183 | for k, _ := range unknownKeys { | ||
184 | result.unknownKeys = append(result.unknownKeys, k) | ||
185 | } | ||
186 | } | ||
187 | |||
188 | return result | ||
189 | } | ||
190 | |||
191 | func (r *RawConfig) init() error { | ||
192 | r.lock.Lock() | ||
193 | defer r.lock.Unlock() | ||
194 | |||
195 | r.config = r.Raw | ||
196 | r.Interpolations = nil | ||
197 | r.Variables = nil | ||
198 | |||
199 | fn := func(node ast.Node) (interface{}, error) { | ||
200 | r.Interpolations = append(r.Interpolations, node) | ||
201 | vars, err := DetectVariables(node) | ||
202 | if err != nil { | ||
203 | return "", err | ||
204 | } | ||
205 | |||
206 | for _, v := range vars { | ||
207 | if r.Variables == nil { | ||
208 | r.Variables = make(map[string]InterpolatedVariable) | ||
209 | } | ||
210 | |||
211 | r.Variables[v.FullKey()] = v | ||
212 | } | ||
213 | |||
214 | return "", nil | ||
215 | } | ||
216 | |||
217 | walker := &interpolationWalker{F: fn} | ||
218 | if err := reflectwalk.Walk(r.Raw, walker); err != nil { | ||
219 | return err | ||
220 | } | ||
221 | |||
222 | return nil | ||
223 | } | ||
224 | |||
225 | func (r *RawConfig) interpolate(fn interpolationWalkerFunc) error { | ||
226 | config, err := copystructure.Copy(r.Raw) | ||
227 | if err != nil { | ||
228 | return err | ||
229 | } | ||
230 | r.config = config.(map[string]interface{}) | ||
231 | |||
232 | w := &interpolationWalker{F: fn, Replace: true} | ||
233 | err = reflectwalk.Walk(r.config, w) | ||
234 | if err != nil { | ||
235 | return err | ||
236 | } | ||
237 | |||
238 | r.unknownKeys = w.unknownKeys | ||
239 | return nil | ||
240 | } | ||
241 | |||
242 | func (r *RawConfig) merge(r2 *RawConfig) *RawConfig { | ||
243 | if r == nil && r2 == nil { | ||
244 | return nil | ||
245 | } | ||
246 | |||
247 | if r == nil { | ||
248 | r = &RawConfig{} | ||
249 | } | ||
250 | |||
251 | rawRaw, err := copystructure.Copy(r.Raw) | ||
252 | if err != nil { | ||
253 | panic(err) | ||
254 | } | ||
255 | |||
256 | raw := rawRaw.(map[string]interface{}) | ||
257 | if r2 != nil { | ||
258 | for k, v := range r2.Raw { | ||
259 | raw[k] = v | ||
260 | } | ||
261 | } | ||
262 | |||
263 | result, err := NewRawConfig(raw) | ||
264 | if err != nil { | ||
265 | panic(err) | ||
266 | } | ||
267 | |||
268 | return result | ||
269 | } | ||
270 | |||
271 | // UnknownKeys returns the keys of the configuration that are unknown | ||
272 | // because they had interpolated variables that must be computed. | ||
273 | func (r *RawConfig) UnknownKeys() []string { | ||
274 | r.lock.Lock() | ||
275 | defer r.lock.Unlock() | ||
276 | return r.unknownKeys | ||
277 | } | ||
278 | |||
279 | // See GobEncode | ||
280 | func (r *RawConfig) GobDecode(b []byte) error { | ||
281 | var data gobRawConfig | ||
282 | err := gob.NewDecoder(bytes.NewReader(b)).Decode(&data) | ||
283 | if err != nil { | ||
284 | return err | ||
285 | } | ||
286 | |||
287 | r.Key = data.Key | ||
288 | r.Raw = data.Raw | ||
289 | |||
290 | return r.init() | ||
291 | } | ||
292 | |||
293 | // GobEncode is a custom Gob encoder to use so that we only include the | ||
294 | // raw configuration. Interpolated variables and such are lost and the | ||
295 | // tree of interpolated variables is recomputed on decode, since it is | ||
296 | // referentially transparent. | ||
297 | func (r *RawConfig) GobEncode() ([]byte, error) { | ||
298 | r.lock.Lock() | ||
299 | defer r.lock.Unlock() | ||
300 | |||
301 | data := gobRawConfig{ | ||
302 | Key: r.Key, | ||
303 | Raw: r.Raw, | ||
304 | } | ||
305 | |||
306 | var buf bytes.Buffer | ||
307 | if err := gob.NewEncoder(&buf).Encode(data); err != nil { | ||
308 | return nil, err | ||
309 | } | ||
310 | |||
311 | return buf.Bytes(), nil | ||
312 | } | ||
313 | |||
314 | type gobRawConfig struct { | ||
315 | Key string | ||
316 | Raw map[string]interface{} | ||
317 | } | ||
318 | |||
319 | // langEvalConfig returns the evaluation configuration we use to execute. | ||
320 | func langEvalConfig(vs map[string]ast.Variable) *hil.EvalConfig { | ||
321 | funcMap := make(map[string]ast.Function) | ||
322 | for k, v := range Funcs() { | ||
323 | funcMap[k] = v | ||
324 | } | ||
325 | funcMap["lookup"] = interpolationFuncLookup(vs) | ||
326 | funcMap["keys"] = interpolationFuncKeys(vs) | ||
327 | funcMap["values"] = interpolationFuncValues(vs) | ||
328 | |||
329 | return &hil.EvalConfig{ | ||
330 | GlobalScope: &ast.BasicScope{ | ||
331 | VarMap: vs, | ||
332 | FuncMap: funcMap, | ||
333 | }, | ||
334 | } | ||
335 | } | ||