Enable only/except for provisioners and post-processors (#9357)

This commit is contained in:
Jeremiah Snapp 2020-06-05 05:51:23 -04:00 committed by GitHub
parent fd0764d668
commit 0d7c5dc670
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 257 additions and 10 deletions

View File

@ -30,6 +30,7 @@ func getBasicParser() *Parser {
},
PostProcessorsSchemas: packer.MapOfPostProcessor{
"amazon-import": func() (packer.PostProcessor, error) { return &MockPostProcessor{}, nil },
"manifest": func() (packer.PostProcessor, error) { return &MockPostProcessor{}, nil },
},
}
}

View File

@ -0,0 +1,21 @@
// starts resources to provision them.
build {
sources = [
"source.virtualbox-iso.ubuntu-1204",
"source.amazon-ebs.ubuntu-1604",
]
post-processor "amazon-import" {
only = ["virtualbox-iso.ubuntu-1204"]
}
post-processor "manifest" {
except = ["virtualbox-iso.ubuntu-1204"]
}
}
source "virtualbox-iso" "ubuntu-1204" {
}
source "amazon-ebs" "ubuntu-1604" {
}

View File

@ -0,0 +1,21 @@
// starts resources to provision them.
build {
sources = [
"source.virtualbox-iso.ubuntu-1204",
"source.amazon-ebs.ubuntu-1604",
]
provisioner "shell" {
only = ["virtualbox-iso.ubuntu-1204"]
}
provisioner "file" {
except = ["virtualbox-iso.ubuntu-1204"]
}
}
source "virtualbox-iso" "ubuntu-1204" {
}
source "amazon-ebs" "ubuntu-1604" {
}

View File

@ -10,8 +10,9 @@ import (
// ProvisionerBlock references a detected but unparsed post processor
type PostProcessorBlock struct {
PType string
PName string
PType string
PName string
OnlyExcept OnlyExcept
HCL2Ref
}
@ -22,8 +23,10 @@ func (p *PostProcessorBlock) String() string {
func (p *Parser) decodePostProcessor(block *hcl.Block) (*PostProcessorBlock, hcl.Diagnostics) {
var b struct {
Name string `hcl:"name,optional"`
Rest hcl.Body `hcl:",remain"`
Name string `hcl:"name,optional"`
Only []string `hcl:"only,optional"`
Except []string `hcl:"except,optional"`
Rest hcl.Body `hcl:",remain"`
}
diags := gohcl.DecodeBody(block.Body, nil, &b)
if diags.HasErrors() {
@ -31,9 +34,15 @@ func (p *Parser) decodePostProcessor(block *hcl.Block) (*PostProcessorBlock, hcl
}
postProcessor := &PostProcessorBlock{
PType: block.Labels[0],
PName: b.Name,
HCL2Ref: newHCL2Ref(block, b.Rest),
PType: block.Labels[0],
PName: b.Name,
OnlyExcept: OnlyExcept{Only: b.Only, Except: b.Except},
HCL2Ref: newHCL2Ref(block, b.Rest),
}
diags = diags.Extend(postProcessor.OnlyExcept.Validate())
if diags.HasErrors() {
return nil, diags
}
if !p.PostProcessorsSchemas.Has(postProcessor.PType) {

View File

@ -9,6 +9,52 @@ import (
"github.com/hashicorp/packer/packer"
)
// OnlyExcept is a struct that is meant to be embedded that contains the
// logic required for "only" and "except" meta-parameters.
type OnlyExcept struct {
Only []string `json:"only,omitempty"`
Except []string `json:"except,omitempty"`
}
// Skip says whether or not to skip the build with the given name.
func (o *OnlyExcept) Skip(n string) bool {
if len(o.Only) > 0 {
for _, v := range o.Only {
if v == n {
return false
}
}
return true
}
if len(o.Except) > 0 {
for _, v := range o.Except {
if v == n {
return true
}
}
return false
}
return false
}
// Validate validates that the OnlyExcept settings are correct for a thing.
func (o *OnlyExcept) Validate() hcl.Diagnostics {
var diags hcl.Diagnostics
if len(o.Only) > 0 && len(o.Except) > 0 {
diags = diags.Append(&hcl.Diagnostic{
Summary: "only one of 'only' or 'except' may be specified",
Severity: hcl.DiagError,
})
}
return diags
}
// ProvisionerBlock references a detected but unparsed provisioner
type ProvisionerBlock struct {
PType string
@ -16,6 +62,7 @@ type ProvisionerBlock struct {
PauseBefore time.Duration
MaxRetries int
Timeout time.Duration
OnlyExcept OnlyExcept
HCL2Ref
}
@ -29,6 +76,8 @@ func (p *Parser) decodeProvisioner(block *hcl.Block) (*ProvisionerBlock, hcl.Dia
PauseBefore string `hcl:"pause_before,optional"`
MaxRetries int `hcl:"max_retries,optional"`
Timeout string `hcl:"timeout,optional"`
Only []string `hcl:"only,optional"`
Except []string `hcl:"except,optional"`
Rest hcl.Body `hcl:",remain"`
}
diags := gohcl.DecodeBody(block.Body, nil, &b)
@ -40,9 +89,15 @@ func (p *Parser) decodeProvisioner(block *hcl.Block) (*ProvisionerBlock, hcl.Dia
PType: block.Labels[0],
PName: b.Name,
MaxRetries: b.MaxRetries,
OnlyExcept: OnlyExcept{Only: b.Only, Except: b.Except},
HCL2Ref: newHCL2Ref(block, b.Rest),
}
diags = diags.Extend(provisioner.OnlyExcept.Validate())
if diags.HasErrors() {
return nil, diags
}
if b.PauseBefore != "" {
pauseBefore, err := time.ParseDuration(b.PauseBefore)
if err != nil {

View File

@ -4,6 +4,7 @@ import (
"path/filepath"
"testing"
. "github.com/hashicorp/packer/hcl2template/internal"
"github.com/hashicorp/packer/packer"
)
@ -122,6 +123,139 @@ func TestParse_build(t *testing.T) {
[]packer.Build{},
true,
},
{"post-processor with only and except",
defaultParser,
parseTestArgs{"testdata/build/post-processor_onlyexcept.pkr.hcl", nil, nil},
&PackerConfig{
Basedir: filepath.Join("testdata", "build"),
Sources: map[SourceRef]SourceBlock{
refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
refAWSEBSUbuntu1604: {Type: "amazon-ebs", Name: "ubuntu-1604"},
},
Builds: Builds{
&BuildBlock{
Sources: []SourceRef{refVBIsoUbuntu1204, refAWSEBSUbuntu1604},
ProvisionerBlocks: nil,
PostProcessors: []*PostProcessorBlock{
{
PType: "amazon-import",
OnlyExcept: OnlyExcept{Only: []string{"virtualbox-iso.ubuntu-1204"}, Except: nil},
},
{
PType: "manifest",
OnlyExcept: OnlyExcept{Only: nil, Except: []string{"virtualbox-iso.ubuntu-1204"}},
},
},
},
},
},
false, false,
[]packer.Build{
&packer.CoreBuild{
Type: "virtualbox-iso.ubuntu-1204",
Prepared: true,
Builder: emptyMockBuilder,
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{
{
{
PType: "amazon-import",
PostProcessor: &MockPostProcessor{
Config: MockConfig{
NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
NestedSlice: []NestedMockConfig{},
},
},
},
},
},
},
&packer.CoreBuild{
Type: "amazon-ebs.ubuntu-1604",
Prepared: true,
Builder: emptyMockBuilder,
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{
{
{
PType: "manifest",
PostProcessor: &MockPostProcessor{
Config: MockConfig{
NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
NestedSlice: []NestedMockConfig{},
},
},
},
},
},
},
},
false,
},
{"provisioner with only and except",
defaultParser,
parseTestArgs{"testdata/build/provisioner_onlyexcept.pkr.hcl", nil, nil},
&PackerConfig{
Basedir: filepath.Join("testdata", "build"),
Sources: map[SourceRef]SourceBlock{
refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
refAWSEBSUbuntu1604: {Type: "amazon-ebs", Name: "ubuntu-1604"},
},
Builds: Builds{
&BuildBlock{
Sources: []SourceRef{refVBIsoUbuntu1204, refAWSEBSUbuntu1604},
ProvisionerBlocks: []*ProvisionerBlock{
{
PType: "shell",
OnlyExcept: OnlyExcept{Only: []string{"virtualbox-iso.ubuntu-1204"}, Except: nil},
},
{
PType: "file",
OnlyExcept: OnlyExcept{Only: nil, Except: []string{"virtualbox-iso.ubuntu-1204"}},
},
},
},
},
},
false, false,
[]packer.Build{
&packer.CoreBuild{
Type: "virtualbox-iso.ubuntu-1204",
Prepared: true,
Builder: emptyMockBuilder,
Provisioners: []packer.CoreBuildProvisioner{
{
PType: "shell",
Provisioner: &MockProvisioner{
Config: MockConfig{
NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
NestedSlice: []NestedMockConfig{},
},
},
},
},
PostProcessors: [][]packer.CoreBuildPostProcessor{},
},
&packer.CoreBuild{
Type: "amazon-ebs.ubuntu-1604",
Prepared: true,
Builder: emptyMockBuilder,
Provisioners: []packer.CoreBuildProvisioner{
{
PType: "file",
Provisioner: &MockProvisioner{
Config: MockConfig{
NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
NestedSlice: []NestedMockConfig{},
},
},
},
},
PostProcessors: [][]packer.CoreBuildPostProcessor{},
},
},
false,
},
}
testParse(t, tests)
}

View File

@ -198,6 +198,9 @@ func (cfg *PackerConfig) getCoreBuildProvisioners(source SourceBlock, blocks []*
var diags hcl.Diagnostics
res := []packer.CoreBuildProvisioner{}
for _, pb := range blocks {
if pb.OnlyExcept.Skip(source.Type + "." + source.Name) {
continue
}
provisioner, moreDiags := cfg.startProvisioner(source, pb, ectx, generatedVars)
diags = append(diags, moreDiags...)
if moreDiags.HasErrors() {
@ -238,6 +241,9 @@ func (cfg *PackerConfig) getCoreBuildPostProcessors(source SourceBlock, blocks [
var diags hcl.Diagnostics
res := []packer.CoreBuildPostProcessor{}
for _, ppb := range blocks {
if ppb.OnlyExcept.Skip(source.Type + "." + source.Name) {
continue
}
postProcessor, moreDiags := cfg.startPostProcessor(source, ppb, ectx, generatedVars)
diags = append(diags, moreDiags...)
if moreDiags.HasErrors() {

View File

@ -10,7 +10,7 @@ import (
var (
refVBIsoUbuntu1204 = SourceRef{Type: "virtualbox-iso", Name: "ubuntu-1204"}
refAWSEBSUbuntu1204 = SourceRef{Type: "amazon-ebs", Name: "ubuntu-1604"}
refAWSEBSUbuntu1604 = SourceRef{Type: "amazon-ebs", Name: "ubuntu-1604"}
)
func TestParser_complete(t *testing.T) {
@ -73,13 +73,13 @@ func TestParser_complete(t *testing.T) {
},
Sources: map[SourceRef]SourceBlock{
refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
refAWSEBSUbuntu1204: {Type: "amazon-ebs", Name: "ubuntu-1604"},
refAWSEBSUbuntu1604: {Type: "amazon-ebs", Name: "ubuntu-1604"},
},
Builds: Builds{
&BuildBlock{
Sources: []SourceRef{
refVBIsoUbuntu1204,
refAWSEBSUbuntu1204,
refAWSEBSUbuntu1604,
},
ProvisionerBlocks: []*ProvisionerBlock{
{