Merge pull request #7183 from hashicorp/skip_post_processor

allow to use `-except` on post-processors
This commit is contained in:
Megan Marsh 2019-01-23 15:10:09 -08:00 committed by GitHub
commit 270f851e72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 115 additions and 67 deletions

View File

@ -8,6 +8,7 @@ import (
"github.com/hashicorp/packer/builder/file" "github.com/hashicorp/packer/builder/file"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
shell_local "github.com/hashicorp/packer/post-processor/shell-local"
) )
func TestBuildOnlyFileCommaFlags(t *testing.T) { func TestBuildOnlyFileCommaFlags(t *testing.T) {
@ -26,12 +27,13 @@ func TestBuildOnlyFileCommaFlags(t *testing.T) {
fatalCommand(t, c.Meta) fatalCommand(t, c.Meta)
} }
if !fileExists("chocolate.txt") { for _, f := range []string{"chocolate.txt", "vanilla.txt",
t.Error("Expected to find chocolate.txt") "apple.txt", "peach.txt", "pear.txt"} {
} if !fileExists(f) {
if !fileExists("vanilla.txt") { t.Errorf("Expected to find %s", f)
t.Error("Expected to find vanilla.txt") }
} }
if fileExists("cherry.txt") { if fileExists("cherry.txt") {
t.Error("Expected NOT to find cherry.txt") t.Error("Expected NOT to find cherry.txt")
} }
@ -56,14 +58,10 @@ func TestBuildStdin(t *testing.T) {
fatalCommand(t, c.Meta) fatalCommand(t, c.Meta)
} }
if !fileExists("chocolate.txt") { for _, f := range []string{"vanilla.txt", "cherry.txt", "chocolate.txt"} {
t.Error("Expected to find chocolate.txt") if !fileExists(f) {
} t.Errorf("Expected to find %s", f)
if !fileExists("vanilla.txt") { }
t.Error("Expected to find vanilla.txt")
}
if !fileExists("cherry.txt") {
t.Error("Expected to find cherry.txt")
} }
} }
@ -75,6 +73,9 @@ func TestBuildOnlyFileMultipleFlags(t *testing.T) {
args := []string{ args := []string{
"-only=chocolate", "-only=chocolate",
"-only=cherry", "-only=cherry",
"-only=apple", // ignored
"-only=peach", // ignored
"-only=pear", // ignored
filepath.Join(testFixture("build-only"), "template.json"), filepath.Join(testFixture("build-only"), "template.json"),
} }
@ -84,14 +85,16 @@ func TestBuildOnlyFileMultipleFlags(t *testing.T) {
fatalCommand(t, c.Meta) fatalCommand(t, c.Meta)
} }
if !fileExists("chocolate.txt") { for _, f := range []string{"vanilla.txt"} {
t.Error("Expected to find chocolate.txt") if fileExists(f) {
t.Errorf("Expected NOT to find %s", f)
}
} }
if fileExists("vanilla.txt") { for _, f := range []string{"chocolate.txt", "cherry.txt",
t.Error("Expected NOT to find vanilla.txt") "apple.txt", "peach.txt", "pear.txt"} {
} if !fileExists(f) {
if !fileExists("cherry.txt") { t.Errorf("Expected to find %s", f)
t.Error("Expected to find cherry.txt") }
} }
} }
@ -101,7 +104,7 @@ func TestBuildExceptFileCommaFlags(t *testing.T) {
} }
args := []string{ args := []string{
"-except=chocolate", "-except=chocolate,apple",
filepath.Join(testFixture("build-only"), "template.json"), filepath.Join(testFixture("build-only"), "template.json"),
} }
@ -111,14 +114,15 @@ func TestBuildExceptFileCommaFlags(t *testing.T) {
fatalCommand(t, c.Meta) fatalCommand(t, c.Meta)
} }
if fileExists("chocolate.txt") { for _, f := range []string{"chocolate.txt", "apple.txt", "peach.txt"} {
t.Error("Expected NOT to find chocolate.txt") if fileExists(f) {
t.Errorf("Expected NOT to find %s", f)
}
} }
if !fileExists("vanilla.txt") { for _, f := range []string{"vanilla.txt", "cherry.txt", "pear.txt"} {
t.Error("Expected to find vanilla.txt") if !fileExists(f) {
} t.Errorf("Expected to find %s", f)
if !fileExists("cherry.txt") { }
t.Error("Expected to find cherry.txt")
} }
} }
@ -137,6 +141,9 @@ func testCoreConfigBuilder(t *testing.T) *packer.CoreConfig {
Builder: func(n string) (packer.Builder, error) { Builder: func(n string) (packer.Builder, error) {
return &file.Builder{}, nil return &file.Builder{}, nil
}, },
PostProcessor: func(n string) (packer.PostProcessor, error) {
return &shell_local.PostProcessor{}, nil
},
} }
return &packer.CoreConfig{ return &packer.CoreConfig{
Components: components, Components: components,
@ -159,4 +166,7 @@ func cleanup() {
os.RemoveAll("chocolate.txt") os.RemoveAll("chocolate.txt")
os.RemoveAll("vanilla.txt") os.RemoveAll("vanilla.txt")
os.RemoveAll("cherry.txt") os.RemoveAll("cherry.txt")
os.RemoveAll("apple.txt")
os.RemoveAll("peach.txt")
os.RemoveAll("pear.txt")
} }

View File

@ -6,8 +6,8 @@ import (
"fmt" "fmt"
"io" "io"
"github.com/hashicorp/packer/helper/flag-kv" kvflag "github.com/hashicorp/packer/helper/flag-kv"
"github.com/hashicorp/packer/helper/flag-slice" sliceflag "github.com/hashicorp/packer/helper/flag-slice"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template" "github.com/hashicorp/packer/template"
) )
@ -31,9 +31,7 @@ type Meta struct {
Version string Version string
// These are set by command-line flags // These are set by command-line flags
flagBuildExcept []string flagVars map[string]string
flagBuildOnly []string
flagVars map[string]string
} }
// Core returns the core for the given template given the configured // Core returns the core for the given template given the configured
@ -59,7 +57,7 @@ func (m *Meta) BuildNames(c *packer.Core) []string {
// TODO: test // TODO: test
// Filter the "only" // Filter the "only"
if len(m.flagBuildOnly) > 0 { if len(m.CoreConfig.Only) > 0 {
// Build a set of all the available names // Build a set of all the available names
nameSet := make(map[string]struct{}) nameSet := make(map[string]struct{})
for _, n := range c.BuildNames() { for _, n := range c.BuildNames() {
@ -67,8 +65,8 @@ func (m *Meta) BuildNames(c *packer.Core) []string {
} }
// Build our result set which we pre-allocate some sane number // Build our result set which we pre-allocate some sane number
result := make([]string, 0, len(m.flagBuildOnly)) result := make([]string, 0, len(m.CoreConfig.Only))
for _, n := range m.flagBuildOnly { for _, n := range m.CoreConfig.Only {
if _, ok := nameSet[n]; ok { if _, ok := nameSet[n]; ok {
result = append(result, n) result = append(result, n)
} }
@ -78,10 +76,10 @@ func (m *Meta) BuildNames(c *packer.Core) []string {
} }
// Filter the "except" // Filter the "except"
if len(m.flagBuildExcept) > 0 { if len(m.CoreConfig.Except) > 0 {
// Build a set of the things we don't want // Build a set of the things we don't want
nameSet := make(map[string]struct{}) nameSet := make(map[string]struct{})
for _, n := range m.flagBuildExcept { for _, n := range m.CoreConfig.Except {
nameSet[n] = struct{}{} nameSet[n] = struct{}{}
} }
@ -111,8 +109,8 @@ func (m *Meta) FlagSet(n string, fs FlagSetFlags) *flag.FlagSet {
// FlagSetBuildFilter tells us to enable the settings for selecting // FlagSetBuildFilter tells us to enable the settings for selecting
// builds we care about. // builds we care about.
if fs&FlagSetBuildFilter != 0 { if fs&FlagSetBuildFilter != 0 {
f.Var((*sliceflag.StringFlag)(&m.flagBuildExcept), "except", "") f.Var((*sliceflag.StringFlag)(&m.CoreConfig.Except), "except", "")
f.Var((*sliceflag.StringFlag)(&m.flagBuildOnly), "only", "") f.Var((*sliceflag.StringFlag)(&m.CoreConfig.Only), "only", "")
} }
// FlagSetVars tells us what variables to use // FlagSetVars tells us what variables to use

View File

@ -1,22 +1,43 @@
{ {
"builders": [ "builders": [
{ {
"name":"chocolate", "name": "chocolate",
"type":"file", "type": "file",
"content":"chocolate", "content": "chocolate",
"target":"chocolate.txt" "target": "chocolate.txt"
}, },
{ {
"name":"vanilla", "name": "vanilla",
"type":"file", "type": "file",
"content":"vanilla", "content": "vanilla",
"target":"vanilla.txt" "target": "vanilla.txt"
}, },
{ {
"name":"cherry", "name": "cherry",
"type":"file", "type": "file",
"content":"cherry", "content": "cherry",
"target":"cherry.txt" "target": "cherry.txt"
} }
],
"post-processors": [
[
{
"name": "apple",
"type": "shell-local",
"inline": [ "touch apple.txt" ]
},
{
"name": "peach",
"type": "shell-local",
"inline": [ "touch peach.txt" ]
}
],
[
{
"name": "pear",
"type": "shell-local",
"inline": [ "touch pear.txt" ]
}
]
] ]
} }

View File

@ -14,7 +14,7 @@ _packer () {
'-force[Force a build to continue if artifacts exist, deletes existing artifacts.]' '-force[Force a build to continue if artifacts exist, deletes existing artifacts.]'
'-machine-readable[Produce machine-readable output.]' '-machine-readable[Produce machine-readable output.]'
'-color=[(false) Disable color output. (Default: color)]' '-color=[(false) Disable color output. (Default: color)]'
'-except=[(foo,bar,baz) Build all builds other than these.]' '-except=[(foo,bar,baz) Run all builds and post-procesors other than these.]'
'-on-error=[(cleanup,abort,ask) If the build fails do: clean up (default), abort, or ask.]' '-on-error=[(cleanup,abort,ask) If the build fails do: clean up (default), abort, or ask.]'
'-only=[(foo,bar,baz) Only build the given builds by name.]' '-only=[(foo,bar,baz) Only build the given builds by name.]'
'-parallel=[(false) Disable parallelization. (Default: parallel)]' '-parallel=[(false) Disable parallelization. (Default: parallel)]'

View File

@ -4,8 +4,8 @@ import (
"fmt" "fmt"
"sort" "sort"
"github.com/hashicorp/go-multierror" multierror "github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-version" version "github.com/hashicorp/go-version"
"github.com/hashicorp/packer/template" "github.com/hashicorp/packer/template"
"github.com/hashicorp/packer/template/interpolate" "github.com/hashicorp/packer/template/interpolate"
) )
@ -20,6 +20,9 @@ type Core struct {
builds map[string]*template.Builder builds map[string]*template.Builder
version string version string
secrets []string secrets []string
except []string
only []string
} }
// CoreConfig is the structure for initializing a new Core. Once a CoreConfig // CoreConfig is the structure for initializing a new Core. Once a CoreConfig
@ -30,6 +33,10 @@ type CoreConfig struct {
Variables map[string]string Variables map[string]string
SensitiveVariables []string SensitiveVariables []string
Version string Version string
// These are set by command-line flags
Except []string
Only []string
} }
// The function type used to lookup Builder implementations. // The function type used to lookup Builder implementations.
@ -61,6 +68,8 @@ func NewCore(c *CoreConfig) (*Core, error) {
components: c.Components, components: c.Components,
variables: c.Variables, variables: c.Variables,
version: c.Version, version: c.Version,
only: c.Only,
except: c.Except,
} }
if err := result.validate(); err != nil { if err := result.validate(); err != nil {
@ -126,7 +135,7 @@ func (c *Core) Build(n string) (Build, error) {
provisioners := make([]coreBuildProvisioner, 0, len(c.Template.Provisioners)) provisioners := make([]coreBuildProvisioner, 0, len(c.Template.Provisioners))
for _, rawP := range c.Template.Provisioners { for _, rawP := range c.Template.Provisioners {
// If we're skipping this, then ignore it // If we're skipping this, then ignore it
if rawP.Skip(rawName) { if rawP.OnlyExcept.Skip(rawName) {
continue continue
} }
@ -172,9 +181,13 @@ func (c *Core) Build(n string) (Build, error) {
current := make([]coreBuildPostProcessor, 0, len(rawPs)) current := make([]coreBuildPostProcessor, 0, len(rawPs))
for _, rawP := range rawPs { for _, rawP := range rawPs {
// If we skip, ignore // If we skip, ignore
if rawP.Skip(rawName) { rawP.OnlyExcept.Except = append(rawP.OnlyExcept.Except, c.except...)
if rawP.OnlyExcept.Skip(rawName) {
continue continue
} }
if rawP.OnlyExcept.Skip(rawP.Name) {
break
}
// Get the post-processor // Get the post-processor
postProcessor, err := c.components.PostProcessor(rawP.Type) postProcessor, err := c.components.PostProcessor(rawP.Type)

View File

@ -11,7 +11,7 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/hashicorp/go-multierror" multierror "github.com/hashicorp/go-multierror"
"github.com/hashicorp/packer/packer/tmp" "github.com/hashicorp/packer/packer/tmp"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
) )
@ -149,6 +149,7 @@ func (r *rawTemplate) Template() (*Template, error) {
delete(c, "only") delete(c, "only")
delete(c, "keep_input_artifact") delete(c, "keep_input_artifact")
delete(c, "type") delete(c, "type")
delete(c, "name")
if len(c) > 0 { if len(c) > 0 {
pp.Config = c pp.Config = c
} }

View File

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/hashicorp/go-multierror" multierror "github.com/hashicorp/go-multierror"
) )
// Template represents the parsed template that is used to configure // Template represents the parsed template that is used to configure
@ -40,6 +40,7 @@ type Builder struct {
type PostProcessor struct { type PostProcessor struct {
OnlyExcept `mapstructure:",squash"` OnlyExcept `mapstructure:",squash"`
Name string
Type string Type string
KeepInputArtifact bool `mapstructure:"keep_input_artifact"` KeepInputArtifact bool `mapstructure:"keep_input_artifact"`
Config map[string]interface{} Config map[string]interface{}

View File

@ -26,10 +26,12 @@ artifacts that are created will be outputted at the end of the build.
will stop between each step, waiting for keyboard input before continuing. will stop between each step, waiting for keyboard input before continuing.
This will allow the user to inspect state and so on. This will allow the user to inspect state and so on.
- `-except=foo,bar,baz` - Builds all the builds except those with the given - `-except=foo,bar,baz` - Run all the builds and post-processors except those
comma-separated names. Build names by default are the names of their with the given comma-separated names. Build and post-processor names by
builders, unless a specific `name` attribute is specified within the default are their type, unless a specific `name` attribute is specified
configuration. within the configuration. Any post-processor following a skipped
post-processor will not run. Because post-processors can be nested in
arrays a differ post-processor chain can still run.
- `-force` - Forces a builder to run when artifacts from a previous build - `-force` - Forces a builder to run when artifacts from a previous build
prevent a build from running. The exact behavior of a forced build is left prevent a build from running. The exact behavior of a forced build is left
@ -44,9 +46,10 @@ artifacts that are created will be outputted at the end of the build.
presents a prompt and waits for you to decide to clean up, abort, or retry presents a prompt and waits for you to decide to clean up, abort, or retry
the failed step. the failed step.
- `-only=foo,bar,baz` - Only build the builds with the given comma-separated - `-only=foo,bar,baz` - Only run the builds with the given comma-separated
names. Build names by default are the names of their builders, unless a names. Build names by default are their type, unless a specific `name`
specific `name` attribute is specified within the configuration. attribute is specified within the configuration. `-only` does not apply to
post-processors.
- `-parallel=false` - Disable parallelization of multiple builders (on by - `-parallel=false` - Disable parallelization of multiple builders (on by
default). default).

View File

@ -81,6 +81,7 @@ The values within `only` or `except` are *build names*, not builder types. If
you recall, build names by default are just their builder type, but if you you recall, build names by default are just their builder type, but if you
specify a custom `name` parameter, then you should use that as the value specify a custom `name` parameter, then you should use that as the value
instead of the type. instead of the type.
Values within `except` could also be a *post-processor* name.
## Build-Specific Overrides ## Build-Specific Overrides