6 "github.com/hashicorp/go-plugin"
7 "github.com/hashicorp/terraform/terraform"
10 // ResourceProvisionerPlugin is the plugin.Plugin implementation.
11 type ResourceProvisionerPlugin struct {
12 F func() terraform.ResourceProvisioner
15 func (p *ResourceProvisionerPlugin) Server(b *plugin.MuxBroker) (interface{}, error) {
16 return &ResourceProvisionerServer{Broker: b, Provisioner: p.F()}, nil
19 func (p *ResourceProvisionerPlugin) Client(
20 b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) {
21 return &ResourceProvisioner{Broker: b, Client: c}, nil
24 // ResourceProvisioner is an implementation of terraform.ResourceProvisioner
25 // that communicates over RPC.
26 type ResourceProvisioner struct {
27 Broker *plugin.MuxBroker
31 func (p *ResourceProvisioner) Validate(c *terraform.ResourceConfig) ([]string, []error) {
32 var resp ResourceProvisionerValidateResponse
33 args := ResourceProvisionerValidateArgs{
37 err := p.Client.Call("Plugin.Validate", &args, &resp)
39 return nil, []error{err}
43 if len(resp.Errors) > 0 {
44 errs = make([]error, len(resp.Errors))
45 for i, err := range resp.Errors {
50 return resp.Warnings, errs
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{
62 var resp ResourceProvisionerApplyResponse
63 args := &ResourceProvisionerApplyArgs{
69 err := p.Client.Call("Plugin.Apply", args, &resp)
73 if resp.Error != nil {
80 func (p *ResourceProvisioner) Stop() error {
81 var resp ResourceProvisionerStopResponse
82 err := p.Client.Call("Plugin.Stop", new(interface{}), &resp)
86 if resp.Error != nil {
93 func (p *ResourceProvisioner) Close() error {
94 return p.Client.Close()
97 type ResourceProvisionerValidateArgs struct {
98 Config *terraform.ResourceConfig
101 type ResourceProvisionerValidateResponse struct {
103 Errors []*plugin.BasicError
106 type ResourceProvisionerApplyArgs struct {
108 State *terraform.InstanceState
109 Config *terraform.ResourceConfig
112 type ResourceProvisionerApplyResponse struct {
113 Error *plugin.BasicError
116 type ResourceProvisionerStopResponse struct {
117 Error *plugin.BasicError
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
127 func (s *ResourceProvisionerServer) Apply(
128 args *ResourceProvisionerApplyArgs,
129 result *ResourceProvisionerApplyResponse) error {
130 conn, err := s.Broker.Dial(args.OutputId)
132 *result = ResourceProvisionerApplyResponse{
133 Error: plugin.NewBasicError(err),
137 client := rpc.NewClient(conn)
140 output := &UIOutput{Client: client}
142 err = s.Provisioner.Apply(output, args.State, args.Config)
143 *result = ResourceProvisionerApplyResponse{
144 Error: plugin.NewBasicError(err),
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)
157 *reply = ResourceProvisionerValidateResponse{
164 func (s *ResourceProvisionerServer) Stop(
166 reply *ResourceProvisionerStopResponse) error {
167 err := s.Provisioner.Stop()
168 *reply = ResourceProvisionerStopResponse{
169 Error: plugin.NewBasicError(err),