github.com/hobbeswalsh/terraform@v0.3.7-0.20150619183303-ad17cf55a0fa/rpc/resource_provisioner.go (about)

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