6 "github.com/hashicorp/go-plugin"
7 "github.com/hashicorp/terraform/configs/configschema"
8 "github.com/hashicorp/terraform/terraform"
11 // ResourceProvisionerPlugin is the plugin.Plugin implementation.
12 type ResourceProvisionerPlugin struct {
13 ResourceProvisioner func() terraform.ResourceProvisioner
16 func (p *ResourceProvisionerPlugin) Server(b *plugin.MuxBroker) (interface{}, error) {
17 return &ResourceProvisionerServer{
19 Provisioner: p.ResourceProvisioner(),
23 func (p *ResourceProvisionerPlugin) Client(
24 b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) {
25 return &ResourceProvisioner{Broker: b, Client: c}, nil
28 // ResourceProvisioner is an implementation of terraform.ResourceProvisioner
29 // that communicates over RPC.
30 type ResourceProvisioner struct {
31 Broker *plugin.MuxBroker
35 func (p *ResourceProvisioner) GetConfigSchema() (*configschema.Block, error) {
36 panic("not implemented")
40 func (p *ResourceProvisioner) Validate(c *terraform.ResourceConfig) ([]string, []error) {
41 var resp ResourceProvisionerValidateResponse
42 args := ResourceProvisionerValidateArgs{
46 err := p.Client.Call("Plugin.Validate", &args, &resp)
48 return nil, []error{err}
52 if len(resp.Errors) > 0 {
53 errs = make([]error, len(resp.Errors))
54 for i, err := range resp.Errors {
59 return resp.Warnings, errs
62 func (p *ResourceProvisioner) Apply(
63 output terraform.UIOutput,
64 s *terraform.InstanceState,
65 c *terraform.ResourceConfig) error {
66 id := p.Broker.NextId()
67 go p.Broker.AcceptAndServe(id, &UIOutputServer{
71 var resp ResourceProvisionerApplyResponse
72 args := &ResourceProvisionerApplyArgs{
78 err := p.Client.Call("Plugin.Apply", args, &resp)
82 if resp.Error != nil {
89 func (p *ResourceProvisioner) Stop() error {
90 var resp ResourceProvisionerStopResponse
91 err := p.Client.Call("Plugin.Stop", new(interface{}), &resp)
95 if resp.Error != nil {
102 func (p *ResourceProvisioner) Close() error {
103 return p.Client.Close()
106 type ResourceProvisionerValidateArgs struct {
107 Config *terraform.ResourceConfig
110 type ResourceProvisionerValidateResponse struct {
112 Errors []*plugin.BasicError
115 type ResourceProvisionerApplyArgs struct {
117 State *terraform.InstanceState
118 Config *terraform.ResourceConfig
121 type ResourceProvisionerApplyResponse struct {
122 Error *plugin.BasicError
125 type ResourceProvisionerStopResponse struct {
126 Error *plugin.BasicError
129 // ResourceProvisionerServer is a net/rpc compatible structure for serving
130 // a ResourceProvisioner. This should not be used directly.
131 type ResourceProvisionerServer struct {
132 Broker *plugin.MuxBroker
133 Provisioner terraform.ResourceProvisioner
136 func (s *ResourceProvisionerServer) Apply(
137 args *ResourceProvisionerApplyArgs,
138 result *ResourceProvisionerApplyResponse) error {
139 conn, err := s.Broker.Dial(args.OutputId)
141 *result = ResourceProvisionerApplyResponse{
142 Error: plugin.NewBasicError(err),
146 client := rpc.NewClient(conn)
149 output := &UIOutput{Client: client}
151 err = s.Provisioner.Apply(output, args.State, args.Config)
152 *result = ResourceProvisionerApplyResponse{
153 Error: plugin.NewBasicError(err),
158 func (s *ResourceProvisionerServer) Validate(
159 args *ResourceProvisionerValidateArgs,
160 reply *ResourceProvisionerValidateResponse) error {
161 warns, errs := s.Provisioner.Validate(args.Config)
162 berrs := make([]*plugin.BasicError, len(errs))
163 for i, err := range errs {
164 berrs[i] = plugin.NewBasicError(err)
166 *reply = ResourceProvisionerValidateResponse{
173 func (s *ResourceProvisionerServer) Stop(
175 reply *ResourceProvisionerStopResponse) error {
176 err := s.Provisioner.Stop()
177 *reply = ResourceProvisionerStopResponse{
178 Error: plugin.NewBasicError(err),