From dc74ec56127e64640906ab850cd2b99dfd49fc16 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 25 May 2015 17:29:10 -0700 Subject: [PATCH] packer: remove Environment --- command/fix.go | 29 ++- command/inspect.go | 17 +- command/meta.go | 5 - command/validate.go | 100 +++++------ command/version.go | 12 +- commands.go | 1 - config.go | 3 - main.go | 20 +-- packer/core.go | 22 +++ packer/core_test.go | 11 ++ packer/environment.go | 183 ------------------- packer/environment_test.go | 310 --------------------------------- packer/rpc/client.go | 7 - packer/rpc/environment.go | 178 ------------------- packer/rpc/environment_test.go | 124 ------------- packer/rpc/server.go | 8 - signal.go | 6 +- 17 files changed, 102 insertions(+), 934 deletions(-) delete mode 100644 packer/environment.go delete mode 100644 packer/environment_test.go delete mode 100644 packer/rpc/environment.go delete mode 100644 packer/rpc/environment_test.go diff --git a/command/fix.go b/command/fix.go index aac0b3916..e908dc52e 100644 --- a/command/fix.go +++ b/command/fix.go @@ -3,7 +3,6 @@ package command import ( "bytes" "encoding/json" - "flag" "fmt" "log" "os" @@ -17,28 +16,22 @@ type FixCommand struct { } func (c *FixCommand) Run(args []string) int { - env, err := c.Meta.Environment() - if err != nil { - c.Ui.Error(fmt.Sprintf("Error initializing environment: %s", err)) + flags := c.Meta.FlagSet("fix", FlagSetNone) + flags.Usage = func() { c.Ui.Say(c.Help()) } + if err := flags.Parse(args); err != nil { return 1 } - cmdFlags := flag.NewFlagSet("fix", flag.ContinueOnError) - cmdFlags.Usage = func() { env.Ui().Say(c.Help()) } - if err := cmdFlags.Parse(args); err != nil { - return 1 - } - - args = cmdFlags.Args() + args = flags.Args() if len(args) != 1 { - cmdFlags.Usage() + flags.Usage() return 1 } // Read the file for decoding tplF, err := os.Open(args[0]) if err != nil { - env.Ui().Error(fmt.Sprintf("Error opening template: %s", err)) + c.Ui.Error(fmt.Sprintf("Error opening template: %s", err)) return 1 } defer tplF.Close() @@ -47,7 +40,7 @@ func (c *FixCommand) Run(args []string) int { var templateData map[string]interface{} decoder := json.NewDecoder(tplF) if err := decoder.Decode(&templateData); err != nil { - env.Ui().Error(fmt.Sprintf("Error parsing template: %s", err)) + c.Ui.Error(fmt.Sprintf("Error parsing template: %s", err)) return 1 } @@ -65,7 +58,7 @@ func (c *FixCommand) Run(args []string) int { log.Printf("Running fixer: %s", name) input, err = fixer.Fix(input) if err != nil { - env.Ui().Error(fmt.Sprintf("Error fixing: %s", err)) + c.Ui.Error(fmt.Sprintf("Error fixing: %s", err)) return 1 } } @@ -73,20 +66,20 @@ func (c *FixCommand) Run(args []string) int { var output bytes.Buffer encoder := json.NewEncoder(&output) if err := encoder.Encode(input); err != nil { - env.Ui().Error(fmt.Sprintf("Error encoding: %s", err)) + c.Ui.Error(fmt.Sprintf("Error encoding: %s", err)) return 1 } var indented bytes.Buffer if err := json.Indent(&indented, output.Bytes(), "", " "); err != nil { - env.Ui().Error(fmt.Sprintf("Error encoding: %s", err)) + c.Ui.Error(fmt.Sprintf("Error encoding: %s", err)) return 1 } result := indented.String() result = strings.Replace(result, `\u003c`, "<", -1) result = strings.Replace(result, `\u003e`, ">", -1) - env.Ui().Say(result) + c.Ui.Say(result) return 0 } diff --git a/command/inspect.go b/command/inspect.go index 8a9fd9569..2574615fb 100644 --- a/command/inspect.go +++ b/command/inspect.go @@ -1,7 +1,6 @@ package command import ( - "flag" "fmt" "github.com/mitchellh/packer/packer" "log" @@ -9,19 +8,13 @@ import ( "strings" ) -type InspectCommand struct{ +type InspectCommand struct { Meta } func (c *InspectCommand) Run(args []string) int { - env, err := c.Meta.Environment() - if err != nil { - c.Ui.Error(fmt.Sprintf("Error initializing environment: %s", err)) - return 1 - } - - flags := flag.NewFlagSet("inspect", flag.ContinueOnError) - flags.Usage = func() { env.Ui().Say(c.Help()) } + flags := c.Meta.FlagSet("build", FlagSetNone) + flags.Usage = func() { c.Ui.Say(c.Help()) } if err := flags.Parse(args); err != nil { return 1 } @@ -36,12 +29,12 @@ func (c *InspectCommand) Run(args []string) int { log.Printf("Reading template: %#v", args[0]) tpl, err := packer.ParseTemplateFile(args[0], nil) if err != nil { - env.Ui().Error(fmt.Sprintf("Failed to parse template: %s", err)) + c.Ui.Error(fmt.Sprintf("Failed to parse template: %s", err)) return 1 } // Convenience... - ui := env.Ui() + ui := c.Ui // Description if tpl.Description != "" { diff --git a/command/meta.go b/command/meta.go index bb059da35..e62577df9 100644 --- a/command/meta.go +++ b/command/meta.go @@ -26,7 +26,6 @@ const ( // Packer command inherits. type Meta struct { CoreConfig *packer.CoreConfig - EnvConfig *packer.EnvironmentConfig Ui packer.Ui // These are set by command-line flags @@ -148,7 +147,3 @@ func (m *Meta) ValidateFlags() error { // TODO return nil } - -func (m *Meta) Environment() (packer.Environment, error) { - return packer.NewEnvironment(m.EnvConfig) -} diff --git a/command/validate.go b/command/validate.go index a63019a9c..5d7e16c5d 100644 --- a/command/validate.go +++ b/command/validate.go @@ -1,12 +1,12 @@ package command import ( - "flag" "fmt" - cmdcommon "github.com/mitchellh/packer/common/command" - "github.com/mitchellh/packer/packer" "log" "strings" + + "github.com/mitchellh/packer/packer" + "github.com/mitchellh/packer/template" ) type ValidateCommand struct { @@ -15,72 +15,54 @@ type ValidateCommand struct { func (c *ValidateCommand) Run(args []string) int { var cfgSyntaxOnly bool - buildOptions := new(cmdcommon.BuildOptions) - - env, err := c.Meta.Environment() - if err != nil { - c.Ui.Error(fmt.Sprintf("Error initializing environment: %s", err)) + flags := c.Meta.FlagSet("validate", FlagSetBuildFilter|FlagSetVars) + flags.Usage = func() { c.Ui.Say(c.Help()) } + flags.BoolVar(&cfgSyntaxOnly, "syntax-only", false, "check syntax only") + if err := flags.Parse(args); err != nil { return 1 } - cmdFlags := flag.NewFlagSet("validate", flag.ContinueOnError) - cmdFlags.Usage = func() { env.Ui().Say(c.Help()) } - cmdFlags.BoolVar(&cfgSyntaxOnly, "syntax-only", false, "check syntax only") - cmdcommon.BuildOptionFlags(cmdFlags, buildOptions) - if err := cmdFlags.Parse(args); err != nil { - return 1 - } - - args = cmdFlags.Args() + args = flags.Args() if len(args) != 1 { - cmdFlags.Usage() + flags.Usage() return 1 } - if err := buildOptions.Validate(); err != nil { - env.Ui().Error(err.Error()) - env.Ui().Error("") - env.Ui().Error(c.Help()) - return 1 - } - - userVars, err := buildOptions.AllUserVars() + // Parse the template + tpl, err := template.ParseFile(args[0]) if err != nil { - env.Ui().Error(fmt.Sprintf("Error compiling user variables: %s", err)) - env.Ui().Error("") - env.Ui().Error(c.Help()) - return 1 - } - - // Parse the template into a machine-usable format - log.Printf("Reading template: %s", args[0]) - tpl, err := packer.ParseTemplateFile(args[0], userVars) - if err != nil { - env.Ui().Error(fmt.Sprintf("Failed to parse template: %s", err)) + c.Ui.Error(fmt.Sprintf("Failed to parse template: %s", err)) return 1 } + // If we're only checking syntax, then we're done already if cfgSyntaxOnly { - env.Ui().Say("Syntax-only check passed. Everything looks okay.") + c.Ui.Say("Syntax-only check passed. Everything looks okay.") return 0 } + // Get the core + core, err := c.Meta.Core(tpl) + if err != nil { + c.Ui.Error(err.Error()) + return 1 + } + errs := make([]error, 0) warnings := make(map[string][]string) - // The component finder for our builds - components := &packer.ComponentFinder{ - Builder: env.Builder, - Hook: env.Hook, - PostProcessor: env.PostProcessor, - Provisioner: env.Provisioner, - } + // Get the builds we care about + buildNames := c.Meta.BuildNames(core) + builds := make([]packer.Build, 0, len(buildNames)) + for _, n := range buildNames { + b, err := core.Build(n) + if err != nil { + c.Ui.Error(fmt.Sprintf( + "Failed to initialize build '%s': %s", + n, err)) + } - // Otherwise, get all the builds - builds, err := buildOptions.Builds(tpl, components) - if err != nil { - env.Ui().Error(err.Error()) - return 1 + builds = append(builds, b) } // Check the configuration of all builds @@ -96,12 +78,12 @@ func (c *ValidateCommand) Run(args []string) int { } if len(errs) > 0 { - env.Ui().Error("Template validation failed. Errors are shown below.\n") + c.Ui.Error("Template validation failed. Errors are shown below.\n") for i, err := range errs { - env.Ui().Error(err.Error()) + c.Ui.Error(err.Error()) if (i + 1) < len(errs) { - env.Ui().Error("") + c.Ui.Error("") } } @@ -109,21 +91,21 @@ func (c *ValidateCommand) Run(args []string) int { } if len(warnings) > 0 { - env.Ui().Say("Template validation succeeded, but there were some warnings.") - env.Ui().Say("These are ONLY WARNINGS, and Packer will attempt to build the") - env.Ui().Say("template despite them, but they should be paid attention to.\n") + c.Ui.Say("Template validation succeeded, but there were some warnings.") + c.Ui.Say("These are ONLY WARNINGS, and Packer will attempt to build the") + c.Ui.Say("template despite them, but they should be paid attention to.\n") for build, warns := range warnings { - env.Ui().Say(fmt.Sprintf("Warnings for build '%s':\n", build)) + c.Ui.Say(fmt.Sprintf("Warnings for build '%s':\n", build)) for _, warning := range warns { - env.Ui().Say(fmt.Sprintf("* %s", warning)) + c.Ui.Say(fmt.Sprintf("* %s", warning)) } } return 0 } - env.Ui().Say("Template validated successfully.") + c.Ui.Say("Template validated successfully.") return 0 } diff --git a/command/version.go b/command/version.go index d9358b3a6..cd170f2df 100644 --- a/command/version.go +++ b/command/version.go @@ -33,15 +33,9 @@ func (c *VersionCommand) Help() string { } func (c *VersionCommand) Run(args []string) int { - env, err := c.Meta.Environment() - if err != nil { - c.Ui.Error(fmt.Sprintf("Error initializing environment: %s", err)) - return 1 - } - - env.Ui().Machine("version", c.Version) - env.Ui().Machine("version-prelease", c.VersionPrerelease) - env.Ui().Machine("version-commit", c.Revision) + c.Ui.Machine("version", c.Version) + c.Ui.Machine("version-prelease", c.VersionPrerelease) + c.Ui.Machine("version-commit", c.Revision) var versionString bytes.Buffer fmt.Fprintf(&versionString, "Packer v%s", c.Version) diff --git a/commands.go b/commands.go index d3a458f16..e0f313957 100644 --- a/commands.go +++ b/commands.go @@ -21,7 +21,6 @@ const OutputPrefix = "o:" func init() { meta := command.Meta{ CoreConfig: &CoreConfig, - EnvConfig: &EnvConfig, Ui: &packer.BasicUi{ Reader: os.Stdin, Writer: os.Stdout, diff --git a/config.go b/config.go index 34cfdcb40..a9c07043f 100644 --- a/config.go +++ b/config.go @@ -16,9 +16,6 @@ import ( // CoreConfig is the global CoreConfig we use to initialize the CLI. var CoreConfig packer.CoreConfig -// EnvConfig is the global EnvironmentConfig we use to initialize the CLI. -var EnvConfig packer.EnvironmentConfig - type config struct { DisableCheckpoint bool `json:"disable_checkpoint"` DisableCheckpointSignature bool `json:"disable_checkpoint_signature"` diff --git a/main.go b/main.go index 8616a8e2d..73d4b88cf 100644 --- a/main.go +++ b/main.go @@ -140,14 +140,13 @@ func wrappedMain() int { defer plugin.CleanupClients() // Create the environment configuration - EnvConfig = *packer.DefaultEnvironmentConfig() - EnvConfig.Cache = cache - EnvConfig.Components.Builder = config.LoadBuilder - EnvConfig.Components.Hook = config.LoadHook - EnvConfig.Components.PostProcessor = config.LoadPostProcessor - EnvConfig.Components.Provisioner = config.LoadProvisioner + CoreConfig.Cache = cache + CoreConfig.Components.Builder = config.LoadBuilder + CoreConfig.Components.Hook = config.LoadHook + CoreConfig.Components.PostProcessor = config.LoadPostProcessor + CoreConfig.Components.Provisioner = config.LoadProvisioner if machineReadable { - EnvConfig.Ui = &packer.MachineReadableUi{ + CoreConfig.Ui = &packer.MachineReadableUi{ Writer: os.Stdout, } @@ -159,13 +158,6 @@ func wrappedMain() int { } } - // Create the core configuration - CoreConfig = packer.CoreConfig{ - Cache: EnvConfig.Cache, - Components: EnvConfig.Components, - Ui: EnvConfig.Ui, - } - //setupSignalHandlers(env) cli := &cli.CLI{ diff --git a/packer/core.go b/packer/core.go index 21ea4b8f9..4c4292ca7 100644 --- a/packer/core.go +++ b/packer/core.go @@ -31,6 +31,28 @@ type CoreConfig struct { Variables map[string]string } +// The function type used to lookup Builder implementations. +type BuilderFunc func(name string) (Builder, error) + +// The function type used to lookup Hook implementations. +type HookFunc func(name string) (Hook, error) + +// The function type used to lookup PostProcessor implementations. +type PostProcessorFunc func(name string) (PostProcessor, error) + +// The function type used to lookup Provisioner implementations. +type ProvisionerFunc func(name string) (Provisioner, error) + +// ComponentFinder is a struct that contains the various function +// pointers necessary to look up components of Packer such as builders, +// commands, etc. +type ComponentFinder struct { + Builder BuilderFunc + Hook HookFunc + PostProcessor PostProcessorFunc + Provisioner ProvisionerFunc +} + // NewCore creates a new Core. func NewCore(c *CoreConfig) (*Core, error) { if c.Ui == nil { diff --git a/packer/core_test.go b/packer/core_test.go index d3f338d12..d66a7786e 100644 --- a/packer/core_test.go +++ b/packer/core_test.go @@ -99,3 +99,14 @@ func TestCoreValidate(t *testing.T) { } } } + +func testComponentFinder() *ComponentFinder { + builderFactory := func(n string) (Builder, error) { return new(MockBuilder), nil } + ppFactory := func(n string) (PostProcessor, error) { return new(TestPostProcessor), nil } + provFactory := func(n string) (Provisioner, error) { return new(MockProvisioner), nil } + return &ComponentFinder{ + Builder: builderFactory, + PostProcessor: ppFactory, + Provisioner: provFactory, + } +} diff --git a/packer/environment.go b/packer/environment.go deleted file mode 100644 index 58585ffcf..000000000 --- a/packer/environment.go +++ /dev/null @@ -1,183 +0,0 @@ -// The packer package contains the core components of Packer. -package packer - -import ( - "errors" - "fmt" - "os" -) - -// The function type used to lookup Builder implementations. -type BuilderFunc func(name string) (Builder, error) - -// The function type used to lookup Hook implementations. -type HookFunc func(name string) (Hook, error) - -// The function type used to lookup PostProcessor implementations. -type PostProcessorFunc func(name string) (PostProcessor, error) - -// The function type used to lookup Provisioner implementations. -type ProvisionerFunc func(name string) (Provisioner, error) - -// ComponentFinder is a struct that contains the various function -// pointers necessary to look up components of Packer such as builders, -// commands, etc. -type ComponentFinder struct { - Builder BuilderFunc - Hook HookFunc - PostProcessor PostProcessorFunc - Provisioner ProvisionerFunc -} - -// The environment interface provides access to the configuration and -// state of a single Packer run. -// -// It allows for things such as executing CLI commands, getting the -// list of available builders, and more. -type Environment interface { - Builder(string) (Builder, error) - Cache() Cache - Hook(string) (Hook, error) - PostProcessor(string) (PostProcessor, error) - Provisioner(string) (Provisioner, error) - Ui() Ui -} - -// An implementation of an Environment that represents the Packer core -// environment. -type coreEnvironment struct { - cache Cache - components ComponentFinder - ui Ui -} - -// This struct configures new environments. -type EnvironmentConfig struct { - Cache Cache - Components ComponentFinder - Ui Ui -} - -// DefaultEnvironmentConfig returns a default EnvironmentConfig that can -// be used to create a new enviroment with NewEnvironment with sane defaults. -func DefaultEnvironmentConfig() *EnvironmentConfig { - config := &EnvironmentConfig{} - config.Ui = &BasicUi{ - Reader: os.Stdin, - Writer: os.Stdout, - ErrorWriter: os.Stdout, - } - - return config -} - -// This creates a new environment -func NewEnvironment(config *EnvironmentConfig) (resultEnv Environment, err error) { - if config == nil { - err = errors.New("config must be given to initialize environment") - return - } - - env := &coreEnvironment{} - env.cache = config.Cache - env.components = config.Components - env.ui = config.Ui - - // We want to make sure the components have valid function pointers. - // If a function pointer was not given, we assume that the function - // will just return a nil component. - if env.components.Builder == nil { - env.components.Builder = func(string) (Builder, error) { return nil, nil } - } - - if env.components.Hook == nil { - env.components.Hook = func(string) (Hook, error) { return nil, nil } - } - - if env.components.PostProcessor == nil { - env.components.PostProcessor = func(string) (PostProcessor, error) { return nil, nil } - } - - if env.components.Provisioner == nil { - env.components.Provisioner = func(string) (Provisioner, error) { return nil, nil } - } - - // The default cache is just the system temporary directory - if env.cache == nil { - env.cache = &FileCache{CacheDir: os.TempDir()} - } - - resultEnv = env - return -} - -// Returns a builder of the given name that is registered with this -// environment. -func (e *coreEnvironment) Builder(name string) (b Builder, err error) { - b, err = e.components.Builder(name) - if err != nil { - return - } - - if b == nil { - err = fmt.Errorf("No builder returned for name: %s", name) - } - - return -} - -// Returns the cache for this environment -func (e *coreEnvironment) Cache() Cache { - return e.cache -} - -// Returns a hook of the given name that is registered with this -// environment. -func (e *coreEnvironment) Hook(name string) (h Hook, err error) { - h, err = e.components.Hook(name) - if err != nil { - return - } - - if h == nil { - err = fmt.Errorf("No hook returned for name: %s", name) - } - - return -} - -// Returns a PostProcessor for the given name that is registered with this -// environment. -func (e *coreEnvironment) PostProcessor(name string) (p PostProcessor, err error) { - p, err = e.components.PostProcessor(name) - if err != nil { - return - } - - if p == nil { - err = fmt.Errorf("No post processor found for name: %s", name) - } - - return -} - -// Returns a provisioner for the given name that is registered with this -// environment. -func (e *coreEnvironment) Provisioner(name string) (p Provisioner, err error) { - p, err = e.components.Provisioner(name) - if err != nil { - return - } - - if p == nil { - err = fmt.Errorf("No provisioner returned for name: %s", name) - } - - return -} - -// Returns the UI for the environment. The UI is the interface that should -// be used for all communication with the outside world. -func (e *coreEnvironment) Ui() Ui { - return e.ui -} diff --git a/packer/environment_test.go b/packer/environment_test.go deleted file mode 100644 index 80edab58e..000000000 --- a/packer/environment_test.go +++ /dev/null @@ -1,310 +0,0 @@ -package packer - -import ( - "bytes" - "errors" - "io/ioutil" - "log" - "os" - "testing" -) - -func init() { - // Disable log output for tests - log.SetOutput(ioutil.Discard) -} - -func testComponentFinder() *ComponentFinder { - builderFactory := func(n string) (Builder, error) { return new(MockBuilder), nil } - ppFactory := func(n string) (PostProcessor, error) { return new(TestPostProcessor), nil } - provFactory := func(n string) (Provisioner, error) { return new(MockProvisioner), nil } - return &ComponentFinder{ - Builder: builderFactory, - PostProcessor: ppFactory, - Provisioner: provFactory, - } -} - -func testEnvironment() Environment { - config := DefaultEnvironmentConfig() - config.Ui = &BasicUi{ - Reader: new(bytes.Buffer), - Writer: new(bytes.Buffer), - ErrorWriter: new(bytes.Buffer), - } - - env, err := NewEnvironment(config) - if err != nil { - panic(err) - } - - return env -} - -func TestEnvironment_DefaultConfig_Ui(t *testing.T) { - config := DefaultEnvironmentConfig() - if config.Ui == nil { - t.Fatal("config.Ui should not be nil") - } - - rwUi, ok := config.Ui.(*BasicUi) - if !ok { - t.Fatal("default UI should be BasicUi") - } - if rwUi.Writer != os.Stdout { - t.Fatal("default UI should go to stdout") - } - if rwUi.Reader != os.Stdin { - t.Fatal("default UI reader should go to stdin") - } -} - -func TestNewEnvironment_NoConfig(t *testing.T) { - env, err := NewEnvironment(nil) - if env != nil { - t.Fatal("env should be nil") - } - if err == nil { - t.Fatal("should have error") - } -} - -func TestEnvironment_NilComponents(t *testing.T) { - config := DefaultEnvironmentConfig() - config.Components = *new(ComponentFinder) - - env, err := NewEnvironment(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - // All of these should not cause panics... so we don't assert - // anything but if there is a panic in the test then yeah, something - // went wrong. - env.Builder("foo") - env.Hook("foo") - env.PostProcessor("foo") - env.Provisioner("foo") -} - -func TestEnvironment_Builder(t *testing.T) { - builder := &MockBuilder{} - builders := make(map[string]Builder) - builders["foo"] = builder - - config := DefaultEnvironmentConfig() - config.Components.Builder = func(n string) (Builder, error) { return builders[n], nil } - - env, _ := NewEnvironment(config) - returnedBuilder, err := env.Builder("foo") - if err != nil { - t.Fatalf("err: %s", err) - } - if returnedBuilder != builder { - t.Fatalf("bad: %#v", returnedBuilder) - } -} - -func TestEnvironment_Builder_NilError(t *testing.T) { - config := DefaultEnvironmentConfig() - config.Components.Builder = func(n string) (Builder, error) { return nil, nil } - - env, _ := NewEnvironment(config) - returnedBuilder, err := env.Builder("foo") - if err == nil { - t.Fatal("should have error") - } - if returnedBuilder != nil { - t.Fatalf("bad: %#v", returnedBuilder) - } -} - -func TestEnvironment_Builder_Error(t *testing.T) { - config := DefaultEnvironmentConfig() - config.Components.Builder = func(n string) (Builder, error) { return nil, errors.New("foo") } - - env, _ := NewEnvironment(config) - returnedBuilder, err := env.Builder("foo") - if err == nil { - t.Fatal("should have error") - } - if err.Error() != "foo" { - t.Fatalf("bad err: %s", err) - } - if returnedBuilder != nil { - t.Fatalf("should be nil: %#v", returnedBuilder) - } -} - -func TestEnvironment_Cache(t *testing.T) { - config := DefaultEnvironmentConfig() - env, _ := NewEnvironment(config) - if env.Cache() == nil { - t.Fatal("cache should not be nil") - } -} - -func TestEnvironment_Hook(t *testing.T) { - hook := &MockHook{} - hooks := make(map[string]Hook) - hooks["foo"] = hook - - config := DefaultEnvironmentConfig() - config.Components.Hook = func(n string) (Hook, error) { return hooks[n], nil } - - env, _ := NewEnvironment(config) - returned, err := env.Hook("foo") - if err != nil { - t.Fatalf("err: %s", err) - } - if returned != hook { - t.Fatalf("bad: %#v", returned) - } -} - -func TestEnvironment_Hook_NilError(t *testing.T) { - config := DefaultEnvironmentConfig() - config.Components.Hook = func(n string) (Hook, error) { return nil, nil } - - env, _ := NewEnvironment(config) - returned, err := env.Hook("foo") - if err == nil { - t.Fatal("should have error") - } - if returned != nil { - t.Fatalf("bad: %#v", returned) - } -} - -func TestEnvironment_Hook_Error(t *testing.T) { - config := DefaultEnvironmentConfig() - config.Components.Hook = func(n string) (Hook, error) { return nil, errors.New("foo") } - - env, _ := NewEnvironment(config) - returned, err := env.Hook("foo") - if err == nil { - t.Fatal("should have error") - } - if err.Error() != "foo" { - t.Fatalf("err: %s", err) - } - if returned != nil { - t.Fatalf("bad: %#v", returned) - } -} - -func TestEnvironment_PostProcessor(t *testing.T) { - pp := &TestPostProcessor{} - pps := make(map[string]PostProcessor) - pps["foo"] = pp - - config := DefaultEnvironmentConfig() - config.Components.PostProcessor = func(n string) (PostProcessor, error) { return pps[n], nil } - - env, _ := NewEnvironment(config) - returned, err := env.PostProcessor("foo") - if err != nil { - t.Fatalf("err: %s", err) - } - if returned != pp { - t.Fatalf("bad: %#v", returned) - } -} - -func TestEnvironment_PostProcessor_NilError(t *testing.T) { - config := DefaultEnvironmentConfig() - config.Components.PostProcessor = func(n string) (PostProcessor, error) { return nil, nil } - - env, _ := NewEnvironment(config) - returned, err := env.PostProcessor("foo") - if err == nil { - t.Fatal("should have error") - } - if returned != nil { - t.Fatalf("bad: %#v", returned) - } -} - -func TestEnvironment_PostProcessor_Error(t *testing.T) { - config := DefaultEnvironmentConfig() - config.Components.PostProcessor = func(n string) (PostProcessor, error) { return nil, errors.New("foo") } - - env, _ := NewEnvironment(config) - returned, err := env.PostProcessor("foo") - if err == nil { - t.Fatal("should be an error") - } - if err.Error() != "foo" { - t.Fatalf("bad err: %s", err) - } - if returned != nil { - t.Fatalf("bad: %#v", returned) - } -} - -func TestEnvironmentProvisioner(t *testing.T) { - p := &MockProvisioner{} - ps := make(map[string]Provisioner) - ps["foo"] = p - - config := DefaultEnvironmentConfig() - config.Components.Provisioner = func(n string) (Provisioner, error) { return ps[n], nil } - - env, _ := NewEnvironment(config) - returned, err := env.Provisioner("foo") - if err != nil { - t.Fatalf("err: %s", err) - } - if returned != p { - t.Fatalf("bad: %#v", returned) - } -} - -func TestEnvironmentProvisioner_NilError(t *testing.T) { - config := DefaultEnvironmentConfig() - config.Components.Provisioner = func(n string) (Provisioner, error) { return nil, nil } - - env, _ := NewEnvironment(config) - returned, err := env.Provisioner("foo") - if err == nil { - t.Fatal("should have error") - } - if returned != nil { - t.Fatalf("bad: %#v", returned) - } -} - -func TestEnvironmentProvisioner_Error(t *testing.T) { - config := DefaultEnvironmentConfig() - config.Components.Provisioner = func(n string) (Provisioner, error) { - return nil, errors.New("foo") - } - - env, _ := NewEnvironment(config) - returned, err := env.Provisioner("foo") - if err == nil { - t.Fatal("should have error") - } - if err.Error() != "foo" { - t.Fatalf("err: %s", err) - } - if returned != nil { - t.Fatalf("bad: %#v", returned) - } -} - -func TestEnvironment_SettingUi(t *testing.T) { - ui := &BasicUi{ - Reader: new(bytes.Buffer), - Writer: new(bytes.Buffer), - } - - config := &EnvironmentConfig{} - config.Ui = ui - - env, _ := NewEnvironment(config) - - if env.Ui() != ui { - t.Fatalf("UI should be equal: %#v", env.Ui()) - } -} diff --git a/packer/rpc/client.go b/packer/rpc/client.go index 0e0140028..2f682f47a 100644 --- a/packer/rpc/client.go +++ b/packer/rpc/client.go @@ -100,13 +100,6 @@ func (c *Client) Communicator() packer.Communicator { } } -func (c *Client) Environment() packer.Environment { - return &Environment{ - client: c.client, - mux: c.mux, - } -} - func (c *Client) Hook() packer.Hook { return &hook{ client: c.client, diff --git a/packer/rpc/environment.go b/packer/rpc/environment.go deleted file mode 100644 index 4e2b73da8..000000000 --- a/packer/rpc/environment.go +++ /dev/null @@ -1,178 +0,0 @@ -package rpc - -import ( - "github.com/mitchellh/packer/packer" - "log" - "net/rpc" -) - -// A Environment is an implementation of the packer.Environment interface -// where the actual environment is executed over an RPC connection. -type Environment struct { - client *rpc.Client - mux *muxBroker -} - -// A EnvironmentServer wraps a packer.Environment and makes it exportable -// as part of a Golang RPC server. -type EnvironmentServer struct { - env packer.Environment - mux *muxBroker -} - -func (e *Environment) Builder(name string) (b packer.Builder, err error) { - var streamId uint32 - err = e.client.Call("Environment.Builder", name, &streamId) - if err != nil { - return - } - - client, err := newClientWithMux(e.mux, streamId) - if err != nil { - return nil, err - } - b = client.Builder() - return -} - -func (e *Environment) Cache() packer.Cache { - var streamId uint32 - if err := e.client.Call("Environment.Cache", new(interface{}), &streamId); err != nil { - panic(err) - } - - client, err := newClientWithMux(e.mux, streamId) - if err != nil { - log.Printf("[ERR] Error getting cache client: %s", err) - return nil - } - return client.Cache() -} - -func (e *Environment) Hook(name string) (h packer.Hook, err error) { - var streamId uint32 - err = e.client.Call("Environment.Hook", name, &streamId) - if err != nil { - return - } - - client, err := newClientWithMux(e.mux, streamId) - if err != nil { - return nil, err - } - return client.Hook(), nil -} - -func (e *Environment) PostProcessor(name string) (p packer.PostProcessor, err error) { - var streamId uint32 - err = e.client.Call("Environment.PostProcessor", name, &streamId) - if err != nil { - return - } - - client, err := newClientWithMux(e.mux, streamId) - if err != nil { - return nil, err - } - p = client.PostProcessor() - return -} - -func (e *Environment) Provisioner(name string) (p packer.Provisioner, err error) { - var streamId uint32 - err = e.client.Call("Environment.Provisioner", name, &streamId) - if err != nil { - return - } - - client, err := newClientWithMux(e.mux, streamId) - if err != nil { - return nil, err - } - p = client.Provisioner() - return -} - -func (e *Environment) Ui() packer.Ui { - var streamId uint32 - e.client.Call("Environment.Ui", new(interface{}), &streamId) - - client, err := newClientWithMux(e.mux, streamId) - if err != nil { - log.Printf("[ERR] Error connecting to Ui: %s", err) - return nil - } - return client.Ui() -} - -func (e *EnvironmentServer) Builder(name string, reply *uint32) error { - builder, err := e.env.Builder(name) - if err != nil { - return NewBasicError(err) - } - - *reply = e.mux.NextId() - server := newServerWithMux(e.mux, *reply) - server.RegisterBuilder(builder) - go server.Serve() - return nil -} - -func (e *EnvironmentServer) Cache(args *interface{}, reply *uint32) error { - cache := e.env.Cache() - - *reply = e.mux.NextId() - server := newServerWithMux(e.mux, *reply) - server.RegisterCache(cache) - go server.Serve() - return nil -} - -func (e *EnvironmentServer) Hook(name string, reply *uint32) error { - hook, err := e.env.Hook(name) - if err != nil { - return NewBasicError(err) - } - - *reply = e.mux.NextId() - server := newServerWithMux(e.mux, *reply) - server.RegisterHook(hook) - go server.Serve() - return nil -} - -func (e *EnvironmentServer) PostProcessor(name string, reply *uint32) error { - pp, err := e.env.PostProcessor(name) - if err != nil { - return NewBasicError(err) - } - - *reply = e.mux.NextId() - server := newServerWithMux(e.mux, *reply) - server.RegisterPostProcessor(pp) - go server.Serve() - return nil -} - -func (e *EnvironmentServer) Provisioner(name string, reply *uint32) error { - prov, err := e.env.Provisioner(name) - if err != nil { - return NewBasicError(err) - } - - *reply = e.mux.NextId() - server := newServerWithMux(e.mux, *reply) - server.RegisterProvisioner(prov) - go server.Serve() - return nil -} - -func (e *EnvironmentServer) Ui(args *interface{}, reply *uint32) error { - ui := e.env.Ui() - - *reply = e.mux.NextId() - server := newServerWithMux(e.mux, *reply) - server.RegisterUi(ui) - go server.Serve() - return nil -} diff --git a/packer/rpc/environment_test.go b/packer/rpc/environment_test.go deleted file mode 100644 index a5085d0ef..000000000 --- a/packer/rpc/environment_test.go +++ /dev/null @@ -1,124 +0,0 @@ -package rpc - -import ( - "github.com/mitchellh/packer/packer" - "testing" -) - -var testEnvBuilder = &packer.MockBuilder{} -var testEnvCache = &testCache{} -var testEnvUi = &testUi{} - -type testEnvironment struct { - builderCalled bool - builderName string - cliCalled bool - cliArgs []string - hookCalled bool - hookName string - ppCalled bool - ppName string - provCalled bool - provName string - uiCalled bool -} - -func (e *testEnvironment) Builder(name string) (packer.Builder, error) { - e.builderCalled = true - e.builderName = name - return testEnvBuilder, nil -} - -func (e *testEnvironment) Cache() packer.Cache { - return testEnvCache -} - -func (e *testEnvironment) Cli(args []string) (int, error) { - e.cliCalled = true - e.cliArgs = args - return 42, nil -} - -func (e *testEnvironment) Hook(name string) (packer.Hook, error) { - e.hookCalled = true - e.hookName = name - return nil, nil -} - -func (e *testEnvironment) PostProcessor(name string) (packer.PostProcessor, error) { - e.ppCalled = true - e.ppName = name - return nil, nil -} - -func (e *testEnvironment) Provisioner(name string) (packer.Provisioner, error) { - e.provCalled = true - e.provName = name - return nil, nil -} - -func (e *testEnvironment) Ui() packer.Ui { - e.uiCalled = true - return testEnvUi -} - -func TestEnvironmentRPC(t *testing.T) { - // Create the interface to test - e := &testEnvironment{} - - // Start the server - client, server := testClientServer(t) - defer client.Close() - defer server.Close() - server.RegisterEnvironment(e) - eClient := client.Environment() - - // Test Builder - builder, _ := eClient.Builder("foo") - if !e.builderCalled { - t.Fatal("builder should be called") - } - if e.builderName != "foo" { - t.Fatalf("bad: %#v", e.builderName) - } - - builder.Prepare(nil) - if !testEnvBuilder.PrepareCalled { - t.Fatal("should be called") - } - - // Test Cache - cache := eClient.Cache() - cache.Lock("foo") - if !testEnvCache.lockCalled { - t.Fatal("should be called") - } - - // Test Provisioner - _, _ = eClient.Provisioner("foo") - if !e.provCalled { - t.Fatal("should be called") - } - if e.provName != "foo" { - t.Fatalf("bad: %s", e.provName) - } - - // Test Ui - ui := eClient.Ui() - if !e.uiCalled { - t.Fatal("should be called") - } - - // Test calls on the Ui - ui.Say("format") - if !testEnvUi.sayCalled { - t.Fatal("should be called") - } - if testEnvUi.sayMessage != "format" { - t.Fatalf("bad: %#v", testEnvUi.sayMessage) - } -} - -func TestEnvironment_ImplementsEnvironment(t *testing.T) { - var _ packer.Environment = new(Environment) -} diff --git a/packer/rpc/server.go b/packer/rpc/server.go index 1f3e7eef2..b6d17dacf 100644 --- a/packer/rpc/server.go +++ b/packer/rpc/server.go @@ -19,7 +19,6 @@ const ( DefaultCacheEndpoint = "Cache" DefaultCommandEndpoint = "Command" DefaultCommunicatorEndpoint = "Communicator" - DefaultEnvironmentEndpoint = "Environment" DefaultHookEndpoint = "Hook" DefaultPostProcessorEndpoint = "PostProcessor" DefaultProvisionerEndpoint = "Provisioner" @@ -95,13 +94,6 @@ func (s *Server) RegisterCommunicator(c packer.Communicator) { }) } -func (s *Server) RegisterEnvironment(b packer.Environment) { - s.server.RegisterName(DefaultEnvironmentEndpoint, &EnvironmentServer{ - env: b, - mux: s.mux, - }) -} - func (s *Server) RegisterHook(h packer.Hook) { s.server.RegisterName(DefaultHookEndpoint, &HookServer{ hook: h, diff --git a/signal.go b/signal.go index b198558d7..e63dd2fe5 100644 --- a/signal.go +++ b/signal.go @@ -10,7 +10,7 @@ import ( // Prepares the signal handlers so that we handle interrupts properly. // The signal handler exists in a goroutine. -func setupSignalHandlers(env packer.Environment) { +func setupSignalHandlers(ui packer.Ui) { ch := make(chan os.Signal, 1) signal.Notify(ch, os.Interrupt) @@ -20,13 +20,13 @@ func setupSignalHandlers(env packer.Environment) { <-ch log.Println("First interrupt. Ignoring to allow plugins to clean up.") - env.Ui().Error("Interrupt signal received. Cleaning up...") + ui.Error("Interrupt signal received. Cleaning up...") // Second interrupt. Go down hard. <-ch log.Println("Second interrupt. Exiting now.") - env.Ui().Error("Interrupt signal received twice. Forcefully exiting now.") + ui.Error("Interrupt signal received twice. Forcefully exiting now.") // Force kill all the plugins, but mark that we're killing them // first so that we don't get panics everywhere.