diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/helper/schema/resource_timeout.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/helper/schema/resource_timeout.go | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/helper/schema/resource_timeout.go b/vendor/github.com/hashicorp/terraform/helper/schema/resource_timeout.go new file mode 100644 index 0000000..445819f --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/helper/schema/resource_timeout.go | |||
@@ -0,0 +1,237 @@ | |||
1 | package schema | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "log" | ||
6 | "time" | ||
7 | |||
8 | "github.com/hashicorp/terraform/terraform" | ||
9 | "github.com/mitchellh/copystructure" | ||
10 | ) | ||
11 | |||
12 | const TimeoutKey = "e2bfb730-ecaa-11e6-8f88-34363bc7c4c0" | ||
13 | const TimeoutsConfigKey = "timeouts" | ||
14 | |||
15 | const ( | ||
16 | TimeoutCreate = "create" | ||
17 | TimeoutRead = "read" | ||
18 | TimeoutUpdate = "update" | ||
19 | TimeoutDelete = "delete" | ||
20 | TimeoutDefault = "default" | ||
21 | ) | ||
22 | |||
23 | func timeoutKeys() []string { | ||
24 | return []string{ | ||
25 | TimeoutCreate, | ||
26 | TimeoutRead, | ||
27 | TimeoutUpdate, | ||
28 | TimeoutDelete, | ||
29 | TimeoutDefault, | ||
30 | } | ||
31 | } | ||
32 | |||
33 | // could be time.Duration, int64 or float64 | ||
34 | func DefaultTimeout(tx interface{}) *time.Duration { | ||
35 | var td time.Duration | ||
36 | switch raw := tx.(type) { | ||
37 | case time.Duration: | ||
38 | return &raw | ||
39 | case int64: | ||
40 | td = time.Duration(raw) | ||
41 | case float64: | ||
42 | td = time.Duration(int64(raw)) | ||
43 | default: | ||
44 | log.Printf("[WARN] Unknown type in DefaultTimeout: %#v", tx) | ||
45 | } | ||
46 | return &td | ||
47 | } | ||
48 | |||
49 | type ResourceTimeout struct { | ||
50 | Create, Read, Update, Delete, Default *time.Duration | ||
51 | } | ||
52 | |||
53 | // ConfigDecode takes a schema and the configuration (available in Diff) and | ||
54 | // validates, parses the timeouts into `t` | ||
55 | func (t *ResourceTimeout) ConfigDecode(s *Resource, c *terraform.ResourceConfig) error { | ||
56 | if s.Timeouts != nil { | ||
57 | raw, err := copystructure.Copy(s.Timeouts) | ||
58 | if err != nil { | ||
59 | log.Printf("[DEBUG] Error with deep copy: %s", err) | ||
60 | } | ||
61 | *t = *raw.(*ResourceTimeout) | ||
62 | } | ||
63 | |||
64 | if raw, ok := c.Config[TimeoutsConfigKey]; ok { | ||
65 | if configTimeouts, ok := raw.([]map[string]interface{}); ok { | ||
66 | for _, timeoutValues := range configTimeouts { | ||
67 | // loop through each Timeout given in the configuration and validate they | ||
68 | // the Timeout defined in the resource | ||
69 | for timeKey, timeValue := range timeoutValues { | ||
70 | // validate that we're dealing with the normal CRUD actions | ||
71 | var found bool | ||
72 | for _, key := range timeoutKeys() { | ||
73 | if timeKey == key { | ||
74 | found = true | ||
75 | break | ||
76 | } | ||
77 | } | ||
78 | |||
79 | if !found { | ||
80 | return fmt.Errorf("Unsupported Timeout configuration key found (%s)", timeKey) | ||
81 | } | ||
82 | |||
83 | // Get timeout | ||
84 | rt, err := time.ParseDuration(timeValue.(string)) | ||
85 | if err != nil { | ||
86 | return fmt.Errorf("Error parsing Timeout for (%s): %s", timeKey, err) | ||
87 | } | ||
88 | |||
89 | var timeout *time.Duration | ||
90 | switch timeKey { | ||
91 | case TimeoutCreate: | ||
92 | timeout = t.Create | ||
93 | case TimeoutUpdate: | ||
94 | timeout = t.Update | ||
95 | case TimeoutRead: | ||
96 | timeout = t.Read | ||
97 | case TimeoutDelete: | ||
98 | timeout = t.Delete | ||
99 | case TimeoutDefault: | ||
100 | timeout = t.Default | ||
101 | } | ||
102 | |||
103 | // If the resource has not delcared this in the definition, then error | ||
104 | // with an unsupported message | ||
105 | if timeout == nil { | ||
106 | return unsupportedTimeoutKeyError(timeKey) | ||
107 | } | ||
108 | |||
109 | *timeout = rt | ||
110 | } | ||
111 | } | ||
112 | } else { | ||
113 | log.Printf("[WARN] Invalid Timeout structure found, skipping timeouts") | ||
114 | } | ||
115 | } | ||
116 | |||
117 | return nil | ||
118 | } | ||
119 | |||
120 | func unsupportedTimeoutKeyError(key string) error { | ||
121 | return fmt.Errorf("Timeout Key (%s) is not supported", key) | ||
122 | } | ||
123 | |||
124 | // DiffEncode, StateEncode, and MetaDecode are analogous to the Go stdlib JSONEncoder | ||
125 | // interface: they encode/decode a timeouts struct from an instance diff, which is | ||
126 | // where the timeout data is stored after a diff to pass into Apply. | ||
127 | // | ||
128 | // StateEncode encodes the timeout into the ResourceData's InstanceState for | ||
129 | // saving to state | ||
130 | // | ||
131 | func (t *ResourceTimeout) DiffEncode(id *terraform.InstanceDiff) error { | ||
132 | return t.metaEncode(id) | ||
133 | } | ||
134 | |||
135 | func (t *ResourceTimeout) StateEncode(is *terraform.InstanceState) error { | ||
136 | return t.metaEncode(is) | ||
137 | } | ||
138 | |||
139 | // metaEncode encodes the ResourceTimeout into a map[string]interface{} format | ||
140 | // and stores it in the Meta field of the interface it's given. | ||
141 | // Assumes the interface is either *terraform.InstanceState or | ||
142 | // *terraform.InstanceDiff, returns an error otherwise | ||
143 | func (t *ResourceTimeout) metaEncode(ids interface{}) error { | ||
144 | m := make(map[string]interface{}) | ||
145 | |||
146 | if t.Create != nil { | ||
147 | m[TimeoutCreate] = t.Create.Nanoseconds() | ||
148 | } | ||
149 | if t.Read != nil { | ||
150 | m[TimeoutRead] = t.Read.Nanoseconds() | ||
151 | } | ||
152 | if t.Update != nil { | ||
153 | m[TimeoutUpdate] = t.Update.Nanoseconds() | ||
154 | } | ||
155 | if t.Delete != nil { | ||
156 | m[TimeoutDelete] = t.Delete.Nanoseconds() | ||
157 | } | ||
158 | if t.Default != nil { | ||
159 | m[TimeoutDefault] = t.Default.Nanoseconds() | ||
160 | // for any key above that is nil, if default is specified, we need to | ||
161 | // populate it with the default | ||
162 | for _, k := range timeoutKeys() { | ||
163 | if _, ok := m[k]; !ok { | ||
164 | m[k] = t.Default.Nanoseconds() | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | |||
169 | // only add the Timeout to the Meta if we have values | ||
170 | if len(m) > 0 { | ||
171 | switch instance := ids.(type) { | ||
172 | case *terraform.InstanceDiff: | ||
173 | if instance.Meta == nil { | ||
174 | instance.Meta = make(map[string]interface{}) | ||
175 | } | ||
176 | instance.Meta[TimeoutKey] = m | ||
177 | case *terraform.InstanceState: | ||
178 | if instance.Meta == nil { | ||
179 | instance.Meta = make(map[string]interface{}) | ||
180 | } | ||
181 | instance.Meta[TimeoutKey] = m | ||
182 | default: | ||
183 | return fmt.Errorf("Error matching type for Diff Encode") | ||
184 | } | ||
185 | } | ||
186 | |||
187 | return nil | ||
188 | } | ||
189 | |||
190 | func (t *ResourceTimeout) StateDecode(id *terraform.InstanceState) error { | ||
191 | return t.metaDecode(id) | ||
192 | } | ||
193 | func (t *ResourceTimeout) DiffDecode(is *terraform.InstanceDiff) error { | ||
194 | return t.metaDecode(is) | ||
195 | } | ||
196 | |||
197 | func (t *ResourceTimeout) metaDecode(ids interface{}) error { | ||
198 | var rawMeta interface{} | ||
199 | var ok bool | ||
200 | switch rawInstance := ids.(type) { | ||
201 | case *terraform.InstanceDiff: | ||
202 | rawMeta, ok = rawInstance.Meta[TimeoutKey] | ||
203 | if !ok { | ||
204 | return nil | ||
205 | } | ||
206 | case *terraform.InstanceState: | ||
207 | rawMeta, ok = rawInstance.Meta[TimeoutKey] | ||
208 | if !ok { | ||
209 | return nil | ||
210 | } | ||
211 | default: | ||
212 | return fmt.Errorf("Unknown or unsupported type in metaDecode: %#v", ids) | ||
213 | } | ||
214 | |||
215 | times := rawMeta.(map[string]interface{}) | ||
216 | if len(times) == 0 { | ||
217 | return nil | ||
218 | } | ||
219 | |||
220 | if v, ok := times[TimeoutCreate]; ok { | ||
221 | t.Create = DefaultTimeout(v) | ||
222 | } | ||
223 | if v, ok := times[TimeoutRead]; ok { | ||
224 | t.Read = DefaultTimeout(v) | ||
225 | } | ||
226 | if v, ok := times[TimeoutUpdate]; ok { | ||
227 | t.Update = DefaultTimeout(v) | ||
228 | } | ||
229 | if v, ok := times[TimeoutDelete]; ok { | ||
230 | t.Delete = DefaultTimeout(v) | ||
231 | } | ||
232 | if v, ok := times[TimeoutDefault]; ok { | ||
233 | t.Default = DefaultTimeout(v) | ||
234 | } | ||
235 | |||
236 | return nil | ||
237 | } | ||