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 }