terraform/plugin/resource_provisioner.go

183 lines
4.1 KiB
Go
Raw Normal View History

package plugin
2014-07-09 20:13:05 +02:00
import (
"net/rpc"
2014-07-10 01:54:34 +02:00
"github.com/hashicorp/go-plugin"
"github.com/hashicorp/terraform/configs/configschema"
2014-07-10 01:54:34 +02:00
"github.com/hashicorp/terraform/terraform"
2014-07-09 20:13:05 +02:00
)
// ResourceProvisionerPlugin is the plugin.Plugin implementation.
type ResourceProvisionerPlugin struct {
ResourceProvisioner func() terraform.ResourceProvisioner
}
func (p *ResourceProvisionerPlugin) Server(b *plugin.MuxBroker) (interface{}, error) {
return &ResourceProvisionerServer{
Broker: b,
Provisioner: p.ResourceProvisioner(),
}, nil
}
func (p *ResourceProvisionerPlugin) Client(
b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) {
return &ResourceProvisioner{Broker: b, Client: c}, nil
}
2014-07-09 20:13:05 +02:00
// ResourceProvisioner is an implementation of terraform.ResourceProvisioner
// that communicates over RPC.
type ResourceProvisioner struct {
Broker *plugin.MuxBroker
2014-07-09 20:13:05 +02:00
Client *rpc.Client
}
func (p *ResourceProvisioner) GetConfigSchema() (*configschema.Block, error) {
panic("not implemented")
return nil, nil
}
2014-07-09 20:13:05 +02:00
func (p *ResourceProvisioner) Validate(c *terraform.ResourceConfig) ([]string, []error) {
var resp ResourceProvisionerValidateResponse
args := ResourceProvisionerValidateArgs{
Config: c,
}
err := p.Client.Call("Plugin.Validate", &args, &resp)
2014-07-09 20:13:05 +02:00
if err != nil {
return nil, []error{err}
}
var errs []error
if len(resp.Errors) > 0 {
errs = make([]error, len(resp.Errors))
for i, err := range resp.Errors {
errs[i] = err
}
}
return resp.Warnings, errs
}
func (p *ResourceProvisioner) Apply(
2014-10-04 18:54:03 +02:00
output terraform.UIOutput,
2014-09-17 01:48:33 +02:00
s *terraform.InstanceState,
2014-07-22 19:36:37 +02:00
c *terraform.ResourceConfig) error {
2014-10-04 18:54:03 +02:00
id := p.Broker.NextId()
go p.Broker.AcceptAndServe(id, &UIOutputServer{
2014-10-04 18:54:03 +02:00
UIOutput: output,
})
2014-07-09 20:13:05 +02:00
var resp ResourceProvisionerApplyResponse
args := &ResourceProvisionerApplyArgs{
2014-10-04 18:54:03 +02:00
OutputId: id,
State: s,
Config: c,
2014-07-09 20:13:05 +02:00
}
err := p.Client.Call("Plugin.Apply", args, &resp)
2014-07-09 20:13:05 +02:00
if err != nil {
2014-07-22 19:36:37 +02:00
return err
2014-07-09 20:13:05 +02:00
}
if resp.Error != nil {
err = resp.Error
}
2014-07-22 19:36:37 +02:00
return err
2014-07-09 20:13:05 +02:00
}
func (p *ResourceProvisioner) Stop() error {
var resp ResourceProvisionerStopResponse
err := p.Client.Call("Plugin.Stop", new(interface{}), &resp)
if err != nil {
return err
}
if resp.Error != nil {
err = resp.Error
}
return err
}
func (p *ResourceProvisioner) Close() error {
return p.Client.Close()
}
2014-07-09 20:13:05 +02:00
type ResourceProvisionerValidateArgs struct {
Config *terraform.ResourceConfig
}
type ResourceProvisionerValidateResponse struct {
Warnings []string
Errors []*plugin.BasicError
2014-07-09 20:13:05 +02:00
}
type ResourceProvisionerApplyArgs struct {
2014-10-04 18:54:03 +02:00
OutputId uint32
State *terraform.InstanceState
Config *terraform.ResourceConfig
2014-07-09 20:13:05 +02:00
}
type ResourceProvisionerApplyResponse struct {
Error *plugin.BasicError
2014-07-09 20:13:05 +02:00
}
type ResourceProvisionerStopResponse struct {
Error *plugin.BasicError
}
2014-07-09 20:13:05 +02:00
// ResourceProvisionerServer is a net/rpc compatible structure for serving
// a ResourceProvisioner. This should not be used directly.
type ResourceProvisionerServer struct {
Broker *plugin.MuxBroker
2014-07-09 20:13:05 +02:00
Provisioner terraform.ResourceProvisioner
}
func (s *ResourceProvisionerServer) Apply(
args *ResourceProvisionerApplyArgs,
result *ResourceProvisionerApplyResponse) error {
2014-10-04 18:54:03 +02:00
conn, err := s.Broker.Dial(args.OutputId)
if err != nil {
*result = ResourceProvisionerApplyResponse{
Error: plugin.NewBasicError(err),
2014-10-04 18:54:03 +02:00
}
return nil
}
client := rpc.NewClient(conn)
defer client.Close()
output := &UIOutput{Client: client}
2014-10-04 18:54:03 +02:00
err = s.Provisioner.Apply(output, args.State, args.Config)
2014-07-09 20:13:05 +02:00
*result = ResourceProvisionerApplyResponse{
Error: plugin.NewBasicError(err),
2014-07-09 20:13:05 +02:00
}
return nil
}
func (s *ResourceProvisionerServer) Validate(
args *ResourceProvisionerValidateArgs,
reply *ResourceProvisionerValidateResponse) error {
warns, errs := s.Provisioner.Validate(args.Config)
berrs := make([]*plugin.BasicError, len(errs))
2014-07-09 20:13:05 +02:00
for i, err := range errs {
berrs[i] = plugin.NewBasicError(err)
2014-07-09 20:13:05 +02:00
}
*reply = ResourceProvisionerValidateResponse{
Warnings: warns,
Errors: berrs,
}
return nil
}
func (s *ResourceProvisionerServer) Stop(
_ interface{},
reply *ResourceProvisionerStopResponse) error {
err := s.Provisioner.Stop()
*reply = ResourceProvisionerStopResponse{
Error: plugin.NewBasicError(err),
}
return nil
}