diff --git a/packer_test/local_eval_test.go b/packer_test/core_tests/local_eval_test.go similarity index 58% rename from packer_test/local_eval_test.go rename to packer_test/core_tests/local_eval_test.go index dec5b1fdb49..dd450d75095 100644 --- a/packer_test/local_eval_test.go +++ b/packer_test/core_tests/local_eval_test.go @@ -1,8 +1,12 @@ -package packer_test +package core_test -import "fmt" +import ( + "fmt" -func (ts *PackerTestSuite) TestEvalLocalsOrder() { + "github.com/hashicorp/packer/packer_test/lib" +) + +func (ts *PackerCoreTestSuite) TestEvalLocalsOrder() { ts.SkipNoAcc() pluginDir, cleanup := ts.MakePluginDir() @@ -12,10 +16,11 @@ func (ts *PackerTestSuite) TestEvalLocalsOrder() { Runs(10). Stdin("local.test_local\n"). SetArgs("console", "./templates/locals_no_order.pkr.hcl"). - Assert(MustSucceed(), Grep("\\[\\]", grepStdout, grepInvert)) + Assert(lib.MustSucceed(), + lib.Grep("\\[\\]", lib.GrepStdout, lib.GrepInvert)) } -func (ts *PackerTestSuite) TestLocalDuplicates() { +func (ts *PackerCoreTestSuite) TestLocalDuplicates() { pluginDir, cleanup := ts.MakePluginDir() defer cleanup() @@ -23,9 +28,9 @@ func (ts *PackerTestSuite) TestLocalDuplicates() { ts.Run(fmt.Sprintf("duplicate local detection with %s command - expect error", cmd), func() { ts.PackerCommand().UsePluginDir(pluginDir). SetArgs(cmd, "./templates/locals_duplicate.pkr.hcl"). - Assert(MustFail(), - Grep("Duplicate local definition"), - Grep("Local variable \"test\" is defined twice")) + Assert(lib.MustFail(), + lib.Grep("Duplicate local definition"), + lib.Grep("Local variable \"test\" is defined twice")) }) } } diff --git a/packer_test/core_tests/suite_test.go b/packer_test/core_tests/suite_test.go new file mode 100644 index 00000000000..0d2e39367f3 --- /dev/null +++ b/packer_test/core_tests/suite_test.go @@ -0,0 +1,23 @@ +package core_test + +import ( + "testing" + + "github.com/hashicorp/packer/packer_test/lib" + "github.com/stretchr/testify/suite" +) + +type PackerCoreTestSuite struct { + *lib.PackerTestSuite +} + +func Test_PackerPluginSuite(t *testing.T) { + baseSuite, cleanup := lib.PackerCoreSuite(t) + defer cleanup() + + ts := &PackerCoreTestSuite{ + baseSuite, + } + + suite.Run(t, ts) +} diff --git a/packer_test/templates/locals_duplicate.pkr.hcl b/packer_test/core_tests/templates/locals_duplicate.pkr.hcl similarity index 100% rename from packer_test/templates/locals_duplicate.pkr.hcl rename to packer_test/core_tests/templates/locals_duplicate.pkr.hcl diff --git a/packer_test/templates/locals_no_order.pkr.hcl b/packer_test/core_tests/templates/locals_no_order.pkr.hcl similarity index 100% rename from packer_test/templates/locals_no_order.pkr.hcl rename to packer_test/core_tests/templates/locals_no_order.pkr.hcl diff --git a/packer_test/base_test.go b/packer_test/lib/base.go similarity index 92% rename from packer_test/base_test.go rename to packer_test/lib/base.go index 4fe675d3158..a54c43a1c48 100644 --- a/packer_test/base_test.go +++ b/packer_test/lib/base.go @@ -1,4 +1,4 @@ -package packer_test +package lib import ( "fmt" @@ -19,7 +19,7 @@ func BuildTestPacker(t *testing.T) (string, error) { return "", fmt.Errorf("failed to compile packer binary: %s", err) } - packerCoreDir := filepath.Dir(testDir) + packerCoreDir := filepath.Dir(filepath.Dir(testDir)) outBin := filepath.Join(os.TempDir(), fmt.Sprintf("packer_core-%d", rand.Int())) if runtime.GOOS == "windows" { diff --git a/packer_test/commands_test.go b/packer_test/lib/commands.go similarity index 99% rename from packer_test/commands_test.go rename to packer_test/lib/commands.go index b8d7bc5849b..6e90bd62580 100644 --- a/packer_test/commands_test.go +++ b/packer_test/lib/commands.go @@ -1,4 +1,4 @@ -package packer_test +package lib import ( "fmt" diff --git a/packer_test/gadgets_test.go b/packer_test/lib/gadgets.go similarity index 94% rename from packer_test/gadgets_test.go rename to packer_test/lib/gadgets.go index 3ddd29e55a3..f1950b016dd 100644 --- a/packer_test/gadgets_test.go +++ b/packer_test/lib/gadgets.go @@ -1,4 +1,4 @@ -package packer_test +package lib import ( "fmt" @@ -86,21 +86,21 @@ func (_ mustFail) Check(stdout, stderr string, err error) error { return nil } -type grepOpts int +type GrepOpts int const ( // Invert the check, i.e. by default an empty grep fails, if this is set, a non-empty grep fails - grepInvert grepOpts = iota + GrepInvert GrepOpts = iota // Only grep stderr - grepStderr + GrepStderr // Only grep stdout - grepStdout + GrepStdout ) // Grep returns a checker that performs a regexp match on the command's output and returns an error if it failed // // Note: by default both streams will be checked by the grep -func Grep(expression string, opts ...grepOpts) Checker { +func Grep(expression string, opts ...GrepOpts) Checker { pc := PipeChecker{ name: fmt.Sprintf("command | grep -E %q", expression), stream: BothStreams, @@ -111,11 +111,11 @@ func Grep(expression string, opts ...grepOpts) Checker { } for _, opt := range opts { switch opt { - case grepInvert: + case GrepInvert: pc.check = ExpectEmptyInput() - case grepStderr: + case GrepStderr: pc.stream = OnlyStderr - case grepStdout: + case GrepStdout: pc.stream = OnlyStdout } } @@ -165,6 +165,6 @@ func (c CustomCheck) Name() string { // returned pipe checker. func LineCountCheck(lines int) *PipeChecker { return MkPipeCheck(fmt.Sprintf("line count (%d)", lines), LineCount()). - SetTester(IntCompare(eq, lines)). + SetTester(IntCompare(Eq, lines)). SetStream(OnlyStdout) } diff --git a/packer_test/pipe_checker_test.go b/packer_test/lib/pipe_checker.go similarity index 95% rename from packer_test/pipe_checker_test.go rename to packer_test/lib/pipe_checker.go index b3b415349b9..1279b5b9ca6 100644 --- a/packer_test/pipe_checker_test.go +++ b/packer_test/lib/pipe_checker.go @@ -1,4 +1,4 @@ -package packer_test +package lib import ( "fmt" @@ -101,30 +101,30 @@ func ExpectEmptyInput() Tester { }) } -type op int +type Op int const ( - eq op = iota - ne - gt - ge - lt - le + Eq Op = iota + Ne + Gt + Ge + Lt + Le ) -func (op op) String() string { +func (op Op) String() string { switch op { - case eq: + case Eq: return "==" - case ne: + case Ne: return "!=" - case gt: + case Gt: return ">" - case ge: + case Ge: return ">=" - case lt: + case Lt: return "<" - case le: + case Le: return "<=" } @@ -134,7 +134,7 @@ func (op op) String() string { // IntCompare reads the input from the pipeline and compares it to a value using `op` // // If the input is not an int, this fails. -func IntCompare(op op, value int) Tester { +func IntCompare(op Op, value int) Tester { return CustomTester(func(in string) error { n, err := strconv.Atoi(strings.TrimSpace(in)) if err != nil { @@ -143,17 +143,17 @@ func IntCompare(op op, value int) Tester { var result bool switch op { - case eq: + case Eq: result = n == value - case ne: + case Ne: result = n != value - case gt: + case Gt: result = n > value - case ge: + case Ge: result = n >= value - case lt: + case Lt: result = n < value - case le: + case Le: result = n <= value default: panic(fmt.Sprintf("Unsupported operator %d, make sure the operation is implemented for IntCompare", op)) diff --git a/packer_test/plugin_test.go b/packer_test/lib/plugin.go similarity index 80% rename from packer_test/plugin_test.go rename to packer_test/lib/plugin.go index a2e1b4aff24..c3a4b0fe75d 100644 --- a/packer_test/plugin_test.go +++ b/packer_test/lib/plugin.go @@ -1,11 +1,10 @@ -package packer_test +package lib import ( "crypto/sha256" "fmt" "io" "os" - "os/exec" "path/filepath" "runtime" "strings" @@ -37,25 +36,6 @@ func LoadPluginVersion(pluginVersion string) (string, bool) { return path, ok } -var tempPluginBinaryPath = struct { - path string - once sync.Once -}{} - -// PluginBinaryDir returns the path to the directory where temporary binaries will be compiled -func PluginBinaryDir() string { - tempPluginBinaryPath.once.Do(func() { - tempDir, err := os.MkdirTemp("", "packer-core-acc-test-") - if err != nil { - panic(fmt.Sprintf("failed to create temporary directory for compiled plugins: %s", err)) - } - - tempPluginBinaryPath.path = tempDir - }) - - return tempPluginBinaryPath.path -} - // LDFlags compiles the ldflags for the plugin to compile based on the information provided. func LDFlags(version *version.Version) string { pluginPackage := "github.com/hashicorp/packer-plugin-tester" @@ -104,48 +84,6 @@ func ExpectedInstalledName(versionStr string) string { runtime.GOOS, runtime.GOARCH, ext) } -// BuildSimplePlugin creates a plugin that essentially does nothing. -// -// The plugin's code is contained in a subdirectory of this, and lets us -// change the attributes of the plugin binary itself, like the SDK version, -// the plugin's version, etc. -// -// The plugin is functional, and can be used to run builds with. -// There won't be anything substantial created though, its goal is only -// to validate the core functionality of Packer. -// -// The path to the plugin is returned, it won't be removed automatically -// though, deletion is the caller's responsibility. -func BuildSimplePlugin(versionString string, t *testing.T) string { - // Only build plugin binary if not already done beforehand - path, ok := LoadPluginVersion(versionString) - if ok { - return path - } - - v := version.Must(version.NewSemver(versionString)) - - t.Logf("Building plugin in version %v", v) - - testDir, err := currentDir() - if err != nil { - t.Fatalf("failed to compile plugin binary: %s", err) - } - - testerPluginDir := filepath.Join(testDir, "plugin_tester") - outBin := filepath.Join(PluginBinaryDir(), BinaryName(v)) - - compileCommand := exec.Command("go", "build", "-C", testerPluginDir, "-o", outBin, "-ldflags", LDFlags(v), ".") - logs, err := compileCommand.CombinedOutput() - if err != nil { - t.Fatalf("failed to compile plugin binary: %s\ncompiler logs: %s", err, logs) - } - - StorePluginVersion(v.String(), outBin) - - return outBin -} - // currentDir returns the directory in which the current file is located. // // Since we're in tests it's reliable as they're supposed to run on the same @@ -171,7 +109,7 @@ func (ts *PackerTestSuite) MakePluginDir(pluginVersions ...string) (pluginTempDi t := ts.T() for _, ver := range pluginVersions { - BuildSimplePlugin(ver, t) + ts.BuildSimplePlugin(ver, t) } var err error diff --git a/packer_test/plugin_tester/LICENSE b/packer_test/lib/plugin_tester/LICENSE similarity index 100% rename from packer_test/plugin_tester/LICENSE rename to packer_test/lib/plugin_tester/LICENSE diff --git a/packer_test/plugin_tester/README.md b/packer_test/lib/plugin_tester/README.md similarity index 100% rename from packer_test/plugin_tester/README.md rename to packer_test/lib/plugin_tester/README.md diff --git a/packer_test/plugin_tester/builder/dynamic/artifact.go b/packer_test/lib/plugin_tester/builder/dynamic/artifact.go similarity index 100% rename from packer_test/plugin_tester/builder/dynamic/artifact.go rename to packer_test/lib/plugin_tester/builder/dynamic/artifact.go diff --git a/packer_test/plugin_tester/builder/dynamic/builder.go b/packer_test/lib/plugin_tester/builder/dynamic/builder.go similarity index 100% rename from packer_test/plugin_tester/builder/dynamic/builder.go rename to packer_test/lib/plugin_tester/builder/dynamic/builder.go diff --git a/packer_test/plugin_tester/builder/dynamic/builder.hcl2spec.go b/packer_test/lib/plugin_tester/builder/dynamic/builder.hcl2spec.go similarity index 100% rename from packer_test/plugin_tester/builder/dynamic/builder.hcl2spec.go rename to packer_test/lib/plugin_tester/builder/dynamic/builder.hcl2spec.go diff --git a/packer_test/plugin_tester/builder/dynamic/builder_acc_test.go b/packer_test/lib/plugin_tester/builder/dynamic/builder_acc_test.go similarity index 100% rename from packer_test/plugin_tester/builder/dynamic/builder_acc_test.go rename to packer_test/lib/plugin_tester/builder/dynamic/builder_acc_test.go diff --git a/packer_test/plugin_tester/builder/dynamic/step_say_config.go b/packer_test/lib/plugin_tester/builder/dynamic/step_say_config.go similarity index 100% rename from packer_test/plugin_tester/builder/dynamic/step_say_config.go rename to packer_test/lib/plugin_tester/builder/dynamic/step_say_config.go diff --git a/packer_test/plugin_tester/builder/dynamic/test-fixtures/template.pkr.hcl b/packer_test/lib/plugin_tester/builder/dynamic/test-fixtures/template.pkr.hcl similarity index 100% rename from packer_test/plugin_tester/builder/dynamic/test-fixtures/template.pkr.hcl rename to packer_test/lib/plugin_tester/builder/dynamic/test-fixtures/template.pkr.hcl diff --git a/packer_test/plugin_tester/datasource/dynamic/data.go b/packer_test/lib/plugin_tester/datasource/dynamic/data.go similarity index 100% rename from packer_test/plugin_tester/datasource/dynamic/data.go rename to packer_test/lib/plugin_tester/datasource/dynamic/data.go diff --git a/packer_test/plugin_tester/datasource/dynamic/data.hcl2spec.go b/packer_test/lib/plugin_tester/datasource/dynamic/data.hcl2spec.go similarity index 100% rename from packer_test/plugin_tester/datasource/dynamic/data.hcl2spec.go rename to packer_test/lib/plugin_tester/datasource/dynamic/data.hcl2spec.go diff --git a/packer_test/plugin_tester/datasource/dynamic/data_acc_test.go b/packer_test/lib/plugin_tester/datasource/dynamic/data_acc_test.go similarity index 100% rename from packer_test/plugin_tester/datasource/dynamic/data_acc_test.go rename to packer_test/lib/plugin_tester/datasource/dynamic/data_acc_test.go diff --git a/packer_test/plugin_tester/datasource/dynamic/test-fixtures/template.pkr.hcl b/packer_test/lib/plugin_tester/datasource/dynamic/test-fixtures/template.pkr.hcl similarity index 100% rename from packer_test/plugin_tester/datasource/dynamic/test-fixtures/template.pkr.hcl rename to packer_test/lib/plugin_tester/datasource/dynamic/test-fixtures/template.pkr.hcl diff --git a/packer_test/plugin_tester/datasource/parrot/data.go b/packer_test/lib/plugin_tester/datasource/parrot/data.go similarity index 100% rename from packer_test/plugin_tester/datasource/parrot/data.go rename to packer_test/lib/plugin_tester/datasource/parrot/data.go diff --git a/packer_test/plugin_tester/datasource/parrot/data.hcl2spec.go b/packer_test/lib/plugin_tester/datasource/parrot/data.hcl2spec.go similarity index 100% rename from packer_test/plugin_tester/datasource/parrot/data.hcl2spec.go rename to packer_test/lib/plugin_tester/datasource/parrot/data.hcl2spec.go diff --git a/packer_test/plugin_tester/datasource/sleeper/data.go b/packer_test/lib/plugin_tester/datasource/sleeper/data.go similarity index 100% rename from packer_test/plugin_tester/datasource/sleeper/data.go rename to packer_test/lib/plugin_tester/datasource/sleeper/data.go diff --git a/packer_test/plugin_tester/datasource/sleeper/data.hcl2spec.go b/packer_test/lib/plugin_tester/datasource/sleeper/data.hcl2spec.go similarity index 100% rename from packer_test/plugin_tester/datasource/sleeper/data.hcl2spec.go rename to packer_test/lib/plugin_tester/datasource/sleeper/data.hcl2spec.go diff --git a/packer_test/plugin_tester/docs/README.md b/packer_test/lib/plugin_tester/docs/README.md similarity index 100% rename from packer_test/plugin_tester/docs/README.md rename to packer_test/lib/plugin_tester/docs/README.md diff --git a/packer_test/plugin_tester/docs/builders/builder-name.mdx b/packer_test/lib/plugin_tester/docs/builders/builder-name.mdx similarity index 100% rename from packer_test/plugin_tester/docs/builders/builder-name.mdx rename to packer_test/lib/plugin_tester/docs/builders/builder-name.mdx diff --git a/packer_test/plugin_tester/docs/datasources/datasource-name.mdx b/packer_test/lib/plugin_tester/docs/datasources/datasource-name.mdx similarity index 100% rename from packer_test/plugin_tester/docs/datasources/datasource-name.mdx rename to packer_test/lib/plugin_tester/docs/datasources/datasource-name.mdx diff --git a/packer_test/plugin_tester/docs/post-processors/postprocessor-name.mdx b/packer_test/lib/plugin_tester/docs/post-processors/postprocessor-name.mdx similarity index 100% rename from packer_test/plugin_tester/docs/post-processors/postprocessor-name.mdx rename to packer_test/lib/plugin_tester/docs/post-processors/postprocessor-name.mdx diff --git a/packer_test/plugin_tester/docs/provisioners/provisioner-name.mdx b/packer_test/lib/plugin_tester/docs/provisioners/provisioner-name.mdx similarity index 100% rename from packer_test/plugin_tester/docs/provisioners/provisioner-name.mdx rename to packer_test/lib/plugin_tester/docs/provisioners/provisioner-name.mdx diff --git a/packer_test/plugin_tester/example/README.md b/packer_test/lib/plugin_tester/example/README.md similarity index 100% rename from packer_test/plugin_tester/example/README.md rename to packer_test/lib/plugin_tester/example/README.md diff --git a/packer_test/plugin_tester/example/build.pkr.hcl b/packer_test/lib/plugin_tester/example/build.pkr.hcl similarity index 100% rename from packer_test/plugin_tester/example/build.pkr.hcl rename to packer_test/lib/plugin_tester/example/build.pkr.hcl diff --git a/packer_test/plugin_tester/example/data.pkr.hcl b/packer_test/lib/plugin_tester/example/data.pkr.hcl similarity index 100% rename from packer_test/plugin_tester/example/data.pkr.hcl rename to packer_test/lib/plugin_tester/example/data.pkr.hcl diff --git a/packer_test/plugin_tester/example/variables.pkr.hcl b/packer_test/lib/plugin_tester/example/variables.pkr.hcl similarity index 100% rename from packer_test/plugin_tester/example/variables.pkr.hcl rename to packer_test/lib/plugin_tester/example/variables.pkr.hcl diff --git a/packer_test/plugin_tester/go.mod b/packer_test/lib/plugin_tester/go.mod similarity index 100% rename from packer_test/plugin_tester/go.mod rename to packer_test/lib/plugin_tester/go.mod diff --git a/packer_test/plugin_tester/go.sum b/packer_test/lib/plugin_tester/go.sum similarity index 100% rename from packer_test/plugin_tester/go.sum rename to packer_test/lib/plugin_tester/go.sum diff --git a/packer_test/plugin_tester/main.go b/packer_test/lib/plugin_tester/main.go similarity index 100% rename from packer_test/plugin_tester/main.go rename to packer_test/lib/plugin_tester/main.go diff --git a/packer_test/plugin_tester/post-processor/dynamic/post-processor.go b/packer_test/lib/plugin_tester/post-processor/dynamic/post-processor.go similarity index 100% rename from packer_test/plugin_tester/post-processor/dynamic/post-processor.go rename to packer_test/lib/plugin_tester/post-processor/dynamic/post-processor.go diff --git a/packer_test/plugin_tester/post-processor/dynamic/post-processor.hcl2spec.go b/packer_test/lib/plugin_tester/post-processor/dynamic/post-processor.hcl2spec.go similarity index 100% rename from packer_test/plugin_tester/post-processor/dynamic/post-processor.hcl2spec.go rename to packer_test/lib/plugin_tester/post-processor/dynamic/post-processor.hcl2spec.go diff --git a/packer_test/plugin_tester/post-processor/dynamic/post-processor_acc_test.go b/packer_test/lib/plugin_tester/post-processor/dynamic/post-processor_acc_test.go similarity index 100% rename from packer_test/plugin_tester/post-processor/dynamic/post-processor_acc_test.go rename to packer_test/lib/plugin_tester/post-processor/dynamic/post-processor_acc_test.go diff --git a/packer_test/plugin_tester/post-processor/dynamic/test-fixtures/template.pkr.hcl b/packer_test/lib/plugin_tester/post-processor/dynamic/test-fixtures/template.pkr.hcl similarity index 100% rename from packer_test/plugin_tester/post-processor/dynamic/test-fixtures/template.pkr.hcl rename to packer_test/lib/plugin_tester/post-processor/dynamic/test-fixtures/template.pkr.hcl diff --git a/packer_test/plugin_tester/provisioner/dynamic/provisioner.go b/packer_test/lib/plugin_tester/provisioner/dynamic/provisioner.go similarity index 100% rename from packer_test/plugin_tester/provisioner/dynamic/provisioner.go rename to packer_test/lib/plugin_tester/provisioner/dynamic/provisioner.go diff --git a/packer_test/plugin_tester/provisioner/dynamic/provisioner.hcl2spec.go b/packer_test/lib/plugin_tester/provisioner/dynamic/provisioner.hcl2spec.go similarity index 100% rename from packer_test/plugin_tester/provisioner/dynamic/provisioner.hcl2spec.go rename to packer_test/lib/plugin_tester/provisioner/dynamic/provisioner.hcl2spec.go diff --git a/packer_test/plugin_tester/provisioner/dynamic/provisioner_acc_test.go b/packer_test/lib/plugin_tester/provisioner/dynamic/provisioner_acc_test.go similarity index 100% rename from packer_test/plugin_tester/provisioner/dynamic/provisioner_acc_test.go rename to packer_test/lib/plugin_tester/provisioner/dynamic/provisioner_acc_test.go diff --git a/packer_test/plugin_tester/provisioner/dynamic/test-fixtures/template.pkr.hcl b/packer_test/lib/plugin_tester/provisioner/dynamic/test-fixtures/template.pkr.hcl similarity index 100% rename from packer_test/plugin_tester/provisioner/dynamic/test-fixtures/template.pkr.hcl rename to packer_test/lib/plugin_tester/provisioner/dynamic/test-fixtures/template.pkr.hcl diff --git a/packer_test/plugin_tester/version/version.go b/packer_test/lib/plugin_tester/version/version.go similarity index 100% rename from packer_test/plugin_tester/version/version.go rename to packer_test/lib/plugin_tester/version/version.go diff --git a/packer_test/lib/suite.go b/packer_test/lib/suite.go new file mode 100644 index 00000000000..f597c712cf0 --- /dev/null +++ b/packer_test/lib/suite.go @@ -0,0 +1,142 @@ +package lib + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "sync" + "testing" + + "github.com/hashicorp/go-version" + "github.com/stretchr/testify/suite" +) + +type PackerTestSuite struct { + suite.Suite + // pluginsDirectory is the directory in which plugins are compiled. + // + // Those binaries are not necessarily meant to be used as-is, but + // instead should be used for composing plugin installation directories. + pluginsDirectory string + // packerPath is the location in which the Packer executable is compiled + // + // Since we don't necessarily want to manually compile Packer beforehand, + // we compile it on demand, and use this executable for the tests. + packerPath string +} + +func (ts *PackerTestSuite) buildPluginVersion(waitgroup *sync.WaitGroup, versionString string, t *testing.T) { + waitgroup.Add(1) + go func() { + defer waitgroup.Done() + ts.BuildSimplePlugin(versionString, t) + }() +} + +func (ts *PackerTestSuite) CompileTestPluginVersions(t *testing.T, versions ...string) { + wg := &sync.WaitGroup{} + + for _, ver := range versions { + ts.buildPluginVersion(wg, ver, t) + } + + wg.Wait() +} + +// BuildSimplePlugin creates a plugin that essentially does nothing. +// +// The plugin's code is contained in a subdirectory of this, and lets us +// change the attributes of the plugin binary itself, like the SDK version, +// the plugin's version, etc. +// +// The plugin is functional, and can be used to run builds with. +// There won't be anything substantial created though, its goal is only +// to validate the core functionality of Packer. +// +// The path to the plugin is returned, it won't be removed automatically +// though, deletion is the caller's responsibility. +func (ts *PackerTestSuite) BuildSimplePlugin(versionString string, t *testing.T) string { + // Only build plugin binary if not already done beforehand + path, ok := LoadPluginVersion(versionString) + if ok { + return path + } + + v := version.Must(version.NewSemver(versionString)) + + t.Logf("Building plugin in version %v", v) + + testDir, err := currentDir() + if err != nil { + t.Fatalf("failed to compile plugin binary: %s", err) + } + + testerPluginDir := filepath.Join(testDir, "plugin_tester") + outBin := filepath.Join(ts.pluginsDirectory, BinaryName(v)) + + compileCommand := exec.Command("go", "build", "-C", testerPluginDir, "-o", outBin, "-ldflags", LDFlags(v), ".") + logs, err := compileCommand.CombinedOutput() + if err != nil { + t.Fatalf("failed to compile plugin binary: %s\ncompiler logs: %s", err, logs) + } + + StorePluginVersion(v.String(), outBin) + + return outBin +} + +// SkipNoAcc is a pre-condition that skips the test if the PACKER_ACC environment +// variable is unset, or set to "0". +// +// This allows us to build tests with a potential for long runs (or errors like +// rate-limiting), so we can still test them, but only in a longer timeouted +// context. +func (ts *PackerTestSuite) SkipNoAcc() { + acc := os.Getenv("PACKER_ACC") + if acc == "" || acc == "0" { + ts.T().Logf("Skipping test as `PACKER_ACC` is unset.") + ts.T().Skip() + } +} + +func PackerCoreSuite(t *testing.T) (*PackerTestSuite, func()) { + ts := &PackerTestSuite{} + + tempDir, err := os.MkdirTemp("", "packer-core-acc-test-") + if err != nil { + panic(fmt.Sprintf("failed to create temporary directory for compiled plugins: %s", err)) + } + ts.pluginsDirectory = tempDir + + defer func() { + }() + + packerPath := os.Getenv("PACKER_CUSTOM_PATH") + if packerPath == "" { + var err error + t.Logf("Building test packer binary...") + packerPath, err = BuildTestPacker(t) + if err != nil { + t.Fatalf("failed to build Packer binary: %s", err) + } + } + ts.packerPath = packerPath + t.Logf("Done") + + return ts, func() { + err := os.RemoveAll(ts.pluginsDirectory) + if err != nil { + t.Logf("failed to cleanup directory %q: %s. This will need manual action", ts.pluginsDirectory, err) + } + + if os.Getenv("PACKER_CUSTOM_PATH") != "" { + return + } + + err = os.Remove(ts.packerPath) + if err != nil { + t.Logf("failed to cleanup compiled packer binary %q: %s. This will need manual action", packerPath, err) + } + } +} diff --git a/packer_test/init_test.go b/packer_test/plugin_tests/init_test.go similarity index 57% rename from packer_test/init_test.go rename to packer_test/plugin_tests/init_test.go index 38939ec252a..e5c3fa46488 100644 --- a/packer_test/init_test.go +++ b/packer_test/plugin_tests/init_test.go @@ -1,6 +1,8 @@ -package packer_test +package plugin_tests -func (ts *PackerTestSuite) TestPackerInitForce() { +import "github.com/hashicorp/packer/packer_test/lib" + +func (ts *PackerPluginTestSuite) TestPackerInitForce() { ts.SkipNoAcc() pluginPath, cleanup := ts.MakePluginDir() @@ -9,17 +11,17 @@ func (ts *PackerTestSuite) TestPackerInitForce() { ts.Run("installs any missing plugins", func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("init", "--force", "./templates/init/hashicups.pkr.hcl"). - Assert(MustSucceed(), Grep("Installed plugin github.com/hashicorp/hashicups v1.0.2", grepStdout)) + Assert(lib.MustSucceed(), lib.Grep("Installed plugin github.com/hashicorp/hashicups v1.0.2", lib.GrepStdout)) }) ts.Run("reinstalls plugins matching version constraints", func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("init", "--force", "./templates/init/hashicups.pkr.hcl"). - Assert(MustSucceed(), Grep("Installed plugin github.com/hashicorp/hashicups v1.0.2", grepStdout)) + Assert(lib.MustSucceed(), lib.Grep("Installed plugin github.com/hashicorp/hashicups v1.0.2", lib.GrepStdout)) }) } -func (ts *PackerTestSuite) TestPackerInitUpgrade() { +func (ts *PackerPluginTestSuite) TestPackerInitUpgrade() { ts.SkipNoAcc() pluginPath, cleanup := ts.MakePluginDir() @@ -27,7 +29,7 @@ func (ts *PackerTestSuite) TestPackerInitUpgrade() { cmd := ts.PackerCommand().UsePluginDir(pluginPath) cmd.SetArgs("plugins", "install", "github.com/hashicorp/hashicups", "1.0.1") - cmd.Assert(MustSucceed(), Grep("Installed plugin github.com/hashicorp/hashicups v1.0.1", grepStdout)) + cmd.Assert(lib.MustSucceed(), lib.Grep("Installed plugin github.com/hashicorp/hashicups v1.0.1", lib.GrepStdout)) _, _, err := cmd.Run() if err != nil { @@ -37,35 +39,35 @@ func (ts *PackerTestSuite) TestPackerInitUpgrade() { ts.Run("upgrades a plugin to the latest matching version constraints", func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("init", "--upgrade", "./templates/init/hashicups.pkr.hcl"). - Assert(MustSucceed(), Grep("Installed plugin github.com/hashicorp/hashicups v1.0.2", grepStdout)) + Assert(lib.MustSucceed(), lib.Grep("Installed plugin github.com/hashicorp/hashicups v1.0.2", lib.GrepStdout)) }) } -func (ts *PackerTestSuite) TestPackerInitWithNonGithubSource() { +func (ts *PackerPluginTestSuite) TestPackerInitWithNonGithubSource() { pluginPath, cleanup := ts.MakePluginDir() defer cleanup() ts.Run("try installing from a non-github source, should fail", func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("init", "./templates/init/non_gh.pkr.hcl"). - Assert(MustFail(), Grep(`doesn't appear to be a valid "github.com" source address`, grepStdout)) + Assert(lib.MustFail(), lib.Grep(`doesn't appear to be a valid "github.com" source address`, lib.GrepStdout)) }) ts.Run("manually install plugin to the expected source", func() { ts.PackerCommand().UsePluginDir(pluginPath). - SetArgs("plugins", "install", "--path", BuildSimplePlugin("1.0.10", ts.T()), "hubgit.com/hashicorp/tester"). - Assert(MustSucceed(), Grep("packer-plugin-tester_v1.0.10", grepStdout)) + SetArgs("plugins", "install", "--path", ts.BuildSimplePlugin("1.0.10", ts.T()), "hubgit.com/hashicorp/tester"). + Assert(lib.MustSucceed(), lib.Grep("packer-plugin-tester_v1.0.10", lib.GrepStdout)) }) ts.Run("re-run packer init on same template, should succeed silently", func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("init", "./templates/init/non_gh.pkr.hcl"). - Assert(MustSucceed(), - MkPipeCheck("no output in stdout").SetTester(ExpectEmptyInput()).SetStream(OnlyStdout)) + Assert(lib.MustSucceed(), + lib.MkPipeCheck("no output in stdout").SetTester(lib.ExpectEmptyInput()).SetStream(lib.OnlyStdout)) }) } -func (ts *PackerTestSuite) TestPackerInitWithMixedVersions() { +func (ts *PackerPluginTestSuite) TestPackerInitWithMixedVersions() { ts.SkipNoAcc() pluginPath, cleanup := ts.MakePluginDir() @@ -74,7 +76,7 @@ func (ts *PackerTestSuite) TestPackerInitWithMixedVersions() { ts.Run("skips the plugin installation with mixed versions before exiting with an error", func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("init", "./templates/init/mixed_versions.pkr.hcl"). - Assert(MustFail(), - Grep("binary reported a pre-release version of 10.7.3-dev", grepStdout)) + Assert(lib.MustFail(), + lib.Grep("binary reported a pre-release version of 10.7.3-dev", lib.GrepStdout)) }) } diff --git a/packer_test/install_test.go b/packer_test/plugin_tests/install_test.go similarity index 52% rename from packer_test/install_test.go rename to packer_test/plugin_tests/install_test.go index 3472c9af3c3..a80369d36a5 100644 --- a/packer_test/install_test.go +++ b/packer_test/plugin_tests/install_test.go @@ -1,62 +1,64 @@ -package packer_test +package plugin_tests -func (ts *PackerTestSuite) TestInstallPluginWithMetadata() { +import "github.com/hashicorp/packer/packer_test/lib" + +func (ts *PackerPluginTestSuite) TestInstallPluginWithMetadata() { tempPluginDir, cleanup := ts.MakePluginDir() defer cleanup() ts.Run("install plugin with metadata in version", func() { ts.PackerCommand().UsePluginDir(tempPluginDir). - SetArgs("plugins", "install", "--path", BuildSimplePlugin("1.0.0+metadata", ts.T()), "github.com/hashicorp/tester"). - Assert(MustSucceed(), Grep("Successfully installed plugin", grepStdout)) + SetArgs("plugins", "install", "--path", ts.BuildSimplePlugin("1.0.0+metadata", ts.T()), "github.com/hashicorp/tester"). + Assert(lib.MustSucceed(), lib.Grep("Successfully installed plugin", lib.GrepStdout)) }) ts.Run("metadata plugin installed must not have metadata in its path", func() { ts.PackerCommand().UsePluginDir(tempPluginDir). SetArgs("plugins", "installed"). - Assert(MustSucceed(), Grep("packer-plugin-tester_v1.0.0[^+]", grepStdout)) + Assert(lib.MustSucceed(), lib.Grep("packer-plugin-tester_v1.0.0[^+]", lib.GrepStdout)) }) ts.Run("plugin with metadata should work with validate", func() { ts.PackerCommand().UsePluginDir(tempPluginDir). SetArgs("validate", "./templates/simple.pkr.hcl"). - Assert(MustSucceed(), Grep("packer-plugin-tester_v1.0.0[^+][^\\n]+plugin:", grepStderr)) + Assert(lib.MustSucceed(), lib.Grep("packer-plugin-tester_v1.0.0[^+][^\\n]+plugin:", lib.GrepStderr)) }) ts.Run("plugin with metadata should work with build", func() { ts.PackerCommand().UsePluginDir(tempPluginDir). SetArgs("build", "./templates/simple.pkr.hcl"). - Assert(MustSucceed(), Grep("packer-plugin-tester_v1.0.0[^+][^\\n]+plugin:", grepStderr)) + Assert(lib.MustSucceed(), lib.Grep("packer-plugin-tester_v1.0.0[^+][^\\n]+plugin:", lib.GrepStderr)) }) } -func (ts *PackerTestSuite) TestInstallPluginWithPath() { +func (ts *PackerPluginTestSuite) TestInstallPluginWithPath() { tempPluginDir, cleanup := ts.MakePluginDir() defer cleanup() ts.Run("install plugin with pre-release only", func() { ts.PackerCommand().UsePluginDir(tempPluginDir). - SetArgs("plugins", "install", "--path", BuildSimplePlugin("1.0.0-dev", ts.T()), "github.com/hashicorp/tester"). - Assert(MustSucceed(), Grep("Successfully installed plugin", grepStdout)) + SetArgs("plugins", "install", "--path", ts.BuildSimplePlugin("1.0.0-dev", ts.T()), "github.com/hashicorp/tester"). + Assert(lib.MustSucceed(), lib.Grep("Successfully installed plugin", lib.GrepStdout)) }) ts.Run("install same plugin with pre-release + metadata", func() { ts.PackerCommand().UsePluginDir(tempPluginDir). - SetArgs("plugins", "install", "--path", BuildSimplePlugin("1.0.0-dev+metadata", ts.T()), "github.com/hashicorp/tester"). - Assert(MustSucceed(), Grep("Successfully installed plugin", grepStdout)) + SetArgs("plugins", "install", "--path", ts.BuildSimplePlugin("1.0.0-dev+metadata", ts.T()), "github.com/hashicorp/tester"). + Assert(lib.MustSucceed(), lib.Grep("Successfully installed plugin", lib.GrepStdout)) }) ts.Run("list plugins, should only report one plugin", func() { ts.PackerCommand().UsePluginDir(tempPluginDir). SetArgs("plugins", "installed"). - Assert(MustSucceed(), - Grep("plugin-tester_v1.0.0-dev[^+]", grepStdout), - Grep("plugin-tester_v1.0.0-dev\\+", grepStdout, grepInvert), - LineCountCheck(1)) + Assert(lib.MustSucceed(), + lib.Grep("plugin-tester_v1.0.0-dev[^+]", lib.GrepStdout), + lib.Grep("plugin-tester_v1.0.0-dev\\+", lib.GrepStdout, lib.GrepInvert), + lib.LineCountCheck(1)) }) } -func (ts *PackerTestSuite) TestInstallPluginPrerelease() { - pluginPath := BuildSimplePlugin("1.0.1-alpha1", ts.T()) +func (ts *PackerPluginTestSuite) TestInstallPluginPrerelease() { + pluginPath := ts.BuildSimplePlugin("1.0.1-alpha1", ts.T()) pluginDir, cleanup := ts.MakePluginDir() defer cleanup() @@ -64,11 +66,11 @@ func (ts *PackerTestSuite) TestInstallPluginPrerelease() { ts.Run("try install plugin with alpha1 prerelease - should fail", func() { ts.PackerCommand().UsePluginDir(pluginDir). SetArgs("plugins", "install", "--path", pluginPath, "github.com/hashicorp/tester"). - Assert(MustFail(), Grep("Packer can only install plugin releases with this command", grepStdout)) + Assert(lib.MustFail(), lib.Grep("Packer can only install plugin releases with this command", lib.GrepStdout)) }) } -func (ts *PackerTestSuite) TestRemoteInstallWithPluginsInstall() { +func (ts *PackerPluginTestSuite) TestRemoteInstallWithPluginsInstall() { ts.SkipNoAcc() pluginPath, cleanup := ts.MakePluginDir() @@ -77,11 +79,11 @@ func (ts *PackerTestSuite) TestRemoteInstallWithPluginsInstall() { ts.Run("install latest version of a remote plugin with packer plugins install", func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("plugins", "install", "github.com/hashicorp/hashicups"). - Assert(MustSucceed()) + Assert(lib.MustSucceed()) }) } -func (ts *PackerTestSuite) TestRemoteInstallOfPreReleasePlugin() { +func (ts *PackerPluginTestSuite) TestRemoteInstallOfPreReleasePlugin() { ts.SkipNoAcc() pluginPath, cleanup := ts.MakePluginDir() @@ -90,15 +92,15 @@ func (ts *PackerTestSuite) TestRemoteInstallOfPreReleasePlugin() { ts.Run("try to init with a pre-release constraint - should fail", func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("init", "templates/pre-release_constraint.pkr.hcl"). - Assert(MustFail(), - Grep("Invalid version constraint", grepStdout), - Grep("Unsupported prerelease for constraint", grepStdout)) + Assert(lib.MustFail(), + lib.Grep("Invalid version constraint", lib.GrepStdout), + lib.Grep("Unsupported prerelease for constraint", lib.GrepStdout)) }) ts.Run("try to plugins install with a pre-release version - should fail", func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("plugin", "install", "github.com/hashicorp/hashicups", "1.0.2-dev"). - Assert(MustFail(), - Grep("Unsupported prerelease for constraint", grepStdout)) + Assert(lib.MustFail(), + lib.Grep("Unsupported prerelease for constraint", lib.GrepStdout)) }) } diff --git a/packer_test/loading_test.go b/packer_test/plugin_tests/loading_test.go similarity index 55% rename from packer_test/loading_test.go rename to packer_test/plugin_tests/loading_test.go index 1f1d8ceeef2..4b14ba8060f 100644 --- a/packer_test/loading_test.go +++ b/packer_test/plugin_tests/loading_test.go @@ -1,13 +1,15 @@ -package packer_test +package plugin_tests import ( "crypto/sha256" "fmt" "os" "path/filepath" + + "github.com/hashicorp/packer/packer_test/lib" ) -func (ts *PackerTestSuite) TestLoadingOrder() { +func (ts *PackerPluginTestSuite) TestLoadingOrder() { pluginDir, cleanup := ts.MakePluginDir("1.0.9", "1.0.10") defer cleanup() @@ -39,100 +41,100 @@ func (ts *PackerTestSuite) TestLoadingOrder() { ts.PackerCommand(). SetArgs(command, tt.templatePath). UsePluginDir(pluginDir). - Assert(MustSucceed(), Grep(tt.grepStr)) + Assert(lib.MustSucceed(), lib.Grep(tt.grepStr)) }) } } } -func (ts *PackerTestSuite) TestLoadWithLegacyPluginName() { +func (ts *PackerPluginTestSuite) TestLoadWithLegacyPluginName() { pluginDir, cleanup := ts.MakePluginDir() defer cleanup() - plugin := BuildSimplePlugin("1.0.10", ts.T()) + plugin := ts.BuildSimplePlugin("1.0.10", ts.T()) - CopyFile(ts.T(), filepath.Join(pluginDir, "packer-plugin-tester"), plugin) + lib.CopyFile(ts.T(), filepath.Join(pluginDir, "packer-plugin-tester"), plugin) ts.Run("only legacy plugins installed: expect build to fail", func() { ts.Run("with required_plugins - expect prompt for packer init", func() { ts.PackerCommand().UsePluginDir(pluginDir). SetArgs("build", "templates/simple.pkr.hcl"). - Assert(MustFail(), - Grep("Did you run packer init for this project", grepStdout), - Grep("following plugins are required", grepStdout)) + Assert(lib.MustFail(), + lib.Grep("Did you run packer init for this project", lib.GrepStdout), + lib.Grep("following plugins are required", lib.GrepStdout)) }) ts.Run("JSON template, without required_plugins: should say the component is unknown", func() { ts.PackerCommand().UsePluginDir(pluginDir). SetArgs("build", "templates/simple.json"). - Assert(MustFail(), - Grep("The builder tester-dynamic is unknown by Packer", grepStdout)) + Assert(lib.MustFail(), + lib.Grep("The builder tester-dynamic is unknown by Packer", lib.GrepStdout)) }) }) pluginDir, cleanup = ts.MakePluginDir("1.0.0") defer cleanup() - CopyFile(ts.T(), filepath.Join(pluginDir, "packer-plugin-tester"), plugin) + lib.CopyFile(ts.T(), filepath.Join(pluginDir, "packer-plugin-tester"), plugin) ts.Run("multiple plugins installed: one with no version in path, one with qualified name. Should pick-up the qualified one only.", func() { ts.PackerCommand().UsePluginDir(pluginDir). SetArgs("build", "templates/simple.pkr.hcl"). - Assert(MustSucceed(), Grep("packer-plugin-tester_v1\\.0\\.0[^\\n]+ plugin:", grepStderr)) + Assert(lib.MustSucceed(), lib.Grep("packer-plugin-tester_v1\\.0\\.0[^\\n]+ plugin:", lib.GrepStderr)) }) - wd, cleanup := TempWorkdir(ts.T(), "./templates/simple.pkr.hcl") + wd, cleanup := lib.TempWorkdir(ts.T(), "./templates/simple.pkr.hcl") defer cleanup() - CopyFile(ts.T(), filepath.Join(wd, "packer-plugin-tester"), plugin) + lib.CopyFile(ts.T(), filepath.Join(wd, "packer-plugin-tester"), plugin) ts.Run("multiple plugins installed: 1.0.0 in plugin dir with sum, one in workdir (no version). Should load 1.0.0", func() { ts.PackerCommand().UsePluginDir(pluginDir).SetWD(wd). SetArgs("build", "simple.pkr.hcl"). - Assert(MustSucceed(), Grep("packer-plugin-tester_v1\\.0\\.0[^\\n]+ plugin:", grepStderr)) + Assert(lib.MustSucceed(), lib.Grep("packer-plugin-tester_v1\\.0\\.0[^\\n]+ plugin:", lib.GrepStderr)) }) } -func (ts *PackerTestSuite) TestLoadWithSHAMismatches() { - plugin := BuildSimplePlugin("1.0.10", ts.T()) +func (ts *PackerPluginTestSuite) TestLoadWithSHAMismatches() { + plugin := ts.BuildSimplePlugin("1.0.10", ts.T()) ts.Run("move plugin with right name, but no SHA256SUM, should reject", func() { pluginDir, cleanup := ts.MakePluginDir("1.0.9") defer cleanup() - pluginDestName := ExpectedInstalledName("1.0.10") + pluginDestName := lib.ExpectedInstalledName("1.0.10") - CopyFile(ts.T(), filepath.Join(pluginDir, "github.com", "hashicorp", "tester", pluginDestName), plugin) + lib.CopyFile(ts.T(), filepath.Join(pluginDir, "github.com", "hashicorp", "tester", pluginDestName), plugin) ts.PackerCommand().UsePluginDir(pluginDir). SetArgs("plugins", "installed"). - Assert(MustSucceed(), - Grep("packer-plugin-tester_v1\\.0\\.9[^\\n]+", grepStdout), - Grep("packer-plugin-tester_v1.0.10", grepStdout, grepInvert), - Grep("v1.0.10[^\\n]+ignoring possibly unsafe binary", grepStderr)) + Assert(lib.MustSucceed(), + lib.Grep("packer-plugin-tester_v1\\.0\\.9[^\\n]+", lib.GrepStdout), + lib.Grep("packer-plugin-tester_v1.0.10", lib.GrepStdout, lib.GrepInvert), + lib.Grep("v1.0.10[^\\n]+ignoring possibly unsafe binary", lib.GrepStderr)) }) ts.Run("move plugin with right name, invalid SHA256SUM, should reject", func() { pluginDir, cleanup := ts.MakePluginDir("1.0.9") defer cleanup() - pluginDestName := ExpectedInstalledName("1.0.10") - CopyFile(ts.T(), filepath.Join(pluginDir, "github.com", "hashicorp", "tester", pluginDestName), plugin) - WriteFile(ts.T(), + pluginDestName := lib.ExpectedInstalledName("1.0.10") + lib.CopyFile(ts.T(), filepath.Join(pluginDir, "github.com", "hashicorp", "tester", pluginDestName), plugin) + lib.WriteFile(ts.T(), filepath.Join(pluginDir, "github.com", "hashicorp", "tester", fmt.Sprintf("%s_SHA256SUM", pluginDestName)), fmt.Sprintf("%x", sha256.New().Sum([]byte("Not the plugin's contents for sure.")))) ts.PackerCommand().UsePluginDir(pluginDir). SetArgs("plugins", "installed"). - Assert(MustSucceed(), - Grep("packer-plugin-tester_v1\\.0\\.9[^\\n]+", grepStdout), - Grep("packer-plugin-tester_v1.0.10", grepInvert, grepStdout), - Grep("v1.0.10[^\\n]+ignoring possibly unsafe binary", grepStderr), - Grep(`Checksums \(\*sha256\.digest\) did not match.`, grepStderr)) + Assert(lib.MustSucceed(), + lib.Grep("packer-plugin-tester_v1\\.0\\.9[^\\n]+", lib.GrepStdout), + lib.Grep("packer-plugin-tester_v1.0.10", lib.GrepInvert, lib.GrepStdout), + lib.Grep("v1.0.10[^\\n]+ignoring possibly unsafe binary", lib.GrepStderr), + lib.Grep(`Checksums \(\*sha256\.digest\) did not match.`, lib.GrepStderr)) }) } -func (ts *PackerTestSuite) TestPluginPathEnvvarWithMultiplePaths() { +func (ts *PackerPluginTestSuite) TestPluginPathEnvvarWithMultiplePaths() { pluginDirOne, cleanup := ts.MakePluginDir("1.0.10") defer cleanup() @@ -143,53 +145,53 @@ func (ts *PackerTestSuite) TestPluginPathEnvvarWithMultiplePaths() { ts.Run("load plugin with two dirs - not supported anymore, should error", func() { ts.PackerCommand().UsePluginDir(pluginDirVal). SetArgs("plugins", "installed"). - Assert(MustFail(), - Grep("Multiple paths are no longer supported for PACKER_PLUGIN_PATH"), - MkPipeCheck("All envvars are suggested", - PipeGrep(`\* PACKER_PLUGIN_PATH=`), - LineCount()). - SetStream(OnlyStderr). - SetTester(IntCompare(eq, 2))) + Assert(lib.MustFail(), + lib.Grep("Multiple paths are no longer supported for PACKER_PLUGIN_PATH"), + lib.MkPipeCheck("All envvars are suggested", + lib.PipeGrep(`\* PACKER_PLUGIN_PATH=`), + lib.LineCount()). + SetStream(lib.OnlyStderr). + SetTester(lib.IntCompare(lib.Eq, 2))) }) } -func (ts *PackerTestSuite) TestInstallNonCanonicalPluginVersion() { +func (ts *PackerPluginTestSuite) TestInstallNonCanonicalPluginVersion() { pluginPath, cleanup := ts.MakePluginDir() defer cleanup() - ManualPluginInstall(ts.T(), + lib.ManualPluginInstall(ts.T(), filepath.Join(pluginPath, "github.com", "hashicorp", "tester"), - BuildSimplePlugin("1.0.10", ts.T()), + ts.BuildSimplePlugin("1.0.10", ts.T()), "001.00.010") ts.Run("try listing plugins with non-canonical version installed - report none", func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("plugins", "installed"). - Assert(MustSucceed(), - Grep(`version .* in path is non canonical`, grepStderr), - MkPipeCheck("no output in stdout").SetTester(ExpectEmptyInput()).SetStream(OnlyStdout)) + Assert(lib.MustSucceed(), + lib.Grep(`version .* in path is non canonical`, lib.GrepStderr), + lib.MkPipeCheck("no output in stdout").SetTester(lib.ExpectEmptyInput()).SetStream(lib.OnlyStdout)) }) } -func (ts *PackerTestSuite) TestLoadPluginWithMetadataInName() { +func (ts *PackerPluginTestSuite) TestLoadPluginWithMetadataInName() { pluginPath, cleanup := ts.MakePluginDir() defer cleanup() - ManualPluginInstall(ts.T(), + lib.ManualPluginInstall(ts.T(), filepath.Join(pluginPath, "github.com", "hashicorp", "tester"), - BuildSimplePlugin("1.0.10+metadata", ts.T()), + ts.BuildSimplePlugin("1.0.10+metadata", ts.T()), "1.0.10+metadata") ts.Run("try listing plugins with metadata in name - report none", func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("plugins", "installed"). - Assert(MustSucceed(), - Grep("found version .* with metadata in the name", grepStderr), - MkPipeCheck("no output in stdout").SetTester(ExpectEmptyInput()).SetStream(OnlyStdout)) + Assert(lib.MustSucceed(), + lib.Grep("found version .* with metadata in the name", lib.GrepStderr), + lib.MkPipeCheck("no output in stdout").SetTester(lib.ExpectEmptyInput()).SetStream(lib.OnlyStdout)) }) } -func (ts *PackerTestSuite) TestLoadWithOnlyReleaseFlag() { +func (ts *PackerPluginTestSuite) TestLoadWithOnlyReleaseFlag() { pluginPath, cleanup := ts.MakePluginDir("1.0.0", "1.0.1-dev") defer cleanup() @@ -197,24 +199,24 @@ func (ts *PackerTestSuite) TestLoadWithOnlyReleaseFlag() { ts.Run(fmt.Sprintf("run %s without --ignore-prerelease flag - pick 1.0.1-dev by default", cmd), func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs(cmd, "./templates/simple.pkr.hcl"). - Assert(MustSucceed(), - Grep("packer-plugin-tester_v1.0.1-dev.*: plugin process exited", grepStderr)) + Assert(lib.MustSucceed(), + lib.Grep("packer-plugin-tester_v1.0.1-dev.*: plugin process exited", lib.GrepStderr)) }) ts.Run(fmt.Sprintf("run %s with --ignore-prerelease flag - pick 1.0.0", cmd), func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs(cmd, "--ignore-prerelease-plugins", "./templates/simple.pkr.hcl"). - Assert(MustSucceed(), - Grep("packer-plugin-tester_v1.0.0.*: plugin process exited", grepStderr)) + Assert(lib.MustSucceed(), + lib.Grep("packer-plugin-tester_v1.0.0.*: plugin process exited", lib.GrepStderr)) }) } } -func (ts *PackerTestSuite) TestWithLegacyConfigAndComponents() { +func (ts *PackerPluginTestSuite) TestWithLegacyConfigAndComponents() { pluginDir, cleanup := ts.MakePluginDir("1.0.0") defer cleanup() - workdir, cleanup := TempWorkdir(ts.T(), "./sample_config.json", "./templates/simple.json", "./templates/simple.pkr.hcl") + workdir, cleanup := lib.TempWorkdir(ts.T(), "./sample_config.json", "./templates/simple.json", "./templates/simple.pkr.hcl") defer cleanup() for _, cmd := range []string{"validate", "build"} { @@ -222,18 +224,18 @@ func (ts *PackerTestSuite) TestWithLegacyConfigAndComponents() { ts.PackerCommand().UsePluginDir(pluginDir).SetWD(workdir). SetArgs(cmd, "simple.json"). AddEnv("PACKER_CONFIG", filepath.Join(workdir, "sample_config.json")). - Assert(MustFail(), - Grep("Your configuration file describes some legacy components", grepStderr), - Grep("packer-provisioner-super-shell", grepStderr)) + Assert(lib.MustFail(), + lib.Grep("Your configuration file describes some legacy components", lib.GrepStderr), + lib.Grep("packer-provisioner-super-shell", lib.GrepStderr)) }) ts.Run(fmt.Sprintf("%s simple HCL2 template with config.json and components defined", cmd), func() { ts.PackerCommand().UsePluginDir(pluginDir).SetWD(workdir). SetArgs(cmd, "simple.pkr.hcl"). AddEnv("PACKER_CONFIG", filepath.Join(workdir, "sample_config.json")). - Assert(MustFail(), - Grep("Your configuration file describes some legacy components", grepStderr), - Grep("packer-provisioner-super-shell", grepStderr)) + Assert(lib.MustFail(), + lib.Grep("Your configuration file describes some legacy components", lib.GrepStderr), + lib.Grep("packer-provisioner-super-shell", lib.GrepStderr)) }) } } diff --git a/packer_test/plugins_remove_test.go b/packer_test/plugin_tests/plugins_remove_test.go similarity index 70% rename from packer_test/plugins_remove_test.go rename to packer_test/plugin_tests/plugins_remove_test.go index cc10b611376..3bdfed37981 100644 --- a/packer_test/plugins_remove_test.go +++ b/packer_test/plugin_tests/plugins_remove_test.go @@ -1,11 +1,13 @@ -package packer_test +package plugin_tests import ( "path/filepath" "strings" + + "github.com/hashicorp/packer/packer_test/lib" ) -func (ts *PackerTestSuite) TestPluginsRemoveWithSourceAddress() { +func (ts *PackerPluginTestSuite) TestPluginsRemoveWithSourceAddress() { pluginPath, cleanup := ts.MakePluginDir("1.0.9", "1.0.10", "2.0.0") defer cleanup() @@ -17,10 +19,10 @@ func (ts *PackerTestSuite) TestPluginsRemoveWithSourceAddress() { ts.Run("plugins remove with source address removes all installed plugin versions", func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("plugins", "remove", "github.com/hashicorp/tester"). - Assert(MustSucceed(), - Grep("packer-plugin-tester_v1.0.9", grepStdout), - Grep("packer-plugin-tester_v1.0.10", grepStdout), - Grep("packer-plugin-tester_v2.0.0", grepStdout), + Assert(lib.MustSucceed(), + lib.Grep("packer-plugin-tester_v1.0.9", lib.GrepStdout), + lib.Grep("packer-plugin-tester_v1.0.10", lib.GrepStdout), + lib.Grep("packer-plugin-tester_v2.0.0", lib.GrepStdout), ) }) @@ -33,8 +35,8 @@ func (ts *PackerTestSuite) TestPluginsRemoveWithSourceAddress() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("plugins", "remove", "github.com/hashicorp/testerONE"). Assert( - MustFail(), - Grep("No installed plugin found matching the plugin constraints github.com/hashicorp/testerONE"), + lib.MustFail(), + lib.Grep("No installed plugin found matching the plugin constraints github.com/hashicorp/testerONE"), ) }) @@ -42,13 +44,13 @@ func (ts *PackerTestSuite) TestPluginsRemoveWithSourceAddress() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("plugins", "remove", "github.com/hashicorp/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/tester"). Assert( - MustFail(), - Grep("The source URL must have at most 16 components"), + lib.MustFail(), + lib.Grep("The source URL must have at most 16 components"), ) }) } -func (ts *PackerTestSuite) TestPluginsRemoveWithSourceAddressAndVersion() { +func (ts *PackerPluginTestSuite) TestPluginsRemoveWithSourceAddressAndVersion() { pluginPath, cleanup := ts.MakePluginDir("1.0.9", "1.0.10", "2.0.0") defer cleanup() @@ -60,17 +62,17 @@ func (ts *PackerTestSuite) TestPluginsRemoveWithSourceAddressAndVersion() { ts.Run("plugins remove with source address and version removes only the versioned plugin", func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("plugins", "remove", "github.com/hashicorp/tester", ">= 2.0.0"). - Assert(MustSucceed(), Grep("packer-plugin-tester_v2.0.0", grepStdout)) + Assert(lib.MustSucceed(), lib.Grep("packer-plugin-tester_v2.0.0", lib.GrepStdout)) }) ts.Run("plugins installed after single plugins remove outputs remaining installed plugins", func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("plugins", "installed"). Assert( - MustSucceed(), - Grep("packer-plugin-tester_v1.0.9", grepStdout), - Grep("packer-plugin-tester_v1.0.10", grepStdout), - Grep("packer-plugin-tester_v2.0.0", grepInvert, grepStdout), + lib.MustSucceed(), + lib.Grep("packer-plugin-tester_v1.0.9", lib.GrepStdout), + lib.Grep("packer-plugin-tester_v1.0.10", lib.GrepStdout), + lib.Grep("packer-plugin-tester_v2.0.0", lib.GrepInvert, lib.GrepStdout), ) }) @@ -80,7 +82,7 @@ func (ts *PackerTestSuite) TestPluginsRemoveWithSourceAddressAndVersion() { } } -func (ts *PackerTestSuite) TestPluginsRemoveWithLocalPath() { +func (ts *PackerPluginTestSuite) TestPluginsRemoveWithLocalPath() { pluginPath, cleanup := ts.MakePluginDir("1.0.9", "1.0.10") defer cleanup() @@ -94,18 +96,18 @@ func (ts *PackerTestSuite) TestPluginsRemoveWithLocalPath() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("plugins", "remove", plugins[0]). Assert( - MustSucceed(), - Grep("packer-plugin-tester_v1.0.9", grepStdout), - Grep("packer-plugin-tester_v1.0.10", grepInvert, grepStdout), + lib.MustSucceed(), + lib.Grep("packer-plugin-tester_v1.0.9", lib.GrepStdout), + lib.Grep("packer-plugin-tester_v1.0.10", lib.GrepInvert, lib.GrepStdout), ) }) ts.Run("plugins installed after calling plugins remove outputs remaining installed plugins", func() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("plugins", "installed"). Assert( - MustSucceed(), - Grep("packer-plugin-tester_v1.0.10", grepStdout), - Grep("packer-plugin-tester_v1.0.9", grepInvert, grepStdout), + lib.MustSucceed(), + lib.Grep("packer-plugin-tester_v1.0.10", lib.GrepStdout), + lib.Grep("packer-plugin-tester_v1.0.9", lib.GrepInvert, lib.GrepStdout), ) }) @@ -118,8 +120,8 @@ func (ts *PackerTestSuite) TestPluginsRemoveWithLocalPath() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("plugins", "remove", filepath.Base(plugins[0])). Assert( - MustFail(), - Grep("A source URL must at least contain a host and a path with 2 components", grepStdout), + lib.MustFail(), + lib.Grep("A source URL must at least contain a host and a path with 2 components", lib.GrepStdout), ) }) @@ -127,13 +129,13 @@ func (ts *PackerTestSuite) TestPluginsRemoveWithLocalPath() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("plugins", "remove", ts.T().TempDir()). Assert( - MustFail(), - Grep("is not under the plugin directory inferred by Packer", grepStdout), + lib.MustFail(), + lib.Grep("is not under the plugin directory inferred by Packer", lib.GrepStdout), ) }) } -func (ts *PackerTestSuite) TestPluginsRemoveWithNoArguments() { +func (ts *PackerPluginTestSuite) TestPluginsRemoveWithNoArguments() { pluginPath, cleanup := ts.MakePluginDir("1.0.9") defer cleanup() @@ -146,8 +148,8 @@ func (ts *PackerTestSuite) TestPluginsRemoveWithNoArguments() { ts.PackerCommand().UsePluginDir(pluginPath). SetArgs("plugins", "remove"). Assert( - MustFail(), - Grep("Usage: packer plugins remove ", grepStdout), + lib.MustFail(), + lib.Grep("Usage: packer plugins remove ", lib.GrepStdout), ) }) @@ -158,12 +160,12 @@ func (ts *PackerTestSuite) TestPluginsRemoveWithNoArguments() { } -func InstalledPlugins(ts *PackerTestSuite, dir string) []string { +func InstalledPlugins(ts *PackerPluginTestSuite, dir string) []string { ts.T().Helper() cmd := ts.PackerCommand().UsePluginDir(dir). SetArgs("plugins", "installed") - cmd.Assert(MustSucceed()) + cmd.Assert(lib.MustSucceed()) if ts.T().Failed() { ts.T().Fatalf("Failed to execute plugin installed for %q", dir) } diff --git a/packer_test/sample_config.json b/packer_test/plugin_tests/sample_config.json similarity index 100% rename from packer_test/sample_config.json rename to packer_test/plugin_tests/sample_config.json diff --git a/packer_test/plugin_tests/suite_test.go b/packer_test/plugin_tests/suite_test.go new file mode 100644 index 00000000000..dac2e3b72d1 --- /dev/null +++ b/packer_test/plugin_tests/suite_test.go @@ -0,0 +1,36 @@ +package plugin_tests + +import ( + "testing" + + "github.com/hashicorp/packer/packer_test/lib" + "github.com/stretchr/testify/suite" +) + +type PackerPluginTestSuite struct { + *lib.PackerTestSuite +} + +func Test_PackerPluginSuite(t *testing.T) { + baseSuite, cleanup := lib.PackerCoreSuite(t) + defer cleanup() + + ts := &PackerPluginTestSuite{ + baseSuite, + } + ts.PackerTestSuite.CompileTestPluginVersions(t, + "1.0.0", + "1.0.0", + "1.0.0+metadata", + "1.0.1-alpha1", + "1.0.9", + "1.0.10", + "1.0.0-dev", + "1.0.0-dev+metadata", + "1.0.10+metadata", + "1.0.1-dev", + "2.0.0", + ) + + suite.Run(t, ts) +} diff --git a/packer_test/templates/init/hashicups.pkr.hcl b/packer_test/plugin_tests/templates/init/hashicups.pkr.hcl similarity index 100% rename from packer_test/templates/init/hashicups.pkr.hcl rename to packer_test/plugin_tests/templates/init/hashicups.pkr.hcl diff --git a/packer_test/templates/init/mixed_versions.pkr.hcl b/packer_test/plugin_tests/templates/init/mixed_versions.pkr.hcl similarity index 100% rename from packer_test/templates/init/mixed_versions.pkr.hcl rename to packer_test/plugin_tests/templates/init/mixed_versions.pkr.hcl diff --git a/packer_test/templates/init/non_gh.pkr.hcl b/packer_test/plugin_tests/templates/init/non_gh.pkr.hcl similarity index 100% rename from packer_test/templates/init/non_gh.pkr.hcl rename to packer_test/plugin_tests/templates/init/non_gh.pkr.hcl diff --git a/packer_test/templates/pin_1.0.9.pkr.hcl b/packer_test/plugin_tests/templates/pin_1.0.9.pkr.hcl similarity index 100% rename from packer_test/templates/pin_1.0.9.pkr.hcl rename to packer_test/plugin_tests/templates/pin_1.0.9.pkr.hcl diff --git a/packer_test/templates/pre-release_constraint.pkr.hcl b/packer_test/plugin_tests/templates/pre-release_constraint.pkr.hcl similarity index 100% rename from packer_test/templates/pre-release_constraint.pkr.hcl rename to packer_test/plugin_tests/templates/pre-release_constraint.pkr.hcl diff --git a/packer_test/templates/simple.json b/packer_test/plugin_tests/templates/simple.json similarity index 100% rename from packer_test/templates/simple.json rename to packer_test/plugin_tests/templates/simple.json diff --git a/packer_test/templates/simple.pkr.hcl b/packer_test/plugin_tests/templates/simple.pkr.hcl similarity index 100% rename from packer_test/templates/simple.pkr.hcl rename to packer_test/plugin_tests/templates/simple.pkr.hcl diff --git a/packer_test/suite_test.go b/packer_test/suite_test.go deleted file mode 100644 index ad76281c6cf..00000000000 --- a/packer_test/suite_test.go +++ /dev/null @@ -1,97 +0,0 @@ -package packer_test - -import ( - "os" - "sync" - "testing" - - "github.com/stretchr/testify/suite" -) - -type PackerTestSuite struct { - suite.Suite - // pluginsDirectory is the directory in which plugins are compiled. - // - // Those binaries are not necessarily meant to be used as-is, but - // instead should be used for composing plugin installation directories. - pluginsDirectory string - // packerPath is the location in which the Packer executable is compiled - // - // Since we don't necessarily want to manually compile Packer beforehand, - // we compile it on demand, and use this executable for the tests. - packerPath string -} - -func buildPluginVersion(waitgroup *sync.WaitGroup, versionString string, t *testing.T) { - waitgroup.Add(1) - go func() { - defer waitgroup.Done() - BuildSimplePlugin(versionString, t) - }() -} - -func (ts *PackerTestSuite) buildPluginBinaries(t *testing.T) { - wg := &sync.WaitGroup{} - - buildPluginVersion(wg, "1.0.0", t) - buildPluginVersion(wg, "1.0.0+metadata", t) - buildPluginVersion(wg, "1.0.1-alpha1", t) - buildPluginVersion(wg, "1.0.9", t) - buildPluginVersion(wg, "1.0.10", t) - - wg.Wait() -} - -// SkipNoAcc is a pre-condition that skips the test if the PACKER_ACC environment -// variable is unset, or set to "0". -// -// This allows us to build tests with a potential for long runs (or errors like -// rate-limiting), so we can still test them, but only in a longer timeouted -// context. -func (ts *PackerTestSuite) SkipNoAcc() { - acc := os.Getenv("PACKER_ACC") - if acc == "" || acc == "0" { - ts.T().Logf("Skipping test as `PACKER_ACC` is unset.") - ts.T().Skip() - } -} - -func Test_PackerCoreSuite(t *testing.T) { - ts := &PackerTestSuite{} - - pluginsDirectory := PluginBinaryDir() - defer func() { - err := os.RemoveAll(pluginsDirectory) - if err != nil { - t.Logf("failed to cleanup directory %q: %s. This will need manual action", pluginsDirectory, err) - } - }() - - ts.pluginsDirectory = pluginsDirectory - ts.buildPluginBinaries(t) - - packerPath := os.Getenv("PACKER_CUSTOM_PATH") - if packerPath == "" { - var err error - t.Logf("Building test packer binary...") - packerPath, err = BuildTestPacker(t) - if err != nil { - t.Fatalf("failed to build Packer binary: %s", err) - } - } - ts.packerPath = packerPath - t.Logf("Done") - - defer func() { - if os.Getenv("PACKER_CUSTOM_PATH") != "" { - return - } - - err := os.Remove(ts.packerPath) - if err != nil { - t.Logf("failed to cleanup compiled packer binary %q: %s. This will need manual action", packerPath, err) - } - }() - - suite.Run(t, ts) -}