Compare commits

..

2 Commits

Author SHA1 Message Date
Wilken Rivera fd3cc596c7 The original approach of running version, but that seems to bypass wrappedMain entirely 2021-04-05 16:06:41 -04:00
Wilken Rivera 708f9cdfbd Add example test to validate correct output 2021-04-05 16:01:01 -04:00
836 changed files with 5987 additions and 108021 deletions
+1 -15
View File
@@ -1,18 +1,4 @@
## 1.7.3 (Upcoming)
## 1.7.2 (April 05, 2021)
### IMPROVEMENTS:
* builder/alicloud: Add `ramrole` configuration to ECS instance. [GH-10845]
### BUG FIXES:
* builder/proxmox: Update Proxmox Go API to ensure only the first non-loopback
IPv4 address gets returned. [GH-10858]
* builder/vsphere: Fix primary disk resize on clone. [GH-10848]
* core: Fix bug where call to "packer version" sent output to stderr instead of
stdout. [GH-10850]
## 1.7.2 (Upcoming)
## 1.7.1 (March 31, 2021)
-71
View File
@@ -1,71 +0,0 @@
// 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)
}
-112
View File
@@ -1,112 +0,0 @@
// 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
}
@@ -1,33 +0,0 @@
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"
]
}
@@ -1,20 +0,0 @@
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"]
}
-72
View File
@@ -1,72 +0,0 @@
package acctest
import (
"os"
"testing"
)
func init() {
testTesting = true
if err := os.Setenv(TestEnvVar, "1"); err != nil {
panic(err)
}
}
func TestTest_noEnv(t *testing.T) {
// Unset the variable
if err := os.Setenv(TestEnvVar, ""); err != nil {
t.Fatalf("err: %s", err)
}
defer os.Setenv(TestEnvVar, "1")
mt := new(mockT)
Test(mt, TestCase{})
if !mt.SkipCalled {
t.Fatal("skip not called")
}
}
func TestTest_preCheck(t *testing.T) {
called := false
mt := new(mockT)
Test(mt, TestCase{
PreCheck: func() { called = true },
})
if !called {
t.Fatal("precheck should be called")
}
}
// mockT implements TestT for testing
type mockT struct {
ErrorCalled bool
ErrorArgs []interface{}
FatalCalled bool
FatalArgs []interface{}
SkipCalled bool
SkipArgs []interface{}
f bool
}
func (t *mockT) Error(args ...interface{}) {
t.ErrorCalled = true
t.ErrorArgs = args
t.f = true
}
func (t *mockT) Fatal(args ...interface{}) {
t.FatalCalled = true
t.FatalArgs = args
t.f = true
}
func (t *mockT) Skip(args ...interface{}) {
t.SkipCalled = true
t.SkipArgs = args
t.f = true
}
-1
View File
@@ -135,7 +135,6 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
InstanceType: b.config.InstanceType,
UserData: b.config.UserData,
UserDataFile: b.config.UserDataFile,
RamRoleName: b.config.RamRoleName,
RegionId: b.config.AlicloudRegion,
InternetChargeType: b.config.InternetChargeType,
InternetMaxBandwidthOut: b.config.InternetMaxBandwidthOut,
-2
View File
@@ -88,7 +88,6 @@ type FlatConfig struct {
AlicloudSourceImage *string `mapstructure:"source_image" required:"true" cty:"source_image" hcl:"source_image"`
ForceStopInstance *bool `mapstructure:"force_stop_instance" required:"false" cty:"force_stop_instance" hcl:"force_stop_instance"`
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance" hcl:"disable_stop_instance"`
RamRoleName *string `mapstructure:"ram_role_name" required:"false" cty:"ram_role_name" hcl:"ram_role_name"`
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id" hcl:"security_group_id"`
SecurityGroupName *string `mapstructure:"security_group_name" required:"false" cty:"security_group_name" hcl:"security_group_name"`
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data" hcl:"user_data"`
@@ -206,7 +205,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"source_image": &hcldec.AttrSpec{Name: "source_image", Type: cty.String, Required: false},
"force_stop_instance": &hcldec.AttrSpec{Name: "force_stop_instance", Type: cty.Bool, Required: false},
"disable_stop_instance": &hcldec.AttrSpec{Name: "disable_stop_instance", Type: cty.Bool, Required: false},
"ram_role_name": &hcldec.AttrSpec{Name: "ram_role_name", Type: cty.String, Required: false},
"security_group_id": &hcldec.AttrSpec{Name: "security_group_id", Type: cty.String, Required: false},
"security_group_name": &hcldec.AttrSpec{Name: "security_group_name", Type: cty.String, Required: false},
"user_data": &hcldec.AttrSpec{Name: "user_data", Type: cty.String, Required: false},
+1 -1
View File
@@ -8,8 +8,8 @@ import (
"testing"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
builderT "github.com/hashicorp/packer/acctest"
)
const defaultTestRegion = "cn-beijing"
-2
View File
@@ -47,8 +47,6 @@ type RunConfig struct {
// E.g., Sysprep a windows which may shutdown the instance within its command.
// The default value is false.
DisableStopInstance bool `mapstructure:"disable_stop_instance" required:"false"`
// Ram Role to apply when launching the instance.
RamRoleName string `mapstructure:"ram_role_name" required:"false"`
// ID of the security group to which a newly
// created instance belongs. Mutual access is allowed between instances in one
// security group. If not specified, the newly created instance will be added
@@ -23,7 +23,6 @@ type stepCreateAlicloudInstance struct {
UserData string
UserDataFile string
instanceId string
RamRoleName string
RegionId string
InternetChargeType string
InternetMaxBandwidthOut int
@@ -116,7 +115,6 @@ func (s *stepCreateAlicloudInstance) buildCreateInstanceRequest(state multistep.
request.RegionId = s.RegionId
request.InstanceType = s.InstanceType
request.InstanceName = s.InstanceName
request.RamRoleName = s.RamRoleName
request.ZoneId = s.ZoneId
sourceImage := state.Get("source_image").(*ecs.Image)
+1 -1
View File
@@ -30,8 +30,8 @@ import (
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure/auth"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
builderT "github.com/hashicorp/packer/acctest"
)
const DeviceLoginAcceptanceTest = "DEVICELOGIN_TEST"
+1
View File
@@ -181,6 +181,7 @@ func NewAzureClient(subscriptionID, resourceGroupName string,
azureClient.GalleryImageVersionsClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.GalleryImageVersionsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.GalleryImageVersionsClient.UserAgent)
azureClient.GalleryImageVersionsClient.Client.PollingDuration = SharedGalleryTimeout
azureClient.GalleryImageVersionsClient.Client.PollingDuration = PollingDuration
azureClient.GalleryImagesClient = newCompute.NewGalleryImagesClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
azureClient.GalleryImagesClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
+1 -1
View File
@@ -28,7 +28,7 @@ package dtl
import (
"testing"
builderT "github.com/hashicorp/packer/acctest"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
)
const DeviceLoginAcceptanceTest = "DEVICELOGIN_TEST"
+3 -10
View File
@@ -80,17 +80,10 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
// Build the steps
steps := []multistep.Step{
&communicator.StepSSHKeyGen{
CommConf: &b.config.Comm,
SSHTemporaryKeyPair: b.config.Comm.SSH.SSHTemporaryKeyPair,
&stepCreateSSHKey{
Debug: b.config.PackerDebug,
DebugKeyPath: fmt.Sprintf("do_%s.pem", b.config.PackerBuildName),
},
multistep.If(b.config.PackerDebug && b.config.Comm.SSHPrivateKeyFile == "",
&communicator.StepDumpSSHKey{
Path: fmt.Sprintf("do_%s.pem", b.config.PackerBuildName),
SSH: &b.config.Comm.SSH,
},
),
&stepCreateSSHKey{},
new(stepCreateDroplet),
new(stepDropletInfo),
&communicator.StepConnect{
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"testing"
"github.com/digitalocean/godo"
builderT "github.com/hashicorp/packer/acctest"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
"golang.org/x/oauth2"
)
+59 -5
View File
@@ -2,16 +2,26 @@ package digitalocean
import (
"context"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"log"
"os"
"runtime"
"github.com/digitalocean/godo"
"github.com/hashicorp/packer-plugin-sdk/multistep"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer-plugin-sdk/uuid"
"golang.org/x/crypto/ssh"
)
type stepCreateSSHKey struct {
Debug bool
DebugKeyPath string
keyId int
}
@@ -20,12 +30,31 @@ func (s *stepCreateSSHKey) Run(ctx context.Context, state multistep.StateBag) mu
ui := state.Get("ui").(packersdk.Ui)
c := state.Get("config").(*Config)
if c.Comm.SSHPublicKey == nil {
ui.Say("No public SSH key found; skipping SSH public key import...")
return multistep.ActionContinue
ui.Say("Creating temporary ssh key for droplet...")
priv, err := rsa.GenerateKey(rand.Reader, 2014)
if err != nil {
err := fmt.Errorf("error generating RSA key: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
ui.Say("Importing SSH public key...")
// ASN.1 DER encoded form
priv_der := x509.MarshalPKCS1PrivateKey(priv)
priv_blk := pem.Block{
Type: "RSA PRIVATE KEY",
Headers: nil,
Bytes: priv_der,
}
// Set the private key in the config for later
c.Comm.SSHPrivateKey = pem.EncodeToMemory(&priv_blk)
// Marshal the public key into SSH compatible format
// TODO properly handle the public key error
pub, _ := ssh.NewPublicKey(&priv.PublicKey)
pub_sshformat := string(ssh.MarshalAuthorizedKey(pub))
// The name of the public key on DO
name := fmt.Sprintf("packer-%s", uuid.TimeOrderedUUID())
@@ -33,7 +62,7 @@ func (s *stepCreateSSHKey) Run(ctx context.Context, state multistep.StateBag) mu
// Create the key!
key, _, err := client.Keys.Create(context.TODO(), &godo.KeyCreateRequest{
Name: name,
PublicKey: string(c.Comm.SSHPublicKey),
PublicKey: pub_sshformat,
})
if err != nil {
err := fmt.Errorf("Error creating temporary SSH key: %s", err)
@@ -50,6 +79,31 @@ func (s *stepCreateSSHKey) Run(ctx context.Context, state multistep.StateBag) mu
// Remember some state for the future
state.Put("ssh_key_id", key.ID)
// If we're in debug mode, output the private key to the working directory.
if s.Debug {
ui.Message(fmt.Sprintf("Saving key for debug purposes: %s", s.DebugKeyPath))
f, err := os.Create(s.DebugKeyPath)
if err != nil {
state.Put("error", fmt.Errorf("Error saving debug key: %s", err))
return multistep.ActionHalt
}
defer f.Close()
// Write the key out
if _, err := f.Write(pem.EncodeToMemory(&priv_blk)); err != nil {
state.Put("error", fmt.Errorf("Error saving debug key: %s", err))
return multistep.ActionHalt
}
// Chmod it so that it is SSH ready
if runtime.GOOS != "windows" {
if err := f.Chmod(0600); err != nil {
state.Put("error", fmt.Errorf("Error setting permissions of debug key: %s", err))
return multistep.ActionHalt
}
}
}
return multistep.ActionContinue
}
+1 -1
View File
@@ -5,8 +5,8 @@ import (
"io/ioutil"
"testing"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
builderT "github.com/hashicorp/packer/acctest"
)
func TestBuilder_implBuilder(t *testing.T) {
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"os"
"testing"
builderT "github.com/hashicorp/packer/acctest"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
)
func TestBuilderAcc_basic(t *testing.T) {
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"os"
"testing"
builderT "github.com/hashicorp/packer/acctest"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
)
func TestBuilderAcc_basic(t *testing.T) {
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"os"
"testing"
builderT "github.com/hashicorp/packer/acctest"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
)
func TestBuilderAcc_basic(t *testing.T) {
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"os"
"testing"
builderT "github.com/hashicorp/packer/acctest"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
)
func TestBuilderAcc_basic(t *testing.T) {
+1 -1
View File
@@ -4,7 +4,7 @@ package bsu
import (
"testing"
builderT "github.com/hashicorp/packer/acctest"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
)
func TestBuilderAcc_basic(t *testing.T) {
+1 -1
View File
@@ -3,7 +3,7 @@ package bsusurrogate
import (
"testing"
builderT "github.com/hashicorp/packer/acctest"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
)
func TestBuilderAcc_basic(t *testing.T) {
+1 -1
View File
@@ -4,7 +4,7 @@ package bsuvolume
import (
"testing"
builderT "github.com/hashicorp/packer/acctest"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
)
func TestBuilderAcc_basic(t *testing.T) {
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"os"
"testing"
builderT "github.com/hashicorp/packer/acctest"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
)
func TestBuilderAcc_basic(t *testing.T) {
-3
View File
@@ -158,9 +158,6 @@ func getVMIP(state multistep.StateBag) (string, error) {
if addr.IsLoopback() {
continue
}
if addr.To4() == nil {
continue
}
return addr.String(), nil
}
}
+2 -1
View File
@@ -6,9 +6,10 @@ import (
"testing"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
builderT "github.com/hashicorp/packer/acctest"
ucloudcommon "github.com/hashicorp/packer/builder/ucloud/common"
"github.com/stretchr/testify/assert"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
)
func TestBuilderAcc_validateRegion(t *testing.T) {
+72
View File
@@ -0,0 +1,72 @@
package vagrant
import (
"runtime"
"strings"
"testing"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
)
func TestArtifact_Impl(t *testing.T) {
var raw interface{} = &artifact{}
if _, ok := raw.(packersdk.Artifact); !ok {
t.Fatalf("Artifact does not implement packersdk.Artifact")
}
}
func TestArtifactId(t *testing.T) {
a := &artifact{
OutputDir: "/my/dir",
BoxName: "package.box",
Provider: "virtualbox",
}
expected := "virtualbox"
if a.Id() != expected {
t.Fatalf("artifact ID should match: expected: %s received: %s", expected, a.Id())
}
}
func TestArtifactString(t *testing.T) {
a := &artifact{
OutputDir: "/my/dir",
BoxName: "package.box",
Provider: "virtualbox",
}
expected := "Vagrant box 'package.box' for 'virtualbox' provider"
if runtime.GOOS == "windows" {
expected = strings.Replace(expected, "/", "\\", -1)
}
if strings.Compare(a.String(), expected) != 0 {
t.Fatalf("artifact string should match: expected: %s received: %s", expected, a.String())
}
}
func TestArtifactState(t *testing.T) {
expectedData := "this is the data"
a := &artifact{
StateData: map[string]interface{}{"state_data": expectedData},
}
// Valid state
result := a.State("state_data")
if result != expectedData {
t.Fatalf("Bad: State data was %s instead of %s", result, expectedData)
}
// Invalid state
result = a.State("invalid_key")
if result != nil {
t.Fatalf("Bad: State should be nil for invalid state data name")
}
// Nil StateData should not fail and should return nil
a = &artifact{}
result = a.State("key")
if result != nil {
t.Fatalf("Bad: State should be nil for nil StateData")
}
}
+130
View File
@@ -0,0 +1,130 @@
package vagrant
import (
"testing"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
)
func TestBuilder_ImplementsBuilder(t *testing.T) {
var raw interface{}
raw = &Builder{}
if _, ok := raw.(packersdk.Builder); !ok {
t.Fatalf("Builder should be a builder")
}
}
func TestBuilder_Prepare_ValidateSource(t *testing.T) {
type testCase struct {
config map[string]interface{}
errExpected bool
reason string
}
cases := []testCase{
{
config: map[string]interface{}{
"global_id": "a3559ec",
},
errExpected: true,
reason: "Need to set SSH communicator.",
},
{
config: map[string]interface{}{
"global_id": "a3559ec",
"communicator": "ssh",
},
errExpected: false,
reason: "Shouldn't fail because we've set global_id",
},
{
config: map[string]interface{}{
"communicator": "ssh",
},
errExpected: true,
reason: "Should fail because we must set source_path or global_id",
},
{
config: map[string]interface{}{
"source_path": "./mybox",
"communicator": "ssh",
},
errExpected: false,
reason: "Source path is set; we should be fine",
},
{
config: map[string]interface{}{
"source_path": "./mybox",
"communicator": "ssh",
"global_id": "a3559ec",
},
errExpected: true,
reason: "Both source path and global are set: we should error.",
},
{
config: map[string]interface{}{
"communicator": "ssh",
"global_id": "a3559ec",
"teardown_method": "suspend",
},
errExpected: false,
reason: "Valid argument for teardown method",
},
{
config: map[string]interface{}{
"communicator": "ssh",
"global_id": "a3559ec",
"teardown_method": "surspernd",
},
errExpected: true,
reason: "Inalid argument for teardown method",
},
{
config: map[string]interface{}{
"communicator": "ssh",
"source_path": "./my.box",
},
errExpected: true,
reason: "Should fail because path does not exist",
},
{
config: map[string]interface{}{
"communicator": "ssh",
"source_path": "file://my.box",
},
errExpected: true,
reason: "Should fail because path does not exist",
},
{
config: map[string]interface{}{
"communicator": "ssh",
"source_path": "http://my.box",
},
errExpected: false,
reason: "Should pass because path is not local",
},
{
config: map[string]interface{}{
"communicator": "ssh",
"source_path": "https://my.box",
},
errExpected: false,
reason: "Should pass because path is not local",
},
{
config: map[string]interface{}{
"communicator": "ssh",
"source_path": "smb://my.box",
},
errExpected: false,
reason: "Should pass because path is not local",
},
}
for _, tc := range cases {
_, _, err := (&Builder{}).Prepare(tc.config)
if (err != nil) != tc.errExpected {
t.Fatalf("Unexpected behavior from test case %#v; %s.", tc.config, tc.reason)
}
}
}
+62
View File
@@ -0,0 +1,62 @@
package vagrant
import (
"strings"
"testing"
"github.com/hashicorp/packer-plugin-sdk/multistep"
)
func TestStepAdd_Impl(t *testing.T) {
var raw interface{}
raw = new(StepAddBox)
if _, ok := raw.(multistep.Step); !ok {
t.Fatalf("initialize should be a step")
}
}
func TestPrepAddArgs(t *testing.T) {
type testArgs struct {
Step StepAddBox
Expected []string
}
addTests := []testArgs{
{
Step: StepAddBox{
SourceBox: "my_source_box.box",
BoxName: "AWESOME BOX",
},
Expected: []string{"AWESOME BOX", "my_source_box.box"},
},
{
Step: StepAddBox{
SourceBox: "my_source_box",
BoxName: "AWESOME BOX",
},
Expected: []string{"my_source_box"},
},
{
Step: StepAddBox{
BoxVersion: "eleventyone",
CACert: "adfasdf",
CAPath: "adfasdf",
DownloadCert: "adfasdf",
Clean: true,
Force: true,
Insecure: true,
Provider: "virtualbox",
SourceBox: "bananabox.box",
BoxName: "bananas",
},
Expected: []string{"bananas", "bananabox.box", "--box-version", "eleventyone", "--cacert", "adfasdf", "--capath", "adfasdf", "--cert", "adfasdf", "--clean", "--force", "--insecure", "--provider", "virtualbox"},
},
}
for _, addTest := range addTests {
addArgs := addTest.Step.generateAddArgs()
for i, val := range addTest.Expected {
if strings.Compare(addArgs[i], val) != 0 {
t.Fatalf("expected %#v but received %#v", addTest.Expected, addArgs)
}
}
}
}
@@ -0,0 +1,115 @@
package vagrant
import (
"io/ioutil"
"os"
"strings"
"testing"
"github.com/hashicorp/packer-plugin-sdk/multistep"
)
func TestStepCreateVagrantfile_Impl(t *testing.T) {
var raw interface{}
raw = new(StepCreateVagrantfile)
if _, ok := raw.(multistep.Step); !ok {
t.Fatalf("initialize should be a step")
}
}
func TestCreateFile(t *testing.T) {
testy := StepCreateVagrantfile{
OutputDir: "./",
SourceBox: "apples",
BoxName: "bananas",
}
templatePath, err := testy.createVagrantfile()
if err != nil {
t.Fatalf(err.Error())
}
defer os.Remove(templatePath)
contents, err := ioutil.ReadFile(templatePath)
if err != nil {
t.Fatalf(err.Error())
}
actual := string(contents)
expected := `Vagrant.configure("2") do |config|
config.vm.define "source", autostart: false do |source|
source.vm.box = "apples"
config.ssh.insert_key = false
end
config.vm.define "output" do |output|
output.vm.box = "bananas"
output.vm.box_url = "file://package.box"
config.ssh.insert_key = false
end
config.vm.synced_folder ".", "/vagrant", disabled: true
end`
if ok := strings.Compare(actual, expected); ok != 0 {
t.Fatalf("EXPECTED: \n%s\n\n RECEIVED: \n%s\n\n", expected, actual)
}
}
func TestCreateFile_customSync(t *testing.T) {
testy := StepCreateVagrantfile{
OutputDir: "./",
SyncedFolder: "myfolder/foldertimes",
}
templatePath, err := testy.createVagrantfile()
if err != nil {
t.Fatalf(err.Error())
}
defer os.Remove(templatePath)
contents, err := ioutil.ReadFile(templatePath)
if err != nil {
t.Fatalf(err.Error())
}
actual := string(contents)
expected := `Vagrant.configure("2") do |config|
config.vm.define "source", autostart: false do |source|
source.vm.box = ""
config.ssh.insert_key = false
end
config.vm.define "output" do |output|
output.vm.box = ""
output.vm.box_url = "file://package.box"
config.ssh.insert_key = false
end
config.vm.synced_folder "myfolder/foldertimes", "/vagrant"
end`
if ok := strings.Compare(actual, expected); ok != 0 {
t.Fatalf("EXPECTED: \n%s\n\n RECEIVED: \n%s\n\n", expected, actual)
}
}
func TestCreateFile_InsertKeyTrue(t *testing.T) {
testy := StepCreateVagrantfile{
OutputDir: "./",
InsertKey: true,
}
templatePath, err := testy.createVagrantfile()
if err != nil {
t.Fatalf(err.Error())
}
defer os.Remove(templatePath)
contents, err := ioutil.ReadFile(templatePath)
if err != nil {
t.Fatalf(err.Error())
}
actual := string(contents)
expected := `Vagrant.configure("2") do |config|
config.vm.define "source", autostart: false do |source|
source.vm.box = ""
config.ssh.insert_key = true
end
config.vm.define "output" do |output|
output.vm.box = ""
output.vm.box_url = "file://package.box"
config.ssh.insert_key = true
end
config.vm.synced_folder ".", "/vagrant", disabled: true
end`
if ok := strings.Compare(actual, expected); ok != 0 {
t.Fatalf("EXPECTED: \n%s\n\n RECEIVED: \n%s\n\n", expected, actual)
}
}
+176
View File
@@ -0,0 +1,176 @@
package vagrant
import (
"context"
"testing"
"github.com/hashicorp/packer-plugin-sdk/communicator"
"github.com/hashicorp/packer-plugin-sdk/multistep"
)
func TestStepSSHConfig_Impl(t *testing.T) {
var raw interface{}
raw = new(StepSSHConfig)
if _, ok := raw.(multistep.Step); !ok {
t.Fatalf("initialize should be a step")
}
}
func TestPrepStepSSHConfig_sshOverrides(t *testing.T) {
type testcase struct {
name string
inputSSHConfig communicator.SSH
expectedSSHConfig communicator.SSH
}
tcs := []testcase{
{
// defaults to overriding with the ssh config from vagrant\
name: "default",
inputSSHConfig: communicator.SSH{},
expectedSSHConfig: communicator.SSH{
SSHHost: "127.0.0.1",
SSHPort: 2222,
SSHUsername: "vagrant",
SSHPassword: "",
},
},
{
// respects SSH host and port overrides independent of credential
// overrides
name: "host_override",
inputSSHConfig: communicator.SSH{
SSHHost: "123.45.67.8",
SSHPort: 1234,
},
expectedSSHConfig: communicator.SSH{
SSHHost: "123.45.67.8",
SSHPort: 1234,
SSHUsername: "vagrant",
SSHPassword: "",
},
},
{
// respects credential overrides
name: "credential_override",
inputSSHConfig: communicator.SSH{
SSHUsername: "megan",
SSHPassword: "SoSecure",
},
expectedSSHConfig: communicator.SSH{
SSHHost: "127.0.0.1",
SSHPort: 2222,
SSHUsername: "megan",
SSHPassword: "SoSecure",
},
},
}
for _, tc := range tcs {
driver := &MockVagrantDriver{}
config := &Config{
Comm: communicator.Config{
SSH: tc.inputSSHConfig,
},
}
state := new(multistep.BasicStateBag)
state.Put("driver", driver)
state.Put("config", config)
step := StepSSHConfig{}
_ = step.Run(context.Background(), state)
if config.Comm.SSHHost != tc.expectedSSHConfig.SSHHost {
t.Fatalf("unexpected sshconfig host: name: %s, recieved %s", tc.name, config.Comm.SSHHost)
}
if config.Comm.SSHPort != tc.expectedSSHConfig.SSHPort {
t.Fatalf("unexpected sshconfig port: name: %s, recieved %d", tc.name, config.Comm.SSHPort)
}
if config.Comm.SSHUsername != tc.expectedSSHConfig.SSHUsername {
t.Fatalf("unexpected sshconfig SSHUsername: name: %s, recieved %s", tc.name, config.Comm.SSHUsername)
}
if config.Comm.SSHPassword != tc.expectedSSHConfig.SSHPassword {
t.Fatalf("unexpected sshconfig SSHUsername: name: %s, recieved %s", tc.name, config.Comm.SSHPassword)
}
}
}
func TestPrepStepSSHConfig_GlobalID(t *testing.T) {
driver := &MockVagrantDriver{}
config := &Config{}
state := new(multistep.BasicStateBag)
state.Put("driver", driver)
state.Put("config", config)
step := StepSSHConfig{
GlobalID: "adsfadf",
}
_ = step.Run(context.Background(), state)
if driver.GlobalID != "adsfadf" {
t.Fatalf("Should have called SSHConfig with GlobalID asdfasdf")
}
}
func TestPrepStepSSHConfig_NoGlobalID(t *testing.T) {
driver := &MockVagrantDriver{}
config := &Config{}
state := new(multistep.BasicStateBag)
state.Put("driver", driver)
state.Put("config", config)
step := StepSSHConfig{}
_ = step.Run(context.Background(), state)
if driver.GlobalID != "source" {
t.Fatalf("Should have called SSHConfig with GlobalID source")
}
}
func TestPrepStepSSHConfig_SpacesInPath(t *testing.T) {
driver := &MockVagrantDriver{}
driver.ReturnSSHConfig = &VagrantSSHConfig{
Hostname: "127.0.0.1",
User: "vagrant",
Port: "2222",
UserKnownHostsFile: "/dev/null",
StrictHostKeyChecking: false,
PasswordAuthentication: false,
IdentityFile: "\"/path with spaces/insecure_private_key\"",
IdentitiesOnly: true,
LogLevel: "FATAL"}
config := &Config{}
state := new(multistep.BasicStateBag)
state.Put("driver", driver)
state.Put("config", config)
step := StepSSHConfig{}
_ = step.Run(context.Background(), state)
expected := "/path with spaces/insecure_private_key"
if config.Comm.SSHPrivateKeyFile != expected {
t.Fatalf("Bad config private key. Recieved: %s; expected: %s.", config.Comm.SSHPrivateKeyFile, expected)
}
}
func TestPrepStepSSHConfig_NoSpacesInPath(t *testing.T) {
driver := &MockVagrantDriver{}
driver.ReturnSSHConfig = &VagrantSSHConfig{
Hostname: "127.0.0.1",
User: "vagrant",
Port: "2222",
UserKnownHostsFile: "/dev/null",
StrictHostKeyChecking: false,
PasswordAuthentication: false,
IdentityFile: "/path/without/spaces/insecure_private_key",
IdentitiesOnly: true,
LogLevel: "FATAL"}
config := &Config{}
state := new(multistep.BasicStateBag)
state.Put("driver", driver)
state.Put("config", config)
step := StepSSHConfig{}
_ = step.Run(context.Background(), state)
expected := "/path/without/spaces/insecure_private_key"
if config.Comm.SSHPrivateKeyFile != expected {
t.Fatalf("Bad config private key. Recieved: %s; expected: %s.", config.Comm.SSHPrivateKeyFile, expected)
}
}
+40
View File
@@ -0,0 +1,40 @@
package vagrant
import (
"strings"
"testing"
)
func TestPrepUpArgs(t *testing.T) {
type testArgs struct {
Step StepUp
Expected []string
}
tests := []testArgs{
{
Step: StepUp{
GlobalID: "foo",
Provider: "bar",
},
Expected: []string{"foo", "--provider=bar"},
},
{
Step: StepUp{},
Expected: []string{"source"},
},
{
Step: StepUp{
Provider: "pro",
},
Expected: []string{"source", "--provider=pro"},
},
}
for _, test := range tests {
args := test.Step.generateArgs()
for i, val := range test.Expected {
if strings.Compare(args[i], val) != 0 {
t.Fatalf("expected %#v but received %#v", test.Expected, args)
}
}
}
}
+13
View File
@@ -0,0 +1,13 @@
package version
import (
"github.com/hashicorp/packer-plugin-sdk/version"
packerVersion "github.com/hashicorp/packer/version"
)
var VagrantPluginVersion *version.PluginVersion
func init() {
VagrantPluginVersion = version.InitializePluginVersion(
packerVersion.Version, packerVersion.VersionPrerelease)
}
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"path/filepath"
"testing"
builderT "github.com/hashicorp/packer/acctest"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
)
func TestBuilderAcc_basic(t *testing.T) {
+4 -24
View File
@@ -1,14 +1,11 @@
package iso
import (
"fmt"
"io/ioutil"
"os/exec"
"path/filepath"
"testing"
"github.com/hashicorp/packer-plugin-sdk/acctest"
"github.com/hashicorp/packer-plugin-sdk/acctest/testutils"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
)
func TestBuilderAcc_basic(t *testing.T) {
@@ -18,25 +15,8 @@ func TestBuilderAcc_basic(t *testing.T) {
t.Fatalf("failed to load template file %s", templatePath)
}
testCase := &acctest.PluginTestCase{
Name: "vmware-iso_builder_basic_test",
Setup: func() error {
return nil
},
Teardown: func() error {
testutils.CleanupFiles("output-vmware-iso", "packer_cache")
return nil
},
builderT.Test(t, builderT.TestCase{
Builder: &Builder{},
Template: string(bytes),
Type: "vmware-iso",
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)
})
}
+1 -1
View File
@@ -11,9 +11,9 @@ import (
"strings"
"testing"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer-plugin-sdk/tmp"
builderT "github.com/hashicorp/packer/acctest"
)
const vmxTestTemplate string = `{"builders":[{%s}],"provisioners":[{%s}]}`
+1 -1
View File
@@ -1,7 +1,7 @@
{
"builders": [
{
"type": "vmware-iso",
"type": "test",
"boot_command": [
"<esc><wait>",
"<esc><wait>",
+1 -1
View File
@@ -4,8 +4,8 @@ import (
"os"
"testing"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
builderT "github.com/hashicorp/packer/acctest"
"github.com/hashicorp/packer/builder/vsphere/common"
commonT "github.com/hashicorp/packer/builder/vsphere/common/testing"
"github.com/vmware/govmomi/vim25/types"
+20 -13
View File
@@ -75,7 +75,7 @@ type StepCloneVM struct {
func (s *StepCloneVM) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packersdk.Ui)
d := state.Get("driver").(driver.Driver)
d := state.Get("driver").(*driver.VCenterDriver)
vmPath := path.Join(s.Location.Folder, s.Location.VMName)
err := d.PreCleanVM(ui, vmPath, s.Force)
@@ -102,18 +102,17 @@ func (s *StepCloneVM) Run(ctx context.Context, state multistep.StateBag) multist
}
vm, err := template.Clone(ctx, &driver.CloneConfig{
Name: s.Location.VMName,
Folder: s.Location.Folder,
Cluster: s.Location.Cluster,
Host: s.Location.Host,
ResourcePool: s.Location.ResourcePool,
Datastore: s.Location.Datastore,
LinkedClone: s.Config.LinkedClone,
Network: s.Config.Network,
MacAddress: s.Config.MacAddress,
Annotation: s.Config.Notes,
VAppProperties: s.Config.VAppConfig.Properties,
PrimaryDiskSize: s.Config.DiskSize,
Name: s.Location.VMName,
Folder: s.Location.Folder,
Cluster: s.Location.Cluster,
Host: s.Location.Host,
ResourcePool: s.Location.ResourcePool,
Datastore: s.Location.Datastore,
LinkedClone: s.Config.LinkedClone,
Network: s.Config.Network,
MacAddress: s.Config.MacAddress,
Annotation: s.Config.Notes,
VAppProperties: s.Config.VAppConfig.Properties,
StorageConfig: driver.StorageConfig{
DiskControllerType: s.Config.StorageConfig.DiskControllerType,
Storage: disks,
@@ -128,6 +127,14 @@ func (s *StepCloneVM) Run(ctx context.Context, state multistep.StateBag) multist
}
state.Put("vm", vm)
if s.Config.DiskSize > 0 {
err = vm.ResizeDisk(s.Config.DiskSize)
if err != nil {
state.Put("error", err)
return multistep.ActionHalt
}
}
return multistep.ActionContinue
}
-251
View File
@@ -1,251 +0,0 @@
package clone
import (
"bytes"
"context"
"path"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/packer-plugin-sdk/multistep"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer/builder/vsphere/common"
"github.com/hashicorp/packer/builder/vsphere/driver"
)
func TestCreateConfig_Prepare(t *testing.T) {
tc := []struct {
name string
config *CloneConfig
fail bool
expectedErrMsg string
}{
{
name: "Valid config",
config: &CloneConfig{
Template: "template name",
StorageConfig: common.StorageConfig{
DiskControllerType: []string{"test"},
Storage: []common.DiskConfig{
{
DiskSize: 0,
},
},
},
},
fail: true,
expectedErrMsg: "storage[0].'disk_size' is required",
},
{
name: "Storage validate disk_size",
config: &CloneConfig{
StorageConfig: common.StorageConfig{
Storage: []common.DiskConfig{
{
DiskSize: 0,
DiskThinProvisioned: true,
},
},
},
},
fail: true,
expectedErrMsg: "storage[0].'disk_size' is required",
},
{
name: "Storage validate disk_controller_index",
config: &CloneConfig{
StorageConfig: common.StorageConfig{
Storage: []common.DiskConfig{
{
DiskSize: 32768,
DiskControllerIndex: 3,
},
},
},
},
fail: true,
expectedErrMsg: "storage[0].'disk_controller_index' references an unknown disk controller",
},
{
name: "Validate template is set",
config: &CloneConfig{
StorageConfig: common.StorageConfig{
DiskControllerType: []string{"test"},
Storage: []common.DiskConfig{
{
DiskSize: 32768,
},
},
},
},
fail: true,
expectedErrMsg: "'template' is required",
},
{
name: "Validate LinkedClone and DiskSize set at the same time",
config: &CloneConfig{
Template: "template name",
LinkedClone: true,
DiskSize: 32768,
StorageConfig: common.StorageConfig{
DiskControllerType: []string{"test"},
Storage: []common.DiskConfig{
{
DiskSize: 32768,
},
},
},
},
fail: true,
expectedErrMsg: "'linked_clone' and 'disk_size' cannot be used together",
},
{
name: "Validate MacAddress and Network not set at the same time",
config: &CloneConfig{
Template: "template name",
MacAddress: "some mac address",
StorageConfig: common.StorageConfig{
DiskControllerType: []string{"test"},
Storage: []common.DiskConfig{
{
DiskSize: 32768,
},
},
},
},
fail: true,
expectedErrMsg: "'network' is required when 'mac_address' is specified",
},
}
for _, c := range tc {
t.Run(c.name, func(t *testing.T) {
errs := c.config.Prepare()
if c.fail {
if len(errs) == 0 {
t.Fatalf("Config preprare should fail")
}
if errs[0].Error() != c.expectedErrMsg {
t.Fatalf("Expected error message: %s but was '%s'", c.expectedErrMsg, errs[0].Error())
}
} else {
if len(errs) != 0 {
t.Fatalf("Config preprare should not fail: %s", errs[0])
}
}
})
}
}
func TestStepCreateVM_Run(t *testing.T) {
state := new(multistep.BasicStateBag)
state.Put("ui", &packersdk.BasicUi{
Reader: new(bytes.Buffer),
Writer: new(bytes.Buffer),
})
driverMock := driver.NewDriverMock()
state.Put("driver", driverMock)
step := basicStepCloneVM()
step.Force = true
vmPath := path.Join(step.Location.Folder, step.Location.VMName)
vmMock := new(driver.VirtualMachineMock)
driverMock.VM = vmMock
if action := step.Run(context.TODO(), state); action == multistep.ActionHalt {
t.Fatalf("Should not halt.")
}
// Pre clean VM
if !driverMock.PreCleanVMCalled {
t.Fatalf("driver.PreCleanVM should be called.")
}
if driverMock.PreCleanForce != step.Force {
t.Fatalf("Force PreCleanVM should be %t but was %t.", step.Force, driverMock.PreCleanForce)
}
if driverMock.PreCleanVMPath != vmPath {
t.Fatalf("VM path expected to be %s but was %s", vmPath, driverMock.PreCleanVMPath)
}
if !driverMock.FindVMCalled {
t.Fatalf("driver.FindVM should be called.")
}
if !vmMock.CloneCalled {
t.Fatalf("vm.Clone should be called.")
}
if diff := cmp.Diff(vmMock.CloneConfig, driverCreateConfig(step.Config, step.Location)); diff != "" {
t.Fatalf("wrong driver.CreateConfig: %s", diff)
}
vm, ok := state.GetOk("vm")
if !ok {
t.Fatal("state must contain the VM")
}
if vm != driverMock.VM {
t.Fatalf("state doesn't contain the created VM.")
}
}
func basicStepCloneVM() *StepCloneVM {
step := &StepCloneVM{
Config: createConfig(),
Location: basicLocationConfig(),
}
return step
}
func basicLocationConfig() *common.LocationConfig {
return &common.LocationConfig{
VMName: "test-vm",
Folder: "test-folder",
Cluster: "test-cluster",
Host: "test-host",
ResourcePool: "test-resource-pool",
Datastore: "test-datastore",
}
}
func createConfig() *CloneConfig {
return &CloneConfig{
Template: "template name",
StorageConfig: common.StorageConfig{
DiskControllerType: []string{"pvscsi"},
Storage: []common.DiskConfig{
{
DiskSize: 32768,
DiskThinProvisioned: true,
},
},
},
}
}
func driverCreateConfig(config *CloneConfig, location *common.LocationConfig) *driver.CloneConfig {
var disks []driver.Disk
for _, disk := range config.StorageConfig.Storage {
disks = append(disks, driver.Disk{
DiskSize: disk.DiskSize,
DiskEagerlyScrub: disk.DiskEagerlyScrub,
DiskThinProvisioned: disk.DiskThinProvisioned,
ControllerIndex: disk.DiskControllerIndex,
})
}
return &driver.CloneConfig{
StorageConfig: driver.StorageConfig{
DiskControllerType: config.StorageConfig.DiskControllerType,
Storage: disks,
},
Annotation: config.Notes,
Name: location.VMName,
Folder: location.Folder,
Cluster: location.Cluster,
Host: location.Host,
ResourcePool: location.ResourcePool,
Datastore: location.Datastore,
LinkedClone: config.LinkedClone,
Network: config.Network,
MacAddress: config.MacAddress,
VAppProperties: config.VAppConfig.Properties,
PrimaryDiskSize: config.DiskSize,
}
}
+1 -9
View File
@@ -24,9 +24,6 @@ type DriverMock struct {
CreateVMCalled bool
CreateConfig *CreateConfig
VM VirtualMachine
FindVMCalled bool
FindVMName string
}
func NewDriverMock() *DriverMock {
@@ -48,12 +45,7 @@ func (d *DriverMock) NewVM(ref *types.ManagedObjectReference) VirtualMachine {
}
func (d *DriverMock) FindVM(name string) (VirtualMachine, error) {
d.FindVMCalled = true
if d.VM == nil {
d.VM = new(VirtualMachineMock)
}
d.FindVMName = name
return d.VM, d.FindDatastoreErr
return nil, nil
}
func (d *DriverMock) FindCluster(name string) (*Cluster, error) {
+29 -29
View File
@@ -32,7 +32,7 @@ type VirtualMachine interface {
Destroy() error
Configure(config *HardwareConfig) error
Customize(spec types.CustomizationSpec) error
ResizeDisk(diskSize int64) ([]types.BaseVirtualDeviceConfigSpec, error)
ResizeDisk(diskSize int64) error
WaitForIP(ctx context.Context, ipNet *net.IPNet) (string, error)
PowerOn() error
PowerOff() error
@@ -68,19 +68,18 @@ type VirtualMachineDriver struct {
}
type CloneConfig struct {
Name string
Folder string
Cluster string
Host string
ResourcePool string
Datastore string
LinkedClone bool
Network string
MacAddress string
Annotation string
VAppProperties map[string]string
PrimaryDiskSize int64
StorageConfig StorageConfig
Name string
Folder string
Cluster string
Host string
ResourcePool string
Datastore string
LinkedClone bool
Network string
MacAddress string
Annotation string
VAppProperties map[string]string
StorageConfig StorageConfig
}
type HardwareConfig struct {
@@ -340,15 +339,6 @@ func (vm *VirtualMachineDriver) Clone(ctx context.Context, config *CloneConfig)
if err != nil {
return nil, err
}
if config.PrimaryDiskSize > 0 {
deviceResizeSpec, err := vm.ResizeDisk(config.PrimaryDiskSize)
if err != nil {
return nil, fmt.Errorf("failed to resize primary disk: %s", err.Error())
}
configSpec.DeviceChange = append(configSpec.DeviceChange, deviceResizeSpec...)
}
virtualDisks := devices.SelectByType((*types.VirtualDisk)(nil))
virtualControllers := devices.SelectByType((*types.VirtualController)(nil))
@@ -359,7 +349,7 @@ func (vm *VirtualMachineDriver) Clone(ctx context.Context, config *CloneConfig)
storageConfigSpec, err := config.StorageConfig.AddStorageDevices(existingDevices)
if err != nil {
return nil, fmt.Errorf("failed to add storage devices: %s", err.Error())
return nil, err
}
configSpec.DeviceChange = append(configSpec.DeviceChange, storageConfigSpec...)
@@ -607,25 +597,35 @@ func (vm *VirtualMachineDriver) Customize(spec types.CustomizationSpec) error {
return task.Wait(vm.driver.ctx)
}
func (vm *VirtualMachineDriver) ResizeDisk(diskSize int64) ([]types.BaseVirtualDeviceConfigSpec, error) {
func (vm *VirtualMachineDriver) ResizeDisk(diskSize int64) error {
var confSpec types.VirtualMachineConfigSpec
devices, err := vm.vm.Device(vm.driver.ctx)
if err != nil {
return nil, err
return err
}
disk, err := findDisk(devices)
if err != nil {
return nil, err
return err
}
disk.CapacityInKB = diskSize * 1024
return []types.BaseVirtualDeviceConfigSpec{
confSpec.DeviceChange = []types.BaseVirtualDeviceConfigSpec{
&types.VirtualDeviceConfigSpec{
Device: disk,
Operation: types.VirtualDeviceConfigSpecOperationEdit,
},
}, nil
}
task, err := vm.vm.Reconfigure(vm.driver.ctx, confSpec)
if err != nil {
return err
}
_, err = task.WaitForResult(vm.driver.ctx, nil)
return err
}
func (vm *VirtualMachineDriver) PowerOn() error {
+3 -8
View File
@@ -55,9 +55,6 @@ type VirtualMachineMock struct {
RemoveCdromsCalled bool
RemoveCdromsErr error
CloneCalled bool
CloneConfig *CloneConfig
CloneError error
}
func (vm *VirtualMachineMock) Info(params ...string) (*mo.VirtualMachine, error) {
@@ -74,9 +71,7 @@ func (vm *VirtualMachineMock) FloppyDevices() (object.VirtualDeviceList, error)
}
func (vm *VirtualMachineMock) Clone(ctx context.Context, config *CloneConfig) (VirtualMachine, error) {
vm.CloneCalled = true
vm.CloneConfig = config
return vm, vm.CloneError
return nil, nil
}
func (vm *VirtualMachineMock) updateVAppConfig(ctx context.Context, newProps map[string]string) (*types.VmConfigSpec, error) {
@@ -112,8 +107,8 @@ func (vm *VirtualMachineMock) Customize(spec types.CustomizationSpec) error {
return nil
}
func (vm *VirtualMachineMock) ResizeDisk(diskSize int64) ([]types.BaseVirtualDeviceConfigSpec, error) {
return nil, nil
func (vm *VirtualMachineMock) ResizeDisk(diskSize int64) error {
return nil
}
func (vm *VirtualMachineMock) PowerOn() error {
+6 -88
View File
@@ -1,7 +1,6 @@
package driver
import (
"context"
"testing"
"github.com/vmware/govmomi/simulator"
@@ -62,7 +61,7 @@ func TestVirtualMachineDriver_Configure(t *testing.T) {
}
}
func TestVirtualMachineDriver_CreateVMWithMultipleDisks(t *testing.T) {
func TestVirtualMachineDriver_CreateVM(t *testing.T) {
sim, err := NewVCenterSimulator()
if err != nil {
t.Fatalf("should not fail: %s", err.Error())
@@ -72,9 +71,10 @@ func TestVirtualMachineDriver_CreateVMWithMultipleDisks(t *testing.T) {
_, datastore := sim.ChooseSimulatorPreCreatedDatastore()
config := &CreateConfig{
Name: "mock name",
Host: "DC0_H0",
Datastore: datastore.Name,
Annotation: "mock annotation",
Name: "mock name",
Host: "DC0_H0",
Datastore: datastore.Name,
NICs: []NIC{
{
Network: "VM Network",
@@ -98,90 +98,8 @@ func TestVirtualMachineDriver_CreateVMWithMultipleDisks(t *testing.T) {
},
}
vm, err := sim.driver.CreateVM(config)
_, err = sim.driver.CreateVM(config)
if err != nil {
t.Fatalf("unexpected error %s", err.Error())
}
devices, err := vm.Devices()
if err != nil {
t.Fatalf("unexpected error %s", err.Error())
}
var disks []*types.VirtualDisk
for _, device := range devices {
switch d := device.(type) {
case *types.VirtualDisk:
disks = append(disks, d)
}
}
if len(disks) != 2 {
t.Fatalf("unexpected number of devices")
}
}
func TestVirtualMachineDriver_CloneWithPrimaryDiskResize(t *testing.T) {
sim, err := NewVCenterSimulator()
if err != nil {
t.Fatalf("should not fail: %s", err.Error())
}
defer sim.Close()
_, datastore := sim.ChooseSimulatorPreCreatedDatastore()
vm, _ := sim.ChooseSimulatorPreCreatedVM()
config := &CloneConfig{
Name: "mock name",
Host: "DC0_H0",
Datastore: datastore.Name,
PrimaryDiskSize: 204800,
StorageConfig: StorageConfig{
DiskControllerType: []string{"pvscsi"},
Storage: []Disk{
{
DiskSize: 3072,
DiskThinProvisioned: true,
ControllerIndex: 0,
},
{
DiskSize: 20480,
DiskThinProvisioned: true,
ControllerIndex: 0,
},
},
},
}
clonedVM, err := vm.Clone(context.TODO(), config)
if err != nil {
t.Fatalf("unexpected error %s", err.Error())
}
devices, err := clonedVM.Devices()
if err != nil {
t.Fatalf("unexpected error %s", err.Error())
}
var disks []*types.VirtualDisk
for _, device := range devices {
switch d := device.(type) {
case *types.VirtualDisk:
disks = append(disks, d)
}
}
if len(disks) != 3 {
t.Fatalf("unexpected number of devices")
}
if disks[0].CapacityInKB != config.PrimaryDiskSize*1024 {
t.Fatalf("unexpected disk size for primary disk: %d", disks[0].CapacityInKB)
}
if disks[1].CapacityInKB != config.StorageConfig.Storage[0].DiskSize*1024 {
t.Fatalf("unexpected disk size for primary disk: %d", disks[1].CapacityInKB)
}
if disks[2].CapacityInKB != config.StorageConfig.Storage[1].DiskSize*1024 {
t.Fatalf("unexpected disk size for primary disk: %d", disks[2].CapacityInKB)
}
}
+1 -1
View File
@@ -6,8 +6,8 @@ import (
"os"
"testing"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
builderT "github.com/hashicorp/packer/acctest"
commonT "github.com/hashicorp/packer/builder/vsphere/common/testing"
"github.com/vmware/govmomi/vim25/types"
)
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"github.com/go-resty/resty/v2"
builderT "github.com/hashicorp/packer/acctest"
builderT "github.com/hashicorp/packer-plugin-sdk/acctest"
)
const InstanceMetadataAddr = "169.254.169.254"
+2
View File
@@ -95,6 +95,8 @@ func TestHelperProcess(*testing.T) {
os.Exit((&BuildCommand{Meta: commandMeta()}).Run(args))
case "hcl2_upgrade":
os.Exit((&HCL2UpgradeCommand{Meta: commandMeta()}).Run(args))
case "version":
os.Exit((&VersionCommand{Meta: commandMeta()}).Run(args))
default:
fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd)
os.Exit(2)
+6
View File
@@ -50,6 +50,7 @@ import (
tencentcloudcvmbuilder "github.com/hashicorp/packer/builder/tencentcloud/cvm"
tritonbuilder "github.com/hashicorp/packer/builder/triton"
uclouduhostbuilder "github.com/hashicorp/packer/builder/ucloud/uhost"
vagrantbuilder "github.com/hashicorp/packer/builder/vagrant"
virtualboxisobuilder "github.com/hashicorp/packer/builder/virtualbox/iso"
virtualboxovfbuilder "github.com/hashicorp/packer/builder/virtualbox/ovf"
virtualboxvmbuilder "github.com/hashicorp/packer/builder/virtualbox/vm"
@@ -68,6 +69,8 @@ import (
manifestpostprocessor "github.com/hashicorp/packer/post-processor/manifest"
shelllocalpostprocessor "github.com/hashicorp/packer/post-processor/shell-local"
ucloudimportpostprocessor "github.com/hashicorp/packer/post-processor/ucloud-import"
vagrantpostprocessor "github.com/hashicorp/packer/post-processor/vagrant"
vagrantcloudpostprocessor "github.com/hashicorp/packer/post-processor/vagrant-cloud"
vspherepostprocessor "github.com/hashicorp/packer/post-processor/vsphere"
vspheretemplatepostprocessor "github.com/hashicorp/packer/post-processor/vsphere-template"
yandexexportpostprocessor "github.com/hashicorp/packer/post-processor/yandex-export"
@@ -134,6 +137,7 @@ var Builders = map[string]packersdk.Builder{
"tencentcloud-cvm": new(tencentcloudcvmbuilder.Builder),
"triton": new(tritonbuilder.Builder),
"ucloud-uhost": new(uclouduhostbuilder.Builder),
"vagrant": new(vagrantbuilder.Builder),
"virtualbox-iso": new(virtualboxisobuilder.Builder),
"virtualbox-ovf": new(virtualboxovfbuilder.Builder),
"virtualbox-vm": new(virtualboxvmbuilder.Builder),
@@ -176,6 +180,8 @@ var PostProcessors = map[string]packersdk.PostProcessor{
"manifest": new(manifestpostprocessor.PostProcessor),
"shell-local": new(shelllocalpostprocessor.PostProcessor),
"ucloud-import": new(ucloudimportpostprocessor.PostProcessor),
"vagrant": new(vagrantpostprocessor.PostProcessor),
"vagrant-cloud": new(vagrantcloudpostprocessor.PostProcessor),
"vsphere": new(vspherepostprocessor.PostProcessor),
"vsphere-template": new(vspheretemplatepostprocessor.PostProcessor),
"yandex-export": new(yandexexportpostprocessor.PostProcessor),
-6
View File
@@ -20,9 +20,6 @@ import (
dockerpushpostprocessor "github.com/hashicorp/packer-plugin-docker/post-processor/docker-push"
dockersavepostprocessor "github.com/hashicorp/packer-plugin-docker/post-processor/docker-save"
dockertagpostprocessor "github.com/hashicorp/packer-plugin-docker/post-processor/docker-tag"
vagrantbuilder "github.com/hashicorp/packer-plugin-vagrant/builder/vagrant"
vagrantpostprocessor "github.com/hashicorp/packer-plugin-vagrant/post-processor/vagrant"
vagrantcloudpostprocessor "github.com/hashicorp/packer-plugin-vagrant/post-processor/vagrant-cloud"
)
// VendoredDatasources are datasource components that were once bundled with the
@@ -41,7 +38,6 @@ var VendoredBuilders = map[string]packersdk.Builder{
"amazon-ebssurrogate": new(amazonebssurrogatebuilder.Builder),
"amazon-ebsvolume": new(amazonebsvolumebuilder.Builder),
"amazon-instance": new(amazoninstancebuilder.Builder),
"vagrant": new(vagrantbuilder.Builder),
}
// VendoredProvisioners are provisioner components that were once bundled with the
@@ -57,8 +53,6 @@ var VendoredPostProcessors = map[string]packersdk.PostProcessor{
"docker-tag": new(dockertagpostprocessor.PostProcessor),
"exoscale-import": new(exoscaleimportpostprocessor.PostProcessor),
"amazon-import": new(anazibimportpostprocessor.PostProcessor),
"vagrant": new(vagrantpostprocessor.PostProcessor),
"vagrant-cloud": new(vagrantcloudpostprocessor.PostProcessor),
}
// Upon init lets load up any plugins that were vendored manually into the default
+26
View File
@@ -1,11 +1,37 @@
package command
import (
"fmt"
"testing"
"github.com/hashicorp/packer/version"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
)
func TestVersionCommand_implements(t *testing.T) {
var _ cli.Command = &VersionCommand{}
}
func Test_version(t *testing.T) {
tc := []struct {
command []string
env []string
expected string
}{
{[]string{"version"}, nil, fmt.Sprintf("Packer v%s", version.FormattedVersion()) + "\n"},
{[]string{"version", "&"}, nil, fmt.Sprintf("Packer v%s", version.FormattedVersion()) + "\n"},
}
for _, tc := range tc {
t.Run(fmt.Sprintf("packer %s", tc.command), func(t *testing.T) {
p := helperCommand(t, tc.command...)
bs, err := p.Output()
fmt.Println(err)
if err != nil {
t.Fatalf("%v: %s", err, bs)
}
assert.Equal(t, tc.expected, string(bs))
})
}
}
+3 -6
View File
@@ -12,7 +12,7 @@ require (
github.com/Azure/go-autorest/autorest/to v0.3.0
github.com/ChrisTrenkamp/goxpath v0.0.0-20170922090931-c385f95c6022
github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.1.0
github.com/Telmate/proxmox-api-go v0.0.0-20210331182840-ff89a0cebcfa
github.com/Telmate/proxmox-api-go v0.0.0-20210320143302-fea68269e6b0
github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190418113227-25233c783f4e
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20170113022742-e6dbea820a9f
github.com/antihax/optional v1.0.0
@@ -25,7 +25,7 @@ require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/digitalocean/go-qemu v0.0.0-20201211181942-d361e7b4965f
github.com/digitalocean/godo v1.11.1
github.com/exoscale/packer-plugin-exoscale v0.1.1
github.com/exoscale/packer-plugin-exoscale v0.1.0
github.com/fatih/camelcase v1.0.0
github.com/fatih/structtag v1.0.0
github.com/go-ini/ini v1.25.4
@@ -51,8 +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
github.com/hashicorp/packer-plugin-vagrant v0.0.1
github.com/hashicorp/packer-plugin-sdk v0.1.1
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
@@ -101,6 +100,4 @@ require (
google.golang.org/grpc v1.32.0
)
replace github.com/hashicorp/packer-plugin-vagrant => /Users/mmarsh/Projects/packer-plugin-vagrant
go 1.16
+4 -35
View File
@@ -82,9 +82,8 @@ github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.1.0/go.mod h1:P+3VS0ETiQPyWOx3
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/Telmate/proxmox-api-go v0.0.0-20200715182505-ec97c70ba887/go.mod h1:OGWyIMJ87/k/GCz8CGiWB2HOXsOVDM6Lpe/nFPkC4IQ=
github.com/Telmate/proxmox-api-go v0.0.0-20210320143302-fea68269e6b0 h1:LeBf+Ex12uqA6dWZp73Qf3dzpV/LvB9SRmHgPBwnXrQ=
github.com/Telmate/proxmox-api-go v0.0.0-20210320143302-fea68269e6b0/go.mod h1:ayPkdmEKnlssqLQ9K1BE1jlsaYhXVwkoduXI30oQF0I=
github.com/Telmate/proxmox-api-go v0.0.0-20210331182840-ff89a0cebcfa h1:n4g0+o4DDX6WGTRfdj1Ux+49vSwtxtqFGB5XtxoDphI=
github.com/Telmate/proxmox-api-go v0.0.0-20210331182840-ff89a0cebcfa/go.mod h1:ayPkdmEKnlssqLQ9K1BE1jlsaYhXVwkoduXI30oQF0I=
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af h1:DBNMBMuMiWYu0b+8KMJuWmfCkcxl09JwdlqwDZZ6U14=
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw=
github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
@@ -127,30 +126,6 @@ github.com/aws/aws-sdk-go v1.36.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zK
github.com/aws/aws-sdk-go v1.36.5/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.38.0 h1:mqnmtdW8rGIQmp2d0WRFLua0zW0Pel0P6/vd3gJuViY=
github.com/aws/aws-sdk-go v1.38.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go-v2 v1.2.1 h1:055XAi+MtmhyYX161p+jWRibkCb9YpI2ymXZiW1dwVY=
github.com/aws/aws-sdk-go-v2 v1.2.1/go.mod h1:hTQc/9pYq5bfFACIUY9tc/2SYWd9Vnmw+testmuQeRY=
github.com/aws/aws-sdk-go-v2/config v1.1.2 h1:H2r6cwMvvINFpEC55Y7jcNaR/oc7zYIChrG2497wmBI=
github.com/aws/aws-sdk-go-v2/config v1.1.2/go.mod h1:77yIk+qmCS/94JlxbwV1d+YEyu6Z8FBlCGcSz3TdM6A=
github.com/aws/aws-sdk-go-v2/credentials v1.1.2 h1:YoNqfhxAJGZI+lStIbqgx30UcCqQ86fr7FjTLUvrFOc=
github.com/aws/aws-sdk-go-v2/credentials v1.1.2/go.mod h1:hofjw//lM0XLplgvzPPMA7oD0doQU1QpaIK1nweEEWg=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.3 h1:d3bKAGy4XdJyK8hz3Nx3WJJ4TCmYp2498G4mFY5wly0=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.3/go.mod h1:Zr1Mj+KUMGVQ+WJvTT68EZJxqhjiie2PWSPGEUPaNY0=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.0.3 h1:vhRq0752KGBMmLnVessDOpt+5XEdzM87hhiuwGiEpqc=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.0.3/go.mod h1:9tFvXNMet5TrBa2bMLhZBvenXs4qKMqiG1n0MNR4FFA=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.0.2 h1:GO0pL4QvQmA0fXJe3MHVO+emtg31MYq5/8sebSWgE6A=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.0.2/go.mod h1:bYl7lGFQQdHia3uMQH4p6ImnuOeDNeUoydoXM5x8Yzw=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.3 h1:dST4y8pZKZdTPs4uwXmGCJmpycz1SHKmCSIhf3GqHEo=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.3/go.mod h1:C50Z41fJaJ7WgaeeCulOGAU3q4+4se4B3uOPFdhBi2I=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.1.1 h1:+WCVceRPiUsrui55mDByXOVremK1n3Hm8GnB4ZD3eco=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.1.1/go.mod h1:B+fb+BFbja6obFOHYmYE4iUMdej9aM2VGSpgdU1pn0M=
github.com/aws/aws-sdk-go-v2/service/s3 v1.2.1 h1:3qn6YVXpOCK9seQ8ZilDyMrhpEUaZNaJG8SXNiCvk+c=
github.com/aws/aws-sdk-go-v2/service/s3 v1.2.1/go.mod h1:3xGOyhtPPD/WXJUljmb5+ZXhNyHa4h6wgL6mWOF6S0c=
github.com/aws/aws-sdk-go-v2/service/sso v1.1.2 h1:9BnjX/ALn5uLo2DbgkwMpUkPL1VLQVBXcjZxqJBhf44=
github.com/aws/aws-sdk-go-v2/service/sso v1.1.2/go.mod h1:5yU1oE3+CVYYLUsaHt2AVU3CJJZ6ER4pwsrRD1L2KSc=
github.com/aws/aws-sdk-go-v2/service/sts v1.1.2 h1:7Kxqov7uQeP8WUEO0iHz3j9Bh0E1rJrn6cf/OGfcDds=
github.com/aws/aws-sdk-go-v2/service/sts v1.1.2/go.mod h1:zu7rotIY9P4Aoc6ytqLP9jeYrECDHUODB5Gbp+BSHl8=
github.com/aws/smithy-go v1.2.0 h1:0PoGBWXkXDIyVdPaZW9gMhaGzj3UOAgTdiVoHuuZAFA=
github.com/aws/smithy-go v1.2.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
@@ -210,9 +185,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE=
github.com/exoscale/egoscale v0.43.1 h1:Lhr0UOfg3t3Y56yh1DsYCjQuUHqFvsC8iUVqvub8+0Q=
github.com/exoscale/egoscale v0.43.1/go.mod h1:mpEXBpROAa/2i5GC0r33rfxG+TxSEka11g1PIXt9+zc=
github.com/exoscale/packer-plugin-exoscale v0.1.0 h1:p4ymqF1tNiTuxgSdnEjGqXehMdDQbV7BPaLsMxGav24=
github.com/exoscale/packer-plugin-exoscale v0.1.0/go.mod h1:ZmJRkxsAlmEsVYOMxYPupDkax54uZ+ph0h3W59aIMZ8=
github.com/exoscale/packer-plugin-exoscale v0.1.1 h1:NJ9UvMvSe3LK3H50hJv9nMG2reqgWKBAUhAEs4JJNso=
github.com/exoscale/packer-plugin-exoscale v0.1.1/go.mod h1:5S07HizadGVKST/m0a5+aNmDiFfY7EbPvnkU4rJWRE8=
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
@@ -296,7 +270,6 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-github/v33 v33.0.0/go.mod h1:GMdDnVZY/2TsWgp/lkYnpSAh6TrzhANBBwm6k6TTEXg=
@@ -428,7 +401,6 @@ github.com/hashicorp/packer v1.6.7-0.20210126105722-aef4ced967ec/go.mod h1:2+Vo/
github.com/hashicorp/packer v1.6.7-0.20210208125835-f616955ebcb6/go.mod h1:7f5ZpTTRG53rQ58BcTADuTnpiBcB3wapuxl4sF2sGMM=
github.com/hashicorp/packer v1.6.7-0.20210217093213-201869d627bf/go.mod h1:+EWPPcqee4h8S/y913Dnta1eJkgiqsGXBQgB75A2qV0=
github.com/hashicorp/packer v1.7.0/go.mod h1:3KRJcwOctl2JaAGpQMI1bWQRArfWNWqcYjO6AOsVVGQ=
github.com/hashicorp/packer v1.7.1/go.mod h1:ApnmMINvuhhnfPyTVqZu6jznDWPVYDJUw7e188DFCmo=
github.com/hashicorp/packer-plugin-amazon v0.0.1 h1:EuyjNK9bL7WhQeIJzhBJxOx8nyc61ai5UbOsb1PIVwI=
github.com/hashicorp/packer-plugin-amazon v0.0.1/go.mod h1:12c9msibyHdId+Mk/pCbdRb1KaLIhaNyxeJ6n8bZt30=
github.com/hashicorp/packer-plugin-docker v0.0.7 h1:hMTrH7vrkFIjphtbbtpuzffTzSjMNgxayo2DPLz9y+c=
@@ -442,10 +414,8 @@ github.com/hashicorp/packer-plugin-sdk v0.0.11/go.mod h1:GNb0WNs7zibb8vzUZce1As6
github.com/hashicorp/packer-plugin-sdk v0.0.12/go.mod h1:hs82OYeufirGG6KRENMpjBWomnIlte99X6wXAPThJ5I=
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 h1:foqSy6m+2MsEf9ygNoBlIoi3SPvlkInS+yT0Uyj3yvw=
github.com/hashicorp/packer-plugin-sdk v0.1.1/go.mod h1:1d3nqB9LUsXMQaNUiL67Q+WYEtjsVcLNTX8ikVlpBrc=
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 h1:oHTVlgoX2piUzL54+LBo9uIMfW+L/kY7or83dDStdIY=
github.com/hashicorp/packer-plugin-sdk v0.1.3/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=
@@ -490,9 +460,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v0.0.0-20160131094358-f86d2e6d8a77/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.11.6/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.7 h1:0hzRabrMN4tSTvMfnL3SCv1ZGeAP23ynzodBgaHeMeg=
github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.13 h1:eSvu8Tmq6j2psUJqJrLcWH6K3w5Dwc+qipbaA6eVEN4=
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/cpuid v0.0.0-20160106104451-349c67577817/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/crc32 v0.0.0-20160114101742-999f3125931f/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg=
github.com/klauspost/crc32 v1.2.0 h1:0VuyqOCruD33/lJ/ojXNvzVyl8Zr5zdTmj9l9qLZ86I=
+2 -9
View File
@@ -126,15 +126,6 @@ func realMain() int {
// wrappedMain is called only when we're wrapped by panicwrap and
// returns the exit status to exit with.
func wrappedMain() int {
// WARNING: WrappedMain causes unexpected behaviors when writing to stderr
// and stdout. Anything in this function written to stderr will be captured
// by the logger, but will not be written to the terminal. Anything in
// this function written to standard out must be prefixed with ErrorPrefix
// or OutputPrefix to be sent to the right terminal stream, but adding
// these prefixes can cause nondeterministic results for output from
// other, asynchronous methods. Try to avoid modifying output in this
// function if at all possible.
// If there is no explicit number of Go threads to use, then set it
if os.Getenv("GOMAXPROCS") == "" {
runtime.GOMAXPROCS(runtime.NumCPU())
@@ -479,3 +470,5 @@ func init() {
// Seed the random number generator
rand.Seed(time.Now().UTC().UnixNano())
}
var backgroundCheckFn func(int) (bool, error)
+9
View File
@@ -2,6 +2,7 @@ package main
import (
"math/rand"
"os"
"reflect"
"strings"
"testing"
@@ -67,3 +68,11 @@ func TestRandom(t *testing.T) {
t.Fatal("math.rand is not seeded properly")
}
}
func ExampleWrappedMain() {
os.Setenv("PACKER_WRAP_COOKIE", "49C22B1A-3A93-4C98-97FA-E07D18C787B5")
backgroundCheckFn = func(_ int) (bool, error) { return true, nil }
os.Args = []string{"packer", "version"}
wrappedMain()
//Output: Packer v1.7.2-dev
}
@@ -52,7 +52,6 @@ type FlatConfig struct {
AlicloudSourceImage *string `mapstructure:"source_image" required:"true" cty:"source_image" hcl:"source_image"`
ForceStopInstance *bool `mapstructure:"force_stop_instance" required:"false" cty:"force_stop_instance" hcl:"force_stop_instance"`
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance" hcl:"disable_stop_instance"`
RamRoleName *string `mapstructure:"ram_role_name" required:"false" cty:"ram_role_name" hcl:"ram_role_name"`
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id" hcl:"security_group_id"`
SecurityGroupName *string `mapstructure:"security_group_name" required:"false" cty:"security_group_name" hcl:"security_group_name"`
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data" hcl:"user_data"`
@@ -178,7 +177,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"source_image": &hcldec.AttrSpec{Name: "source_image", Type: cty.String, Required: false},
"force_stop_instance": &hcldec.AttrSpec{Name: "force_stop_instance", Type: cty.Bool, Required: false},
"disable_stop_instance": &hcldec.AttrSpec{Name: "disable_stop_instance", Type: cty.Bool, Required: false},
"ram_role_name": &hcldec.AttrSpec{Name: "ram_role_name", Type: cty.String, Required: false},
"security_group_id": &hcldec.AttrSpec{Name: "security_group_id", Type: cty.String, Required: false},
"security_group_name": &hcldec.AttrSpec{Name: "security_group_name", Type: cty.String, Required: false},
"user_data": &hcldec.AttrSpec{Name: "user_data", Type: cty.String, Required: false},
@@ -59,8 +59,6 @@ type Config struct {
ImageLabels map[string]string `mapstructure:"image_labels"`
//The unique name of the resulting image.
ImageName string `mapstructure:"image_name" required:"true"`
//Specifies a Cloud Storage location, either regional or multi-regional, where image content is to be stored. If not specified, the multi-region location closest to the source is chosen automatically.
ImageStorageLocations []string `mapstructure:"image_storage_locations"`
//Skip removing the TAR file uploaded to the GCS
//bucket after the import process has completed. "true" means that we should
//leave it in the GCS bucket, "false" means to clean it out. Defaults to
@@ -184,7 +182,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, artifa
return nil, false, false, err
}
gceImageArtifact, err := CreateGceImage(opts, ui, p.config.ProjectId, rawImageGcsPath, p.config.ImageName, p.config.ImageDescription, p.config.ImageFamily, p.config.ImageLabels, p.config.ImageGuestOsFeatures, shieldedVMStateConfig, p.config.ImageStorageLocations)
gceImageArtifact, err := CreateGceImage(opts, ui, p.config.ProjectId, rawImageGcsPath, p.config.ImageName, p.config.ImageDescription, p.config.ImageFamily, p.config.ImageLabels, p.config.ImageGuestOsFeatures, shieldedVMStateConfig)
if err != nil {
return nil, false, false, err
}
@@ -297,7 +295,7 @@ func UploadToBucket(opts option.ClientOption, ui packersdk.Ui, artifact packersd
return storageObject.SelfLink, nil
}
func CreateGceImage(opts option.ClientOption, ui packersdk.Ui, project string, rawImageURL string, imageName string, imageDescription string, imageFamily string, imageLabels map[string]string, imageGuestOsFeatures []string, shieldedVMStateConfig *compute.InitialStateConfig, imageStorageLocations []string) (packersdk.Artifact, error) {
func CreateGceImage(opts option.ClientOption, ui packersdk.Ui, project string, rawImageURL string, imageName string, imageDescription string, imageFamily string, imageLabels map[string]string, imageGuestOsFeatures []string, shieldedVMStateConfig *compute.InitialStateConfig) (packersdk.Artifact, error) {
service, err := compute.NewService(context.TODO(), opts)
if err != nil {
@@ -321,7 +319,6 @@ func CreateGceImage(opts option.ClientOption, ui packersdk.Ui, project string, r
RawDisk: &compute.ImageRawDisk{Source: rawImageURL},
SourceType: "RAW",
ShieldedInstanceInitialState: shieldedVMStateConfig,
StorageLocations: imageStorageLocations,
}
ui.Say(fmt.Sprintf("Creating GCE image %v...", imageName))
@@ -29,7 +29,6 @@ type FlatConfig struct {
ImageGuestOsFeatures []string `mapstructure:"image_guest_os_features" cty:"image_guest_os_features" hcl:"image_guest_os_features"`
ImageLabels map[string]string `mapstructure:"image_labels" cty:"image_labels" hcl:"image_labels"`
ImageName *string `mapstructure:"image_name" required:"true" cty:"image_name" hcl:"image_name"`
ImageStorageLocations []string `mapstructure:"image_storage_locations" cty:"image_storage_locations" hcl:"image_storage_locations"`
SkipClean *bool `mapstructure:"skip_clean" cty:"skip_clean" hcl:"skip_clean"`
VaultGCPOauthEngine *string `mapstructure:"vault_gcp_oauth_engine" cty:"vault_gcp_oauth_engine" hcl:"vault_gcp_oauth_engine"`
ImagePlatformKey *string `mapstructure:"image_platform_key" cty:"image_platform_key" hcl:"image_platform_key"`
@@ -69,7 +68,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"image_guest_os_features": &hcldec.AttrSpec{Name: "image_guest_os_features", Type: cty.List(cty.String), Required: false},
"image_labels": &hcldec.AttrSpec{Name: "image_labels", Type: cty.Map(cty.String), Required: false},
"image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false},
"image_storage_locations": &hcldec.AttrSpec{Name: "image_storage_locations", Type: cty.List(cty.String), Required: false},
"skip_clean": &hcldec.AttrSpec{Name: "skip_clean", Type: cty.Bool, Required: false},
"vault_gcp_oauth_engine": &hcldec.AttrSpec{Name: "vault_gcp_oauth_engine", Type: cty.String, Required: false},
"image_platform_key": &hcldec.AttrSpec{Name: "image_platform_key", Type: cty.String, Required: false},
@@ -0,0 +1,15 @@
package vagrantcloud
import (
"testing"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
)
func TestArtifact_ImplementsArtifact(t *testing.T) {
var raw interface{}
raw = &Artifact{}
if _, ok := raw.(packersdk.Artifact); !ok {
t.Fatalf("Artifact should be a Artifact")
}
}
@@ -0,0 +1,30 @@
package vagrantcloud
import (
"encoding/json"
"strings"
"testing"
)
func TestVagranCloudErrors(t *testing.T) {
testCases := []struct {
resp string
expected string
}{
{`{"Status":"422 Unprocessable Entity", "StatusCode":422, "errors":[]}`, ""},
{`{"Status":"404 Artifact not found", "StatusCode":404, "errors":["error1", "error2"]}`, "error1. error2"},
{`{"StatusCode":403, "errors":[{"message":"Bad credentials"}]}`, "message Bad credentials"},
{`{"StatusCode":500, "errors":[["error in unexpected format"]]}`, "[error in unexpected format]"},
}
for _, tc := range testCases {
var cloudErrors VagrantCloudErrors
err := json.NewDecoder(strings.NewReader(tc.resp)).Decode(&cloudErrors)
if err != nil {
t.Errorf("failed to decode error response: %s", err)
}
if got := cloudErrors.FormatErrors(); got != tc.expected {
t.Errorf("failed to get expected response; expected %q, got %q", tc.expected, got)
}
}
}
@@ -112,7 +112,7 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
}
if p.config.VagrantCloudUrl == VAGRANT_CLOUD_URL && p.config.AccessToken == "" {
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("access_token must be set if vagrant_cloud_url has not been overridden"))
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("access_token must be set if vagrant_cloud_url has not been overriden"))
}
// Create the HTTP client
@@ -0,0 +1,850 @@
package vagrantcloud
import (
"archive/tar"
"bytes"
"compress/gzip"
"context"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"runtime"
"strings"
"testing"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/stretchr/testify/assert"
)
type stubResponse struct {
Path string
Method string
Response string
StatusCode int
}
type tarFiles []struct {
Name, Body string
}
func testGoodConfig() map[string]interface{} {
return map[string]interface{}{
"access_token": "foo",
"version_description": "bar",
"box_tag": "hashicorp/precise64",
"version": "0.5",
}
}
func testBadConfig() map[string]interface{} {
return map[string]interface{}{
"access_token": "foo",
"box_tag": "baz",
"version_description": "bar",
}
}
func testNoAccessTokenProvidedConfig() map[string]interface{} {
return map[string]interface{}{
"box_tag": "baz",
"version_description": "bar",
"version": "0.5",
}
}
func newStackServer(stack []stubResponse) *httptest.Server {
return httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
if len(stack) < 1 {
rw.Header().Add("Error", fmt.Sprintf("Request stack is empty - Method: %s Path: %s", req.Method, req.URL.Path))
http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
match := stack[0]
stack = stack[1:]
if match.Method != "" && req.Method != match.Method {
rw.Header().Add("Error", fmt.Sprintf("Request %s != %s", match.Method, req.Method))
http.Error(rw, fmt.Sprintf("Request %s != %s", match.Method, req.Method), http.StatusInternalServerError)
return
}
if match.Path != "" && match.Path != req.URL.Path {
rw.Header().Add("Error", fmt.Sprintf("Request %s != %s", match.Path, req.URL.Path))
http.Error(rw, fmt.Sprintf("Request %s != %s", match.Path, req.URL.Path), http.StatusInternalServerError)
return
}
rw.Header().Add("Complete", fmt.Sprintf("Method: %s Path: %s", match.Method, match.Path))
rw.WriteHeader(match.StatusCode)
if match.Response != "" {
_, err := rw.Write([]byte(match.Response))
if err != nil {
panic("failed to write response: " + err.Error())
}
}
}))
}
func newSecureServer(token string, handler http.HandlerFunc) *httptest.Server {
token = fmt.Sprintf("Bearer %s", token)
return httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
if req.Header.Get("authorization") != token {
http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
return
}
if handler != nil {
handler(rw, req)
}
}))
}
func newSelfSignedSslServer(token string, handler http.HandlerFunc) *httptest.Server {
token = fmt.Sprintf("Bearer %s", token)
return httptest.NewTLSServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
if req.Header.Get("authorization") != token {
http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
return
}
if handler != nil {
handler(rw, req)
}
}))
}
func newNoAuthServer(handler http.HandlerFunc) *httptest.Server {
return httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
if req.Header.Get("authorization") != "" {
http.Error(rw, "Authorization header was provider", http.StatusBadRequest)
return
}
if handler != nil {
handler(rw, req)
}
}))
}
func TestPostProcessor_Insecure_Ssl(t *testing.T) {
var p PostProcessor
server := newSelfSignedSslServer("foo", nil)
defer server.Close()
config := testGoodConfig()
config["vagrant_cloud_url"] = server.URL
config["insecure_skip_tls_verify"] = true
if err := p.Configure(config); err != nil {
t.Fatalf("Expected TLS to skip certificate validation: %s", err)
}
}
func TestPostProcessor_Configure_fromVagrantEnv(t *testing.T) {
var p PostProcessor
config := testGoodConfig()
server := newSecureServer("bar", nil)
defer server.Close()
config["vagrant_cloud_url"] = server.URL
config["access_token"] = ""
os.Setenv("VAGRANT_CLOUD_TOKEN", "bar")
defer func() {
os.Setenv("VAGRANT_CLOUD_TOKEN", "")
}()
if err := p.Configure(config); err != nil {
t.Fatalf("err: %s", err)
}
if p.config.AccessToken != "bar" {
t.Fatalf("Expected to get token from VAGRANT_CLOUD_TOKEN env var. Got '%s' instead",
p.config.AccessToken)
}
}
func TestPostProcessor_Configure_fromAtlasEnv(t *testing.T) {
var p PostProcessor
config := testGoodConfig()
config["access_token"] = ""
server := newSecureServer("foo", nil)
defer server.Close()
config["vagrant_cloud_url"] = server.URL
os.Setenv("ATLAS_TOKEN", "foo")
defer func() {
os.Setenv("ATLAS_TOKEN", "")
}()
if err := p.Configure(config); err != nil {
t.Fatalf("err: %s", err)
}
if p.config.AccessToken != "foo" {
t.Fatalf("Expected to get token from ATLAS_TOKEN env var. Got '%s' instead",
p.config.AccessToken)
}
if !p.warnAtlasToken {
t.Fatal("Expected warn flag to be set when getting token from atlas env var.")
}
}
func TestPostProcessor_Configure_Good(t *testing.T) {
config := testGoodConfig()
server := newSecureServer("foo", nil)
defer server.Close()
config["vagrant_cloud_url"] = server.URL
var p PostProcessor
if err := p.Configure(config); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestPostProcessor_Configure_Bad(t *testing.T) {
config := testBadConfig()
server := newSecureServer("foo", nil)
defer server.Close()
config["vagrant_cloud_url"] = server.URL
var p PostProcessor
if err := p.Configure(config); err == nil {
t.Fatalf("should have err")
}
}
func TestPostProcessor_Configure_checkAccessTokenIsRequiredByDefault(t *testing.T) {
var p PostProcessor
server := newSecureServer("foo", nil)
defer server.Close()
config := testNoAccessTokenProvidedConfig()
config["vagrant_cloud_url"] = server.URL
if err := p.Configure(config); err == nil {
t.Fatalf("Expected access token to be required.")
}
}
func TestPostProcessor_Configure_checkAccessTokenIsNotRequiredForOverridenVagrantCloud(t *testing.T) {
var p PostProcessor
server := newNoAuthServer(nil)
defer server.Close()
config := testNoAccessTokenProvidedConfig()
config["vagrant_cloud_url"] = server.URL
if err := p.Configure(config); err != nil {
t.Fatalf("Expected blank access token to be allowed and authenticate to pass: %s", err)
}
}
func TestPostProcessor_PostProcess_checkArtifactType(t *testing.T) {
artifact := &packersdk.MockArtifact{
BuilderIdValue: "invalid.builder",
}
config := testGoodConfig()
server := newSecureServer("foo", nil)
defer server.Close()
config["vagrant_cloud_url"] = server.URL
var p PostProcessor
p.Configure(config)
_, _, _, err := p.PostProcess(context.Background(), testUi(), artifact)
if !strings.Contains(err.Error(), "Unknown artifact type") {
t.Fatalf("Should error with message 'Unknown artifact type...' with BuilderId: %s", artifact.BuilderIdValue)
}
}
func TestPostProcessor_PostProcess_checkArtifactFileIsBox(t *testing.T) {
artifact := &packersdk.MockArtifact{
BuilderIdValue: "mitchellh.post-processor.vagrant", // good
FilesValue: []string{"invalid.boxfile"}, // should have .box extension
}
config := testGoodConfig()
server := newSecureServer("foo", nil)
defer server.Close()
config["vagrant_cloud_url"] = server.URL
var p PostProcessor
p.Configure(config)
_, _, _, err := p.PostProcess(context.Background(), testUi(), artifact)
if !strings.Contains(err.Error(), "Unknown files in artifact") {
t.Fatalf("Should error with message 'Unknown files in artifact...' with artifact file: %s",
artifact.FilesValue[0])
}
}
func TestPostProcessor_PostProcess_uploadsAndReleases(t *testing.T) {
files := tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", `{"provider": "virtualbox"}`},
}
boxfile, err := createBox(files)
if err != nil {
t.Fatalf("%s", err)
}
defer os.Remove(boxfile.Name())
artifact := &packersdk.MockArtifact{
BuilderIdValue: "mitchellh.post-processor.vagrant",
FilesValue: []string{boxfile.Name()},
}
s := newStackServer([]stubResponse{stubResponse{StatusCode: 200, Method: "PUT", Path: "/box-upload-path"}})
defer s.Close()
stack := []stubResponse{
stubResponse{StatusCode: 200, Method: "GET", Path: "/authenticate"},
stubResponse{StatusCode: 200, Method: "GET", Path: "/box/hashicorp/precise64", Response: `{"tag": "hashicorp/precise64"}`},
stubResponse{StatusCode: 200, Method: "POST", Path: "/box/hashicorp/precise64/versions", Response: `{}`},
stubResponse{StatusCode: 200, Method: "POST", Path: "/box/hashicorp/precise64/version/0.5/providers", Response: `{}`},
stubResponse{StatusCode: 200, Method: "GET", Path: "/box/hashicorp/precise64/version/0.5/provider/id/upload", Response: `{"upload_path": "` + s.URL + `/box-upload-path"}`},
stubResponse{StatusCode: 200, Method: "PUT", Path: "/box/hashicorp/precise64/version/0.5/release"},
}
server := newStackServer(stack)
defer server.Close()
config := testGoodConfig()
config["vagrant_cloud_url"] = server.URL
config["no_direct_upload"] = true
var p PostProcessor
err = p.Configure(config)
if err != nil {
t.Fatalf("err: %s", err)
}
_, _, _, err = p.PostProcess(context.Background(), testUi(), artifact)
if err != nil {
t.Fatalf("err: %s", err)
}
}
func TestPostProcessor_PostProcess_uploadsAndNoRelease(t *testing.T) {
files := tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", `{"provider": "virtualbox"}`},
}
boxfile, err := createBox(files)
if err != nil {
t.Fatalf("%s", err)
}
defer os.Remove(boxfile.Name())
artifact := &packersdk.MockArtifact{
BuilderIdValue: "mitchellh.post-processor.vagrant",
FilesValue: []string{boxfile.Name()},
}
s := newStackServer([]stubResponse{stubResponse{StatusCode: 200, Method: "PUT", Path: "/box-upload-path"}})
defer s.Close()
stack := []stubResponse{
stubResponse{StatusCode: 200, Method: "GET", Path: "/authenticate"},
stubResponse{StatusCode: 200, Method: "GET", Path: "/box/hashicorp/precise64", Response: `{"tag": "hashicorp/precise64"}`},
stubResponse{StatusCode: 200, Method: "POST", Path: "/box/hashicorp/precise64/versions", Response: `{}`},
stubResponse{StatusCode: 200, Method: "POST", Path: "/box/hashicorp/precise64/version/0.5/providers", Response: `{}`},
stubResponse{StatusCode: 200, Method: "GET", Path: "/box/hashicorp/precise64/version/0.5/provider/id/upload", Response: `{"upload_path": "` + s.URL + `/box-upload-path"}`},
}
server := newStackServer(stack)
defer server.Close()
config := testGoodConfig()
config["vagrant_cloud_url"] = server.URL
config["no_direct_upload"] = true
config["no_release"] = true
var p PostProcessor
err = p.Configure(config)
if err != nil {
t.Fatalf("err: %s", err)
}
_, _, _, err = p.PostProcess(context.Background(), testUi(), artifact)
if err != nil {
t.Fatalf("err: %s", err)
}
}
func TestPostProcessor_PostProcess_directUpload5GFile(t *testing.T) {
// Disable test on Windows due to unreliable sparse file creation
if runtime.GOOS == "windows" {
return
}
// Boxes up to 5GB are supported for direct upload so
// set the box asset to be 5GB exactly
fSize := int64(5368709120)
files := tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", `{"provider": "virtualbox"}`},
}
f, err := createBox(files)
if err != nil {
t.Fatalf("%s", err)
}
defer os.Remove(f.Name())
if err := expandFile(f, fSize); err != nil {
t.Fatalf("failed to expand box file - %s", err)
}
artifact := &packersdk.MockArtifact{
BuilderIdValue: "mitchellh.post-processor.vagrant",
FilesValue: []string{f.Name()},
}
f.Close()
s := newStackServer(
[]stubResponse{
stubResponse{StatusCode: 200, Method: "PUT", Path: "/box-upload-path"},
},
)
defer s.Close()
stack := []stubResponse{
stubResponse{StatusCode: 200, Method: "GET", Path: "/authenticate"},
stubResponse{StatusCode: 200, Method: "GET", Path: "/box/hashicorp/precise64", Response: `{"tag": "hashicorp/precise64"}`},
stubResponse{StatusCode: 200, Method: "POST", Path: "/box/hashicorp/precise64/versions", Response: `{}`},
stubResponse{StatusCode: 200, Method: "POST", Path: "/box/hashicorp/precise64/version/0.5/providers", Response: `{}`},
stubResponse{StatusCode: 200, Method: "GET", Path: "/box/hashicorp/precise64/version/0.5/provider/id/upload/direct"},
stubResponse{StatusCode: 200, Method: "PUT", Path: "/box-upload-complete"},
}
server := newStackServer(stack)
defer server.Close()
config := testGoodConfig()
config["vagrant_cloud_url"] = server.URL
config["no_release"] = true
// Set response here so we have API server URL available
stack[4].Response = `{"upload_path": "` + s.URL + `/box-upload-path", "callback": "` + server.URL + `/box-upload-complete"}`
var p PostProcessor
err = p.Configure(config)
if err != nil {
t.Fatalf("err: %s", err)
}
_, _, _, err = p.PostProcess(context.Background(), testUi(), artifact)
if err != nil {
t.Fatalf("err: %s", err)
}
}
func TestPostProcessor_PostProcess_directUploadOver5GFile(t *testing.T) {
// Disable test on Windows due to unreliable sparse file creation
if runtime.GOOS == "windows" {
return
}
// Boxes over 5GB are not supported for direct upload so
// set the box asset to be one byte over 5GB
fSize := int64(5368709121)
files := tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", `{"provider": "virtualbox"}`},
}
f, err := createBox(files)
if err != nil {
t.Fatalf("%s", err)
}
defer os.Remove(f.Name())
if err := expandFile(f, fSize); err != nil {
t.Fatalf("failed to expand box file - %s", err)
}
f.Close()
artifact := &packersdk.MockArtifact{
BuilderIdValue: "mitchellh.post-processor.vagrant",
FilesValue: []string{f.Name()},
}
s := newStackServer(
[]stubResponse{
stubResponse{StatusCode: 200, Method: "PUT", Path: "/box-upload-path"},
},
)
defer s.Close()
stack := []stubResponse{
stubResponse{StatusCode: 200, Method: "GET", Path: "/authenticate"},
stubResponse{StatusCode: 200, Method: "GET", Path: "/box/hashicorp/precise64", Response: `{"tag": "hashicorp/precise64"}`},
stubResponse{StatusCode: 200, Method: "POST", Path: "/box/hashicorp/precise64/versions", Response: `{}`},
stubResponse{StatusCode: 200, Method: "POST", Path: "/box/hashicorp/precise64/version/0.5/providers", Response: `{}`},
stubResponse{StatusCode: 200, Method: "GET", Path: "/box/hashicorp/precise64/version/0.5/provider/id/upload", Response: `{"upload_path": "` + s.URL + `/box-upload-path"}`},
}
server := newStackServer(stack)
defer server.Close()
config := testGoodConfig()
config["vagrant_cloud_url"] = server.URL
config["no_release"] = true
var p PostProcessor
err = p.Configure(config)
if err != nil {
t.Fatalf("err: %s", err)
}
_, _, _, err = p.PostProcess(context.Background(), testUi(), artifact)
if err != nil {
t.Fatalf("err: %s", err)
}
}
func TestPostProcessor_PostProcess_uploadsDirectAndReleases(t *testing.T) {
files := tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", `{"provider": "virtualbox"}`},
}
boxfile, err := createBox(files)
if err != nil {
t.Fatalf("%s", err)
}
defer os.Remove(boxfile.Name())
artifact := &packersdk.MockArtifact{
BuilderIdValue: "mitchellh.post-processor.vagrant",
FilesValue: []string{boxfile.Name()},
}
s := newStackServer(
[]stubResponse{
stubResponse{StatusCode: 200, Method: "PUT", Path: "/box-upload-path"},
},
)
defer s.Close()
stack := []stubResponse{
stubResponse{StatusCode: 200, Method: "GET", Path: "/authenticate"},
stubResponse{StatusCode: 200, Method: "GET", Path: "/box/hashicorp/precise64", Response: `{"tag": "hashicorp/precise64"}`},
stubResponse{StatusCode: 200, Method: "POST", Path: "/box/hashicorp/precise64/versions", Response: `{}`},
stubResponse{StatusCode: 200, Method: "POST", Path: "/box/hashicorp/precise64/version/0.5/providers", Response: `{}`},
stubResponse{StatusCode: 200, Method: "GET", Path: "/box/hashicorp/precise64/version/0.5/provider/id/upload/direct"},
stubResponse{StatusCode: 200, Method: "PUT", Path: "/box-upload-complete"},
stubResponse{StatusCode: 200, Method: "PUT", Path: "/box/hashicorp/precise64/version/0.5/release"},
}
server := newStackServer(stack)
defer server.Close()
config := testGoodConfig()
config["vagrant_cloud_url"] = server.URL
// Set response here so we have API server URL available
stack[4].Response = `{"upload_path": "` + s.URL + `/box-upload-path", "callback": "` + server.URL + `/box-upload-complete"}`
var p PostProcessor
err = p.Configure(config)
if err != nil {
t.Fatalf("err: %s", err)
}
_, _, _, err = p.PostProcess(context.Background(), testUi(), artifact)
if err != nil {
t.Fatalf("err: %s", err)
}
}
func testUi() *packersdk.BasicUi {
return &packersdk.BasicUi{
Reader: new(bytes.Buffer),
Writer: new(bytes.Buffer),
}
}
func TestPostProcessor_ImplementsPostProcessor(t *testing.T) {
var _ packersdk.PostProcessor = new(PostProcessor)
}
func TestProviderFromBuilderName(t *testing.T) {
if providerFromBuilderName("foobar") != "foobar" {
t.Fatal("should copy unknown provider")
}
if providerFromBuilderName("vmware") != "vmware_desktop" {
t.Fatal("should convert provider")
}
}
func TestProviderFromVagrantBox_missing_box(t *testing.T) {
// Bad: Box does not exist
boxfile := "i_dont_exist.box"
_, err := providerFromVagrantBox(boxfile)
if err == nil {
t.Fatal("Should have error as box file does not exist")
}
t.Logf("%s", err)
}
func TestProviderFromVagrantBox_empty_box(t *testing.T) {
// Bad: Empty box file
boxfile, err := newBoxFile()
if err != nil {
t.Fatalf("%s", err)
}
defer os.Remove(boxfile.Name())
_, err = providerFromVagrantBox(boxfile.Name())
if err == nil {
t.Fatal("Should have error as box file is empty")
}
t.Logf("%s", err)
}
func TestProviderFromVagrantBox_gzip_only_box(t *testing.T) {
boxfile, err := newBoxFile()
if err != nil {
t.Fatalf("%s", err)
}
defer os.Remove(boxfile.Name())
// Bad: Box is just a plain gzip file
aw := gzip.NewWriter(boxfile)
_, err = aw.Write([]byte("foo content"))
if err != nil {
t.Fatal("Error zipping test box file")
}
aw.Close() // Flush the gzipped contents to file
_, err = providerFromVagrantBox(boxfile.Name())
if err == nil {
t.Fatalf("Should have error as box file is a plain gzip file: %s", err)
}
t.Logf("%s", err)
}
func TestProviderFromVagrantBox_no_files_in_archive(t *testing.T) {
// Bad: Box contains no files
boxfile, err := createBox(tarFiles{})
if err != nil {
t.Fatalf("Error creating test box: %s", err)
}
defer os.Remove(boxfile.Name())
_, err = providerFromVagrantBox(boxfile.Name())
if err == nil {
t.Fatalf("Should have error as box file has no contents")
}
t.Logf("%s", err)
}
func TestProviderFromVagrantBox_no_metadata(t *testing.T) {
// Bad: Box contains no metadata/metadata.json file
files := tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
}
boxfile, err := createBox(files)
if err != nil {
t.Fatalf("Error creating test box: %s", err)
}
defer os.Remove(boxfile.Name())
_, err = providerFromVagrantBox(boxfile.Name())
if err == nil {
t.Fatalf("Should have error as box file does not include metadata.json file")
}
t.Logf("%s", err)
}
func TestProviderFromVagrantBox_metadata_empty(t *testing.T) {
// Bad: Create a box with an empty metadata.json file
files := tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", ""},
}
boxfile, err := createBox(files)
if err != nil {
t.Fatalf("Error creating test box: %s", err)
}
defer os.Remove(boxfile.Name())
_, err = providerFromVagrantBox(boxfile.Name())
if err == nil {
t.Fatalf("Should have error as box files metadata.json file is empty")
}
t.Logf("%s", err)
}
func TestProviderFromVagrantBox_metadata_bad_json(t *testing.T) {
// Bad: Create a box with bad JSON in the metadata.json file
files := tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", "{provider: badjson}"},
}
boxfile, err := createBox(files)
if err != nil {
t.Fatalf("Error creating test box: %s", err)
}
defer os.Remove(boxfile.Name())
_, err = providerFromVagrantBox(boxfile.Name())
if err == nil {
t.Fatalf("Should have error as box files metadata.json file contains badly formatted JSON")
}
t.Logf("%s", err)
}
func TestProviderFromVagrantBox_metadata_no_provider_key(t *testing.T) {
// Bad: Create a box with no 'provider' key in the metadata.json file
files := tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", `{"cows":"moo"}`},
}
boxfile, err := createBox(files)
if err != nil {
t.Fatalf("Error creating test box: %s", err)
}
defer os.Remove(boxfile.Name())
_, err = providerFromVagrantBox(boxfile.Name())
if err == nil {
t.Fatalf("Should have error as provider key/value pair is missing from boxes metadata.json file")
}
t.Logf("%s", err)
}
func TestProviderFromVagrantBox_metadata_provider_value_empty(t *testing.T) {
// Bad: The boxes metadata.json file 'provider' key has an empty value
files := tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", `{"provider":""}`},
}
boxfile, err := createBox(files)
if err != nil {
t.Fatalf("Error creating test box: %s", err)
}
defer os.Remove(boxfile.Name())
_, err = providerFromVagrantBox(boxfile.Name())
if err == nil {
t.Fatalf("Should have error as value associated with 'provider' key in boxes metadata.json file is empty")
}
t.Logf("%s", err)
}
func TestProviderFromVagrantBox_metadata_ok(t *testing.T) {
// Good: The boxes metadata.json file has the 'provider' key/value pair
expectedProvider := "virtualbox"
files := tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", `{"provider":"` + expectedProvider + `"}`},
}
boxfile, err := createBox(files)
if err != nil {
t.Fatalf("Error creating test box: %s", err)
}
defer os.Remove(boxfile.Name())
provider, err := providerFromVagrantBox(boxfile.Name())
if err != nil {
t.Fatalf("error getting provider from vagrant box %s:%v", boxfile.Name(), err)
}
assert.Equal(t, expectedProvider, provider, "Error: Expected provider: '%s'. Got '%s'", expectedProvider, provider)
t.Logf("Expected provider '%s'. Got provider '%s'", expectedProvider, provider)
}
func TestGetProvider_artifice(t *testing.T) {
expectedProvider := "virtualbox"
files := tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", `{"provider":"` + expectedProvider + `"}`},
}
boxfile, err := createBox(files)
if err != nil {
t.Fatalf("Error creating test box: %s", err)
}
defer os.Remove(boxfile.Name())
provider, err := getProvider("", boxfile.Name(), "artifice")
if err != nil {
t.Fatalf("error getting provider %s:%v", boxfile.Name(), err)
}
assert.Equal(t, expectedProvider, provider, "Error: Expected provider: '%s'. Got '%s'", expectedProvider, provider)
t.Logf("Expected provider '%s'. Got provider '%s'", expectedProvider, provider)
}
func TestGetProvider_other(t *testing.T) {
expectedProvider := "virtualbox"
provider, _ := getProvider(expectedProvider, "foo.box", "other")
assert.Equal(t, expectedProvider, provider, "Error: Expected provider: '%s'. Got '%s'", expectedProvider, provider)
t.Logf("Expected provider '%s'. Got provider '%s'", expectedProvider, provider)
}
func newBoxFile() (boxfile *os.File, err error) {
boxfile, err = ioutil.TempFile(os.TempDir(), "test*.box")
if err != nil {
return boxfile, fmt.Errorf("Error creating test box file: %s", err)
}
return boxfile, nil
}
func createBox(files tarFiles) (boxfile *os.File, err error) {
boxfile, err = newBoxFile()
if err != nil {
return boxfile, err
}
// Box files are gzipped tar archives
aw := gzip.NewWriter(boxfile)
tw := tar.NewWriter(aw)
// Add each file to the box
for _, file := range files {
// Create and write the tar file header
hdr := &tar.Header{
Name: file.Name,
Mode: 0644,
Size: int64(len(file.Body)),
}
err = tw.WriteHeader(hdr)
if err != nil {
return boxfile, fmt.Errorf("Error writing box tar file header: %s", err)
}
// Write the file contents
_, err = tw.Write([]byte(file.Body))
if err != nil {
return boxfile, fmt.Errorf("Error writing box tar file contents: %s", err)
}
}
// Flush and close each writer
err = tw.Close()
if err != nil {
return boxfile, fmt.Errorf("Error flushing tar file contents: %s", err)
}
err = aw.Close()
if err != nil {
return boxfile, fmt.Errorf("Error flushing gzip file contents: %s", err)
}
return boxfile, nil
}
func expandFile(f *os.File, finalSize int64) (err error) {
s, err := f.Stat()
if err != nil {
return
}
size := finalSize - s.Size()
if size < 1 {
return
}
if _, err = f.Seek(size-1, 2); err != nil {
return
}
if _, err = f.Write([]byte{0}); err != nil {
return
}
return nil
}
@@ -0,0 +1,13 @@
package version
import (
"github.com/hashicorp/packer-plugin-sdk/version"
packerVersion "github.com/hashicorp/packer/version"
)
var VagrantCloudPluginVersion *version.PluginVersion
func init() {
VagrantCloudPluginVersion = version.InitializePluginVersion(
packerVersion.Version, packerVersion.VersionPrerelease)
}
+22
View File
@@ -0,0 +1,22 @@
package vagrant
import (
"testing"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
)
func TestArtifact_ImplementsArtifact(t *testing.T) {
var raw interface{}
raw = &Artifact{}
if _, ok := raw.(packersdk.Artifact); !ok {
t.Fatalf("Artifact should be a Artifact")
}
}
func TestArtifact_Id(t *testing.T) {
artifact := NewArtifact("vmware", "./")
if artifact.Id() != "vmware" {
t.Fatalf("should return name as Id")
}
}
+37
View File
@@ -0,0 +1,37 @@
package vagrant
import (
"strings"
"testing"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
)
func TestAWSProvider_impl(t *testing.T) {
var _ Provider = new(AWSProvider)
}
func TestAWSProvider_KeepInputArtifact(t *testing.T) {
p := new(AWSProvider)
if !p.KeepInputArtifact() {
t.Fatal("should keep input artifact")
}
}
func TestAWSProvider_ArtifactId(t *testing.T) {
p := new(AWSProvider)
ui := testUi()
artifact := &packersdk.MockArtifact{
IdValue: "us-east-1:ami-1234",
}
vagrantfile, _, err := p.Process(ui, artifact, "foo")
if err != nil {
t.Fatalf("should not have error: %s", err)
}
result := `aws.region_config "us-east-1", ami: "ami-1234"`
if !strings.Contains(vagrantfile, result) {
t.Fatalf("wrong substitution: %s", vagrantfile)
}
}
+94
View File
@@ -0,0 +1,94 @@
package vagrant
import (
"strings"
"testing"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
)
func TestAzureProvider_impl(t *testing.T) {
var _ Provider = new(AzureProvider)
}
func TestAzureProvider_KeepInputArtifact(t *testing.T) {
p := new(AzureProvider)
if !p.KeepInputArtifact() {
t.Fatal("should keep input artifact")
}
}
func TestAzureProvider_ManagedImage(t *testing.T) {
p := new(AzureProvider)
ui := testUi()
artifact := &packersdk.MockArtifact{
StringValue: `Azure.ResourceManagement.VMImage:
OSType: Linux
ManagedImageResourceGroupName: packerruns
ManagedImageName: packer-1533651633
ManagedImageId: /subscriptions/e6229913-d9c3-4ddd-99a4-9e1ef3beaa1b/resourceGroups/packerruns/providers/Microsoft.Compute/images/packer-1533675589
ManagedImageLocation: westus`,
}
vagrantfile, _, err := p.Process(ui, artifact, "foo")
if err != nil {
t.Fatalf("should not have error: %s", err)
}
result := `azure.location = "westus"`
if !strings.Contains(vagrantfile, result) {
t.Fatalf("wrong substitution: %s", vagrantfile)
}
result = `azure.vm_managed_image_id = "/subscriptions/e6229913-d9c3-4ddd-99a4-9e1ef3beaa1b/resourceGroups/packerruns/providers/Microsoft.Compute/images/packer-1533675589"`
if !strings.Contains(vagrantfile, result) {
t.Fatalf("wrong substitution: %s", vagrantfile)
}
// DO NOT set resource group in Vagrantfile, it should be separate from the image
result = `azure.resource_group_name`
if strings.Contains(vagrantfile, result) {
t.Fatalf("wrong substitution: %s", vagrantfile)
}
result = `azure.vm_operating_system`
if strings.Contains(vagrantfile, result) {
t.Fatalf("wrong substitution: %s", vagrantfile)
}
}
func TestAzureProvider_VHD(t *testing.T) {
p := new(AzureProvider)
ui := testUi()
artifact := &packersdk.MockArtifact{
IdValue: "https://packerbuildswest.blob.core.windows.net/system/Microsoft.Compute/Images/images/packer-osDisk.96ed2120-591d-4900-95b0-ee8e985f2213.vhd",
StringValue: `Azure.ResourceManagement.VMImage:
OSType: Linux
StorageAccountLocation: westus
OSDiskUri: https://packerbuildswest.blob.core.windows.net/system/Microsoft.Compute/Images/images/packer-osDisk.96ed2120-591d-4900-95b0-ee8e985f2213.vhd
OSDiskUriReadOnlySas: https://packerbuildswest.blob.core.windows.net/system/Microsoft.Compute/Images/images/packer-osDisk.96ed2120-591d-4900-95b0-ee8e985f2213.vhd?se=2018-09-07T18%3A36%3A34Z&sig=xUiFvwAviPYoP%2Bc91vErqvwYR1eK4x%2BAx7YLMe84zzU%3D&sp=r&sr=b&sv=2016-05-31
TemplateUri: https://packerbuildswest.blob.core.windows.net/system/Microsoft.Compute/Images/images/packer-vmTemplate.96ed2120-591d-4900-95b0-ee8e985f2213.json
TemplateUriReadOnlySas: https://packerbuildswest.blob.core.windows.net/system/Microsoft.Compute/Images/images/packer-vmTemplate.96ed2120-591d-4900-95b0-ee8e985f2213.json?se=2018-09-07T18%3A36%3A34Z&sig=lDxePyAUCZbfkB5ddiofimXfwk5INn%2F9E2BsnqIKC9Q%3D&sp=r&sr=b&sv=2016-05-31`,
}
vagrantfile, _, err := p.Process(ui, artifact, "foo")
if err != nil {
t.Fatalf("should not have error: %s", err)
}
result := `azure.location = "westus"`
if !strings.Contains(vagrantfile, result) {
t.Fatalf("wrong substitution: %s", vagrantfile)
}
result = `azure.vm_vhd_uri = "https://packerbuildswest.blob.core.windows.net/system/Microsoft.Compute/Images/images/packer-osDisk.96ed2120-591d-4900-95b0-ee8e985f2213.vhd"`
if !strings.Contains(vagrantfile, result) {
t.Fatalf("wrong substitution: %s", vagrantfile)
}
result = `azure.vm_operating_system = "Linux"`
if !strings.Contains(vagrantfile, result) {
t.Fatalf("wrong substitution: %s", vagrantfile)
}
// DO NOT set resource group in Vagrantfile, it should be separate from the image
result = `azure.resource_group_name`
if strings.Contains(vagrantfile, result) {
t.Fatalf("wrong substitution: %s", vagrantfile)
}
}
@@ -0,0 +1,41 @@
package vagrant
import (
"strings"
"testing"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
)
func TestDigitalOceanProvider_impl(t *testing.T) {
var _ Provider = new(DigitalOceanProvider)
}
func TestDigitalOceanProvider_KeepInputArtifact(t *testing.T) {
p := new(DigitalOceanProvider)
if !p.KeepInputArtifact() {
t.Fatal("should keep input artifact")
}
}
func TestDigitalOceanProvider_ArtifactId(t *testing.T) {
p := new(DigitalOceanProvider)
ui := testUi()
artifact := &packersdk.MockArtifact{
IdValue: "San Francisco:42",
}
vagrantfile, _, err := p.Process(ui, artifact, "foo")
if err != nil {
t.Fatalf("should not have error: %s", err)
}
image := `digital_ocean.image = "42"`
if !strings.Contains(vagrantfile, image) {
t.Fatalf("wrong image substitution: %s", vagrantfile)
}
region := `digital_ocean.region = "San Francisco"`
if !strings.Contains(vagrantfile, region) {
t.Fatalf("wrong region substitution: %s", vagrantfile)
}
}
+9
View File
@@ -0,0 +1,9 @@
package vagrant
import (
"testing"
)
func TestDockerProvider_impl(t *testing.T) {
var _ Provider = new(DockerProvider)
}
+37
View File
@@ -0,0 +1,37 @@
package vagrant
import (
"strings"
"testing"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
)
func TestGoogleProvider_impl(t *testing.T) {
var _ Provider = new(GoogleProvider)
}
func TestGoogleProvider_KeepInputArtifact(t *testing.T) {
p := new(GoogleProvider)
if !p.KeepInputArtifact() {
t.Fatal("should keep input artifact")
}
}
func TestGoogleProvider_ArtifactId(t *testing.T) {
p := new(GoogleProvider)
ui := testUi()
artifact := &packersdk.MockArtifact{
IdValue: "packer-1234",
}
vagrantfile, _, err := p.Process(ui, artifact, "foo")
if err != nil {
t.Fatalf("should not have error: %s", err)
}
result := `google.image = "packer-1234"`
if !strings.Contains(vagrantfile, result) {
t.Fatalf("wrong substitution: %s", vagrantfile)
}
}

Some files were not shown because too many files have changed in this diff Show More