From 0cc3a5f918760ee10a8c645d4d2433062a42ba10 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 5 May 2013 16:25:32 -0700 Subject: [PATCH] packer/plugin: Much more robust subprocess starting --- packer/plugin/command.go | 28 ++++++++-------------------- packer/plugin/plugin.go | 38 +++++++++++++++++++++++++++----------- packer/rpc/command.go | 12 ++++++++++-- packer/rpc/server.go | 4 ++++ 4 files changed, 49 insertions(+), 33 deletions(-) diff --git a/packer/plugin/command.go b/packer/plugin/command.go index 26a9f54f0..de65fa9da 100644 --- a/packer/plugin/command.go +++ b/packer/plugin/command.go @@ -10,19 +10,10 @@ import ( "time" ) -type processCommand struct { - cmd *exec.Cmd -} - -func (c *processCommand) Run(e packer.Environment, args []string) int { - return 0 -} - -func (c *processCommand) Synopsis() string { +func Command(cmd *exec.Cmd) packer.Command { out := new(bytes.Buffer) - c.cmd.Stdout = out - c.cmd.Start() - defer c.cmd.Process.Kill() + cmd.Stdout = out + cmd.Start() // TODO: timeout // TODO: check that command is even running @@ -37,13 +28,10 @@ func (c *processCommand) Synopsis() string { time.Sleep(10 * time.Millisecond) } - client, _ := rpc.Dial("tcp", address) - defer client.Close() + client, err := rpc.Dial("tcp", address) + if err != nil { + panic(err) + } - realCommand := packrpc.Command(client) - return realCommand.Synopsis() -} - -func Command(cmd *exec.Cmd) packer.Command { - return &processCommand{cmd} + return packrpc.Command(client) } diff --git a/packer/plugin/plugin.go b/packer/plugin/plugin.go index d694feab5..c7f9135c2 100644 --- a/packer/plugin/plugin.go +++ b/packer/plugin/plugin.go @@ -6,26 +6,42 @@ package plugin import ( "fmt" "github.com/mitchellh/packer/packer" + "net" + "net/rpc" "os" packrpc "github.com/mitchellh/packer/packer/rpc" ) -// This serves the plugin by starting the RPC server and serving requests. -// This function never returns. -func serve(server *packrpc.Server) { - // Start up the server - server.Start() +// This serves a single RPC connection on the given RPC server on +// a random port. +func serve(server *rpc.Server) (err error) { + listener, err := net.Listen("tcp", ":2345") + if err != nil { + return + } + defer listener.Close() // Output the address to stdout - fmt.Println(server.Address()) + fmt.Println(":2345") os.Stdout.Sync() - // Never return, wait on a channel that never gets a message - <-make(chan bool) + // Accept a connection + conn, err := listener.Accept() + if err != nil { + return + } + + // Serve a single connection + server.ServeConn(conn) + return } +// Serves a command from a plugin. func ServeCommand(command packer.Command) { - server := packrpc.NewServer() - server.RegisterCommand(command) - serve(server) + server := rpc.NewServer() + packrpc.RegisterCommand(server, command) + + if err := serve(server); err != nil { + panic(err) + } } diff --git a/packer/rpc/command.go b/packer/rpc/command.go index 6aa3a2165..0e2c89e39 100644 --- a/packer/rpc/command.go +++ b/packer/rpc/command.go @@ -31,12 +31,20 @@ func Command(client *rpc.Client) *ClientCommand { func (c *ClientCommand) Run(env packer.Environment, args []string) (result int) { // TODO: Environment rpcArgs := &CommandRunArgs{nil, args} - c.client.Call("Command.Run", rpcArgs, &result) + err := c.client.Call("Command.Run", rpcArgs, &result) + if err != nil { + panic(err) + } + return } func (c *ClientCommand) Synopsis() (result string) { - c.client.Call("Command.Synopsis", CommandSynopsisArgs(0), &result) + err := c.client.Call("Command.Synopsis", CommandSynopsisArgs(0), &result) + if err != nil { + panic(err) + } + return } diff --git a/packer/rpc/server.go b/packer/rpc/server.go index 456537c6c..673b3878d 100644 --- a/packer/rpc/server.go +++ b/packer/rpc/server.go @@ -7,6 +7,10 @@ import ( "net/rpc" ) +func RegisterCommand(s *rpc.Server, c packer.Command) { + s.RegisterName("Command", &ServerCommand{c}) +} + // A Server is a Golang RPC server that has helper methods for automatically // setting up the endpoints for Packer interfaces. type Server struct {