Interpolate boot_command when defined by user variable (#8640)
This commit is contained in:
parent
63cba2dc00
commit
328eb8ee96
|
@ -397,12 +397,17 @@ func (c *Core) init() error {
|
|||
allVariables[k] = v
|
||||
}
|
||||
|
||||
// Regex to exclude any build function variable or template variable
|
||||
// from interpolating earlier
|
||||
// E.g.: {{ .HTTPIP }} won't interpolate now
|
||||
renderFilter := "{{(\\s|)\\.(.*?)(\\s|)}}"
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
shouldRetry = false
|
||||
// First, loop over the variables in the template
|
||||
for k, v := range allVariables {
|
||||
// Interpolate the default
|
||||
renderedV, err := interpolate.Render(v, ctx)
|
||||
renderedV, err := interpolate.RenderRegex(v, ctx, renderFilter)
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// We only get here if interpolation has succeeded, so something is
|
||||
|
|
|
@ -143,6 +143,36 @@ func TestCoreBuild_env(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCoreBuild_IgnoreTemplateVariables(t *testing.T) {
|
||||
os.Setenv("PACKER_TEST_ENV", "test")
|
||||
defer os.Setenv("PACKER_TEST_ENV", "")
|
||||
|
||||
config := TestCoreConfig(t)
|
||||
testCoreTemplate(t, config, fixtureDir("build-ignore-template-variable.json"))
|
||||
core := TestCore(t, config)
|
||||
|
||||
if core.variables["http_ip"] != "{{ .HTTPIP }}" {
|
||||
t.Fatalf("bad: User variable http_ip={{ .HTTPIP }} should not be interpolated")
|
||||
}
|
||||
|
||||
if core.variables["var"] != "test_{{ .PACKER_TEST_TEMP }}" {
|
||||
t.Fatalf("bad: User variable var should be half interpolated to var=test_{{ .PACKER_TEST_TEMP }} but was var=%s", core.variables["var"])
|
||||
}
|
||||
|
||||
if core.variables["array_var"] != "us-west-1,us-west-2" {
|
||||
t.Fatalf("bad: User variable array_var should be \"us-west-1,us-west-2\" but was %s", core.variables["var"])
|
||||
}
|
||||
|
||||
build, err := core.Build("test")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if _, err := build.Prepare(); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreBuild_buildNameVar(t *testing.T) {
|
||||
config := TestCoreConfig(t)
|
||||
testCoreTemplate(t, config, fixtureDir("build-var-build-name.json"))
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"variables": {
|
||||
"var": "{{env `PACKER_TEST_ENV`}}_{{ .PACKER_TEST_TEMP }}",
|
||||
"http_ip": "{{ .HTTPIP }}",
|
||||
"array_var": "us-west-1,us-west-2"
|
||||
},
|
||||
|
||||
"builders": [{
|
||||
"type": "test"
|
||||
}]
|
||||
}
|
|
@ -2,6 +2,9 @@ package interpolate
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/google/uuid"
|
||||
"regexp"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
|
@ -42,8 +45,44 @@ func NewContext() *Context {
|
|||
}
|
||||
|
||||
// Render is shorthand for constructing an I and calling Render.
|
||||
func Render(v string, ctx *Context) (string, error) {
|
||||
return (&I{Value: v}).Render(ctx)
|
||||
func Render(v string, ctx *Context) (rendered string, err error) {
|
||||
// Keep interpolating until all variables are done
|
||||
// Sometimes a variable can been inside another one
|
||||
for {
|
||||
rendered, err = (&I{Value: v}).Render(ctx)
|
||||
if err != nil || rendered == v {
|
||||
break
|
||||
}
|
||||
v = rendered
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Render is shorthand for constructing an I and calling Render.
|
||||
// Use regex to filter variables that are not supposed to be interpolated now
|
||||
func RenderRegex(v string, ctx *Context, regex string) (string, error) {
|
||||
re := regexp.MustCompile(regex)
|
||||
matches := re.FindAllStringSubmatch(v, -1)
|
||||
|
||||
// Replace variables to be excluded with a unique UUID
|
||||
excluded := make(map[string]string)
|
||||
for _, value := range matches {
|
||||
id := uuid.New().String()
|
||||
excluded[id] = value[0]
|
||||
v = strings.ReplaceAll(v, value[0], id)
|
||||
}
|
||||
|
||||
rendered, err := (&I{Value: v}).Render(ctx)
|
||||
if err != nil {
|
||||
return rendered, err
|
||||
}
|
||||
|
||||
// Replace back by the UUID the previously excluded values
|
||||
for id, value := range excluded {
|
||||
rendered = strings.ReplaceAll(rendered, id, value)
|
||||
}
|
||||
|
||||
return rendered, nil
|
||||
}
|
||||
|
||||
// Validate is shorthand for constructing an I and calling Validate.
|
||||
|
|
Loading…
Reference in New Issue