From 8054e66db66fae64ca4415a146607a44df1c9b9d Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 27 Oct 2014 20:31:02 -0700 Subject: [PATCH] command: move more to this package, remove old packages --- command/build/command.go | 283 ------------------- command/build/command_test.go | 54 ---- command/build/help.go | 19 -- command/{inspect/command.go => inspect.go} | 38 ++- command/inspect/command_test.go | 14 - command/inspect/help.go | 13 - command/{validate/command.go => validate.go} | 41 ++- command/validate/command_test.go | 14 - command/validate/help.go | 20 -- commands.go | 29 +- log.go | 29 ++ packer.go | 149 ++++++---- plugin/command-build/main.go | 15 - plugin/command-build/main_test.go | 1 - plugin/command-inspect/main.go | 15 - plugin/command-inspect/main_test.go | 1 - plugin/command-validate/main.go | 15 - plugin/command-validate/main_test.go | 1 - 18 files changed, 208 insertions(+), 543 deletions(-) delete mode 100644 command/build/command.go delete mode 100644 command/build/command_test.go delete mode 100644 command/build/help.go rename command/{inspect/command.go => inspect.go} (82%) delete mode 100644 command/inspect/command_test.go delete mode 100644 command/inspect/help.go rename command/{validate/command.go => validate.go} (72%) delete mode 100644 command/validate/command_test.go delete mode 100644 command/validate/help.go create mode 100644 log.go delete mode 100644 plugin/command-build/main.go delete mode 100644 plugin/command-build/main_test.go delete mode 100644 plugin/command-inspect/main.go delete mode 100644 plugin/command-inspect/main_test.go delete mode 100644 plugin/command-validate/main.go delete mode 100644 plugin/command-validate/main_test.go diff --git a/command/build/command.go b/command/build/command.go deleted file mode 100644 index ee2119a22..000000000 --- a/command/build/command.go +++ /dev/null @@ -1,283 +0,0 @@ -package build - -import ( - "bytes" - "flag" - "fmt" - cmdcommon "github.com/mitchellh/packer/common/command" - "github.com/mitchellh/packer/packer" - "log" - "os" - "os/signal" - "strconv" - "strings" - "sync" -) - -type Command byte - -func (Command) Help() string { - return strings.TrimSpace(helpText) -} - -func (c Command) Run(env packer.Environment, args []string) int { - var cfgColor, cfgDebug, cfgForce, cfgParallel bool - buildOptions := new(cmdcommon.BuildOptions) - - cmdFlags := flag.NewFlagSet("build", flag.ContinueOnError) - cmdFlags.Usage = func() { env.Ui().Say(c.Help()) } - cmdFlags.BoolVar(&cfgColor, "color", true, "enable or disable color") - cmdFlags.BoolVar(&cfgDebug, "debug", false, "debug mode for builds") - cmdFlags.BoolVar(&cfgForce, "force", false, "force a build if artifacts exist") - cmdFlags.BoolVar(&cfgParallel, "parallel", true, "enable/disable parallelization") - cmdcommon.BuildOptionFlags(cmdFlags, buildOptions) - if err := cmdFlags.Parse(args); err != nil { - return 1 - } - - args = cmdFlags.Args() - if len(args) != 1 { - cmdFlags.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() - if err != nil { - env.Ui().Error(fmt.Sprintf("Error compiling user variables: %s", err)) - env.Ui().Error("") - env.Ui().Error(c.Help()) - return 1 - } - - // Read the file into a byte array so that we can parse the template - 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)) - return 1 - } - - // The component finder for our builds - components := &packer.ComponentFinder{ - Builder: env.Builder, - Hook: env.Hook, - PostProcessor: env.PostProcessor, - Provisioner: env.Provisioner, - } - - // Go through each builder and compile the builds that we care about - builds, err := buildOptions.Builds(tpl, components) - if err != nil { - env.Ui().Error(err.Error()) - return 1 - } - - if cfgDebug { - env.Ui().Say("Debug mode enabled. Builds will not be parallelized.") - } - - // Compile all the UIs for the builds - colors := [5]packer.UiColor{ - packer.UiColorGreen, - packer.UiColorCyan, - packer.UiColorMagenta, - packer.UiColorYellow, - packer.UiColorBlue, - } - - buildUis := make(map[string]packer.Ui) - for i, b := range builds { - var ui packer.Ui - ui = env.Ui() - if cfgColor { - ui = &packer.ColoredUi{ - Color: colors[i%len(colors)], - Ui: env.Ui(), - } - } - - buildUis[b.Name()] = ui - ui.Say(fmt.Sprintf("%s output will be in this color.", b.Name())) - } - - // Add a newline between the color output and the actual output - env.Ui().Say("") - - log.Printf("Build debug mode: %v", cfgDebug) - log.Printf("Force build: %v", cfgForce) - - // Set the debug and force mode and prepare all the builds - for _, b := range builds { - log.Printf("Preparing build: %s", b.Name()) - b.SetDebug(cfgDebug) - b.SetForce(cfgForce) - - warnings, err := b.Prepare() - if err != nil { - env.Ui().Error(err.Error()) - return 1 - } - if len(warnings) > 0 { - ui := buildUis[b.Name()] - ui.Say(fmt.Sprintf("Warnings for build '%s':\n", b.Name())) - for _, warning := range warnings { - ui.Say(fmt.Sprintf("* %s", warning)) - } - ui.Say("") - } - } - - // Run all the builds in parallel and wait for them to complete - var interruptWg, wg sync.WaitGroup - interrupted := false - artifacts := make(map[string][]packer.Artifact) - errors := make(map[string]error) - for _, b := range builds { - // Increment the waitgroup so we wait for this item to finish properly - wg.Add(1) - - // Handle interrupts for this build - sigCh := make(chan os.Signal, 1) - signal.Notify(sigCh, os.Interrupt) - defer signal.Stop(sigCh) - go func(b packer.Build) { - <-sigCh - interruptWg.Add(1) - defer interruptWg.Done() - interrupted = true - - log.Printf("Stopping build: %s", b.Name()) - b.Cancel() - log.Printf("Build cancelled: %s", b.Name()) - }(b) - - // Run the build in a goroutine - go func(b packer.Build) { - defer wg.Done() - - name := b.Name() - log.Printf("Starting build run: %s", name) - ui := buildUis[name] - runArtifacts, err := b.Run(ui, env.Cache()) - - if err != nil { - ui.Error(fmt.Sprintf("Build '%s' errored: %s", name, err)) - errors[name] = err - } else { - ui.Say(fmt.Sprintf("Build '%s' finished.", name)) - artifacts[name] = runArtifacts - } - }(b) - - if cfgDebug { - log.Printf("Debug enabled, so waiting for build to finish: %s", b.Name()) - wg.Wait() - } - - if !cfgParallel { - log.Printf("Parallelization disabled, waiting for build to finish: %s", b.Name()) - wg.Wait() - } - - if interrupted { - log.Println("Interrupted, not going to start any more builds.") - break - } - } - - // Wait for both the builds to complete and the interrupt handler, - // if it is interrupted. - log.Printf("Waiting on builds to complete...") - wg.Wait() - - log.Printf("Builds completed. Waiting on interrupt barrier...") - interruptWg.Wait() - - if interrupted { - env.Ui().Say("Cleanly cancelled builds after being interrupted.") - return 1 - } - - if len(errors) > 0 { - env.Ui().Machine("error-count", strconv.FormatInt(int64(len(errors)), 10)) - - env.Ui().Error("\n==> Some builds didn't complete successfully and had errors:") - for name, err := range errors { - // Create a UI for the machine readable stuff to be targetted - ui := &packer.TargettedUi{ - Target: name, - Ui: env.Ui(), - } - - ui.Machine("error", err.Error()) - - env.Ui().Error(fmt.Sprintf("--> %s: %s", name, err)) - } - } - - if len(artifacts) > 0 { - env.Ui().Say("\n==> Builds finished. The artifacts of successful builds are:") - for name, buildArtifacts := range artifacts { - // Create a UI for the machine readable stuff to be targetted - ui := &packer.TargettedUi{ - Target: name, - Ui: env.Ui(), - } - - // Machine-readable helpful - ui.Machine("artifact-count", strconv.FormatInt(int64(len(buildArtifacts)), 10)) - - for i, artifact := range buildArtifacts { - var message bytes.Buffer - fmt.Fprintf(&message, "--> %s: ", name) - - if artifact != nil { - fmt.Fprintf(&message, artifact.String()) - } else { - fmt.Fprint(&message, "") - } - - iStr := strconv.FormatInt(int64(i), 10) - if artifact != nil { - ui.Machine("artifact", iStr, "builder-id", artifact.BuilderId()) - ui.Machine("artifact", iStr, "id", artifact.Id()) - ui.Machine("artifact", iStr, "string", artifact.String()) - - files := artifact.Files() - ui.Machine("artifact", - iStr, - "files-count", strconv.FormatInt(int64(len(files)), 10)) - for fi, file := range files { - fiStr := strconv.FormatInt(int64(fi), 10) - ui.Machine("artifact", iStr, "file", fiStr, file) - } - } else { - ui.Machine("artifact", iStr, "nil") - } - - ui.Machine("artifact", iStr, "end") - env.Ui().Say(message.String()) - } - } - } else { - env.Ui().Say("\n==> Builds finished but no artifacts were created.") - } - - if len(errors) > 0 { - // If any errors occurred, exit with a non-zero exit status - return 1 - } - - return 0 -} - -func (Command) Synopsis() string { - return "build image(s) from template" -} diff --git a/command/build/command_test.go b/command/build/command_test.go deleted file mode 100644 index 2edd82b4a..000000000 --- a/command/build/command_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package build - -import ( - "bytes" - "github.com/mitchellh/packer/packer" - "testing" -) - -func testEnvironment() packer.Environment { - config := packer.DefaultEnvironmentConfig() - config.Ui = &packer.BasicUi{ - Reader: new(bytes.Buffer), - Writer: new(bytes.Buffer), - } - - env, err := packer.NewEnvironment(config) - if err != nil { - panic(err) - } - - return env -} - -func TestCommand_Implements(t *testing.T) { - var _ packer.Command = new(Command) -} - -func TestCommand_Run_NoArgs(t *testing.T) { - command := new(Command) - result := command.Run(testEnvironment(), make([]string, 0)) - if result != 1 { - t.Fatalf("bad: %d", result) - } -} - -func TestCommand_Run_MoreThanOneArg(t *testing.T) { - command := new(Command) - - args := []string{"one", "two"} - result := command.Run(testEnvironment(), args) - if result != 1 { - t.Fatalf("bad: %d", result) - } -} - -func TestCommand_Run_MissingFile(t *testing.T) { - command := new(Command) - - args := []string{"i-better-not-exist"} - result := command.Run(testEnvironment(), args) - if result != 1 { - t.Fatalf("bad: %d", result) - } -} diff --git a/command/build/help.go b/command/build/help.go deleted file mode 100644 index 5b27a53ad..000000000 --- a/command/build/help.go +++ /dev/null @@ -1,19 +0,0 @@ -package build - -const helpText = ` -Usage: packer build [options] TEMPLATE - - Will execute multiple builds in parallel as defined in the template. - The various artifacts created by the template will be outputted. - -Options: - - -debug Debug mode enabled for builds - -force Force a build to continue if artifacts exist, deletes existing artifacts - -machine-readable Machine-readable output - -except=foo,bar,baz Build all builds other than these - -only=foo,bar,baz Only build the given builds by name - -parallel=false Disable parallelization (on by default) - -var 'key=value' Variable for templates, can be used multiple times. - -var-file=path JSON file containing user variables. -` diff --git a/command/inspect/command.go b/command/inspect.go similarity index 82% rename from command/inspect/command.go rename to command/inspect.go index 25d8427cc..8a9fd9569 100644 --- a/command/inspect/command.go +++ b/command/inspect.go @@ -1,4 +1,4 @@ -package inspect +package command import ( "flag" @@ -9,17 +9,17 @@ import ( "strings" ) -type Command struct{} - -func (Command) Help() string { - return strings.TrimSpace(helpText) +type InspectCommand struct{ + Meta } -func (c Command) Synopsis() string { - return "see components of a template" -} +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 + } -func (c Command) Run(env packer.Environment, args []string) int { flags := flag.NewFlagSet("inspect", flag.ContinueOnError) flags.Usage = func() { env.Ui().Say(c.Help()) } if err := flags.Parse(args); err != nil { @@ -148,3 +148,23 @@ func (c Command) Run(env packer.Environment, args []string) int { return 0 } + +func (*InspectCommand) Help() string { + helpText := ` +Usage: packer inspect TEMPLATE + + Inspects a template, parsing and outputting the components a template + defines. This does not validate the contents of a template (other than + basic syntax by necessity). + +Options: + + -machine-readable Machine-readable output +` + + return strings.TrimSpace(helpText) +} + +func (c *InspectCommand) Synopsis() string { + return "see components of a template" +} diff --git a/command/inspect/command_test.go b/command/inspect/command_test.go deleted file mode 100644 index a2766fef4..000000000 --- a/command/inspect/command_test.go +++ /dev/null @@ -1,14 +0,0 @@ -package inspect - -import ( - "github.com/mitchellh/packer/packer" - "testing" -) - -func TestCommand_Impl(t *testing.T) { - var raw interface{} - raw = new(Command) - if _, ok := raw.(packer.Command); !ok { - t.Fatalf("must be a Command") - } -} diff --git a/command/inspect/help.go b/command/inspect/help.go deleted file mode 100644 index 320f24e8f..000000000 --- a/command/inspect/help.go +++ /dev/null @@ -1,13 +0,0 @@ -package inspect - -const helpText = ` -Usage: packer inspect TEMPLATE - - Inspects a template, parsing and outputting the components a template - defines. This does not validate the contents of a template (other than - basic syntax by necessity). - -Options: - - -machine-readable Machine-readable output -` diff --git a/command/validate/command.go b/command/validate.go similarity index 72% rename from command/validate/command.go rename to command/validate.go index 838ba13b5..a63019a9c 100644 --- a/command/validate/command.go +++ b/command/validate.go @@ -1,4 +1,4 @@ -package validate +package command import ( "flag" @@ -9,16 +9,20 @@ import ( "strings" ) -type Command byte - -func (Command) Help() string { - return strings.TrimSpace(helpString) +type ValidateCommand struct { + Meta } -func (c Command) Run(env packer.Environment, args []string) int { +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)) + 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") @@ -123,6 +127,29 @@ func (c Command) Run(env packer.Environment, args []string) int { return 0 } -func (Command) Synopsis() string { +func (*ValidateCommand) Help() string { + helpText := ` +Usage: packer validate [options] TEMPLATE + + Checks the template is valid by parsing the template and also + checking the configuration with the various builders, provisioners, etc. + + If it is not valid, the errors will be shown and the command will exit + with a non-zero exit status. If it is valid, it will exit with a zero + exit status. + +Options: + + -syntax-only Only check syntax. Do not verify config of the template. + -except=foo,bar,baz Validate all builds other than these + -only=foo,bar,baz Validate only these builds + -var 'key=value' Variable for templates, can be used multiple times. + -var-file=path JSON file containing user variables. +` + + return strings.TrimSpace(helpText) +} + +func (*ValidateCommand) Synopsis() string { return "check that a template is valid" } diff --git a/command/validate/command_test.go b/command/validate/command_test.go deleted file mode 100644 index 33fab19dd..000000000 --- a/command/validate/command_test.go +++ /dev/null @@ -1,14 +0,0 @@ -package validate - -import ( - "github.com/mitchellh/packer/packer" - "testing" -) - -func TestCommand_Impl(t *testing.T) { - var raw interface{} - raw = new(Command) - if _, ok := raw.(packer.Command); !ok { - t.Fatalf("must be a Command") - } -} diff --git a/command/validate/help.go b/command/validate/help.go deleted file mode 100644 index 8959cd881..000000000 --- a/command/validate/help.go +++ /dev/null @@ -1,20 +0,0 @@ -package validate - -const helpString = ` -Usage: packer validate [options] TEMPLATE - - Checks the template is valid by parsing the template and also - checking the configuration with the various builders, provisioners, etc. - - If it is not valid, the errors will be shown and the command will exit - with a non-zero exit status. If it is valid, it will exit with a zero - exit status. - -Options: - - -syntax-only Only check syntax. Do not verify config of the template. - -except=foo,bar,baz Validate all builds other than these - -only=foo,bar,baz Validate only these builds - -var 'key=value' Variable for templates, can be used multiple times. - -var-file=path JSON file containing user variables. -` diff --git a/commands.go b/commands.go index 215ec3dab..2b5179edd 100644 --- a/commands.go +++ b/commands.go @@ -18,16 +18,13 @@ const ErrorPrefix = "e:" const OutputPrefix = "o:" func init() { - Ui = &cli.BasicUi{Writer: os.Stdout} - /* - Ui = &cli.PrefixedUi{ - AskPrefix: OutputPrefix, - OutputPrefix: OutputPrefix, - InfoPrefix: OutputPrefix, - ErrorPrefix: ErrorPrefix, - Ui: &cli.BasicUi{Writer: os.Stdout}, - } - */ + Ui = &cli.PrefixedUi{ + AskPrefix: OutputPrefix, + OutputPrefix: OutputPrefix, + InfoPrefix: OutputPrefix, + ErrorPrefix: ErrorPrefix, + Ui: &cli.BasicUi{Writer: os.Stdout}, + } meta := command.Meta{ EnvConfig: &EnvConfig, @@ -40,6 +37,18 @@ func init() { Meta: meta, }, nil }, + + "inspect": func() (cli.Command, error) { + return &command.InspectCommand{ + Meta: meta, + }, nil + }, + + "validate": func() (cli.Command, error) { + return &command.ValidateCommand{ + Meta: meta, + }, nil + }, } } diff --git a/log.go b/log.go new file mode 100644 index 000000000..ad3593c55 --- /dev/null +++ b/log.go @@ -0,0 +1,29 @@ +package main + +import ( + "io" + "os" +) + +// These are the environmental variables that determine if we log, and if +// we log whether or not the log should go to a file. +const EnvLog = "PACKER_LOG" //Set to True +const EnvLogFile = "PACKER_LOG_PATH" //Set to a file + +// logOutput determines where we should send logs (if anywhere). +func logOutput() (logOutput io.Writer, err error) { + logOutput = nil + if os.Getenv(EnvLog) != "" { + logOutput = os.Stderr + + if logPath := os.Getenv(EnvLogFile); logPath != "" { + var err error + logOutput, err = os.Create(logPath) + if err != nil { + return nil, err + } + } + } + + return +} diff --git a/packer.go b/packer.go index 2fe63aa96..f72c876b4 100644 --- a/packer.go +++ b/packer.go @@ -9,11 +9,13 @@ import ( "os" "path/filepath" "runtime" + "sync" "github.com/mitchellh/cli" "github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer/plugin" "github.com/mitchellh/panicwrap" + "github.com/mitchellh/prefixedio" ) func main() { @@ -25,58 +27,77 @@ func main() { // realMain is executed from main and returns the exit status to exit with. func realMain() int { - // If there is no explicit number of Go threads to use, then set it - if os.Getenv("GOMAXPROCS") == "" { - runtime.GOMAXPROCS(runtime.NumCPU()) - } + var wrapConfig panicwrap.WrapConfig - // Determine where logs should go in general (requested by the user) - logWriter, err := logOutput() - if err != nil { - fmt.Fprintf(os.Stderr, "Couldn't setup log output: %s", err) - return 1 - } + if !panicwrap.Wrapped(&wrapConfig) { + // Determine where logs should go in general (requested by the user) + logWriter, err := logOutput() + if err != nil { + fmt.Fprintf(os.Stderr, "Couldn't setup log output: %s", err) + return 1 + } + if logWriter == nil { + logWriter = ioutil.Discard + } - // We also always send logs to a temporary file that we use in case - // there is a panic. Otherwise, we delete it. - logTempFile, err := ioutil.TempFile("", "packer-log") - if err != nil { - fmt.Fprintf(os.Stderr, "Couldn't setup logging tempfile: %s", err) - return 1 - } - defer os.Remove(logTempFile.Name()) - defer logTempFile.Close() + // We always send logs to a temporary file that we use in case + // there is a panic. Otherwise, we delete it. + logTempFile, err := ioutil.TempFile("", "packer-log") + if err != nil { + fmt.Fprintf(os.Stderr, "Couldn't setup logging tempfile: %s", err) + return 1 + } + defer os.Remove(logTempFile.Name()) + defer logTempFile.Close() + + // Tell the logger to log to this file + os.Setenv(EnvLog, "") + os.Setenv(EnvLogFile, "") + + // Setup the prefixed readers that send data properly to + // stdout/stderr. + doneCh := make(chan struct{}) + outR, outW := io.Pipe() + go copyOutput(outR, doneCh) + + // Create the configuration for panicwrap and wrap our executable + wrapConfig.Handler = panicHandler(logTempFile) + wrapConfig.Writer = io.MultiWriter(logTempFile, logWriter) + wrapConfig.Stdout = outW + exitStatus, err := panicwrap.Wrap(&wrapConfig) + if err != nil { + fmt.Fprintf(os.Stderr, "Couldn't start Packer: %s", err) + return 1 + } - // Reset the log variables to minimize work in the subprocess - os.Setenv("PACKER_LOG", "") - os.Setenv("PACKER_LOG_FILE", "") + // If >= 0, we're the parent, so just exit + if exitStatus >= 0 { + // Close the stdout writer so that our copy process can finish + outW.Close() - // Create the configuration for panicwrap and wrap our executable - wrapConfig := &panicwrap.WrapConfig{ - Handler: panicHandler(logTempFile), - Writer: io.MultiWriter(logTempFile, logWriter), - } + // Wait for the output copying to finish + <-doneCh - exitStatus, err := panicwrap.Wrap(wrapConfig) - if err != nil { - fmt.Fprintf(os.Stderr, "Couldn't start Packer: %s", err) - return 1 - } + return exitStatus + } - if exitStatus >= 0 { - return exitStatus + // We're the child, so just close the tempfile we made in order to + // save file handles since the tempfile is only used by the parent. + logTempFile.Close() } - // We're the child, so just close the tempfile we made in order to - // save file handles since the tempfile is only used by the parent. - logTempFile.Close() - + // Call the real main return wrappedMain() } // wrappedMain is called only when we're wrapped by panicwrap and // returns the exit status to exit with. func wrappedMain() int { + // If there is no explicit number of Go threads to use, then set it + if os.Getenv("GOMAXPROCS") == "" { + runtime.GOMAXPROCS(runtime.NumCPU()) + } + log.SetOutput(os.Stderr) log.Printf( @@ -220,20 +241,44 @@ func loadConfig() (*config, error) { return &config, nil } -// logOutput determines where we should send logs (if anywhere). -func logOutput() (logOutput io.Writer, err error) { - logOutput = ioutil.Discard - if os.Getenv("PACKER_LOG") != "" { - logOutput = os.Stderr - - if logPath := os.Getenv("PACKER_LOG_PATH"); logPath != "" { - var err error - logOutput, err = os.Create(logPath) - if err != nil { - return nil, err - } - } +// copyOutput uses output prefixes to determine whether data on stdout +// should go to stdout or stderr. This is due to panicwrap using stderr +// as the log and error channel. +func copyOutput(r io.Reader, doneCh chan<- struct{}) { + defer close(doneCh) + + pr, err := prefixedio.NewReader(r) + if err != nil { + panic(err) + } + + stderrR, err := pr.Prefix(ErrorPrefix) + if err != nil { + panic(err) + } + stdoutR, err := pr.Prefix(OutputPrefix) + if err != nil { + panic(err) + } + defaultR, err := pr.Prefix("") + if err != nil { + panic(err) } - return + var wg sync.WaitGroup + wg.Add(3) + go func() { + defer wg.Done() + io.Copy(os.Stderr, stderrR) + }() + go func() { + defer wg.Done() + io.Copy(os.Stdout, stdoutR) + }() + go func() { + defer wg.Done() + io.Copy(os.Stdout, defaultR) + }() + + wg.Wait() } diff --git a/plugin/command-build/main.go b/plugin/command-build/main.go deleted file mode 100644 index 1285e1e7a..000000000 --- a/plugin/command-build/main.go +++ /dev/null @@ -1,15 +0,0 @@ -package main - -import ( - "github.com/mitchellh/packer/command/build" - "github.com/mitchellh/packer/packer/plugin" -) - -func main() { - server, err := plugin.Server() - if err != nil { - panic(err) - } - server.RegisterCommand(new(build.Command)) - server.Serve() -} diff --git a/plugin/command-build/main_test.go b/plugin/command-build/main_test.go deleted file mode 100644 index 06ab7d0f9..000000000 --- a/plugin/command-build/main_test.go +++ /dev/null @@ -1 +0,0 @@ -package main diff --git a/plugin/command-inspect/main.go b/plugin/command-inspect/main.go deleted file mode 100644 index 9aeedc34c..000000000 --- a/plugin/command-inspect/main.go +++ /dev/null @@ -1,15 +0,0 @@ -package main - -import ( - "github.com/mitchellh/packer/command/inspect" - "github.com/mitchellh/packer/packer/plugin" -) - -func main() { - server, err := plugin.Server() - if err != nil { - panic(err) - } - server.RegisterCommand(new(inspect.Command)) - server.Serve() -} diff --git a/plugin/command-inspect/main_test.go b/plugin/command-inspect/main_test.go deleted file mode 100644 index 06ab7d0f9..000000000 --- a/plugin/command-inspect/main_test.go +++ /dev/null @@ -1 +0,0 @@ -package main diff --git a/plugin/command-validate/main.go b/plugin/command-validate/main.go deleted file mode 100644 index 1105ed75e..000000000 --- a/plugin/command-validate/main.go +++ /dev/null @@ -1,15 +0,0 @@ -package main - -import ( - "github.com/mitchellh/packer/command/validate" - "github.com/mitchellh/packer/packer/plugin" -) - -func main() { - server, err := plugin.Server() - if err != nil { - panic(err) - } - server.RegisterCommand(new(validate.Command)) - server.Serve() -} diff --git a/plugin/command-validate/main_test.go b/plugin/command-validate/main_test.go deleted file mode 100644 index 06ab7d0f9..000000000 --- a/plugin/command-validate/main_test.go +++ /dev/null @@ -1 +0,0 @@ -package main