packer: test for template path

This commit is contained in:
Mitchell Hashimoto 2015-05-29 14:29:32 -07:00
parent 31d6dcb656
commit 639e63fd7c
6 changed files with 84 additions and 31 deletions

View File

@ -104,7 +104,8 @@ func Decode(target interface{}, config *DecodeOpts, raws ...interface{}) error {
// detecting things like user variables from the raw configuration params.
func DetectContext(raws ...interface{}) (*interpolate.Context, error) {
var s struct {
Vars map[string]string `mapstructure:"packer_user_variables"`
TemplatePath string `mapstructure:"packer_template_path"`
Vars map[string]string `mapstructure:"packer_user_variables"`
}
for _, r := range raws {
@ -114,6 +115,7 @@ func DetectContext(raws ...interface{}) (*interpolate.Context, error) {
}
return &interpolate.Context{
TemplatePath: s.TemplatePath,
UserVariables: s.Vars,
}, nil
}

View File

@ -24,6 +24,9 @@ const (
// force build is enabled.
ForceConfigKey = "packer_force"
// TemplatePathKey is the path to the template that configured this build
TemplatePathKey = "packer_template_path"
// This key contains a map[string]string of the user variables for
// template processing.
UserVariablesConfigKey = "packer_user_variables"
@ -78,6 +81,7 @@ type coreBuild struct {
hooks map[string][]Hook
postProcessors [][]coreBuildPostProcessor
provisioners []coreBuildProvisioner
templatePath string
variables map[string]string
debug bool
@ -125,6 +129,7 @@ func (b *coreBuild) Prepare() (warn []string, err error) {
BuilderTypeConfigKey: b.builderType,
DebugConfigKey: b.debug,
ForceConfigKey: b.force,
TemplatePathKey: b.templatePath,
UserVariablesConfigKey: b.variables,
}

View File

@ -50,27 +50,10 @@ type ComponentFinder struct {
// NewCore creates a new Core.
func NewCore(c *CoreConfig) (*Core, error) {
// Go through and interpolate all the build names. We shuld be able
// to do this at this point with the variables.
builds := make(map[string]*template.Builder)
for _, b := range c.Template.Builders {
v, err := interpolate.Render(b.Name, &interpolate.Context{
UserVariables: c.Variables,
})
if err != nil {
return nil, fmt.Errorf(
"Error interpolating builder '%s': %s",
b.Name, err)
}
builds[v] = b
}
result := &Core{
components: c.Components,
template: c.Template,
variables: c.Variables,
builds: builds,
}
if err := result.validate(); err != nil {
return nil, err
@ -79,6 +62,20 @@ func NewCore(c *CoreConfig) (*Core, error) {
return nil, err
}
// Go through and interpolate all the build names. We shuld be able
// to do this at this point with the variables.
result.builds = make(map[string]*template.Builder)
for _, b := range c.Template.Builders {
v, err := interpolate.Render(b.Name, result.context())
if err != nil {
return nil, fmt.Errorf(
"Error interpolating builder '%s': %s",
b.Name, err)
}
result.builds[v] = b
}
return result, nil
}
@ -204,6 +201,7 @@ func (c *Core) Build(n string) (Build, error) {
builderType: configBuilder.Type,
postProcessors: postProcessors,
provisioners: provisioners,
templatePath: c.template.Path,
variables: c.variables,
}, nil
}
@ -243,7 +241,9 @@ func (c *Core) init() error {
}
// Go through the variables and interpolate the environment variables
ctx := &interpolate.Context{EnableEnv: true}
ctx := c.context()
ctx.EnableEnv = true
ctx.UserVariables = nil
for k, v := range c.template.Variables {
// Ignore variables that are required
if v.Required {
@ -268,3 +268,10 @@ func (c *Core) init() error {
return nil
}
func (c *Core) context() *interpolate.Context {
return &interpolate.Context{
TemplatePath: c.template.Path,
UserVariables: c.variables,
}
}

View File

@ -2,6 +2,7 @@ package packer
import (
"os"
"path/filepath"
"reflect"
"testing"
@ -338,6 +339,35 @@ func TestCoreBuild_postProcess(t *testing.T) {
}
}
func TestCoreBuild_templatePath(t *testing.T) {
config := TestCoreConfig(t)
testCoreTemplate(t, config, fixtureDir("build-template-path.json"))
b := TestBuilder(t, config, "test")
core := TestCore(t, config)
expected, _ := filepath.Abs("./test-fixtures")
build, err := core.Build("test")
if err != nil {
t.Fatalf("err: %s", err)
}
if _, err := build.Prepare(); err != nil {
t.Fatalf("err: %s", err)
}
// Interpolate the config
var result map[string]interface{}
err = configHelper.Decode(&result, nil, b.PrepareConfig...)
if err != nil {
t.Fatalf("err: %s", err)
}
if result["value"] != expected {
t.Fatalf("bad: %#v", result)
}
}
func TestCoreValidate(t *testing.T) {
cases := []struct {
File string

View File

@ -24,13 +24,13 @@ func init() {
// Funcs are the interpolation funcs that are available within interpolations.
var FuncGens = map[string]FuncGenerator{
"env": funcGenEnv,
"isotime": funcGenIsotime,
"pwd": funcGenPwd,
"template_path": funcGenTemplatePath,
"timestamp": funcGenTimestamp,
"uuid": funcGenUuid,
"user": funcGenUser,
"env": funcGenEnv,
"isotime": funcGenIsotime,
"pwd": funcGenPwd,
"template_dir": funcGenTemplateDir,
"timestamp": funcGenTimestamp,
"uuid": funcGenUuid,
"user": funcGenUser,
"upper": funcGenPrimitive(strings.ToUpper),
"lower": funcGenPrimitive(strings.ToLower),
@ -94,13 +94,18 @@ func funcGenPwd(ctx *Context) interface{} {
}
}
func funcGenTemplatePath(ctx *Context) interface{} {
func funcGenTemplateDir(ctx *Context) interface{} {
return func() (string, error) {
if ctx == nil || ctx.TemplatePath == "" {
return "", errors.New("template path not available")
}
return filepath.Dir(ctx.TemplatePath), nil
path, err := filepath.Abs(filepath.Dir(ctx.TemplatePath))
if err != nil {
return "", err
}
return path, nil
}
}

View File

@ -2,6 +2,7 @@ package interpolate
import (
"os"
"path/filepath"
"strconv"
"testing"
"time"
@ -117,18 +118,21 @@ func TestFuncPwd(t *testing.T) {
}
func TestFuncTemplatePath(t *testing.T) {
path := "foo/bar"
expected, _ := filepath.Abs(filepath.Dir(path))
cases := []struct {
Input string
Output string
}{
{
`{{template_path}}`,
`foo`,
`{{template_dir}}`,
expected,
},
}
ctx := &Context{
TemplatePath: "foo/bar",
TemplatePath: path,
}
for _, tc := range cases {
i := &I{Value: tc.Input}