Turn Environment into an interface
This commit is contained in:
parent
fefd2ae208
commit
520503e10c
|
@ -6,7 +6,7 @@ import (
|
||||||
|
|
||||||
type buildCommand byte
|
type buildCommand byte
|
||||||
|
|
||||||
func (buildCommand) Run(env *Environment, args []string) int {
|
func (buildCommand) Run(env Environment, args []string) int {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
// TODO: Error message
|
// TODO: Error message
|
||||||
return 1
|
return 1
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package packer
|
package packer
|
||||||
|
|
||||||
|
import "net/rpc"
|
||||||
|
|
||||||
// A command is a runnable sub-command of the `packer` application.
|
// A command is a runnable sub-command of the `packer` application.
|
||||||
// When `packer` is called with the proper subcommand, this will be
|
// When `packer` is called with the proper subcommand, this will be
|
||||||
// called.
|
// called.
|
||||||
|
@ -14,7 +16,12 @@ package packer
|
||||||
// Synopsis should return a one-line, short synopsis of the command.
|
// Synopsis should return a one-line, short synopsis of the command.
|
||||||
// This should be less than 50 characters ideally.
|
// This should be less than 50 characters ideally.
|
||||||
type Command interface {
|
type Command interface {
|
||||||
Run(env *Environment, args []string) int
|
Run(env Environment, args []string) int
|
||||||
Synopsis() string
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -9,14 +9,20 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The environment struct contains all the state necessary for a single
|
// The environment interface provides access to the configuration and
|
||||||
// instance of Packer.
|
// state of a single Packer run.
|
||||||
//
|
//
|
||||||
// It is *not* a singleton, but generally a single environment is created
|
// It allows for things such as executing CLI commands, getting the
|
||||||
// when Packer starts running to represent that Packer run. Technically,
|
// list of available builders, and more.
|
||||||
// if you're building a custom Packer binary, you could instantiate multiple
|
type Environment interface {
|
||||||
// environments and run them in parallel.
|
BuilderFactory() BuilderFactory
|
||||||
type Environment struct {
|
Cli(args []string) int
|
||||||
|
Ui() Ui
|
||||||
|
}
|
||||||
|
|
||||||
|
// An implementation of an Environment that represents the Packer core
|
||||||
|
// environment.
|
||||||
|
type coreEnvironment struct {
|
||||||
builderFactory BuilderFactory
|
builderFactory BuilderFactory
|
||||||
command map[string]Command
|
command map[string]Command
|
||||||
ui Ui
|
ui Ui
|
||||||
|
@ -40,13 +46,13 @@ func DefaultEnvironmentConfig() *EnvironmentConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This creates a new environment
|
// This creates a new environment
|
||||||
func NewEnvironment(config *EnvironmentConfig) (env *Environment, err error) {
|
func NewEnvironment(config *EnvironmentConfig) (resultEnv Environment, err error) {
|
||||||
if config == nil {
|
if config == nil {
|
||||||
err = errors.New("config must be given to initialize environment")
|
err = errors.New("config must be given to initialize environment")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
env = &Environment{}
|
env := &coreEnvironment{}
|
||||||
env.builderFactory = config.BuilderFactory
|
env.builderFactory = config.BuilderFactory
|
||||||
env.command = make(map[string]Command)
|
env.command = make(map[string]Command)
|
||||||
env.ui = config.Ui
|
env.ui = config.Ui
|
||||||
|
@ -60,19 +66,20 @@ func NewEnvironment(config *EnvironmentConfig) (env *Environment, err error) {
|
||||||
env.command["version"] = new(versionCommand)
|
env.command["version"] = new(versionCommand)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resultEnv = env
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the BuilderFactory associated with this Environment.
|
// Returns the BuilderFactory associated with this Environment.
|
||||||
func (e *Environment) BuilderFactory() BuilderFactory {
|
func (e *coreEnvironment) BuilderFactory() BuilderFactory {
|
||||||
return e.builderFactory
|
return e.builderFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executes a command as if it was typed on the command-line interface.
|
// Executes a command as if it was typed on the command-line interface.
|
||||||
// The return value is the exit code of the command.
|
// 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" {
|
if len(args) == 0 || args[0] == "--help" || args[0] == "-h" {
|
||||||
e.PrintHelp()
|
e.printHelp()
|
||||||
return 1
|
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 we still don't have a command, show the help.
|
||||||
if command == nil {
|
if command == nil {
|
||||||
e.PrintHelp()
|
e.printHelp()
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +105,7 @@ func (e *Environment) Cli(args []string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prints the CLI help to the UI.
|
// 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
|
// Created a sorted slice of the map keys and record the longest
|
||||||
// command name so we can better format the output later.
|
// command name so we can better format the output later.
|
||||||
commandKeys := make([]string, len(e.command))
|
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
|
// Returns the UI for the environment. The UI is the interface that should
|
||||||
// be used for all communication with the outside world.
|
// be used for all communication with the outside world.
|
||||||
func (e *Environment) Ui() Ui {
|
func (e *coreEnvironment) Ui() Ui {
|
||||||
return e.ui
|
return e.ui
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,10 @@ import (
|
||||||
type TestCommand struct {
|
type TestCommand struct {
|
||||||
runArgs []string
|
runArgs []string
|
||||||
runCalled bool
|
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.runCalled = true
|
||||||
tc.runArgs = args
|
tc.runArgs = args
|
||||||
tc.runEnv = env
|
tc.runEnv = env
|
||||||
|
@ -25,7 +25,7 @@ func (tc *TestCommand) Synopsis() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func testEnvironment() *Environment {
|
func testEnvironment() Environment {
|
||||||
config := &EnvironmentConfig{}
|
config := &EnvironmentConfig{}
|
||||||
config.Ui = &ReaderWriterUi{
|
config.Ui = &ReaderWriterUi{
|
||||||
new(bytes.Buffer),
|
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")
|
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) {
|
func TestEnvironment_SettingUi(t *testing.T) {
|
||||||
assert := asserts.NewTestingAsserts(t, true)
|
assert := asserts.NewTestingAsserts(t, true)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ const Version = "0.1.0.dev"
|
||||||
type versionCommand byte
|
type versionCommand byte
|
||||||
|
|
||||||
// Implement the Command interface by simply showing the version
|
// 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)
|
env.Ui().Say("Packer v%v\n", Version)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue