Commit 2ac629c9 authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

packer/rpc: get PostProcessor working

parent ec68a3fd
...@@ -15,14 +15,12 @@ type Client struct { ...@@ -15,14 +15,12 @@ type Client struct {
} }
func NewClient(rwc io.ReadWriteCloser) (*Client, error) { func NewClient(rwc io.ReadWriteCloser) (*Client, error) {
// Create the MuxConn around the RWC and get the client to server stream. return NewClientWithMux(NewMuxConn(rwc), 0)
// This is the primary stream that we use to communicate with the }
// remote RPC server. On the remote side Server.ServeConn also listens
// on this stream ID. func NewClientWithMux(mux *MuxConn, streamId uint32) (*Client, error) {
mux := NewMuxConn(rwc) clientConn, err := mux.Dial(streamId)
clientConn, err := mux.Dial(0)
if err != nil { if err != nil {
mux.Close()
return nil, err return nil, err
} }
...@@ -37,7 +35,7 @@ func (c *Client) Close() error { ...@@ -37,7 +35,7 @@ func (c *Client) Close() error {
return err return err
} }
return c.mux.Close() return nil
} }
func (c *Client) Artifact() packer.Artifact { func (c *Client) Artifact() packer.Artifact {
...@@ -56,12 +54,13 @@ func (c *Client) Cache() packer.Cache { ...@@ -56,12 +54,13 @@ func (c *Client) Cache() packer.Cache {
func (c *Client) PostProcessor() packer.PostProcessor { func (c *Client) PostProcessor() packer.PostProcessor {
return &postProcessor{ return &postProcessor{
client: c.client, client: c.client,
mux: c.mux,
} }
} }
func (c *Client) Ui() packer.Ui { func (c *Client) Ui() packer.Ui {
return &Ui{ return &Ui{
client: c.client, client: c.client,
endpoint: DefaultUiEndpoint, endpoint: DefaultUiEndpoint,
} }
} }
...@@ -21,7 +21,7 @@ type MuxConn struct { ...@@ -21,7 +21,7 @@ type MuxConn struct {
curId uint32 curId uint32
rwc io.ReadWriteCloser rwc io.ReadWriteCloser
streams map[uint32]*Stream streams map[uint32]*Stream
mu sync.RWMutex mu sync.Mutex
wlock sync.Mutex wlock sync.Mutex
} }
......
...@@ -9,14 +9,14 @@ import ( ...@@ -9,14 +9,14 @@ import (
// executed over an RPC connection. // executed over an RPC connection.
type postProcessor struct { type postProcessor struct {
client *rpc.Client client *rpc.Client
server *rpc.Server mux *MuxConn
} }
// PostProcessorServer wraps a packer.PostProcessor implementation and makes it // PostProcessorServer wraps a packer.PostProcessor implementation and makes it
// exportable as part of a Golang RPC server. // exportable as part of a Golang RPC server.
type PostProcessorServer struct { type PostProcessorServer struct {
client *rpc.Client client *rpc.Client
server *rpc.Server mux *MuxConn
p packer.PostProcessor p packer.PostProcessor
} }
...@@ -24,15 +24,10 @@ type PostProcessorConfigureArgs struct { ...@@ -24,15 +24,10 @@ type PostProcessorConfigureArgs struct {
Configs []interface{} Configs []interface{}
} }
type PostProcessorPostProcessArgs struct {
ArtifactEndpoint string
UiEndpoint string
}
type PostProcessorProcessResponse struct { type PostProcessorProcessResponse struct {
Err error Err error
Keep bool Keep bool
ArtifactEndpoint string StreamId uint32
} }
func PostProcessor(client *rpc.Client) *postProcessor { func PostProcessor(client *rpc.Client) *postProcessor {
...@@ -49,21 +44,14 @@ func (p *postProcessor) Configure(raw ...interface{}) (err error) { ...@@ -49,21 +44,14 @@ func (p *postProcessor) Configure(raw ...interface{}) (err error) {
} }
func (p *postProcessor) PostProcess(ui packer.Ui, a packer.Artifact) (packer.Artifact, bool, error) { func (p *postProcessor) PostProcess(ui packer.Ui, a packer.Artifact) (packer.Artifact, bool, error) {
artifactEndpoint := registerComponent(p.server, "Artifact", &ArtifactServer{ nextId := p.mux.NextId()
artifact: a, server := NewServerWithMux(p.mux, nextId)
}, true) server.RegisterArtifact(a)
server.RegisterUi(ui)
uiEndpoint := registerComponent(p.server, "Ui", &UiServer{ go server.Serve()
ui: ui,
}, true)
args := PostProcessorPostProcessArgs{
ArtifactEndpoint: artifactEndpoint,
UiEndpoint: uiEndpoint,
}
var response PostProcessorProcessResponse var response PostProcessorProcessResponse
if err := p.client.Call("PostProcessor.PostProcess", &args, &response); err != nil { if err := p.client.Call("PostProcessor.PostProcess", nextId, &response); err != nil {
return nil, false, err return nil, false, err
} }
...@@ -71,14 +59,16 @@ func (p *postProcessor) PostProcess(ui packer.Ui, a packer.Artifact) (packer.Art ...@@ -71,14 +59,16 @@ func (p *postProcessor) PostProcess(ui packer.Ui, a packer.Artifact) (packer.Art
return nil, false, response.Err return nil, false, response.Err
} }
if response.ArtifactEndpoint == "" { if response.StreamId == 0 {
return nil, false, nil return nil, false, nil
} }
return &artifact{ client, err := NewClientWithMux(p.mux, response.StreamId)
client: p.client, if err != nil {
endpoint: response.ArtifactEndpoint, return nil, false, err
}, response.Keep, nil }
return client.Artifact(), response.Keep, nil
} }
func (p *PostProcessorServer) Configure(args *PostProcessorConfigureArgs, reply *error) error { func (p *PostProcessorServer) Configure(args *PostProcessorConfigureArgs, reply *error) error {
...@@ -90,23 +80,20 @@ func (p *PostProcessorServer) Configure(args *PostProcessorConfigureArgs, reply ...@@ -90,23 +80,20 @@ func (p *PostProcessorServer) Configure(args *PostProcessorConfigureArgs, reply
return nil return nil
} }
func (p *PostProcessorServer) PostProcess(args *PostProcessorPostProcessArgs, reply *PostProcessorProcessResponse) error { func (p *PostProcessorServer) PostProcess(streamId uint32, reply *PostProcessorProcessResponse) error {
artifact := &artifact{ client, err := NewClientWithMux(p.mux, streamId)
client: p.client, if err != nil {
endpoint: args.ArtifactEndpoint, return NewBasicError(err)
}
ui := &Ui{
client: p.client,
endpoint: args.UiEndpoint,
} }
defer client.Close()
var artifactEndpoint string streamId = 0
artifactResult, keep, err := p.p.PostProcess(ui, artifact) artifactResult, keep, err := p.p.PostProcess(client.Ui(), client.Artifact())
if err == nil && artifactResult != nil { if err == nil && artifactResult != nil {
artifactEndpoint = registerComponent(p.server, "Artifact", &ArtifactServer{ streamId = p.mux.NextId()
artifact: artifactResult, server := NewServerWithMux(p.mux, streamId)
}, true) server.RegisterArtifact(artifactResult)
go server.Serve()
} }
if err != nil { if err != nil {
...@@ -114,9 +101,9 @@ func (p *PostProcessorServer) PostProcess(args *PostProcessorPostProcessArgs, re ...@@ -114,9 +101,9 @@ func (p *PostProcessorServer) PostProcess(args *PostProcessorPostProcessArgs, re
} }
*reply = PostProcessorProcessResponse{ *reply = PostProcessorProcessResponse{
Err: err, Err: err,
Keep: keep, Keep: keep,
ArtifactEndpoint: artifactEndpoint, StreamId: streamId,
} }
return nil return nil
......
...@@ -13,6 +13,7 @@ type TestPostProcessor struct { ...@@ -13,6 +13,7 @@ type TestPostProcessor struct {
configVal []interface{} configVal []interface{}
ppCalled bool ppCalled bool
ppArtifact packer.Artifact ppArtifact packer.Artifact
ppArtifactId string
ppUi packer.Ui ppUi packer.Ui
} }
...@@ -25,6 +26,7 @@ func (pp *TestPostProcessor) Configure(v ...interface{}) error { ...@@ -25,6 +26,7 @@ func (pp *TestPostProcessor) Configure(v ...interface{}) error {
func (pp *TestPostProcessor) PostProcess(ui packer.Ui, a packer.Artifact) (packer.Artifact, bool, error) { func (pp *TestPostProcessor) PostProcess(ui packer.Ui, a packer.Artifact) (packer.Artifact, bool, error) {
pp.ppCalled = true pp.ppCalled = true
pp.ppArtifact = a pp.ppArtifact = a
pp.ppArtifactId = a.Id()
pp.ppUi = ui pp.ppUi = ui
return testPostProcessorArtifact, false, nil return testPostProcessorArtifact, false, nil
} }
...@@ -70,8 +72,8 @@ func TestPostProcessorRPC(t *testing.T) { ...@@ -70,8 +72,8 @@ func TestPostProcessorRPC(t *testing.T) {
t.Fatal("postprocess should be called") t.Fatal("postprocess should be called")
} }
if p.ppArtifact.Id() != "ppTestId" { if p.ppArtifactId != "ppTestId" {
t.Fatal("unknown artifact") t.Fatalf("unknown artifact: %s", p.ppArtifact.Id())
} }
if artifact.Id() != "id" { if artifact.Id() != "id" {
......
...@@ -21,15 +21,21 @@ const ( ...@@ -21,15 +21,21 @@ const (
// Server represents an RPC server for Packer. This must be paired on // Server represents an RPC server for Packer. This must be paired on
// the other side with a Client. // the other side with a Client.
type Server struct { type Server struct {
mux *MuxConn mux *MuxConn
server *rpc.Server streamId uint32
server *rpc.Server
} }
// NewServer returns a new Packer RPC server. // NewServer returns a new Packer RPC server.
func NewServer(conn io.ReadWriteCloser) *Server { func NewServer(conn io.ReadWriteCloser) *Server {
return NewServerWithMux(NewMuxConn(conn), 0)
}
func NewServerWithMux(mux *MuxConn, streamId uint32) *Server {
return &Server{ return &Server{
mux: NewMuxConn(conn), mux: mux,
server: rpc.NewServer(), streamId: streamId,
server: rpc.NewServer(),
} }
} }
...@@ -51,7 +57,8 @@ func (s *Server) RegisterCache(c packer.Cache) { ...@@ -51,7 +57,8 @@ func (s *Server) RegisterCache(c packer.Cache) {
func (s *Server) RegisterPostProcessor(p packer.PostProcessor) { func (s *Server) RegisterPostProcessor(p packer.PostProcessor) {
s.server.RegisterName(DefaultPostProcessorEndpoint, &PostProcessorServer{ s.server.RegisterName(DefaultPostProcessorEndpoint, &PostProcessorServer{
p: p, mux: s.mux,
p: p,
}) })
} }
...@@ -66,7 +73,7 @@ func (s *Server) RegisterUi(ui packer.Ui) { ...@@ -66,7 +73,7 @@ func (s *Server) RegisterUi(ui packer.Ui) {
func (s *Server) Serve() { func (s *Server) Serve() {
// Accept a connection on stream ID 0, which is always used for // Accept a connection on stream ID 0, which is always used for
// normal client to server connections. // normal client to server connections.
stream, err := s.mux.Accept(0) stream, err := s.mux.Accept(s.streamId)
defer stream.Close() defer stream.Close()
if err != nil { if err != nil {
log.Printf("[ERR] Error retrieving stream for serving: %s", err) log.Printf("[ERR] Error retrieving stream for serving: %s", err)
......
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