diff --git a/packer/plugin/client.go b/packer/plugin/client.go index a7e698b91..29011e741 100644 --- a/packer/plugin/client.go +++ b/packer/plugin/client.go @@ -143,13 +143,12 @@ func (c *Client) Hook() (packer.Hook, error) { // Returns a post-processor implementation that is communicating over // this client. If the client hasn't been started, this will start it. func (c *Client) PostProcessor() (packer.PostProcessor, error) { - _, err := c.rpcClient() + client, err := c.rpcClient() if err != nil { return nil, err } - // TODO - return nil, nil + return &cmdPostProcessor{packrpc.PostProcessor(client), c}, nil } // Returns a provisioner implementation that is communicating over this diff --git a/packer/plugin/plugin.go b/packer/plugin/plugin.go index d520e190a..91ed6231a 100644 --- a/packer/plugin/plugin.go +++ b/packer/plugin/plugin.go @@ -137,6 +137,19 @@ func ServeHook(hook packer.Hook) { } } +// Serves a post-processor from a plugin. +func ServePostProcessor(p packer.PostProcessor) { + log.Println("Preparing to serve a post-processor plugin...") + + server := rpc.NewServer() + packrpc.RegisterPostProcessor(server, p) + + swallowInterrupts() + if err := serve(server); err != nil { + log.Panic(err) + } +} + // Serves a provisioner from a plugin. func ServeProvisioner(p packer.Provisioner) { log.Println("Preparing to serve a provisioner plugin...") diff --git a/packer/plugin/plugin_test.go b/packer/plugin/plugin_test.go index 786503491..a3b385511 100644 --- a/packer/plugin/plugin_test.go +++ b/packer/plugin/plugin_test.go @@ -59,6 +59,8 @@ func TestHelperProcess(*testing.T) { case "mock": fmt.Println(":1234") <-make(chan int) + case "post-processor": + ServePostProcessor(new(helperPostProcessor)) case "provisioner": ServeProvisioner(new(helperProvisioner)) case "start-timeout": diff --git a/packer/plugin/post_processor.go b/packer/plugin/post_processor.go new file mode 100644 index 000000000..52044ec23 --- /dev/null +++ b/packer/plugin/post_processor.go @@ -0,0 +1,37 @@ +package plugin + +import ( + "github.com/mitchellh/packer/packer" + "log" +) + +type cmdPostProcessor struct { + p packer.PostProcessor + client *Client +} + +func (c *cmdPostProcessor) Configure(config interface{}) error { + defer func() { + r := recover() + c.checkExit(r, nil) + }() + + return c.p.Configure(config) +} + +func (c *cmdPostProcessor) PostProcess(a packer.Artifact) (packer.Artifact, error) { + defer func() { + r := recover() + c.checkExit(r, nil) + }() + + return c.p.PostProcess(a) +} + +func (c *cmdPostProcessor) checkExit(p interface{}, cb func()) { + if c.client.Exited() { + cb() + } else if p != nil { + log.Panic(p) + } +} diff --git a/packer/plugin/post_processor_test.go b/packer/plugin/post_processor_test.go new file mode 100644 index 000000000..ef50e8d68 --- /dev/null +++ b/packer/plugin/post_processor_test.go @@ -0,0 +1,37 @@ +package plugin + +import ( + "github.com/mitchellh/packer/packer" + "os/exec" + "testing" +) + +type helperPostProcessor byte + +func (helperPostProcessor) Configure(interface{}) error { + return nil +} + +func (helperPostProcessor) PostProcess(packer.Artifact) (packer.Artifact, error) { + return nil, nil +} + +func TestPostProcessor_NoExist(t *testing.T) { + c := NewClient(&ClientConfig{Cmd: exec.Command("i-should-not-exist")}) + defer c.Kill() + + _, err := c.PostProcessor() + if err == nil { + t.Fatal("should have error") + } +} + +func TestPostProcessor_Good(t *testing.T) { + c := NewClient(&ClientConfig{Cmd: helperProcess("post-processor")}) + defer c.Kill() + + _, err := c.PostProcessor() + if err != nil { + t.Fatalf("should not have error: %s", err) + } +}