rpc: ResourceProvisioner support on client/server

This commit is contained in:
Mitchell Hashimoto 2014-09-28 10:55:12 -07:00
parent 0281c1108e
commit bc6db2bd1b
4 changed files with 88 additions and 3 deletions

View File

@ -81,3 +81,21 @@ func (c *Client) ResourceProvider() (terraform.ResourceProvider, error) {
Name: "ResourceProvider",
}, nil
}
func (c *Client) ResourceProvisioner() (terraform.ResourceProvisioner, error) {
var id uint32
if err := c.control.Call(
"Dispenser.ResourceProvisioner", new(interface{}), &id); err != nil {
return nil, err
}
conn, err := c.broker.Dial(id)
if err != nil {
return nil, err
}
return &ResourceProvisioner{
Client: rpc.NewClient(conn),
Name: "ResourceProvisioner",
}, nil
}

View File

@ -40,3 +40,37 @@ func TestClient_ResourceProvider(t *testing.T) {
t.Fatalf("bad: %#v", e)
}
}
func TestClient_ResourceProvisioner(t *testing.T) {
clientConn, serverConn := testConn(t)
p := new(terraform.MockResourceProvisioner)
server := &Server{ProvisionerFunc: testProvisionerFixed(p)}
go server.ServeConn(serverConn)
client, err := NewClient(clientConn)
if err != nil {
t.Fatalf("err: %s", err)
}
defer client.Close()
provisioner, err := client.ResourceProvisioner()
if err != nil {
t.Fatalf("err: %s", err)
}
// Apply
state := &terraform.InstanceState{}
conf := &terraform.ResourceConfig{}
err = provisioner.Apply(state, conf)
if !p.ApplyCalled {
t.Fatal("apply should be called")
}
if !reflect.DeepEqual(p.ApplyConfig, conf) {
t.Fatalf("bad: %#v", p.ApplyConfig)
}
if err != nil {
t.Fatalf("bad: %#v", err)
}
}

View File

@ -51,3 +51,9 @@ func testProviderFixed(p terraform.ResourceProvider) ProviderFunc {
return p
}
}
func testProvisionerFixed(p terraform.ResourceProvisioner) ProvisionerFunc {
return func() terraform.ResourceProvisioner {
return p
}
}

View File

@ -13,13 +13,18 @@ import (
// Server listens for network connections and then dispenses interface
// implementations for Terraform over net/rpc.
type Server struct {
ProviderFunc ProviderFunc
ProviderFunc ProviderFunc
ProvisionerFunc ProvisionerFunc
}
// ProviderFunc creates terraform.ResourceProviders when they're requested
// from the server.
type ProviderFunc func() terraform.ResourceProvider
// ProvisionerFunc creates terraform.ResourceProvisioners when they're requested
// from the server.
type ProvisionerFunc func() terraform.ResourceProvisioner
// Accept accepts connections on a listener and serves requests for
// each incoming connection. Accept blocks; the caller typically invokes
// it in a go statement.
@ -63,7 +68,8 @@ func (s *Server) ServeConn(conn io.ReadWriteCloser) {
// connection.
server := rpc.NewServer()
server.RegisterName("Dispenser", &dispenseServer{
ProviderFunc: s.ProviderFunc,
ProviderFunc: s.ProviderFunc,
ProvisionerFunc: s.ProvisionerFunc,
broker: broker,
})
@ -72,7 +78,8 @@ func (s *Server) ServeConn(conn io.ReadWriteCloser) {
// dispenseServer dispenses variousinterface implementations for Terraform.
type dispenseServer struct {
ProviderFunc ProviderFunc
ProviderFunc ProviderFunc
ProvisionerFunc ProvisionerFunc
broker *muxBroker
}
@ -97,6 +104,26 @@ func (d *dispenseServer) ResourceProvider(
return nil
}
func (d *dispenseServer) ResourceProvisioner(
args interface{}, response *uint32) error {
id := d.broker.NextId()
*response = id
go func() {
conn, err := d.broker.Accept(id)
if err != nil {
log.Printf("[ERR] Plugin dispense: %s", err)
return
}
d.serve(conn, "ResourceProvisioner", &ResourceProvisionerServer{
Provisioner: d.ProvisionerFunc(),
})
}()
return nil
}
func (d *dispenseServer) serve(conn io.ReadWriteCloser, name string, v interface{}) {
server := rpc.NewServer()
if err := server.RegisterName(name, v); err != nil {