github.com/subuk/terraform@v0.6.14-0.20160317140351-de1567c2e732/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 func (p *ResourceProvisioner) Close() error { 67 return p.Client.Close() 68 } 69 70 type ResourceProvisionerValidateArgs struct { 71 Config *terraform.ResourceConfig 72 } 73 74 type ResourceProvisionerValidateResponse struct { 75 Warnings []string 76 Errors []*BasicError 77 } 78 79 type ResourceProvisionerApplyArgs struct { 80 OutputId uint32 81 State *terraform.InstanceState 82 Config *terraform.ResourceConfig 83 } 84 85 type ResourceProvisionerApplyResponse struct { 86 Error *BasicError 87 } 88 89 // ResourceProvisionerServer is a net/rpc compatible structure for serving 90 // a ResourceProvisioner. This should not be used directly. 91 type ResourceProvisionerServer struct { 92 Broker *muxBroker 93 Provisioner terraform.ResourceProvisioner 94 } 95 96 func (s *ResourceProvisionerServer) Apply( 97 args *ResourceProvisionerApplyArgs, 98 result *ResourceProvisionerApplyResponse) error { 99 conn, err := s.Broker.Dial(args.OutputId) 100 if err != nil { 101 *result = ResourceProvisionerApplyResponse{ 102 Error: NewBasicError(err), 103 } 104 return nil 105 } 106 client := rpc.NewClient(conn) 107 defer client.Close() 108 109 output := &UIOutput{ 110 Client: client, 111 Name: "UIOutput", 112 } 113 114 err = s.Provisioner.Apply(output, args.State, args.Config) 115 *result = ResourceProvisionerApplyResponse{ 116 Error: NewBasicError(err), 117 } 118 return nil 119 } 120 121 func (s *ResourceProvisionerServer) Validate( 122 args *ResourceProvisionerValidateArgs, 123 reply *ResourceProvisionerValidateResponse) error { 124 warns, errs := s.Provisioner.Validate(args.Config) 125 berrs := make([]*BasicError, len(errs)) 126 for i, err := range errs { 127 berrs[i] = NewBasicError(err) 128 } 129 *reply = ResourceProvisionerValidateResponse{ 130 Warnings: warns, 131 Errors: berrs, 132 } 133 return nil 134 }