Commit 5aebe7b1 authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

packer/rpc: BuilderFactory remote

parent 8a78d4d8
package rpc
import (
"github.com/mitchellh/packer/packer"
"net/rpc"
"time"
)
// An implementation of packer.BuilderFactory where the factory is actually
// executed over an RPC connection.
type BuilderFactory struct {
client *rpc.Client
}
// BuilderFactoryServer wraps a packer.BuilderFactory and makes it exportable
// as part of a Golang RPC server.
type BuilderFactoryServer struct {
bf packer.BuilderFactory
}
type BuilderFactoryCreateArgs struct {
Name string
}
func (b *BuilderFactory) CreateBuilder(name string) packer.Builder {
var reply string
b.client.Call("BuilderFactory.CreateBuilder", &BuilderFactoryCreateArgs{name}, &reply)
// TODO: error handling
client, _ := rpc.Dial("tcp", reply)
return &Builder{client}
}
func (b *BuilderFactoryServer) CreateBuilder(args *BuilderFactoryCreateArgs, reply *string) error {
// Get the actual builder response
builder := b.bf.CreateBuilder(args.Name)
// Now we wrap that back up into a server, and send it on backwards.
server := NewServer()
server.RegisterBuilder(builder)
server.Start()
// Start a timer where we'll quit the server after some number of seconds.
go func() {
time.Sleep(30 * time.Second)
server.Stop()
}()
// Set the reply to the address of the sever
*reply = server.Address()
return nil
}
package rpc
import (
"cgl.tideland.biz/asserts"
"github.com/mitchellh/packer/packer"
"net/rpc"
"testing"
)
type testBuilderFactory struct {
createCalled bool
createName string
}
func (b *testBuilderFactory) CreateBuilder(name string) packer.Builder {
b.createCalled = true
b.createName = name
return &testBuilder{}
}
func TestBuilderFactoryRPC(t *testing.T) {
assert := asserts.NewTestingAsserts(t, true)
// Create the interface to test
b := new(testBuilderFactory)
// Start the server
server := NewServer()
server.RegisterBuilderFactory(b)
server.Start()
defer server.Stop()
// Create the client over RPC and run some methods to verify it works
client, err := rpc.Dial("tcp", server.Address())
assert.Nil(err, "should be able to connect")
// Test Create
name := "foo"
bClient := &BuilderFactory{client}
_ = bClient.CreateBuilder(name)
assert.True(b.createCalled, "create should be called")
assert.Equal(b.createName, "foo", "name should be foo")
}
func TestBuilderFactory_ImplementsBuilderFactory(t *testing.T) {
assert := asserts.NewTestingAsserts(t, true)
var realVar packer.BuilderFactory
b := &BuilderFactory{nil}
assert.Implementor(b, &realVar, "should be a BuilderFactory")
}
...@@ -37,6 +37,10 @@ func (s *Server) RegisterBuilder(b packer.Builder) { ...@@ -37,6 +37,10 @@ func (s *Server) RegisterBuilder(b packer.Builder) {
s.server.RegisterName("Builder", &BuilderServer{b}) s.server.RegisterName("Builder", &BuilderServer{b})
} }
func (s *Server) RegisterBuilderFactory(b packer.BuilderFactory) {
s.server.RegisterName("BuilderFactory", &BuilderFactoryServer{b})
}
func (s *Server) RegisterUi(ui packer.Ui) { func (s *Server) RegisterUi(ui packer.Ui) {
s.server.RegisterName("Ui", &UiServer{ui}) s.server.RegisterName("Ui", &UiServer{ui})
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment