diff --git a/CHANGELOG.md b/CHANGELOG.md index 1419d99d9..b7e384ca6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,8 @@ IMPROVEMENTS: * core: Plugins communicate over a single TCP connection per plugin now, instead of sometimes dozens. Performance around plugin communication dramatically increased. +* core: Build names are now template processed so you can use things + like user variables in them. [GH-744] * builder/amazon/all: Launched EC2 instances now have a name of "Packer Builder" so that they are easily recognizable. [GH-642] * builder/amazon/all: Copying AMIs to multiple regions now happens diff --git a/command/inspect/command.go b/command/inspect/command.go index cdad078be..25d8427cc 100644 --- a/command/inspect/command.go +++ b/command/inspect/command.go @@ -142,5 +142,9 @@ func (c Command) Run(env packer.Environment, args []string) int { } } + ui.Say("\nNote: If your build names contain user variables or template\n" + + "functions such as 'timestamp', these are processed at build time,\n" + + "and therefore only show in their raw form here.") + return 0 } diff --git a/packer/template.go b/packer/template.go index ac04bad4d..aadaf4511 100644 --- a/packer/template.go +++ b/packer/template.go @@ -446,6 +446,39 @@ func (t *Template) Build(name string, components *ComponentFinder) (b Build, err return } + // Prepare the variables + var varErrors []error + variables := make(map[string]string) + for k, v := range t.Variables { + if v.Required && !v.HasValue { + varErrors = append(varErrors, + fmt.Errorf("Required user variable '%s' not set", k)) + } + + var val string = v.Default + if v.HasValue { + val = v.Value + } + + variables[k] = val + } + + if len(varErrors) > 0 { + return nil, &MultiError{varErrors} + } + + // Process the name + tpl, err := NewConfigTemplate() + if err != nil { + return nil, err + } + tpl.UserVars = variables + + name, err = tpl.Process(name, nil) + if err != nil { + return nil, err + } + // Gather the Hooks hooks := make(map[string][]Hook) for tplEvent, tplHooks := range t.Hooks { @@ -542,27 +575,6 @@ func (t *Template) Build(name string, components *ComponentFinder) (b Build, err provisioners = append(provisioners, coreProv) } - // Prepare the variables - var varErrors []error - variables := make(map[string]string) - for k, v := range t.Variables { - if v.Required && !v.HasValue { - varErrors = append(varErrors, - fmt.Errorf("Required user variable '%s' not set", k)) - } - - var val string = v.Default - if v.HasValue { - val = v.Value - } - - variables[k] = val - } - - if len(varErrors) > 0 { - return nil, &MultiError{varErrors} - } - b = &coreBuild{ name: name, builder: builder, diff --git a/packer/template_test.go b/packer/template_test.go index e71b35d96..38412c790 100644 --- a/packer/template_test.go +++ b/packer/template_test.go @@ -688,6 +688,48 @@ func TestTemplate_BuildUnknownBuilder(t *testing.T) { } } +func TestTemplateBuild_names(t *testing.T) { + data := ` + { + "variables": { + "foo": null + }, + + "builders": [ + { + "name": "test1", + "type": "test-builder" + }, + { + "name": "test2-{{user \"foo\"}}", + "type": "test-builder" + } + ] + } + ` + + template, err := ParseTemplate([]byte(data), map[string]string{"foo": "bar"}) + if err != nil { + t.Fatalf("err: %s", err) + } + + b, err := template.Build("test1", testComponentFinder()) + if err != nil { + t.Fatalf("err: %s", err) + } + if b.Name() != "test1" { + t.Fatalf("bad: %#v", b.Name()) + } + + b, err = template.Build("test2-{{user \"foo\"}}", testComponentFinder()) + if err != nil { + t.Fatalf("err: %s", err) + } + if b.Name() != "test2-bar" { + t.Fatalf("bad: %#v", b.Name()) + } +} + func TestTemplate_Build_NilBuilderFunc(t *testing.T) { data := ` {