]>
Commit | Line | Data |
---|---|---|
bae9f6d2 JC |
1 | package plugin |
2 | ||
3 | import ( | |
4 | "net/rpc" | |
5 | ||
6 | "github.com/hashicorp/go-plugin" | |
7 | "github.com/hashicorp/terraform/terraform" | |
8 | ) | |
9 | ||
10 | // ResourceProviderPlugin is the plugin.Plugin implementation. | |
11 | type ResourceProviderPlugin struct { | |
12 | F func() terraform.ResourceProvider | |
13 | } | |
14 | ||
15 | func (p *ResourceProviderPlugin) Server(b *plugin.MuxBroker) (interface{}, error) { | |
16 | return &ResourceProviderServer{Broker: b, Provider: p.F()}, nil | |
17 | } | |
18 | ||
19 | func (p *ResourceProviderPlugin) Client( | |
20 | b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) { | |
21 | return &ResourceProvider{Broker: b, Client: c}, nil | |
22 | } | |
23 | ||
24 | // ResourceProvider is an implementation of terraform.ResourceProvider | |
25 | // that communicates over RPC. | |
26 | type ResourceProvider struct { | |
27 | Broker *plugin.MuxBroker | |
28 | Client *rpc.Client | |
29 | } | |
30 | ||
31 | func (p *ResourceProvider) Stop() error { | |
32 | var resp ResourceProviderStopResponse | |
33 | err := p.Client.Call("Plugin.Stop", new(interface{}), &resp) | |
34 | if err != nil { | |
35 | return err | |
36 | } | |
37 | if resp.Error != nil { | |
38 | err = resp.Error | |
39 | } | |
40 | ||
41 | return err | |
42 | } | |
43 | ||
44 | func (p *ResourceProvider) Input( | |
45 | input terraform.UIInput, | |
46 | c *terraform.ResourceConfig) (*terraform.ResourceConfig, error) { | |
47 | id := p.Broker.NextId() | |
48 | go p.Broker.AcceptAndServe(id, &UIInputServer{ | |
49 | UIInput: input, | |
50 | }) | |
51 | ||
52 | var resp ResourceProviderInputResponse | |
53 | args := ResourceProviderInputArgs{ | |
54 | InputId: id, | |
55 | Config: c, | |
56 | } | |
57 | ||
58 | err := p.Client.Call("Plugin.Input", &args, &resp) | |
59 | if err != nil { | |
60 | return nil, err | |
61 | } | |
62 | if resp.Error != nil { | |
63 | err = resp.Error | |
64 | return nil, err | |
65 | } | |
66 | ||
67 | return resp.Config, nil | |
68 | } | |
69 | ||
70 | func (p *ResourceProvider) Validate(c *terraform.ResourceConfig) ([]string, []error) { | |
71 | var resp ResourceProviderValidateResponse | |
72 | args := ResourceProviderValidateArgs{ | |
73 | Config: c, | |
74 | } | |
75 | ||
76 | err := p.Client.Call("Plugin.Validate", &args, &resp) | |
77 | if err != nil { | |
78 | return nil, []error{err} | |
79 | } | |
80 | ||
81 | var errs []error | |
82 | if len(resp.Errors) > 0 { | |
83 | errs = make([]error, len(resp.Errors)) | |
84 | for i, err := range resp.Errors { | |
85 | errs[i] = err | |
86 | } | |
87 | } | |
88 | ||
89 | return resp.Warnings, errs | |
90 | } | |
91 | ||
92 | func (p *ResourceProvider) ValidateResource( | |
93 | t string, c *terraform.ResourceConfig) ([]string, []error) { | |
94 | var resp ResourceProviderValidateResourceResponse | |
95 | args := ResourceProviderValidateResourceArgs{ | |
96 | Config: c, | |
97 | Type: t, | |
98 | } | |
99 | ||
100 | err := p.Client.Call("Plugin.ValidateResource", &args, &resp) | |
101 | if err != nil { | |
102 | return nil, []error{err} | |
103 | } | |
104 | ||
105 | var errs []error | |
106 | if len(resp.Errors) > 0 { | |
107 | errs = make([]error, len(resp.Errors)) | |
108 | for i, err := range resp.Errors { | |
109 | errs[i] = err | |
110 | } | |
111 | } | |
112 | ||
113 | return resp.Warnings, errs | |
114 | } | |
115 | ||
116 | func (p *ResourceProvider) Configure(c *terraform.ResourceConfig) error { | |
117 | var resp ResourceProviderConfigureResponse | |
118 | err := p.Client.Call("Plugin.Configure", c, &resp) | |
119 | if err != nil { | |
120 | return err | |
121 | } | |
122 | if resp.Error != nil { | |
123 | err = resp.Error | |
124 | } | |
125 | ||
126 | return err | |
127 | } | |
128 | ||
129 | func (p *ResourceProvider) Apply( | |
130 | info *terraform.InstanceInfo, | |
131 | s *terraform.InstanceState, | |
132 | d *terraform.InstanceDiff) (*terraform.InstanceState, error) { | |
133 | var resp ResourceProviderApplyResponse | |
134 | args := &ResourceProviderApplyArgs{ | |
135 | Info: info, | |
136 | State: s, | |
137 | Diff: d, | |
138 | } | |
139 | ||
140 | err := p.Client.Call("Plugin.Apply", args, &resp) | |
141 | if err != nil { | |
142 | return nil, err | |
143 | } | |
144 | if resp.Error != nil { | |
145 | err = resp.Error | |
146 | } | |
147 | ||
148 | return resp.State, err | |
149 | } | |
150 | ||
151 | func (p *ResourceProvider) Diff( | |
152 | info *terraform.InstanceInfo, | |
153 | s *terraform.InstanceState, | |
154 | c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) { | |
155 | var resp ResourceProviderDiffResponse | |
156 | args := &ResourceProviderDiffArgs{ | |
157 | Info: info, | |
158 | State: s, | |
159 | Config: c, | |
160 | } | |
161 | err := p.Client.Call("Plugin.Diff", args, &resp) | |
162 | if err != nil { | |
163 | return nil, err | |
164 | } | |
165 | if resp.Error != nil { | |
166 | err = resp.Error | |
167 | } | |
168 | ||
169 | return resp.Diff, err | |
170 | } | |
171 | ||
172 | func (p *ResourceProvider) ValidateDataSource( | |
173 | t string, c *terraform.ResourceConfig) ([]string, []error) { | |
174 | var resp ResourceProviderValidateResourceResponse | |
175 | args := ResourceProviderValidateResourceArgs{ | |
176 | Config: c, | |
177 | Type: t, | |
178 | } | |
179 | ||
180 | err := p.Client.Call("Plugin.ValidateDataSource", &args, &resp) | |
181 | if err != nil { | |
182 | return nil, []error{err} | |
183 | } | |
184 | ||
185 | var errs []error | |
186 | if len(resp.Errors) > 0 { | |
187 | errs = make([]error, len(resp.Errors)) | |
188 | for i, err := range resp.Errors { | |
189 | errs[i] = err | |
190 | } | |
191 | } | |
192 | ||
193 | return resp.Warnings, errs | |
194 | } | |
195 | ||
196 | func (p *ResourceProvider) Refresh( | |
197 | info *terraform.InstanceInfo, | |
198 | s *terraform.InstanceState) (*terraform.InstanceState, error) { | |
199 | var resp ResourceProviderRefreshResponse | |
200 | args := &ResourceProviderRefreshArgs{ | |
201 | Info: info, | |
202 | State: s, | |
203 | } | |
204 | ||
205 | err := p.Client.Call("Plugin.Refresh", args, &resp) | |
206 | if err != nil { | |
207 | return nil, err | |
208 | } | |
209 | if resp.Error != nil { | |
210 | err = resp.Error | |
211 | } | |
212 | ||
213 | return resp.State, err | |
214 | } | |
215 | ||
216 | func (p *ResourceProvider) ImportState( | |
217 | info *terraform.InstanceInfo, | |
218 | id string) ([]*terraform.InstanceState, error) { | |
219 | var resp ResourceProviderImportStateResponse | |
220 | args := &ResourceProviderImportStateArgs{ | |
221 | Info: info, | |
222 | Id: id, | |
223 | } | |
224 | ||
225 | err := p.Client.Call("Plugin.ImportState", args, &resp) | |
226 | if err != nil { | |
227 | return nil, err | |
228 | } | |
229 | if resp.Error != nil { | |
230 | err = resp.Error | |
231 | } | |
232 | ||
233 | return resp.State, err | |
234 | } | |
235 | ||
236 | func (p *ResourceProvider) Resources() []terraform.ResourceType { | |
237 | var result []terraform.ResourceType | |
238 | ||
239 | err := p.Client.Call("Plugin.Resources", new(interface{}), &result) | |
240 | if err != nil { | |
241 | // TODO: panic, log, what? | |
242 | return nil | |
243 | } | |
244 | ||
245 | return result | |
246 | } | |
247 | ||
248 | func (p *ResourceProvider) ReadDataDiff( | |
249 | info *terraform.InstanceInfo, | |
250 | c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) { | |
251 | var resp ResourceProviderReadDataDiffResponse | |
252 | args := &ResourceProviderReadDataDiffArgs{ | |
253 | Info: info, | |
254 | Config: c, | |
255 | } | |
256 | ||
257 | err := p.Client.Call("Plugin.ReadDataDiff", args, &resp) | |
258 | if err != nil { | |
259 | return nil, err | |
260 | } | |
261 | if resp.Error != nil { | |
262 | err = resp.Error | |
263 | } | |
264 | ||
265 | return resp.Diff, err | |
266 | } | |
267 | ||
268 | func (p *ResourceProvider) ReadDataApply( | |
269 | info *terraform.InstanceInfo, | |
270 | d *terraform.InstanceDiff) (*terraform.InstanceState, error) { | |
271 | var resp ResourceProviderReadDataApplyResponse | |
272 | args := &ResourceProviderReadDataApplyArgs{ | |
273 | Info: info, | |
274 | Diff: d, | |
275 | } | |
276 | ||
277 | err := p.Client.Call("Plugin.ReadDataApply", args, &resp) | |
278 | if err != nil { | |
279 | return nil, err | |
280 | } | |
281 | if resp.Error != nil { | |
282 | err = resp.Error | |
283 | } | |
284 | ||
285 | return resp.State, err | |
286 | } | |
287 | ||
288 | func (p *ResourceProvider) DataSources() []terraform.DataSource { | |
289 | var result []terraform.DataSource | |
290 | ||
291 | err := p.Client.Call("Plugin.DataSources", new(interface{}), &result) | |
292 | if err != nil { | |
293 | // TODO: panic, log, what? | |
294 | return nil | |
295 | } | |
296 | ||
297 | return result | |
298 | } | |
299 | ||
300 | func (p *ResourceProvider) Close() error { | |
301 | return p.Client.Close() | |
302 | } | |
303 | ||
304 | // ResourceProviderServer is a net/rpc compatible structure for serving | |
305 | // a ResourceProvider. This should not be used directly. | |
306 | type ResourceProviderServer struct { | |
307 | Broker *plugin.MuxBroker | |
308 | Provider terraform.ResourceProvider | |
309 | } | |
310 | ||
311 | type ResourceProviderStopResponse struct { | |
312 | Error *plugin.BasicError | |
313 | } | |
314 | ||
315 | type ResourceProviderConfigureResponse struct { | |
316 | Error *plugin.BasicError | |
317 | } | |
318 | ||
319 | type ResourceProviderInputArgs struct { | |
320 | InputId uint32 | |
321 | Config *terraform.ResourceConfig | |
322 | } | |
323 | ||
324 | type ResourceProviderInputResponse struct { | |
325 | Config *terraform.ResourceConfig | |
326 | Error *plugin.BasicError | |
327 | } | |
328 | ||
329 | type ResourceProviderApplyArgs struct { | |
330 | Info *terraform.InstanceInfo | |
331 | State *terraform.InstanceState | |
332 | Diff *terraform.InstanceDiff | |
333 | } | |
334 | ||
335 | type ResourceProviderApplyResponse struct { | |
336 | State *terraform.InstanceState | |
337 | Error *plugin.BasicError | |
338 | } | |
339 | ||
340 | type ResourceProviderDiffArgs struct { | |
341 | Info *terraform.InstanceInfo | |
342 | State *terraform.InstanceState | |
343 | Config *terraform.ResourceConfig | |
344 | } | |
345 | ||
346 | type ResourceProviderDiffResponse struct { | |
347 | Diff *terraform.InstanceDiff | |
348 | Error *plugin.BasicError | |
349 | } | |
350 | ||
351 | type ResourceProviderRefreshArgs struct { | |
352 | Info *terraform.InstanceInfo | |
353 | State *terraform.InstanceState | |
354 | } | |
355 | ||
356 | type ResourceProviderRefreshResponse struct { | |
357 | State *terraform.InstanceState | |
358 | Error *plugin.BasicError | |
359 | } | |
360 | ||
361 | type ResourceProviderImportStateArgs struct { | |
362 | Info *terraform.InstanceInfo | |
363 | Id string | |
364 | } | |
365 | ||
366 | type ResourceProviderImportStateResponse struct { | |
367 | State []*terraform.InstanceState | |
368 | Error *plugin.BasicError | |
369 | } | |
370 | ||
371 | type ResourceProviderReadDataApplyArgs struct { | |
372 | Info *terraform.InstanceInfo | |
373 | Diff *terraform.InstanceDiff | |
374 | } | |
375 | ||
376 | type ResourceProviderReadDataApplyResponse struct { | |
377 | State *terraform.InstanceState | |
378 | Error *plugin.BasicError | |
379 | } | |
380 | ||
381 | type ResourceProviderReadDataDiffArgs struct { | |
382 | Info *terraform.InstanceInfo | |
383 | Config *terraform.ResourceConfig | |
384 | } | |
385 | ||
386 | type ResourceProviderReadDataDiffResponse struct { | |
387 | Diff *terraform.InstanceDiff | |
388 | Error *plugin.BasicError | |
389 | } | |
390 | ||
391 | type ResourceProviderValidateArgs struct { | |
392 | Config *terraform.ResourceConfig | |
393 | } | |
394 | ||
395 | type ResourceProviderValidateResponse struct { | |
396 | Warnings []string | |
397 | Errors []*plugin.BasicError | |
398 | } | |
399 | ||
400 | type ResourceProviderValidateResourceArgs struct { | |
401 | Config *terraform.ResourceConfig | |
402 | Type string | |
403 | } | |
404 | ||
405 | type ResourceProviderValidateResourceResponse struct { | |
406 | Warnings []string | |
407 | Errors []*plugin.BasicError | |
408 | } | |
409 | ||
410 | func (s *ResourceProviderServer) Stop( | |
411 | _ interface{}, | |
412 | reply *ResourceProviderStopResponse) error { | |
413 | err := s.Provider.Stop() | |
414 | *reply = ResourceProviderStopResponse{ | |
415 | Error: plugin.NewBasicError(err), | |
416 | } | |
417 | ||
418 | return nil | |
419 | } | |
420 | ||
421 | func (s *ResourceProviderServer) Input( | |
422 | args *ResourceProviderInputArgs, | |
423 | reply *ResourceProviderInputResponse) error { | |
424 | conn, err := s.Broker.Dial(args.InputId) | |
425 | if err != nil { | |
426 | *reply = ResourceProviderInputResponse{ | |
427 | Error: plugin.NewBasicError(err), | |
428 | } | |
429 | return nil | |
430 | } | |
431 | client := rpc.NewClient(conn) | |
432 | defer client.Close() | |
433 | ||
434 | input := &UIInput{Client: client} | |
435 | ||
436 | config, err := s.Provider.Input(input, args.Config) | |
437 | *reply = ResourceProviderInputResponse{ | |
438 | Config: config, | |
439 | Error: plugin.NewBasicError(err), | |
440 | } | |
441 | ||
442 | return nil | |
443 | } | |
444 | ||
445 | func (s *ResourceProviderServer) Validate( | |
446 | args *ResourceProviderValidateArgs, | |
447 | reply *ResourceProviderValidateResponse) error { | |
448 | warns, errs := s.Provider.Validate(args.Config) | |
449 | berrs := make([]*plugin.BasicError, len(errs)) | |
450 | for i, err := range errs { | |
451 | berrs[i] = plugin.NewBasicError(err) | |
452 | } | |
453 | *reply = ResourceProviderValidateResponse{ | |
454 | Warnings: warns, | |
455 | Errors: berrs, | |
456 | } | |
457 | return nil | |
458 | } | |
459 | ||
460 | func (s *ResourceProviderServer) ValidateResource( | |
461 | args *ResourceProviderValidateResourceArgs, | |
462 | reply *ResourceProviderValidateResourceResponse) error { | |
463 | warns, errs := s.Provider.ValidateResource(args.Type, args.Config) | |
464 | berrs := make([]*plugin.BasicError, len(errs)) | |
465 | for i, err := range errs { | |
466 | berrs[i] = plugin.NewBasicError(err) | |
467 | } | |
468 | *reply = ResourceProviderValidateResourceResponse{ | |
469 | Warnings: warns, | |
470 | Errors: berrs, | |
471 | } | |
472 | return nil | |
473 | } | |
474 | ||
475 | func (s *ResourceProviderServer) Configure( | |
476 | config *terraform.ResourceConfig, | |
477 | reply *ResourceProviderConfigureResponse) error { | |
478 | err := s.Provider.Configure(config) | |
479 | *reply = ResourceProviderConfigureResponse{ | |
480 | Error: plugin.NewBasicError(err), | |
481 | } | |
482 | return nil | |
483 | } | |
484 | ||
485 | func (s *ResourceProviderServer) Apply( | |
486 | args *ResourceProviderApplyArgs, | |
487 | result *ResourceProviderApplyResponse) error { | |
488 | state, err := s.Provider.Apply(args.Info, args.State, args.Diff) | |
489 | *result = ResourceProviderApplyResponse{ | |
490 | State: state, | |
491 | Error: plugin.NewBasicError(err), | |
492 | } | |
493 | return nil | |
494 | } | |
495 | ||
496 | func (s *ResourceProviderServer) Diff( | |
497 | args *ResourceProviderDiffArgs, | |
498 | result *ResourceProviderDiffResponse) error { | |
499 | diff, err := s.Provider.Diff(args.Info, args.State, args.Config) | |
500 | *result = ResourceProviderDiffResponse{ | |
501 | Diff: diff, | |
502 | Error: plugin.NewBasicError(err), | |
503 | } | |
504 | return nil | |
505 | } | |
506 | ||
507 | func (s *ResourceProviderServer) Refresh( | |
508 | args *ResourceProviderRefreshArgs, | |
509 | result *ResourceProviderRefreshResponse) error { | |
510 | newState, err := s.Provider.Refresh(args.Info, args.State) | |
511 | *result = ResourceProviderRefreshResponse{ | |
512 | State: newState, | |
513 | Error: plugin.NewBasicError(err), | |
514 | } | |
515 | return nil | |
516 | } | |
517 | ||
518 | func (s *ResourceProviderServer) ImportState( | |
519 | args *ResourceProviderImportStateArgs, | |
520 | result *ResourceProviderImportStateResponse) error { | |
521 | states, err := s.Provider.ImportState(args.Info, args.Id) | |
522 | *result = ResourceProviderImportStateResponse{ | |
523 | State: states, | |
524 | Error: plugin.NewBasicError(err), | |
525 | } | |
526 | return nil | |
527 | } | |
528 | ||
529 | func (s *ResourceProviderServer) Resources( | |
530 | nothing interface{}, | |
531 | result *[]terraform.ResourceType) error { | |
532 | *result = s.Provider.Resources() | |
533 | return nil | |
534 | } | |
535 | ||
536 | func (s *ResourceProviderServer) ValidateDataSource( | |
537 | args *ResourceProviderValidateResourceArgs, | |
538 | reply *ResourceProviderValidateResourceResponse) error { | |
539 | warns, errs := s.Provider.ValidateDataSource(args.Type, args.Config) | |
540 | berrs := make([]*plugin.BasicError, len(errs)) | |
541 | for i, err := range errs { | |
542 | berrs[i] = plugin.NewBasicError(err) | |
543 | } | |
544 | *reply = ResourceProviderValidateResourceResponse{ | |
545 | Warnings: warns, | |
546 | Errors: berrs, | |
547 | } | |
548 | return nil | |
549 | } | |
550 | ||
551 | func (s *ResourceProviderServer) ReadDataDiff( | |
552 | args *ResourceProviderReadDataDiffArgs, | |
553 | result *ResourceProviderReadDataDiffResponse) error { | |
554 | diff, err := s.Provider.ReadDataDiff(args.Info, args.Config) | |
555 | *result = ResourceProviderReadDataDiffResponse{ | |
556 | Diff: diff, | |
557 | Error: plugin.NewBasicError(err), | |
558 | } | |
559 | return nil | |
560 | } | |
561 | ||
562 | func (s *ResourceProviderServer) ReadDataApply( | |
563 | args *ResourceProviderReadDataApplyArgs, | |
564 | result *ResourceProviderReadDataApplyResponse) error { | |
565 | newState, err := s.Provider.ReadDataApply(args.Info, args.Diff) | |
566 | *result = ResourceProviderReadDataApplyResponse{ | |
567 | State: newState, | |
568 | Error: plugin.NewBasicError(err), | |
569 | } | |
570 | return nil | |
571 | } | |
572 | ||
573 | func (s *ResourceProviderServer) DataSources( | |
574 | nothing interface{}, | |
575 | result *[]terraform.DataSource) error { | |
576 | *result = s.Provider.DataSources() | |
577 | return nil | |
578 | } |