From fbcc6cb2b2699d57c47d42c88ce53600df32fbab Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 22 May 2013 16:15:57 -0700 Subject: [PATCH] packer: Build now has provisioners, template parses and builds --- packer/build.go | 18 +++++++++++++----- packer/build_test.go | 6 +++--- packer/template.go | 29 +++++++++++++++++++++++++---- packer/template_test.go | 28 +++++++++++++++++++++------- 4 files changed, 62 insertions(+), 19 deletions(-) diff --git a/packer/build.go b/packer/build.go index 698ccc0af..2a8c4cdd0 100644 --- a/packer/build.go +++ b/packer/build.go @@ -15,14 +15,22 @@ type Build interface { // multiple files, of course, but it should be for only a single provider // (such as VirtualBox, EC2, etc.). type coreBuild struct { - name string - builder Builder - hooks map[string][]Hook - rawConfig interface{} + name string + builder Builder + builderConfig interface{} + hooks map[string][]Hook + provisioners []coreBuildProvisioner prepareCalled bool } +// Keeps track of the provisioner and the configuration of the provisioner +// within the build. +type coreBuildProvisioner struct { + provisioner Provisioner + config interface{} +} + // Returns the name of the build. func (b *coreBuild) Name() string { return b.name @@ -32,7 +40,7 @@ func (b *coreBuild) Name() string { // and any hooks. This _must_ be called prior to Run. func (b *coreBuild) Prepare() (err error) { b.prepareCalled = true - err = b.builder.Prepare(b.rawConfig) + err = b.builder.Prepare(b.builderConfig) if err != nil { log.Printf("Build '%s' prepare failure: %s\n", b.name, err) } diff --git a/packer/build_test.go b/packer/build_test.go index a5d656292..8679873c3 100644 --- a/packer/build_test.go +++ b/packer/build_test.go @@ -28,9 +28,9 @@ func (tb *TestBuilder) Run(ui Ui, h Hook) Artifact { func testBuild() Build { return &coreBuild{ - name: "test", - builder: &TestBuilder{}, - rawConfig: 42, + name: "test", + builder: &TestBuilder{}, + builderConfig: 42, } } diff --git a/packer/template.go b/packer/template.go index 8e5ee8188..82ba0ca16 100644 --- a/packer/template.go +++ b/packer/template.go @@ -149,6 +149,7 @@ func (t *Template) BuildNames() []string { // If the build does not exist as part of this template, an error is // returned. func (t *Template) Build(name string, components *ComponentFinder) (b Build, err error) { + // Setup the Builder builderConfig, ok := t.Builders[name] if !ok { err = fmt.Errorf("No such build found in template: %s", name) @@ -165,6 +166,7 @@ func (t *Template) Build(name string, components *ComponentFinder) (b Build, err return } + // Gather the Hooks hooks := make(map[string][]Hook) for tplEvent, tplHooks := range t.Hooks { curHooks := make([]Hook, 0, len(tplHooks)) @@ -187,11 +189,30 @@ func (t *Template) Build(name string, components *ComponentFinder) (b Build, err hooks[tplEvent] = curHooks } + // Prepare the provisioners + provisioners := make([]coreBuildProvisioner, 0, len(t.Provisioners)) + for _, rawProvisioner := range t.Provisioners { + var provisioner Provisioner + provisioner, err = components.Provisioner(rawProvisioner.pType) + if err != nil { + return + } + + if provisioner == nil { + err = fmt.Errorf("Provisioner type not found: %s", rawProvisioner.pType) + return + } + + coreProv := coreBuildProvisioner{provisioner, rawProvisioner.rawConfig} + provisioners = append(provisioners, coreProv) + } + b = &coreBuild{ - name: name, - builder: builder, - hooks: hooks, - rawConfig: builderConfig.rawConfig, + name: name, + builder: builder, + builderConfig: builderConfig.rawConfig, + hooks: hooks, + provisioners: provisioners, } return diff --git a/packer/template_test.go b/packer/template_test.go index de9c89381..3efc86dd9 100644 --- a/packer/template_test.go +++ b/packer/template_test.go @@ -302,6 +302,12 @@ func TestTemplate_Build(t *testing.T) { "name": "test1", "type": "test-builder" } + ], + + "provisioners": [ + { + "type": "test-prov" + } ] } ` @@ -319,18 +325,26 @@ func TestTemplate_Build(t *testing.T) { "test-builder": builder, } + provisioner := &TestProvisioner{} + provisionerMap := map[string]Provisioner{ + "test-prov": provisioner, + } + builderFactory := func(n string) (Builder, error) { return builderMap[n], nil } - components := &ComponentFinder{Builder: builderFactory} + provFactory := func(n string) (Provisioner, error) { return provisionerMap[n], nil } + components := &ComponentFinder{ + Builder: builderFactory, + Provisioner: provFactory, + } // Get the build, verifying we can get it without issue, but also // that the proper builder was looked up and used for the build. build, err := template.Build("test1", components) assert.Nil(err, "should not error") - build.Prepare() - build.Run(testUi()) - - assert.True(builder.prepareCalled, "prepare should be called") - assert.Equal(builder.prepareConfig, expectedConfig, "prepare config should be correct") - assert.True(builder.runCalled, "run should be called") + coreBuild, ok := build.(*coreBuild) + assert.True(ok, "should be a core build") + assert.Equal(coreBuild.builder, builder, "should have the same builder") + assert.Equal(coreBuild.builderConfig, expectedConfig, "should have proper config") + assert.Equal(len(coreBuild.provisioners), 1, "should have one provisioner") }