packer: `only` metaparameter for provisioners [GH-438]

This commit is contained in:
Mitchell Hashimoto 2013-09-20 10:49:35 -07:00
parent f79c5543d1
commit 28d25c718c
2 changed files with 129 additions and 3 deletions

View File

@ -59,6 +59,7 @@ type RawPostProcessorConfig struct {
type RawProvisionerConfig struct {
Type string
Override map[string]interface{}
Only []string
RawConfig interface{}
}
@ -237,9 +238,8 @@ func ParseTemplate(data []byte) (t *Template, err error) {
continue
}
// The provisioners not only don't need or want the override settings
// (as they are processed as part of the preparation below), but will
// actively reject them as invalid configuration.
// Delete the keys that we used
delete(v, "only")
delete(v, "override")
// Verify that the override keys exist...
@ -250,6 +250,17 @@ func ParseTemplate(data []byte) (t *Template, err error) {
}
}
// Verify that the only settings are good
if len(raw.Only) > 0 {
for _, n := range raw.Only {
if _, ok := t.Builders[n]; !ok {
errors = append(errors,
fmt.Errorf("provisioner %d: 'only' specified builder '%s' not found",
i+1, n))
}
}
}
raw.RawConfig = v
}
@ -425,6 +436,21 @@ func (t *Template) Build(name string, components *ComponentFinder) (b Build, err
// Prepare the provisioners
provisioners := make([]coreBuildProvisioner, 0, len(t.Provisioners))
for _, rawProvisioner := range t.Provisioners {
if len(rawProvisioner.Only) > 0 {
onlyFound := false
for _, n := range rawProvisioner.Only {
if n == name {
onlyFound = true
break
}
}
if !onlyFound {
// Skip this provisioner
continue
}
}
var provisioner Provisioner
provisioner, err = components.Provisioner(rawProvisioner.Type)
if err != nil {

View File

@ -9,6 +9,26 @@ import (
"testing"
)
func testTemplateComponentFinder() *ComponentFinder {
builder := testBuilder()
provisioner := &MockProvisioner{}
builderMap := map[string]Builder{
"test-builder": builder,
}
provisionerMap := map[string]Provisioner{
"test-prov": provisioner,
}
builderFactory := func(n string) (Builder, error) { return builderMap[n], nil }
provFactory := func(n string) (Provisioner, error) { return provisionerMap[n], nil }
return &ComponentFinder{
Builder: builderFactory,
Provisioner: provFactory,
}
}
func TestParseTemplateFile_basic(t *testing.T) {
data := `
{
@ -663,6 +683,86 @@ func TestTemplate_Build(t *testing.T) {
}
}
func TestTemplateBuild_onlyProvInvalid(t *testing.T) {
data := `
{
"builders": [
{
"name": "test1",
"type": "test-builder"
},
{
"name": "test2",
"type": "test-builder"
}
],
"provisioners": [
{
"type": "test-prov",
"only": "test5"
}
]
}
`
_, err := ParseTemplate([]byte(data))
if err == nil {
t.Fatal("should have error")
}
}
func TestTemplateBuild_onlyProv(t *testing.T) {
data := `
{
"builders": [
{
"name": "test1",
"type": "test-builder"
},
{
"name": "test2",
"type": "test-builder"
}
],
"provisioners": [
{
"type": "test-prov",
"only": ["test2"]
}
]
}
`
template, err := ParseTemplate([]byte(data))
if err != nil {
t.Fatalf("err: %s", err)
}
// Verify test1 has no provisioners
build, err := template.Build("test1", testTemplateComponentFinder())
if err != nil {
t.Fatalf("err: %s", err)
}
cbuild := build.(*coreBuild)
if len(cbuild.provisioners) > 0 {
t.Fatal("should have no provisioners")
}
// Verify test2 has no provisioners
build, err = template.Build("test2", testTemplateComponentFinder())
if err != nil {
t.Fatalf("err: %s", err)
}
cbuild = build.(*coreBuild)
if len(cbuild.provisioners) != 1 {
t.Fatalf("invalid: %d", len(cbuild.provisioners))
}
}
func TestTemplate_Build_ProvisionerOverride(t *testing.T) {
assert := asserts.NewTestingAsserts(t, true)