Commit 1b557d77 authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

packer/rpc: Builder.Run() no longer blocks RPC connection

parent 079d6f4d
package rpc package rpc
import ( import (
"encoding/gob"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"log"
"net"
"net/rpc" "net/rpc"
) )
...@@ -22,6 +25,11 @@ type BuilderPrepareArgs struct { ...@@ -22,6 +25,11 @@ type BuilderPrepareArgs struct {
} }
type BuilderRunArgs struct { type BuilderRunArgs struct {
RPCAddress string
ResponseAddress string
}
type BuilderRunResponse struct {
RPCAddress string RPCAddress string
} }
...@@ -45,14 +53,38 @@ func (b *builder) Run(ui packer.Ui, hook packer.Hook) packer.Artifact { ...@@ -45,14 +53,38 @@ func (b *builder) Run(ui packer.Ui, hook packer.Hook) packer.Artifact {
RegisterUi(server, ui) RegisterUi(server, ui)
RegisterHook(server, hook) RegisterHook(server, hook)
args := &BuilderRunArgs{serveSingleConn(server)} // Create a server for the response
responseL := netListenerInRange(portRangeMin, portRangeMax)
artifactAddress := make(chan string)
go func() {
defer responseL.Close()
conn, err := responseL.Accept()
if err != nil {
log.Panic(err)
}
defer conn.Close()
decoder := gob.NewDecoder(conn)
var response BuilderRunResponse
if err := decoder.Decode(&response); err != nil {
log.Panic(err)
}
artifactAddress <- response.RPCAddress
}()
args := &BuilderRunArgs{
serveSingleConn(server),
responseL.Addr().String(),
}
var reply string if err := b.client.Call("Builder.Run", args, new(interface{})); err != nil {
if err := b.client.Call("Builder.Run", args, &reply); err != nil {
panic(err) panic(err)
} }
client, err := rpc.Dial("tcp", reply) client, err := rpc.Dial("tcp", <-artifactAddress)
if err != nil { if err != nil {
panic(err) panic(err)
} }
...@@ -73,20 +105,33 @@ func (b *BuilderServer) Prepare(args *BuilderPrepareArgs, reply *error) error { ...@@ -73,20 +105,33 @@ func (b *BuilderServer) Prepare(args *BuilderPrepareArgs, reply *error) error {
return nil return nil
} }
func (b *BuilderServer) Run(args *BuilderRunArgs, reply *string) error { func (b *BuilderServer) Run(args *BuilderRunArgs, reply *interface{}) error {
client, err := rpc.Dial("tcp", args.RPCAddress) client, err := rpc.Dial("tcp", args.RPCAddress)
if err != nil { if err != nil {
return err return err
} }
hook := Hook(client) responseC, err := net.Dial("tcp", args.ResponseAddress)
ui := &Ui{client} if err != nil {
artifact := b.builder.Run(ui, hook) return err
}
// Wrap the artifact responseWriter := gob.NewEncoder(responseC)
server := rpc.NewServer()
RegisterArtifact(server, artifact) // Run the build in a goroutine so we don't block the RPC connection
go func () {
defer responseC.Close()
hook := Hook(client)
ui := &Ui{client}
artifact := b.builder.Run(ui, hook)
// Wrap the artifact
server := rpc.NewServer()
RegisterArtifact(server, artifact)
responseWriter.Encode(&BuilderRunResponse{serveSingleConn(server)})
}()
*reply = serveSingleConn(server)
return nil return nil
} }
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