package rpc import ( "github.com/mitchellh/packer/packer" "net/rpc" ) // An implementation of packer.PostProcessor where the PostProcessor is actually // executed over an RPC connection. type postProcessor struct { client *rpc.Client } // PostProcessorServer wraps a packer.PostProcessor implementation and makes it // exportable as part of a Golang RPC server. type PostProcessorServer struct { p packer.PostProcessor } type PostProcessorConfigureArgs struct { Configs []interface{} } type PostProcessorProcessResponse struct { Err error Keep bool RPCAddress string } func PostProcessor(client *rpc.Client) *postProcessor { return &postProcessor{client} } func (p *postProcessor) Configure(raw ...interface{}) (err error) { args := &PostProcessorConfigureArgs{Configs: raw} if cerr := p.client.Call("PostProcessor.Configure", args, &err); cerr != nil { err = cerr } return } func (p *postProcessor) PostProcess(ui packer.Ui, a packer.Artifact) (packer.Artifact, bool, error) { server := rpc.NewServer() RegisterArtifact(server, a) RegisterUi(server, ui) var response PostProcessorProcessResponse if err := p.client.Call("PostProcessor.PostProcess", serveSingleConn(server), &response); err != nil { return nil, false, err } if response.Err != nil { return nil, false, response.Err } if response.RPCAddress == "" { return nil, false, nil } client, err := rpc.Dial("tcp", response.RPCAddress) if err != nil { return nil, false, err } return Artifact(client), response.Keep, nil } func (p *PostProcessorServer) Configure(args *PostProcessorConfigureArgs, reply *error) error { *reply = p.p.Configure(args.Configs...) if *reply != nil { *reply = NewBasicError(*reply) } return nil } func (p *PostProcessorServer) PostProcess(address string, reply *PostProcessorProcessResponse) error { client, err := rpc.Dial("tcp", address) if err != nil { return err } responseAddress := "" artifact, keep, err := p.p.PostProcess(&Ui{client}, Artifact(client)) if err == nil && artifact != nil { server := rpc.NewServer() RegisterArtifact(server, artifact) responseAddress = serveSingleConn(server) } if err != nil { err = NewBasicError(err) } *reply = PostProcessorProcessResponse{ Err: err, Keep: keep, RPCAddress: responseAddress, } return nil }