6 "github.com/hashicorp/go-plugin"
7 "github.com/hashicorp/terraform/terraform"
10 // ResourceProviderPlugin is the plugin.Plugin implementation.
11 type ResourceProviderPlugin struct {
12 F func() terraform.ResourceProvider
15 func (p *ResourceProviderPlugin) Server(b *plugin.MuxBroker) (interface{}, error) {
16 return &ResourceProviderServer{Broker: b, Provider: p.F()}, nil
19 func (p *ResourceProviderPlugin) Client(
20 b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) {
21 return &ResourceProvider{Broker: b, Client: c}, nil
24 // ResourceProvider is an implementation of terraform.ResourceProvider
25 // that communicates over RPC.
26 type ResourceProvider struct {
27 Broker *plugin.MuxBroker
31 func (p *ResourceProvider) Stop() error {
32 var resp ResourceProviderStopResponse
33 err := p.Client.Call("Plugin.Stop", new(interface{}), &resp)
37 if resp.Error != nil {
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{
52 var resp ResourceProviderInputResponse
53 args := ResourceProviderInputArgs{
58 err := p.Client.Call("Plugin.Input", &args, &resp)
62 if resp.Error != nil {
67 return resp.Config, nil
70 func (p *ResourceProvider) Validate(c *terraform.ResourceConfig) ([]string, []error) {
71 var resp ResourceProviderValidateResponse
72 args := ResourceProviderValidateArgs{
76 err := p.Client.Call("Plugin.Validate", &args, &resp)
78 return nil, []error{err}
82 if len(resp.Errors) > 0 {
83 errs = make([]error, len(resp.Errors))
84 for i, err := range resp.Errors {
89 return resp.Warnings, errs
92 func (p *ResourceProvider) ValidateResource(
93 t string, c *terraform.ResourceConfig) ([]string, []error) {
94 var resp ResourceProviderValidateResourceResponse
95 args := ResourceProviderValidateResourceArgs{
100 err := p.Client.Call("Plugin.ValidateResource", &args, &resp)
102 return nil, []error{err}
106 if len(resp.Errors) > 0 {
107 errs = make([]error, len(resp.Errors))
108 for i, err := range resp.Errors {
113 return resp.Warnings, errs
116 func (p *ResourceProvider) Configure(c *terraform.ResourceConfig) error {
117 var resp ResourceProviderConfigureResponse
118 err := p.Client.Call("Plugin.Configure", c, &resp)
122 if resp.Error != nil {
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{
140 err := p.Client.Call("Plugin.Apply", args, &resp)
144 if resp.Error != nil {
148 return resp.State, err
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{
161 err := p.Client.Call("Plugin.Diff", args, &resp)
165 if resp.Error != nil {
169 return resp.Diff, err
172 func (p *ResourceProvider) ValidateDataSource(
173 t string, c *terraform.ResourceConfig) ([]string, []error) {
174 var resp ResourceProviderValidateResourceResponse
175 args := ResourceProviderValidateResourceArgs{
180 err := p.Client.Call("Plugin.ValidateDataSource", &args, &resp)
182 return nil, []error{err}
186 if len(resp.Errors) > 0 {
187 errs = make([]error, len(resp.Errors))
188 for i, err := range resp.Errors {
193 return resp.Warnings, errs
196 func (p *ResourceProvider) Refresh(
197 info *terraform.InstanceInfo,
198 s *terraform.InstanceState) (*terraform.InstanceState, error) {
199 var resp ResourceProviderRefreshResponse
200 args := &ResourceProviderRefreshArgs{
205 err := p.Client.Call("Plugin.Refresh", args, &resp)
209 if resp.Error != nil {
213 return resp.State, err
216 func (p *ResourceProvider) ImportState(
217 info *terraform.InstanceInfo,
218 id string) ([]*terraform.InstanceState, error) {
219 var resp ResourceProviderImportStateResponse
220 args := &ResourceProviderImportStateArgs{
225 err := p.Client.Call("Plugin.ImportState", args, &resp)
229 if resp.Error != nil {
233 return resp.State, err
236 func (p *ResourceProvider) Resources() []terraform.ResourceType {
237 var result []terraform.ResourceType
239 err := p.Client.Call("Plugin.Resources", new(interface{}), &result)
241 // TODO: panic, log, what?
248 func (p *ResourceProvider) ReadDataDiff(
249 info *terraform.InstanceInfo,
250 c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
251 var resp ResourceProviderReadDataDiffResponse
252 args := &ResourceProviderReadDataDiffArgs{
257 err := p.Client.Call("Plugin.ReadDataDiff", args, &resp)
261 if resp.Error != nil {
265 return resp.Diff, err
268 func (p *ResourceProvider) ReadDataApply(
269 info *terraform.InstanceInfo,
270 d *terraform.InstanceDiff) (*terraform.InstanceState, error) {
271 var resp ResourceProviderReadDataApplyResponse
272 args := &ResourceProviderReadDataApplyArgs{
277 err := p.Client.Call("Plugin.ReadDataApply", args, &resp)
281 if resp.Error != nil {
285 return resp.State, err
288 func (p *ResourceProvider) DataSources() []terraform.DataSource {
289 var result []terraform.DataSource
291 err := p.Client.Call("Plugin.DataSources", new(interface{}), &result)
293 // TODO: panic, log, what?
300 func (p *ResourceProvider) Close() error {
301 return p.Client.Close()
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
311 type ResourceProviderStopResponse struct {
312 Error *plugin.BasicError
315 type ResourceProviderConfigureResponse struct {
316 Error *plugin.BasicError
319 type ResourceProviderInputArgs struct {
321 Config *terraform.ResourceConfig
324 type ResourceProviderInputResponse struct {
325 Config *terraform.ResourceConfig
326 Error *plugin.BasicError
329 type ResourceProviderApplyArgs struct {
330 Info *terraform.InstanceInfo
331 State *terraform.InstanceState
332 Diff *terraform.InstanceDiff
335 type ResourceProviderApplyResponse struct {
336 State *terraform.InstanceState
337 Error *plugin.BasicError
340 type ResourceProviderDiffArgs struct {
341 Info *terraform.InstanceInfo
342 State *terraform.InstanceState
343 Config *terraform.ResourceConfig
346 type ResourceProviderDiffResponse struct {
347 Diff *terraform.InstanceDiff
348 Error *plugin.BasicError
351 type ResourceProviderRefreshArgs struct {
352 Info *terraform.InstanceInfo
353 State *terraform.InstanceState
356 type ResourceProviderRefreshResponse struct {
357 State *terraform.InstanceState
358 Error *plugin.BasicError
361 type ResourceProviderImportStateArgs struct {
362 Info *terraform.InstanceInfo
366 type ResourceProviderImportStateResponse struct {
367 State []*terraform.InstanceState
368 Error *plugin.BasicError
371 type ResourceProviderReadDataApplyArgs struct {
372 Info *terraform.InstanceInfo
373 Diff *terraform.InstanceDiff
376 type ResourceProviderReadDataApplyResponse struct {
377 State *terraform.InstanceState
378 Error *plugin.BasicError
381 type ResourceProviderReadDataDiffArgs struct {
382 Info *terraform.InstanceInfo
383 Config *terraform.ResourceConfig
386 type ResourceProviderReadDataDiffResponse struct {
387 Diff *terraform.InstanceDiff
388 Error *plugin.BasicError
391 type ResourceProviderValidateArgs struct {
392 Config *terraform.ResourceConfig
395 type ResourceProviderValidateResponse struct {
397 Errors []*plugin.BasicError
400 type ResourceProviderValidateResourceArgs struct {
401 Config *terraform.ResourceConfig
405 type ResourceProviderValidateResourceResponse struct {
407 Errors []*plugin.BasicError
410 func (s *ResourceProviderServer) Stop(
412 reply *ResourceProviderStopResponse) error {
413 err := s.Provider.Stop()
414 *reply = ResourceProviderStopResponse{
415 Error: plugin.NewBasicError(err),
421 func (s *ResourceProviderServer) Input(
422 args *ResourceProviderInputArgs,
423 reply *ResourceProviderInputResponse) error {
424 conn, err := s.Broker.Dial(args.InputId)
426 *reply = ResourceProviderInputResponse{
427 Error: plugin.NewBasicError(err),
431 client := rpc.NewClient(conn)
434 input := &UIInput{Client: client}
436 config, err := s.Provider.Input(input, args.Config)
437 *reply = ResourceProviderInputResponse{
439 Error: plugin.NewBasicError(err),
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)
453 *reply = ResourceProviderValidateResponse{
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)
468 *reply = ResourceProviderValidateResourceResponse{
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),
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{
491 Error: plugin.NewBasicError(err),
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{
502 Error: plugin.NewBasicError(err),
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{
513 Error: plugin.NewBasicError(err),
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{
524 Error: plugin.NewBasicError(err),
529 func (s *ResourceProviderServer) Resources(
531 result *[]terraform.ResourceType) error {
532 *result = s.Provider.Resources()
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)
544 *reply = ResourceProviderValidateResourceResponse{
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{
557 Error: plugin.NewBasicError(err),
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{
568 Error: plugin.NewBasicError(err),
573 func (s *ResourceProviderServer) DataSources(
575 result *[]terraform.DataSource) error {
576 *result = s.Provider.DataSources()