Render variables one time on prepare method (#8727)
This commit is contained in:
parent
c2ad9481f6
commit
23fa3107a3
|
@ -25,6 +25,11 @@ func (a *NullArtifact) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *NullArtifact) State(name string) interface{} {
|
func (a *NullArtifact) State(name string) interface{} {
|
||||||
|
if name == "generated_data" {
|
||||||
|
return map[interface{}]interface{}{
|
||||||
|
"ID": "Null",
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||||
state := new(multistep.BasicStateBag)
|
state := new(multistep.BasicStateBag)
|
||||||
state.Put("hook", hook)
|
state.Put("hook", hook)
|
||||||
state.Put("ui", ui)
|
state.Put("ui", ui)
|
||||||
|
state.Put("instance_id", "Null")
|
||||||
|
|
||||||
// Run!
|
// Run!
|
||||||
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
|
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
|
||||||
|
|
|
@ -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) {
|
func TestBuildEverything(t *testing.T) {
|
||||||
c := &BuildCommand{
|
c := &BuildCommand{
|
||||||
Meta: testMetaFile(t),
|
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("chocolate.txt")
|
||||||
os.RemoveAll("vanilla.txt")
|
os.RemoveAll("vanilla.txt")
|
||||||
os.RemoveAll("cherry.txt")
|
os.RemoveAll("cherry.txt")
|
||||||
|
@ -245,6 +272,9 @@ func cleanup() {
|
||||||
os.RemoveAll("lilas.txt")
|
os.RemoveAll("lilas.txt")
|
||||||
os.RemoveAll("campanules.txt")
|
os.RemoveAll("campanules.txt")
|
||||||
os.RemoveAll("ducky.txt")
|
os.RemoveAll("ducky.txt")
|
||||||
|
for _, file := range moreFiles {
|
||||||
|
os.RemoveAll(file)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildCommand_ParseArgs(t *testing.T) {
|
func TestBuildCommand_ParseArgs(t *testing.T) {
|
||||||
|
|
|
@ -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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -80,6 +80,13 @@ func BasicPlaceholderData() map[string]string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func CastDataToMap(data interface{}) map[string]interface{} {
|
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
|
// Provisioners expect a map[string]interface{} in their data field, but
|
||||||
// it gets converted into a map[interface]interface on the way over the
|
// 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.
|
// RPC. Check that data can be cast into such a form, and cast it.
|
||||||
|
|
|
@ -44,7 +44,12 @@ func NewContext() *Context {
|
||||||
return &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) {
|
func Render(v string, ctx *Context) (rendered string, err error) {
|
||||||
// Keep interpolating until all variables are done
|
// Keep interpolating until all variables are done
|
||||||
// Sometimes a variable can been inside another one
|
// Sometimes a variable can been inside another one
|
||||||
|
|
|
@ -57,7 +57,7 @@ func RenderMap(v interface{}, ctx *Context, f *RenderFilter) (map[string]interfa
|
||||||
// RenderInterface renders any value and returns the resulting value.
|
// RenderInterface renders any value and returns the resulting value.
|
||||||
func RenderInterface(v interface{}, ctx *Context) (interface{}, error) {
|
func RenderInterface(v interface{}, ctx *Context) (interface{}, error) {
|
||||||
f := func(v string) (string, error) {
|
f := func(v string) (string, error) {
|
||||||
return Render(v, ctx)
|
return RenderOnce(v, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
walker := &renderWalker{
|
walker := &renderWalker{
|
||||||
|
|
Loading…
Reference in New Issue