Commit a8b056e9 authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

packer/rpc: builds

parent bd6fbc05
...@@ -9,16 +9,14 @@ import ( ...@@ -9,16 +9,14 @@ import (
// over an RPC connection. // over an RPC connection.
type build struct { type build struct {
client *rpc.Client client *rpc.Client
mux *MuxConn
} }
// BuildServer wraps a packer.Build implementation and makes it exportable // BuildServer wraps a packer.Build implementation and makes it exportable
// as part of a Golang RPC server. // as part of a Golang RPC server.
type BuildServer struct { type BuildServer struct {
build packer.Build build packer.Build
} mux *MuxConn
type BuildRunArgs struct {
UiRPCAddress string
} }
type BuildPrepareResponse struct { type BuildPrepareResponse struct {
...@@ -27,7 +25,7 @@ type BuildPrepareResponse struct { ...@@ -27,7 +25,7 @@ type BuildPrepareResponse struct {
} }
func Build(client *rpc.Client) *build { func Build(client *rpc.Client) *build {
return &build{client} return &build{client: client}
} }
func (b *build) Name() (result string) { func (b *build) Name() (result string) {
...@@ -45,25 +43,25 @@ func (b *build) Prepare(v map[string]string) ([]string, error) { ...@@ -45,25 +43,25 @@ func (b *build) Prepare(v map[string]string) ([]string, error) {
} }
func (b *build) Run(ui packer.Ui, cache packer.Cache) ([]packer.Artifact, error) { func (b *build) Run(ui packer.Ui, cache packer.Cache) ([]packer.Artifact, error) {
// Create and start the server for the UI nextId := b.mux.NextId()
server := rpc.NewServer() server := NewServerWithMux(b.mux, nextId)
RegisterCache(server, cache) server.RegisterCache(cache)
RegisterUi(server, ui) server.RegisterUi(ui)
args := &BuildRunArgs{serveSingleConn(server)} go server.Serve()
var result []string var result []uint32
if err := b.client.Call("Build.Run", args, &result); err != nil { if err := b.client.Call("Build.Run", nextId, &result); err != nil {
return nil, err return nil, err
} }
artifacts := make([]packer.Artifact, len(result)) artifacts := make([]packer.Artifact, len(result))
for i, addr := range result { for i, streamId := range result {
client, err := rpcDial(addr) client, err := NewClientWithMux(b.mux, streamId)
if err != nil { if err != nil {
return nil, err return nil, err
} }
artifacts[i] = Artifact(client) artifacts[i] = client.Artifact()
} }
return artifacts, nil return artifacts, nil
...@@ -101,23 +99,26 @@ func (b *BuildServer) Prepare(v map[string]string, resp *BuildPrepareResponse) e ...@@ -101,23 +99,26 @@ func (b *BuildServer) Prepare(v map[string]string, resp *BuildPrepareResponse) e
return nil return nil
} }
func (b *BuildServer) Run(args *BuildRunArgs, reply *[]string) error { func (b *BuildServer) Run(streamId uint32, reply *[]uint32) error {
client, err := rpcDial(args.UiRPCAddress) client, err := NewClientWithMux(b.mux, streamId)
if err != nil { if err != nil {
return err return NewBasicError(err)
} }
defer client.Close()
ui := &Ui{client: client} artifacts, err := b.build.Run(client.Ui(), client.Cache())
artifacts, err := b.build.Run(ui, Cache(client))
if err != nil { if err != nil {
return NewBasicError(err) return NewBasicError(err)
} }
*reply = make([]string, len(artifacts)) *reply = make([]uint32, len(artifacts))
for i, artifact := range artifacts { for i, artifact := range artifacts {
server := rpc.NewServer() streamId := b.mux.NextId()
RegisterArtifact(server, artifact) server := NewServerWithMux(b.mux, streamId)
(*reply)[i] = serveSingleConn(server) server.RegisterArtifact(artifact)
go server.Serve()
(*reply)[i] = streamId
} }
return nil return nil
......
...@@ -3,7 +3,6 @@ package rpc ...@@ -3,7 +3,6 @@ package rpc
import ( import (
"errors" "errors"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"net/rpc"
"reflect" "reflect"
"testing" "testing"
) )
...@@ -60,25 +59,13 @@ func (b *testBuild) Cancel() { ...@@ -60,25 +59,13 @@ func (b *testBuild) Cancel() {
b.cancelCalled = true b.cancelCalled = true
} }
func buildRPCClient(t *testing.T) (*testBuild, packer.Build) {
// Create the interface to test
b := new(testBuild)
// Start the server
server := rpc.NewServer()
RegisterBuild(server, b)
address := serveSingleConn(server)
// Create the client over RPC and run some methods to verify it works
client, err := rpc.Dial("tcp", address)
if err != nil {
t.Fatalf("err: %s", err)
}
return b, Build(client)
}
func TestBuild(t *testing.T) { func TestBuild(t *testing.T) {
b, bClient := buildRPCClient(t) b := new(testBuild)
client, server := testClientServer(t)
defer client.Close()
defer server.Close()
server.RegisterBuild(b)
bClient := client.Build()
// Test Name // Test Name
bClient.Name() bClient.Name()
...@@ -120,23 +107,6 @@ func TestBuild(t *testing.T) { ...@@ -120,23 +107,6 @@ func TestBuild(t *testing.T) {
t.Fatalf("bad: %#v", artifacts) t.Fatalf("bad: %#v", artifacts)
} }
// Test the UI given to run, which should be fully functional
if b.runCalled {
b.runCache.Lock("foo")
if !cache.lockCalled {
t.Fatal("lock shuld be called")
}
b.runUi.Say("format")
if !ui.sayCalled {
t.Fatal("say should be called")
}
if ui.sayMessage != "format" {
t.Fatalf("bad: %#v", ui.sayMessage)
}
}
// Test run with an error // Test run with an error
b.errRunResult = true b.errRunResult = true
_, err = bClient.Run(ui, cache) _, err = bClient.Run(ui, cache)
...@@ -164,7 +134,12 @@ func TestBuild(t *testing.T) { ...@@ -164,7 +134,12 @@ func TestBuild(t *testing.T) {
} }
func TestBuildPrepare_Warnings(t *testing.T) { func TestBuildPrepare_Warnings(t *testing.T) {
b, bClient := buildRPCClient(t) b := new(testBuild)
client, server := testClientServer(t)
defer client.Close()
defer server.Close()
server.RegisterBuild(b)
bClient := client.Build()
expected := []string{"foo"} expected := []string{"foo"}
b.prepareWarnings = expected b.prepareWarnings = expected
......
...@@ -45,6 +45,13 @@ func (c *Client) Artifact() packer.Artifact { ...@@ -45,6 +45,13 @@ func (c *Client) Artifact() packer.Artifact {
} }
} }
func (c *Client) Build() packer.Build {
return &build{
client: c.client,
mux: c.mux,
}
}
func (c *Client) Builder() packer.Builder { func (c *Client) Builder() packer.Builder {
return &builder{ return &builder{
client: c.client, client: c.client,
......
...@@ -14,7 +14,7 @@ func RegisterArtifact(s *rpc.Server, a packer.Artifact) { ...@@ -14,7 +14,7 @@ func RegisterArtifact(s *rpc.Server, a packer.Artifact) {
// Registers the appropriate endpoint on an RPC server to serve a // Registers the appropriate endpoint on an RPC server to serve a
// Packer Build. // Packer Build.
func RegisterBuild(s *rpc.Server, b packer.Build) { func RegisterBuild(s *rpc.Server, b packer.Build) {
registerComponent(s, "Build", &BuildServer{b}, false) registerComponent(s, "Build", &BuildServer{build: b}, false)
} }
// Registers the appropriate endpoint on an RPC server to serve a // Registers the appropriate endpoint on an RPC server to serve a
......
...@@ -13,6 +13,7 @@ var endpointId uint64 ...@@ -13,6 +13,7 @@ var endpointId uint64
const ( const (
DefaultArtifactEndpoint string = "Artifact" DefaultArtifactEndpoint string = "Artifact"
DefaultBuildEndpoint = "Build"
DefaultBuilderEndpoint = "Builder" DefaultBuilderEndpoint = "Builder"
DefaultCacheEndpoint = "Cache" DefaultCacheEndpoint = "Cache"
DefaultCommandEndpoint = "Command" DefaultCommandEndpoint = "Command"
...@@ -55,6 +56,13 @@ func (s *Server) RegisterArtifact(a packer.Artifact) { ...@@ -55,6 +56,13 @@ func (s *Server) RegisterArtifact(a packer.Artifact) {
}) })
} }
func (s *Server) RegisterBuild(b packer.Build) {
s.server.RegisterName(DefaultBuildEndpoint, &BuildServer{
build: b,
mux: s.mux,
})
}
func (s *Server) RegisterBuilder(b packer.Builder) { func (s *Server) RegisterBuilder(b packer.Builder) {
s.server.RegisterName(DefaultBuilderEndpoint, &BuilderServer{ s.server.RegisterName(DefaultBuilderEndpoint, &BuilderServer{
builder: b, builder: b,
......
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