github.com/pdecat/terraform@v0.11.9-beta1/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) Stop() error { 81 var resp ResourceProvisionerStopResponse 82 err := p.Client.Call("Plugin.Stop", new(interface{}), &resp) 83 if err != nil { 84 return err 85 } 86 if resp.Error != nil { 87 err = resp.Error 88 } 89 90 return err 91 } 92 93 func (p *ResourceProvisioner) Close() error { 94 return p.Client.Close() 95 } 96 97 type ResourceProvisionerValidateArgs struct { 98 Config *terraform.ResourceConfig 99 } 100 101 type ResourceProvisionerValidateResponse struct { 102 Warnings []string 103 Errors []*plugin.BasicError 104 } 105 106 type ResourceProvisionerApplyArgs struct { 107 OutputId uint32 108 State *terraform.InstanceState 109 Config *terraform.ResourceConfig 110 } 111 112 type ResourceProvisionerApplyResponse struct { 113 Error *plugin.BasicError 114 } 115 116 type ResourceProvisionerStopResponse struct { 117 Error *plugin.BasicError 118 } 119 120 // ResourceProvisionerServer is a net/rpc compatible structure for serving 121 // a ResourceProvisioner. This should not be used directly. 122 type ResourceProvisionerServer struct { 123 Broker *plugin.MuxBroker 124 Provisioner terraform.ResourceProvisioner 125 } 126 127 func (s *ResourceProvisionerServer) Apply( 128 args *ResourceProvisionerApplyArgs, 129 result *ResourceProvisionerApplyResponse) error { 130 conn, err := s.Broker.Dial(args.OutputId) 131 if err != nil { 132 *result = ResourceProvisionerApplyResponse{ 133 Error: plugin.NewBasicError(err), 134 } 135 return nil 136 } 137 client := rpc.NewClient(conn) 138 defer client.Close() 139 140 output := &UIOutput{Client: client} 141 142 err = s.Provisioner.Apply(output, args.State, args.Config) 143 *result = ResourceProvisionerApplyResponse{ 144 Error: plugin.NewBasicError(err), 145 } 146 return nil 147 } 148 149 func (s *ResourceProvisionerServer) Validate( 150 args *ResourceProvisionerValidateArgs, 151 reply *ResourceProvisionerValidateResponse) error { 152 warns, errs := s.Provisioner.Validate(args.Config) 153 berrs := make([]*plugin.BasicError, len(errs)) 154 for i, err := range errs { 155 berrs[i] = plugin.NewBasicError(err) 156 } 157 *reply = ResourceProvisionerValidateResponse{ 158 Warnings: warns, 159 Errors: berrs, 160 } 161 return nil 162 } 163 164 func (s *ResourceProvisionerServer) Stop( 165 _ interface{}, 166 reply *ResourceProvisionerStopResponse) error { 167 err := s.Provisioner.Stop() 168 *reply = ResourceProvisionerStopResponse{ 169 Error: plugin.NewBasicError(err), 170 } 171 172 return nil 173 }