Render variables one time on prepare method (#8727)

This commit is contained in:
Sylvia Moss 2020-02-13 17:35:23 +01:00 committed by GitHub
parent c2ad9481f6
commit 23fa3107a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 76 additions and 3 deletions

View File

@ -25,6 +25,11 @@ func (a *NullArtifact) String() string {
}
func (a *NullArtifact) State(name string) interface{} {
if name == "generated_data" {
return map[interface{}]interface{}{
"ID": "Null",
}
}
return nil
}

View File

@ -47,6 +47,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
state := new(multistep.BasicStateBag)
state.Put("hook", hook)
state.Put("ui", ui)
state.Put("instance_id", "Null")
// Run!
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)

View File

@ -111,6 +111,33 @@ func TestBuildOnlyFileMultipleFlags(t *testing.T) {
}
}
func TestBuildProvisionAndPosProcessWithBuildVariablesSharing(t *testing.T) {
c := &BuildCommand{
Meta: testMetaFile(t),
}
args := []string{
filepath.Join(testFixture("build-variable-sharing"), "template.json"),
}
files := []string{
"provisioner.Null.txt",
"post-processor.Null.txt",
}
defer cleanup(files...)
if code := c.Run(args); code != 0 {
fatalCommand(t, c.Meta)
}
for _, f := range files {
if !fileExists(f) {
t.Errorf("Expected to find %s", f)
}
}
}
func TestBuildEverything(t *testing.T) {
c := &BuildCommand{
Meta: testMetaFile(t),
@ -231,7 +258,7 @@ func testMetaFile(t *testing.T) Meta {
}
}
func cleanup() {
func cleanup(moreFiles ...string) {
os.RemoveAll("chocolate.txt")
os.RemoveAll("vanilla.txt")
os.RemoveAll("cherry.txt")
@ -245,6 +272,9 @@ func cleanup() {
os.RemoveAll("lilas.txt")
os.RemoveAll("campanules.txt")
os.RemoveAll("ducky.txt")
for _, file := range moreFiles {
os.RemoveAll(file)
}
}
func TestBuildCommand_ParseArgs(t *testing.T) {

View File

@ -0,0 +1,25 @@
{
"builders": [
{
"name": "chocolate",
"type": "null",
"communicator": "none"
}
],
"provisioners": [
{
"type": "shell-local",
"inline": [
"echo hi > provisioner.{{ build `ID`}}.txt"
]
}
],
"post-processors": [
{
"type": "shell-local",
"inline": [
"echo hi > post-processor.{{ build `ID`}}.txt"
]
}
]
}

View File

@ -80,6 +80,13 @@ func BasicPlaceholderData() map[string]string {
}
func CastDataToMap(data interface{}) map[string]interface{} {
if interMap, ok := data.(map[string]interface{}); ok {
// null and file builder sometimes don't use a communicator and
// therefore don't go through RPC
return interMap
}
// Provisioners expect a map[string]interface{} in their data field, but
// it gets converted into a map[interface]interface on the way over the
// RPC. Check that data can be cast into such a form, and cast it.

View File

@ -44,7 +44,12 @@ func NewContext() *Context {
return &Context{}
}
// Render is shorthand for constructing an I and calling Render.
// RenderOnce is shorthand for constructing an I and calling Render one time.
func RenderOnce(v string, ctx *Context) (string, error) {
return (&I{Value: v}).Render(ctx)
}
// Render is shorthand for constructing an I and calling Render until all variables are rendered.
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

View File

@ -57,7 +57,7 @@ func RenderMap(v interface{}, ctx *Context, f *RenderFilter) (map[string]interfa
// RenderInterface renders any value and returns the resulting value.
func RenderInterface(v interface{}, ctx *Context) (interface{}, error) {
f := func(v string) (string, error) {
return Render(v, ctx)
return RenderOnce(v, ctx)
}
walker := &renderWalker{