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