Commit 41a7fd45 authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

packer: Return artifact from build

parent cf6d2218
...@@ -7,7 +7,7 @@ import "log" ...@@ -7,7 +7,7 @@ import "log"
type Build interface { type Build interface {
Name() string Name() string
Prepare() error Prepare() error
Run(Ui) Run(Ui) Artifact
} }
// A build struct represents a single build job, the result of which should // A build struct represents a single build job, the result of which should
...@@ -41,11 +41,11 @@ func (b *coreBuild) Prepare() (err error) { ...@@ -41,11 +41,11 @@ func (b *coreBuild) Prepare() (err error) {
} }
// Runs the actual build. Prepare must be called prior to running this. // Runs the actual build. Prepare must be called prior to running this.
func (b *coreBuild) Run(ui Ui) { func (b *coreBuild) Run(ui Ui) Artifact {
if !b.prepareCalled { if !b.prepareCalled {
panic("Prepare must be called first") panic("Prepare must be called first")
} }
hook := &DispatchHook{b.hooks} hook := &DispatchHook{b.hooks}
b.builder.Run(ui, hook) return b.builder.Run(ui, hook)
} }
...@@ -7,7 +7,7 @@ import ( ...@@ -7,7 +7,7 @@ import (
// An implementation of packer.Build where the build is actually executed // An implementation of packer.Build where the build is actually executed
// over an RPC connection. // over an RPC connection.
type Build struct { type build struct {
client *rpc.Client client *rpc.Client
} }
...@@ -23,23 +23,38 @@ type BuildRunArgs struct { ...@@ -23,23 +23,38 @@ type BuildRunArgs struct {
UiRPCAddress string UiRPCAddress string
} }
func (b *Build) Name() (result string) { func Build(client *rpc.Client) *build {
return &build{client}
}
func (b *build) Name() (result string) {
b.client.Call("Build.Name", new(interface{}), &result) b.client.Call("Build.Name", new(interface{}), &result)
return return
} }
func (b *Build) Prepare() (err error) { func (b *build) Prepare() (err error) {
b.client.Call("Build.Prepare", new(interface{}), &err) b.client.Call("Build.Prepare", new(interface{}), &err)
return return
} }
func (b *Build) Run(ui packer.Ui) { func (b *build) Run(ui packer.Ui) packer.Artifact {
// Create and start the server for the UI // Create and start the server for the UI
// TODO: Error handling // TODO: Error handling
server := rpc.NewServer() server := rpc.NewServer()
RegisterUi(server, ui) RegisterUi(server, ui)
args := &BuildRunArgs{serveSingleConn(server)} args := &BuildRunArgs{serveSingleConn(server)}
b.client.Call("Build.Run", args, new(interface{}))
var reply string
if err := b.client.Call("Build.Run", args, &reply); err != nil {
panic(err)
}
client, err := rpc.Dial("tcp", reply)
if err != nil {
panic(err)
}
return Artifact(client)
} }
func (b *BuildServer) Name(args *interface{}, reply *string) error { func (b *BuildServer) Name(args *interface{}, reply *string) error {
...@@ -52,14 +67,18 @@ func (b *BuildServer) Prepare(args *BuildPrepareArgs, reply *error) error { ...@@ -52,14 +67,18 @@ func (b *BuildServer) Prepare(args *BuildPrepareArgs, reply *error) error {
return nil return nil
} }
func (b *BuildServer) Run(args *BuildRunArgs, reply *interface{}) error { func (b *BuildServer) Run(args *BuildRunArgs, reply *string) error {
client, err := rpc.Dial("tcp", args.UiRPCAddress) client, err := rpc.Dial("tcp", args.UiRPCAddress)
if err != nil { if err != nil {
return err return err
} }
b.build.Run(&Ui{client}) artifact := b.build.Run(&Ui{client})
// Wrap the artifact
server := rpc.NewServer()
RegisterArtifact(server, artifact)
*reply = nil *reply = serveSingleConn(server)
return nil return nil
} }
...@@ -7,6 +7,8 @@ import ( ...@@ -7,6 +7,8 @@ import (
"testing" "testing"
) )
var testBuildArtifact = &testArtifact{}
type testBuild struct { type testBuild struct {
nameCalled bool nameCalled bool
prepareCalled bool prepareCalled bool
...@@ -24,32 +26,27 @@ func (b *testBuild) Prepare() error { ...@@ -24,32 +26,27 @@ func (b *testBuild) Prepare() error {
return nil return nil
} }
func (b *testBuild) Run(ui packer.Ui) { func (b *testBuild) Run(ui packer.Ui) packer.Artifact {
b.runCalled = true b.runCalled = true
b.runUi = ui b.runUi = ui
return testBuildArtifact
} }
func TestBuildRPC(t *testing.T) { func TestBuildRPC(t *testing.T) {
assert := asserts.NewTestingAsserts(t, true) assert := asserts.NewTestingAsserts(t, true)
// Create the UI to test // Create the interface to test
b := new(testBuild) b := new(testBuild)
bServer := &BuildServer{b}
// Start the RPC server // Start the server
readyChan := make(chan int) server := rpc.NewServer()
stopChan := make(chan int) RegisterBuild(server, b)
defer func() { stopChan <- 1 }() address := serveSingleConn(server)
go testRPCServer(":1234", "Build", bServer, readyChan, stopChan)
<-readyChan
// Create the client over RPC and run some methods to verify it works // Create the client over RPC and run some methods to verify it works
client, err := rpc.Dial("tcp", ":1234") client, err := rpc.Dial("tcp", address)
if err != nil { assert.Nil(err, "should be able to connect")
panic(err) bClient := Build(client)
}
bClient := &Build{client}
// Test Name // Test Name
bClient.Name() bClient.Name()
...@@ -76,7 +73,7 @@ func TestBuild_ImplementsBuild(t *testing.T) { ...@@ -76,7 +73,7 @@ func TestBuild_ImplementsBuild(t *testing.T) {
assert := asserts.NewTestingAsserts(t, true) assert := asserts.NewTestingAsserts(t, true)
var realBuild packer.Build var realBuild packer.Build
b := &Build{nil} b := Build(nil)
assert.Implementor(b, &realBuild, "should be a Build") assert.Implementor(b, &realBuild, "should be a Build")
} }
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