github.com/ns1/terraform@v0.7.10-0.20161109153551-8949419bef40/plugin/resource_provisioner.go (about)

     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  // ResourceProvisionerPlugin is the plugin.Plugin implementation.
    11  type ResourceProvisionerPlugin struct {
    12  	F func() terraform.ResourceProvisioner
    13  }
    14  
    15  func (p *ResourceProvisionerPlugin) Server(b *plugin.MuxBroker) (interface{}, error) {
    16  	return &ResourceProvisionerServer{Broker: b, Provisioner: p.F()}, nil
    17  }
    18  
    19  func (p *ResourceProvisionerPlugin) Client(
    20  	b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) {
    21  	return &ResourceProvisioner{Broker: b, Client: c}, nil
    22  }
    23  
    24  // ResourceProvisioner is an implementation of terraform.ResourceProvisioner
    25  // that communicates over RPC.
    26  type ResourceProvisioner struct {
    27  	Broker *plugin.MuxBroker
    28  	Client *rpc.Client
    29  }
    30  
    31  func (p *ResourceProvisioner) Validate(c *terraform.ResourceConfig) ([]string, []error) {
    32  	var resp ResourceProvisionerValidateResponse
    33  	args := ResourceProvisionerValidateArgs{
    34  		Config: c,
    35  	}
    36  
    37  	err := p.Client.Call("Plugin.Validate", &args, &resp)
    38  	if err != nil {
    39  		return nil, []error{err}
    40  	}
    41  
    42  	var errs []error
    43  	if len(resp.Errors) > 0 {
    44  		errs = make([]error, len(resp.Errors))
    45  		for i, err := range resp.Errors {
    46  			errs[i] = err
    47  		}
    48  	}
    49  
    50  	return resp.Warnings, errs
    51  }
    52  
    53  func (p *ResourceProvisioner) Apply(
    54  	output terraform.UIOutput,
    55  	s *terraform.InstanceState,
    56  	c *terraform.ResourceConfig) error {
    57  	id := p.Broker.NextId()
    58  	go p.Broker.AcceptAndServe(id, &UIOutputServer{
    59  		UIOutput: output,
    60  	})
    61  
    62  	var resp ResourceProvisionerApplyResponse
    63  	args := &ResourceProvisionerApplyArgs{
    64  		OutputId: id,
    65  		State:    s,
    66  		Config:   c,
    67  	}
    68  
    69  	err := p.Client.Call("Plugin.Apply", args, &resp)
    70  	if err != nil {
    71  		return err
    72  	}
    73  	if resp.Error != nil {
    74  		err = resp.Error
    75  	}
    76  
    77  	return err
    78  }
    79  
    80  func (p *ResourceProvisioner) Close() error {
    81  	return p.Client.Close()
    82  }
    83  
    84  type ResourceProvisionerValidateArgs struct {
    85  	Config *terraform.ResourceConfig
    86  }
    87  
    88  type ResourceProvisionerValidateResponse struct {
    89  	Warnings []string
    90  	Errors   []*plugin.BasicError
    91  }
    92  
    93  type ResourceProvisionerApplyArgs struct {
    94  	OutputId uint32
    95  	State    *terraform.InstanceState
    96  	Config   *terraform.ResourceConfig
    97  }
    98  
    99  type ResourceProvisionerApplyResponse struct {
   100  	Error *plugin.BasicError
   101  }
   102  
   103  // ResourceProvisionerServer is a net/rpc compatible structure for serving
   104  // a ResourceProvisioner. This should not be used directly.
   105  type ResourceProvisionerServer struct {
   106  	Broker      *plugin.MuxBroker
   107  	Provisioner terraform.ResourceProvisioner
   108  }
   109  
   110  func (s *ResourceProvisionerServer) Apply(
   111  	args *ResourceProvisionerApplyArgs,
   112  	result *ResourceProvisionerApplyResponse) error {
   113  	conn, err := s.Broker.Dial(args.OutputId)
   114  	if err != nil {
   115  		*result = ResourceProvisionerApplyResponse{
   116  			Error: plugin.NewBasicError(err),
   117  		}
   118  		return nil
   119  	}
   120  	client := rpc.NewClient(conn)
   121  	defer client.Close()
   122  
   123  	output := &UIOutput{Client: client}
   124  
   125  	err = s.Provisioner.Apply(output, args.State, args.Config)
   126  	*result = ResourceProvisionerApplyResponse{
   127  		Error: plugin.NewBasicError(err),
   128  	}
   129  	return nil
   130  }
   131  
   132  func (s *ResourceProvisionerServer) Validate(
   133  	args *ResourceProvisionerValidateArgs,
   134  	reply *ResourceProvisionerValidateResponse) error {
   135  	warns, errs := s.Provisioner.Validate(args.Config)
   136  	berrs := make([]*plugin.BasicError, len(errs))
   137  	for i, err := range errs {
   138  		berrs[i] = plugin.NewBasicError(err)
   139  	}
   140  	*reply = ResourceProvisionerValidateResponse{
   141  		Warnings: warns,
   142  		Errors:   berrs,
   143  	}
   144  	return nil
   145  }