Template can create Builds
This commit is contained in:
parent
8f08c5d8a2
commit
262d8aa9a8
|
@ -7,6 +7,7 @@ package packer
|
|||
type Build struct {
|
||||
name string
|
||||
builder Builder
|
||||
rawConfig interface{}
|
||||
|
||||
prepareCalled bool
|
||||
}
|
||||
|
@ -43,9 +44,9 @@ func (NilBuilderFactory) CreateBuilder(name string) Builder {
|
|||
|
||||
// Prepare prepares the build by doing some initialization for the builder
|
||||
// and any hooks. This _must_ be called prior to Run.
|
||||
func (b *Build) Prepare(config interface{}) {
|
||||
func (b *Build) Prepare() {
|
||||
b.prepareCalled = true
|
||||
b.builder.Prepare(config)
|
||||
b.builder.Prepare(b.rawConfig)
|
||||
}
|
||||
|
||||
// Runs the actual build. Prepare must be called prior to running this.
|
||||
|
|
|
@ -5,6 +5,14 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
type hashBuilderFactory struct {
|
||||
builderMap map[string]Builder
|
||||
}
|
||||
|
||||
func (bf *hashBuilderFactory) CreateBuilder(name string) Builder {
|
||||
return bf.builderMap[name]
|
||||
}
|
||||
|
||||
type TestBuilder struct {
|
||||
prepareCalled bool
|
||||
prepareConfig interface{}
|
||||
|
@ -28,17 +36,25 @@ func testBuild() *Build {
|
|||
return &Build{
|
||||
name: "test",
|
||||
builder: &TestBuilder{},
|
||||
rawConfig: 42,
|
||||
}
|
||||
}
|
||||
|
||||
func testBuilder() *TestBuilder {
|
||||
return &TestBuilder{}
|
||||
}
|
||||
|
||||
func testBuildFactory(builderMap map[string]Builder) BuilderFactory {
|
||||
return &hashBuilderFactory{builderMap}
|
||||
}
|
||||
|
||||
func TestBuild_Prepare(t *testing.T) {
|
||||
assert := asserts.NewTestingAsserts(t, true)
|
||||
|
||||
build := testBuild()
|
||||
build.Prepare(42)
|
||||
|
||||
builder := build.builder.(*TestBuilder)
|
||||
|
||||
build.Prepare()
|
||||
assert.True(builder.prepareCalled, "prepare should be called")
|
||||
assert.Equal(builder.prepareConfig, 42, "prepare config should be 42")
|
||||
}
|
||||
|
@ -49,7 +65,7 @@ func TestBuild_Run(t *testing.T) {
|
|||
ui := testUi()
|
||||
|
||||
build := testBuild()
|
||||
build.Prepare(nil)
|
||||
build.Prepare()
|
||||
build.Run(ui)
|
||||
|
||||
builder := build.builder.(*TestBuilder)
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package packer
|
||||
|
||||
import "encoding/json"
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// The rawTemplate struct represents the structure of a template read
|
||||
// directly from a file. The builders and other components map just to
|
||||
|
@ -74,3 +77,42 @@ func ParseTemplate(data []byte) (t *Template, err error) {
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
// BuildNames returns a slice of the available names of builds that
|
||||
// this template represents.
|
||||
func (t *Template) BuildNames() []string {
|
||||
names := make([]string, len(t.Builders))
|
||||
i := 0
|
||||
for name, _ := range t.Builders {
|
||||
names[i] = name
|
||||
i++
|
||||
}
|
||||
|
||||
return names
|
||||
}
|
||||
|
||||
// Build returns a Build for the given name.
|
||||
//
|
||||
// If the build does not exist as part of this template, an error is
|
||||
// returned.
|
||||
func (t *Template) Build(name string, bf BuilderFactory) (b *Build, err error) {
|
||||
builderConfig, ok := t.Builders[name]
|
||||
if !ok {
|
||||
err = fmt.Errorf("No such build found in template: %s", name)
|
||||
return
|
||||
}
|
||||
|
||||
builder := bf.CreateBuilder(builderConfig.builderName)
|
||||
if builder == nil {
|
||||
err = fmt.Errorf("Builder could not be found: %s", builderConfig.builderName)
|
||||
return
|
||||
}
|
||||
|
||||
b = &Build{
|
||||
name: name,
|
||||
builder: builder,
|
||||
rawConfig: builderConfig.rawConfig,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package packer
|
|||
|
||||
import (
|
||||
"cgl.tideland.biz/asserts"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -87,3 +88,121 @@ func TestParseTemplate_BuilderWithName(t *testing.T) {
|
|||
assert.True(ok, "should have bob builder")
|
||||
assert.Equal(builder.builderName, "amazon-ebs", "builder should be amazon-ebs")
|
||||
}
|
||||
|
||||
func TestTemplate_BuildNames(t *testing.T) {
|
||||
assert := asserts.NewTestingAsserts(t, true)
|
||||
|
||||
data := `
|
||||
{
|
||||
"name": "my-image",
|
||||
"builders": [
|
||||
{
|
||||
"name": "bob",
|
||||
"type": "amazon-ebs"
|
||||
},
|
||||
{
|
||||
"name": "chris",
|
||||
"type": "another"
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
result, err := ParseTemplate([]byte(data))
|
||||
assert.Nil(err, "should not error")
|
||||
|
||||
buildNames := result.BuildNames()
|
||||
sort.Strings(buildNames)
|
||||
assert.Equal(buildNames, []string{"bob", "chris"}, "should have proper builds")
|
||||
}
|
||||
|
||||
func TestTemplate_BuildUnknown(t *testing.T) {
|
||||
assert := asserts.NewTestingAsserts(t, true)
|
||||
|
||||
data := `
|
||||
{
|
||||
"name": "my-image",
|
||||
"builders": [
|
||||
{
|
||||
"name": "test1",
|
||||
"type": "test-builder"
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
template, err := ParseTemplate([]byte(data))
|
||||
assert.Nil(err, "should not error")
|
||||
|
||||
build, err := template.Build("nope", nil)
|
||||
assert.Nil(build, "build should be nil")
|
||||
assert.NotNil(err, "should have error")
|
||||
}
|
||||
|
||||
func TestTemplate_BuildUnknownBuilder(t *testing.T) {
|
||||
assert := asserts.NewTestingAsserts(t, true)
|
||||
|
||||
data := `
|
||||
{
|
||||
"name": "my-image",
|
||||
"builders": [
|
||||
{
|
||||
"name": "test1",
|
||||
"type": "test-builder"
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
template, err := ParseTemplate([]byte(data))
|
||||
assert.Nil(err, "should not error")
|
||||
|
||||
builderFactory := testBuildFactory(map[string]Builder{})
|
||||
build, err := template.Build("test1", builderFactory)
|
||||
assert.Nil(build, "build should be nil")
|
||||
assert.NotNil(err, "should have error")
|
||||
}
|
||||
|
||||
func TestTemplate_Build(t *testing.T) {
|
||||
assert := asserts.NewTestingAsserts(t, true)
|
||||
|
||||
data := `
|
||||
{
|
||||
"name": "my-image",
|
||||
"builders": [
|
||||
{
|
||||
"name": "test1",
|
||||
"type": "test-builder"
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
expectedConfig := map[string]interface{} {
|
||||
"name": "test1",
|
||||
"type": "test-builder",
|
||||
}
|
||||
|
||||
template, err := ParseTemplate([]byte(data))
|
||||
assert.Nil(err, "should not error")
|
||||
|
||||
builder := testBuilder()
|
||||
builderMap := map[string]Builder {
|
||||
"test-builder": builder,
|
||||
}
|
||||
|
||||
builderFactory := testBuildFactory(builderMap)
|
||||
|
||||
// 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", builderFactory)
|
||||
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")
|
||||
assert.Equal(builder.runBuild, build, "run should be called with build")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue