enable force, debug, and on-error for hcl2 builds

This commit is contained in:
Megan Marsh 2020-05-14 16:22:51 -07:00
parent e3635566eb
commit ee5635722b
6 changed files with 40 additions and 5 deletions

View File

@ -135,8 +135,11 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int
} }
builds, diags := packerStarter.GetBuilds(packer.GetBuildsOptions{ builds, diags := packerStarter.GetBuilds(packer.GetBuildsOptions{
Only: cla.Only, Only: cla.Only,
Except: cla.Except, Except: cla.Except,
Debug: cla.Debug,
Force: cla.Force,
OnError: cla.OnError,
}) })
// here, something could have gone wrong but we still want to run valid // here, something could have gone wrong but we still want to run valid
@ -186,6 +189,8 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int
log.Printf("On error: %v", cla.OnError) log.Printf("On error: %v", cla.OnError)
// Set the debug and force mode and prepare all the builds // Set the debug and force mode and prepare all the builds
// This is only affects json templates, because HCL2
// templates have already been prepared in GetBuilds() above.
for i := range builds { for i := range builds {
b := builds[i] b := builds[i]
log.Printf("Preparing build: %s", b.Name()) log.Printf("Preparing build: %s", b.Name())

View File

@ -311,7 +311,7 @@ func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]packer.Build
} }
} }
builder, moreDiags, generatedVars := cfg.startBuilder(src, cfg.EvalContext(nil)) builder, moreDiags, generatedVars := cfg.startBuilder(src, cfg.EvalContext(nil), opts)
diags = append(diags, moreDiags...) diags = append(diags, moreDiags...)
if moreDiags.HasErrors() { if moreDiags.HasErrors() {
continue continue

View File

@ -2,6 +2,7 @@ package hcl2template
import ( import (
"fmt" "fmt"
"strconv"
"github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
@ -38,7 +39,7 @@ func (p *Parser) decodeSource(block *hcl.Block) (*SourceBlock, hcl.Diagnostics)
return source, diags return source, diags
} }
func (cfg *PackerConfig) startBuilder(source *SourceBlock, ectx *hcl.EvalContext) (packer.Builder, hcl.Diagnostics, []string) { func (cfg *PackerConfig) startBuilder(source *SourceBlock, ectx *hcl.EvalContext, opts packer.GetBuildsOptions) (packer.Builder, hcl.Diagnostics, []string) {
var diags hcl.Diagnostics var diags hcl.Diagnostics
builder, err := cfg.builderSchemas.Start(source.Type) builder, err := cfg.builderSchemas.Start(source.Type)
@ -57,12 +58,23 @@ func (cfg *PackerConfig) startBuilder(source *SourceBlock, ectx *hcl.EvalContext
return nil, diags, nil return nil, diags, nil
} }
generatedVars, warning, err := builder.Prepare(source.builderVariables(), decoded) // Note: HCL prepares inside of the Start func, but Json does not. Json
// builds are instead prepared only in command/build.go
// TODO: either make json prepare when plugins are loaded, or make HCL
// prepare at a later step, to make builds from different template types
// easier to reason about.
builderVars := source.builderVariables()
builderVars["packer_debug"] = strconv.FormatBool(opts.Debug)
builderVars["packer_force"] = strconv.FormatBool(opts.Force)
builderVars["packer_on_error"] = opts.OnError
generatedVars, warning, err := builder.Prepare(builderVars, decoded)
moreDiags = warningErrorsToDiags(source.block, warning, err) moreDiags = warningErrorsToDiags(source.block, warning, err)
diags = append(diags, moreDiags...) diags = append(diags, moreDiags...)
return builder, diags, generatedVars return builder, diags, generatedVars
} }
// These variables will populate the PackerConfig inside of the builders.
func (source *SourceBlock) builderVariables() map[string]string { func (source *SourceBlock) builderVariables() map[string]string {
return map[string]string{ return map[string]string{
"packer_build_name": source.Name, "packer_build_name": source.Name,

View File

@ -146,6 +146,11 @@ func wrappedMain() int {
runtime.Version(), runtime.Version(),
runtime.GOOS, runtime.GOARCH) runtime.GOOS, runtime.GOARCH)
// The config being loaded here is the Packer config -- it defines
// the location of third party builder plugins, plugin ports to use, and
// whether to disable telemetry. It is a global config.
// Do not confuse this config with the .json Packer template which gets
// passed into commands like `packer build`
config, err := loadConfig() config, err := loadConfig()
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Error loading configuration: \n\n%s\n", err) fmt.Fprintf(os.Stderr, "Error loading configuration: \n\n%s\n", err)
@ -328,6 +333,7 @@ func loadConfig() (*config, error) {
} }
defer f.Close() defer f.Close()
// This loads a json config, defined in packer/config.go
if err := decodeConfig(f, &config); err != nil { if err := decodeConfig(f, &config); err != nil {
return nil, err return nil, err
} }

View File

@ -199,6 +199,8 @@ func (c *Core) generateCoreBuildProvisioner(rawP *template.Provisioner, rawName
return cbp, nil return cbp, nil
} }
// This is used for json templates to launch the build plugins.
// They will be prepared via b.Prepare() later.
func (c *Core) GetBuilds(opts GetBuildsOptions) ([]Build, hcl.Diagnostics) { func (c *Core) GetBuilds(opts GetBuildsOptions) ([]Build, hcl.Diagnostics) {
buildNames := c.BuildNames(opts.Only, opts.Except) buildNames := c.BuildNames(opts.Only, opts.Except)
builds := []Build{} builds := []Build{}
@ -225,6 +227,12 @@ func (c *Core) Build(n string) (Build, error) {
if !ok { if !ok {
return nil, fmt.Errorf("no such build found: %s", n) return nil, fmt.Errorf("no such build found: %s", n)
} }
// BuilderStore = config.Builders, gathered in loadConfig() in main.go
// For reference, the builtin BuilderStore is generated in
// packer/config.go in the Discover() func.
// the Start command launches the builder plugin of the given type without
// calling Prepare() or passing any build-specific details.
builder, err := c.components.BuilderStore.Start(configBuilder.Type) builder, err := c.components.BuilderStore.Start(configBuilder.Type)
if err != nil { if err != nil {
return nil, fmt.Errorf( return nil, fmt.Errorf(
@ -315,6 +323,8 @@ func (c *Core) Build(n string) (Build, error) {
// TODO hooks one day // TODO hooks one day
// Return a structure that contains the plugins, their types, variables, and
// the raw builder config loaded from the json template
return &CoreBuild{ return &CoreBuild{
Type: n, Type: n,
Builder: builder, Builder: builder,

View File

@ -6,6 +6,8 @@ type GetBuildsOptions struct {
// Get builds except the ones that match with except and with only the ones // Get builds except the ones that match with except and with only the ones
// that match with Only. When those are empty everything matches. // that match with Only. When those are empty everything matches.
Except, Only []string Except, Only []string
Debug, Force bool
OnError string
} }
type BuildGetter interface { type BuildGetter interface {