2015-05-23 17:48:07 -04:00
|
|
|
package packer
|
|
|
|
|
|
|
|
import (
|
2019-03-22 09:53:28 -04:00
|
|
|
"context"
|
2020-04-16 05:58:54 -04:00
|
|
|
"errors"
|
2015-05-23 17:48:07 -04:00
|
|
|
"os"
|
2015-05-29 17:29:32 -04:00
|
|
|
"path/filepath"
|
2015-05-23 19:12:32 -04:00
|
|
|
"reflect"
|
2015-05-23 17:48:07 -04:00
|
|
|
"testing"
|
|
|
|
|
2020-12-17 16:29:25 -05:00
|
|
|
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
|
|
"github.com/hashicorp/packer-plugin-sdk/template"
|
|
|
|
configHelper "github.com/hashicorp/packer-plugin-sdk/template/config"
|
2015-05-23 17:48:07 -04:00
|
|
|
)
|
|
|
|
|
2015-05-23 19:12:32 -04:00
|
|
|
func TestCoreBuildNames(t *testing.T) {
|
|
|
|
cases := []struct {
|
|
|
|
File string
|
|
|
|
Vars map[string]string
|
|
|
|
Result []string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"build-names-basic.json",
|
|
|
|
nil,
|
|
|
|
[]string{"something"},
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
"build-names-func.json",
|
|
|
|
nil,
|
|
|
|
[]string{"TUBES"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range cases {
|
|
|
|
tpl, err := template.ParseFile(fixtureDir(tc.File))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s\n\n%s", tc.File, err)
|
|
|
|
}
|
|
|
|
|
2020-07-24 04:58:03 -04:00
|
|
|
core := NewCore(&CoreConfig{
|
2015-05-23 19:12:32 -04:00
|
|
|
Template: tpl,
|
|
|
|
Variables: tc.Vars,
|
|
|
|
})
|
2020-07-24 04:58:03 -04:00
|
|
|
err = core.Initialize()
|
2015-05-23 19:12:32 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s\n\n%s", tc.File, err)
|
|
|
|
}
|
|
|
|
|
2020-04-30 10:40:58 -04:00
|
|
|
names := core.BuildNames(nil, nil)
|
2015-05-23 19:12:32 -04:00
|
|
|
if !reflect.DeepEqual(names, tc.Result) {
|
|
|
|
t.Fatalf("err: %s\n\n%#v", tc.File, names)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-25 20:58:59 -04:00
|
|
|
func TestCoreBuild_basic(t *testing.T) {
|
|
|
|
config := TestCoreConfig(t)
|
|
|
|
testCoreTemplate(t, config, fixtureDir("build-basic.json"))
|
|
|
|
b := TestBuilder(t, config, "test")
|
|
|
|
core := TestCore(t, config)
|
|
|
|
|
|
|
|
b.ArtifactId = "hello"
|
|
|
|
|
|
|
|
build, err := core.Build("test")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := build.Prepare(); err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
2019-03-22 09:53:28 -04:00
|
|
|
artifact, err := build.Run(context.Background(), nil)
|
2015-05-25 20:58:59 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if len(artifact) != 1 {
|
|
|
|
t.Fatalf("bad: %#v", artifact)
|
|
|
|
}
|
|
|
|
|
|
|
|
if artifact[0].Id() != b.ArtifactId {
|
|
|
|
t.Fatalf("bad: %s", artifact[0].Id())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-25 21:15:07 -04:00
|
|
|
func TestCoreBuild_basicInterpolated(t *testing.T) {
|
|
|
|
config := TestCoreConfig(t)
|
|
|
|
testCoreTemplate(t, config, fixtureDir("build-basic-interpolated.json"))
|
|
|
|
b := TestBuilder(t, config, "test")
|
|
|
|
core := TestCore(t, config)
|
|
|
|
|
|
|
|
b.ArtifactId = "hello"
|
|
|
|
|
|
|
|
build, err := core.Build("NAME")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := build.Prepare(); err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
2019-03-22 09:53:28 -04:00
|
|
|
artifact, err := build.Run(context.Background(), nil)
|
2015-05-25 21:15:07 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if len(artifact) != 1 {
|
|
|
|
t.Fatalf("bad: %#v", artifact)
|
|
|
|
}
|
|
|
|
|
|
|
|
if artifact[0].Id() != b.ArtifactId {
|
|
|
|
t.Fatalf("bad: %s", artifact[0].Id())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-28 17:40:45 -04:00
|
|
|
func TestCoreBuild_env(t *testing.T) {
|
|
|
|
os.Setenv("PACKER_TEST_ENV", "test")
|
|
|
|
defer os.Setenv("PACKER_TEST_ENV", "")
|
|
|
|
|
|
|
|
config := TestCoreConfig(t)
|
|
|
|
testCoreTemplate(t, config, fixtureDir("build-env.json"))
|
|
|
|
b := TestBuilder(t, config, "test")
|
|
|
|
core := TestCore(t, config)
|
|
|
|
|
|
|
|
b.ArtifactId = "hello"
|
|
|
|
|
|
|
|
build, err := core.Build("test")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := build.Prepare(); err != nil {
|
2015-06-13 16:51:29 -04:00
|
|
|
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"] != "test" {
|
|
|
|
t.Fatalf("bad: %#v", result)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-27 13:10:16 -05:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-13 16:51:29 -04:00
|
|
|
func TestCoreBuild_buildNameVar(t *testing.T) {
|
|
|
|
config := TestCoreConfig(t)
|
|
|
|
testCoreTemplate(t, config, fixtureDir("build-var-build-name.json"))
|
|
|
|
b := TestBuilder(t, config, "test")
|
|
|
|
core := TestCore(t, config)
|
|
|
|
|
|
|
|
b.ArtifactId = "hello"
|
|
|
|
|
|
|
|
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"] != "test" {
|
|
|
|
t.Fatalf("bad: %#v", result)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCoreBuild_buildTypeVar(t *testing.T) {
|
|
|
|
config := TestCoreConfig(t)
|
|
|
|
testCoreTemplate(t, config, fixtureDir("build-var-build-type.json"))
|
|
|
|
b := TestBuilder(t, config, "test")
|
|
|
|
core := TestCore(t, config)
|
|
|
|
|
|
|
|
b.ArtifactId = "hello"
|
|
|
|
|
|
|
|
build, err := core.Build("test")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := build.Prepare(); err != nil {
|
2015-05-28 17:40:45 -04:00
|
|
|
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"] != "test" {
|
|
|
|
t.Fatalf("bad: %#v", result)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-25 21:15:07 -04:00
|
|
|
func TestCoreBuild_nonExist(t *testing.T) {
|
|
|
|
config := TestCoreConfig(t)
|
|
|
|
testCoreTemplate(t, config, fixtureDir("build-basic.json"))
|
|
|
|
TestBuilder(t, config, "test")
|
|
|
|
core := TestCore(t, config)
|
|
|
|
|
|
|
|
_, err := core.Build("nope")
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("should error")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-26 12:14:29 -04:00
|
|
|
func TestCoreBuild_prov(t *testing.T) {
|
|
|
|
config := TestCoreConfig(t)
|
|
|
|
testCoreTemplate(t, config, fixtureDir("build-prov.json"))
|
|
|
|
b := TestBuilder(t, config, "test")
|
|
|
|
p := TestProvisioner(t, config, "test")
|
|
|
|
core := TestCore(t, config)
|
|
|
|
|
|
|
|
b.ArtifactId = "hello"
|
|
|
|
|
|
|
|
build, err := core.Build("test")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := build.Prepare(); err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
2019-03-22 09:53:28 -04:00
|
|
|
artifact, err := build.Run(context.Background(), nil)
|
2015-05-26 12:14:29 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if len(artifact) != 1 {
|
|
|
|
t.Fatalf("bad: %#v", artifact)
|
|
|
|
}
|
|
|
|
|
|
|
|
if artifact[0].Id() != b.ArtifactId {
|
|
|
|
t.Fatalf("bad: %s", artifact[0].Id())
|
|
|
|
}
|
|
|
|
if !p.ProvCalled {
|
|
|
|
t.Fatal("provisioner not called")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-26 12:16:39 -04:00
|
|
|
func TestCoreBuild_provSkip(t *testing.T) {
|
|
|
|
config := TestCoreConfig(t)
|
|
|
|
testCoreTemplate(t, config, fixtureDir("build-prov-skip.json"))
|
|
|
|
b := TestBuilder(t, config, "test")
|
|
|
|
p := TestProvisioner(t, config, "test")
|
|
|
|
core := TestCore(t, config)
|
|
|
|
|
|
|
|
b.ArtifactId = "hello"
|
|
|
|
|
|
|
|
build, err := core.Build("test")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := build.Prepare(); err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
2019-03-22 09:53:28 -04:00
|
|
|
artifact, err := build.Run(context.Background(), nil)
|
2015-05-26 12:16:39 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if len(artifact) != 1 {
|
|
|
|
t.Fatalf("bad: %#v", artifact)
|
|
|
|
}
|
|
|
|
|
|
|
|
if artifact[0].Id() != b.ArtifactId {
|
|
|
|
t.Fatalf("bad: %s", artifact[0].Id())
|
|
|
|
}
|
|
|
|
if p.ProvCalled {
|
|
|
|
t.Fatal("provisioner should not be called")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCoreBuild_provSkipInclude(t *testing.T) {
|
|
|
|
config := TestCoreConfig(t)
|
|
|
|
testCoreTemplate(t, config, fixtureDir("build-prov-skip-include.json"))
|
|
|
|
b := TestBuilder(t, config, "test")
|
|
|
|
p := TestProvisioner(t, config, "test")
|
|
|
|
core := TestCore(t, config)
|
|
|
|
|
|
|
|
b.ArtifactId = "hello"
|
|
|
|
|
|
|
|
build, err := core.Build("test")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := build.Prepare(); err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
2019-03-22 09:53:28 -04:00
|
|
|
artifact, err := build.Run(context.Background(), nil)
|
2015-05-26 12:16:39 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if len(artifact) != 1 {
|
|
|
|
t.Fatalf("bad: %#v", artifact)
|
|
|
|
}
|
|
|
|
|
|
|
|
if artifact[0].Id() != b.ArtifactId {
|
|
|
|
t.Fatalf("bad: %s", artifact[0].Id())
|
|
|
|
}
|
|
|
|
if !p.ProvCalled {
|
|
|
|
t.Fatal("provisioner should be called")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-26 12:46:04 -04:00
|
|
|
func TestCoreBuild_provOverride(t *testing.T) {
|
|
|
|
config := TestCoreConfig(t)
|
|
|
|
testCoreTemplate(t, config, fixtureDir("build-prov-override.json"))
|
|
|
|
b := TestBuilder(t, config, "test")
|
|
|
|
p := TestProvisioner(t, config, "test")
|
|
|
|
core := TestCore(t, config)
|
|
|
|
|
|
|
|
b.ArtifactId = "hello"
|
|
|
|
|
|
|
|
build, err := core.Build("test")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := build.Prepare(); err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
2019-03-22 09:53:28 -04:00
|
|
|
artifact, err := build.Run(context.Background(), nil)
|
2015-05-26 12:46:04 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if len(artifact) != 1 {
|
|
|
|
t.Fatalf("bad: %#v", artifact)
|
|
|
|
}
|
|
|
|
|
|
|
|
if artifact[0].Id() != b.ArtifactId {
|
|
|
|
t.Fatalf("bad: %s", artifact[0].Id())
|
|
|
|
}
|
|
|
|
if !p.ProvCalled {
|
|
|
|
t.Fatal("provisioner not called")
|
|
|
|
}
|
|
|
|
|
|
|
|
found := false
|
|
|
|
for _, raw := range p.PrepConfigs {
|
|
|
|
if m, ok := raw.(map[string]interface{}); ok {
|
|
|
|
if _, ok := m["foo"]; ok {
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
t.Fatal("override not called")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-26 12:28:59 -04:00
|
|
|
func TestCoreBuild_postProcess(t *testing.T) {
|
|
|
|
config := TestCoreConfig(t)
|
|
|
|
testCoreTemplate(t, config, fixtureDir("build-pp.json"))
|
|
|
|
b := TestBuilder(t, config, "test")
|
|
|
|
p := TestPostProcessor(t, config, "test")
|
|
|
|
core := TestCore(t, config)
|
|
|
|
ui := TestUi(t)
|
|
|
|
|
|
|
|
b.ArtifactId = "hello"
|
|
|
|
p.ArtifactId = "goodbye"
|
|
|
|
|
|
|
|
build, err := core.Build("test")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := build.Prepare(); err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
2019-03-22 09:53:28 -04:00
|
|
|
artifact, err := build.Run(context.Background(), ui)
|
2015-05-26 12:28:59 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if len(artifact) != 1 {
|
|
|
|
t.Fatalf("bad: %#v", artifact)
|
|
|
|
}
|
|
|
|
|
|
|
|
if artifact[0].Id() != p.ArtifactId {
|
|
|
|
t.Fatalf("bad: %s", artifact[0].Id())
|
|
|
|
}
|
|
|
|
if p.PostProcessArtifact.Id() != b.ArtifactId {
|
|
|
|
t.Fatalf("bad: %s", p.PostProcessArtifact.Id())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-29 17:29:32 -04:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-23 17:48:07 -04:00
|
|
|
func TestCoreValidate(t *testing.T) {
|
|
|
|
cases := []struct {
|
|
|
|
File string
|
|
|
|
Vars map[string]string
|
|
|
|
Err bool
|
|
|
|
}{
|
2020-03-11 13:49:45 -04:00
|
|
|
{"validate-dup-builder.json", nil, true},
|
2015-05-23 17:48:07 -04:00
|
|
|
|
|
|
|
// Required variable not set
|
2020-03-11 13:49:45 -04:00
|
|
|
{"validate-req-variable.json", nil, true},
|
|
|
|
{"validate-req-variable.json", map[string]string{"foo": "bar"}, false},
|
2015-06-29 14:49:45 -04:00
|
|
|
|
|
|
|
// Min version good
|
2020-03-11 13:49:45 -04:00
|
|
|
{"validate-min-version.json", map[string]string{"foo": "bar"}, false},
|
|
|
|
{"validate-min-version-high.json", map[string]string{"foo": "bar"}, true},
|
2015-05-23 17:48:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range cases {
|
|
|
|
f, err := os.Open(fixtureDir(tc.File))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
tpl, err := template.Parse(f)
|
|
|
|
f.Close()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s\n\n%s", tc.File, err)
|
|
|
|
}
|
|
|
|
|
2020-07-24 04:58:03 -04:00
|
|
|
core := NewCore(&CoreConfig{
|
2015-05-23 17:48:07 -04:00
|
|
|
Template: tpl,
|
|
|
|
Variables: tc.Vars,
|
2015-06-29 14:49:45 -04:00
|
|
|
Version: "1.0.0",
|
2015-05-23 17:48:07 -04:00
|
|
|
})
|
2020-07-24 04:58:03 -04:00
|
|
|
err = core.Initialize()
|
2018-08-20 19:32:47 -04:00
|
|
|
|
2015-05-28 17:42:53 -04:00
|
|
|
if (err != nil) != tc.Err {
|
2015-05-23 17:48:07 -04:00
|
|
|
t.Fatalf("err: %s\n\n%s", tc.File, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-05-25 20:29:10 -04:00
|
|
|
|
2019-06-07 18:56:20 -04:00
|
|
|
// Tests that we can properly interpolate user variables defined within the
|
|
|
|
// packer template
|
2019-03-08 17:49:47 -05:00
|
|
|
func TestCore_InterpolateUserVars(t *testing.T) {
|
|
|
|
cases := []struct {
|
|
|
|
File string
|
|
|
|
Expected map[string]string
|
|
|
|
Err bool
|
|
|
|
}{
|
|
|
|
{
|
2019-06-07 18:56:20 -04:00
|
|
|
"build-variables-interpolate.json",
|
2019-03-08 17:49:47 -05:00
|
|
|
map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
"bar": "bar",
|
|
|
|
"baz": "barbaz",
|
|
|
|
"bang": "bangbarbaz",
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
2019-06-07 18:56:20 -04:00
|
|
|
"build-variables-interpolate2.json",
|
2019-03-08 17:49:47 -05:00
|
|
|
map[string]string{},
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
|
|
f, err := os.Open(fixtureDir(tc.File))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
tpl, err := template.Parse(f)
|
|
|
|
f.Close()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s\n\n%s", tc.File, err)
|
|
|
|
}
|
|
|
|
|
2020-07-24 04:58:03 -04:00
|
|
|
ccf := NewCore(&CoreConfig{
|
2019-03-08 17:49:47 -05:00
|
|
|
Template: tpl,
|
|
|
|
Version: "1.0.0",
|
|
|
|
})
|
2020-07-24 04:58:03 -04:00
|
|
|
err = ccf.Initialize()
|
2019-03-08 17:49:47 -05:00
|
|
|
|
|
|
|
if (err != nil) != tc.Err {
|
2020-03-12 16:40:56 -04:00
|
|
|
if tc.Err == false {
|
|
|
|
t.Fatalf("Error interpolating %s: Expected no error, but got: %s", tc.File, err)
|
|
|
|
} else {
|
|
|
|
t.Fatalf("Error interpolating %s: Expected an error, but got: %s", tc.File, err)
|
|
|
|
}
|
|
|
|
|
2019-03-08 17:49:47 -05:00
|
|
|
}
|
|
|
|
if !tc.Err {
|
|
|
|
for k, v := range ccf.variables {
|
|
|
|
if tc.Expected[k] != v {
|
|
|
|
t.Fatalf("Expected %s but got %s", tc.Expected[k], v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-07 18:56:20 -04:00
|
|
|
// Tests that we can properly interpolate user variables defined within a
|
|
|
|
// var-file provided alongside the Packer template
|
|
|
|
func TestCore_InterpolateUserVars_VarFile(t *testing.T) {
|
|
|
|
cases := []struct {
|
|
|
|
File string
|
|
|
|
Variables map[string]string
|
|
|
|
Expected map[string]string
|
|
|
|
Err bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
// tests that we can interpolate from var files when var isn't set in
|
|
|
|
// originating template
|
|
|
|
"build-basic-interpolated.json",
|
|
|
|
map[string]string{
|
|
|
|
"name": "gotta-{{user `my_var`}}",
|
|
|
|
"my_var": "interpolate-em-all",
|
|
|
|
},
|
|
|
|
map[string]string{
|
|
|
|
"name": "gotta-interpolate-em-all",
|
|
|
|
"my_var": "interpolate-em-all"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// tests that we can interpolate from var files when var is set in
|
|
|
|
// originating template as required
|
|
|
|
"build-basic-interpolated-required.json",
|
|
|
|
map[string]string{
|
|
|
|
"name": "gotta-{{user `my_var`}}",
|
|
|
|
"my_var": "interpolate-em-all",
|
|
|
|
},
|
|
|
|
map[string]string{
|
|
|
|
"name": "gotta-interpolate-em-all",
|
|
|
|
"my_var": "interpolate-em-all"},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
|
|
f, err := os.Open(fixtureDir(tc.File))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
tpl, err := template.Parse(f)
|
|
|
|
f.Close()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s\n\n%s", tc.File, err)
|
|
|
|
}
|
|
|
|
|
2020-07-24 04:58:03 -04:00
|
|
|
ccf := NewCore(&CoreConfig{
|
2019-06-07 18:56:20 -04:00
|
|
|
Template: tpl,
|
|
|
|
Version: "1.0.0",
|
|
|
|
Variables: tc.Variables,
|
|
|
|
})
|
2020-07-24 04:58:03 -04:00
|
|
|
err = ccf.Initialize()
|
2019-06-07 18:56:20 -04:00
|
|
|
|
|
|
|
if (err != nil) != tc.Err {
|
|
|
|
t.Fatalf("err: %s\n\n%s", tc.File, err)
|
|
|
|
}
|
|
|
|
if !tc.Err {
|
|
|
|
for k, v := range ccf.variables {
|
|
|
|
if tc.Expected[k] != v {
|
|
|
|
t.Fatalf("Expected value %s for key %s but got %s",
|
|
|
|
tc.Expected[k], k, v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-20 19:32:47 -04:00
|
|
|
func TestSensitiveVars(t *testing.T) {
|
|
|
|
cases := []struct {
|
|
|
|
File string
|
|
|
|
Vars map[string]string
|
|
|
|
SensitiveVars []string
|
|
|
|
Expected string
|
|
|
|
Err bool
|
|
|
|
}{
|
|
|
|
// hardcoded
|
|
|
|
{
|
|
|
|
"sensitive-variables.json",
|
2020-11-20 13:21:29 -05:00
|
|
|
map[string]string{"foo": "bar_extra_sensitive_probably_a_password"},
|
2018-08-20 19:32:47 -04:00
|
|
|
[]string{"foo"},
|
2020-11-20 13:21:29 -05:00
|
|
|
"the foo jumped over the <sensitive>",
|
2018-08-20 19:32:47 -04:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
// interpolated
|
|
|
|
{
|
|
|
|
"sensitive-variables.json",
|
2020-11-20 13:21:29 -05:00
|
|
|
map[string]string{"foo": "bar_extra_sensitive_probably_a_password",
|
2019-06-07 18:56:20 -04:00
|
|
|
"bang": "{{ user `foo`}}"},
|
|
|
|
[]string{"bang"},
|
2020-11-20 13:21:29 -05:00
|
|
|
"the foo jumped over the <sensitive>",
|
2018-08-20 19:32:47 -04:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range cases {
|
|
|
|
f, err := os.Open(fixtureDir(tc.File))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
tpl, err := template.Parse(f)
|
|
|
|
f.Close()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s\n\n%s", tc.File, err)
|
|
|
|
}
|
|
|
|
|
2020-07-24 04:58:03 -04:00
|
|
|
ccf := NewCore(&CoreConfig{
|
2018-08-20 19:32:47 -04:00
|
|
|
Template: tpl,
|
|
|
|
Variables: tc.Vars,
|
|
|
|
Version: "1.0.0",
|
|
|
|
})
|
2020-07-24 04:58:03 -04:00
|
|
|
err = ccf.Initialize()
|
2018-08-20 19:32:47 -04:00
|
|
|
|
|
|
|
if (err != nil) != tc.Err {
|
|
|
|
t.Fatalf("err: %s\n\n%s", tc.File, err)
|
|
|
|
}
|
2020-11-20 13:21:29 -05:00
|
|
|
// Check that filter correctly manipulates strings:
|
|
|
|
filtered := packersdk.LogSecretFilter.FilterString("the foo jumped over the bar_extra_sensitive_probably_a_password")
|
|
|
|
if filtered != tc.Expected {
|
2018-08-20 19:32:47 -04:00
|
|
|
t.Fatalf("not filtering sensitive vars; filtered is %#v", filtered)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-11 13:49:45 -04:00
|
|
|
// Normally I wouldn't test a little helper function, but it's regex.
|
2020-03-12 13:00:56 -04:00
|
|
|
func TestIsDoneInterpolating(t *testing.T) {
|
2020-03-11 13:49:45 -04:00
|
|
|
cases := []struct {
|
|
|
|
inputString string
|
|
|
|
expectedBool bool
|
|
|
|
expectedErr bool
|
|
|
|
}{
|
|
|
|
// Many of these tests are just exercising the regex to make sure it
|
|
|
|
// doesnt get confused by different kinds of whitespace
|
|
|
|
{"charmander-{{ user `spacesaroundticks` }}", false, false},
|
|
|
|
{"pidgey-{{ user `partyparrot`}}", false, false},
|
|
|
|
{"jigglypuff-{{ user`notickspaaces`}}", false, false},
|
|
|
|
{"eevee-{{user`nospaces`}}", false, false},
|
|
|
|
{"staryu-{{ user `somanyspaces` }}", false, false},
|
|
|
|
{"{{ user `somanyspaces` }}-{{isotime}}", false, false},
|
|
|
|
// Make sure that we only flag on "user" when it's in the right set of
|
|
|
|
// brackets, in a properly declared template engine format
|
|
|
|
{"missingno-{{ user `missingbracket` }", true, false},
|
|
|
|
{"missing2-{user ``missingopenbrackets }}", true, false},
|
|
|
|
{"wat-userjustinname", true, false},
|
|
|
|
// Any functions that aren't "user" should have already been properly
|
|
|
|
// interpolated by the time this is called, so these cases aren't
|
|
|
|
// realistic. That said, this makes it clear that this function doesn't
|
|
|
|
// care about anything but the user function
|
|
|
|
{"pokemon-{{ isotime }}", true, false},
|
|
|
|
{"squirtle-{{ env `water`}}", true, false},
|
|
|
|
{"bulbasaur-notinterpolated", true, false},
|
|
|
|
{"extra-{{thisfunc `user`}}", true, false},
|
|
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
|
|
done, err := isDoneInterpolating(tc.inputString)
|
|
|
|
if (err != nil) != tc.expectedErr {
|
|
|
|
t.Fatalf("Test case failed. Error: %s expected error: "+
|
|
|
|
"%t test string: %s", err, tc.expectedErr, tc.inputString)
|
|
|
|
}
|
|
|
|
if done != tc.expectedBool {
|
|
|
|
t.Fatalf("Test case failed. inputString: %s. "+
|
|
|
|
"Expected done = %t but got done = %t", tc.inputString,
|
|
|
|
tc.expectedBool, done)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-11 15:48:35 -04:00
|
|
|
func TestEnvAndFileVars(t *testing.T) {
|
|
|
|
os.Setenv("INTERPOLATE_TEST_ENV_1", "bulbasaur")
|
|
|
|
os.Setenv("INTERPOLATE_TEST_ENV_3", "/path/to/nowhere")
|
|
|
|
os.Setenv("INTERPOLATE_TEST_ENV_2", "5")
|
|
|
|
os.Setenv("INTERPOLATE_TEST_ENV_4", "bananas")
|
|
|
|
|
2020-03-12 16:40:56 -04:00
|
|
|
f, err := os.Open(fixtureDir("complex-recursed-env-user-var-file.json"))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
2020-03-11 15:48:35 -04:00
|
|
|
|
2020-03-12 16:40:56 -04:00
|
|
|
tpl, err := template.Parse(f)
|
|
|
|
f.Close()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s\n\n%s", "complex-recursed-env-user-var-file.json", err)
|
|
|
|
}
|
2020-03-11 15:48:35 -04:00
|
|
|
|
2020-07-24 04:58:03 -04:00
|
|
|
ccf := NewCore(&CoreConfig{
|
2020-03-12 16:40:56 -04:00
|
|
|
Template: tpl,
|
|
|
|
Version: "1.0.0",
|
|
|
|
Variables: map[string]string{
|
2020-03-11 15:48:35 -04:00
|
|
|
"var_1": "partyparrot",
|
2020-03-12 16:40:56 -04:00
|
|
|
"var_2": "{{user `env_1`}}-{{user `env_2`}}{{user `env_3`}}-{{user `var_1`}}",
|
|
|
|
"final_var": "{{user `env_1`}}/{{user `env_2`}}/{{user `env_4`}}{{user `env_3`}}-{{user `var_1`}}/vmware/{{user `var_2`}}.vmx",
|
|
|
|
},
|
|
|
|
})
|
2020-07-24 04:58:03 -04:00
|
|
|
err = ccf.Initialize()
|
|
|
|
|
2020-03-12 16:40:56 -04:00
|
|
|
expected := map[string]string{
|
|
|
|
"var_1": "partyparrot",
|
|
|
|
"var_2": "bulbasaur-5/path/to/nowhere-partyparrot",
|
|
|
|
"final_var": "bulbasaur/5/bananas/path/to/nowhere-partyparrot/vmware/bulbasaur-5/path/to/nowhere-partyparrot.vmx",
|
|
|
|
"env_1": "bulbasaur",
|
|
|
|
"env_2": "5",
|
|
|
|
"env_3": "/path/to/nowhere",
|
|
|
|
"env_4": "bananas",
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s\n\n%s", "complex-recursed-env-user-var-file.json", err)
|
|
|
|
}
|
|
|
|
for k, v := range ccf.variables {
|
|
|
|
if expected[k] != v {
|
|
|
|
t.Fatalf("Expected value %s for key %s but got %s",
|
|
|
|
expected[k], k, v)
|
2020-03-11 15:48:35 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clean up env vars
|
|
|
|
os.Unsetenv("INTERPOLATE_TEST_ENV_1")
|
|
|
|
os.Unsetenv("INTERPOLATE_TEST_ENV_3")
|
|
|
|
os.Unsetenv("INTERPOLATE_TEST_ENV_2")
|
|
|
|
os.Unsetenv("INTERPOLATE_TEST_ENV_4")
|
|
|
|
}
|
2020-03-11 13:49:45 -04:00
|
|
|
|
2015-05-25 20:58:59 -04:00
|
|
|
func testCoreTemplate(t *testing.T, c *CoreConfig, p string) {
|
|
|
|
tpl, err := template.ParseFile(p)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s\n\n%s", p, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Template = tpl
|
|
|
|
}
|
2020-04-16 05:58:54 -04:00
|
|
|
|
|
|
|
func TestCoreBuild_provRetry(t *testing.T) {
|
|
|
|
config := TestCoreConfig(t)
|
|
|
|
testCoreTemplate(t, config, fixtureDir("build-prov-retry.json"))
|
|
|
|
b := TestBuilder(t, config, "test")
|
2020-12-09 06:39:54 -05:00
|
|
|
pString := new(packersdk.MockProvisioner)
|
|
|
|
pInt := new(packersdk.MockProvisioner)
|
2021-01-13 06:14:06 -05:00
|
|
|
config.Components.ProvisionerStore = MapOfProvisioner{
|
2020-12-01 18:02:15 -05:00
|
|
|
"test-string": func() (packersdk.Provisioner, error) { return pString, nil },
|
2020-08-05 11:41:20 -04:00
|
|
|
// backwards compatibility
|
2020-12-01 18:02:15 -05:00
|
|
|
"test-integer": func() (packersdk.Provisioner, error) { return pInt, nil },
|
2020-08-05 11:41:20 -04:00
|
|
|
}
|
2020-04-16 05:58:54 -04:00
|
|
|
core := TestCore(t, config)
|
|
|
|
|
|
|
|
b.ArtifactId = "hello"
|
|
|
|
|
|
|
|
build, err := core.Build("test")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := build.Prepare(); err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ui := testUi()
|
2020-08-05 11:41:20 -04:00
|
|
|
pInt.ProvFunc = func(ctx context.Context) error {
|
|
|
|
return errors.New("failed")
|
|
|
|
}
|
|
|
|
pString.ProvFunc = func(ctx context.Context) error {
|
2020-04-16 05:58:54 -04:00
|
|
|
return errors.New("failed")
|
|
|
|
}
|
|
|
|
|
|
|
|
artifact, err := build.Run(context.Background(), ui)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if len(artifact) != 1 {
|
|
|
|
t.Fatalf("bad: %#v", artifact)
|
|
|
|
}
|
|
|
|
|
|
|
|
if artifact[0].Id() != b.ArtifactId {
|
|
|
|
t.Fatalf("bad: %s", artifact[0].Id())
|
|
|
|
}
|
2020-08-05 11:41:20 -04:00
|
|
|
if !pString.ProvRetried {
|
|
|
|
t.Fatal("provisioner should retry for max_retries string value")
|
|
|
|
}
|
|
|
|
// backwards compatibility
|
|
|
|
if !pInt.ProvRetried {
|
|
|
|
t.Fatal("provisioner should retry for max_retries integer value")
|
2020-04-16 05:58:54 -04:00
|
|
|
}
|
|
|
|
}
|