diff --git a/acctest/plugin/component_acc_test.go b/acctest/plugin/component_acc_test.go new file mode 100644 index 000000000..838ab5f8f --- /dev/null +++ b/acctest/plugin/component_acc_test.go @@ -0,0 +1,71 @@ +// component_acc_test.go should contain acceptance tests for plugin components +// to make sure all component types can be discovered and started. +package plugin + +import ( + _ "embed" + "fmt" + "io/ioutil" + "os" + "os/exec" + "testing" + + amazonacc "github.com/hashicorp/packer-plugin-amazon/builder/ebs/acceptance" + "github.com/hashicorp/packer-plugin-sdk/acctest" + "github.com/hashicorp/packer/hcl2template/addrs" +) + +//go:embed test-fixtures/basic-amazon-ami-datasource.pkr.hcl +var basicAmazonAmiDatasourceHCL2Template string + +func TestAccInitAndBuildBasicAmazonAmiDatasource(t *testing.T) { + plugin := addrs.Plugin{ + Hostname: "github.com", + Namespace: "hashicorp", + Type: "amazon", + } + testCase := &acctest.PluginTestCase{ + Name: "amazon-ami_basic_datasource_test", + Setup: func() error { + return cleanupPluginInstallation(plugin) + }, + Teardown: func() error { + helper := amazonacc.AWSHelper{ + Region: "us-west-2", + AMIName: "packer-amazon-ami-test", + } + return helper.CleanUpAmi() + }, + Template: basicAmazonAmiDatasourceHCL2Template, + Type: "amazon-ami", + Init: true, + CheckInit: func(initCommand *exec.Cmd, logfile string) error { + if initCommand.ProcessState != nil { + if initCommand.ProcessState.ExitCode() != 0 { + return fmt.Errorf("Bad exit code. Logfile: %s", logfile) + } + } + logs, err := os.Open(logfile) + if err != nil { + return fmt.Errorf("Unable find %s", logfile) + } + defer logs.Close() + + logsBytes, err := ioutil.ReadAll(logs) + if err != nil { + return fmt.Errorf("Unable to read %s", logfile) + } + initOutput := string(logsBytes) + return checkPluginInstallation(initOutput, plugin) + }, + Check: func(buildCommand *exec.Cmd, logfile string) error { + if buildCommand.ProcessState != nil { + if buildCommand.ProcessState.ExitCode() != 0 { + return fmt.Errorf("Bad exit code. Logfile: %s", logfile) + } + } + return nil + }, + } + acctest.TestPlugin(t, testCase) +} diff --git a/acctest/plugin/plugin_acc_test.go b/acctest/plugin/plugin_acc_test.go new file mode 100644 index 000000000..d7908028f --- /dev/null +++ b/acctest/plugin/plugin_acc_test.go @@ -0,0 +1,112 @@ +// plugin_acc_test.go should contain acceptance tests for features related to +// installing, discovering and running plugins. +package plugin + +import ( + _ "embed" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "regexp" + "testing" + + amazonacc "github.com/hashicorp/packer-plugin-amazon/builder/ebs/acceptance" + "github.com/hashicorp/packer-plugin-sdk/acctest" + "github.com/hashicorp/packer-plugin-sdk/acctest/testutils" + "github.com/hashicorp/packer/hcl2template/addrs" + "github.com/mitchellh/go-homedir" +) + +//go:embed test-fixtures/basic-amazon-ebs.pkr.hcl +var basicAmazonEbsHCL2Template string + +func TestAccInitAndBuildBasicAmazonEbs(t *testing.T) { + plugin := addrs.Plugin{ + Hostname: "github.com", + Namespace: "hashicorp", + Type: "amazon", + } + testCase := &acctest.PluginTestCase{ + Name: "amazon-ebs_basic_plugin_init_and_build_test", + Setup: func() error { + return cleanupPluginInstallation(plugin) + }, + Teardown: func() error { + helper := amazonacc.AWSHelper{ + Region: "us-east-1", + AMIName: "packer-plugin-amazon-ebs-test", + } + return helper.CleanUpAmi() + }, + Template: basicAmazonEbsHCL2Template, + Type: "amazon-ebs", + Init: true, + CheckInit: func(initCommand *exec.Cmd, logfile string) error { + if initCommand.ProcessState != nil { + if initCommand.ProcessState.ExitCode() != 0 { + return fmt.Errorf("Bad exit code. Logfile: %s", logfile) + } + } + logs, err := os.Open(logfile) + if err != nil { + return fmt.Errorf("Unable find %s", logfile) + } + defer logs.Close() + + logsBytes, err := ioutil.ReadAll(logs) + if err != nil { + return fmt.Errorf("Unable to read %s", logfile) + } + initOutput := string(logsBytes) + return checkPluginInstallation(initOutput, plugin) + }, + Check: func(buildCommand *exec.Cmd, logfile string) error { + if buildCommand.ProcessState != nil { + if buildCommand.ProcessState.ExitCode() != 0 { + return fmt.Errorf("Bad exit code. Logfile: %s", logfile) + } + } + return nil + }, + } + acctest.TestPlugin(t, testCase) +} + +func cleanupPluginInstallation(plugin addrs.Plugin) error { + home, err := homedir.Dir() + if err != nil { + return err + } + pluginPath := filepath.Join(home, + ".packer.d", + "plugins", + plugin.Hostname, + plugin.Namespace, + plugin.Type) + testutils.CleanupFiles(pluginPath) + return nil +} + +func checkPluginInstallation(initOutput string, plugin addrs.Plugin) error { + expectedInitLog := "Installed plugin " + plugin.String() + if matched, _ := regexp.MatchString(expectedInitLog+".*", initOutput); !matched { + return fmt.Errorf("logs doesn't contain expected foo value %q", initOutput) + } + + home, err := homedir.Dir() + if err != nil { + return err + } + pluginPath := filepath.Join(home, + ".packer.d", + "plugins", + plugin.Hostname, + plugin.Namespace, + plugin.Type) + if !testutils.FileExists(pluginPath) { + return fmt.Errorf("%s plugin installation not found", plugin.String()) + } + return nil +} diff --git a/acctest/plugin/test-fixtures/basic-amazon-ami-datasource.pkr.hcl b/acctest/plugin/test-fixtures/basic-amazon-ami-datasource.pkr.hcl new file mode 100644 index 000000000..a634347f7 --- /dev/null +++ b/acctest/plugin/test-fixtures/basic-amazon-ami-datasource.pkr.hcl @@ -0,0 +1,33 @@ +packer { + required_plugins { + amazon = { + version = ">= 0.0.1" + source = "github.com/hashicorp/amazon" + } + } +} + +data "amazon-ami" "test" { + filters = { + name = "ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*" + root-device-type = "ebs" + virtualization-type = "hvm" + } + most_recent = true + owners = ["099720109477"] +} + +source "amazon-ebs" "basic-example" { + region = "us-west-2" + source_ami = data.amazon-ami.test.id + ami_name = "packer-amazon-ami-test" + communicator = "ssh" + instance_type = "t2.micro" + ssh_username = "ubuntu" +} + +build { + sources = [ + "source.amazon-ebs.basic-example" + ] +} diff --git a/acctest/plugin/test-fixtures/basic-amazon-ebs.pkr.hcl b/acctest/plugin/test-fixtures/basic-amazon-ebs.pkr.hcl new file mode 100644 index 000000000..aa9399a92 --- /dev/null +++ b/acctest/plugin/test-fixtures/basic-amazon-ebs.pkr.hcl @@ -0,0 +1,20 @@ +packer { + required_plugins { + amazon = { + version = ">= 0.0.1" + source = "github.com/hashicorp/amazon" + } + } +} + +source "amazon-ebs" "basic-test" { + region = "us-east-1" + instance_type = "m3.medium" + source_ami = "ami-76b2a71e" + ssh_username = "ubuntu" + ami_name = "packer-plugin-amazon-ebs-test" +} + +build { + sources = ["source.amazon-ebs.basic-test"] +} diff --git a/go.mod b/go.mod index 42f9d9c05..150b47b92 100644 --- a/go.mod +++ b/go.mod @@ -51,7 +51,7 @@ require ( github.com/hashicorp/hcl/v2 v2.9.1 github.com/hashicorp/packer-plugin-amazon v0.0.1 github.com/hashicorp/packer-plugin-docker v0.0.7 - github.com/hashicorp/packer-plugin-sdk v0.1.3-0.20210407090040-d1eff9fe99e8 + github.com/hashicorp/packer-plugin-sdk v0.1.3-0.20210407132324-af39c7839daf github.com/hashicorp/vault/api v1.0.4 github.com/hetznercloud/hcloud-go v1.15.1 github.com/hyperonecom/h1-client-go v0.0.0-20191203060043-b46280e4c4a4 diff --git a/go.sum b/go.sum index 49bf46a4c..0eea065a0 100644 --- a/go.sum +++ b/go.sum @@ -443,10 +443,15 @@ github.com/hashicorp/packer-plugin-sdk v0.0.12/go.mod h1:hs82OYeufirGG6KRENMpjBW github.com/hashicorp/packer-plugin-sdk v0.0.14/go.mod h1:tNb3XzJPnjMl3QuUdKmF47B5ImerdTakalHzUAvW0aw= github.com/hashicorp/packer-plugin-sdk v0.1.0/go.mod h1:CFsC20uZjtER/EnTn/CSMKD0kEdkqOVev8mtOmfnZiI= github.com/hashicorp/packer-plugin-sdk v0.1.1/go.mod h1:1d3nqB9LUsXMQaNUiL67Q+WYEtjsVcLNTX8ikVlpBrc= -github.com/hashicorp/packer-plugin-sdk v0.1.2 h1:R/WKJw6BDwvjbcKeC3mZs+wSmdFHE8iK+qz+QnArPQk= github.com/hashicorp/packer-plugin-sdk v0.1.2/go.mod h1:KRjczE1/c9NV5Re+PXt3myJsVTI/FxEHpZjRjOH0Fug= github.com/hashicorp/packer-plugin-sdk v0.1.3-0.20210407090040-d1eff9fe99e8 h1:pkB+Y15/ck/NRUBFF9DrdPYQwmnHsEvnNwmgMfl/8hA= github.com/hashicorp/packer-plugin-sdk v0.1.3-0.20210407090040-d1eff9fe99e8/go.mod h1:xePpgQgQYv/bamiypx3hH9ukidxDdcN8q0R0wLi8IEQ= +github.com/hashicorp/packer-plugin-sdk v0.1.3-0.20210407130359-85b84b1d6060 h1:uRrDQYiP3pFn5W17Bvj9If2taHB/DqIP7uuPQGnLDFM= +github.com/hashicorp/packer-plugin-sdk v0.1.3-0.20210407130359-85b84b1d6060/go.mod h1:xePpgQgQYv/bamiypx3hH9ukidxDdcN8q0R0wLi8IEQ= +github.com/hashicorp/packer-plugin-sdk v0.1.3-0.20210407130906-826d4f395a10 h1:VlcHJEpR99eeZi7uujdQKFOIK8rE5ditXGqpBWiGjc4= +github.com/hashicorp/packer-plugin-sdk v0.1.3-0.20210407130906-826d4f395a10/go.mod h1:xePpgQgQYv/bamiypx3hH9ukidxDdcN8q0R0wLi8IEQ= +github.com/hashicorp/packer-plugin-sdk v0.1.3-0.20210407132324-af39c7839daf h1:0DBlIExTDefzbfkOl213QtgJsVJXWdgW/aIQIvYUMzs= +github.com/hashicorp/packer-plugin-sdk v0.1.3-0.20210407132324-af39c7839daf/go.mod h1:xePpgQgQYv/bamiypx3hH9ukidxDdcN8q0R0wLi8IEQ= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.9.2 h1:yJoyfZXo4Pk2p/M/viW+YLibBFiIbKoP79gu7kDAFP0= github.com/hashicorp/serf v0.9.2/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= diff --git a/vendor/github.com/hashicorp/packer-plugin-amazon/builder/ebs/acceptance/aws.go b/vendor/github.com/hashicorp/packer-plugin-amazon/builder/ebs/acceptance/aws.go new file mode 100644 index 000000000..bcf13df0c --- /dev/null +++ b/vendor/github.com/hashicorp/packer-plugin-amazon/builder/ebs/acceptance/aws.go @@ -0,0 +1,46 @@ +package amazon_acc + +import ( + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ec2" + awscommon "github.com/hashicorp/packer-plugin-amazon/builder/common" +) + +type AWSHelper struct { + Region string + AMIName string +} + +func (a *AWSHelper) CleanUpAmi() error { + accessConfig := &awscommon.AccessConfig{} + session, err := accessConfig.Session() + if err != nil { + return fmt.Errorf("AWSAMICleanUp: Unable to create aws session %s", err.Error()) + } + + regionconn := ec2.New(session.Copy(&aws.Config{ + Region: aws.String(a.Region), + })) + + resp, err := regionconn.DescribeImages(&ec2.DescribeImagesInput{ + Owners: aws.StringSlice([]string{"self"}), + Filters: []*ec2.Filter{{ + Name: aws.String("name"), + Values: aws.StringSlice([]string{a.AMIName}), + }}}) + if err != nil { + return fmt.Errorf("AWSAMICleanUp: Unable to find Image %s: %s", a.AMIName, err.Error()) + } + + if resp != nil && len(resp.Images) > 0 { + _, err = regionconn.DeregisterImage(&ec2.DeregisterImageInput{ + ImageId: resp.Images[0].ImageId, + }) + if err != nil { + return fmt.Errorf("AWSAMICleanUp: Unable to Deregister Image %s", err.Error()) + } + } + return nil +} diff --git a/vendor/github.com/hashicorp/packer-plugin-amazon/builder/ebs/acceptance/builder_acceptance.go b/vendor/github.com/hashicorp/packer-plugin-amazon/builder/ebs/acceptance/builder_acceptance.go new file mode 100644 index 000000000..25fdb13d8 --- /dev/null +++ b/vendor/github.com/hashicorp/packer-plugin-amazon/builder/ebs/acceptance/builder_acceptance.go @@ -0,0 +1,58 @@ +package amazon_acc + +// This is the code necessary for running the provisioner acceptance tests. +// It provides the builder config and cleans up created resource. + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + + amazonebsbuilder "github.com/hashicorp/packer-plugin-amazon/builder/ebs" + packersdk "github.com/hashicorp/packer-plugin-sdk/packer" +) + +type AmazonEBSAccTest struct{} + +func (s *AmazonEBSAccTest) GetConfigs() (map[string]string, error) { + fixtures := map[string]string{ + "linux": "amazon-ebs.txt", + "windows": "amazon-ebs_windows.txt", + } + + configs := make(map[string]string) + + for distro, fixture := range fixtures { + fileName := fixture + filePath := filepath.Join("../../builder/amazon/ebs/acceptance/test-fixtures/", fileName) + config, err := os.Open(filePath) + if err != nil { + return nil, fmt.Errorf("Expected to find %s", filePath) + } + defer config.Close() + + file, err := ioutil.ReadAll(config) + if err != nil { + return nil, fmt.Errorf("Unable to read %s", filePath) + } + + configs[distro] = string(file) + + } + return configs, nil +} + +func (s *AmazonEBSAccTest) CleanUp() error { + helper := AWSHelper{ + Region: "us-east-1", + AMIName: "packer-acc-test", + } + return helper.CleanUpAmi() +} + +func (s *AmazonEBSAccTest) GetBuilderStore() packersdk.MapOfBuilder { + return packersdk.MapOfBuilder{ + "amazon-ebs": func() (packersdk.Builder, error) { return &amazonebsbuilder.Builder{}, nil }, + } +} diff --git a/vendor/github.com/hashicorp/packer-plugin-sdk/acctest/pluginacc.go b/vendor/github.com/hashicorp/packer-plugin-sdk/acctest/pluginacc.go index 94e2377f8..f6488b130 100644 --- a/vendor/github.com/hashicorp/packer-plugin-sdk/acctest/pluginacc.go +++ b/vendor/github.com/hashicorp/packer-plugin-sdk/acctest/pluginacc.go @@ -18,9 +18,16 @@ const TestEnvVar = "PACKER_ACC" // A PluginTestCase should generally map 1:1 to each test method for your // acceptance tests. // Requirements: -// - The plugin to be tested must be previously installed so that Packer can discover it. -// - Packer must also be installed +// - If not using 'packer init', the plugin must be previously installed +// - Packer must be installed locally type PluginTestCase struct { + // Init, if true `packer init` will be executed prior to `packer build`. + Init bool + // CheckInit is called after packer init step is executed in order to test that + // the step executed successfully. If this is not set, then the next + // step will be called + CheckInit func(*exec.Cmd, string) error + // Check is called after this step is executed in order to test that // the step executed successfully. If this is not set, then the next // step will be called @@ -89,6 +96,28 @@ func TestPlugin(t *testing.T, testCase *PluginTestCase) { if err != nil { t.Fatalf("Couldn't find packer binary installed on system: %s", err.Error()) } + + if testCase.Init { + initLogfile := fmt.Sprintf("packer_init_log_%s.txt", testCase.Name) + initCommand := exec.Command(packerbin, "init", templatePath) + initCommand.Env = append(initCommand.Env, os.Environ()...) + initCommand.Env = append(initCommand.Env, "PACKER_LOG=1", fmt.Sprintf("PACKER_LOG_PATH=%s", initLogfile)) + initCommand.Run() + + if testCase.CheckInit != nil { + if err := testCase.CheckInit(initCommand, initLogfile); err != nil { + cwd, _ := os.Getwd() + t.Fatalf(fmt.Sprintf("Error running plugin acceptance"+ + " tests: %s\nLogs can be found at %s\nand the "+ + "acceptance test template can be found at %s", + err.Error(), filepath.Join(cwd, initLogfile), + filepath.Join(cwd, templatePath))) + } else { + os.Remove(initLogfile) + } + } + } + // Run build buildCommand := exec.Command(packerbin, "build", "--machine-readable", templatePath) buildCommand.Env = append(buildCommand.Env, os.Environ()...) diff --git a/vendor/modules.txt b/vendor/modules.txt index 341bddb9b..8702f258b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -498,6 +498,7 @@ github.com/hashicorp/packer-plugin-amazon/builder/common github.com/hashicorp/packer-plugin-amazon/builder/common/awserrors github.com/hashicorp/packer-plugin-amazon/builder/common/ssm github.com/hashicorp/packer-plugin-amazon/builder/ebs +github.com/hashicorp/packer-plugin-amazon/builder/ebs/acceptance github.com/hashicorp/packer-plugin-amazon/builder/ebssurrogate github.com/hashicorp/packer-plugin-amazon/builder/ebsvolume github.com/hashicorp/packer-plugin-amazon/builder/instance @@ -511,7 +512,7 @@ github.com/hashicorp/packer-plugin-docker/post-processor/docker-import github.com/hashicorp/packer-plugin-docker/post-processor/docker-push github.com/hashicorp/packer-plugin-docker/post-processor/docker-save github.com/hashicorp/packer-plugin-docker/post-processor/docker-tag -# github.com/hashicorp/packer-plugin-sdk v0.1.3-0.20210407090040-d1eff9fe99e8 +# github.com/hashicorp/packer-plugin-sdk v0.1.3-0.20210407132324-af39c7839daf ## explicit github.com/hashicorp/packer-plugin-sdk/acctest github.com/hashicorp/packer-plugin-sdk/acctest/provisioneracc