diff --git a/packer/rpc/build.go b/packer/rpc/build.go index 2df03a6ab..f2f7d48ab 100644 --- a/packer/rpc/build.go +++ b/packer/rpc/build.go @@ -107,7 +107,8 @@ func (b *BuildServer) Run(args *BuildRunArgs, reply *[]string) error { return err } - artifacts, err := b.build.Run(&Ui{client}, Cache(client)) + ui := &Ui{client: client} + artifacts, err := b.build.Run(ui, Cache(client)) if err != nil { return NewBasicError(err) } diff --git a/packer/rpc/builder.go b/packer/rpc/builder.go index 42f92c4d4..0c5dfab37 100644 --- a/packer/rpc/builder.go +++ b/packer/rpc/builder.go @@ -146,7 +146,7 @@ func (b *BuilderServer) Run(args *BuilderRunArgs, reply *interface{}) error { cache := Cache(client) hook := Hook(client) - ui := &Ui{client} + ui := &Ui{client: client} artifact, responseErr := b.builder.Run(ui, hook, cache) responseAddress := "" diff --git a/packer/rpc/environment.go b/packer/rpc/environment.go index 36db72c56..aaf0db412 100644 --- a/packer/rpc/environment.go +++ b/packer/rpc/environment.go @@ -114,7 +114,7 @@ func (e *Environment) Ui() packer.Ui { panic(err) } - return &Ui{client} + return &Ui{client: client} } func (e *EnvironmentServer) Builder(name *string, reply *string) error { diff --git a/packer/rpc/hook.go b/packer/rpc/hook.go index 223b96df2..cede08302 100644 --- a/packer/rpc/hook.go +++ b/packer/rpc/hook.go @@ -51,7 +51,7 @@ func (h *HookServer) Run(args *HookRunArgs, reply *interface{}) error { return err } - if err := h.hook.Run(args.Name, &Ui{client}, Communicator(client), args.Data); err != nil { + if err := h.hook.Run(args.Name, &Ui{client: client}, Communicator(client), args.Data); err != nil { return NewBasicError(err) } diff --git a/packer/rpc/post_processor.go b/packer/rpc/post_processor.go index 0a5eaefd3..2f743eb65 100644 --- a/packer/rpc/post_processor.go +++ b/packer/rpc/post_processor.go @@ -82,7 +82,7 @@ func (p *PostProcessorServer) PostProcess(address string, reply *PostProcessorPr responseAddress := "" - artifact, keep, err := p.p.PostProcess(&Ui{client}, Artifact(client)) + artifact, keep, err := p.p.PostProcess(&Ui{client: client}, Artifact(client)) if err == nil && artifact != nil { server := rpc.NewServer() RegisterArtifact(server, artifact) diff --git a/packer/rpc/provisioner.go b/packer/rpc/provisioner.go index 4cd329d6b..a62f97d45 100644 --- a/packer/rpc/provisioner.go +++ b/packer/rpc/provisioner.go @@ -71,7 +71,7 @@ func (p *ProvisionerServer) Provision(args *ProvisionerProvisionArgs, reply *int } comm := Communicator(client) - ui := &Ui{client} + ui := &Ui{client: client} if err := p.p.Provision(ui, comm); err != nil { return NewBasicError(err) diff --git a/packer/rpc/server.go b/packer/rpc/server.go index f6098ea7a..c9154160a 100644 --- a/packer/rpc/server.go +++ b/packer/rpc/server.go @@ -1,73 +1,93 @@ package rpc import ( + "fmt" "github.com/mitchellh/packer/packer" "net/rpc" + "sync/atomic" ) +// This keeps track of the endpoint ID to use when registering artifacts. +var endpointId uint64 = 0 + // Registers the appropriate endpoint on an RPC server to serve an // Artifact. func RegisterArtifact(s *rpc.Server, a packer.Artifact) { - s.RegisterName("Artifact", &ArtifactServer{a}) + registerComponent(s, "Artifact", &ArtifactServer{a}, false) } // Registers the appropriate endpoint on an RPC server to serve a // Packer Build. func RegisterBuild(s *rpc.Server, b packer.Build) { - s.RegisterName("Build", &BuildServer{b}) + registerComponent(s, "Build", &BuildServer{b}, false) } // Registers the appropriate endpoint on an RPC server to serve a // Packer Builder. func RegisterBuilder(s *rpc.Server, b packer.Builder) { - s.RegisterName("Builder", &BuilderServer{b}) + registerComponent(s, "Builder", &BuilderServer{b}, false) } // Registers the appropriate endpoint on an RPC server to serve a // Packer Cache. func RegisterCache(s *rpc.Server, c packer.Cache) { - s.RegisterName("Cache", &CacheServer{c}) + registerComponent(s, "Cache", &CacheServer{c}, false) } // Registers the appropriate endpoint on an RPC server to serve a // Packer Command. func RegisterCommand(s *rpc.Server, c packer.Command) { - s.RegisterName("Command", &CommandServer{c}) + registerComponent(s, "Command", &CommandServer{c}, false) } // Registers the appropriate endpoint on an RPC server to serve a // Packer Communicator. func RegisterCommunicator(s *rpc.Server, c packer.Communicator) { - s.RegisterName("Communicator", &CommunicatorServer{c}) + registerComponent(s, "Communicator", &CommunicatorServer{c}, false) } // Registers the appropriate endpoint on an RPC server to serve a // Packer Environment func RegisterEnvironment(s *rpc.Server, e packer.Environment) { - s.RegisterName("Environment", &EnvironmentServer{e}) + registerComponent(s, "Environment", &EnvironmentServer{e}, false) } // Registers the appropriate endpoint on an RPC server to serve a // Hook. -func RegisterHook(s *rpc.Server, hook packer.Hook) { - s.RegisterName("Hook", &HookServer{hook}) +func RegisterHook(s *rpc.Server, h packer.Hook) { + registerComponent(s, "Hook", &HookServer{h}, false) } // Registers the appropriate endpoing on an RPC server to serve a // PostProcessor. func RegisterPostProcessor(s *rpc.Server, p packer.PostProcessor) { - s.RegisterName("PostProcessor", &PostProcessorServer{p}) + registerComponent(s, "PostProcessor", &PostProcessorServer{p}, false) } // Registers the appropriate endpoint on an RPC server to serve a packer.Provisioner func RegisterProvisioner(s *rpc.Server, p packer.Provisioner) { - s.RegisterName("Provisioner", &ProvisionerServer{p}) + registerComponent(s, "Provisioner", &ProvisionerServer{p}, false) } // Registers the appropriate endpoint on an RPC server to serve a // Packer UI func RegisterUi(s *rpc.Server, ui packer.Ui) { - s.RegisterName("Ui", &UiServer{ui}) + registerComponent(s, "Ui", &UiServer{ui}, false) +} + +// registerComponent registers a single Packer RPC component onto +// the RPC server. If id is true, then a unique ID number will be appended +// onto the end of the endpoint. +// +// The endpoint name is returned. +func registerComponent(s *rpc.Server, name string, rcvr interface{}, id bool) string { + endpoint := name + if id { + fmt.Sprintf("%s.%d", endpoint, atomic.AddUint64(&endpointId, 1)) + } + + s.RegisterName(endpoint, rcvr) + return endpoint } func serveSingleConn(s *rpc.Server) string { diff --git a/packer/rpc/ui.go b/packer/rpc/ui.go index 4d7ccc57f..1857e4928 100644 --- a/packer/rpc/ui.go +++ b/packer/rpc/ui.go @@ -9,7 +9,8 @@ import ( // An implementation of packer.Ui where the Ui is actually executed // over an RPC connection. type Ui struct { - client *rpc.Client + client *rpc.Client + endpoint string } // UiServer wraps a packer.Ui implementation and makes it exportable @@ -25,12 +26,12 @@ type UiMachineArgs struct { } func (u *Ui) Ask(query string) (result string, err error) { - err = u.client.Call("Ui.Ask", query, &result) + err = u.client.Call(u.endpoint+".Ask", query, &result) return } func (u *Ui) Error(message string) { - if err := u.client.Call("Ui.Error", message, new(interface{})); err != nil { + if err := u.client.Call(u.endpoint+".Error", message, new(interface{})); err != nil { log.Printf("Error in Ui RPC call: %s", err) } } @@ -41,19 +42,19 @@ func (u *Ui) Machine(t string, args ...string) { Args: args, } - if err := u.client.Call("Ui.Machine", rpcArgs, new(interface{})); err != nil { + if err := u.client.Call(u.endpoint+".Machine", rpcArgs, new(interface{})); err != nil { log.Printf("Error in Ui RPC call: %s", err) } } func (u *Ui) Message(message string) { - if err := u.client.Call("Ui.Message", message, new(interface{})); err != nil { + if err := u.client.Call(u.endpoint+".Message", message, new(interface{})); err != nil { log.Printf("Error in Ui RPC call: %s", err) } } func (u *Ui) Say(message string) { - if err := u.client.Call("Ui.Say", message, new(interface{})); err != nil { + if err := u.client.Call(u.endpoint+".Say", message, new(interface{})); err != nil { log.Printf("Error in Ui RPC call: %s", err) } } diff --git a/packer/rpc/ui_test.go b/packer/rpc/ui_test.go index 8a85c5573..3a46bf02c 100644 --- a/packer/rpc/ui_test.go +++ b/packer/rpc/ui_test.go @@ -62,7 +62,7 @@ func TestUiRPC(t *testing.T) { panic(err) } - uiClient := &Ui{client} + uiClient := &Ui{client: client, endpoint: "Ui"} // Basic error and say tests result, err := uiClient.Ask("query")