github.com/bendemaree/terraform@v0.5.4-0.20150613200311-f50d97d6eee6/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 }