diff --git a/command/build.go b/command/build.go index 238b8df51..5a9413ba8 100644 --- a/command/build.go +++ b/command/build.go @@ -25,7 +25,7 @@ type BuildCommand struct { } func (c *BuildCommand) Run(args []string) int { - buildCtx, cleanup := handleTermInterrupt(c.Ui) + ctx, cleanup := handleTermInterrupt(c.Ui) defer cleanup() cfg, ret := c.ParseArgs(args) @@ -33,7 +33,7 @@ func (c *BuildCommand) Run(args []string) int { return ret } - return c.RunContext(buildCtx, cfg) + return c.RunContext(ctx, cfg) } func (c *BuildCommand) ParseArgs(args []string) (*BuildArgs, int) { @@ -106,20 +106,20 @@ func (m *Meta) GetConfig(cla *MetaArgs) (packer.BuildGetter, int) { // will continue to work but users are encouraged to move to the new style. // See: https://packer.io/guides/hcl // `) - return m.GetConfigFromJSON(cla.Path) + return m.GetConfigFromJSON(cla) } } -func (m *Meta) GetConfigFromJSON(path string) (packer.BuildGetter, int) { +func (m *Meta) GetConfigFromJSON(cla *MetaArgs) (packer.BuildGetter, int) { // Parse the template - tpl, err := template.ParseFile(path) + tpl, err := template.ParseFile(cla.Path) if err != nil { m.Ui.Error(fmt.Sprintf("Failed to parse template: %s", err)) return nil, 1 } // Get the core - core, err := m.Core(tpl) + core, err := m.Core(tpl, cla) ret := 0 if err != nil { m.Ui.Error(err.Error()) diff --git a/command/console.go b/command/console.go index f63fc3211..2db92e846 100644 --- a/command/console.go +++ b/command/console.go @@ -2,6 +2,7 @@ package command import ( "bufio" + "context" "errors" "fmt" "io" @@ -30,16 +31,40 @@ type ConsoleCommand struct { } func (c *ConsoleCommand) Run(args []string) int { - flags := c.Meta.FlagSet("console", FlagSetVars) - flags.Usage = func() { c.Ui.Say(c.Help()) } - if err := flags.Parse(args); err != nil { - return 1 + ctx, cleanup := handleTermInterrupt(c.Ui) + defer cleanup() + + cfg, ret := c.ParseArgs(args) + if ret != 0 { + return ret } - var templ *template.Template + return c.RunContext(ctx, cfg) +} + +func (c *ConsoleCommand) ParseArgs(args []string) (*ConsoleArgs, int) { + var cfg ConsoleArgs + flags := c.Meta.FlagSet("console", FlagSetVars) + flags.Usage = func() { c.Ui.Say(c.Help()) } + cfg.AddFlagSets(flags) + if err := flags.Parse(args); err != nil { + return &cfg, 1 + } + + if len(args) > 1 { + // User provided too many arguments + flags.Usage() + return &cfg, 1 + } args = flags.Args() - if len(args) < 1 { + return &cfg, 0 +} + +func (c *ConsoleCommand) RunContext(ctx context.Context, cla *ConsoleArgs) int { + + var templ *template.Template + if cla.Path == "" { // If user has not defined a builder, create a tiny null placeholder // builder so that we can properly initialize the core tpl, err := template.Parse(strings.NewReader(TiniestBuilder)) @@ -48,22 +73,18 @@ func (c *ConsoleCommand) Run(args []string) int { return 1 } templ = tpl - } else if len(args) == 1 { + } else { // Parse the provided template - tpl, err := template.ParseFile(args[0]) + tpl, err := template.ParseFile(cla.Path) if err != nil { c.Ui.Error(fmt.Sprintf("Failed to parse template: %s", err)) return 1 } templ = tpl - } else { - // User provided too many arguments - flags.Usage() - return 1 } // Get the core - core, err := c.Meta.Core(templ) + core, err := c.Meta.Core(templ, &cla.MetaArgs) if err != nil { c.Ui.Error(err.Error()) return 1 diff --git a/command/meta.go b/command/meta.go index 6e0543e2c..6f37f14c4 100644 --- a/command/meta.go +++ b/command/meta.go @@ -29,22 +29,18 @@ type Meta struct { CoreConfig *packer.CoreConfig Ui packer.Ui Version string - - // These are set by command-line flags - varFiles []string - flagVars map[string]string } // Core returns the core for the given template given the configured // CoreConfig and user variables on this Meta. -func (m *Meta) Core(tpl *template.Template) (*packer.Core, error) { +func (m *Meta) Core(tpl *template.Template, cla *MetaArgs) (*packer.Core, error) { // Copy the config so we don't modify it config := *m.CoreConfig config.Template = tpl fj := &kvflag.FlagJSON{} // First populate fj with contents from var files - for _, file := range m.varFiles { + for _, file := range cla.VarFiles { err := fj.Set(file) if err != nil { return nil, err @@ -53,15 +49,15 @@ func (m *Meta) Core(tpl *template.Template) (*packer.Core, error) { // Now read fj values back into flagvars and set as config.Variables. Only // add to flagVars if the key doesn't already exist, because flagVars comes // from the command line and should not be overridden by variable files. - if m.flagVars == nil { - m.flagVars = map[string]string{} + if cla.Vars == nil { + cla.Vars = map[string]string{} } for k, v := range *fj { - if _, exists := m.flagVars[k]; !exists { - m.flagVars[k] = v + if _, exists := cla.Vars[k]; !exists { + cla.Vars[k] = v } } - config.Variables = m.flagVars + config.Variables = cla.Vars // Init the core core, err := packer.NewCore(&config) diff --git a/command/validate.go b/command/validate.go index 8f08b44bc..fb6cd324a 100644 --- a/command/validate.go +++ b/command/validate.go @@ -1,6 +1,7 @@ package command import ( + "context" "encoding/json" "fmt" "log" @@ -19,35 +20,52 @@ type ValidateCommand struct { } func (c *ValidateCommand) Run(args []string) int { - var cfgSyntaxOnly bool + ctx, cleanup := handleTermInterrupt(c.Ui) + defer cleanup() + + cfg, ret := c.ParseArgs(args) + if ret != 0 { + return ret + } + + return c.RunContext(ctx, cfg) +} + +func (c *ValidateCommand) ParseArgs(args []string) (*ValidateArgs, int) { + var cfg ValidateArgs + flags := c.Meta.FlagSet("validate", FlagSetBuildFilter|FlagSetVars) flags.Usage = func() { c.Ui.Say(c.Help()) } - flags.BoolVar(&cfgSyntaxOnly, "syntax-only", false, "check syntax only") + cfg.AddFlagSets(flags) if err := flags.Parse(args); err != nil { - return 1 + return &cfg, 1 } args = flags.Args() if len(args) != 1 { flags.Usage() - return 1 + return &cfg, 1 } + cfg.Path = args[0] + return &cfg, 0 +} +func (c *ValidateCommand) RunContext(ctx context.Context, cla *ValidateArgs) int { // Parse the template - tpl, err := template.ParseFile(args[0]) + tpl, err := template.ParseFile(cla.Path) if err != nil { 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 { + if cla.SyntaxOnly { c.Ui.Say("Syntax-only check passed. Everything looks okay.") return 0 } // Get the core - core, err := c.Meta.Core(tpl) + core, err := c.Meta.Core(tpl, &cla.MetaArgs) if err != nil { c.Ui.Error(err.Error()) return 1