Commit 53c3d330 authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

packer/rpc: Support Artifacts

parent 55d9cd21
...@@ -19,10 +19,11 @@ func (tb *TestBuilder) Prepare(config interface{}) error { ...@@ -19,10 +19,11 @@ func (tb *TestBuilder) Prepare(config interface{}) error {
return nil return nil
} }
func (tb *TestBuilder) Run(ui Ui, h Hook) { func (tb *TestBuilder) Run(ui Ui, h Hook) Artifact {
tb.runCalled = true tb.runCalled = true
tb.runHook = h tb.runHook = h
tb.runUi = ui tb.runUi = ui
return nil
} }
func testBuild() Build { func testBuild() Build {
......
...@@ -11,5 +11,5 @@ package packer ...@@ -11,5 +11,5 @@ package packer
// Run is where the actual build should take place. It takes a Build and a Ui. // Run is where the actual build should take place. It takes a Build and a Ui.
type Builder interface { type Builder interface {
Prepare(config interface{}) error Prepare(config interface{}) error
Run(ui Ui, hook Hook) Run(ui Ui, hook Hook) Artifact
} }
package rpc
import (
"github.com/mitchellh/packer/packer"
"net/rpc"
)
// An implementation of packer.Artifact where the artifact is actually
// available over an RPC connection.
type artifact struct {
client *rpc.Client
}
// ArtifactServer wraps a packer.Artifact implementation and makes it
// exportable as part of a Golang RPC server.
type ArtifactServer struct {
artifact packer.Artifact
}
func Artifact(client *rpc.Client) *artifact {
return &artifact{client}
}
func (a *artifact) BuilderId() (result string) {
a.client.Call("Artifact.BuilderId", new(interface{}), &result)
return
}
func (a *artifact) Files() (result []string) {
a.client.Call("Artifact.Files", new(interface{}), &result)
return
}
func (a *artifact) Id() (result string) {
a.client.Call("Artifact.Id", new(interface{}), &result)
return
}
func (a *artifact) String() (result string) {
a.client.Call("Artifact.String", new(interface{}), &result)
return
}
func (s *ArtifactServer) BuilderId(args *interface{}, reply *string) error {
*reply = s.artifact.BuilderId()
return nil
}
func (s *ArtifactServer) Files(args *interface{}, reply *[]string) error {
*reply = s.artifact.Files()
return nil
}
func (s *ArtifactServer) Id(args *interface{}, reply *string) error {
*reply = s.artifact.Id()
return nil
}
func (s *ArtifactServer) String(args *interface{}, reply *string) error {
*reply = s.artifact.String()
return nil
}
package rpc
import (
"cgl.tideland.biz/asserts"
"github.com/mitchellh/packer/packer"
"net/rpc"
"testing"
)
type testArtifact struct{}
func (testArtifact) BuilderId() string {
return "bid"
}
func (testArtifact) Files() []string {
return []string{"a", "b"}
}
func (testArtifact) Id() string {
return "id"
}
func (testArtifact) String() string {
return "string"
}
func TestArtifactRPC(t *testing.T) {
assert := asserts.NewTestingAsserts(t, true)
// Create the interface to test
a := new(testArtifact)
// Start the server
server := rpc.NewServer()
RegisterArtifact(server, a)
address := serveSingleConn(server)
// Create the client over RPC and run some methods to verify it works
client, err := rpc.Dial("tcp", address)
assert.Nil(err, "should be able to connect")
aClient := Artifact(client)
// Test
assert.Equal(aClient.BuilderId(), "bid", "should have correct builder ID")
assert.Equal(aClient.Files(), []string{"a", "b"}, "should have correct builder ID")
assert.Equal(aClient.Id(), "id", "should have correct builder ID")
assert.Equal(aClient.String(), "string", "should have correct builder ID")
}
func TestArtifact_Implements(t *testing.T) {
assert := asserts.NewTestingAsserts(t, true)
var r packer.Artifact
a := Artifact(nil)
assert.Implementor(a, &r, "should be an Artifact")
}
...@@ -38,7 +38,7 @@ func (b *builder) Prepare(config interface{}) (err error) { ...@@ -38,7 +38,7 @@ func (b *builder) Prepare(config interface{}) (err error) {
return return
} }
func (b *builder) Run(ui packer.Ui, hook packer.Hook) { func (b *builder) Run(ui packer.Ui, hook packer.Hook) packer.Artifact {
// Create and start the server for the Build and UI // Create and start the server for the Build and UI
// TODO: Error handling // TODO: Error handling
server := rpc.NewServer() server := rpc.NewServer()
...@@ -47,6 +47,9 @@ func (b *builder) Run(ui packer.Ui, hook packer.Hook) { ...@@ -47,6 +47,9 @@ func (b *builder) Run(ui packer.Ui, hook packer.Hook) {
args := &BuilderRunArgs{serveSingleConn(server)} args := &BuilderRunArgs{serveSingleConn(server)}
b.client.Call("Builder.Run", args, new(interface{})) b.client.Call("Builder.Run", args, new(interface{}))
// TODO: artifact
return nil
} }
func (b *BuilderServer) Prepare(args *BuilderPrepareArgs, reply *error) error { func (b *BuilderServer) Prepare(args *BuilderPrepareArgs, reply *error) error {
......
...@@ -21,10 +21,11 @@ func (b *testBuilder) Prepare(config interface{}) error { ...@@ -21,10 +21,11 @@ func (b *testBuilder) Prepare(config interface{}) error {
return nil return nil
} }
func (b *testBuilder) Run(ui packer.Ui, hook packer.Hook) { func (b *testBuilder) Run(ui packer.Ui, hook packer.Hook) packer.Artifact {
b.runCalled = true b.runCalled = true
b.runHook = hook b.runHook = hook
b.runUi = ui b.runUi = ui
return nil
} }
func TestBuilderRPC(t *testing.T) { func TestBuilderRPC(t *testing.T) {
......
...@@ -5,6 +5,12 @@ import ( ...@@ -5,6 +5,12 @@ import (
"net/rpc" "net/rpc"
) )
// Registers the appropriate endpoint on an RPC server to serve an
// Artifact.
func RegisterArtifact(s *rpc.Server, a packer.Artifact) {
s.RegisterName("Artifact", &ArtifactServer{a})
}
// 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) {
......
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