From 520503e10c12228430c8c653f1fd0fe47e79a0a7 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 2 May 2013 14:03:55 -0700 Subject: [PATCH] Turn Environment into an interface --- packer/build_command.go | 2 +- packer/command.go | 9 ++++++++- packer/environment.go | 37 ++++++++++++++++++++++--------------- packer/environment_test.go | 11 +++-------- packer/version.go | 2 +- 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/packer/build_command.go b/packer/build_command.go index 264552af5..2bfadd2b9 100644 --- a/packer/build_command.go +++ b/packer/build_command.go @@ -6,7 +6,7 @@ import ( type buildCommand byte -func (buildCommand) Run(env *Environment, args []string) int { +func (buildCommand) Run(env Environment, args []string) int { if len(args) != 1 { // TODO: Error message return 1 diff --git a/packer/command.go b/packer/command.go index 58857098f..c69f2e532 100644 --- a/packer/command.go +++ b/packer/command.go @@ -1,5 +1,7 @@ package packer +import "net/rpc" + // A command is a runnable sub-command of the `packer` application. // When `packer` is called with the proper subcommand, this will be // called. @@ -14,7 +16,12 @@ package packer // Synopsis should return a one-line, short synopsis of the command. // This should be less than 50 characters ideally. type Command interface { - Run(env *Environment, args []string) int + Run(env Environment, args []string) int Synopsis() string } +// An RPCCommand is an implementation of the Command interface where the +// command is actually executed over an RPC connection. +type RPCCommand struct { + client *rpc.Client +} diff --git a/packer/environment.go b/packer/environment.go index 0179fd979..73f5de17c 100644 --- a/packer/environment.go +++ b/packer/environment.go @@ -9,14 +9,20 @@ import ( "strings" ) -// The environment struct contains all the state necessary for a single -// instance of Packer. +// The environment interface provides access to the configuration and +// state of a single Packer run. // -// It is *not* a singleton, but generally a single environment is created -// when Packer starts running to represent that Packer run. Technically, -// if you're building a custom Packer binary, you could instantiate multiple -// environments and run them in parallel. -type Environment struct { +// It allows for things such as executing CLI commands, getting the +// list of available builders, and more. +type Environment interface { + BuilderFactory() BuilderFactory + Cli(args []string) int + Ui() Ui +} + +// An implementation of an Environment that represents the Packer core +// environment. +type coreEnvironment struct { builderFactory BuilderFactory command map[string]Command ui Ui @@ -40,13 +46,13 @@ func DefaultEnvironmentConfig() *EnvironmentConfig { } // This creates a new environment -func NewEnvironment(config *EnvironmentConfig) (env *Environment, err error) { +func NewEnvironment(config *EnvironmentConfig) (resultEnv Environment, err error) { if config == nil { err = errors.New("config must be given to initialize environment") return } - env = &Environment{} + env := &coreEnvironment{} env.builderFactory = config.BuilderFactory env.command = make(map[string]Command) env.ui = config.Ui @@ -60,19 +66,20 @@ func NewEnvironment(config *EnvironmentConfig) (env *Environment, err error) { env.command["version"] = new(versionCommand) } + resultEnv = env return } // Returns the BuilderFactory associated with this Environment. -func (e *Environment) BuilderFactory() BuilderFactory { +func (e *coreEnvironment) BuilderFactory() BuilderFactory { return e.builderFactory } // Executes a command as if it was typed on the command-line interface. // The return value is the exit code of the command. -func (e *Environment) Cli(args []string) int { +func (e *coreEnvironment) Cli(args []string) int { if len(args) == 0 || args[0] == "--help" || args[0] == "-h" { - e.PrintHelp() + e.printHelp() return 1 } @@ -89,7 +96,7 @@ func (e *Environment) Cli(args []string) int { // If we still don't have a command, show the help. if command == nil { - e.PrintHelp() + e.printHelp() return 1 } } @@ -98,7 +105,7 @@ func (e *Environment) Cli(args []string) int { } // Prints the CLI help to the UI. -func (e *Environment) PrintHelp() { +func (e *coreEnvironment) printHelp() { // Created a sorted slice of the map keys and record the longest // command name so we can better format the output later. commandKeys := make([]string, len(e.command)) @@ -131,6 +138,6 @@ func (e *Environment) PrintHelp() { // Returns the UI for the environment. The UI is the interface that should // be used for all communication with the outside world. -func (e *Environment) Ui() Ui { +func (e *coreEnvironment) Ui() Ui { return e.ui } diff --git a/packer/environment_test.go b/packer/environment_test.go index 673e40beb..03898db01 100644 --- a/packer/environment_test.go +++ b/packer/environment_test.go @@ -11,10 +11,10 @@ import ( type TestCommand struct { runArgs []string runCalled bool - runEnv *Environment + runEnv Environment } -func (tc *TestCommand) Run(env *Environment, args []string) int { +func (tc *TestCommand) Run(env Environment, args []string) int { tc.runCalled = true tc.runArgs = args tc.runEnv = env @@ -25,7 +25,7 @@ func (tc *TestCommand) Synopsis() string { return "" } -func testEnvironment() *Environment { +func testEnvironment() Environment { config := &EnvironmentConfig{} config.Ui = &ReaderWriterUi{ new(bytes.Buffer), @@ -140,11 +140,6 @@ func TestEnvironment_DefaultCli_Version(t *testing.T) { assert.Equal(defaultEnv.Cli([]string{"bad", "version"}), 1, "version should NOT work anywhere") } -func TestEnvironment_PrintHelp(t *testing.T) { - // Just call the function and verify that no panics occur - testEnvironment().PrintHelp() -} - func TestEnvironment_SettingUi(t *testing.T) { assert := asserts.NewTestingAsserts(t, true) diff --git a/packer/version.go b/packer/version.go index d37f67181..b9d2e1105 100644 --- a/packer/version.go +++ b/packer/version.go @@ -6,7 +6,7 @@ const Version = "0.1.0.dev" type versionCommand byte // Implement the Command interface by simply showing the version -func (versionCommand) Run(env *Environment, args []string) int { +func (versionCommand) Run(env Environment, args []string) int { env.Ui().Say("Packer v%v\n", Version) return 0 }