packer: test for template path
This commit is contained in:
parent
31d6dcb656
commit
639e63fd7c
|
@ -104,7 +104,8 @@ func Decode(target interface{}, config *DecodeOpts, raws ...interface{}) error {
|
||||||
// detecting things like user variables from the raw configuration params.
|
// detecting things like user variables from the raw configuration params.
|
||||||
func DetectContext(raws ...interface{}) (*interpolate.Context, error) {
|
func DetectContext(raws ...interface{}) (*interpolate.Context, error) {
|
||||||
var s struct {
|
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 {
|
for _, r := range raws {
|
||||||
|
@ -114,6 +115,7 @@ func DetectContext(raws ...interface{}) (*interpolate.Context, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &interpolate.Context{
|
return &interpolate.Context{
|
||||||
|
TemplatePath: s.TemplatePath,
|
||||||
UserVariables: s.Vars,
|
UserVariables: s.Vars,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,9 @@ const (
|
||||||
// force build is enabled.
|
// force build is enabled.
|
||||||
ForceConfigKey = "packer_force"
|
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
|
// This key contains a map[string]string of the user variables for
|
||||||
// template processing.
|
// template processing.
|
||||||
UserVariablesConfigKey = "packer_user_variables"
|
UserVariablesConfigKey = "packer_user_variables"
|
||||||
|
@ -78,6 +81,7 @@ type coreBuild struct {
|
||||||
hooks map[string][]Hook
|
hooks map[string][]Hook
|
||||||
postProcessors [][]coreBuildPostProcessor
|
postProcessors [][]coreBuildPostProcessor
|
||||||
provisioners []coreBuildProvisioner
|
provisioners []coreBuildProvisioner
|
||||||
|
templatePath string
|
||||||
variables map[string]string
|
variables map[string]string
|
||||||
|
|
||||||
debug bool
|
debug bool
|
||||||
|
@ -125,6 +129,7 @@ func (b *coreBuild) Prepare() (warn []string, err error) {
|
||||||
BuilderTypeConfigKey: b.builderType,
|
BuilderTypeConfigKey: b.builderType,
|
||||||
DebugConfigKey: b.debug,
|
DebugConfigKey: b.debug,
|
||||||
ForceConfigKey: b.force,
|
ForceConfigKey: b.force,
|
||||||
|
TemplatePathKey: b.templatePath,
|
||||||
UserVariablesConfigKey: b.variables,
|
UserVariablesConfigKey: b.variables,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,27 +50,10 @@ type ComponentFinder struct {
|
||||||
|
|
||||||
// NewCore creates a new Core.
|
// NewCore creates a new Core.
|
||||||
func NewCore(c *CoreConfig) (*Core, error) {
|
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{
|
result := &Core{
|
||||||
components: c.Components,
|
components: c.Components,
|
||||||
template: c.Template,
|
template: c.Template,
|
||||||
variables: c.Variables,
|
variables: c.Variables,
|
||||||
builds: builds,
|
|
||||||
}
|
}
|
||||||
if err := result.validate(); err != nil {
|
if err := result.validate(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -79,6 +62,20 @@ func NewCore(c *CoreConfig) (*Core, error) {
|
||||||
return nil, err
|
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
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,6 +201,7 @@ func (c *Core) Build(n string) (Build, error) {
|
||||||
builderType: configBuilder.Type,
|
builderType: configBuilder.Type,
|
||||||
postProcessors: postProcessors,
|
postProcessors: postProcessors,
|
||||||
provisioners: provisioners,
|
provisioners: provisioners,
|
||||||
|
templatePath: c.template.Path,
|
||||||
variables: c.variables,
|
variables: c.variables,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -243,7 +241,9 @@ func (c *Core) init() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go through the variables and interpolate the environment variables
|
// 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 {
|
for k, v := range c.template.Variables {
|
||||||
// Ignore variables that are required
|
// Ignore variables that are required
|
||||||
if v.Required {
|
if v.Required {
|
||||||
|
@ -268,3 +268,10 @@ func (c *Core) init() error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Core) context() *interpolate.Context {
|
||||||
|
return &interpolate.Context{
|
||||||
|
TemplatePath: c.template.Path,
|
||||||
|
UserVariables: c.variables,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package packer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"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) {
|
func TestCoreValidate(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
File string
|
File string
|
||||||
|
|
|
@ -24,13 +24,13 @@ func init() {
|
||||||
|
|
||||||
// Funcs are the interpolation funcs that are available within interpolations.
|
// Funcs are the interpolation funcs that are available within interpolations.
|
||||||
var FuncGens = map[string]FuncGenerator{
|
var FuncGens = map[string]FuncGenerator{
|
||||||
"env": funcGenEnv,
|
"env": funcGenEnv,
|
||||||
"isotime": funcGenIsotime,
|
"isotime": funcGenIsotime,
|
||||||
"pwd": funcGenPwd,
|
"pwd": funcGenPwd,
|
||||||
"template_path": funcGenTemplatePath,
|
"template_dir": funcGenTemplateDir,
|
||||||
"timestamp": funcGenTimestamp,
|
"timestamp": funcGenTimestamp,
|
||||||
"uuid": funcGenUuid,
|
"uuid": funcGenUuid,
|
||||||
"user": funcGenUser,
|
"user": funcGenUser,
|
||||||
|
|
||||||
"upper": funcGenPrimitive(strings.ToUpper),
|
"upper": funcGenPrimitive(strings.ToUpper),
|
||||||
"lower": funcGenPrimitive(strings.ToLower),
|
"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) {
|
return func() (string, error) {
|
||||||
if ctx == nil || ctx.TemplatePath == "" {
|
if ctx == nil || ctx.TemplatePath == "" {
|
||||||
return "", errors.New("template path not available")
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package interpolate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -117,18 +118,21 @@ func TestFuncPwd(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFuncTemplatePath(t *testing.T) {
|
func TestFuncTemplatePath(t *testing.T) {
|
||||||
|
path := "foo/bar"
|
||||||
|
expected, _ := filepath.Abs(filepath.Dir(path))
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
Input string
|
Input string
|
||||||
Output string
|
Output string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
`{{template_path}}`,
|
`{{template_dir}}`,
|
||||||
`foo`,
|
expected,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := &Context{
|
ctx := &Context{
|
||||||
TemplatePath: "foo/bar",
|
TemplatePath: path,
|
||||||
}
|
}
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
i := &I{Value: tc.Input}
|
i := &I{Value: tc.Input}
|
||||||
|
|
Loading…
Reference in New Issue