Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6ad1024bd8 | |||
| c23b6a1b12 | |||
| 7583fd9d85 | |||
| d6904502ac | |||
| 2061aa9e69 | |||
| cbe06050b4 | |||
| d22ba61ae0 | |||
| 9eaad88ac0 | |||
| 20faaef05c | |||
| d0a4a71da8 | |||
| 3af472be9a | |||
| 5a00020830 | |||
| 6094c97998 | |||
| 1a41eac70b | |||
| 7a85b7328e | |||
| 3dac34766c | |||
| 642ed07476 | |||
| 88f8feecfe |
@@ -20,6 +20,7 @@ async function checkPluginDocs() {
|
||||
console.log(`\n${COLOR_BLUE}${repo}${COLOR_RESET} | ${title}`);
|
||||
console.log(`Fetching docs from release "${version}" …`);
|
||||
try {
|
||||
// Validate that all required properties are present
|
||||
const undefinedProps = ["title", "repo", "version", "path"].filter(
|
||||
(key) => typeof pluginEntry[key] == "undefined"
|
||||
);
|
||||
@@ -34,6 +35,22 @@ async function checkPluginDocs() {
|
||||
)} are defined. Additional information on this configuration can be found in "website/README.md".`
|
||||
);
|
||||
}
|
||||
// Validate pluginTier property
|
||||
const { pluginTier } = pluginEntry;
|
||||
if (typeof pluginTier !== "undefined") {
|
||||
const validPluginTiers = ["official", "community"];
|
||||
const isValid = validPluginTiers.indexOf(pluginTier) !== -1;
|
||||
if (!isValid) {
|
||||
throw new Error(
|
||||
`Failed to validate plugin docs config. Invalid pluginTier "${pluginTier}" found for "${
|
||||
title || pluginEntry.path || repo
|
||||
}". In "website/data/docs-remote-plugins.json", the optional pluginTier property must be one of ${JSON.stringify(
|
||||
validPluginTiers
|
||||
)}. The pluginTier property can also be omitted, in which case it will be determined from the plugin repository owner.`
|
||||
);
|
||||
}
|
||||
}
|
||||
// Attempt to fetch plugin docs files
|
||||
const docsMdxFiles = await fetchPluginDocs({ repo, tag: version });
|
||||
const mdxFilesByComponent = docsMdxFiles.reduce((acc, mdxFile) => {
|
||||
const componentType = mdxFile.filePath.split("/")[1];
|
||||
|
||||
@@ -43,9 +43,6 @@
|
||||
/builder/triton/ @sean-
|
||||
/website/pages/docs/builders/triton* @sean-
|
||||
|
||||
/builder/ncloud/ @YuSungDuk
|
||||
/website/pages/docs/builders/ncloud* @YuSungDuk
|
||||
|
||||
/builder/proxmox/ @carlpett
|
||||
/website/pages/docs/builders/proxmox* @carlpett
|
||||
|
||||
@@ -68,15 +65,10 @@
|
||||
/builder/yandex/ @GennadySpb @alexanderKhaustov @seukyaso
|
||||
/website/pages/docs/builders/yandex* @GennadySpb @alexanderKhaustov @seukyaso
|
||||
|
||||
/builder/osc/ @marinsalinas @Hakujou @outscale-mgo
|
||||
/website/pages/docs/builders/osc* @marinsalinas @Hakujou @outscale-mgo
|
||||
|
||||
/examples/tencentcloud/ @likexian
|
||||
/builder/tencentcloud/ @likexian
|
||||
/website/pages/docs/builders/tencentcloud* @likexian
|
||||
|
||||
|
||||
|
||||
# provisioners
|
||||
|
||||
/examples/ansible/ @bhcleek
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
package ncloud
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testConfig() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"access_key": "access_key",
|
||||
"secret_key": "secret_key",
|
||||
"server_image_product_code": "SPSW0WINNT000016",
|
||||
"server_product_code": "SPSVRSSD00000011",
|
||||
"server_image_name": "packer-test {{timestamp}}",
|
||||
"server_image_description": "server description",
|
||||
"block_storage_size": 100,
|
||||
"user_data": "#!/bin/sh\nyum install -y httpd\ntouch /var/www/html/index.html\nchkconfig --level 2345 httpd on",
|
||||
"region": "Korea",
|
||||
"access_control_group_configuration_no": "33",
|
||||
"communicator": "ssh",
|
||||
"ssh_username": "root",
|
||||
}
|
||||
}
|
||||
|
||||
func testConfigForMemberServerImage() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"access_key": "access_key",
|
||||
"secret_key": "secret_key",
|
||||
"server_product_code": "SPSVRSSD00000011",
|
||||
"member_server_image_no": "2440",
|
||||
"server_image_name": "packer-test {{timestamp}}",
|
||||
"server_image_description": "server description",
|
||||
"block_storage_size": 100,
|
||||
"user_data": "#!/bin/sh\nyum install -y httpd\ntouch /var/www/html/index.html\nchkconfig --level 2345 httpd on",
|
||||
"region": "Korea",
|
||||
"access_control_group_configuration_no": "33",
|
||||
"communicator": "ssh",
|
||||
"ssh_username": "root",
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigWithServerImageProductCode(t *testing.T) {
|
||||
raw := testConfig()
|
||||
|
||||
var c Config
|
||||
c.Prepare(raw)
|
||||
|
||||
if c.AccessKey != "access_key" {
|
||||
t.Errorf("Expected 'access_key' to be set to '%s', but got '%s'.", raw["access_key"], c.AccessKey)
|
||||
}
|
||||
|
||||
if c.SecretKey != "secret_key" {
|
||||
t.Errorf("Expected 'secret_key' to be set to '%s', but got '%s'.", raw["secret_key"], c.SecretKey)
|
||||
}
|
||||
|
||||
if c.ServerImageProductCode != "SPSW0WINNT000016" {
|
||||
t.Errorf("Expected 'server_image_product_code' to be set to '%s', but got '%s'.", raw["server_image_product_code"], c.ServerImageProductCode)
|
||||
}
|
||||
|
||||
if c.ServerProductCode != "SPSVRSSD00000011" {
|
||||
t.Errorf("Expected 'server_product_code' to be set to '%s', but got '%s'.", raw["server_product_code"], c.ServerProductCode)
|
||||
}
|
||||
|
||||
if c.BlockStorageSize != 100 {
|
||||
t.Errorf("Expected 'block_storage_size' to be set to '%d', but got '%d'.", raw["block_storage_size"], c.BlockStorageSize)
|
||||
}
|
||||
|
||||
if c.ServerImageDescription != "server description" {
|
||||
t.Errorf("Expected 'server_image_description_key' to be set to '%s', but got '%s'.", raw["server_image_description"], c.ServerImageDescription)
|
||||
}
|
||||
|
||||
if c.Region != "Korea" {
|
||||
t.Errorf("Expected 'region' to be set to '%s', but got '%s'.", raw["server_image_description"], c.Region)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigWithMemberServerImageCode(t *testing.T) {
|
||||
raw := testConfigForMemberServerImage()
|
||||
|
||||
var c Config
|
||||
c.Prepare(raw)
|
||||
|
||||
if c.AccessKey != "access_key" {
|
||||
t.Errorf("Expected 'access_key' to be set to '%s', but got '%s'.", raw["access_key"], c.AccessKey)
|
||||
}
|
||||
|
||||
if c.SecretKey != "secret_key" {
|
||||
t.Errorf("Expected 'secret_key' to be set to '%s', but got '%s'.", raw["secret_key"], c.SecretKey)
|
||||
}
|
||||
|
||||
if c.MemberServerImageNo != "2440" {
|
||||
t.Errorf("Expected 'member_server_image_no' to be set to '%s', but got '%s'.", raw["member_server_image_no"], c.MemberServerImageNo)
|
||||
}
|
||||
|
||||
if c.ServerProductCode != "SPSVRSSD00000011" {
|
||||
t.Errorf("Expected 'server_product_code' to be set to '%s', but got '%s'.", raw["server_product_code"], c.ServerProductCode)
|
||||
}
|
||||
|
||||
if c.BlockStorageSize != 100 {
|
||||
t.Errorf("Expected 'block_storage_size' to be set to '%d', but got '%d'.", raw["block_storage_size"], c.BlockStorageSize)
|
||||
}
|
||||
|
||||
if c.ServerImageDescription != "server description" {
|
||||
t.Errorf("Expected 'server_image_description_key' to be set to '%s', but got '%s'.", raw["server_image_description"], c.ServerImageDescription)
|
||||
}
|
||||
|
||||
if c.Region != "Korea" {
|
||||
t.Errorf("Expected 'region' to be set to '%s', but got '%s'.", raw["server_image_description"], c.Region)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyConfig(t *testing.T) {
|
||||
raw := new(map[string]interface{})
|
||||
|
||||
var c Config
|
||||
_, err := c.Prepare(raw)
|
||||
|
||||
if err == nil {
|
||||
t.Error("Expected Config to require 'access_key', 'secret_key' and some mandatory fields, but it did not")
|
||||
}
|
||||
|
||||
if strings.Contains(err.Error(), "access_key is required") {
|
||||
t.Error("Expected Config to require 'access_key', but it did not")
|
||||
}
|
||||
|
||||
if strings.Contains(err.Error(), "secret_key is required") {
|
||||
t.Error("Expected Config to require 'secret_key', but it did not")
|
||||
}
|
||||
|
||||
if strings.Contains(err.Error(), "server_image_product_code or member_server_image_no is required") {
|
||||
t.Error("Expected Config to require 'server_image_product_code' or 'member_server_image_no', but it did not")
|
||||
}
|
||||
}
|
||||
|
||||
func TestExistsBothServerImageProductCodeAndMemberServerImageNoConfig(t *testing.T) {
|
||||
raw := map[string]interface{}{
|
||||
"access_key": "access_key",
|
||||
"secret_key": "secret_key",
|
||||
"server_image_product_code": "SPSW0WINNT000016",
|
||||
"server_product_code": "SPSVRSSD00000011",
|
||||
"member_server_image_no": "2440",
|
||||
}
|
||||
|
||||
var c Config
|
||||
_, err := c.Prepare(raw)
|
||||
|
||||
if strings.Contains(err.Error(), "Only one of server_image_product_code and member_server_image_no can be set") {
|
||||
t.Error("Expected Config to require Only one of 'server_image_product_code' and 'member_server_image_no' can be set, but it did not")
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package ncloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepCreateAccessControlGroupShouldFailIfOperationCreateAccessControlGroupFails(t *testing.T) {
|
||||
var testSubject = &StepCreateAccessControlGroup{
|
||||
CreateAccessControlGroup: func() (string, error) { return "", fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: &Config{
|
||||
Region: "Korea",
|
||||
SupportVPC: true,
|
||||
},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateAccessControlGroup()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateAccessControlGroupShouldPassIfOperationCreateAccessControlGroupPasses(t *testing.T) {
|
||||
var testSubject = &StepCreateAccessControlGroup{
|
||||
CreateAccessControlGroup: func() (string, error) { return "123", nil },
|
||||
AddAccessControlGroupRule: func(acgNo string) error {
|
||||
return nil
|
||||
},
|
||||
Say: func(message string) {},
|
||||
Error: func(error) {},
|
||||
Config: &Config{
|
||||
Region: "Korea",
|
||||
SupportVPC: true,
|
||||
},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateAccessControlGroup()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepCreateAccessControlGroup() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
return stateBag
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package ncloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepCreateBlockStorageInstanceShouldFailIfOperationCreateBlockStorageInstanceFails(t *testing.T) {
|
||||
|
||||
var testSubject = &StepCreateBlockStorage{
|
||||
CreateBlockStorage: func(serverInstanceNo string) (*string, error) { return nil, fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: new(Config),
|
||||
}
|
||||
|
||||
testSubject.Config.BlockStorageSize = 10
|
||||
|
||||
stateBag := createTestStateBagStepCreateBlockStorageInstance()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateBlockStorageInstanceShouldPassIfOperationCreateBlockStorageInstancePasses(t *testing.T) {
|
||||
var instanceNo = "a"
|
||||
var testSubject = &StepCreateBlockStorage{
|
||||
CreateBlockStorage: func(serverInstanceNo string) (*string, error) { return &instanceNo, nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: new(Config),
|
||||
}
|
||||
|
||||
testSubject.Config.BlockStorageSize = 10
|
||||
|
||||
stateBag := createTestStateBagStepCreateBlockStorageInstance()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepCreateBlockStorageInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("instance_no", "a")
|
||||
|
||||
return stateBag
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package ncloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepCreateInitScriptShouldFailIfOperationCreateInitScriptFails(t *testing.T) {
|
||||
var testSubject = &StepCreateInitScript{
|
||||
CreateInitScript: func() (string, error) { return "", fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: &Config{
|
||||
Region: "Korea",
|
||||
SupportVPC: true,
|
||||
UserData: "test",
|
||||
},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateInitScript()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateInitScriptShouldPassIfOperationCreateInitScriptPasses(t *testing.T) {
|
||||
var testSubject = &StepCreateInitScript{
|
||||
CreateInitScript: func() (string, error) { return "123", nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: &Config{
|
||||
Region: "Korea",
|
||||
SupportVPC: true,
|
||||
},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateInitScript()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepCreateInitScript() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
return stateBag
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package ncloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepCreateLoginKeyShouldFailIfOperationCreateLoginKeyFails(t *testing.T) {
|
||||
var testSubject = &StepCreateLoginKey{
|
||||
CreateLoginKey: func() (*LoginKey, error) { return nil, fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateLoginKey()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateLoginKeyShouldPassIfOperationCreateLoginKeyPasses(t *testing.T) {
|
||||
var testSubject = &StepCreateLoginKey{
|
||||
CreateLoginKey: func() (*LoginKey, error) { return &LoginKey{"a", "b"}, nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateLoginKey()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepCreateLoginKey() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
return stateBag
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package ncloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/ncloud"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/server"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepCreatePublicIPInstanceShouldFailIfOperationCreatePublicIPInstanceFails(t *testing.T) {
|
||||
var testSubject = &StepCreatePublicIP{
|
||||
CreatePublicIP: func(serverInstanceNo string) (*server.PublicIpInstance, error) {
|
||||
return nil, fmt.Errorf("!! Unit Test FAIL !!")
|
||||
},
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateServerImage()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreatePublicIPInstanceShouldPassIfOperationCreatePublicIPInstancePasses(t *testing.T) {
|
||||
c := new(Config)
|
||||
c.Comm.Prepare(nil)
|
||||
c.Comm.Type = "ssh"
|
||||
|
||||
var testSubject = &StepCreatePublicIP{
|
||||
CreatePublicIP: func(serverInstanceNo string) (*server.PublicIpInstance, error) {
|
||||
return &server.PublicIpInstance{PublicIpInstanceNo: ncloud.String("a"), PublicIp: ncloud.String("b")}, nil
|
||||
},
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: c,
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreatePublicIPInstance()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepCreatePublicIPInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("instance_no", "a")
|
||||
|
||||
return stateBag
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package ncloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/server"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepCreateServerImageShouldFailIfOperationCreateServerImageFails(t *testing.T) {
|
||||
var testSubject = &StepCreateServerImage{
|
||||
CreateServerImage: func(serverInstanceNo string) (*server.MemberServerImage, error) {
|
||||
return nil, fmt.Errorf("!! Unit Test FAIL !!")
|
||||
},
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateServerImage()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
func TestStepCreateServerImageShouldPassIfOperationCreateServerImagePasses(t *testing.T) {
|
||||
var testSubject = &StepCreateServerImage{
|
||||
CreateServerImage: func(serverInstanceNo string) (*server.MemberServerImage, error) { return nil, nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateServerImage()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepCreateServerImage() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("instance_no", "a")
|
||||
|
||||
return stateBag
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package ncloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepCreateServerInstanceShouldFailIfOperationCreateFails(t *testing.T) {
|
||||
var testSubject = &StepCreateServerInstance{
|
||||
CreateServerInstance: func(loginKeyName string, feeSystemTypeCode string, state multistep.StateBag) (string, error) {
|
||||
return "", fmt.Errorf("!! Unit Test FAIL !!")
|
||||
},
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateServerInstance()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateServerInstanceShouldPassIfOperationCreatePasses(t *testing.T) {
|
||||
var testSubject = &StepCreateServerInstance{
|
||||
CreateServerInstance: func(loginKeyName string, feeSystemTypeCode string, state multistep.StateBag) (string, error) {
|
||||
return "", nil
|
||||
},
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateServerInstance()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepCreateServerInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("login_key", &LoginKey{"a", "b"})
|
||||
stateBag.Put("zone_no", "1")
|
||||
|
||||
return stateBag
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package ncloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepDeleteBlockStorageInstanceShouldFailIfOperationDeleteBlockStorageInstanceFails(t *testing.T) {
|
||||
var testSubject = &StepDeleteBlockStorage{
|
||||
DeleteBlockStorage: func(blockStorageNo string) error { return fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: &Config{BlockStorageSize: 10},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepDeleteBlockStorageInstance()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepDeleteBlockStorageInstanceShouldPassIfOperationDeleteBlockStorageInstancePasses(t *testing.T) {
|
||||
var testSubject = &StepDeleteBlockStorage{
|
||||
DeleteBlockStorage: func(blockStorageNo string) error { return nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: &Config{BlockStorageSize: 10},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepDeleteBlockStorageInstance()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepDeleteBlockStorageInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("instance_no", "1")
|
||||
|
||||
return stateBag
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package ncloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepGetRootPasswordShouldFailIfOperationGetRootPasswordFails(t *testing.T) {
|
||||
var testSubject = &StepGetRootPassword{
|
||||
GetRootPassword: func(string, string) (string, error) { return "", fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: &Config{},
|
||||
}
|
||||
|
||||
stateBag := DeleteTestStateBagStepGetRootPassword()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepGetRootPasswordShouldPassIfOperationGetRootPasswordPasses(t *testing.T) {
|
||||
var testSubject = &StepGetRootPassword{
|
||||
GetRootPassword: func(string, string) (string, error) { return "a", nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: &Config{},
|
||||
}
|
||||
|
||||
stateBag := DeleteTestStateBagStepGetRootPassword()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteTestStateBagStepGetRootPassword() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("login_key", &LoginKey{"a", "b"})
|
||||
stateBag.Put("instance_no", "a")
|
||||
|
||||
return stateBag
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package ncloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepStopServerInstanceShouldFailIfOperationStopFails(t *testing.T) {
|
||||
var testSubject = &StepStopServerInstance{
|
||||
StopServerInstance: func(serverInstanceNo string) error { return fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepStopServerInstance()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepStopServerInstanceShouldPassIfOperationStopPasses(t *testing.T) {
|
||||
var testSubject = &StepStopServerInstance{
|
||||
StopServerInstance: func(serverInstanceNo string) error { return nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepStopServerInstance()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepStopServerInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("instance_no", "a")
|
||||
return stateBag
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package ncloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepTerminateServerInstanceShouldFailIfOperationTerminationFails(t *testing.T) {
|
||||
var testSubject = &StepTerminateServerInstance{
|
||||
TerminateServerInstance: func(serverInstanceNo string) error { return fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepTerminateServerInstance()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepTerminateServerInstanceShouldPassIfOperationTerminationPasses(t *testing.T) {
|
||||
var testSubject = &StepTerminateServerInstance{
|
||||
TerminateServerInstance: func(serverInstanceNo string) error { return nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepTerminateServerInstance()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepTerminateServerInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("instance_no", "a")
|
||||
return stateBag
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package ncloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepValidateTemplateShouldFailIfValidateFails(t *testing.T) {
|
||||
var testSubject = &StepValidateTemplate{
|
||||
Validate: func() error { return fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepValidateTemplate()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepValidateTemplateShouldPassIfValidatePasses(t *testing.T) {
|
||||
var testSubject = &StepValidateTemplate{
|
||||
Validate: func() error { return nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepValidateTemplate()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepValidateTemplate() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
return stateBag
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package version
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/packer-plugin-sdk/version"
|
||||
packerVersion "github.com/hashicorp/packer/version"
|
||||
)
|
||||
|
||||
var NCloudPluginVersion *version.PluginVersion
|
||||
|
||||
func init() {
|
||||
NCloudPluginVersion = version.InitializePluginVersion(
|
||||
packerVersion.Version, packerVersion.VersionPrerelease)
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
//TODO: explain how to delete the image.
|
||||
package bsu
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
builderT "github.com/hashicorp/packer/acctest"
|
||||
)
|
||||
|
||||
func TestBuilderAcc_basic(t *testing.T) {
|
||||
builderT.Test(t, builderT.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Builder: &Builder{},
|
||||
Template: testBuilderAccBasic,
|
||||
SkipArtifactTeardown: true,
|
||||
})
|
||||
}
|
||||
|
||||
func testAccPreCheck(t *testing.T) {
|
||||
}
|
||||
|
||||
const testBuilderAccBasic = `
|
||||
{
|
||||
"builders": [{
|
||||
"type": "test",
|
||||
"region": "eu-west-2",
|
||||
"vm_type": "t2.micro",
|
||||
"source_omi": "ami-abe953fa",
|
||||
"ssh_username": "outscale",
|
||||
"omi_name": "packer-test",
|
||||
"associate_public_ip_address": true,
|
||||
"force_deregister": true
|
||||
}]
|
||||
}
|
||||
`
|
||||
@@ -1,131 +0,0 @@
|
||||
package bsu
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
func testConfig() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"access_key": "foo",
|
||||
"secret_key": "bar",
|
||||
"source_omi": "foo",
|
||||
"vm_type": "foo",
|
||||
"region": "us-east-1",
|
||||
"ssh_username": "root",
|
||||
"omi_name": "foo",
|
||||
}
|
||||
}
|
||||
|
||||
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_BadType(t *testing.T) {
|
||||
b := &Builder{}
|
||||
c := map[string]interface{}{
|
||||
"access_key": []string{},
|
||||
}
|
||||
|
||||
_, warnings, err := b.Prepare(c)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatalf("prepare should fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_OMIName(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Test good
|
||||
config["omi_name"] = "foo"
|
||||
config["skip_region_validation"] = true
|
||||
_, warnings, err := b.Prepare(config)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
// Test bad
|
||||
config["omi_name"] = "foo {{"
|
||||
b = Builder{}
|
||||
_, warnings, err = b.Prepare(config)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Test bad
|
||||
delete(config, "omi_name")
|
||||
b = Builder{}
|
||||
_, warnings, err = b.Prepare(config)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_InvalidKey(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Add a random key
|
||||
config["i_should_not_be_valid"] = true
|
||||
_, warnings, err := b.Prepare(config)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Test good
|
||||
config["shutdown_behavior"] = "terminate"
|
||||
config["skip_region_validation"] = true
|
||||
_, warnings, err := b.Prepare(config)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
// Test good
|
||||
config["shutdown_behavior"] = "stop"
|
||||
_, warnings, err = b.Prepare(config)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
// Test bad
|
||||
config["shutdown_behavior"] = "foobar"
|
||||
_, warnings, err = b.Prepare(config)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package bsusurrogate
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
builderT "github.com/hashicorp/packer/acctest"
|
||||
)
|
||||
|
||||
func TestBuilderAcc_basic(t *testing.T) {
|
||||
builderT.Test(t, builderT.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Builder: &Builder{},
|
||||
Template: testBuilderAccBasic,
|
||||
SkipArtifactTeardown: true,
|
||||
})
|
||||
}
|
||||
|
||||
func testAccPreCheck(t *testing.T) {
|
||||
}
|
||||
|
||||
const testBuilderAccBasic = `
|
||||
{
|
||||
"builders": [{
|
||||
"type": "test",
|
||||
"region": "eu-west-2",
|
||||
"vm_type": "t2.micro",
|
||||
"source_omi": "ami-abe953fa",
|
||||
"ssh_username": "outscale",
|
||||
"omi_name": "packer-test {{timestamp}}",
|
||||
"omi_virtualization_type": "hvm",
|
||||
"subregion_name": "eu-west-2a",
|
||||
"launch_block_device_mappings" : [
|
||||
{
|
||||
"volume_type" : "io1",
|
||||
"device_name" : "/dev/xvdf",
|
||||
"delete_on_vm_deletion" : false,
|
||||
"volume_size" : 10,
|
||||
"iops": 300
|
||||
}
|
||||
],
|
||||
"omi_root_device":{
|
||||
"source_device_name": "/dev/xvdf",
|
||||
"device_name": "/dev/sda1",
|
||||
"delete_on_vm_deletion": true,
|
||||
"volume_size": 10,
|
||||
"volume_type": "standard"
|
||||
}
|
||||
|
||||
}]
|
||||
}
|
||||
`
|
||||
@@ -1,15 +0,0 @@
|
||||
package bsusurrogate
|
||||
|
||||
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.Fatal("Builder should be a builder")
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
//TODO: explain how to delete the image.
|
||||
package bsuvolume
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
builderT "github.com/hashicorp/packer/acctest"
|
||||
)
|
||||
|
||||
func TestBuilderAcc_basic(t *testing.T) {
|
||||
builderT.Test(t, builderT.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Builder: &Builder{},
|
||||
Template: testBuilderAccBasic,
|
||||
SkipArtifactTeardown: true,
|
||||
})
|
||||
}
|
||||
|
||||
func testAccPreCheck(t *testing.T) {
|
||||
}
|
||||
|
||||
const testBuilderAccBasic = `
|
||||
{
|
||||
"builders": [
|
||||
{
|
||||
"type": "test",
|
||||
"region": "eu-west-2",
|
||||
"vm_type": "t2.micro",
|
||||
"source_omi": "ami-abe953fa",
|
||||
"ssh_username": "outscale",
|
||||
"bsu_volumes": [
|
||||
{
|
||||
"volume_type": "gp2",
|
||||
"device_name": "/dev/xvdf",
|
||||
"delete_on_vm_deletion": false,
|
||||
"tags": {
|
||||
"zpool": "data",
|
||||
"Name": "Data1"
|
||||
},
|
||||
"volume_size": 10
|
||||
},
|
||||
{
|
||||
"volume_type": "gp2",
|
||||
"device_name": "/dev/xvdg",
|
||||
"tags": {
|
||||
"zpool": "data",
|
||||
"Name": "Data2"
|
||||
},
|
||||
"delete_on_vm_deletion": false,
|
||||
"volume_size": 10
|
||||
},
|
||||
{
|
||||
"volume_size": 10,
|
||||
"tags": {
|
||||
"Name": "Data3",
|
||||
"zpool": "data"
|
||||
},
|
||||
"delete_on_vm_deletion": false,
|
||||
"device_name": "/dev/xvdh",
|
||||
"volume_type": "gp2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
@@ -1,92 +0,0 @@
|
||||
package bsuvolume
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
func testConfig() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"access_key": "foo",
|
||||
"secret_key": "bar",
|
||||
"source_omi": "foo",
|
||||
"vm_type": "foo",
|
||||
"region": "us-east-1",
|
||||
"ssh_username": "root",
|
||||
}
|
||||
}
|
||||
|
||||
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_BadType(t *testing.T) {
|
||||
b := &Builder{}
|
||||
c := map[string]interface{}{
|
||||
"access_key": []string{},
|
||||
}
|
||||
|
||||
_, warnings, err := b.Prepare(c)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatalf("prepare should fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_InvalidKey(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Add a random key
|
||||
config["i_should_not_be_valid"] = true
|
||||
_, warnings, err := b.Prepare(config)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Test good
|
||||
config["shutdown_behavior"] = "terminate"
|
||||
config["skip_region_validation"] = true
|
||||
_, warnings, err := b.Prepare(config)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
// Test good
|
||||
config["shutdown_behavior"] = "stop"
|
||||
_, warnings, err = b.Prepare(config)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
// Test bad
|
||||
config["shutdown_behavior"] = "foobar"
|
||||
_, warnings, err = b.Prepare(config)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package chroot
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
func TestCommunicator_ImplementsCommunicator(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = &Communicator{}
|
||||
if _, ok := raw.(packersdk.Communicator); !ok {
|
||||
t.Fatalf("Communicator should be a communicator")
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package chroot
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCopyFilesCleanupFunc_ImplementsCleanupFunc(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = new(StepCopyFiles)
|
||||
if _, ok := raw.(Cleanup); !ok {
|
||||
t.Fatalf("cleanup func should be a CleanupFunc")
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testAccessConfig() *AccessConfig {
|
||||
return &AccessConfig{}
|
||||
}
|
||||
|
||||
func TestAccessConfigPrepare_Region(t *testing.T) {
|
||||
c := testAccessConfig()
|
||||
|
||||
c.RawRegion = "us-east-12"
|
||||
err := c.ValidateOSCRegion(c.RawRegion)
|
||||
if err == nil {
|
||||
t.Fatalf("should have region validation err: %s", c.RawRegion)
|
||||
}
|
||||
|
||||
c.RawRegion = "us-east-1"
|
||||
err = c.ValidateOSCRegion(c.RawRegion)
|
||||
if err == nil {
|
||||
t.Fatalf("should have region validation err: %s", c.RawRegion)
|
||||
}
|
||||
|
||||
c.RawRegion = "custom"
|
||||
err = c.ValidateOSCRegion(c.RawRegion)
|
||||
if err == nil {
|
||||
t.Fatalf("should have region validation err: %s", c.RawRegion)
|
||||
}
|
||||
|
||||
c.RawRegion = "custom"
|
||||
c.SkipValidation = true
|
||||
// testing whole prepare func here; this is checking that validation is
|
||||
// skipped, so we don't need a mock connection
|
||||
if err := c.Prepare(nil); err != nil {
|
||||
t.Fatalf("shouldn't have err: %s", err)
|
||||
}
|
||||
|
||||
c.SkipValidation = false
|
||||
c.RawRegion = ""
|
||||
if err := c.Prepare(nil); err != nil {
|
||||
t.Fatalf("shouldn't have err: %s", err)
|
||||
}
|
||||
}
|
||||
@@ -1,289 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/outscale/osc-sdk-go/osc"
|
||||
)
|
||||
|
||||
func TestBlockDevice_LaunchDevices(t *testing.T) {
|
||||
cases := []struct {
|
||||
Config *BlockDevice
|
||||
Result osc.BlockDeviceMappingVmCreation
|
||||
}{
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
SnapshotId: "snap-1234",
|
||||
VolumeType: "standard",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: osc.BlockDeviceMappingVmCreation{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: osc.BsuToCreate{
|
||||
SnapshotId: "snap-1234",
|
||||
VolumeType: "standard",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeSize: 8,
|
||||
},
|
||||
|
||||
Result: osc.BlockDeviceMappingVmCreation{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "io1",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
IOPS: 1000,
|
||||
},
|
||||
|
||||
Result: osc.BlockDeviceMappingVmCreation{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeType: "io1",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
Iops: 1000,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "gp2",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: osc.BlockDeviceMappingVmCreation{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeType: "gp2",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "gp2",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: osc.BlockDeviceMappingVmCreation{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeType: "gp2",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "standard",
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: osc.BlockDeviceMappingVmCreation{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeType: "standard",
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VirtualName: "ephemeral0",
|
||||
},
|
||||
|
||||
Result: osc.BlockDeviceMappingVmCreation{
|
||||
DeviceName: "/dev/sdb",
|
||||
VirtualDeviceName: "ephemeral0",
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
NoDevice: true,
|
||||
},
|
||||
|
||||
Result: osc.BlockDeviceMappingVmCreation{
|
||||
DeviceName: "/dev/sdb",
|
||||
NoDevice: "",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
|
||||
launchBlockDevices := LaunchBlockDevices{
|
||||
LaunchMappings: []BlockDevice{*tc.Config},
|
||||
}
|
||||
|
||||
expected := []osc.BlockDeviceMappingVmCreation{tc.Result}
|
||||
|
||||
launchResults := launchBlockDevices.BuildOSCLaunchDevices()
|
||||
if !reflect.DeepEqual(expected, launchResults) {
|
||||
t.Fatalf("Bad block device, \nexpected: %#v\n\ngot: %#v",
|
||||
expected, launchResults)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockDevice_OMI(t *testing.T) {
|
||||
cases := []struct {
|
||||
Config *BlockDevice
|
||||
Result osc.BlockDeviceMappingImage
|
||||
}{
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
SnapshotId: "snap-1234",
|
||||
VolumeType: "standard",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: osc.BlockDeviceMappingImage{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: osc.BsuToCreate{
|
||||
SnapshotId: "snap-1234",
|
||||
VolumeType: "standard",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: osc.BlockDeviceMappingImage{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "io1",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
IOPS: 1000,
|
||||
},
|
||||
|
||||
Result: osc.BlockDeviceMappingImage{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeType: "io1",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
Iops: 1000,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "gp2",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: osc.BlockDeviceMappingImage{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeType: "gp2",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "gp2",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: osc.BlockDeviceMappingImage{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeType: "gp2",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeType: "standard",
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: osc.BlockDeviceMappingImage{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeType: "standard",
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VirtualName: "ephemeral0",
|
||||
},
|
||||
|
||||
Result: osc.BlockDeviceMappingImage{
|
||||
DeviceName: "/dev/sdb",
|
||||
VirtualDeviceName: "ephemeral0",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
omiBlockDevices := OMIBlockDevices{
|
||||
OMIMappings: []BlockDevice{*tc.Config},
|
||||
}
|
||||
|
||||
expected := []osc.BlockDeviceMappingImage{tc.Result}
|
||||
|
||||
omiResults := omiBlockDevices.BuildOscOMIDevices()
|
||||
if !reflect.DeepEqual(expected, omiResults) {
|
||||
t.Fatalf("%d - Bad block device, \nexpected: %+#v\n\ngot: %+#v",
|
||||
i, expected, omiResults)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/outscale/osc-sdk-go/osc"
|
||||
)
|
||||
|
||||
func testImage() osc.Image {
|
||||
return osc.Image{
|
||||
ImageId: "ami-abcd1234",
|
||||
ImageName: "ami_test_name",
|
||||
Tags: []osc.ResourceTag{
|
||||
{
|
||||
Key: "key-1",
|
||||
Value: "value-1",
|
||||
},
|
||||
{
|
||||
Key: "key-2",
|
||||
Value: "value-2",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func testState() multistep.StateBag {
|
||||
state := new(multistep.BasicStateBag)
|
||||
return state
|
||||
}
|
||||
|
||||
func TestInterpolateBuildInfo_extractBuildInfo_noSourceImage(t *testing.T) {
|
||||
state := testState()
|
||||
buildInfo := extractBuildInfo("foo", state)
|
||||
|
||||
expected := BuildInfoTemplate{
|
||||
BuildRegion: "foo",
|
||||
}
|
||||
if !reflect.DeepEqual(*buildInfo, expected) {
|
||||
t.Fatalf("Unexpected BuildInfoTemplate: expected %#v got %#v\n", expected, *buildInfo)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInterpolateBuildInfo_extractBuildInfo_withSourceImage(t *testing.T) {
|
||||
state := testState()
|
||||
state.Put("source_image", testImage())
|
||||
buildInfo := extractBuildInfo("foo", state)
|
||||
|
||||
expected := BuildInfoTemplate{
|
||||
BuildRegion: "foo",
|
||||
SourceOMI: "ami-abcd1234",
|
||||
SourceOMIName: "ami_test_name",
|
||||
SourceOMITags: map[string]string{
|
||||
"key-1": "value-1",
|
||||
"key-2": "value-2",
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(*buildInfo, expected) {
|
||||
t.Fatalf("Unexpected BuildInfoTemplate: expected %#v got %#v\n", expected, *buildInfo)
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testOMIConfig() *OMIConfig {
|
||||
return &OMIConfig{
|
||||
OMIName: "foo",
|
||||
}
|
||||
}
|
||||
|
||||
func getFakeAccessConfig(region string) *AccessConfig {
|
||||
c := testAccessConfig()
|
||||
c.RawRegion = region
|
||||
return c
|
||||
}
|
||||
|
||||
func TestOMIConfigPrepare_name(t *testing.T) {
|
||||
c := testOMIConfig()
|
||||
accessConf := testAccessConfig()
|
||||
if err := c.Prepare(accessConf, nil); err != nil {
|
||||
t.Fatalf("shouldn't have err: %s", err)
|
||||
}
|
||||
|
||||
c.OMIName = ""
|
||||
if err := c.Prepare(accessConf, nil); err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOMIConfigPrepare_regions(t *testing.T) {
|
||||
c := testOMIConfig()
|
||||
c.OMIRegions = nil
|
||||
|
||||
var errs []error
|
||||
accessConf := testAccessConfig()
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatalf("shouldn't have err: %#v", errs)
|
||||
}
|
||||
|
||||
c.OMIRegions = []string{"us-east-1", "us-west-1"}
|
||||
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatalf("shouldn't have err: %#v", errs)
|
||||
}
|
||||
errs = errs[:0]
|
||||
|
||||
c.OMIRegions = []string{"us-east-1", "us-west-1", "us-east-1"}
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatalf("bad: %s", errs[0])
|
||||
}
|
||||
|
||||
expected := []string{"us-east-1", "us-west-1"}
|
||||
if !reflect.DeepEqual(c.OMIRegions, expected) {
|
||||
t.Fatalf("bad: %#v", c.OMIRegions)
|
||||
}
|
||||
|
||||
c.OMIRegions = []string{"custom"}
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatal("shouldn't have error")
|
||||
}
|
||||
|
||||
c.OMIRegions = []string{"us-east-1", "us-east-2", "us-west-1"}
|
||||
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatal(fmt.Sprintf("shouldn't have error: %s", errs[0]))
|
||||
}
|
||||
|
||||
c.OMIRegions = []string{"us-east-1", "us-east-2", "us-west-1"}
|
||||
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatal("should have passed; we are able to use default KMS key if not sharing")
|
||||
}
|
||||
|
||||
c.SnapshotAccountIDs = []string{"user-foo", "user-bar"}
|
||||
c.OMIRegions = []string{"us-east-1", "us-east-2", "us-west-1"}
|
||||
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatal("should have an error b/c can't use default KMS key if sharing")
|
||||
}
|
||||
|
||||
c.OMIRegions = []string{"us-east-1", "us-west-1"}
|
||||
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatal("should have error b/c theres a region in the key map that isn't in omi_regions")
|
||||
}
|
||||
|
||||
c.OMIRegions = []string{"us-east-1", "us-west-1", "us-east-2"}
|
||||
|
||||
c.SnapshotAccountIDs = []string{"foo", "bar"}
|
||||
c.OMIRegions = []string{"us-east-1", "us-west-1"}
|
||||
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatal("should have error b/c theres a region in in omi_regions that isn't in the key map")
|
||||
}
|
||||
|
||||
// allow rawregion to exist in omi_regions list.
|
||||
accessConf = getFakeAccessConfig("us-east-1")
|
||||
c.OMIRegions = []string{"us-east-1", "us-west-1", "us-east-2"}
|
||||
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatal("should allow user to have the raw region in omi_regions")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestOMINameValidation(t *testing.T) {
|
||||
c := testOMIConfig()
|
||||
|
||||
accessConf := testAccessConfig()
|
||||
|
||||
c.OMIName = "aa"
|
||||
if err := c.Prepare(accessConf, nil); err == nil {
|
||||
t.Fatal("shouldn't be able to have an omi name with less than 3 characters")
|
||||
}
|
||||
|
||||
var longOmiName string
|
||||
for i := 0; i < 129; i++ {
|
||||
longOmiName += "a"
|
||||
}
|
||||
c.OMIName = longOmiName
|
||||
if err := c.Prepare(accessConf, nil); err == nil {
|
||||
t.Fatal("shouldn't be able to have an omi name with great than 128 characters")
|
||||
}
|
||||
|
||||
c.OMIName = "+aaa"
|
||||
if err := c.Prepare(accessConf, nil); err == nil {
|
||||
t.Fatal("shouldn't be able to have an omi name with invalid characters")
|
||||
}
|
||||
|
||||
c.OMIName = "fooBAR1()[] ./-'@_"
|
||||
if err := c.Prepare(accessConf, nil); err != nil {
|
||||
t.Fatal("should be able to use all of the allowed OMI characters")
|
||||
}
|
||||
|
||||
c.OMIName = `xyz-base-2017-04-05-1934`
|
||||
if err := c.Prepare(accessConf, nil); err != nil {
|
||||
t.Fatalf("expected `xyz-base-2017-04-05-1934` to pass validation.")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package retry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRetry(t *testing.T) {
|
||||
numTries := uint(0)
|
||||
// Test that a passing function only gets called once.
|
||||
err := Run(0, 0, 0, func(i uint) (bool, error) {
|
||||
numTries++
|
||||
return true, nil
|
||||
})
|
||||
if numTries != 1 {
|
||||
t.Fatal("Passing function should not have been retried.")
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("Passing function should not have returned a retry error. Error: %s", err)
|
||||
}
|
||||
|
||||
// Test that a failing function gets retried (once in this example).
|
||||
numTries = 0
|
||||
results := []bool{false, true}
|
||||
err = Run(0, 0, 0, func(i uint) (bool, error) {
|
||||
result := results[numTries]
|
||||
numTries++
|
||||
return result, nil
|
||||
})
|
||||
if numTries != 2 {
|
||||
t.Fatalf("Retried function should have been tried twice. Tried %d times.", numTries)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("Successful retried function should not have returned a retry error. Error: %s", err)
|
||||
}
|
||||
|
||||
// Test that a function error gets returned, and the function does not get called again.
|
||||
numTries = 0
|
||||
funcErr := fmt.Errorf("This function had an error!")
|
||||
err = Run(0, 0, 0, func(i uint) (bool, error) {
|
||||
numTries++
|
||||
return false, funcErr
|
||||
})
|
||||
if numTries != 1 {
|
||||
t.Fatal("Errant function should not have been retried.")
|
||||
}
|
||||
if err != funcErr {
|
||||
t.Fatalf("Errant function did not return the right error %s. Error: %s", funcErr, err)
|
||||
}
|
||||
|
||||
// Test when a function exhausts its retries.
|
||||
numTries = 0
|
||||
expectedTries := uint(3)
|
||||
err = Run(0, 0, expectedTries, func(i uint) (bool, error) {
|
||||
numTries++
|
||||
return false, nil
|
||||
})
|
||||
if numTries != expectedTries {
|
||||
t.Fatalf("Unsuccessful retry function should have been called %d times. Only called %d times.", expectedTries, numTries)
|
||||
}
|
||||
if err != RetryExhaustedError {
|
||||
t.Fatalf("Unsuccessful retry function should have returned a retry exhausted error. Actual error: %s", err)
|
||||
}
|
||||
}
|
||||
@@ -1,243 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Clear out the OUTSCALE access key env vars so they don't
|
||||
// affect our tests.
|
||||
os.Setenv("OUTSCALE_ACCESS_KEY_ID", "")
|
||||
os.Setenv("OUTSCALE_ACCESS_KEY", "")
|
||||
os.Setenv("OUTSCALE_SECRET_ACCESS_KEY", "")
|
||||
os.Setenv("OUTSCALE_SECRET_KEY", "")
|
||||
}
|
||||
|
||||
func testConfig() *RunConfig {
|
||||
return &RunConfig{
|
||||
SourceOmi: "abcd",
|
||||
VmType: "m1.small",
|
||||
Comm: communicator.Config{
|
||||
SSH: communicator.SSH{
|
||||
SSHUsername: "foo",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func testConfigFilter() *RunConfig {
|
||||
config := testConfig()
|
||||
config.SourceOmi = ""
|
||||
config.SourceOmiFilter = OmiFilterOptions{}
|
||||
return config
|
||||
}
|
||||
|
||||
func TestRunConfigPrepare(t *testing.T) {
|
||||
c := testConfig()
|
||||
err := c.Prepare(nil)
|
||||
if len(err) > 0 {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigPrepare_VmType(t *testing.T) {
|
||||
c := testConfig()
|
||||
c.VmType = ""
|
||||
if err := c.Prepare(nil); len(err) != 1 {
|
||||
t.Fatalf("Should error if an vm_type is not specified")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigPrepare_SourceOmi(t *testing.T) {
|
||||
c := testConfig()
|
||||
c.SourceOmi = ""
|
||||
if err := c.Prepare(nil); len(err) != 2 {
|
||||
t.Fatalf("Should error if a source_omi (or source_omi_filter) is not specified")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigPrepare_SourceOmiFilterBlank(t *testing.T) {
|
||||
c := testConfigFilter()
|
||||
if err := c.Prepare(nil); len(err) != 2 {
|
||||
t.Fatalf("Should error if source_ami_filter is empty or not specified (and source_ami is not specified)")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigPrepare_SourceOmiFilterOwnersBlank(t *testing.T) {
|
||||
c := testConfigFilter()
|
||||
filter_key := "name"
|
||||
filter_value := "foo"
|
||||
c.SourceOmiFilter = OmiFilterOptions{
|
||||
NameValueFilter: config.NameValueFilter{
|
||||
Filters: map[string]string{filter_key: filter_value},
|
||||
},
|
||||
}
|
||||
if err := c.Prepare(nil); len(err) != 1 {
|
||||
t.Fatalf("Should error if Owners is not specified)")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigPrepare_SourceOmiFilterGood(t *testing.T) {
|
||||
c := testConfigFilter()
|
||||
owner := "123"
|
||||
filter_key := "name"
|
||||
filter_value := "foo"
|
||||
goodFilter := OmiFilterOptions{
|
||||
Owners: []string{owner},
|
||||
NameValueFilter: config.NameValueFilter{
|
||||
Filters: map[string]string{filter_key: filter_value},
|
||||
},
|
||||
}
|
||||
c.SourceOmiFilter = goodFilter
|
||||
if err := c.Prepare(nil); len(err) != 0 {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigPrepare_EnableT2UnlimitedGood(t *testing.T) {
|
||||
c := testConfig()
|
||||
// Must have a T2 vm type if T2 Unlimited is enabled
|
||||
c.VmType = "t2.micro"
|
||||
c.EnableT2Unlimited = true
|
||||
err := c.Prepare(nil)
|
||||
if len(err) > 0 {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigPrepare_EnableT2UnlimitedBadVmType(t *testing.T) {
|
||||
c := testConfig()
|
||||
// T2 Unlimited cannot be used with vm types other than T2
|
||||
c.VmType = "m5.large"
|
||||
c.EnableT2Unlimited = true
|
||||
err := c.Prepare(nil)
|
||||
if len(err) != 1 {
|
||||
t.Fatalf("Should error if T2 Unlimited is enabled with non-T2 vm_type")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigPrepare_EnableT2UnlimitedBadWithSpotInstanceRequest(t *testing.T) {
|
||||
c := testConfig()
|
||||
// T2 Unlimited cannot be used with Spot Instances
|
||||
c.VmType = "t2.micro"
|
||||
c.EnableT2Unlimited = true
|
||||
c.SpotPrice = "auto"
|
||||
c.SpotPriceAutoProduct = "Linux/UNIX"
|
||||
err := c.Prepare(nil)
|
||||
if len(err) != 1 {
|
||||
t.Fatalf("Should error if T2 Unlimited has been used in conjuntion with a Spot Price request")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigPrepare_SpotAuto(t *testing.T) {
|
||||
c := testConfig()
|
||||
c.SpotPrice = "auto"
|
||||
if err := c.Prepare(nil); len(err) != 1 {
|
||||
t.Fatalf("Should error if spot_price_auto_product is not set and spot_price is set to auto")
|
||||
}
|
||||
|
||||
// Good - SpotPrice and SpotPriceAutoProduct are correctly set
|
||||
c.SpotPriceAutoProduct = "foo"
|
||||
if err := c.Prepare(nil); len(err) != 0 {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
c.SpotPrice = ""
|
||||
if err := c.Prepare(nil); len(err) != 1 {
|
||||
t.Fatalf("Should error if spot_price is not set to auto and spot_price_auto_product is set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigPrepare_SSHPort(t *testing.T) {
|
||||
c := testConfig()
|
||||
c.Comm.SSHPort = 0
|
||||
if err := c.Prepare(nil); len(err) != 0 {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if c.Comm.SSHPort != 22 {
|
||||
t.Fatalf("invalid value: %d", c.Comm.SSHPort)
|
||||
}
|
||||
|
||||
c.Comm.SSHPort = 44
|
||||
if err := c.Prepare(nil); len(err) != 0 {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if c.Comm.SSHPort != 44 {
|
||||
t.Fatalf("invalid value: %d", c.Comm.SSHPort)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigPrepare_UserData(t *testing.T) {
|
||||
c := testConfig()
|
||||
tf, err := ioutil.TempFile("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.Remove(tf.Name())
|
||||
defer tf.Close()
|
||||
|
||||
c.UserData = "foo"
|
||||
c.UserDataFile = tf.Name()
|
||||
if err := c.Prepare(nil); len(err) != 1 {
|
||||
t.Fatalf("Should error if user_data string and user_data_file have both been specified")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigPrepare_UserDataFile(t *testing.T) {
|
||||
c := testConfig()
|
||||
if err := c.Prepare(nil); len(err) != 0 {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
c.UserDataFile = "idontexistidontthink"
|
||||
if err := c.Prepare(nil); len(err) != 1 {
|
||||
t.Fatalf("Should error if the file specified by user_data_file does not exist")
|
||||
}
|
||||
|
||||
tf, err := ioutil.TempFile("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.Remove(tf.Name())
|
||||
defer tf.Close()
|
||||
|
||||
c.UserDataFile = tf.Name()
|
||||
if err := c.Prepare(nil); len(err) != 0 {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigPrepare_TemporaryKeyPairName(t *testing.T) {
|
||||
c := testConfig()
|
||||
c.Comm.SSHTemporaryKeyPairName = ""
|
||||
if err := c.Prepare(nil); len(err) != 0 {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if c.Comm.SSHTemporaryKeyPairName == "" {
|
||||
t.Fatal("keypair name is empty")
|
||||
}
|
||||
|
||||
// Match prefix and UUID, e.g. "packer_5790d491-a0b8-c84c-c9d2-2aea55086550".
|
||||
r := regexp.MustCompile(`\Apacker_(?:(?i)[a-f\d]{8}(?:-[a-f\d]{4}){3}-[a-f\d]{12}?)\z`)
|
||||
if !r.MatchString(c.Comm.SSHTemporaryKeyPairName) {
|
||||
t.Fatal("keypair name is not valid")
|
||||
}
|
||||
|
||||
c.Comm.SSHTemporaryKeyPairName = "ssh-key-123"
|
||||
if err := c.Prepare(nil); len(err) != 0 {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if c.Comm.SSHTemporaryKeyPairName != "ssh-key-123" {
|
||||
t.Fatal("keypair name does not match")
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package version
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/packer-plugin-sdk/version"
|
||||
packerVersion "github.com/hashicorp/packer/version"
|
||||
)
|
||||
|
||||
var OutscalePluginVersion *version.PluginVersion
|
||||
|
||||
func init() {
|
||||
OutscalePluginVersion = version.InitializePluginVersion(
|
||||
packerVersion.Version, packerVersion.VersionPrerelease)
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package proxmox
|
||||
|
||||
import proxmoxiso "github.com/hashicorp/packer/builder/proxmox/iso"
|
||||
|
||||
type Builder = proxmoxiso.Builder
|
||||
@@ -1,91 +0,0 @@
|
||||
package proxmox
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/Telmate/proxmox-api-go/proxmox"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestTokenAuth(t *testing.T) {
|
||||
mockAPI := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Header.Get("Authorization") != "PVEAPIToken=dummy@vmhost!test-token=ac5293bf-15e2-477f-b04c-a6dfa7a46b80" {
|
||||
rw.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
}))
|
||||
defer mockAPI.Close()
|
||||
|
||||
pmURL, _ := url.Parse(mockAPI.URL)
|
||||
config := Config{
|
||||
proxmoxURL: pmURL,
|
||||
SkipCertValidation: false,
|
||||
Username: "dummy@vmhost!test-token",
|
||||
Password: "not-used",
|
||||
Token: "ac5293bf-15e2-477f-b04c-a6dfa7a46b80",
|
||||
}
|
||||
|
||||
client, err := newProxmoxClient(config)
|
||||
require.NoError(t, err)
|
||||
|
||||
ref := proxmox.NewVmRef(110)
|
||||
ref.SetNode("node1")
|
||||
ref.SetVmType("qemu")
|
||||
err = client.Sendkey(ref, "ping")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestLogin(t *testing.T) {
|
||||
mockAPI := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
// mock ticketing api
|
||||
if req.Method == http.MethodPost && req.URL.Path == "/access/ticket" {
|
||||
body, _ := ioutil.ReadAll(req.Body)
|
||||
values, _ := url.ParseQuery(string(body))
|
||||
user := values.Get("username")
|
||||
pass := values.Get("password")
|
||||
if user != "dummy@vmhost" || pass != "correct-horse-battery-staple" {
|
||||
rw.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
_ = json.NewEncoder(rw).Encode(map[string]interface{}{
|
||||
"data": map[string]string{
|
||||
"username": user,
|
||||
"ticket": "dummy-ticket",
|
||||
"CSRFPreventionToken": "random-token",
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// validate ticket
|
||||
if val, err := req.Cookie("PVEAuthCookie"); err != nil || val.Value != "dummy-ticket" {
|
||||
rw.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
}))
|
||||
defer mockAPI.Close()
|
||||
|
||||
pmURL, _ := url.Parse(mockAPI.URL)
|
||||
config := Config{
|
||||
proxmoxURL: pmURL,
|
||||
SkipCertValidation: false,
|
||||
Username: "dummy@vmhost",
|
||||
Password: "correct-horse-battery-staple",
|
||||
Token: "",
|
||||
}
|
||||
|
||||
client, err := newProxmoxClient(config)
|
||||
require.NoError(t, err)
|
||||
|
||||
ref := proxmox.NewVmRef(110)
|
||||
ref.SetNode("node1")
|
||||
ref.SetVmType("qemu")
|
||||
err = client.Sendkey(ref, "ping")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
package proxmox
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
func mandatoryConfig(t *testing.T) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"proxmox_url": "https://my-proxmox.my-domain:8006/api2/json",
|
||||
"username": "apiuser@pve",
|
||||
"password": "supersecret",
|
||||
"node": "my-proxmox",
|
||||
"ssh_username": "root",
|
||||
}
|
||||
}
|
||||
|
||||
func TestRequiredParameters(t *testing.T) {
|
||||
var c Config
|
||||
_, _, err := c.Prepare(&c, make(map[string]interface{}))
|
||||
if err == nil {
|
||||
t.Fatal("Expected empty configuration to fail")
|
||||
}
|
||||
errs, ok := err.(*packersdk.MultiError)
|
||||
if !ok {
|
||||
t.Fatal("Expected errors to be packersdk.MultiError")
|
||||
}
|
||||
|
||||
required := []string{"username", "password", "proxmox_url", "node", "ssh_username"}
|
||||
for _, param := range required {
|
||||
found := false
|
||||
for _, err := range errs.Errors {
|
||||
if strings.Contains(err.Error(), param) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("Expected error about missing parameter %q", required)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgentSetToFalse(t *testing.T) {
|
||||
cfg := mandatoryConfig(t)
|
||||
cfg["qemu_agent"] = false
|
||||
|
||||
var c Config
|
||||
_, _, err := c.Prepare(&c, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if c.Agent != false {
|
||||
t.Errorf("Expected Agent to be false, got %t", c.Agent)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPacketQueueSupportForNetworkAdapters(t *testing.T) {
|
||||
drivertests := []struct {
|
||||
expectedToFail bool
|
||||
model string
|
||||
}{
|
||||
{expectedToFail: false, model: "virtio"},
|
||||
{expectedToFail: true, model: "e1000"},
|
||||
{expectedToFail: true, model: "e1000-82540em"},
|
||||
{expectedToFail: true, model: "e1000-82544gc"},
|
||||
{expectedToFail: true, model: "e1000-82545em"},
|
||||
{expectedToFail: true, model: "i82551"},
|
||||
{expectedToFail: true, model: "i82557b"},
|
||||
{expectedToFail: true, model: "i82559er"},
|
||||
{expectedToFail: true, model: "ne2k_isa"},
|
||||
{expectedToFail: true, model: "ne2k_pci"},
|
||||
{expectedToFail: true, model: "pcnet"},
|
||||
{expectedToFail: true, model: "rtl8139"},
|
||||
{expectedToFail: true, model: "vmxnet3"},
|
||||
}
|
||||
|
||||
for _, tt := range drivertests {
|
||||
device := make(map[string]interface{})
|
||||
device["bridge"] = "vmbr0"
|
||||
device["model"] = tt.model
|
||||
device["packet_queues"] = 2
|
||||
|
||||
devices := make([]map[string]interface{}, 0)
|
||||
devices = append(devices, device)
|
||||
|
||||
cfg := mandatoryConfig(t)
|
||||
cfg["network_adapters"] = devices
|
||||
|
||||
var c Config
|
||||
_, _, err := c.Prepare(&c, cfg)
|
||||
|
||||
if tt.expectedToFail == true && err == nil {
|
||||
t.Error("expected config preparation to fail, but no error occured")
|
||||
}
|
||||
|
||||
if tt.expectedToFail == false && err != nil {
|
||||
t.Errorf("expected config preparation to succeed, but %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
package proxmox
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/Telmate/proxmox-api-go/proxmox"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
type converterMock struct {
|
||||
shutdownVm func(*proxmox.VmRef) (string, error)
|
||||
createTemplate func(*proxmox.VmRef) error
|
||||
}
|
||||
|
||||
func (m converterMock) ShutdownVm(r *proxmox.VmRef) (string, error) {
|
||||
return m.shutdownVm(r)
|
||||
}
|
||||
func (m converterMock) CreateTemplate(r *proxmox.VmRef) error {
|
||||
return m.createTemplate(r)
|
||||
}
|
||||
|
||||
var _ templateConverter = converterMock{}
|
||||
|
||||
func TestConvertToTemplate(t *testing.T) {
|
||||
cs := []struct {
|
||||
name string
|
||||
shutdownErr error
|
||||
expectCallCreateTemplate bool
|
||||
createTemplateErr error
|
||||
expectedAction multistep.StepAction
|
||||
expectTemplateIdSet bool
|
||||
}{
|
||||
{
|
||||
name: "no errors returns continue and sets template id",
|
||||
expectCallCreateTemplate: true,
|
||||
expectedAction: multistep.ActionContinue,
|
||||
expectTemplateIdSet: true,
|
||||
},
|
||||
{
|
||||
name: "when shutdown fails, don't try to create template and halt",
|
||||
shutdownErr: fmt.Errorf("failed to stop vm"),
|
||||
expectCallCreateTemplate: false,
|
||||
expectedAction: multistep.ActionHalt,
|
||||
expectTemplateIdSet: false,
|
||||
},
|
||||
{
|
||||
name: "when create template fails, halt",
|
||||
expectCallCreateTemplate: true,
|
||||
createTemplateErr: fmt.Errorf("failed to stop vm"),
|
||||
expectedAction: multistep.ActionHalt,
|
||||
expectTemplateIdSet: false,
|
||||
},
|
||||
}
|
||||
|
||||
const vmid = 123
|
||||
|
||||
for _, c := range cs {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
converter := converterMock{
|
||||
shutdownVm: func(r *proxmox.VmRef) (string, error) {
|
||||
if r.VmId() != vmid {
|
||||
t.Errorf("ShutdownVm called with unexpected id, expected %d, got %d", vmid, r.VmId())
|
||||
}
|
||||
return "", c.shutdownErr
|
||||
},
|
||||
createTemplate: func(r *proxmox.VmRef) error {
|
||||
if r.VmId() != vmid {
|
||||
t.Errorf("CreateTemplate called with unexpected id, expected %d, got %d", vmid, r.VmId())
|
||||
}
|
||||
if !c.expectCallCreateTemplate {
|
||||
t.Error("Did not expect CreateTemplate to be called")
|
||||
}
|
||||
|
||||
return c.createTemplateErr
|
||||
},
|
||||
}
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", packersdk.TestUi(t))
|
||||
state.Put("vmRef", proxmox.NewVmRef(vmid))
|
||||
state.Put("proxmoxClient", converter)
|
||||
|
||||
step := stepConvertToTemplate{}
|
||||
action := step.Run(context.TODO(), state)
|
||||
if action != c.expectedAction {
|
||||
t.Errorf("Expected action to be %v, got %v", c.expectedAction, action)
|
||||
}
|
||||
|
||||
id, wasSet := state.GetOk("template_id")
|
||||
|
||||
if c.expectTemplateIdSet != wasSet {
|
||||
t.Errorf("Expected template_id state present=%v was present=%v", c.expectTemplateIdSet, wasSet)
|
||||
}
|
||||
|
||||
if c.expectTemplateIdSet && id != vmid {
|
||||
t.Errorf("Expected template_id state to be set to %d, got %v", vmid, id)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
package proxmox
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/Telmate/proxmox-api-go/proxmox"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
type finalizerMock struct {
|
||||
getConfig func() (map[string]interface{}, error)
|
||||
setConfig func(map[string]interface{}) (string, error)
|
||||
}
|
||||
|
||||
func (m finalizerMock) GetVmConfig(*proxmox.VmRef) (map[string]interface{}, error) {
|
||||
return m.getConfig()
|
||||
}
|
||||
func (m finalizerMock) SetVmConfig(vmref *proxmox.VmRef, c map[string]interface{}) (interface{}, error) {
|
||||
return m.setConfig(c)
|
||||
}
|
||||
|
||||
var _ templateFinalizer = finalizerMock{}
|
||||
|
||||
func TestTemplateFinalize(t *testing.T) {
|
||||
cs := []struct {
|
||||
name string
|
||||
builderConfig *Config
|
||||
initialVMConfig map[string]interface{}
|
||||
getConfigErr error
|
||||
expectCallSetConfig bool
|
||||
expectedVMConfig map[string]interface{}
|
||||
setConfigErr error
|
||||
expectedAction multistep.StepAction
|
||||
}{
|
||||
{
|
||||
name: "empty config changes only description",
|
||||
builderConfig: &Config{},
|
||||
initialVMConfig: map[string]interface{}{
|
||||
"name": "dummy",
|
||||
"description": "Packer ephemeral build VM",
|
||||
"ide2": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso,media=cdrom",
|
||||
},
|
||||
expectCallSetConfig: true,
|
||||
expectedVMConfig: map[string]interface{}{
|
||||
"name": nil,
|
||||
"description": "",
|
||||
"ide2": nil,
|
||||
},
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "all options",
|
||||
builderConfig: &Config{
|
||||
TemplateName: "my-template",
|
||||
TemplateDescription: "some-description",
|
||||
},
|
||||
initialVMConfig: map[string]interface{}{
|
||||
"name": "dummy",
|
||||
"description": "Packer ephemeral build VM",
|
||||
},
|
||||
expectCallSetConfig: true,
|
||||
expectedVMConfig: map[string]interface{}{
|
||||
"name": "my-template",
|
||||
"description": "some-description",
|
||||
},
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "all options with cloud-init",
|
||||
builderConfig: &Config{
|
||||
TemplateName: "my-template",
|
||||
TemplateDescription: "some-description",
|
||||
CloudInit: true,
|
||||
},
|
||||
initialVMConfig: map[string]interface{}{
|
||||
"name": "dummy",
|
||||
"description": "Packer ephemeral build VM",
|
||||
"bootdisk": "virtio0",
|
||||
"virtio0": "ceph01:base-223-disk-0,cache=unsafe,media=disk,size=32G",
|
||||
},
|
||||
expectCallSetConfig: true,
|
||||
expectedVMConfig: map[string]interface{}{
|
||||
"name": "my-template",
|
||||
"description": "some-description",
|
||||
"ide3": "ceph01:cloudinit",
|
||||
},
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "no available controller for cloud-init drive",
|
||||
builderConfig: &Config{
|
||||
TemplateName: "my-template",
|
||||
TemplateDescription: "some-description",
|
||||
CloudInit: true,
|
||||
},
|
||||
initialVMConfig: map[string]interface{}{
|
||||
"name": "dummy",
|
||||
"description": "Packer ephemeral build VM",
|
||||
"ide0": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso,media=cdrom",
|
||||
"ide1": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso,media=cdrom",
|
||||
"ide2": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso,media=cdrom",
|
||||
"ide3": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso,media=cdrom",
|
||||
"bootdisk": "virtio0",
|
||||
"virtio0": "ceph01:base-223-disk-0,cache=unsafe,media=disk,size=32G",
|
||||
},
|
||||
expectCallSetConfig: false,
|
||||
expectedAction: multistep.ActionHalt,
|
||||
},
|
||||
{
|
||||
name: "GetVmConfig error should return halt",
|
||||
builderConfig: &Config{
|
||||
TemplateName: "my-template",
|
||||
TemplateDescription: "some-description",
|
||||
CloudInit: true,
|
||||
},
|
||||
getConfigErr: fmt.Errorf("some error"),
|
||||
expectCallSetConfig: false,
|
||||
expectedAction: multistep.ActionHalt,
|
||||
},
|
||||
{
|
||||
name: "SetVmConfig error should return halt",
|
||||
builderConfig: &Config{
|
||||
TemplateName: "my-template",
|
||||
TemplateDescription: "some-description",
|
||||
},
|
||||
initialVMConfig: map[string]interface{}{
|
||||
"name": "dummy",
|
||||
"description": "Packer ephemeral build VM",
|
||||
},
|
||||
expectCallSetConfig: true,
|
||||
setConfigErr: fmt.Errorf("some error"),
|
||||
expectedAction: multistep.ActionHalt,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cs {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
finalizer := finalizerMock{
|
||||
getConfig: func() (map[string]interface{}, error) {
|
||||
return c.initialVMConfig, c.getConfigErr
|
||||
},
|
||||
setConfig: func(cfg map[string]interface{}) (string, error) {
|
||||
if !c.expectCallSetConfig {
|
||||
t.Error("Did not expect SetVmConfig to be called")
|
||||
}
|
||||
for key, val := range c.expectedVMConfig {
|
||||
if cfg[key] != val {
|
||||
t.Errorf("Expected %q to be %q, got %q", key, val, cfg[key])
|
||||
}
|
||||
}
|
||||
|
||||
return "", c.setConfigErr
|
||||
},
|
||||
}
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", packersdk.TestUi(t))
|
||||
state.Put("config", c.builderConfig)
|
||||
state.Put("vmRef", proxmox.NewVmRef(1))
|
||||
state.Put("proxmoxClient", finalizer)
|
||||
|
||||
step := stepFinalizeTemplateConfig{}
|
||||
action := step.Run(context.TODO(), state)
|
||||
if action != c.expectedAction {
|
||||
t.Errorf("Expected action to be %v, got %v", c.expectedAction, action)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
package proxmox
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/Telmate/proxmox-api-go/proxmox"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
type startedVMCleanerMock struct {
|
||||
stopVm func() (string, error)
|
||||
deleteVm func() (string, error)
|
||||
}
|
||||
|
||||
func (m startedVMCleanerMock) StopVm(*proxmox.VmRef) (string, error) {
|
||||
return m.stopVm()
|
||||
}
|
||||
func (m startedVMCleanerMock) DeleteVm(*proxmox.VmRef) (string, error) {
|
||||
return m.deleteVm()
|
||||
}
|
||||
|
||||
var _ startedVMCleaner = &startedVMCleanerMock{}
|
||||
|
||||
func TestCleanupStartVM(t *testing.T) {
|
||||
cs := []struct {
|
||||
name string
|
||||
setVmRef bool
|
||||
setSuccess bool
|
||||
stopVMErr error
|
||||
expectCallStopVM bool
|
||||
deleteVMErr error
|
||||
expectCallDeleteVM bool
|
||||
}{
|
||||
{
|
||||
name: "when vmRef state is not set, nothing should happen",
|
||||
setVmRef: false,
|
||||
expectCallStopVM: false,
|
||||
},
|
||||
{
|
||||
name: "when success state is set, nothing should happen",
|
||||
setVmRef: true,
|
||||
setSuccess: true,
|
||||
expectCallStopVM: false,
|
||||
},
|
||||
{
|
||||
name: "when not successful, vm should be stopped and deleted",
|
||||
setVmRef: true,
|
||||
setSuccess: false,
|
||||
expectCallStopVM: true,
|
||||
expectCallDeleteVM: true,
|
||||
},
|
||||
{
|
||||
name: "if stopping fails, DeleteVm should not be called",
|
||||
setVmRef: true,
|
||||
setSuccess: false,
|
||||
expectCallStopVM: true,
|
||||
stopVMErr: fmt.Errorf("some error"),
|
||||
expectCallDeleteVM: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cs {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
var stopWasCalled, deleteWasCalled bool
|
||||
|
||||
cleaner := startedVMCleanerMock{
|
||||
stopVm: func() (string, error) {
|
||||
if !c.expectCallStopVM {
|
||||
t.Error("Did not expect StopVm to be called")
|
||||
}
|
||||
|
||||
stopWasCalled = true
|
||||
return "", c.stopVMErr
|
||||
},
|
||||
deleteVm: func() (string, error) {
|
||||
if !c.expectCallDeleteVM {
|
||||
t.Error("Did not expect DeleteVm to be called")
|
||||
}
|
||||
|
||||
deleteWasCalled = true
|
||||
return "", c.deleteVMErr
|
||||
},
|
||||
}
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", packersdk.TestUi(t))
|
||||
state.Put("proxmoxClient", cleaner)
|
||||
if c.setVmRef {
|
||||
state.Put("vmRef", proxmox.NewVmRef(1))
|
||||
}
|
||||
if c.setSuccess {
|
||||
state.Put("success", "true")
|
||||
}
|
||||
|
||||
step := stepStartVM{}
|
||||
step.Cleanup(state)
|
||||
|
||||
if c.expectCallStopVM && !stopWasCalled {
|
||||
t.Error("Expected StopVm to be called, but it wasn't")
|
||||
}
|
||||
if c.expectCallDeleteVM && !deleteWasCalled {
|
||||
t.Error("Expected DeleteVm to be called, but it wasn't")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type startVMMock struct {
|
||||
create func(*proxmox.VmRef, proxmox.ConfigQemu, multistep.StateBag) error
|
||||
startVm func(*proxmox.VmRef) (string, error)
|
||||
setVmConfig func(*proxmox.VmRef, map[string]interface{}) (interface{}, error)
|
||||
}
|
||||
|
||||
func (m *startVMMock) Create(vmRef *proxmox.VmRef, config proxmox.ConfigQemu, state multistep.StateBag) error {
|
||||
return m.create(vmRef, config, state)
|
||||
}
|
||||
func (m *startVMMock) StartVm(vmRef *proxmox.VmRef) (string, error) {
|
||||
return m.startVm(vmRef)
|
||||
}
|
||||
func (m *startVMMock) SetVmConfig(vmRef *proxmox.VmRef, config map[string]interface{}) (interface{}, error) {
|
||||
return m.setVmConfig(vmRef, config)
|
||||
}
|
||||
func (m *startVMMock) GetNextID(int) (int, error) {
|
||||
return 1, nil
|
||||
}
|
||||
|
||||
func TestStartVM(t *testing.T) {
|
||||
// TODO: proxmox-api-go does a lot of manipulation on the input and does not
|
||||
// give any way to access the actual data it sends to the Proxmox server,
|
||||
// which means writing good tests here is quite hard. This test is mainly a
|
||||
// stub to revisit when we can write better tests.
|
||||
cs := []struct {
|
||||
name string
|
||||
config *Config
|
||||
expectedAction multistep.StepAction
|
||||
}{
|
||||
{
|
||||
name: "Example config from documentation works",
|
||||
config: &Config{
|
||||
Disks: []diskConfig{
|
||||
{
|
||||
Type: "sata",
|
||||
Size: "10G",
|
||||
StoragePool: "local",
|
||||
StoragePoolType: "lvm",
|
||||
},
|
||||
},
|
||||
NICs: []nicConfig{
|
||||
{
|
||||
Bridge: "vmbr0",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cs {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
mock := &startVMMock{
|
||||
create: func(vmRef *proxmox.VmRef, config proxmox.ConfigQemu, state multistep.StateBag) error {
|
||||
return nil
|
||||
},
|
||||
startVm: func(*proxmox.VmRef) (string, error) {
|
||||
return "", nil
|
||||
},
|
||||
setVmConfig: func(*proxmox.VmRef, map[string]interface{}) (interface{}, error) {
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", packersdk.TestUi(t))
|
||||
state.Put("config", c.config)
|
||||
state.Put("proxmoxClient", mock)
|
||||
s := stepStartVM{vmCreator: mock}
|
||||
|
||||
action := s.Run(context.TODO(), state)
|
||||
if action != c.expectedAction {
|
||||
t.Errorf("Expected action %s, got %s", c.expectedAction, action)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
package proxmox
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/Telmate/proxmox-api-go/proxmox"
|
||||
"github.com/hashicorp/packer-plugin-sdk/bootcommand"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
type commandTyperMock struct {
|
||||
sendkey func(*proxmox.VmRef, string) error
|
||||
}
|
||||
|
||||
func (m commandTyperMock) Sendkey(ref *proxmox.VmRef, cmd string) error {
|
||||
return m.sendkey(ref, cmd)
|
||||
}
|
||||
|
||||
var _ commandTyper = commandTyperMock{}
|
||||
|
||||
func TestTypeBootCommand(t *testing.T) {
|
||||
cs := []struct {
|
||||
name string
|
||||
builderConfig *Config
|
||||
expectCallSendkey bool
|
||||
sendkeyErr error
|
||||
expectedKeysSent string
|
||||
expectedAction multistep.StepAction
|
||||
}{
|
||||
{
|
||||
name: "simple boot command is typed",
|
||||
builderConfig: &Config{BootConfig: bootcommand.BootConfig{BootCommand: []string{"hello"}}},
|
||||
expectCallSendkey: true,
|
||||
expectedKeysSent: "hello",
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "interpolated boot command",
|
||||
builderConfig: &Config{BootConfig: bootcommand.BootConfig{BootCommand: []string{"hello<enter>world"}}},
|
||||
expectCallSendkey: true,
|
||||
expectedKeysSent: "helloretworld",
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "merge multiple interpolated boot command",
|
||||
builderConfig: &Config{BootConfig: bootcommand.BootConfig{BootCommand: []string{"Hello World 2.0", "foo!bar@baz"}}},
|
||||
expectCallSendkey: true,
|
||||
expectedKeysSent: "shift-hellospcshift-worldspc2dot0fooshift-1barshift-2baz",
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "holding and releasing keys",
|
||||
builderConfig: &Config{BootConfig: bootcommand.BootConfig{BootCommand: []string{"<leftShiftOn>hello<rightAltOn>world<leftShiftOff><rightAltOff>"}}},
|
||||
expectCallSendkey: true,
|
||||
expectedKeysSent: "shift-hshift-eshift-lshift-lshift-oshift-alt_r-wshift-alt_r-oshift-alt_r-rshift-alt_r-lshift-alt_r-d",
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "holding multiple alphabetical keys and shift",
|
||||
builderConfig: &Config{BootConfig: bootcommand.BootConfig{BootCommand: []string{"<cOn><leftShiftOn>n<leftShiftOff><cOff>"}}},
|
||||
expectCallSendkey: true,
|
||||
expectedKeysSent: "shift-c-n",
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "noop keystrokes",
|
||||
builderConfig: &Config{BootConfig: bootcommand.BootConfig{BootCommand: []string{"<cOn><leftShiftOn><cOff><leftAltOn><leftShiftOff><leftAltOff>"}}},
|
||||
expectCallSendkey: true,
|
||||
expectedKeysSent: "",
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "noop keystrokes mixed",
|
||||
builderConfig: &Config{BootConfig: bootcommand.BootConfig{BootCommand: []string{"<cOn><leftShiftOn><cOff>h<leftShiftOff>"}}},
|
||||
expectCallSendkey: true,
|
||||
expectedKeysSent: "shift-h",
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "without boot command sendkey should not be called",
|
||||
builderConfig: &Config{BootConfig: bootcommand.BootConfig{BootCommand: []string{}}},
|
||||
expectCallSendkey: false,
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "invalid boot command template function",
|
||||
builderConfig: &Config{BootConfig: bootcommand.BootConfig{BootCommand: []string{"{{ foo }}"}}},
|
||||
expectCallSendkey: false,
|
||||
expectedAction: multistep.ActionHalt,
|
||||
},
|
||||
{
|
||||
// When proxmox (or Qemu, really) doesn't recognize the keycode we send, we get no error back, but
|
||||
// a map {"data": "invalid parameter: X"}, where X is the keycode.
|
||||
name: "invalid keys sent to proxmox",
|
||||
builderConfig: &Config{BootConfig: bootcommand.BootConfig{BootCommand: []string{"x"}}},
|
||||
expectCallSendkey: true,
|
||||
sendkeyErr: fmt.Errorf("invalid parameter: x"),
|
||||
expectedKeysSent: "x",
|
||||
expectedAction: multistep.ActionHalt,
|
||||
},
|
||||
{
|
||||
name: "error in typing should return halt",
|
||||
builderConfig: &Config{BootConfig: bootcommand.BootConfig{BootCommand: []string{"hello"}}},
|
||||
expectCallSendkey: true,
|
||||
sendkeyErr: fmt.Errorf("some error"),
|
||||
expectedKeysSent: "h",
|
||||
expectedAction: multistep.ActionHalt,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cs {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
accumulator := strings.Builder{}
|
||||
typer := commandTyperMock{
|
||||
sendkey: func(ref *proxmox.VmRef, cmd string) error {
|
||||
if !c.expectCallSendkey {
|
||||
t.Error("Did not expect sendkey to be called")
|
||||
}
|
||||
|
||||
accumulator.WriteString(cmd)
|
||||
|
||||
return c.sendkeyErr
|
||||
},
|
||||
}
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", packersdk.TestUi(t))
|
||||
state.Put("config", c.builderConfig)
|
||||
state.Put("http_port", int(0))
|
||||
state.Put("vmRef", proxmox.NewVmRef(1))
|
||||
state.Put("proxmoxClient", typer)
|
||||
|
||||
step := stepTypeBootCommand{
|
||||
c.builderConfig.BootConfig,
|
||||
c.builderConfig.Ctx,
|
||||
}
|
||||
action := step.Run(context.TODO(), state)
|
||||
step.Cleanup(state)
|
||||
|
||||
if action != c.expectedAction {
|
||||
t.Errorf("Expected action to be %v, got %v", c.expectedAction, action)
|
||||
}
|
||||
if c.expectedKeysSent != accumulator.String() {
|
||||
t.Errorf("Expected keystrokes to be %q, got %q", c.expectedKeysSent, accumulator.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,232 +0,0 @@
|
||||
package proxmoxiso
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/template"
|
||||
)
|
||||
|
||||
func TestBasicExampleFromDocsIsValid(t *testing.T) {
|
||||
const config = `{
|
||||
"builders": [
|
||||
{
|
||||
"type": "proxmox-iso",
|
||||
"proxmox_url": "https://my-proxmox.my-domain:8006/api2/json",
|
||||
"insecure_skip_tls_verify": true,
|
||||
"username": "apiuser@pve",
|
||||
"password": "supersecret",
|
||||
|
||||
"node": "my-proxmox",
|
||||
"network_adapters": [
|
||||
{
|
||||
"bridge": "vmbr0"
|
||||
}
|
||||
],
|
||||
"disks": [
|
||||
{
|
||||
"type": "scsi",
|
||||
"disk_size": "5G",
|
||||
"storage_pool": "local-lvm",
|
||||
"storage_pool_type": "lvm"
|
||||
}
|
||||
],
|
||||
|
||||
"iso_file": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso",
|
||||
"http_directory":"config",
|
||||
"boot_wait": "10s",
|
||||
"boot_command": [
|
||||
"<up><tab> ip=dhcp inst.cmdline inst.ks=http://{{.HTTPIP}}:{{.HTTPPort}}/ks.cfg<enter>"
|
||||
],
|
||||
|
||||
"ssh_username": "root",
|
||||
"ssh_timeout": "15m",
|
||||
"ssh_password": "packer",
|
||||
|
||||
"unmount_iso": true,
|
||||
"template_name": "fedora-29",
|
||||
"template_description": "Fedora 29-1.2, generated on {{ isotime \"2006-01-02T15:04:05Z\" }}"
|
||||
}
|
||||
]
|
||||
}`
|
||||
tpl, err := template.Parse(strings.NewReader(config))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
b := &Builder{}
|
||||
_, _, err = b.Prepare(tpl.Builders["proxmox-iso"].Config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// The example config does not set a number of optional fields. Validate that:
|
||||
// Memory 0 is too small, using default: 512
|
||||
// Number of cores 0 is too small, using default: 1
|
||||
// Number of sockets 0 is too small, using default: 1
|
||||
// CPU type not set, using default 'kvm64'
|
||||
// OS not set, using default 'other'
|
||||
// NIC 0 model not set, using default 'e1000'
|
||||
// Disk 0 cache mode not set, using default 'none'
|
||||
// Agent not set, default is true
|
||||
// SCSI controller not set, using default 'lsi'
|
||||
// Firewall toggle not set, using default: 0
|
||||
// Disable KVM not set, using default: 0
|
||||
|
||||
if b.config.Memory != 512 {
|
||||
t.Errorf("Expected Memory to be 512, got %d", b.config.Memory)
|
||||
}
|
||||
if b.config.Cores != 1 {
|
||||
t.Errorf("Expected Cores to be 1, got %d", b.config.Cores)
|
||||
}
|
||||
if b.config.Sockets != 1 {
|
||||
t.Errorf("Expected Sockets to be 1, got %d", b.config.Sockets)
|
||||
}
|
||||
if b.config.CPUType != "kvm64" {
|
||||
t.Errorf("Expected CPU type to be 'kvm64', got %s", b.config.CPUType)
|
||||
}
|
||||
if b.config.OS != "other" {
|
||||
t.Errorf("Expected OS to be 'other', got %s", b.config.OS)
|
||||
}
|
||||
if b.config.NICs[0].Model != "e1000" {
|
||||
t.Errorf("Expected NIC model to be 'e1000', got %s", b.config.NICs[0].Model)
|
||||
}
|
||||
if b.config.NICs[0].Firewall != false {
|
||||
t.Errorf("Expected NIC firewall to be false, got %t", b.config.NICs[0].Firewall)
|
||||
}
|
||||
if b.config.Disks[0].CacheMode != "none" {
|
||||
t.Errorf("Expected disk cache mode to be 'none', got %s", b.config.Disks[0].CacheMode)
|
||||
}
|
||||
if b.config.Agent != true {
|
||||
t.Errorf("Expected Agent to be true, got %t", b.config.Agent)
|
||||
}
|
||||
if b.config.DisableKVM != false {
|
||||
t.Errorf("Expected Disable KVM toggle to be false, got %t", b.config.DisableKVM)
|
||||
}
|
||||
if b.config.SCSIController != "lsi" {
|
||||
t.Errorf("Expected SCSI controller to be 'lsi', got %s", b.config.SCSIController)
|
||||
}
|
||||
if b.config.CloudInit != false {
|
||||
t.Errorf("Expected CloudInit to be false, got %t", b.config.CloudInit)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgentSetToFalse(t *testing.T) {
|
||||
cfg := mandatoryConfig(t)
|
||||
cfg["qemu_agent"] = false
|
||||
|
||||
var c Config
|
||||
_, warn, err := c.Prepare(cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err, warn)
|
||||
}
|
||||
|
||||
if c.Agent != false {
|
||||
t.Errorf("Expected Agent to be false, got %t", c.Agent)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPacketQueueSupportForNetworkAdapters(t *testing.T) {
|
||||
drivertests := []struct {
|
||||
expectedToFail bool
|
||||
model string
|
||||
}{
|
||||
{expectedToFail: false, model: "virtio"},
|
||||
{expectedToFail: true, model: "e1000"},
|
||||
{expectedToFail: true, model: "e1000-82540em"},
|
||||
{expectedToFail: true, model: "e1000-82544gc"},
|
||||
{expectedToFail: true, model: "e1000-82545em"},
|
||||
{expectedToFail: true, model: "i82551"},
|
||||
{expectedToFail: true, model: "i82557b"},
|
||||
{expectedToFail: true, model: "i82559er"},
|
||||
{expectedToFail: true, model: "ne2k_isa"},
|
||||
{expectedToFail: true, model: "ne2k_pci"},
|
||||
{expectedToFail: true, model: "pcnet"},
|
||||
{expectedToFail: true, model: "rtl8139"},
|
||||
{expectedToFail: true, model: "vmxnet3"},
|
||||
}
|
||||
|
||||
for _, tt := range drivertests {
|
||||
device := make(map[string]interface{})
|
||||
device["bridge"] = "vmbr0"
|
||||
device["model"] = tt.model
|
||||
device["packet_queues"] = 2
|
||||
|
||||
devices := make([]map[string]interface{}, 0)
|
||||
devices = append(devices, device)
|
||||
|
||||
cfg := mandatoryConfig(t)
|
||||
cfg["network_adapters"] = devices
|
||||
|
||||
var c Config
|
||||
_, _, err := c.Prepare(cfg)
|
||||
|
||||
if tt.expectedToFail == true && err == nil {
|
||||
t.Error("expected config preparation to fail, but no error occured")
|
||||
}
|
||||
|
||||
if tt.expectedToFail == false && err != nil {
|
||||
t.Errorf("expected config preparation to succeed, but %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHardDiskControllerIOThreadSupport(t *testing.T) {
|
||||
drivertests := []struct {
|
||||
expectedToFail bool
|
||||
controller string
|
||||
disk_type string
|
||||
}{
|
||||
// io thread is only supported by virtio-scsi-single controller
|
||||
// and only for virtio and scsi disks
|
||||
{expectedToFail: false, controller: "virtio-scsi-single", disk_type: "scsi"},
|
||||
{expectedToFail: false, controller: "virtio-scsi-single", disk_type: "virtio"},
|
||||
{expectedToFail: true, controller: "virtio-scsi-single", disk_type: "sata"},
|
||||
{expectedToFail: true, controller: "lsi", disk_type: "scsi"},
|
||||
{expectedToFail: true, controller: "lsi53c810", disk_type: "virtio"},
|
||||
}
|
||||
|
||||
for _, tt := range drivertests {
|
||||
nic := make(map[string]interface{})
|
||||
nic["bridge"] = "vmbr0"
|
||||
|
||||
nics := make([]map[string]interface{}, 0)
|
||||
nics = append(nics, nic)
|
||||
|
||||
disk := make(map[string]interface{})
|
||||
disk["type"] = tt.disk_type
|
||||
disk["io_thread"] = true
|
||||
disk["storage_pool"] = "local-lvm"
|
||||
disk["storage_pool_type"] = "lvm"
|
||||
|
||||
disks := make([]map[string]interface{}, 0)
|
||||
disks = append(disks, disk)
|
||||
|
||||
cfg := mandatoryConfig(t)
|
||||
cfg["network_adapters"] = nics
|
||||
cfg["disks"] = disks
|
||||
cfg["scsi_controller"] = tt.controller
|
||||
|
||||
var c Config
|
||||
_, _, err := c.Prepare(cfg)
|
||||
|
||||
if tt.expectedToFail == true && err == nil {
|
||||
t.Error("expected config preparation to fail, but no error occured")
|
||||
}
|
||||
|
||||
if tt.expectedToFail == false && err != nil {
|
||||
t.Errorf("expected config preparation to succeed, but %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mandatoryConfig(t *testing.T) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"proxmox_url": "https://my-proxmox.my-domain:8006/api2/json",
|
||||
"username": "apiuser@pve",
|
||||
"password": "supersecret",
|
||||
"node": "my-proxmox",
|
||||
"ssh_username": "root",
|
||||
"iso_file": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso",
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
package proxmoxiso
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/Telmate/proxmox-api-go/proxmox"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
type finalizerMock struct {
|
||||
getConfig func() (map[string]interface{}, error)
|
||||
setConfig func(map[string]interface{}) (string, error)
|
||||
}
|
||||
|
||||
func (m finalizerMock) GetVmConfig(*proxmox.VmRef) (map[string]interface{}, error) {
|
||||
return m.getConfig()
|
||||
}
|
||||
func (m finalizerMock) SetVmConfig(vmref *proxmox.VmRef, c map[string]interface{}) (interface{}, error) {
|
||||
return m.setConfig(c)
|
||||
}
|
||||
|
||||
var _ templateFinalizer = finalizerMock{}
|
||||
|
||||
func TestISOTemplateFinalize(t *testing.T) {
|
||||
cs := []struct {
|
||||
name string
|
||||
builderConfig *Config
|
||||
initialVMConfig map[string]interface{}
|
||||
getConfigErr error
|
||||
expectCallSetConfig bool
|
||||
expectedVMConfig map[string]interface{}
|
||||
setConfigErr error
|
||||
expectedAction multistep.StepAction
|
||||
}{
|
||||
{
|
||||
name: "default config does nothing",
|
||||
builderConfig: &Config{},
|
||||
initialVMConfig: map[string]interface{}{
|
||||
"ide2": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso,media=cdrom",
|
||||
},
|
||||
expectCallSetConfig: false,
|
||||
expectedVMConfig: map[string]interface{}{
|
||||
"ide2": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso,media=cdrom",
|
||||
},
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "should unmount when configured",
|
||||
builderConfig: &Config{
|
||||
UnmountISO: true,
|
||||
},
|
||||
initialVMConfig: map[string]interface{}{
|
||||
"ide2": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso,media=cdrom",
|
||||
},
|
||||
expectCallSetConfig: true,
|
||||
expectedVMConfig: map[string]interface{}{
|
||||
"ide2": "none,media=cdrom",
|
||||
},
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "no cd-drive with unmount=true should returns halt",
|
||||
builderConfig: &Config{
|
||||
UnmountISO: true,
|
||||
},
|
||||
initialVMConfig: map[string]interface{}{
|
||||
"ide1": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso,media=cdrom",
|
||||
},
|
||||
expectCallSetConfig: false,
|
||||
expectedAction: multistep.ActionHalt,
|
||||
},
|
||||
{
|
||||
name: "GetVmConfig error should return halt",
|
||||
builderConfig: &Config{
|
||||
UnmountISO: true,
|
||||
},
|
||||
getConfigErr: fmt.Errorf("some error"),
|
||||
expectCallSetConfig: false,
|
||||
expectedAction: multistep.ActionHalt,
|
||||
},
|
||||
{
|
||||
name: "SetVmConfig error should return halt",
|
||||
builderConfig: &Config{
|
||||
UnmountISO: true,
|
||||
},
|
||||
initialVMConfig: map[string]interface{}{
|
||||
"ide2": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso,media=cdrom",
|
||||
},
|
||||
expectCallSetConfig: true,
|
||||
setConfigErr: fmt.Errorf("some error"),
|
||||
expectedAction: multistep.ActionHalt,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cs {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
finalizer := finalizerMock{
|
||||
getConfig: func() (map[string]interface{}, error) {
|
||||
return c.initialVMConfig, c.getConfigErr
|
||||
},
|
||||
setConfig: func(cfg map[string]interface{}) (string, error) {
|
||||
if !c.expectCallSetConfig {
|
||||
t.Error("Did not expect SetVmConfig to be called")
|
||||
}
|
||||
for key, val := range c.expectedVMConfig {
|
||||
if cfg[key] != val {
|
||||
t.Errorf("Expected %q to be %q, got %q", key, val, cfg[key])
|
||||
}
|
||||
}
|
||||
|
||||
return "", c.setConfigErr
|
||||
},
|
||||
}
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", packersdk.TestUi(t))
|
||||
state.Put("iso-config", c.builderConfig)
|
||||
state.Put("vmRef", proxmox.NewVmRef(1))
|
||||
state.Put("proxmoxClient", finalizer)
|
||||
|
||||
step := stepFinalizeISOTemplate{}
|
||||
action := step.Run(context.TODO(), state)
|
||||
if action != c.expectedAction {
|
||||
t.Errorf("Expected action to be %v, got %v", c.expectedAction, action)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
package proxmoxiso
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
type uploaderMock struct {
|
||||
fail bool
|
||||
wasCalled bool
|
||||
}
|
||||
|
||||
func (m *uploaderMock) Upload(node string, storage string, contentType string, filename string, file io.Reader) error {
|
||||
m.wasCalled = true
|
||||
if m.fail {
|
||||
return fmt.Errorf("Testing induced failure")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ uploader = &uploaderMock{}
|
||||
|
||||
func TestUploadISO(t *testing.T) {
|
||||
cs := []struct {
|
||||
name string
|
||||
builderConfig *Config
|
||||
downloadPath string
|
||||
failUpload bool
|
||||
|
||||
expectError bool
|
||||
expectUploadCalled bool
|
||||
expectedISOPath string
|
||||
expectedAction multistep.StepAction
|
||||
}{
|
||||
{
|
||||
name: "should not call upload unless configured to do so",
|
||||
builderConfig: &Config{shouldUploadISO: false, ISOFile: "local:iso/some-file"},
|
||||
|
||||
expectUploadCalled: false,
|
||||
expectedISOPath: "local:iso/some-file",
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "success should continue",
|
||||
builderConfig: &Config{
|
||||
shouldUploadISO: true,
|
||||
ISOStoragePool: "local",
|
||||
ISOConfig: commonsteps.ISOConfig{ISOUrls: []string{"http://server.example/some-file.iso"}},
|
||||
},
|
||||
downloadPath: "testdata/test.iso",
|
||||
|
||||
expectedISOPath: "local:iso/some-file.iso",
|
||||
expectUploadCalled: true,
|
||||
expectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
name: "failing upload should halt",
|
||||
builderConfig: &Config{
|
||||
shouldUploadISO: true,
|
||||
ISOStoragePool: "local",
|
||||
ISOConfig: commonsteps.ISOConfig{ISOUrls: []string{"http://server.example/some-file.iso"}},
|
||||
},
|
||||
downloadPath: "testdata/test.iso",
|
||||
failUpload: true,
|
||||
|
||||
expectError: true,
|
||||
expectUploadCalled: true,
|
||||
expectedAction: multistep.ActionHalt,
|
||||
},
|
||||
{
|
||||
name: "downloader: state misconfiguration should halt",
|
||||
builderConfig: &Config{
|
||||
shouldUploadISO: true,
|
||||
ISOStoragePool: "local",
|
||||
ISOConfig: commonsteps.ISOConfig{ISOUrls: []string{"http://server.example/some-file.iso"}},
|
||||
},
|
||||
|
||||
expectError: true,
|
||||
expectUploadCalled: false,
|
||||
expectedAction: multistep.ActionHalt,
|
||||
},
|
||||
{
|
||||
name: "downloader: file unreadable should halt",
|
||||
builderConfig: &Config{
|
||||
shouldUploadISO: true,
|
||||
ISOStoragePool: "local",
|
||||
ISOConfig: commonsteps.ISOConfig{ISOUrls: []string{"http://server.example/some-file.iso"}},
|
||||
},
|
||||
downloadPath: "testdata/non-existent.iso",
|
||||
|
||||
expectError: true,
|
||||
expectUploadCalled: false,
|
||||
expectedAction: multistep.ActionHalt,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cs {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
m := &uploaderMock{fail: c.failUpload}
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", packersdk.TestUi(t))
|
||||
state.Put("iso-config", c.builderConfig)
|
||||
state.Put(downloadPathKey, c.downloadPath)
|
||||
state.Put("proxmoxClient", m)
|
||||
|
||||
step := stepUploadISO{}
|
||||
action := step.Run(context.TODO(), state)
|
||||
step.Cleanup(state)
|
||||
|
||||
if action != c.expectedAction {
|
||||
t.Errorf("Expected action to be %v, got %v", c.expectedAction, action)
|
||||
}
|
||||
if m.wasCalled != c.expectUploadCalled {
|
||||
t.Errorf("Expected mock to be called: %v, got: %v", c.expectUploadCalled, m.wasCalled)
|
||||
}
|
||||
err, gotError := state.GetOk("error")
|
||||
if gotError != c.expectError {
|
||||
t.Errorf("Expected error state to be: %v, got: %v", c.expectError, gotError)
|
||||
}
|
||||
if err == nil {
|
||||
if isoPath := state.Get("iso_file"); isoPath != c.expectedISOPath {
|
||||
if _, ok := isoPath.(string); !ok {
|
||||
isoPath = ""
|
||||
}
|
||||
t.Errorf("Expected state iso_path to be %q, got %q", c.expectedISOPath, isoPath)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
@@ -1,13 +0,0 @@
|
||||
package version
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/packer-plugin-sdk/version"
|
||||
packerVersion "github.com/hashicorp/packer/version"
|
||||
)
|
||||
|
||||
var ProxmoxPluginVersion *version.PluginVersion
|
||||
|
||||
func init() {
|
||||
ProxmoxPluginVersion = version.InitializePluginVersion(
|
||||
packerVersion.Version, packerVersion.VersionPrerelease)
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package qemu
|
||||
|
||||
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.Error("Builder must implement builder.")
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
package qemu
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
)
|
||||
|
||||
func testCommConfig() *CommConfig {
|
||||
return &CommConfig{
|
||||
Comm: communicator.Config{
|
||||
SSH: communicator.SSH{
|
||||
SSHUsername: "foo",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommConfigPrepare(t *testing.T) {
|
||||
c := testCommConfig()
|
||||
warns, errs := c.Prepare(interpolate.NewContext())
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
if len(warns) != 0 {
|
||||
t.Fatal("should not have any warnings")
|
||||
}
|
||||
|
||||
if c.HostPortMin != 2222 {
|
||||
t.Errorf("bad min communicator host port: %d", c.HostPortMin)
|
||||
}
|
||||
|
||||
if c.HostPortMax != 4444 {
|
||||
t.Errorf("bad max communicator host port: %d", c.HostPortMax)
|
||||
}
|
||||
|
||||
if c.Comm.SSHPort != 22 {
|
||||
t.Errorf("bad communicator port: %d", c.Comm.SSHPort)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommConfigPrepare_SSHHostPort(t *testing.T) {
|
||||
var c *CommConfig
|
||||
var errs []error
|
||||
var warns []string
|
||||
|
||||
// Bad
|
||||
c = testCommConfig()
|
||||
c.HostPortMin = 1000
|
||||
c.HostPortMax = 500
|
||||
warns, errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) == 0 {
|
||||
t.Fatalf("bad: %#v", errs)
|
||||
}
|
||||
if len(warns) != 0 {
|
||||
t.Fatal("should not have any warnings")
|
||||
}
|
||||
|
||||
// Good
|
||||
c = testCommConfig()
|
||||
c.HostPortMin = 50
|
||||
c.HostPortMax = 500
|
||||
warns, errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("should not have error: %s", errs)
|
||||
}
|
||||
if len(warns) != 0 {
|
||||
t.Fatal("should not have any warnings")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommConfigPrepare_SSHPrivateKey(t *testing.T) {
|
||||
var c *CommConfig
|
||||
var errs []error
|
||||
var warns []string
|
||||
|
||||
c = testCommConfig()
|
||||
c.Comm.SSHPrivateKeyFile = ""
|
||||
warns, errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("should not have error: %#v", errs)
|
||||
}
|
||||
if len(warns) != 0 {
|
||||
t.Fatal("should not have any warnings")
|
||||
}
|
||||
|
||||
c = testCommConfig()
|
||||
c.Comm.SSHPrivateKeyFile = "/i/dont/exist"
|
||||
warns, errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) == 0 {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
if len(warns) != 0 {
|
||||
t.Fatal("should not have any warnings")
|
||||
}
|
||||
|
||||
// Test bad contents
|
||||
tf, err := ioutil.TempFile("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.Remove(tf.Name())
|
||||
defer tf.Close()
|
||||
|
||||
if _, err := tf.Write([]byte("HELLO!")); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
c = testCommConfig()
|
||||
c.Comm.SSHPrivateKeyFile = tf.Name()
|
||||
warns, errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) == 0 {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
if len(warns) != 0 {
|
||||
t.Fatal("should not have any warnings")
|
||||
}
|
||||
|
||||
// Test good contents
|
||||
_, err = tf.Seek(0, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
err = tf.Truncate(0)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
_, err = tf.Write([]byte(testPem))
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
c = testCommConfig()
|
||||
c.Comm.SSHPrivateKeyFile = tf.Name()
|
||||
warns, errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("should not have error: %#v", errs)
|
||||
}
|
||||
if len(warns) != 0 {
|
||||
t.Fatal("should not have any warnings")
|
||||
}
|
||||
}
|
||||
@@ -1,695 +0,0 @@
|
||||
package qemu
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/common"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var testPem = `
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEAxd4iamvrwRJvtNDGQSIbNvvIQN8imXTRWlRY62EvKov60vqu
|
||||
hh+rDzFYAIIzlmrJopvOe0clqmi3mIP9dtkjPFrYflq52a2CF5q+BdwsJXuRHbJW
|
||||
LmStZUwW1khSz93DhvhmK50nIaczW63u4EO/jJb3xj+wxR1Nkk9bxi3DDsYFt8SN
|
||||
AzYx9kjlEYQ/+sI4/ATfmdV9h78SVotjScupd9KFzzi76gWq9gwyCBLRynTUWlyD
|
||||
2UOfJRkOvhN6/jKzvYfVVwjPSfA9IMuooHdScmC4F6KBKJl/zf/zETM0XyzIDNmH
|
||||
uOPbCiljq2WoRM+rY6ET84EO0kVXbfx8uxUsqQIDAQABAoIBAQCkPj9TF0IagbM3
|
||||
5BSs/CKbAWS4dH/D4bPlxx4IRCNirc8GUg+MRb04Xz0tLuajdQDqeWpr6iLZ0RKV
|
||||
BvreLF+TOdV7DNQ4XE4gSdJyCtCaTHeort/aordL3l0WgfI7mVk0L/yfN1PEG4YG
|
||||
E9q1TYcyrB3/8d5JwIkjabxERLglCcP+geOEJp+QijbvFIaZR/n2irlKW4gSy6ko
|
||||
9B0fgUnhkHysSg49ChHQBPQ+o5BbpuLrPDFMiTPTPhdfsvGGcyCGeqfBA56oHcSF
|
||||
K02Fg8OM+Bd1lb48LAN9nWWY4WbwV+9bkN3Ym8hO4c3a/Dxf2N7LtAQqWZzFjvM3
|
||||
/AaDvAgBAoGBAPLD+Xn1IYQPMB2XXCXfOuJewRY7RzoVWvMffJPDfm16O7wOiW5+
|
||||
2FmvxUDayk4PZy6wQMzGeGKnhcMMZTyaq2g/QtGfrvy7q1Lw2fB1VFlVblvqhoJa
|
||||
nMJojjC4zgjBkXMHsRLeTmgUKyGs+fdFbfI6uejBnnf+eMVUMIdJ+6I9AoGBANCn
|
||||
kWO9640dttyXURxNJ3lBr2H3dJOkmD6XS+u+LWqCSKQe691Y/fZ/ZL0Oc4Mhy7I6
|
||||
hsy3kDQ5k2V0fkaNODQIFJvUqXw2pMewUk8hHc9403f4fe9cPrL12rQ8WlQw4yoC
|
||||
v2B61vNczCCUDtGxlAaw8jzSRaSI5s6ax3K7enbdAoGBAJB1WYDfA2CoAQO6y9Sl
|
||||
b07A/7kQ8SN5DbPaqrDrBdJziBQxukoMJQXJeGFNUFD/DXFU5Fp2R7C86vXT7HIR
|
||||
v6m66zH+CYzOx/YE6EsUJms6UP9VIVF0Rg/RU7teXQwM01ZV32LQ8mswhTH20o/3
|
||||
uqMHmxUMEhZpUMhrfq0isyApAoGAe1UxGTXfj9AqkIVYylPIq2HqGww7+jFmVEj1
|
||||
9Wi6S6Sq72ffnzzFEPkIQL/UA4TsdHMnzsYKFPSbbXLIWUeMGyVTmTDA5c0e5XIR
|
||||
lPhMOKCAzv8w4VUzMnEkTzkFY5JqFCD/ojW57KvDdNZPVB+VEcdxyAW6aKELXMAc
|
||||
eHLc1nkCgYEApm/motCTPN32nINZ+Vvywbv64ZD+gtpeMNP3CLrbe1X9O+H52AXa
|
||||
1jCoOldWR8i2bs2NVPcKZgdo6fFULqE4dBX7Te/uYEIuuZhYLNzRO1IKU/YaqsXG
|
||||
3bfQ8hKYcSnTfE0gPtLDnqCIxTocaGLSHeG3TH9fTw+dA8FvWpUztI4=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
`
|
||||
|
||||
func testConfig() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"iso_checksum": "md5:0B0F137F17AC10944716020B018F8126",
|
||||
"iso_url": "http://www.google.com/",
|
||||
"ssh_username": "foo",
|
||||
common.BuildNameConfigKey: "foo",
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_Defaults(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
if c.OutputDir != "output-foo" {
|
||||
t.Errorf("bad output dir: %s", c.OutputDir)
|
||||
}
|
||||
|
||||
if c.CommConfig.HostPortMin != 2222 {
|
||||
t.Errorf("bad min ssh host port: %d", c.CommConfig.HostPortMin)
|
||||
}
|
||||
|
||||
if c.CommConfig.HostPortMax != 4444 {
|
||||
t.Errorf("bad max ssh host port: %d", c.CommConfig.HostPortMax)
|
||||
}
|
||||
|
||||
if c.CommConfig.Comm.SSHPort != 22 {
|
||||
t.Errorf("bad ssh port: %d", c.CommConfig.Comm.SSHPort)
|
||||
}
|
||||
|
||||
if c.VMName != "packer-foo" {
|
||||
t.Errorf("bad vm name: %s", c.VMName)
|
||||
}
|
||||
|
||||
if c.Format != "qcow2" {
|
||||
t.Errorf("bad format: %s", c.Format)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_VNCBindAddress(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
|
||||
// Test a default boot_wait
|
||||
delete(config, "vnc_bind_address")
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if c.VNCBindAddress != "127.0.0.1" {
|
||||
t.Fatalf("bad value: %s", c.VNCBindAddress)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_DiskCompaction(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
|
||||
// Bad
|
||||
config["skip_compaction"] = false
|
||||
config["disk_compression"] = true
|
||||
config["format"] = "img"
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
if c.SkipCompaction != true {
|
||||
t.Fatalf("SkipCompaction should be true")
|
||||
}
|
||||
if c.DiskCompression != false {
|
||||
t.Fatalf("DiskCompression should be false")
|
||||
}
|
||||
|
||||
// Good
|
||||
config["skip_compaction"] = false
|
||||
config["disk_compression"] = true
|
||||
config["format"] = "qcow2"
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
if c.SkipCompaction != false {
|
||||
t.Fatalf("SkipCompaction should be false")
|
||||
}
|
||||
if c.DiskCompression != true {
|
||||
t.Fatalf("DiskCompression should be true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_DiskSize(t *testing.T) {
|
||||
type testcase struct {
|
||||
InputSize string
|
||||
OutputSize string
|
||||
ErrExpected bool
|
||||
}
|
||||
|
||||
testCases := []testcase{
|
||||
{"", "40960M", false}, // not provided
|
||||
{"12345", "12345M", false}, // no unit given, defaults to M
|
||||
{"12345x", "12345x", true}, // invalid unit
|
||||
{"12345T", "12345T", false}, // terabytes
|
||||
{"12345b", "12345b", false}, // bytes get preserved when set.
|
||||
{"60000M", "60000M", false}, // Original test case
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
// Set input disk size
|
||||
var c Config
|
||||
config := testConfig()
|
||||
delete(config, "disk_size")
|
||||
config["disk_size"] = tc.InputSize
|
||||
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if (err == nil) == tc.ErrExpected {
|
||||
t.Fatalf("bad: error when providing disk size %s; Err expected: %t; err recieved: %v", tc.InputSize, tc.ErrExpected, err)
|
||||
}
|
||||
|
||||
if c.DiskSize != tc.OutputSize {
|
||||
t.Fatalf("bad size: received: %s but expected %s", c.DiskSize, tc.OutputSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_AdditionalDiskSize(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
|
||||
config["disk_additional_size"] = []string{"1M"}
|
||||
config["disk_image"] = true
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error")
|
||||
}
|
||||
|
||||
delete(config, "disk_image")
|
||||
config["disk_additional_size"] = []string{"1M"}
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
if c.AdditionalDiskSize[0] != "1M" {
|
||||
t.Fatalf("bad size: %s", c.AdditionalDiskSize)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_Format(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
|
||||
// Bad
|
||||
config["format"] = "illegal value"
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Good
|
||||
config["format"] = "qcow2"
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
// Good
|
||||
config["format"] = "raw"
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_UseBackingFile(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
|
||||
config["use_backing_file"] = true
|
||||
|
||||
// Bad: iso_url is not a disk_image
|
||||
config["disk_image"] = false
|
||||
config["format"] = "qcow2"
|
||||
c = Config{}
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Bad: format is not 'qcow2'
|
||||
config["disk_image"] = true
|
||||
config["format"] = "raw"
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Good: iso_url is a disk image and format is 'qcow2'
|
||||
config["disk_image"] = true
|
||||
config["format"] = "qcow2"
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_SkipResizeDisk(t *testing.T) {
|
||||
config := testConfig()
|
||||
config["skip_resize_disk"] = true
|
||||
config["disk_image"] = false
|
||||
|
||||
var c Config
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Errorf("unexpected warns when calling prepare with skip_resize_disk set to true: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Errorf("setting skip_resize_disk to true when disk_image is false should have error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_FloppyFiles(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
|
||||
delete(config, "floppy_files")
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("bad err: %s", err)
|
||||
}
|
||||
|
||||
if len(c.FloppyFiles) != 0 {
|
||||
t.Fatalf("bad: %#v", c.FloppyFiles)
|
||||
}
|
||||
|
||||
floppies_path := "../test-fixtures/floppies"
|
||||
config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)}
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
expected := []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)}
|
||||
if !reflect.DeepEqual(c.FloppyFiles, expected) {
|
||||
t.Fatalf("bad: %#v", c.FloppyFiles)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_InvalidFloppies(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"}
|
||||
c = Config{}
|
||||
_, errs := c.Prepare(config)
|
||||
if errs == nil {
|
||||
t.Fatalf("Nonexistent floppies should trigger multierror")
|
||||
}
|
||||
|
||||
if len(errs.(*packersdk.MultiError).Errors) != 2 {
|
||||
t.Fatalf("Multierror should work and report 2 errors")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_InvalidKey(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
|
||||
// Add a random key
|
||||
config["i_should_not_be_valid"] = true
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_OutputDir(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
|
||||
// Test with existing dir
|
||||
dir, err := ioutil.TempDir("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
config["output_directory"] = dir
|
||||
c = Config{}
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Test with a good one
|
||||
config["output_directory"] = "i-hope-i-dont-exist"
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_ShutdownTimeout(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
|
||||
// Test with a bad value
|
||||
config["shutdown_timeout"] = "this is not good"
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Test with a good one
|
||||
config["shutdown_timeout"] = "5s"
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_SSHHostPort(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
|
||||
// Bad
|
||||
config["host_port_min"] = 1000
|
||||
config["host_port_max"] = 500
|
||||
c = Config{}
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Bad
|
||||
config["host_port_min"] = -500
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Good
|
||||
config["host_port_min"] = 500
|
||||
config["host_port_max"] = 1000
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_SSHPrivateKey(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
|
||||
config["ssh_private_key_file"] = ""
|
||||
c = Config{}
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
config["ssh_private_key_file"] = "/i/dont/exist"
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Test bad contents
|
||||
tf, err := ioutil.TempFile("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.Remove(tf.Name())
|
||||
defer tf.Close()
|
||||
|
||||
if _, err := tf.Write([]byte("HELLO!")); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
config["ssh_private_key_file"] = tf.Name()
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Test good contents
|
||||
if _, err := tf.Seek(0, 0); err != nil {
|
||||
t.Fatalf("errorf getting key")
|
||||
}
|
||||
if err := tf.Truncate(0); err != nil {
|
||||
t.Fatalf("errorf getting key")
|
||||
}
|
||||
if _, err := tf.Write([]byte(testPem)); err != nil {
|
||||
t.Fatalf("errorf getting key")
|
||||
}
|
||||
config["ssh_private_key_file"] = tf.Name()
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
|
||||
// Test a default boot_wait
|
||||
delete(config, "ssh_timeout")
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Test with a bad value
|
||||
config["ssh_timeout"] = "this is not good"
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Test with a good one
|
||||
config["ssh_timeout"] = "5s"
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_QemuArgs(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
|
||||
// Test with empty
|
||||
delete(config, "qemuargs")
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(c.QemuArgs, [][]string{}) {
|
||||
t.Fatalf("bad: %#v", c.QemuArgs)
|
||||
}
|
||||
|
||||
// Test with a good one
|
||||
config["qemuargs"] = [][]interface{}{
|
||||
{"foo", "bar", "baz"},
|
||||
}
|
||||
|
||||
c = Config{}
|
||||
warns, err = c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
expected := [][]string{
|
||||
{"foo", "bar", "baz"},
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(c.QemuArgs, expected) {
|
||||
t.Fatalf("bad: %#v", c.QemuArgs)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_VNCPassword(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
config["vnc_use_password"] = true
|
||||
config["output_directory"] = "not-a-real-directory"
|
||||
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
expected := filepath.Join("not-a-real-directory", "packer-foo.monitor")
|
||||
if !reflect.DeepEqual(c.QMPSocketPath, expected) {
|
||||
t.Fatalf("Bad QMP socket Path: %s", c.QMPSocketPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommConfigPrepare_BackwardsCompatibility(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
hostPortMin := 1234
|
||||
hostPortMax := 4321
|
||||
sshTimeout := 2 * time.Minute
|
||||
|
||||
config["ssh_wait_timeout"] = sshTimeout
|
||||
config["ssh_host_port_min"] = hostPortMin
|
||||
config["ssh_host_port_max"] = hostPortMax
|
||||
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) == 0 {
|
||||
t.Fatalf("should have deprecation warn")
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
if c.CommConfig.Comm.SSHTimeout != sshTimeout {
|
||||
t.Fatalf("SSHTimeout should be %s for backwards compatibility, but it was %s", sshTimeout.String(), c.CommConfig.Comm.SSHTimeout.String())
|
||||
}
|
||||
|
||||
if c.CommConfig.HostPortMin != hostPortMin {
|
||||
t.Fatalf("HostPortMin should be %d for backwards compatibility, but it was %d", hostPortMin, c.CommConfig.HostPortMin)
|
||||
}
|
||||
|
||||
if c.CommConfig.HostPortMax != hostPortMax {
|
||||
t.Fatalf("HostPortMax should be %d for backwards compatibility, but it was %d", hostPortMax, c.CommConfig.HostPortMax)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_LoadQemuImgArgs(t *testing.T) {
|
||||
var c Config
|
||||
config := testConfig()
|
||||
config["qemu_img_args"] = map[string][]string{
|
||||
"convert": []string{"-o", "preallocation=full"},
|
||||
"resize": []string{"-foo", "bar"},
|
||||
"create": []string{"-baz", "bang"},
|
||||
}
|
||||
warns, err := c.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
assert.Equal(t, []string{"-o", "preallocation=full"},
|
||||
c.QemuImgArgs.Convert, "Convert args not loaded properly")
|
||||
assert.Equal(t, []string{"-foo", "bar"},
|
||||
c.QemuImgArgs.Resize, "Resize args not loaded properly")
|
||||
assert.Equal(t, []string{"-baz", "bang"},
|
||||
c.QemuImgArgs.Create, "Create args not loaded properly")
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package qemu
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_buildConvertCommand(t *testing.T) {
|
||||
type testCase struct {
|
||||
Step *stepConvertDisk
|
||||
Expected []string
|
||||
Reason string
|
||||
}
|
||||
testcases := []testCase{
|
||||
{
|
||||
&stepConvertDisk{
|
||||
Format: "qcow2",
|
||||
DiskCompression: false,
|
||||
},
|
||||
[]string{"convert", "-O", "qcow2", "source.qcow", "target.qcow2"},
|
||||
"Basic, happy path, no compression, no extra args",
|
||||
},
|
||||
{
|
||||
&stepConvertDisk{
|
||||
Format: "qcow2",
|
||||
DiskCompression: true,
|
||||
},
|
||||
[]string{"convert", "-c", "-O", "qcow2", "source.qcow", "target.qcow2"},
|
||||
"Basic, happy path, with compression, no extra args",
|
||||
},
|
||||
{
|
||||
&stepConvertDisk{
|
||||
Format: "qcow2",
|
||||
DiskCompression: true,
|
||||
QemuImgArgs: QemuImgArgs{
|
||||
Convert: []string{"-o", "preallocation=full"},
|
||||
},
|
||||
},
|
||||
[]string{"convert", "-c", "-o", "preallocation=full", "-O", "qcow2", "source.qcow", "target.qcow2"},
|
||||
"Basic, happy path, with compression, one set of extra args",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
command := tc.Step.buildConvertCommand("source.qcow", "target.qcow2")
|
||||
|
||||
assert.Equal(t, command, tc.Expected,
|
||||
fmt.Sprintf("%s. Expected %#v", tc.Reason, tc.Expected))
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
package qemu
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func copyTestState(t *testing.T, d *DriverMock) multistep.StateBag {
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", packersdk.TestUi(t))
|
||||
state.Put("driver", d)
|
||||
state.Put("iso_path", "example_source.qcow2")
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
func Test_StepCopySkip(t *testing.T) {
|
||||
testcases := []stepCopyDisk{
|
||||
stepCopyDisk{
|
||||
DiskImage: false,
|
||||
UseBackingFile: false,
|
||||
},
|
||||
stepCopyDisk{
|
||||
DiskImage: true,
|
||||
UseBackingFile: true,
|
||||
},
|
||||
stepCopyDisk{
|
||||
DiskImage: false,
|
||||
UseBackingFile: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
d := new(DriverMock)
|
||||
state := copyTestState(t, d)
|
||||
action := tc.Run(context.TODO(), state)
|
||||
if action != multistep.ActionContinue {
|
||||
t.Fatalf("Should have gotten an ActionContinue")
|
||||
}
|
||||
|
||||
if d.CopyCalled || d.QemuImgCalled {
|
||||
t.Fatalf("Should have skipped step since DiskImage and UseBackingFile are not set")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_StepCopyCalled(t *testing.T) {
|
||||
step := stepCopyDisk{
|
||||
DiskImage: true,
|
||||
Format: "qcow2",
|
||||
VMName: "output.qcow2",
|
||||
}
|
||||
|
||||
d := new(DriverMock)
|
||||
state := copyTestState(t, d)
|
||||
action := step.Run(context.TODO(), state)
|
||||
if action != multistep.ActionContinue {
|
||||
t.Fatalf("Should have gotten an ActionContinue")
|
||||
}
|
||||
|
||||
if !d.CopyCalled {
|
||||
t.Fatalf("Should have copied since all extensions are qcow2")
|
||||
}
|
||||
if d.QemuImgCalled {
|
||||
t.Fatalf("Should not have called qemu-img when formats match")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_StepQemuImgCalled(t *testing.T) {
|
||||
step := stepCopyDisk{
|
||||
DiskImage: true,
|
||||
Format: "raw",
|
||||
VMName: "output.qcow2",
|
||||
}
|
||||
|
||||
d := new(DriverMock)
|
||||
state := copyTestState(t, d)
|
||||
action := step.Run(context.TODO(), state)
|
||||
if action != multistep.ActionContinue {
|
||||
t.Fatalf("Should have gotten an ActionContinue")
|
||||
}
|
||||
if d.CopyCalled {
|
||||
t.Fatalf("Should not have copied since extensions don't match")
|
||||
}
|
||||
if !d.QemuImgCalled {
|
||||
t.Fatalf("Should have called qemu-img since extensions don't match")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_StepQemuImgCalledWithExtraArgs(t *testing.T) {
|
||||
step := &stepCopyDisk{
|
||||
DiskImage: true,
|
||||
Format: "raw",
|
||||
VMName: "output.qcow2",
|
||||
QemuImgArgs: QemuImgArgs{
|
||||
Convert: []string{"-o", "preallocation=full"},
|
||||
},
|
||||
}
|
||||
|
||||
d := new(DriverMock)
|
||||
state := copyTestState(t, d)
|
||||
action := step.Run(context.TODO(), state)
|
||||
if action != multistep.ActionContinue {
|
||||
t.Fatalf("Should have gotten an ActionContinue")
|
||||
}
|
||||
if d.CopyCalled {
|
||||
t.Fatalf("Should not have copied since extensions don't match")
|
||||
}
|
||||
if !d.QemuImgCalled {
|
||||
t.Fatalf("Should have called qemu-img since extensions don't match")
|
||||
}
|
||||
assert.Equal(
|
||||
t,
|
||||
d.QemuImgCalls,
|
||||
[]string{"convert", "-o", "preallocation=full", "-O", "raw",
|
||||
"example_source.qcow2", "output.qcow2"},
|
||||
"should have added user extra args")
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
package qemu
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_buildCreateCommand(t *testing.T) {
|
||||
type testCase struct {
|
||||
Step *stepCreateDisk
|
||||
I int
|
||||
Expected []string
|
||||
Reason string
|
||||
}
|
||||
testcases := []testCase{
|
||||
{
|
||||
&stepCreateDisk{
|
||||
Format: "qcow2",
|
||||
UseBackingFile: false,
|
||||
},
|
||||
0,
|
||||
[]string{"create", "-f", "qcow2", "target.qcow2", "1234M"},
|
||||
"Basic, happy path, no backing store, no extra args",
|
||||
},
|
||||
{
|
||||
&stepCreateDisk{
|
||||
Format: "qcow2",
|
||||
DiskImage: true,
|
||||
UseBackingFile: true,
|
||||
AdditionalDiskSize: []string{"1M", "2M"},
|
||||
},
|
||||
0,
|
||||
[]string{"create", "-f", "qcow2", "-b", "source.qcow2", "target.qcow2", "1234M"},
|
||||
"Basic, happy path, backing store, additional disks",
|
||||
},
|
||||
{
|
||||
&stepCreateDisk{
|
||||
Format: "qcow2",
|
||||
UseBackingFile: true,
|
||||
DiskImage: true,
|
||||
},
|
||||
1,
|
||||
[]string{"create", "-f", "qcow2", "target.qcow2", "1234M"},
|
||||
"Basic, happy path, backing store set but not at first index, no extra args",
|
||||
},
|
||||
{
|
||||
&stepCreateDisk{
|
||||
Format: "qcow2",
|
||||
UseBackingFile: true,
|
||||
DiskImage: true,
|
||||
QemuImgArgs: QemuImgArgs{
|
||||
Create: []string{"-foo", "bar"},
|
||||
},
|
||||
},
|
||||
0,
|
||||
[]string{"create", "-f", "qcow2", "-b", "source.qcow2", "-foo", "bar", "target.qcow2", "1234M"},
|
||||
"Basic, happy path, backing store set, extra args",
|
||||
},
|
||||
{
|
||||
&stepCreateDisk{
|
||||
Format: "qcow2",
|
||||
UseBackingFile: true,
|
||||
QemuImgArgs: QemuImgArgs{
|
||||
Create: []string{"-foo", "bar"},
|
||||
},
|
||||
},
|
||||
1,
|
||||
[]string{"create", "-f", "qcow2", "-foo", "bar", "target.qcow2", "1234M"},
|
||||
"Basic, happy path, backing store set but not at first index, extra args",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("iso_path", "source.qcow2")
|
||||
command := tc.Step.buildCreateCommand("target.qcow2", "1234M", tc.I, state)
|
||||
|
||||
assert.Equal(t, command, tc.Expected,
|
||||
fmt.Sprintf("%s. Expected %#v", tc.Reason, tc.Expected))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_StepCreateCalled(t *testing.T) {
|
||||
type testCase struct {
|
||||
Step *stepCreateDisk
|
||||
Expected []string
|
||||
Reason string
|
||||
}
|
||||
testcases := []testCase{
|
||||
{
|
||||
&stepCreateDisk{
|
||||
Format: "qcow2",
|
||||
DiskImage: true,
|
||||
DiskSize: "1M",
|
||||
VMName: "target",
|
||||
UseBackingFile: true,
|
||||
},
|
||||
[]string{
|
||||
"create", "-f", "qcow2", "-b", "source.qcow2", "target", "1M",
|
||||
},
|
||||
"Basic, happy path, backing store, no additional disks",
|
||||
},
|
||||
{
|
||||
&stepCreateDisk{
|
||||
Format: "raw",
|
||||
DiskImage: false,
|
||||
DiskSize: "4M",
|
||||
VMName: "target",
|
||||
UseBackingFile: false,
|
||||
},
|
||||
[]string{
|
||||
"create", "-f", "raw", "target", "4M",
|
||||
},
|
||||
"Basic, happy path, raw, no additional disks",
|
||||
},
|
||||
{
|
||||
&stepCreateDisk{
|
||||
Format: "qcow2",
|
||||
DiskImage: true,
|
||||
DiskSize: "4M",
|
||||
VMName: "target",
|
||||
UseBackingFile: false,
|
||||
AdditionalDiskSize: []string{"3M", "8M"},
|
||||
},
|
||||
[]string{
|
||||
"create", "-f", "qcow2", "target-1", "3M",
|
||||
"create", "-f", "qcow2", "target-2", "8M",
|
||||
},
|
||||
"Skips disk creation when disk can be copied",
|
||||
},
|
||||
{
|
||||
&stepCreateDisk{
|
||||
Format: "qcow2",
|
||||
DiskImage: true,
|
||||
DiskSize: "4M",
|
||||
VMName: "target",
|
||||
UseBackingFile: false,
|
||||
},
|
||||
nil,
|
||||
"Skips disk creation when disk can be copied",
|
||||
},
|
||||
{
|
||||
&stepCreateDisk{
|
||||
Format: "qcow2",
|
||||
DiskImage: true,
|
||||
DiskSize: "1M",
|
||||
VMName: "target",
|
||||
UseBackingFile: true,
|
||||
AdditionalDiskSize: []string{"3M", "8M"},
|
||||
},
|
||||
[]string{
|
||||
"create", "-f", "qcow2", "-b", "source.qcow2", "target", "1M",
|
||||
"create", "-f", "qcow2", "target-1", "3M",
|
||||
"create", "-f", "qcow2", "target-2", "8M",
|
||||
},
|
||||
"Basic, happy path, backing store, additional disks",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
d := new(DriverMock)
|
||||
state := copyTestState(t, d)
|
||||
state.Put("iso_path", "source.qcow2")
|
||||
action := tc.Step.Run(context.TODO(), state)
|
||||
if action != multistep.ActionContinue {
|
||||
t.Fatalf("Should have gotten an ActionContinue")
|
||||
}
|
||||
|
||||
assert.Equal(t, d.QemuImgCalls, tc.Expected,
|
||||
fmt.Sprintf("%s. Expected %#v", tc.Reason, tc.Expected))
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package qemu
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
func TestStepHTTPIPDiscover_Run(t *testing.T) {
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", &packersdk.BasicUi{
|
||||
Reader: new(bytes.Buffer),
|
||||
Writer: new(bytes.Buffer),
|
||||
})
|
||||
config := &Config{}
|
||||
state.Put("config", config)
|
||||
step := new(stepHTTPIPDiscover)
|
||||
hostIp := "10.0.2.2"
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
httpIp := state.Get("http_ip").(string)
|
||||
if httpIp != hostIp {
|
||||
t.Fatalf("bad: Http ip is %s but was supposed to be %s", httpIp, hostIp)
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
package qemu
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestStepResizeDisk_Skips(t *testing.T) {
|
||||
testConfigs := []*Config{
|
||||
&Config{
|
||||
DiskImage: false,
|
||||
SkipResizeDisk: false,
|
||||
},
|
||||
&Config{
|
||||
DiskImage: false,
|
||||
SkipResizeDisk: true,
|
||||
},
|
||||
}
|
||||
for _, config := range testConfigs {
|
||||
state := testState(t)
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
|
||||
state.Put("config", config)
|
||||
step := new(stepResizeDisk)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
if len(driver.QemuImgCalls) > 0 {
|
||||
t.Fatal("should NOT have called qemu-img")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_buildResizeCommand(t *testing.T) {
|
||||
type testCase struct {
|
||||
Step *stepResizeDisk
|
||||
Expected []string
|
||||
Reason string
|
||||
}
|
||||
testcases := []testCase{
|
||||
{
|
||||
&stepResizeDisk{
|
||||
Format: "qcow2",
|
||||
DiskSize: "1234M",
|
||||
},
|
||||
[]string{"resize", "-f", "qcow2", "source.qcow", "1234M"},
|
||||
"no extra args",
|
||||
},
|
||||
{
|
||||
&stepResizeDisk{
|
||||
Format: "qcow2",
|
||||
DiskSize: "1234M",
|
||||
QemuImgArgs: QemuImgArgs{
|
||||
Resize: []string{"-foo", "bar"},
|
||||
},
|
||||
},
|
||||
[]string{"resize", "-f", "qcow2", "-foo", "bar", "source.qcow", "1234M"},
|
||||
"one set of extra args",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
command := tc.Step.buildResizeCommand("source.qcow")
|
||||
|
||||
assert.Equal(t, command, tc.Expected,
|
||||
fmt.Sprintf("%s. Expected %#v", tc.Reason, tc.Expected))
|
||||
}
|
||||
}
|
||||
@@ -1,710 +0,0 @@
|
||||
package qemu
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func runTestState(t *testing.T, config *Config) multistep.StateBag {
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", config)
|
||||
|
||||
d := new(DriverMock)
|
||||
d.VersionResult = "3.0.0"
|
||||
state.Put("driver", d)
|
||||
|
||||
state.Put("commHostPort", 5000)
|
||||
state.Put("floppy_path", "fake_floppy_path")
|
||||
state.Put("http_ip", "127.0.0.1")
|
||||
state.Put("http_port", 1234)
|
||||
state.Put("iso_path", "/path/to/test.iso")
|
||||
state.Put("qemu_disk_paths", []string{})
|
||||
state.Put("vnc_port", 5905)
|
||||
state.Put("vnc_password", "fake_vnc_password")
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
func Test_UserOverrides(t *testing.T) {
|
||||
type testCase struct {
|
||||
Config *Config
|
||||
Expected []string
|
||||
Reason string
|
||||
}
|
||||
testcases := []testCase{
|
||||
{
|
||||
&Config{
|
||||
HTTPConfig: commonsteps.HTTPConfig{
|
||||
HTTPDir: "http/directory",
|
||||
},
|
||||
OutputDir: "output/directory",
|
||||
VMName: "myvm",
|
||||
QemuArgs: [][]string{
|
||||
{"-randomflag1", "{{.HTTPIP}}-{{.HTTPPort}}-{{.HTTPDir}}"},
|
||||
{"-randomflag2", "{{.OutputDir}}-{{.Name}}"},
|
||||
},
|
||||
},
|
||||
[]string{
|
||||
"-display", "gtk",
|
||||
"-drive", "file=/path/to/test.iso,media=cdrom",
|
||||
"-randomflag1", "127.0.0.1-1234-http/directory",
|
||||
"-randomflag2", "output/directory-myvm",
|
||||
"-device", ",netdev=user.0",
|
||||
},
|
||||
"Test that interpolation overrides work.",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
VMName: "myvm",
|
||||
QemuArgs: [][]string{{"-display", "partydisplay"}},
|
||||
},
|
||||
[]string{
|
||||
"-display", "partydisplay",
|
||||
"-drive", "file=/path/to/test.iso,media=cdrom",
|
||||
"-device", ",netdev=user.0",
|
||||
},
|
||||
"User input overrides default, rest is populated as normal",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
VMName: "myvm",
|
||||
NetDevice: "mynetdevice",
|
||||
QemuArgs: [][]string{{"-device", "somerandomdevice"}},
|
||||
},
|
||||
[]string{
|
||||
"-display", "gtk",
|
||||
"-device", "somerandomdevice",
|
||||
"-device", "mynetdevice,netdev=user.0",
|
||||
"-drive", "file=/path/to/test.iso,media=cdrom",
|
||||
},
|
||||
"Net device gets added",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
state := runTestState(t, tc.Config)
|
||||
|
||||
step := &stepRun{
|
||||
atLeastVersion2: true,
|
||||
ui: packersdk.TestUi(t),
|
||||
}
|
||||
args, err := step.getCommandArgs(tc.Config, state)
|
||||
if err != nil {
|
||||
t.Fatalf("should not have an error getting args. Error: %s", err)
|
||||
}
|
||||
|
||||
expected := append([]string{
|
||||
"-m", "0M",
|
||||
"-boot", "once=d",
|
||||
"-fda", "fake_floppy_path",
|
||||
"-name", "myvm",
|
||||
"-netdev", "user,id=user.0,hostfwd=tcp::5000-:0",
|
||||
"-vnc", ":5",
|
||||
"-machine", "type=,accel="},
|
||||
tc.Expected...)
|
||||
|
||||
assert.ElementsMatch(t, args, expected,
|
||||
fmt.Sprintf("%s, \nRecieved: %#v", tc.Reason, args))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Test_DriveAndDeviceArgs(t *testing.T) {
|
||||
type testCase struct {
|
||||
Config *Config
|
||||
ExtraState map[string]interface{}
|
||||
Step *stepRun
|
||||
Expected []string
|
||||
Reason string
|
||||
}
|
||||
|
||||
testcases := []testCase{
|
||||
{
|
||||
&Config{},
|
||||
map[string]interface{}{},
|
||||
&stepRun{
|
||||
atLeastVersion2: true,
|
||||
ui: packersdk.TestUi(t),
|
||||
},
|
||||
[]string{
|
||||
"-display", "gtk",
|
||||
"-boot", "once=d",
|
||||
"-drive", "file=/path/to/test.iso,media=cdrom",
|
||||
},
|
||||
"Boot value should default to once=d when diskImage isn't set",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
DiskImage: true,
|
||||
DiskInterface: "virtio-scsi",
|
||||
|
||||
OutputDir: "path_to_output",
|
||||
DiskCache: "writeback",
|
||||
Format: "qcow2",
|
||||
DetectZeroes: "off",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"cd_path": "fake_cd_path.iso",
|
||||
"qemu_disk_paths": []string{"path_to_output"},
|
||||
},
|
||||
&stepRun{
|
||||
DiskImage: true,
|
||||
atLeastVersion2: true,
|
||||
ui: packersdk.TestUi(t),
|
||||
},
|
||||
[]string{
|
||||
"-display", "gtk",
|
||||
"-boot", "c",
|
||||
"-device", "virtio-scsi-pci,id=scsi0",
|
||||
"-device", "scsi-hd,bus=scsi0.0,drive=drive0",
|
||||
"-drive", "if=none,file=path_to_output,id=drive0,cache=writeback,discard=,format=qcow2",
|
||||
"-drive", "file=fake_cd_path.iso,media=cdrom",
|
||||
},
|
||||
"virtio-scsi interface, DiskImage true, extra cdrom, detectZeroes off",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
DiskImage: true,
|
||||
DiskInterface: "virtio-scsi",
|
||||
|
||||
OutputDir: "path_to_output",
|
||||
DiskCache: "writeback",
|
||||
Format: "qcow2",
|
||||
DetectZeroes: "on",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"cd_path": "fake_cd_path.iso",
|
||||
"qemu_disk_paths": []string{"path_to_output"},
|
||||
},
|
||||
&stepRun{
|
||||
DiskImage: true,
|
||||
atLeastVersion2: true,
|
||||
ui: packersdk.TestUi(t),
|
||||
},
|
||||
[]string{
|
||||
"-display", "gtk",
|
||||
"-boot", "c",
|
||||
"-device", "virtio-scsi-pci,id=scsi0",
|
||||
"-device", "scsi-hd,bus=scsi0.0,drive=drive0",
|
||||
"-drive", "if=none,file=path_to_output,id=drive0,cache=writeback,discard=,format=qcow2,detect-zeroes=on",
|
||||
"-drive", "file=fake_cd_path.iso,media=cdrom",
|
||||
},
|
||||
"virtio-scsi interface, DiskImage true, extra cdrom, detectZeroes on",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
DiskInterface: "virtio-scsi",
|
||||
|
||||
OutputDir: "path_to_output",
|
||||
DiskCache: "writeback",
|
||||
Format: "qcow2",
|
||||
DetectZeroes: "off",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"cd_path": "fake_cd_path.iso",
|
||||
// when disk image is false, we will always have at least one
|
||||
// disk path: the one we create to be the main disk.
|
||||
"qemu_disk_paths": []string{"qemupath1", "qemupath2"},
|
||||
},
|
||||
&stepRun{
|
||||
atLeastVersion2: true,
|
||||
ui: packersdk.TestUi(t),
|
||||
},
|
||||
[]string{
|
||||
"-display", "gtk",
|
||||
"-boot", "once=d",
|
||||
"-device", "virtio-scsi-pci,id=scsi0",
|
||||
"-device", "scsi-hd,bus=scsi0.0,drive=drive0",
|
||||
"-device", "scsi-hd,bus=scsi0.0,drive=drive1",
|
||||
"-drive", "if=none,file=qemupath1,id=drive0,cache=writeback,discard=,format=qcow2",
|
||||
"-drive", "if=none,file=qemupath2,id=drive1,cache=writeback,discard=,format=qcow2",
|
||||
"-drive", "file=/path/to/test.iso,media=cdrom",
|
||||
"-drive", "file=fake_cd_path.iso,media=cdrom",
|
||||
},
|
||||
"virtio-scsi interface, bootable iso, cdrom",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
DiskInterface: "virtio-scsi",
|
||||
|
||||
OutputDir: "path_to_output",
|
||||
DiskCache: "writeback",
|
||||
Format: "qcow2",
|
||||
DetectZeroes: "on",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"cd_path": "fake_cd_path.iso",
|
||||
// when disk image is false, we will always have at least one
|
||||
// disk path: the one we create to be the main disk.
|
||||
"qemu_disk_paths": []string{"qemupath1", "qemupath2"},
|
||||
},
|
||||
&stepRun{
|
||||
atLeastVersion2: true,
|
||||
ui: packersdk.TestUi(t),
|
||||
},
|
||||
[]string{
|
||||
"-display", "gtk",
|
||||
"-boot", "once=d",
|
||||
"-device", "virtio-scsi-pci,id=scsi0",
|
||||
"-device", "scsi-hd,bus=scsi0.0,drive=drive0",
|
||||
"-device", "scsi-hd,bus=scsi0.0,drive=drive1",
|
||||
"-drive", "if=none,file=qemupath1,id=drive0,cache=writeback,discard=,format=qcow2,detect-zeroes=on",
|
||||
"-drive", "if=none,file=qemupath2,id=drive1,cache=writeback,discard=,format=qcow2,detect-zeroes=on",
|
||||
"-drive", "file=/path/to/test.iso,media=cdrom",
|
||||
"-drive", "file=fake_cd_path.iso,media=cdrom",
|
||||
},
|
||||
"virtio-scsi interface, DiskImage false, extra cdrom, detect zeroes on",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
DiskInterface: "virtio-scsi",
|
||||
|
||||
OutputDir: "path_to_output",
|
||||
DiskCache: "writeback",
|
||||
Format: "qcow2",
|
||||
},
|
||||
map[string]interface{}{
|
||||
// when disk image is false, we will always have at least one
|
||||
// disk path: the one we create to be the main disk.
|
||||
"qemu_disk_paths": []string{"output/dir/path/mydisk.qcow2"},
|
||||
},
|
||||
&stepRun{
|
||||
atLeastVersion2: true,
|
||||
ui: packersdk.TestUi(t),
|
||||
},
|
||||
[]string{
|
||||
"-display", "gtk",
|
||||
"-boot", "once=d",
|
||||
"-device", "virtio-scsi-pci,id=scsi0",
|
||||
"-device", "scsi-hd,bus=scsi0.0,drive=drive0",
|
||||
"-drive", "if=none,file=output/dir/path/mydisk.qcow2,id=drive0,cache=writeback,discard=,format=qcow2,detect-zeroes=",
|
||||
"-drive", "file=/path/to/test.iso,media=cdrom",
|
||||
},
|
||||
"virtio-scsi interface, DiskImage false, no extra disks or cds",
|
||||
},
|
||||
{
|
||||
&Config{},
|
||||
map[string]interface{}{
|
||||
"cd_path": "fake_cd_path.iso",
|
||||
"qemu_disk_paths": []string{"output/dir/path/mydisk.qcow2"},
|
||||
},
|
||||
&stepRun{
|
||||
atLeastVersion2: true,
|
||||
ui: packersdk.TestUi(t),
|
||||
},
|
||||
[]string{
|
||||
"-display", "gtk",
|
||||
"-boot", "once=d",
|
||||
"-drive", "file=output/dir/path/mydisk.qcow2,if=,cache=,discard=,format=,detect-zeroes=",
|
||||
"-drive", "file=/path/to/test.iso,media=cdrom",
|
||||
"-drive", "file=fake_cd_path.iso,media=cdrom",
|
||||
},
|
||||
"cd_path is set and DiskImage is false",
|
||||
},
|
||||
{
|
||||
&Config{},
|
||||
map[string]interface{}{
|
||||
// when disk image is false, we will always have at least one
|
||||
// disk path: the one we create to be the main disk.
|
||||
"qemu_disk_paths": []string{"output/dir/path/mydisk.qcow2"},
|
||||
},
|
||||
&stepRun{
|
||||
atLeastVersion2: true,
|
||||
ui: packersdk.TestUi(t),
|
||||
},
|
||||
[]string{
|
||||
"-display", "gtk",
|
||||
"-boot", "once=d",
|
||||
"-drive", "file=output/dir/path/mydisk.qcow2,if=,cache=,discard=,format=,detect-zeroes=",
|
||||
"-drive", "file=/path/to/test.iso,media=cdrom",
|
||||
},
|
||||
"empty config",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
OutputDir: "path_to_output",
|
||||
DiskInterface: "virtio",
|
||||
DiskCache: "writeback",
|
||||
Format: "qcow2",
|
||||
},
|
||||
map[string]interface{}{
|
||||
// when disk image is false, we will always have at least one
|
||||
// disk path: the one we create to be the main disk.
|
||||
"qemu_disk_paths": []string{"output/dir/path/mydisk.qcow2"},
|
||||
},
|
||||
&stepRun{
|
||||
atLeastVersion2: false,
|
||||
ui: packersdk.TestUi(t),
|
||||
},
|
||||
[]string{
|
||||
"-boot", "once=d",
|
||||
"-drive", "file=path_to_output,if=virtio,cache=writeback,format=qcow2",
|
||||
"-drive", "file=/path/to/test.iso,media=cdrom",
|
||||
},
|
||||
"version less than 2",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
OutputDir: "path_to_output",
|
||||
DiskInterface: "virtio",
|
||||
DiskCache: "writeback",
|
||||
Format: "qcow2",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"cd_path": "fake_cd_path.iso",
|
||||
"qemu_disk_paths": []string{"qemupath1", "qemupath2"},
|
||||
},
|
||||
&stepRun{
|
||||
atLeastVersion2: true,
|
||||
ui: packersdk.TestUi(t),
|
||||
},
|
||||
[]string{
|
||||
"-display", "gtk",
|
||||
"-boot", "once=d",
|
||||
"-drive", "file=qemupath1,if=virtio,cache=writeback,discard=,format=qcow2,detect-zeroes=",
|
||||
"-drive", "file=qemupath2,if=virtio,cache=writeback,discard=,format=qcow2,detect-zeroes=",
|
||||
"-drive", "file=fake_cd_path.iso,media=cdrom",
|
||||
"-drive", "file=/path/to/test.iso,media=cdrom",
|
||||
},
|
||||
"virtio interface with extra disks",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
DiskImage: true,
|
||||
OutputDir: "path_to_output",
|
||||
DiskInterface: "virtio",
|
||||
DiskCache: "writeback",
|
||||
Format: "qcow2",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"cd_path": "fake_cd_path.iso",
|
||||
"qemu_disk_paths": []string{"path_to_output"},
|
||||
},
|
||||
&stepRun{
|
||||
DiskImage: true,
|
||||
atLeastVersion2: true,
|
||||
ui: packersdk.TestUi(t),
|
||||
},
|
||||
[]string{
|
||||
"-display", "gtk",
|
||||
"-boot", "c",
|
||||
"-drive", "file=path_to_output,if=virtio,cache=writeback,discard=,format=qcow2,detect-zeroes=",
|
||||
"-drive", "file=fake_cd_path.iso,media=cdrom",
|
||||
},
|
||||
"virtio interface with disk image",
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
state := runTestState(t, &Config{})
|
||||
for k, v := range tc.ExtraState {
|
||||
state.Put(k, v)
|
||||
}
|
||||
|
||||
args, err := tc.Step.getCommandArgs(tc.Config, state)
|
||||
if err != nil {
|
||||
t.Fatalf("should not have an error getting args. Error: %s", err)
|
||||
}
|
||||
|
||||
expected := append([]string{
|
||||
"-m", "0M",
|
||||
"-fda", "fake_floppy_path",
|
||||
"-name", "",
|
||||
"-netdev", "user,id=user.0,hostfwd=tcp::5000-:0",
|
||||
"-vnc", ":5",
|
||||
"-machine", "type=,accel=",
|
||||
"-device", ",netdev=user.0"},
|
||||
tc.Expected...)
|
||||
|
||||
assert.ElementsMatch(t, args, expected,
|
||||
fmt.Sprintf("%s, \nRecieved: %#v", tc.Reason, args))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_OptionalConfigOptionsGetSet(t *testing.T) {
|
||||
c := &Config{
|
||||
VNCUsePassword: true,
|
||||
QMPEnable: true,
|
||||
QMPSocketPath: "qmp_path",
|
||||
VMName: "MyFancyName",
|
||||
MachineType: "pc",
|
||||
Accelerator: "hvf",
|
||||
}
|
||||
|
||||
state := runTestState(t, c)
|
||||
step := &stepRun{
|
||||
atLeastVersion2: true,
|
||||
ui: packersdk.TestUi(t),
|
||||
}
|
||||
args, err := step.getCommandArgs(c, state)
|
||||
if err != nil {
|
||||
t.Fatalf("should not have an error getting args. Error: %s", err)
|
||||
}
|
||||
|
||||
expected := []string{
|
||||
"-display", "gtk",
|
||||
"-m", "0M",
|
||||
"-boot", "once=d",
|
||||
"-fda", "fake_floppy_path",
|
||||
"-name", "MyFancyName",
|
||||
"-netdev", "user,id=user.0,hostfwd=tcp::5000-:0",
|
||||
"-vnc", ":5,password",
|
||||
"-machine", "type=pc,accel=hvf",
|
||||
"-device", ",netdev=user.0",
|
||||
"-drive", "file=/path/to/test.iso,media=cdrom",
|
||||
"-qmp", "unix:qmp_path,server,nowait",
|
||||
}
|
||||
|
||||
assert.ElementsMatch(t, args, expected, "password flag should be set, and d drive should be set: %s", args)
|
||||
}
|
||||
|
||||
// Tests for presence of Packer-generated arguments. Doesn't test that
|
||||
// arguments which shouldn't be there are absent.
|
||||
func Test_Defaults(t *testing.T) {
|
||||
type testCase struct {
|
||||
Config *Config
|
||||
ExtraState map[string]interface{}
|
||||
Step *stepRun
|
||||
Expected []string
|
||||
Reason string
|
||||
}
|
||||
|
||||
testcases := []testCase{
|
||||
{
|
||||
&Config{},
|
||||
map[string]interface{}{},
|
||||
&stepRun{ui: packersdk.TestUi(t)},
|
||||
[]string{"-boot", "once=d"},
|
||||
"Boot value should default to once=d",
|
||||
},
|
||||
{
|
||||
&Config{},
|
||||
map[string]interface{}{},
|
||||
&stepRun{
|
||||
DiskImage: true,
|
||||
ui: packersdk.TestUi(t),
|
||||
},
|
||||
[]string{"-boot", "c"},
|
||||
"Boot value should be set to c when DiskImage is set on step",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
QMPEnable: true,
|
||||
QMPSocketPath: "/path/to/socket",
|
||||
},
|
||||
map[string]interface{}{},
|
||||
&stepRun{ui: packersdk.TestUi(t)},
|
||||
[]string{"-qmp", "unix:/path/to/socket,server,nowait"},
|
||||
"Args should contain -qmp when qmp_enable is set",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
QMPEnable: true,
|
||||
},
|
||||
map[string]interface{}{},
|
||||
&stepRun{ui: packersdk.TestUi(t)},
|
||||
[]string{"-qmp", "unix:,server,nowait"},
|
||||
"Args contain -qmp even when socket path isn't set, if qmp enabled",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
VMName: "partyname",
|
||||
},
|
||||
map[string]interface{}{},
|
||||
&stepRun{ui: packersdk.TestUi(t)},
|
||||
[]string{"-name", "partyname"},
|
||||
"Name is set from config",
|
||||
},
|
||||
{
|
||||
&Config{},
|
||||
map[string]interface{}{},
|
||||
&stepRun{ui: packersdk.TestUi(t)},
|
||||
[]string{"-name", ""},
|
||||
"Name is set from config, even when name is blank (which won't " +
|
||||
"happen for real thanks to defaulting in build prepare)",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
Accelerator: "none",
|
||||
MachineType: "fancymachine",
|
||||
},
|
||||
map[string]interface{}{},
|
||||
&stepRun{ui: packersdk.TestUi(t)},
|
||||
[]string{"-machine", "type=fancymachine"},
|
||||
"Don't add accelerator tag when no accelerator is set.",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
Accelerator: "kvm",
|
||||
MachineType: "fancymachine",
|
||||
},
|
||||
map[string]interface{}{},
|
||||
&stepRun{ui: packersdk.TestUi(t)},
|
||||
[]string{"-machine", "type=fancymachine,accel=kvm"},
|
||||
"Add accelerator tag when accelerator is set.",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
NetBridge: "fakebridge",
|
||||
},
|
||||
map[string]interface{}{},
|
||||
&stepRun{ui: packersdk.TestUi(t)},
|
||||
[]string{"-netdev", "bridge,id=user.0,br=fakebridge"},
|
||||
"Add netbridge tag when netbridge is set.",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
CommConfig: CommConfig{
|
||||
Comm: communicator.Config{
|
||||
Type: "none",
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{},
|
||||
&stepRun{ui: packersdk.TestUi(t)},
|
||||
[]string{"-netdev", "user,id=user.0"},
|
||||
"No host forwarding when no net bridge and no communicator",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
CommConfig: CommConfig{
|
||||
Comm: communicator.Config{
|
||||
Type: "ssh",
|
||||
SSH: communicator.SSH{
|
||||
SSHPort: 4567,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"commHostPort": 1111,
|
||||
},
|
||||
&stepRun{ui: packersdk.TestUi(t)},
|
||||
[]string{"-netdev", "user,id=user.0,hostfwd=tcp::1111-:4567"},
|
||||
"Host forwarding when a communicator is configured",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
VNCBindAddress: "1.1.1.1",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"vnc_port": 5959,
|
||||
},
|
||||
&stepRun{ui: packersdk.TestUi(t)},
|
||||
[]string{"-vnc", "1.1.1.1:59"},
|
||||
"no VNC password should be set",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
VNCBindAddress: "1.1.1.1",
|
||||
VNCUsePassword: true,
|
||||
},
|
||||
map[string]interface{}{
|
||||
"vnc_port": 5959,
|
||||
},
|
||||
&stepRun{ui: packersdk.TestUi(t)},
|
||||
[]string{"-vnc", "1.1.1.1:59,password"},
|
||||
"VNC password should be set",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
MemorySize: 2345,
|
||||
},
|
||||
map[string]interface{}{},
|
||||
&stepRun{ui: packersdk.TestUi(t)},
|
||||
[]string{"-m", "2345M"},
|
||||
"Memory is set, with unit M",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
CpuCount: 2,
|
||||
},
|
||||
map[string]interface{}{},
|
||||
&stepRun{ui: packersdk.TestUi(t)},
|
||||
[]string{"-smp", "cpus=2,sockets=2"},
|
||||
"both cpus and sockets are set to config's CpuCount",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
CpuCount: 2,
|
||||
},
|
||||
map[string]interface{}{},
|
||||
&stepRun{ui: packersdk.TestUi(t)},
|
||||
[]string{"-smp", "cpus=2,sockets=2"},
|
||||
"both cpus and sockets are set to config's CpuCount",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
CpuCount: 2,
|
||||
},
|
||||
map[string]interface{}{
|
||||
"floppy_path": "/path/to/floppy",
|
||||
},
|
||||
&stepRun{ui: packersdk.TestUi(t)},
|
||||
[]string{"-fda", "/path/to/floppy"},
|
||||
"floppy path should be set under fda flag, when it exists",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
Headless: false,
|
||||
Display: "fakedisplay",
|
||||
UseDefaultDisplay: false,
|
||||
},
|
||||
map[string]interface{}{},
|
||||
&stepRun{
|
||||
atLeastVersion2: true,
|
||||
ui: packersdk.TestUi(t),
|
||||
},
|
||||
[]string{"-display", "fakedisplay"},
|
||||
"Display option should value config display",
|
||||
},
|
||||
{
|
||||
&Config{
|
||||
Headless: false,
|
||||
},
|
||||
map[string]interface{}{},
|
||||
&stepRun{
|
||||
atLeastVersion2: true,
|
||||
ui: packersdk.TestUi(t),
|
||||
},
|
||||
[]string{"-display", "gtk"},
|
||||
"Display option should default to gtk",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
state := runTestState(t, &Config{})
|
||||
for k, v := range tc.ExtraState {
|
||||
state.Put(k, v)
|
||||
}
|
||||
|
||||
args, err := tc.Step.getCommandArgs(tc.Config, state)
|
||||
if err != nil {
|
||||
t.Fatalf("should not have an error getting args. Error: %s", err)
|
||||
}
|
||||
if !matchArgument(args, tc.Expected) {
|
||||
t.Fatalf("Couldn't find %#v in result. Got: %#v, Reason: %s",
|
||||
tc.Expected, args, tc.Reason)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This test makes sure that arguments don't end up in the final boot command
|
||||
// if they aren't configured in the config.
|
||||
// func TestDefaultsAbsentValues(t *testing.T) {}
|
||||
func matchArgument(actual []string, expected []string) bool {
|
||||
key := expected[0]
|
||||
for i, k := range actual {
|
||||
if key == k {
|
||||
if expected[1] == actual[i+1] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
package qemu
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
func Test_Shutdown_Null_success(t *testing.T) {
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", packersdk.TestUi(t))
|
||||
driverMock := new(DriverMock)
|
||||
driverMock.WaitForShutdownState = true
|
||||
state.Put("driver", driverMock)
|
||||
|
||||
step := &stepShutdown{
|
||||
ShutdownCommand: "",
|
||||
ShutdownTimeout: 5 * time.Minute,
|
||||
Comm: &communicator.Config{
|
||||
Type: "none",
|
||||
},
|
||||
}
|
||||
action := step.Run(context.TODO(), state)
|
||||
if action != multistep.ActionContinue {
|
||||
t.Fatalf("Should have successfully shut down.")
|
||||
}
|
||||
err := state.Get("error")
|
||||
if err != nil {
|
||||
err = err.(error)
|
||||
t.Fatalf("Shutdown shouldn't have errored; err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Shutdown_Null_failure(t *testing.T) {
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", packersdk.TestUi(t))
|
||||
driverMock := new(DriverMock)
|
||||
driverMock.WaitForShutdownState = false
|
||||
state.Put("driver", driverMock)
|
||||
|
||||
step := &stepShutdown{
|
||||
ShutdownCommand: "",
|
||||
ShutdownTimeout: 5 * time.Minute,
|
||||
Comm: &communicator.Config{
|
||||
Type: "none",
|
||||
},
|
||||
}
|
||||
action := step.Run(context.TODO(), state)
|
||||
if action != multistep.ActionHalt {
|
||||
t.Fatalf("Shouldn't have successfully shut down.")
|
||||
}
|
||||
err := state.Get("error")
|
||||
if err == nil {
|
||||
t.Fatalf("Shutdown should have errored")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Shutdown_NoShutdownCommand(t *testing.T) {
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", packersdk.TestUi(t))
|
||||
driverMock := new(DriverMock)
|
||||
state.Put("driver", driverMock)
|
||||
|
||||
step := &stepShutdown{
|
||||
ShutdownCommand: "",
|
||||
ShutdownTimeout: 5 * time.Minute,
|
||||
Comm: &communicator.Config{
|
||||
Type: "ssh",
|
||||
},
|
||||
}
|
||||
action := step.Run(context.TODO(), state)
|
||||
if action != multistep.ActionContinue {
|
||||
t.Fatalf("Should have successfully shut down.")
|
||||
}
|
||||
|
||||
if !driverMock.StopCalled {
|
||||
t.Fatalf("should have called Stop through the driver.")
|
||||
}
|
||||
err := state.Get("error")
|
||||
if err != nil {
|
||||
err = err.(error)
|
||||
t.Fatalf("Shutdown shouldn't have errored; err: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package qemu
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
func testState(t *testing.T) multistep.StateBag {
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("driver", new(DriverMock))
|
||||
state.Put("ui", &packersdk.BasicUi{
|
||||
Reader: new(bytes.Buffer),
|
||||
Writer: new(bytes.Buffer),
|
||||
})
|
||||
return state
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package version
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/packer-plugin-sdk/version"
|
||||
packerVersion "github.com/hashicorp/packer/version"
|
||||
)
|
||||
|
||||
var QemuPluginVersion *version.PluginVersion
|
||||
|
||||
func init() {
|
||||
QemuPluginVersion = version.InitializePluginVersion(
|
||||
packerVersion.Version, packerVersion.VersionPrerelease)
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
func TestLocalArtifact_impl(t *testing.T) {
|
||||
var _ packersdk.Artifact = new(artifact)
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
)
|
||||
|
||||
func TestDriverConfigPrepare(t *testing.T) {
|
||||
tc := []struct {
|
||||
name string
|
||||
config *DriverConfig
|
||||
expectedConfig *DriverConfig
|
||||
errs []error
|
||||
}{
|
||||
{
|
||||
name: "Set default values",
|
||||
config: new(DriverConfig),
|
||||
expectedConfig: &DriverConfig{
|
||||
FusionAppPath: "/Applications/VMware Fusion.app",
|
||||
RemoteDatastore: "datastore1",
|
||||
RemoteCacheDatastore: "datastore1",
|
||||
RemoteCacheDirectory: "packer_cache",
|
||||
RemotePort: 22,
|
||||
RemoteUser: "root",
|
||||
},
|
||||
errs: nil,
|
||||
},
|
||||
{
|
||||
name: "Override default values",
|
||||
config: &DriverConfig{
|
||||
FusionAppPath: "foo",
|
||||
RemoteDatastore: "set-datastore1",
|
||||
RemoteCacheDatastore: "set-datastore1",
|
||||
RemoteCacheDirectory: "set_packer_cache",
|
||||
RemotePort: 443,
|
||||
RemoteUser: "admin",
|
||||
},
|
||||
expectedConfig: &DriverConfig{
|
||||
FusionAppPath: "foo",
|
||||
RemoteDatastore: "set-datastore1",
|
||||
RemoteCacheDatastore: "set-datastore1",
|
||||
RemoteCacheDirectory: "set_packer_cache",
|
||||
RemotePort: 443,
|
||||
RemoteUser: "admin",
|
||||
},
|
||||
errs: nil,
|
||||
},
|
||||
{
|
||||
name: "Invalid remote type",
|
||||
config: &DriverConfig{
|
||||
RemoteType: "invalid",
|
||||
RemoteHost: "host",
|
||||
},
|
||||
expectedConfig: nil,
|
||||
errs: []error{fmt.Errorf("Only 'esx5' value is accepted for remote_type")},
|
||||
},
|
||||
{
|
||||
name: "Remote host not set",
|
||||
config: &DriverConfig{
|
||||
RemoteType: "esx5",
|
||||
},
|
||||
expectedConfig: nil,
|
||||
errs: []error{fmt.Errorf("remote_host must be specified")},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range tc {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
errs := c.config.Prepare(interpolate.NewContext())
|
||||
if !reflect.DeepEqual(errs, c.errs) {
|
||||
t.Fatalf("bad: \n expected '%v' \nactual '%v'", c.errs, errs)
|
||||
}
|
||||
if len(c.errs) == 0 {
|
||||
if diff := cmp.Diff(c.config, c.expectedConfig); diff != "" {
|
||||
t.Fatalf("bad value: %s", diff)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
)
|
||||
|
||||
func TestESX5Driver_implDriver(t *testing.T) {
|
||||
var _ Driver = new(ESX5Driver)
|
||||
}
|
||||
|
||||
func TestESX5Driver_UpdateVMX(t *testing.T) {
|
||||
var driver ESX5Driver
|
||||
data := make(map[string]string)
|
||||
driver.UpdateVMX("0.0.0.0", "", 5900, data)
|
||||
if _, ok := data["remotedisplay.vnc.ip"]; ok {
|
||||
// Do not add the remotedisplay.vnc.ip on ESXi
|
||||
t.Fatal("invalid VMX data key: remotedisplay.vnc.ip")
|
||||
}
|
||||
if enabled := data["remotedisplay.vnc.enabled"]; enabled != "TRUE" {
|
||||
t.Errorf("bad VMX data for key remotedisplay.vnc.enabled: %v", enabled)
|
||||
}
|
||||
if port := data["remotedisplay.vnc.port"]; port != fmt.Sprint(port) {
|
||||
t.Errorf("bad VMX data for key remotedisplay.vnc.port: %v", port)
|
||||
}
|
||||
}
|
||||
|
||||
func TestESX5Driver_implOutputDir(t *testing.T) {
|
||||
var _ OutputDir = new(ESX5Driver)
|
||||
}
|
||||
|
||||
func TestESX5Driver_implVNCAddressFinder(t *testing.T) {
|
||||
var _ VNCAddressFinder = new(ESX5Driver)
|
||||
}
|
||||
|
||||
func TestESX5Driver_implRemoteDriver(t *testing.T) {
|
||||
var _ RemoteDriver = new(ESX5Driver)
|
||||
}
|
||||
|
||||
func TestESX5Driver_HostIP(t *testing.T) {
|
||||
expected_host := "127.0.0.1"
|
||||
|
||||
//create mock SSH server
|
||||
listen, _ := net.Listen("tcp", fmt.Sprintf("%s:0", expected_host))
|
||||
port := listen.Addr().(*net.TCPAddr).Port
|
||||
defer listen.Close()
|
||||
|
||||
driver := ESX5Driver{Host: "localhost", Port: port}
|
||||
state := new(multistep.BasicStateBag)
|
||||
|
||||
if host, _ := driver.HostIP(state); host != expected_host {
|
||||
t.Error(fmt.Sprintf("Expected string, %s but got %s", expected_host, host))
|
||||
}
|
||||
}
|
||||
|
||||
func TestESX5Driver_CommHost(t *testing.T) {
|
||||
const expected_host = "127.0.0.1"
|
||||
|
||||
conf := make(map[string]interface{})
|
||||
conf["communicator"] = "winrm"
|
||||
conf["winrm_username"] = "username"
|
||||
conf["winrm_password"] = "password"
|
||||
conf["winrm_host"] = expected_host
|
||||
|
||||
var commConfig communicator.Config
|
||||
err := config.Decode(&commConfig, nil, conf)
|
||||
if err != nil {
|
||||
t.Fatalf("error decoding config: %v", err)
|
||||
}
|
||||
state := new(multistep.BasicStateBag)
|
||||
sshConfig := SSHConfig{Comm: commConfig}
|
||||
state.Put("sshConfig", &sshConfig)
|
||||
driver := ESX5Driver{CommConfig: *(&sshConfig.Comm)}
|
||||
|
||||
host, err := driver.CommHost(state)
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
if host != expected_host {
|
||||
t.Errorf("bad host name: %s", host)
|
||||
}
|
||||
address, ok := state.GetOk("vm_address")
|
||||
if !ok {
|
||||
t.Error("state not updated with vm_address")
|
||||
}
|
||||
if address.(string) != expected_host {
|
||||
t.Errorf("bad vm_address: %s", address.(string))
|
||||
}
|
||||
}
|
||||
|
||||
func TestESX5Driver_VerifyOvfTool(t *testing.T) {
|
||||
driver := ESX5Driver{}
|
||||
// should always skip validation if export is skipped, so this should always
|
||||
// pass even when ovftool is not installed.
|
||||
err := driver.VerifyOvfTool(true, false)
|
||||
if err != nil {
|
||||
t.Fatalf("shouldn't fail ever because should always skip check")
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDriverMock_impl(t *testing.T) {
|
||||
var _ Driver = new(DriverMock)
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,15 +0,0 @@
|
||||
// +build !windows
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestWorkstationVersion_ws14(t *testing.T) {
|
||||
input := `VMware Workstation Information:
|
||||
VMware Workstation 14.1.1 build-7528167 Release`
|
||||
if err := workstationTestVersion("10", input); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -1,315 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
)
|
||||
|
||||
func TestHWConfigPrepare(t *testing.T) {
|
||||
c := new(HWConfig)
|
||||
|
||||
if errs := c.Prepare(interpolate.NewContext()); len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
|
||||
if c.CpuCount < 0 {
|
||||
t.Errorf("bad cpu count: %d", c.CpuCount)
|
||||
}
|
||||
|
||||
if c.CoreCount < 0 {
|
||||
t.Errorf("bad core count: %d", c.CoreCount)
|
||||
}
|
||||
|
||||
if c.MemorySize < 0 {
|
||||
t.Errorf("bad memory size: %d", c.MemorySize)
|
||||
}
|
||||
|
||||
if c.Sound {
|
||||
t.Errorf("peripheral choice (sound) should be conservative: %t", c.Sound)
|
||||
}
|
||||
|
||||
if c.USB {
|
||||
t.Errorf("peripheral choice (usb) should be conservative: %t", c.USB)
|
||||
}
|
||||
|
||||
if strings.ToUpper(c.Parallel) != "NONE" {
|
||||
t.Errorf("parallel port should not be defined: %s", c.Parallel)
|
||||
}
|
||||
|
||||
if strings.ToUpper(c.Serial) != "NONE" {
|
||||
t.Errorf("serial port should not be defined: %s", c.Serial)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHWConfigParallel_File(t *testing.T) {
|
||||
c := new(HWConfig)
|
||||
|
||||
c.Parallel = "file:filename"
|
||||
if errs := c.Prepare(interpolate.NewContext()); len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
|
||||
if !c.HasParallel() {
|
||||
t.Errorf("parallel port should be defined")
|
||||
}
|
||||
|
||||
parallel, err := c.ReadParallel()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read parallel port definition: %s", err)
|
||||
}
|
||||
|
||||
switch parallel.Union.(type) {
|
||||
case *ParallelPortFile:
|
||||
break
|
||||
default:
|
||||
t.Errorf("parallel port should be a file type")
|
||||
}
|
||||
|
||||
if parallel.File.Filename != "filename" {
|
||||
t.Errorf("parallel port filename should be \"filename\": %s", parallel.File.Filename)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHWConfigParallel_Device(t *testing.T) {
|
||||
c := new(HWConfig)
|
||||
|
||||
c.Parallel = "device:devicename,uni"
|
||||
if errs := c.Prepare(interpolate.NewContext()); len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
|
||||
if !c.HasParallel() {
|
||||
t.Errorf("parallel port should be defined")
|
||||
}
|
||||
|
||||
parallel, err := c.ReadParallel()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read parallel port definition: %s", err)
|
||||
}
|
||||
|
||||
switch parallel.Union.(type) {
|
||||
case *ParallelPortDevice:
|
||||
break
|
||||
default:
|
||||
t.Errorf("parallel port should be a device type")
|
||||
}
|
||||
|
||||
if strings.ToLower(parallel.Device.Bidirectional) != "false" {
|
||||
t.Errorf("parallel port device should not be bidirectional: %s", parallel.Device.Bidirectional)
|
||||
}
|
||||
|
||||
if parallel.Device.Devicename != "devicename" {
|
||||
t.Errorf("parallel port device should be \"devicename\": %s", parallel.Device.Devicename)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHWConfigParallel_Auto(t *testing.T) {
|
||||
c := new(HWConfig)
|
||||
|
||||
c.Parallel = "auto:bi"
|
||||
if errs := c.Prepare(interpolate.NewContext()); len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
|
||||
if !c.HasParallel() {
|
||||
t.Errorf("parallel port should be defined")
|
||||
}
|
||||
|
||||
parallel, err := c.ReadParallel()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read parallel port definition: %s", err)
|
||||
}
|
||||
|
||||
switch parallel.Union.(type) {
|
||||
case *ParallelPortAuto:
|
||||
break
|
||||
default:
|
||||
t.Errorf("parallel port should be an auto type")
|
||||
}
|
||||
|
||||
if strings.ToLower(parallel.Auto.Bidirectional) != "true" {
|
||||
t.Errorf("parallel port device should be bidirectional: %s", parallel.Auto.Bidirectional)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHWConfigParallel_None(t *testing.T) {
|
||||
c := new(HWConfig)
|
||||
|
||||
c.Parallel = "none"
|
||||
if errs := c.Prepare(interpolate.NewContext()); len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
|
||||
if !c.HasParallel() {
|
||||
t.Errorf("parallel port should be defined")
|
||||
}
|
||||
|
||||
parallel, err := c.ReadParallel()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read parallel port definition: %s", err)
|
||||
}
|
||||
|
||||
if parallel.Union != nil {
|
||||
t.Errorf("parallel port shouldn't exist")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHWConfigSerial_File(t *testing.T) {
|
||||
c := new(HWConfig)
|
||||
|
||||
c.Serial = "file:filename,true"
|
||||
if errs := c.Prepare(interpolate.NewContext()); len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
|
||||
if !c.HasSerial() {
|
||||
t.Errorf("serial port should be defined")
|
||||
}
|
||||
|
||||
serial, err := c.ReadSerial()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read serial port definition: %s", err)
|
||||
}
|
||||
|
||||
switch serial.Union.(type) {
|
||||
case *SerialConfigFile:
|
||||
break
|
||||
default:
|
||||
t.Errorf("serial port should be a file type")
|
||||
}
|
||||
|
||||
if serial.File.Filename != "filename" {
|
||||
t.Errorf("serial port filename should be \"filename\": %s", serial.File.Filename)
|
||||
}
|
||||
|
||||
if strings.ToLower(serial.File.Yield) != "true" {
|
||||
t.Errorf("serial port yield should be true: %s", serial.File.Yield)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHWConfigSerial_Device(t *testing.T) {
|
||||
c := new(HWConfig)
|
||||
|
||||
c.Serial = "device:devicename,true"
|
||||
if errs := c.Prepare(interpolate.NewContext()); len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
|
||||
if !c.HasSerial() {
|
||||
t.Errorf("serial port should be defined")
|
||||
}
|
||||
|
||||
serial, err := c.ReadSerial()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read serial port definition: %s", err)
|
||||
}
|
||||
|
||||
switch serial.Union.(type) {
|
||||
case *SerialConfigDevice:
|
||||
break
|
||||
default:
|
||||
t.Errorf("serial port should be a device type")
|
||||
}
|
||||
|
||||
if serial.Device.Devicename != "devicename" {
|
||||
t.Errorf("serial port device should be \"devicename\": %s", serial.Device.Devicename)
|
||||
}
|
||||
|
||||
if strings.ToLower(serial.Device.Yield) != "true" {
|
||||
t.Errorf("serial port device should yield: %s", serial.Device.Yield)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHWConfigSerial_Pipe(t *testing.T) {
|
||||
c := new(HWConfig)
|
||||
|
||||
c.Serial = "pipe:mypath,client,app,true"
|
||||
if errs := c.Prepare(interpolate.NewContext()); len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
|
||||
if !c.HasSerial() {
|
||||
t.Errorf("serial port should be defined")
|
||||
}
|
||||
|
||||
serial, err := c.ReadSerial()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read serial port definition: %s", err)
|
||||
}
|
||||
|
||||
switch serial.Union.(type) {
|
||||
case *SerialConfigPipe:
|
||||
break
|
||||
default:
|
||||
t.Errorf("serial port should be a pipe type")
|
||||
}
|
||||
|
||||
if serial.Pipe.Filename != "mypath" {
|
||||
t.Errorf("serial port pipe name should be \"mypath\": %s", serial.Pipe.Filename)
|
||||
}
|
||||
|
||||
if strings.ToLower(serial.Pipe.Endpoint) != "client" {
|
||||
t.Errorf("serial port endpoint should be \"client\": %s", serial.Pipe.Endpoint)
|
||||
}
|
||||
|
||||
if strings.ToLower(serial.Pipe.Host) != "true" {
|
||||
t.Errorf("serial port host type for app should be true: %s", serial.Pipe.Host)
|
||||
}
|
||||
|
||||
if strings.ToLower(serial.Pipe.Yield) != "true" {
|
||||
t.Errorf("serial port should yield: %s", serial.Pipe.Yield)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHWConfigSerial_Auto(t *testing.T) {
|
||||
c := new(HWConfig)
|
||||
|
||||
c.Serial = "auto:true"
|
||||
if errs := c.Prepare(interpolate.NewContext()); len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
|
||||
if !c.HasSerial() {
|
||||
t.Errorf("serial port should be defined")
|
||||
}
|
||||
|
||||
serial, err := c.ReadSerial()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read serial port definition: %s", err)
|
||||
}
|
||||
|
||||
switch serial.Union.(type) {
|
||||
case *SerialConfigAuto:
|
||||
break
|
||||
default:
|
||||
t.Errorf("serial port should be an auto type")
|
||||
}
|
||||
|
||||
if strings.ToLower(serial.Auto.Yield) != "true" {
|
||||
t.Errorf("serial port should yield: %s", serial.Auto.Yield)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHWConfigSerial_None(t *testing.T) {
|
||||
c := new(HWConfig)
|
||||
|
||||
c.Serial = "none"
|
||||
if errs := c.Prepare(interpolate.NewContext()); len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
|
||||
if !c.HasSerial() {
|
||||
t.Errorf("serial port should be defined")
|
||||
}
|
||||
|
||||
serial, err := c.ReadSerial()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read serial port definition: %s", err)
|
||||
}
|
||||
|
||||
if serial.Union != nil {
|
||||
t.Errorf("serial port shouldn't exist")
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/common"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
)
|
||||
|
||||
func TestOutputConfigPrepare(t *testing.T) {
|
||||
c := new(OutputConfig)
|
||||
if c.OutputDir != "" {
|
||||
t.Fatalf("what: %s", c.OutputDir)
|
||||
}
|
||||
|
||||
pc := &common.PackerConfig{PackerBuildName: "foo"}
|
||||
errs := c.Prepare(interpolate.NewContext(), pc)
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
|
||||
if c.OutputDir == "" {
|
||||
t.Fatal("should have output dir")
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLocalOutputDir_impl(t *testing.T) {
|
||||
var _ OutputDir = new(LocalOutputDir)
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRemoteDriverMock_impl(t *testing.T) {
|
||||
var _ Driver = new(RemoteDriverMock)
|
||||
var _ RemoteDriver = new(RemoteDriverMock)
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/hashicorp/packer-plugin-sdk/bootcommand"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
)
|
||||
|
||||
func TestRunConfig_Prepare(t *testing.T) {
|
||||
tc := []struct {
|
||||
name string
|
||||
config *RunConfig
|
||||
expectedConfig *RunConfig
|
||||
driver *DriverConfig
|
||||
errs []error
|
||||
warnings []string
|
||||
}{
|
||||
{
|
||||
name: "VNC dafaults",
|
||||
config: &RunConfig{},
|
||||
expectedConfig: &RunConfig{
|
||||
VNCPortMin: 5900,
|
||||
VNCPortMax: 6000,
|
||||
VNCBindAddress: "127.0.0.1",
|
||||
},
|
||||
driver: new(DriverConfig),
|
||||
errs: nil,
|
||||
warnings: nil,
|
||||
},
|
||||
{
|
||||
name: "VNC port min less than vnc port max",
|
||||
config: &RunConfig{
|
||||
VNCPortMin: 5000,
|
||||
VNCPortMax: 5900,
|
||||
},
|
||||
expectedConfig: &RunConfig{
|
||||
VNCPortMin: 5000,
|
||||
VNCPortMax: 5900,
|
||||
VNCBindAddress: "127.0.0.1",
|
||||
},
|
||||
driver: new(DriverConfig),
|
||||
errs: nil,
|
||||
warnings: nil,
|
||||
},
|
||||
{
|
||||
name: "VNC port min bigger than vnc port max",
|
||||
config: &RunConfig{
|
||||
VNCPortMin: 5900,
|
||||
VNCPortMax: 5000,
|
||||
},
|
||||
expectedConfig: nil,
|
||||
driver: new(DriverConfig),
|
||||
errs: []error{fmt.Errorf("vnc_port_min must be less than vnc_port_max")},
|
||||
warnings: nil,
|
||||
},
|
||||
{
|
||||
name: "VNC port min must be positive",
|
||||
config: &RunConfig{
|
||||
VNCPortMin: -1,
|
||||
},
|
||||
expectedConfig: nil,
|
||||
driver: new(DriverConfig),
|
||||
errs: []error{fmt.Errorf("vnc_port_min must be positive")},
|
||||
warnings: nil,
|
||||
},
|
||||
{
|
||||
name: "fail when vnc_over_websocket set when remote_type is not set",
|
||||
config: &RunConfig{
|
||||
VNCOverWebsocket: true,
|
||||
},
|
||||
expectedConfig: nil,
|
||||
driver: new(DriverConfig),
|
||||
errs: []error{fmt.Errorf("'vnc_over_websocket' can only be used with remote VMWare builds.")},
|
||||
warnings: nil,
|
||||
},
|
||||
{
|
||||
name: "warn about ignored vnc configuration",
|
||||
config: &RunConfig{
|
||||
VNCOverWebsocket: true,
|
||||
VNCPortMin: 5000,
|
||||
VNCPortMax: 5900,
|
||||
},
|
||||
expectedConfig: &RunConfig{
|
||||
VNCOverWebsocket: true,
|
||||
VNCPortMin: 5000,
|
||||
VNCPortMax: 5900,
|
||||
},
|
||||
driver: &DriverConfig{RemoteType: "esxi"},
|
||||
errs: nil,
|
||||
warnings: []string{"[WARN] When 'vnc_over_websocket' is set " +
|
||||
"any other VNC configuration will be ignored."},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range tc {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
warnings, errs := c.config.Prepare(interpolate.NewContext(), c.driver)
|
||||
if !reflect.DeepEqual(errs, c.errs) {
|
||||
t.Fatalf("bad: \n expected '%v' \nactual '%v'", c.errs, errs)
|
||||
}
|
||||
if diff := cmp.Diff(warnings, c.warnings); diff != "" {
|
||||
t.Fatalf("unexpected warnings: %s", diff)
|
||||
}
|
||||
if len(c.errs) == 0 {
|
||||
if diff := cmp.Diff(c.config, c.expectedConfig,
|
||||
cmpopts.IgnoreFields(bootcommand.VNCConfig{},
|
||||
"BootConfig",
|
||||
)); diff != "" {
|
||||
t.Fatalf("unexpected config: %s", diff)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
)
|
||||
|
||||
func testSSHConfig() *SSHConfig {
|
||||
return &SSHConfig{
|
||||
Comm: communicator.Config{
|
||||
SSH: communicator.SSH{
|
||||
SSHUsername: "foo",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestSSHConfigPrepare(t *testing.T) {
|
||||
c := testSSHConfig()
|
||||
errs := c.Prepare(interpolate.NewContext())
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
|
||||
if c.Comm.SSHPort != 22 {
|
||||
t.Errorf("bad ssh port: %d", c.Comm.SSHPort)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSSHConfigPrepare_SSHPrivateKey(t *testing.T) {
|
||||
var c *SSHConfig
|
||||
var errs []error
|
||||
|
||||
c = testSSHConfig()
|
||||
c.Comm.SSHPrivateKeyFile = ""
|
||||
errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("should not have error: %#v", errs)
|
||||
}
|
||||
|
||||
c = testSSHConfig()
|
||||
c.Comm.SSHPrivateKeyFile = "/i/dont/exist"
|
||||
errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) == 0 {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Test bad contents
|
||||
tf, err := ioutil.TempFile("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.Remove(tf.Name())
|
||||
defer tf.Close()
|
||||
|
||||
if _, err := tf.Write([]byte("HELLO!")); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
c = testSSHConfig()
|
||||
c.Comm.SSHPrivateKeyFile = tf.Name()
|
||||
errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) == 0 {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Test good contents
|
||||
tf.Seek(0, 0)
|
||||
tf.Truncate(0)
|
||||
tf.Write([]byte(testPem))
|
||||
c = testSSHConfig()
|
||||
c.Comm.SSHPrivateKeyFile = tf.Name()
|
||||
errs = c.Prepare(interpolate.NewContext())
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("should not have error: %#v", errs)
|
||||
}
|
||||
}
|
||||
|
||||
const testPem = `
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEAxd4iamvrwRJvtNDGQSIbNvvIQN8imXTRWlRY62EvKov60vqu
|
||||
hh+rDzFYAIIzlmrJopvOe0clqmi3mIP9dtkjPFrYflq52a2CF5q+BdwsJXuRHbJW
|
||||
LmStZUwW1khSz93DhvhmK50nIaczW63u4EO/jJb3xj+wxR1Nkk9bxi3DDsYFt8SN
|
||||
AzYx9kjlEYQ/+sI4/ATfmdV9h78SVotjScupd9KFzzi76gWq9gwyCBLRynTUWlyD
|
||||
2UOfJRkOvhN6/jKzvYfVVwjPSfA9IMuooHdScmC4F6KBKJl/zf/zETM0XyzIDNmH
|
||||
uOPbCiljq2WoRM+rY6ET84EO0kVXbfx8uxUsqQIDAQABAoIBAQCkPj9TF0IagbM3
|
||||
5BSs/CKbAWS4dH/D4bPlxx4IRCNirc8GUg+MRb04Xz0tLuajdQDqeWpr6iLZ0RKV
|
||||
BvreLF+TOdV7DNQ4XE4gSdJyCtCaTHeort/aordL3l0WgfI7mVk0L/yfN1PEG4YG
|
||||
E9q1TYcyrB3/8d5JwIkjabxERLglCcP+geOEJp+QijbvFIaZR/n2irlKW4gSy6ko
|
||||
9B0fgUnhkHysSg49ChHQBPQ+o5BbpuLrPDFMiTPTPhdfsvGGcyCGeqfBA56oHcSF
|
||||
K02Fg8OM+Bd1lb48LAN9nWWY4WbwV+9bkN3Ym8hO4c3a/Dxf2N7LtAQqWZzFjvM3
|
||||
/AaDvAgBAoGBAPLD+Xn1IYQPMB2XXCXfOuJewRY7RzoVWvMffJPDfm16O7wOiW5+
|
||||
2FmvxUDayk4PZy6wQMzGeGKnhcMMZTyaq2g/QtGfrvy7q1Lw2fB1VFlVblvqhoJa
|
||||
nMJojjC4zgjBkXMHsRLeTmgUKyGs+fdFbfI6uejBnnf+eMVUMIdJ+6I9AoGBANCn
|
||||
kWO9640dttyXURxNJ3lBr2H3dJOkmD6XS+u+LWqCSKQe691Y/fZ/ZL0Oc4Mhy7I6
|
||||
hsy3kDQ5k2V0fkaNODQIFJvUqXw2pMewUk8hHc9403f4fe9cPrL12rQ8WlQw4yoC
|
||||
v2B61vNczCCUDtGxlAaw8jzSRaSI5s6ax3K7enbdAoGBAJB1WYDfA2CoAQO6y9Sl
|
||||
b07A/7kQ8SN5DbPaqrDrBdJziBQxukoMJQXJeGFNUFD/DXFU5Fp2R7C86vXT7HIR
|
||||
v6m66zH+CYzOx/YE6EsUJms6UP9VIVF0Rg/RU7teXQwM01ZV32LQ8mswhTH20o/3
|
||||
uqMHmxUMEhZpUMhrfq0isyApAoGAe1UxGTXfj9AqkIVYylPIq2HqGww7+jFmVEj1
|
||||
9Wi6S6Sq72ffnzzFEPkIQL/UA4TsdHMnzsYKFPSbbXLIWUeMGyVTmTDA5c0e5XIR
|
||||
lPhMOKCAzv8w4VUzMnEkTzkFY5JqFCD/ojW57KvDdNZPVB+VEcdxyAW6aKELXMAc
|
||||
eHLc1nkCgYEApm/motCTPN32nINZ+Vvywbv64ZD+gtpeMNP3CLrbe1X9O+H52AXa
|
||||
1jCoOldWR8i2bs2NVPcKZgdo6fFULqE4dBX7Te/uYEIuuZhYLNzRO1IKU/YaqsXG
|
||||
3bfQ8hKYcSnTfE0gPtLDnqCIxTocaGLSHeG3TH9fTw+dA8FvWpUztI4=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
`
|
||||
@@ -1,29 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
)
|
||||
|
||||
func TestCommHost(t *testing.T) {
|
||||
state := testState(t)
|
||||
config := SSHConfig{
|
||||
Comm: communicator.Config{
|
||||
Type: "ssh",
|
||||
SSH: communicator.SSH{
|
||||
SSHHost: "127.0.0.1",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
hostFunc := CommHost(&config)
|
||||
out, err := hostFunc(state)
|
||||
if err != nil {
|
||||
t.Fatalf("Should not have had an error")
|
||||
}
|
||||
|
||||
if out != "127.0.0.1" {
|
||||
t.Fatalf("Should have respected ssh override.")
|
||||
}
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepCleanVMX_impl(t *testing.T) {
|
||||
var _ multistep.Step = new(StepCleanVMX)
|
||||
}
|
||||
|
||||
func TestStepCleanVMX(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepCleanVMX)
|
||||
|
||||
vmxPath := testVMXFile(t)
|
||||
defer os.Remove(vmxPath)
|
||||
state.Put("vmx_path", vmxPath)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCleanVMX_floppyPath(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepCleanVMX)
|
||||
|
||||
vmxPath := testVMXFile(t)
|
||||
defer os.Remove(vmxPath)
|
||||
if err := ioutil.WriteFile(vmxPath, []byte(testVMXFloppyPath), 0644); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Set the path to the temporary vmx
|
||||
state.Put("vmx_path", vmxPath)
|
||||
|
||||
// Add the floppy device to the list of temporary build devices
|
||||
state.Put("temporaryDevices", []string{"floppy0"})
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the resulting data
|
||||
vmxContents, err := ioutil.ReadFile(vmxPath)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
vmxData := ParseVMX(string(vmxContents))
|
||||
|
||||
cases := []struct {
|
||||
Key string
|
||||
Value string
|
||||
}{
|
||||
{"floppy0.present", "FALSE"},
|
||||
{"floppy0.filetype", ""},
|
||||
{"floppy0.filename", ""},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
if tc.Value == "" {
|
||||
if _, ok := vmxData[tc.Key]; ok {
|
||||
t.Fatalf("should not have key: %s", tc.Key)
|
||||
}
|
||||
} else {
|
||||
if vmxData[tc.Key] != tc.Value {
|
||||
t.Fatalf("bad: %s %#v", tc.Key, vmxData[tc.Key])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCleanVMX_isoPath(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepCleanVMX)
|
||||
|
||||
vmxPath := testVMXFile(t)
|
||||
defer os.Remove(vmxPath)
|
||||
if err := ioutil.WriteFile(vmxPath, []byte(testVMXISOPath), 0644); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Set the path to the temporary vmx
|
||||
state.Put("vmx_path", vmxPath)
|
||||
|
||||
// Add the cdrom device to the list of temporary build devices
|
||||
state.Put("temporaryDevices", []string{"ide0:0"})
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the resulting data
|
||||
vmxContents, err := ioutil.ReadFile(vmxPath)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
vmxData := ParseVMX(string(vmxContents))
|
||||
|
||||
cases := []struct {
|
||||
Key string
|
||||
Value string
|
||||
}{
|
||||
{"ide0:0.filename", "auto detect"},
|
||||
{"ide0:0.devicetype", "cdrom-raw"},
|
||||
{"ide0:1.filename", "bar"},
|
||||
{"foo", "bar"},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
if tc.Value == "" {
|
||||
if _, ok := vmxData[tc.Key]; ok {
|
||||
t.Fatalf("should not have key: %s", tc.Key)
|
||||
}
|
||||
} else {
|
||||
if vmxData[tc.Key] != tc.Value {
|
||||
t.Fatalf("bad: %s %#v", tc.Key, vmxData[tc.Key])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCleanVMX_ethernet(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := &StepCleanVMX{
|
||||
RemoveEthernetInterfaces: true,
|
||||
}
|
||||
|
||||
vmxPath := testVMXFile(t)
|
||||
defer os.Remove(vmxPath)
|
||||
if err := ioutil.WriteFile(vmxPath, []byte(testVMXEthernet), 0644); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Set the path to the temporary vmx
|
||||
state.Put("vmx_path", vmxPath)
|
||||
|
||||
// TODO: Add the ethernet devices to the list of temporary build devices
|
||||
// state.Put("temporaryDevices", []string{"ethernet0", "ethernet1"})
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the resulting data
|
||||
vmxContents, err := ioutil.ReadFile(vmxPath)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
vmxData := ParseVMX(string(vmxContents))
|
||||
|
||||
cases := []struct {
|
||||
Key string
|
||||
Value string
|
||||
}{
|
||||
{"ethernet0.addresstype", ""},
|
||||
{"ethernet0.bsdname", ""},
|
||||
{"ethernet0.connectiontype", ""},
|
||||
{"ethernet1.addresstype", ""},
|
||||
{"ethernet1.bsdname", ""},
|
||||
{"ethernet1.connectiontype", ""},
|
||||
{"foo", "bar"},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
if tc.Value == "" {
|
||||
if _, ok := vmxData[tc.Key]; ok {
|
||||
t.Fatalf("should not have key: %s", tc.Key)
|
||||
}
|
||||
} else {
|
||||
if vmxData[tc.Key] != tc.Value {
|
||||
t.Fatalf("bad: %s %#v", tc.Key, vmxData[tc.Key])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const testVMXFloppyPath = `
|
||||
floppy0.present = "TRUE"
|
||||
floppy0.filetype = "file"
|
||||
`
|
||||
|
||||
const testVMXISOPath = `
|
||||
ide0:0.devicetype = "cdrom-image"
|
||||
ide0:0.filename = "foo"
|
||||
ide0:1.filename = "bar"
|
||||
foo = "bar"
|
||||
`
|
||||
|
||||
const testVMXEthernet = `
|
||||
ethernet0.addresstype = "generated"
|
||||
ethernet0.bsdname = "en0"
|
||||
ethernet0.connectiontype = "nat"
|
||||
ethernet1.addresstype = "generated"
|
||||
ethernet1.bsdname = "en1"
|
||||
ethernet1.connectiontype = "nat"
|
||||
foo = "bar"
|
||||
`
|
||||
@@ -1,62 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepCompactDisk_impl(t *testing.T) {
|
||||
var _ multistep.Step = new(StepCompactDisk)
|
||||
}
|
||||
|
||||
func TestStepCompactDisk(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepCompactDisk)
|
||||
|
||||
diskFullPaths := []string{"foo"}
|
||||
state.Put("disk_full_paths", diskFullPaths)
|
||||
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the driver
|
||||
if !driver.CompactDiskCalled {
|
||||
t.Fatal("should've called")
|
||||
}
|
||||
if driver.CompactDiskPath != "foo" {
|
||||
t.Fatal("should call with right path")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCompactDisk_skip(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepCompactDisk)
|
||||
step.Skip = true
|
||||
|
||||
diskFullPaths := []string{"foo"}
|
||||
state.Put("disk_full_paths", diskFullPaths)
|
||||
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the driver
|
||||
if driver.CompactDiskCalled {
|
||||
t.Fatal("should not have called")
|
||||
}
|
||||
}
|
||||
@@ -1,379 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func testVMXFile(t *testing.T) string {
|
||||
tf, err := ioutil.TempFile("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// displayName must always be set
|
||||
err = WriteVMX(tf.Name(), map[string]string{"displayName": "PackerBuild"})
|
||||
if err != nil {
|
||||
t.Fatalf("error writing .vmx file: %v", err)
|
||||
}
|
||||
tf.Close()
|
||||
|
||||
return tf.Name()
|
||||
}
|
||||
|
||||
func TestStepConfigureVMX_impl(t *testing.T) {
|
||||
var _ multistep.Step = new(StepConfigureVMX)
|
||||
}
|
||||
|
||||
func TestStepConfigureVMX(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepConfigureVMX)
|
||||
step.CustomData = map[string]string{
|
||||
"foo": "bar",
|
||||
}
|
||||
|
||||
vmxPath := testVMXFile(t)
|
||||
defer os.Remove(vmxPath)
|
||||
state.Put("vmx_path", vmxPath)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the resulting data
|
||||
vmxContents, err := ioutil.ReadFile(vmxPath)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
vmxData := ParseVMX(string(vmxContents))
|
||||
|
||||
cases := []struct {
|
||||
Key string
|
||||
Value string
|
||||
}{
|
||||
// Stuff we set
|
||||
{"msg.autoanswer", "true"},
|
||||
{"uuid.action", "create"},
|
||||
|
||||
// Custom data
|
||||
{"foo", "bar"},
|
||||
|
||||
// Stuff that should NOT exist
|
||||
{"floppy0.present", ""},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
if tc.Value == "" {
|
||||
if _, ok := vmxData[tc.Key]; ok {
|
||||
t.Fatalf("should not have key: %s", tc.Key)
|
||||
}
|
||||
} else {
|
||||
if vmxData[tc.Key] != tc.Value {
|
||||
t.Fatalf("bad: %s %#v", tc.Key, vmxData[tc.Key])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepConfigureVMX_floppyPath(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepConfigureVMX)
|
||||
|
||||
vmxPath := testVMXFile(t)
|
||||
defer os.Remove(vmxPath)
|
||||
|
||||
state.Put("floppy_path", "foo")
|
||||
state.Put("vmx_path", vmxPath)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the resulting data
|
||||
vmxContents, err := ioutil.ReadFile(vmxPath)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
vmxData := ParseVMX(string(vmxContents))
|
||||
|
||||
cases := []struct {
|
||||
Key string
|
||||
Value string
|
||||
}{
|
||||
{"floppy0.present", "TRUE"},
|
||||
{"floppy0.filetype", "file"},
|
||||
{"floppy0.filename", "foo"},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
if tc.Value == "" {
|
||||
if _, ok := vmxData[tc.Key]; ok {
|
||||
t.Fatalf("should not have key: %s", tc.Key)
|
||||
}
|
||||
} else {
|
||||
if vmxData[tc.Key] != tc.Value {
|
||||
t.Fatalf("bad: %s %#v", tc.Key, vmxData[tc.Key])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestStepConfigureVMX_generatedAddresses(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepConfigureVMX)
|
||||
|
||||
vmxPath := testVMXFile(t)
|
||||
defer os.Remove(vmxPath)
|
||||
|
||||
additionalTestVmxData := []struct {
|
||||
Key string
|
||||
Value string
|
||||
}{
|
||||
{"foo", "bar"},
|
||||
{"ethernet0.generatedaddress", "foo"},
|
||||
{"ethernet1.generatedaddress", "foo"},
|
||||
{"ethernet1.generatedaddressoffset", "foo"},
|
||||
}
|
||||
|
||||
// Get any existing VMX data from the VMX file
|
||||
vmxData, err := ReadVMX(vmxPath)
|
||||
if err != nil {
|
||||
t.Fatalf("err %s", err)
|
||||
}
|
||||
|
||||
// Add the additional key/value pairs we need for this test to the existing VMX data
|
||||
for _, data := range additionalTestVmxData {
|
||||
vmxData[data.Key] = data.Value
|
||||
}
|
||||
|
||||
// Recreate the VMX file so it includes all the data needed for this test
|
||||
err = WriteVMX(vmxPath, vmxData)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
state.Put("vmx_path", vmxPath)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the resulting data
|
||||
vmxContents, err := ioutil.ReadFile(vmxPath)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
vmxData = ParseVMX(string(vmxContents))
|
||||
|
||||
cases := []struct {
|
||||
Key string
|
||||
Value string
|
||||
}{
|
||||
{"foo", "bar"},
|
||||
{"ethernet0.generatedaddress", ""},
|
||||
{"ethernet1.generatedaddress", ""},
|
||||
{"ethernet1.generatedaddressoffset", ""},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
if tc.Value == "" {
|
||||
if _, ok := vmxData[tc.Key]; ok {
|
||||
t.Fatalf("should not have key: %s", tc.Key)
|
||||
}
|
||||
} else {
|
||||
if vmxData[tc.Key] != tc.Value {
|
||||
t.Fatalf("bad: %s %#v", tc.Key, vmxData[tc.Key])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Should fail if the displayName key is not found in the VMX
|
||||
func TestStepConfigureVMX_displayNameMissing(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepConfigureVMX)
|
||||
|
||||
// testVMXFile adds displayName key/value pair to the VMX
|
||||
vmxPath := testVMXFile(t)
|
||||
defer os.Remove(vmxPath)
|
||||
|
||||
// Bad: Delete displayName from the VMX/Create an empty VMX file
|
||||
err := WriteVMX(vmxPath, map[string]string{})
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
state.Put("vmx_path", vmxPath)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionHalt {
|
||||
t.Fatalf("bad action: %#v. Should halt when displayName key is missing from VMX", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); !ok {
|
||||
t.Fatal("should store error in state when displayName key is missing from VMX")
|
||||
}
|
||||
}
|
||||
|
||||
// Should store the value of displayName in the statebag
|
||||
func TestStepConfigureVMX_displayNameStore(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepConfigureVMX)
|
||||
|
||||
// testVMXFile adds displayName key/value pair to the VMX
|
||||
vmxPath := testVMXFile(t)
|
||||
defer os.Remove(vmxPath)
|
||||
|
||||
state.Put("vmx_path", vmxPath)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// The value of displayName must be stored in the statebag
|
||||
if _, ok := state.GetOk("display_name"); !ok {
|
||||
t.Fatalf("displayName should be stored in the statebag as 'display_name'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepConfigureVMX_vmxPathBad(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepConfigureVMX)
|
||||
|
||||
state.Put("vmx_path", "some_bad_path")
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionHalt {
|
||||
t.Fatalf("bad action: %#v. Should halt when vmxPath is bad", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); !ok {
|
||||
t.Fatal("should store error in state when vmxPath is bad")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestStepConfigureVMX_DefaultDiskAndCDROMTypes(t *testing.T) {
|
||||
type testCase struct {
|
||||
inDiskAdapter string
|
||||
inCDromAdapter string
|
||||
expectedOut DiskAndCDConfigData
|
||||
reason string
|
||||
}
|
||||
testcases := []testCase{
|
||||
{
|
||||
inDiskAdapter: "",
|
||||
inCDromAdapter: "",
|
||||
expectedOut: DiskAndCDConfigData{
|
||||
SCSI_Present: "TRUE",
|
||||
SCSI_diskAdapterType: "",
|
||||
SATA_Present: "FALSE",
|
||||
NVME_Present: "FALSE",
|
||||
|
||||
DiskType: "scsi",
|
||||
CDROMType: "ide",
|
||||
CDROMType_PrimarySecondary: "0",
|
||||
},
|
||||
reason: "Test that default creases scsi disk with ide cd",
|
||||
},
|
||||
{
|
||||
inDiskAdapter: "ide",
|
||||
inCDromAdapter: "",
|
||||
expectedOut: DiskAndCDConfigData{
|
||||
SCSI_Present: "FALSE",
|
||||
SCSI_diskAdapterType: "lsilogic",
|
||||
SATA_Present: "FALSE",
|
||||
NVME_Present: "FALSE",
|
||||
|
||||
DiskType: "ide",
|
||||
CDROMType: "ide",
|
||||
CDROMType_PrimarySecondary: "1",
|
||||
},
|
||||
reason: "ide disk adapter should pass through and not get defaulted to scsi",
|
||||
},
|
||||
{
|
||||
inDiskAdapter: "sata",
|
||||
inCDromAdapter: "",
|
||||
expectedOut: DiskAndCDConfigData{
|
||||
SCSI_Present: "FALSE",
|
||||
SCSI_diskAdapterType: "lsilogic",
|
||||
SATA_Present: "TRUE",
|
||||
NVME_Present: "FALSE",
|
||||
|
||||
DiskType: "sata",
|
||||
CDROMType: "sata",
|
||||
CDROMType_PrimarySecondary: "1",
|
||||
},
|
||||
reason: "when disk is set to sata, cdromtype should also default to sata",
|
||||
},
|
||||
{
|
||||
inDiskAdapter: "nvme",
|
||||
inCDromAdapter: "",
|
||||
expectedOut: DiskAndCDConfigData{
|
||||
SCSI_Present: "FALSE",
|
||||
SCSI_diskAdapterType: "lsilogic",
|
||||
SATA_Present: "TRUE",
|
||||
NVME_Present: "TRUE",
|
||||
|
||||
DiskType: "nvme",
|
||||
CDROMType: "sata",
|
||||
CDROMType_PrimarySecondary: "0",
|
||||
},
|
||||
reason: "when disk is set to nvme, cdromtype should default to sata",
|
||||
},
|
||||
{
|
||||
inDiskAdapter: "scsi",
|
||||
inCDromAdapter: "",
|
||||
expectedOut: DiskAndCDConfigData{
|
||||
SCSI_Present: "TRUE",
|
||||
SCSI_diskAdapterType: "lsilogic",
|
||||
SATA_Present: "FALSE",
|
||||
NVME_Present: "FALSE",
|
||||
|
||||
DiskType: "scsi",
|
||||
CDROMType: "ide",
|
||||
CDROMType_PrimarySecondary: "0",
|
||||
},
|
||||
reason: "when disk is set to scsi, adapter should default back to lsilogic",
|
||||
},
|
||||
{
|
||||
inDiskAdapter: "scsi",
|
||||
inCDromAdapter: "scsi",
|
||||
expectedOut: DiskAndCDConfigData{
|
||||
SCSI_Present: "TRUE",
|
||||
SCSI_diskAdapterType: "lsilogic",
|
||||
SATA_Present: "FALSE",
|
||||
NVME_Present: "FALSE",
|
||||
|
||||
DiskType: "scsi",
|
||||
CDROMType: "scsi",
|
||||
CDROMType_PrimarySecondary: "0",
|
||||
},
|
||||
reason: "when cdrom adapter is set, it should override the default",
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
diskConfigData := DefaultDiskAndCDROMTypes(tc.inDiskAdapter, tc.inCDromAdapter)
|
||||
assert.Equal(t, diskConfigData, tc.expectedOut, tc.reason)
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStepConfigureVNC_implVNCAddressFinder(t *testing.T) {
|
||||
var _ VNCAddressFinder = new(StepConfigureVNC)
|
||||
}
|
||||
|
||||
func TestStepConfigureVNC_UpdateVMX(t *testing.T) {
|
||||
var s StepConfigureVNC
|
||||
data := make(map[string]string)
|
||||
s.UpdateVMX("0.0.0.0", "", 5900, data)
|
||||
if ip := data["remotedisplay.vnc.ip"]; ip != "0.0.0.0" {
|
||||
t.Errorf("bad VMX data for key remotedisplay.vnc.ip: %v", ip)
|
||||
}
|
||||
if enabled := data["remotedisplay.vnc.enabled"]; enabled != "TRUE" {
|
||||
t.Errorf("bad VMX data for key remotedisplay.vnc.enabled: %v", enabled)
|
||||
}
|
||||
if port := data["remotedisplay.vnc.port"]; port != fmt.Sprint(port) {
|
||||
t.Errorf("bad VMX data for key remotedisplay.vnc.port: %v", port)
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestStepCreateDisks_impl(t *testing.T) {
|
||||
var _ multistep.Step = new(StepCreateDisks)
|
||||
}
|
||||
|
||||
func strPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
func NewTestCreateDiskStep() *StepCreateDisks {
|
||||
return &StepCreateDisks{
|
||||
OutputDir: strPtr("output_dir"),
|
||||
CreateMainDisk: true,
|
||||
DiskName: "disk_name",
|
||||
MainDiskSize: uint(1024),
|
||||
AdditionalDiskSize: []uint{},
|
||||
DiskAdapterType: "fake_adapter",
|
||||
DiskTypeId: "1",
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateDisks_MainOnly(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := NewTestCreateDiskStep()
|
||||
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
if !driver.CreateDiskCalled {
|
||||
t.Fatalf("Should have called create disk.")
|
||||
}
|
||||
|
||||
diskFullPaths, ok := state.Get("disk_full_paths").([]string)
|
||||
if !ok {
|
||||
t.Fatalf("Should be able to load disk_full_paths from state")
|
||||
}
|
||||
|
||||
assert.Equal(t, diskFullPaths, []string{filepath.Join("output_dir", "disk_name.vmdk")})
|
||||
|
||||
// Cleanup
|
||||
step.Cleanup(state)
|
||||
}
|
||||
|
||||
func TestStepCreateDisks_MainAndExtra(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := NewTestCreateDiskStep()
|
||||
step.AdditionalDiskSize = []uint{1024, 2048, 4096}
|
||||
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
if !driver.CreateDiskCalled {
|
||||
t.Fatalf("Should have called create disk.")
|
||||
}
|
||||
|
||||
diskFullPaths, ok := state.Get("disk_full_paths").([]string)
|
||||
if !ok {
|
||||
t.Fatalf("Should be able to load disk_full_paths from state")
|
||||
}
|
||||
|
||||
assert.Equal(t, diskFullPaths,
|
||||
[]string{
|
||||
filepath.Join("output_dir", "disk_name.vmdk"),
|
||||
filepath.Join("output_dir", "disk_name-1.vmdk"),
|
||||
filepath.Join("output_dir", "disk_name-2.vmdk"),
|
||||
filepath.Join("output_dir", "disk_name-3.vmdk"),
|
||||
})
|
||||
// Cleanup
|
||||
step.Cleanup(state)
|
||||
}
|
||||
|
||||
func TestStepCreateDisks_ExtraOnly(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := NewTestCreateDiskStep()
|
||||
step.CreateMainDisk = false
|
||||
step.AdditionalDiskSize = []uint{1024, 2048, 4096}
|
||||
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
if !driver.CreateDiskCalled {
|
||||
t.Fatalf("Should have called create disk.")
|
||||
}
|
||||
|
||||
diskFullPaths, ok := state.Get("disk_full_paths").([]string)
|
||||
if !ok {
|
||||
t.Fatalf("Should be able to load disk_full_paths from state")
|
||||
}
|
||||
|
||||
assert.Equal(t, diskFullPaths,
|
||||
[]string{
|
||||
filepath.Join("output_dir", "disk_name-1.vmdk"),
|
||||
filepath.Join("output_dir", "disk_name-2.vmdk"),
|
||||
filepath.Join("output_dir", "disk_name-3.vmdk"),
|
||||
})
|
||||
|
||||
// Cleanup
|
||||
step.Cleanup(state)
|
||||
}
|
||||
|
||||
func TestStepCreateDisks_Nothing(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := NewTestCreateDiskStep()
|
||||
step.CreateMainDisk = false
|
||||
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
if driver.CreateDiskCalled {
|
||||
t.Fatalf("Should not have called create disk.")
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
step.Cleanup(state)
|
||||
}
|
||||
@@ -1,233 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestStepExport_impl(t *testing.T) {
|
||||
var _ multistep.Step = new(StepExport)
|
||||
}
|
||||
|
||||
func stringPointer(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
func remoteExportTestState(t *testing.T) multistep.StateBag {
|
||||
state := testState(t)
|
||||
driverConfig := &DriverConfig{
|
||||
RemoteHost: "123.45.67.8",
|
||||
RemotePassword: "password",
|
||||
RemoteUser: "user",
|
||||
RemoteType: "esx5",
|
||||
}
|
||||
state.Put("driverConfig", driverConfig)
|
||||
state.Put("display_name", "vm_name")
|
||||
return state
|
||||
}
|
||||
|
||||
func TestStepExport_ReturnIfSkip(t *testing.T) {
|
||||
state := testState(t)
|
||||
driverConfig := &DriverConfig{}
|
||||
state.Put("driverConfig", driverConfig)
|
||||
step := new(StepExport)
|
||||
|
||||
step.SkipExport = true
|
||||
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// We told step to skip so it should not have reached the driver's Export
|
||||
// func.
|
||||
d := state.Get("driver").(*DriverMock)
|
||||
if d.ExportCalled {
|
||||
t.Fatal("Should not have called the driver export func")
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
step.Cleanup(state)
|
||||
}
|
||||
|
||||
func TestStepExport_localArgs(t *testing.T) {
|
||||
// even though we aren't overriding the remote args and they are present,
|
||||
// test shouldn't use them since remoteType is not set to esx.
|
||||
state := testState(t)
|
||||
driverConfig := &DriverConfig{}
|
||||
state.Put("driverConfig", driverConfig)
|
||||
step := new(StepExport)
|
||||
|
||||
step.SkipExport = false
|
||||
step.OutputDir = stringPointer("test-output")
|
||||
step.VMName = "test-name"
|
||||
step.Format = "ova"
|
||||
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Check that step ran, and called Export with the expected args.
|
||||
d := state.Get("driver").(*DriverMock)
|
||||
if !d.ExportCalled {
|
||||
t.Fatal("Should have called the driver export func")
|
||||
}
|
||||
|
||||
assert.Equal(t, d.ExportArgs,
|
||||
[]string{
|
||||
filepath.Join("test-output", "test-name.vmx"),
|
||||
filepath.Join("test-output", "test-name.ova")})
|
||||
|
||||
// Cleanup
|
||||
step.Cleanup(state)
|
||||
}
|
||||
|
||||
func TestStepExport_localArgsExportOutputPath(t *testing.T) {
|
||||
// even though we aren't overriding the remote args and they are present,
|
||||
// test shouldn't use them since remoteType is not set to esx.
|
||||
state := testState(t)
|
||||
driverConfig := &DriverConfig{}
|
||||
state.Put("driverConfig", driverConfig)
|
||||
state.Put("export_output_path", "local_output")
|
||||
step := new(StepExport)
|
||||
|
||||
step.SkipExport = false
|
||||
step.OutputDir = stringPointer("test-output")
|
||||
step.VMName = "test-name"
|
||||
step.Format = "ova"
|
||||
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Check that step ran, and called Export with the expected args.
|
||||
d := state.Get("driver").(*DriverMock)
|
||||
if !d.ExportCalled {
|
||||
t.Fatal("Should have called the driver export func")
|
||||
}
|
||||
|
||||
assert.Equal(t, d.ExportArgs,
|
||||
[]string{
|
||||
filepath.Join("local_output", "test-name.vmx"),
|
||||
filepath.Join("local_output", "test-name.ova")})
|
||||
|
||||
// Cleanup
|
||||
step.Cleanup(state)
|
||||
}
|
||||
|
||||
func TestStepExport_localArgs_OvftoolOptions(t *testing.T) {
|
||||
// even though we aren't overriding the remote args and they are present,
|
||||
// test shouldn't use them since remoteType is not set to esx.
|
||||
state := testState(t)
|
||||
driverConfig := &DriverConfig{}
|
||||
state.Put("driverConfig", driverConfig)
|
||||
step := new(StepExport)
|
||||
|
||||
step.SkipExport = false
|
||||
step.OutputDir = stringPointer("test-output")
|
||||
step.VMName = "test-name"
|
||||
step.Format = "ova"
|
||||
step.OVFToolOptions = []string{"--option=value", "--second-option=\"quoted value\""}
|
||||
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Check that step ran, and called Export with the expected args.
|
||||
d := state.Get("driver").(*DriverMock)
|
||||
if !d.ExportCalled {
|
||||
t.Fatal("Should have called the driver export func")
|
||||
}
|
||||
|
||||
assert.Equal(t, d.ExportArgs, []string{"--option=value",
|
||||
"--second-option=\"quoted value\"",
|
||||
filepath.Join("test-output", "test-name.vmx"),
|
||||
filepath.Join("test-output", "test-name.ova")})
|
||||
|
||||
// Cleanup
|
||||
step.Cleanup(state)
|
||||
}
|
||||
|
||||
func TestStepExport_RemoteArgs(t *testing.T) {
|
||||
// Even though we aren't overriding the remote args and they are present,
|
||||
// test shouldn't use them since remoteType is not set to esx.
|
||||
state := remoteExportTestState(t)
|
||||
step := new(StepExport)
|
||||
|
||||
step.SkipExport = false
|
||||
step.OutputDir = stringPointer("test-output")
|
||||
step.VMName = "test-name"
|
||||
step.Format = "ova"
|
||||
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Check that step ran, and called Export with the expected args.
|
||||
d := state.Get("driver").(*DriverMock)
|
||||
if !d.ExportCalled {
|
||||
t.Fatal("Should have called the driver export func")
|
||||
}
|
||||
|
||||
assert.Equal(t, d.ExportArgs, []string{"--noSSLVerify=true",
|
||||
"--skipManifestCheck",
|
||||
"-tt=ova",
|
||||
"vi://user:password@123.45.67.8/vm_name",
|
||||
filepath.Join("test-output", "test-name.ova")})
|
||||
|
||||
// Cleanup
|
||||
step.Cleanup(state)
|
||||
}
|
||||
|
||||
func TestStepExport_RemoteArgsWithExportOutputPath(t *testing.T) {
|
||||
// Even though we aren't overriding the remote args and they are present,
|
||||
// test shouldn't use them since remoteType is not set to esx.
|
||||
state := remoteExportTestState(t)
|
||||
state.Put("export_output_path", "local_output")
|
||||
step := new(StepExport)
|
||||
|
||||
step.SkipExport = false
|
||||
step.OutputDir = stringPointer("test-output")
|
||||
step.VMName = "test-name"
|
||||
step.Format = "ova"
|
||||
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Check that step ran, and called Export with the expected args.
|
||||
d := state.Get("driver").(*DriverMock)
|
||||
if !d.ExportCalled {
|
||||
t.Fatal("Should have called the driver export func")
|
||||
}
|
||||
|
||||
assert.Equal(t, d.ExportArgs, []string{"--noSSLVerify=true",
|
||||
"--skipManifestCheck",
|
||||
"-tt=ova",
|
||||
"vi://user:password@123.45.67.8/vm_name",
|
||||
filepath.Join("local_output", "test-name.ova")})
|
||||
|
||||
// Cleanup
|
||||
step.Cleanup(state)
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepHTTPIPDiscover_Run(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepHTTPIPDiscover)
|
||||
driverMock := state.Get("driver").(Driver)
|
||||
hostIp, _ := driverMock.HostIP(state)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
httpIp := state.Get("http_ip").(string)
|
||||
if httpIp != hostIp {
|
||||
t.Fatalf("bad: Http ip is %s but was supposed to be %s", httpIp, hostIp)
|
||||
}
|
||||
|
||||
// Halt step when fails to get ip
|
||||
state.Put("driver", &DriverMock{HostIPErr: errors.New("error")})
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionHalt {
|
||||
t.Fatalf("bad action: step was supposed to fail %#v", action)
|
||||
}
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func testOutputDir(t *testing.T) string {
|
||||
td, err := ioutil.TempDir("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
os.RemoveAll(td)
|
||||
|
||||
return td
|
||||
}
|
||||
|
||||
func TestStepOutputDir_impl(t *testing.T) {
|
||||
var _ multistep.Step = new(StepOutputDir)
|
||||
}
|
||||
|
||||
func TestStepOutputDir(t *testing.T) {
|
||||
state := testState(t)
|
||||
driver := new(DriverMock)
|
||||
state.Put("driver", driver)
|
||||
|
||||
td := testOutputDir(t)
|
||||
outconfig := &OutputConfig{
|
||||
OutputDir: td,
|
||||
}
|
||||
|
||||
step := &StepOutputDir{
|
||||
OutputConfig: outconfig,
|
||||
VMName: "testVM",
|
||||
}
|
||||
// Delete the test output directory when done
|
||||
defer os.RemoveAll(td)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
if _, err := os.Stat(td); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Test the cleanup
|
||||
step.Cleanup(state)
|
||||
if _, err := os.Stat(td); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepOutputDir_existsNoForce(t *testing.T) {
|
||||
state := testState(t)
|
||||
|
||||
td := testOutputDir(t)
|
||||
outconfig := &OutputConfig{
|
||||
OutputDir: td,
|
||||
}
|
||||
|
||||
step := &StepOutputDir{
|
||||
OutputConfig: outconfig,
|
||||
VMName: "testVM",
|
||||
}
|
||||
// Delete the test output directory when done
|
||||
defer os.RemoveAll(td)
|
||||
|
||||
// Make sure the dir exists
|
||||
if err := os.MkdirAll(td, 0755); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.RemoveAll(td)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionHalt {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); !ok {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Test the cleanup
|
||||
step.Cleanup(state)
|
||||
if _, err := os.Stat(td); err != nil {
|
||||
t.Fatal("should not delete dir")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepOutputDir_existsForce(t *testing.T) {
|
||||
state := testState(t)
|
||||
|
||||
td := testOutputDir(t)
|
||||
outconfig := &OutputConfig{
|
||||
OutputDir: td,
|
||||
}
|
||||
|
||||
step := &StepOutputDir{
|
||||
OutputConfig: outconfig,
|
||||
VMName: "testVM",
|
||||
}
|
||||
step.Force = true
|
||||
|
||||
// Delete the test output directory when done
|
||||
defer os.RemoveAll(td)
|
||||
|
||||
// Make sure the dir exists
|
||||
if err := os.MkdirAll(td, 0755); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.RemoveAll(td)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
if _, err := os.Stat(td); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepOutputDir_cancel(t *testing.T) {
|
||||
state := testState(t)
|
||||
td := testOutputDir(t)
|
||||
outconfig := &OutputConfig{
|
||||
OutputDir: td,
|
||||
}
|
||||
|
||||
step := &StepOutputDir{
|
||||
OutputConfig: outconfig,
|
||||
VMName: "testVM",
|
||||
}
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
if _, err := os.Stat(td); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Test cancel/halt
|
||||
state.Put(multistep.StateCancelled, true)
|
||||
step.Cleanup(state)
|
||||
if _, err := os.Stat(td); err == nil {
|
||||
t.Fatal("directory should not exist")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepOutputDir_halt(t *testing.T) {
|
||||
state := testState(t)
|
||||
td := testOutputDir(t)
|
||||
outconfig := &OutputConfig{
|
||||
OutputDir: td,
|
||||
}
|
||||
|
||||
step := &StepOutputDir{
|
||||
OutputConfig: outconfig,
|
||||
VMName: "testVM",
|
||||
}
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
if _, err := os.Stat(td); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Test cancel/halt
|
||||
state.Put(multistep.StateHalted, true)
|
||||
step.Cleanup(state)
|
||||
if _, err := os.Stat(td); err == nil {
|
||||
t.Fatal("directory should not exist")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepOutputDir_Remote(t *testing.T) {
|
||||
// Tests remote driver
|
||||
state := testState(t)
|
||||
driver := new(RemoteDriverMock)
|
||||
state.Put("driver", driver)
|
||||
|
||||
td := testOutputDir(t)
|
||||
outconfig := &OutputConfig{
|
||||
OutputDir: td,
|
||||
RemoteOutputDir: "remote_path",
|
||||
}
|
||||
|
||||
step := &StepOutputDir{
|
||||
OutputConfig: outconfig,
|
||||
VMName: "testVM",
|
||||
RemoteType: "esx5",
|
||||
}
|
||||
// Delete the test output directory when done
|
||||
defer os.RemoveAll(td)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
|
||||
// We don't pre-create the output path for export but we do set it in state.
|
||||
exportOutputPath := state.Get("export_output_path").(string)
|
||||
if exportOutputPath != td {
|
||||
t.Fatalf("err: should have set export_output_path!")
|
||||
}
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepPrepareTools_impl(t *testing.T) {
|
||||
var _ multistep.Step = new(StepPrepareTools)
|
||||
}
|
||||
|
||||
func TestStepPrepareTools(t *testing.T) {
|
||||
tf, err := ioutil.TempFile("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
tf.Close()
|
||||
defer os.Remove(tf.Name())
|
||||
|
||||
state := testState(t)
|
||||
step := &StepPrepareTools{
|
||||
RemoteType: "",
|
||||
ToolsUploadFlavor: "foo",
|
||||
}
|
||||
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
|
||||
// Mock results
|
||||
driver.ToolsIsoPathResult = tf.Name()
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the driver
|
||||
if !driver.ToolsIsoPathCalled {
|
||||
t.Fatal("tools iso path should be called")
|
||||
}
|
||||
if driver.ToolsIsoPathFlavor != "foo" {
|
||||
t.Fatalf("bad: %#v", driver.ToolsIsoPathFlavor)
|
||||
}
|
||||
|
||||
// Test the resulting state
|
||||
path, ok := state.GetOk("tools_upload_source")
|
||||
if !ok {
|
||||
t.Fatal("should have tools_upload_source")
|
||||
}
|
||||
if path != tf.Name() {
|
||||
t.Fatalf("bad: %#v", path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepPrepareTools_esx5(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := &StepPrepareTools{
|
||||
RemoteType: "esx5",
|
||||
ToolsUploadFlavor: "foo",
|
||||
}
|
||||
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the driver
|
||||
if driver.ToolsIsoPathCalled {
|
||||
t.Fatal("tools iso path should NOT be called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepPrepareTools_nonExist(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := &StepPrepareTools{
|
||||
RemoteType: "",
|
||||
ToolsUploadFlavor: "foo",
|
||||
}
|
||||
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
|
||||
// Mock results
|
||||
driver.ToolsIsoPathResult = "foo"
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionHalt {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); !ok {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Test the driver
|
||||
if !driver.ToolsIsoPathCalled {
|
||||
t.Fatal("tools iso path should be called")
|
||||
}
|
||||
if driver.ToolsIsoPathFlavor != "foo" {
|
||||
t.Fatalf("bad: %#v", driver.ToolsIsoPathFlavor)
|
||||
}
|
||||
|
||||
// Test the resulting state
|
||||
if _, ok := state.GetOk("tools_upload_source"); ok {
|
||||
t.Fatal("should NOT have tools_upload_source")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepPrepareTools_SourcePath(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := &StepPrepareTools{
|
||||
RemoteType: "",
|
||||
ToolsSourcePath: "/path/to/tool.iso",
|
||||
}
|
||||
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
|
||||
// Mock results
|
||||
driver.ToolsIsoPathResult = "foo"
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionHalt {
|
||||
t.Fatalf("Should have failed when stat failed %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); !ok {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Test the driver
|
||||
if driver.ToolsIsoPathCalled {
|
||||
t.Fatal("tools iso path should not be called when ToolsSourcePath is set")
|
||||
}
|
||||
|
||||
// Test the resulting state
|
||||
if _, ok := state.GetOk("tools_upload_source"); ok {
|
||||
t.Fatal("should NOT have tools_upload_source")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepPrepareTools_SourcePath_exists(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := &StepPrepareTools{
|
||||
RemoteType: "",
|
||||
ToolsSourcePath: "./step_prepare_tools.go",
|
||||
}
|
||||
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
|
||||
// Mock results
|
||||
driver.ToolsIsoPathResult = "foo"
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("Step should succeed when stat succeeds: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the driver
|
||||
if driver.ToolsIsoPathCalled {
|
||||
t.Fatal("tools iso path should not be called when ToolsSourcePath is set")
|
||||
}
|
||||
|
||||
// Test the resulting state
|
||||
if _, ok := state.GetOk("tools_upload_source"); !ok {
|
||||
t.Fatal("should have tools_upload_source")
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepRegister_impl(t *testing.T) {
|
||||
var _ multistep.Step = new(StepRegister)
|
||||
}
|
||||
|
||||
func TestStepRegister_regularDriver(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepRegister)
|
||||
|
||||
state.Put("vmx_path", "foo")
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
step.Cleanup(state)
|
||||
}
|
||||
|
||||
func TestStepRegister_remoteDriver(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := &StepRegister{
|
||||
KeepRegistered: false,
|
||||
SkipExport: true,
|
||||
}
|
||||
|
||||
driver := new(RemoteDriverMock)
|
||||
|
||||
state.Put("driver", driver)
|
||||
state.Put("vmx_path", "foo")
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// verify
|
||||
if !driver.RegisterCalled {
|
||||
t.Fatal("register should be called")
|
||||
}
|
||||
if driver.RegisterPath != "foo" {
|
||||
t.Fatal("should call with correct path")
|
||||
}
|
||||
if driver.UnregisterCalled {
|
||||
t.Fatal("unregister should not be called")
|
||||
}
|
||||
|
||||
// cleanup
|
||||
step.Cleanup(state)
|
||||
if !driver.UnregisterCalled {
|
||||
t.Fatal("unregister should be called")
|
||||
}
|
||||
if driver.UnregisterPath != "foo" {
|
||||
t.Fatal("should unregister proper path")
|
||||
}
|
||||
}
|
||||
func TestStepRegister_WithoutUnregister_remoteDriver(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := &StepRegister{KeepRegistered: true}
|
||||
|
||||
driver := new(RemoteDriverMock)
|
||||
|
||||
state.Put("driver", driver)
|
||||
state.Put("vmx_path", "foo")
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// cleanup
|
||||
step.Cleanup(state)
|
||||
if driver.UnregisterCalled {
|
||||
t.Fatal("unregister should not be called")
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepRemoteUpload_Cleanup(t *testing.T) {
|
||||
state := new(multistep.BasicStateBag)
|
||||
driver := new(RemoteDriverMock)
|
||||
state.Put("driver", driver)
|
||||
state.Put("path_key", "packer_cache")
|
||||
|
||||
// Should clean up cache
|
||||
s := &StepRemoteUpload{
|
||||
Key: "path_key",
|
||||
DoCleanup: true,
|
||||
}
|
||||
s.Cleanup(state)
|
||||
|
||||
if !driver.CacheRemoved {
|
||||
t.Fatalf("bad: remote cache was not removed")
|
||||
}
|
||||
if driver.RemovedCachePath != "packer_cache" {
|
||||
t.Fatalf("bad: removed cache path was expected to be packer_cache but was %s", driver.RemovedCachePath)
|
||||
}
|
||||
|
||||
// Should NOT clean up cache
|
||||
s = &StepRemoteUpload{
|
||||
Key: "path_key",
|
||||
}
|
||||
driver = new(RemoteDriverMock)
|
||||
state.Put("driver", driver)
|
||||
s.Cleanup(state)
|
||||
|
||||
if driver.CacheRemoved {
|
||||
t.Fatalf("bad: remote cache was removed but was expected to not")
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepRun_impl(t *testing.T) {
|
||||
var _ multistep.Step = new(StepRun)
|
||||
}
|
||||
|
||||
func TestStepRun(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepRun)
|
||||
|
||||
state.Put("vmx_path", "foo")
|
||||
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the driver
|
||||
if !driver.StartCalled {
|
||||
t.Fatal("start should be called")
|
||||
}
|
||||
if driver.StartPath != "foo" {
|
||||
t.Fatalf("bad: %#v", driver.StartPath)
|
||||
}
|
||||
if driver.StartHeadless {
|
||||
t.Fatal("bad")
|
||||
}
|
||||
|
||||
// Test cleanup
|
||||
step.Cleanup(state)
|
||||
if driver.StopCalled {
|
||||
t.Fatal("stop should not be called if not running")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepRun_cleanupRunning(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepRun)
|
||||
|
||||
state.Put("vmx_path", "foo")
|
||||
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the driver
|
||||
if !driver.StartCalled {
|
||||
t.Fatal("start should be called")
|
||||
}
|
||||
if driver.StartPath != "foo" {
|
||||
t.Fatalf("bad: %#v", driver.StartPath)
|
||||
}
|
||||
if driver.StartHeadless {
|
||||
t.Fatal("bad")
|
||||
}
|
||||
|
||||
// Mark that it is running
|
||||
driver.IsRunningResult = true
|
||||
|
||||
// Test cleanup
|
||||
step.Cleanup(state)
|
||||
if !driver.StopCalled {
|
||||
t.Fatal("stop should be called")
|
||||
}
|
||||
}
|
||||
@@ -1,205 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
func testLocalOutputDir(t *testing.T) *LocalOutputDir {
|
||||
td, err := ioutil.TempDir("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
os.RemoveAll(td)
|
||||
|
||||
result := new(LocalOutputDir)
|
||||
result.SetOutputDir(td)
|
||||
return result
|
||||
}
|
||||
|
||||
func testStepShutdownState(t *testing.T) multistep.StateBag {
|
||||
dir := testLocalOutputDir(t)
|
||||
if err := dir.MkdirAll(); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
state := testState(t)
|
||||
state.Put("communicator", new(packersdk.MockCommunicator))
|
||||
state.Put("dir", dir)
|
||||
state.Put("vmx_path", "foo")
|
||||
return state
|
||||
}
|
||||
|
||||
func TestStepShutdown_impl(t *testing.T) {
|
||||
var _ multistep.Step = new(StepShutdown)
|
||||
}
|
||||
|
||||
func TestStepShutdown_command(t *testing.T) {
|
||||
state := testStepShutdownState(t)
|
||||
step := new(StepShutdown)
|
||||
step.Command = "foo"
|
||||
step.Timeout = 10 * time.Second
|
||||
step.Testing = true
|
||||
|
||||
comm := state.Get("communicator").(*packersdk.MockCommunicator)
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
driver.IsRunningResult = true
|
||||
|
||||
// Set not running after some time
|
||||
go func() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
driver.Lock()
|
||||
defer driver.Unlock()
|
||||
driver.IsRunningResult = false
|
||||
}()
|
||||
|
||||
resultCh := make(chan multistep.StepAction, 1)
|
||||
go func() {
|
||||
resultCh <- step.Run(context.Background(), state)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-resultCh:
|
||||
t.Fatal("should not have returned so quickly")
|
||||
case <-time.After(50 * time.Millisecond):
|
||||
}
|
||||
|
||||
var action multistep.StepAction
|
||||
select {
|
||||
case action = <-resultCh:
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatal("should've returned by now")
|
||||
}
|
||||
|
||||
// Test the run
|
||||
if action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the driver
|
||||
if driver.StopCalled {
|
||||
t.Fatal("stop should not be called")
|
||||
}
|
||||
|
||||
if !comm.StartCalled {
|
||||
t.Fatal("start should be called")
|
||||
}
|
||||
if comm.StartCmd.Command != "foo" {
|
||||
t.Fatalf("bad: %#v", comm.StartCmd.Command)
|
||||
}
|
||||
|
||||
// Clean up the created test output directory
|
||||
dir := state.Get("dir").(*LocalOutputDir)
|
||||
if err := dir.RemoveAll(); err != nil {
|
||||
t.Fatalf("Error cleaning up directory: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepShutdown_noCommand(t *testing.T) {
|
||||
state := testStepShutdownState(t)
|
||||
step := new(StepShutdown)
|
||||
|
||||
comm := state.Get("communicator").(*packersdk.MockCommunicator)
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the driver
|
||||
if !driver.StopCalled {
|
||||
t.Fatal("stop should be called")
|
||||
}
|
||||
if driver.StopPath != "foo" {
|
||||
t.Fatal("should call with right path")
|
||||
}
|
||||
|
||||
if comm.StartCalled {
|
||||
t.Fatal("start should not be called")
|
||||
}
|
||||
|
||||
// Clean up the created test output directory
|
||||
dir := state.Get("dir").(*LocalOutputDir)
|
||||
if err := dir.RemoveAll(); err != nil {
|
||||
t.Fatalf("Error cleaning up directory: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepShutdown_locks(t *testing.T) {
|
||||
if os.Getenv("PACKER_ACC") == "" {
|
||||
t.Skip("This test is only run with PACKER_ACC=1 due to the requirement of access to the VMware binaries.")
|
||||
}
|
||||
|
||||
state := testStepShutdownState(t)
|
||||
step := new(StepShutdown)
|
||||
step.Testing = true
|
||||
|
||||
dir := state.Get("dir").(*LocalOutputDir)
|
||||
comm := state.Get("communicator").(*packersdk.MockCommunicator)
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
|
||||
// Create some lock files
|
||||
lockPath := filepath.Join(dir.dir, "nope.lck")
|
||||
err := ioutil.WriteFile(lockPath, []byte("foo"), 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Remove the lock file after a certain time
|
||||
go func() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
os.Remove(lockPath)
|
||||
}()
|
||||
|
||||
resultCh := make(chan multistep.StepAction, 1)
|
||||
go func() {
|
||||
resultCh <- step.Run(context.Background(), state)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-resultCh:
|
||||
t.Fatal("should not have returned so quickly")
|
||||
case <-time.After(50 * time.Millisecond):
|
||||
}
|
||||
|
||||
var action multistep.StepAction
|
||||
select {
|
||||
case action = <-resultCh:
|
||||
case <-time.After(300 * time.Millisecond):
|
||||
t.Fatal("should've returned by now")
|
||||
}
|
||||
|
||||
// Test the run
|
||||
if action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the driver
|
||||
if !driver.StopCalled {
|
||||
t.Fatal("stop should be called")
|
||||
}
|
||||
if driver.StopPath != "foo" {
|
||||
t.Fatal("should call with right path")
|
||||
}
|
||||
|
||||
if comm.StartCalled {
|
||||
t.Fatal("start should not be called")
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepSuppressMessages_impl(t *testing.T) {
|
||||
var _ multistep.Step = new(StepSuppressMessages)
|
||||
}
|
||||
|
||||
func TestStepSuppressMessages(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepSuppressMessages)
|
||||
|
||||
state.Put("vmx_path", "foo")
|
||||
|
||||
driver := state.Get("driver").(*DriverMock)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test the driver
|
||||
if !driver.SuppressMessagesCalled {
|
||||
t.Fatal("should've called")
|
||||
}
|
||||
if driver.SuppressMessagesPath != "foo" {
|
||||
t.Fatal("should call with right path")
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
func testState(t *testing.T) multistep.StateBag {
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("driver", new(DriverMock))
|
||||
state.Put("ui", &packersdk.BasicUi{
|
||||
Reader: new(bytes.Buffer),
|
||||
Writer: new(bytes.Buffer),
|
||||
})
|
||||
state.Put("temporaryDevices", []string{})
|
||||
return state
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
# this entry is normal
|
||||
{
|
||||
ip_address=127.0.0.17
|
||||
hw_address=1,d:ea:d0:66:77:88
|
||||
identifier=1,d:ea:d0:0:11:22
|
||||
lease=0x5fd78ae2
|
||||
name=vagrant-2019
|
||||
}
|
||||
|
||||
# this entry has tabs
|
||||
{
|
||||
ip_address=127.0.0.17
|
||||
hw_address=1,d:ea:d0:66:77:88
|
||||
identifier=1,d:ea:d0:33:44:55
|
||||
lease=0x5fd7b4e5
|
||||
name=vagrant-2019
|
||||
}
|
||||
|
||||
# These next two entries have the same address, but different uids
|
||||
{
|
||||
ip_address=127.0.0.19
|
||||
hw_address=1,d:ea:d0:66:77:88
|
||||
identifier=1,d:ea:d0:66:77:88
|
||||
lease=0x5fd72edc
|
||||
name=vagrant-2019
|
||||
}
|
||||
{
|
||||
ip_address=127.0.0.19
|
||||
hw_address=1,d:ea:d0:99:aa:bb
|
||||
identifier=1,d:ea:d0:99:aa:bb
|
||||
lease=0x5fd72edc
|
||||
name=vagrant-2019
|
||||
}
|
||||
|
||||
# this entry does not have all fields
|
||||
{
|
||||
ip_address=127.0.0.20
|
||||
hw_address=1,d:ea:d0:99:aa:bc
|
||||
identifier=1,d:ea:d0:99:aa:bc
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
allow unknown-clients; # global.grants
|
||||
default-lease-time 1800; # global.parameters
|
||||
max-lease-time 7200; # global.parameters
|
||||
|
||||
subnet 172.33.33.0 netmask 255.255.255.0 { # subnet4
|
||||
range 172.33.33.128 172.33.33.254; # subnet4.address
|
||||
option broadcast-address 172.33.33.255; # subnet4.options
|
||||
# allow unknown-clients; # subnet4.grants
|
||||
default-lease-time 2400; # subnet4.parameters
|
||||
max-lease-time 9600; # subnet4.parameters
|
||||
option routers 172.33.33.2; # subnet4.options
|
||||
}
|
||||
host vmnet8 { # host
|
||||
hardware ethernet 00:50:56:C0:00:08; # host.address
|
||||
fixed-address 172.33.33.1; # host.address
|
||||
option domain-name "packer.test"; # host.options
|
||||
# allow unknown-clients; # subnet4.grants
|
||||
# default-lease-time 1800; # subnet4.parameters
|
||||
# max-lease-time 7200; # subnet4.parameters
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
# This entry is normal
|
||||
lease 127.0.0.17 {
|
||||
starts 3 2020/05/13 12:00:37;
|
||||
ends 3 2020/05/13 12:30:37;
|
||||
hardware ethernet 0d:ea:d0:66:77:88;
|
||||
uid 01:0d:ea:d0:00:11:22;
|
||||
}
|
||||
|
||||
# This entry has tabs
|
||||
lease 127.0.0.17 {
|
||||
starts 6 2020/06/12 22:28:54;
|
||||
ends 6 2020/06/12 22:58:54;
|
||||
hardware ethernet 0d:ea:d0:66:77:88;
|
||||
uid 01:0d:ea:d0:33:44:55;
|
||||
}
|
||||
|
||||
# These next two entries have the same address, but different uids
|
||||
lease 127.0.0.19 {
|
||||
starts 4 2020/05/28 11:35:06;
|
||||
ends 4 2020/05/28 12:05:06;
|
||||
hardware ethernet 0d:ea:d0:66:77:88;
|
||||
uid 01:0d:ea:d0:66:77:88;
|
||||
client-hostname "VAGRANT-ADA-LUZ";
|
||||
}
|
||||
|
||||
lease 127.0.0.19 {
|
||||
starts 5 2020/08/20 20:32:03;
|
||||
ends 5 2020/08/20 21:02:03;
|
||||
hardware ethernet 0d:ea:d0:99:aa:bb;
|
||||
uid 01:0d:ea:d0:99:aa:bb;
|
||||
client-hostname "WINDOWS-SQABBAS";
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
network8.device = "vmnet8"
|
||||
network0.name = "Bridged"
|
||||
network2.device = "vmnet57005"
|
||||
network3.name = "butneeds"
|
||||
network0.device = "vmnet0"
|
||||
network1.name = "HostOnly"
|
||||
network8.name = "NAT"
|
||||
network1.device = "vmnet1"
|
||||
network3.notuseful = "blah"
|
||||
network3.device = "nameanddevice"
|
||||
network2.name = "bleep bloop"
|
||||
@@ -1,19 +0,0 @@
|
||||
VERSION=1,0
|
||||
answer VNET_1_DHCP yes
|
||||
answer VNET_1_DHCP_CFG_HASH 01F4CE0D79A1599698B6E5814CCB68058BB0ED5E
|
||||
answer VNET_1_HOSTONLY_NETMASK 255.255.255.0
|
||||
answer VNET_1_HOSTONLY_SUBNET 192.168.70.0
|
||||
answer VNET_1_NAT no
|
||||
answer VNET_1_VIRTUAL_ADAPTER yes
|
||||
answer VNET_8_DHCP yes
|
||||
answer VNET_8_DHCP_CFG_HASH C30F14F65A0FE4B5DCC6C67497D7A8A33E5E538C
|
||||
answer VNET_8_HOSTONLY_NETMASK 255.255.255.0
|
||||
answer VNET_8_HOSTONLY_SUBNET 172.16.41.0
|
||||
answer VNET_8_NAT yes
|
||||
answer VNET_8_VIRTUAL_ADAPTER yes
|
||||
add_nat_portfwd 8 tcp 2200 172.16.41.129 3389
|
||||
add_nat_portfwd 8 tcp 2201 172.16.41.129 3389
|
||||
add_nat_portfwd 8 tcp 2222 172.16.41.129 22
|
||||
add_nat_portfwd 8 tcp 3389 172.16.41.131 3389
|
||||
add_nat_portfwd 8 tcp 55985 172.16.41.129 5985
|
||||
add_nat_portfwd 8 tcp 55986 172.16.41.129 5986
|
||||
@@ -1,65 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
)
|
||||
|
||||
func TestToolsConfigPrepare_Empty(t *testing.T) {
|
||||
c := &ToolsConfig{}
|
||||
|
||||
errs := c.Prepare(interpolate.NewContext())
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
|
||||
if c.ToolsUploadPath != "{{ .Flavor }}.iso" {
|
||||
t.Fatal("should have defaulted tools upload path")
|
||||
}
|
||||
}
|
||||
|
||||
func TestToolsConfigPrepare_SetUploadPath(t *testing.T) {
|
||||
c := &ToolsConfig{
|
||||
ToolsUploadPath: "path/to/tools.iso",
|
||||
}
|
||||
|
||||
errs := c.Prepare(interpolate.NewContext())
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("err: %#v", errs)
|
||||
}
|
||||
|
||||
if c.ToolsUploadPath != "path/to/tools.iso" {
|
||||
t.Fatal("should have used given tools upload path")
|
||||
}
|
||||
}
|
||||
|
||||
func TestToolsConfigPrepare_ErrorIfOnlySource(t *testing.T) {
|
||||
c := &ToolsConfig{
|
||||
ToolsSourcePath: "path/to/tools.iso",
|
||||
}
|
||||
|
||||
errs := c.Prepare(interpolate.NewContext())
|
||||
if len(errs) != 1 {
|
||||
t.Fatalf("Should have received an error because the flavor and " +
|
||||
"upload path aren't set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestToolsConfigPrepare_SourceSuccess(t *testing.T) {
|
||||
for _, c := range []*ToolsConfig{
|
||||
&ToolsConfig{
|
||||
ToolsSourcePath: "path/to/tools.iso",
|
||||
ToolsUploadPath: "partypath.iso",
|
||||
},
|
||||
&ToolsConfig{
|
||||
ToolsSourcePath: "path/to/tools.iso",
|
||||
ToolsUploadFlavor: "linux",
|
||||
},
|
||||
} {
|
||||
errs := c.Prepare(interpolate.NewContext())
|
||||
if len(errs) != 0 {
|
||||
t.Fatalf("Should not have received an error")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
)
|
||||
|
||||
func TestVMXConfigPrepare(t *testing.T) {
|
||||
c := new(VMXConfig)
|
||||
c.VMXData = map[string]string{
|
||||
"one": "foo",
|
||||
"two": "bar",
|
||||
}
|
||||
|
||||
errs := c.Prepare(interpolate.NewContext())
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("bad: %#v", errs)
|
||||
}
|
||||
|
||||
if len(c.VMXData) != 2 {
|
||||
t.Fatal("should have two items in VMXData")
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package common
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestParseVMX(t *testing.T) {
|
||||
contents := `
|
||||
.encoding = "UTF-8"
|
||||
config.version = "8"
|
||||
scsi0:0.virtualSSD = 1
|
||||
`
|
||||
|
||||
results := ParseVMX(contents)
|
||||
if len(results) != 3 {
|
||||
t.Fatalf("not correct number of results: %d", len(results))
|
||||
}
|
||||
|
||||
if results[".encoding"] != "UTF-8" {
|
||||
t.Errorf("invalid .encoding: %s", results[".encoding"])
|
||||
}
|
||||
|
||||
if results["config.version"] != "8" {
|
||||
t.Errorf("invalid config.version: %s", results["config.version"])
|
||||
}
|
||||
|
||||
if results["scsi0:0.virtualssd"] != "1" {
|
||||
t.Errorf("invalid scsi0:0.virtualssd: %s", results["scsi0:0.virtualssd"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeVMX(t *testing.T) {
|
||||
contents := map[string]string{
|
||||
".encoding": "UTF-8",
|
||||
"config.version": "8",
|
||||
"scsi0:0.virtualssd": "1",
|
||||
}
|
||||
|
||||
expected := `.encoding = "UTF-8"
|
||||
config.version = "8"
|
||||
scsi0:0.virtualSSD = 1
|
||||
`
|
||||
|
||||
result := EncodeVMX(contents)
|
||||
if result != expected {
|
||||
t.Errorf("invalid results: %s", result)
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
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"
|
||||
)
|
||||
|
||||
func TestBuilderAcc_basic(t *testing.T) {
|
||||
templatePath := filepath.Join("testdata", "minimal.json")
|
||||
bytes, err := ioutil.ReadFile(templatePath)
|
||||
if err != nil {
|
||||
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
|
||||
},
|
||||
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,651 +0,0 @@
|
||||
package iso
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/common"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
func testConfig() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"iso_checksum": "md5:0B0F137F17AC10944716020B018F8126",
|
||||
"iso_url": "http://www.packer.io",
|
||||
"shutdown_command": "foo",
|
||||
"ssh_username": "foo",
|
||||
|
||||
common.BuildNameConfigKey: "foo",
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilder_ImplementsBuilder(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = &Builder{}
|
||||
if _, ok := raw.(packersdk.Builder); !ok {
|
||||
t.Error("Builder must implement builder.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_Defaults(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
_, warns, err := b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
if b.config.DiskName != "disk" {
|
||||
t.Errorf("bad disk name: %s", b.config.DiskName)
|
||||
}
|
||||
|
||||
if b.config.OutputDir != "output-foo" {
|
||||
t.Errorf("bad output dir: %s", b.config.OutputDir)
|
||||
}
|
||||
|
||||
if b.config.Version != "9" {
|
||||
t.Errorf("bad Version: %s", b.config.Version)
|
||||
}
|
||||
|
||||
if b.config.VMName != "packer-foo" {
|
||||
t.Errorf("bad vm name: %s", b.config.VMName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_DiskSize(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
delete(config, "disk_size")
|
||||
_, warns, err := b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("bad err: %s", err)
|
||||
}
|
||||
|
||||
if b.config.DiskSize != 40000 {
|
||||
t.Fatalf("bad size: %d", b.config.DiskSize)
|
||||
}
|
||||
|
||||
config["disk_size"] = 60000
|
||||
b = Builder{}
|
||||
_, warns, err = b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
if b.config.DiskSize != 60000 {
|
||||
t.Fatalf("bad size: %d", b.config.DiskSize)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_FloppyFiles(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
delete(config, "floppy_files")
|
||||
_, warns, err := b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("bad err: %s", err)
|
||||
}
|
||||
|
||||
if len(b.config.FloppyFiles) != 0 {
|
||||
t.Fatalf("bad: %#v", b.config.FloppyFiles)
|
||||
}
|
||||
|
||||
floppies_path := "../../test-fixtures/floppies"
|
||||
config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)}
|
||||
b = Builder{}
|
||||
_, warns, err = b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
expected := []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)}
|
||||
if !reflect.DeepEqual(b.config.FloppyFiles, expected) {
|
||||
t.Fatalf("bad: %#v", b.config.FloppyFiles)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_InvalidFloppies(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"}
|
||||
|
||||
b = Builder{}
|
||||
_, _, errs := b.Prepare(config)
|
||||
if errs == nil {
|
||||
t.Fatalf("Nonexistent floppies should trigger multierror")
|
||||
}
|
||||
|
||||
if len(errs.(*packersdk.MultiError).Errors) != 2 {
|
||||
t.Fatalf("Multierror should work and report 2 errors")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_RemoteType(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
config["format"] = "ovf"
|
||||
config["remote_host"] = "foobar.example.com"
|
||||
config["remote_password"] = "supersecret"
|
||||
config["skip_validate_credentials"] = true
|
||||
// Bad
|
||||
config["remote_type"] = "foobar"
|
||||
_, warns, err := b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
config["remote_type"] = "esx5"
|
||||
// Bad
|
||||
config["remote_host"] = ""
|
||||
b = Builder{}
|
||||
_, warns, err = b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Good
|
||||
config["remote_type"] = ""
|
||||
config["format"] = ""
|
||||
config["remote_host"] = ""
|
||||
config["remote_password"] = ""
|
||||
config["remote_private_key_file"] = ""
|
||||
b = Builder{}
|
||||
_, warns, err = b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
// Good
|
||||
config["remote_type"] = "esx5"
|
||||
config["remote_host"] = "foobar.example.com"
|
||||
config["remote_password"] = "supersecret"
|
||||
b = Builder{}
|
||||
_, warns, err = b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_Export(t *testing.T) {
|
||||
type testCase struct {
|
||||
InputConfigVals map[string]string
|
||||
ExpectedSkipExportValue bool
|
||||
ExpectedFormat string
|
||||
ExpectedErr bool
|
||||
Reason string
|
||||
}
|
||||
testCases := []testCase{
|
||||
{
|
||||
InputConfigVals: map[string]string{
|
||||
"remote_type": "",
|
||||
"format": "",
|
||||
},
|
||||
ExpectedSkipExportValue: true,
|
||||
ExpectedFormat: "vmx",
|
||||
ExpectedErr: false,
|
||||
Reason: "should have defaulted format to vmx.",
|
||||
},
|
||||
{
|
||||
InputConfigVals: map[string]string{
|
||||
"remote_type": "esx5",
|
||||
"format": "",
|
||||
"remote_host": "fakehost.com",
|
||||
"remote_password": "fakepassword",
|
||||
"remote_username": "fakeuser",
|
||||
},
|
||||
ExpectedSkipExportValue: false,
|
||||
ExpectedFormat: "ovf",
|
||||
ExpectedErr: false,
|
||||
Reason: "should have defaulted format to ovf with remote set to esx5.",
|
||||
},
|
||||
{
|
||||
InputConfigVals: map[string]string{
|
||||
"remote_type": "esx5",
|
||||
"format": "",
|
||||
},
|
||||
ExpectedSkipExportValue: false,
|
||||
ExpectedFormat: "ovf",
|
||||
ExpectedErr: true,
|
||||
Reason: "should have errored because remote host isn't set for remote build.",
|
||||
},
|
||||
{
|
||||
InputConfigVals: map[string]string{
|
||||
"remote_type": "invalid",
|
||||
"format": "",
|
||||
"remote_host": "fakehost.com",
|
||||
"remote_password": "fakepassword",
|
||||
"remote_username": "fakeuser",
|
||||
},
|
||||
ExpectedSkipExportValue: false,
|
||||
ExpectedFormat: "ovf",
|
||||
ExpectedErr: true,
|
||||
Reason: "should error with invalid remote type",
|
||||
},
|
||||
{
|
||||
InputConfigVals: map[string]string{
|
||||
"remote_type": "",
|
||||
"format": "invalid",
|
||||
},
|
||||
ExpectedSkipExportValue: false,
|
||||
ExpectedFormat: "invalid",
|
||||
ExpectedErr: true,
|
||||
Reason: "should error with invalid format",
|
||||
},
|
||||
{
|
||||
InputConfigVals: map[string]string{
|
||||
"remote_type": "",
|
||||
"format": "ova",
|
||||
},
|
||||
ExpectedSkipExportValue: false,
|
||||
ExpectedFormat: "ova",
|
||||
ExpectedErr: false,
|
||||
Reason: "should set user-given ova format",
|
||||
},
|
||||
{
|
||||
InputConfigVals: map[string]string{
|
||||
"remote_type": "esx5",
|
||||
"format": "ova",
|
||||
"remote_host": "fakehost.com",
|
||||
"remote_password": "fakepassword",
|
||||
"remote_username": "fakeuser",
|
||||
},
|
||||
ExpectedSkipExportValue: false,
|
||||
ExpectedFormat: "ova",
|
||||
ExpectedErr: false,
|
||||
Reason: "should set user-given ova format",
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
config := testConfig()
|
||||
for k, v := range tc.InputConfigVals {
|
||||
config[k] = v
|
||||
}
|
||||
config["skip_validate_credentials"] = true
|
||||
outCfg := &Config{}
|
||||
warns, errs := (outCfg).Prepare(config)
|
||||
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
|
||||
if (errs != nil) != tc.ExpectedErr {
|
||||
t.Fatalf("received error: \n %s \n but 'expected err' was %t", errs, tc.ExpectedErr)
|
||||
}
|
||||
|
||||
if outCfg.Format != tc.ExpectedFormat {
|
||||
t.Fatalf("Expected: %s. Actual: %s. Reason: %s", tc.ExpectedFormat,
|
||||
outCfg.Format, tc.Reason)
|
||||
}
|
||||
if outCfg.SkipExport != tc.ExpectedSkipExportValue {
|
||||
t.Fatalf("For SkipExport expected %t but recieved %t",
|
||||
tc.ExpectedSkipExportValue, outCfg.SkipExport)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_RemoteExport(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
config["remote_type"] = "esx5"
|
||||
config["remote_host"] = "foobar.example.com"
|
||||
config["skip_validate_credentials"] = true
|
||||
// Bad
|
||||
config["remote_password"] = ""
|
||||
_, warns, err := b.Prepare(config)
|
||||
if len(warns) != 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Good
|
||||
config["remote_password"] = "supersecret"
|
||||
b = Builder{}
|
||||
_, warns, err = b.Prepare(config)
|
||||
if len(warns) != 0 {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_Format(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Bad
|
||||
config["format"] = "foobar"
|
||||
_, warns, err := b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
goodFormats := []string{"ova", "ovf", "vmx"}
|
||||
|
||||
for _, format := range goodFormats {
|
||||
// Good
|
||||
config["format"] = format
|
||||
config["remote_type"] = "esx5"
|
||||
config["remote_host"] = "hosty.hostface"
|
||||
config["remote_password"] = "password"
|
||||
config["skip_validate_credentials"] = true
|
||||
|
||||
b = Builder{}
|
||||
_, warns, err = b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_InvalidKey(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Add a random key
|
||||
config["i_should_not_be_valid"] = true
|
||||
_, warns, err := b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_OutputDir(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Test with existing dir
|
||||
dir, err := ioutil.TempDir("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
config["output_directory"] = dir
|
||||
b = Builder{}
|
||||
_, warns, err := b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Test with a good one
|
||||
config["output_directory"] = "i-hope-i-dont-exist"
|
||||
b = Builder{}
|
||||
_, warns, err = b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_ToolsUploadPath(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Test a default
|
||||
delete(config, "tools_upload_path")
|
||||
_, warns, err := b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if b.config.ToolsUploadPath == "" {
|
||||
t.Fatalf("bad value: %s", b.config.ToolsUploadPath)
|
||||
}
|
||||
|
||||
// Test with a bad value
|
||||
config["tools_upload_path"] = "{{{nope}"
|
||||
b = Builder{}
|
||||
_, warns, err = b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Test with a good one
|
||||
config["tools_upload_path"] = "hey"
|
||||
b = Builder{}
|
||||
_, warns, err = b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_VMXTemplatePath(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Test bad
|
||||
config["vmx_template_path"] = "/i/dont/exist/forreal"
|
||||
_, warns, err := b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Test good
|
||||
tf, err := ioutil.TempFile("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.Remove(tf.Name())
|
||||
defer tf.Close()
|
||||
|
||||
if _, err := tf.Write([]byte("HELLO!")); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
config["vmx_template_path"] = tf.Name()
|
||||
b = Builder{}
|
||||
_, warns, err = b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
// Bad template
|
||||
tf2, err := ioutil.TempFile("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.Remove(tf2.Name())
|
||||
defer tf2.Close()
|
||||
|
||||
if _, err := tf2.Write([]byte("{{foo}")); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
config["vmx_template_path"] = tf2.Name()
|
||||
b = Builder{}
|
||||
_, warns, err = b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_VNCPort(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Bad
|
||||
config["vnc_port_min"] = 1000
|
||||
config["vnc_port_max"] = 500
|
||||
_, warns, err := b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Bad
|
||||
config["vnc_port_min"] = -500
|
||||
b = Builder{}
|
||||
_, warns, err = b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Good
|
||||
config["vnc_port_min"] = 500
|
||||
config["vnc_port_max"] = 1000
|
||||
b = Builder{}
|
||||
_, warns, err = b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderCheckCollisions(t *testing.T) {
|
||||
config := testConfig()
|
||||
config["vmx_data"] = map[string]string{
|
||||
"no.collision": "awesomesauce",
|
||||
"ide0:0.fileName": "is a collision",
|
||||
"displayName": "also a collision",
|
||||
}
|
||||
{
|
||||
var b Builder
|
||||
_, warns, _ := b.Prepare(config)
|
||||
if len(warns) != 1 {
|
||||
t.Fatalf("Should have warning about two collisions.")
|
||||
}
|
||||
}
|
||||
{
|
||||
config["vmx_template_path"] = "some/path.vmx"
|
||||
var b Builder
|
||||
_, warns, _ := b.Prepare(config)
|
||||
if len(warns) != 0 {
|
||||
t.Fatalf("Should not check for collisions with custom template.")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_CommConfig(t *testing.T) {
|
||||
// Test Winrm
|
||||
{
|
||||
config := testConfig()
|
||||
config["communicator"] = "winrm"
|
||||
config["winrm_username"] = "username"
|
||||
config["winrm_password"] = "password"
|
||||
config["winrm_host"] = "1.2.3.4"
|
||||
|
||||
var b Builder
|
||||
_, warns, err := b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
if b.config.SSHConfig.Comm.WinRMUser != "username" {
|
||||
t.Errorf("bad winrm_username: %s", b.config.SSHConfig.Comm.WinRMUser)
|
||||
}
|
||||
if b.config.SSHConfig.Comm.WinRMPassword != "password" {
|
||||
t.Errorf("bad winrm_password: %s", b.config.SSHConfig.Comm.WinRMPassword)
|
||||
}
|
||||
if host := b.config.SSHConfig.Comm.Host(); host != "1.2.3.4" {
|
||||
t.Errorf("bad host: %s", host)
|
||||
}
|
||||
}
|
||||
|
||||
// Test SSH
|
||||
{
|
||||
config := testConfig()
|
||||
config["communicator"] = "ssh"
|
||||
config["ssh_username"] = "username"
|
||||
config["ssh_password"] = "password"
|
||||
config["ssh_host"] = "1.2.3.4"
|
||||
|
||||
var b Builder
|
||||
_, warns, err := b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
if b.config.SSHConfig.Comm.SSHUsername != "username" {
|
||||
t.Errorf("bad ssh_username: %s", b.config.SSHConfig.Comm.SSHUsername)
|
||||
}
|
||||
if b.config.SSHConfig.Comm.SSHPassword != "password" {
|
||||
t.Errorf("bad ssh_password: %s", b.config.SSHConfig.Comm.SSHPassword)
|
||||
}
|
||||
if host := b.config.SSHConfig.Comm.Host(); host != "1.2.3.4" {
|
||||
t.Errorf("bad host: %s", host)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,339 +0,0 @@
|
||||
package iso
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
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}]}`
|
||||
|
||||
func createFloppyOutput(prefix string) (string, map[string]string, error) {
|
||||
f, err := tmp.File(prefix)
|
||||
if err != nil {
|
||||
return "", map[string]string{}, fmt.Errorf("unable to create temp file")
|
||||
}
|
||||
f.Close()
|
||||
|
||||
output := f.Name()
|
||||
outputFile := strings.Replace(output, "\\", "\\\\", -1)
|
||||
vmxData := map[string]string{
|
||||
"floppy0.present": "TRUE",
|
||||
"floppy0.fileType": "file",
|
||||
"floppy0.clientDevice": "FALSE",
|
||||
"floppy0.fileName": outputFile,
|
||||
"floppy0.startConnected": "TRUE",
|
||||
}
|
||||
return output, vmxData, nil
|
||||
}
|
||||
|
||||
func readFloppyOutput(path string) (string, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unable to open file %s", path)
|
||||
}
|
||||
defer f.Close()
|
||||
data, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unable to read file: %s", err)
|
||||
}
|
||||
if len(data) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
return string(data[:bytes.IndexByte(data, 0)]), nil
|
||||
}
|
||||
|
||||
// RenderConfig helps create dynamic packer template configs for parsing by
|
||||
// builderT without having to write the config to a file.
|
||||
func RenderConfig(builderConfig map[string]interface{}, provisionerConfig map[string]string) string {
|
||||
// set up basic build template
|
||||
t := map[string][]map[string]interface{}{
|
||||
"builders": {
|
||||
map[string]interface{}{
|
||||
"type": "test",
|
||||
"iso_url": "https://archive.org/download/ut-ttylinux-i686-12.6/ut-ttylinux-i686-12.6.iso",
|
||||
"iso_checksum": "md5:43c1feeae55a44c6ef694b8eb18408a6",
|
||||
"ssh_username": "root",
|
||||
"ssh_password": "password",
|
||||
"ssh_wait_timeout": "45s",
|
||||
"boot_command": []string{"<enter><wait5><wait10>", "root<enter><wait>password<enter><wait>", "udhcpc<enter><wait>"},
|
||||
"shutdown_command": "/sbin/shutdown -h; exit 0",
|
||||
"ssh_key_exchange_algorithms": []string{"diffie-hellman-group1-sha1"},
|
||||
},
|
||||
},
|
||||
"provisioners": {
|
||||
map[string]interface{}{
|
||||
"type": "shell",
|
||||
"inline": []string{"echo hola mundo"},
|
||||
},
|
||||
},
|
||||
}
|
||||
// apply special builder overrides
|
||||
for k, v := range builderConfig {
|
||||
t["builders"][0][k] = v
|
||||
}
|
||||
// Apply special provisioner overrides
|
||||
for k, v := range provisionerConfig {
|
||||
t["provisioners"][0][k] = v
|
||||
}
|
||||
|
||||
j, _ := json.Marshal(t)
|
||||
return string(j)
|
||||
}
|
||||
|
||||
func TestStepCreateVmx_SerialFile(t *testing.T) {
|
||||
if os.Getenv("PACKER_ACC") == "" {
|
||||
t.Skip("This test is only run with PACKER_ACC=1 due to the requirement of access to the VMware binaries.")
|
||||
}
|
||||
|
||||
tmpfile, err := tmp.File("SerialFileInput.")
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create temp file")
|
||||
}
|
||||
serialConfig := map[string]interface{}{
|
||||
"serial": fmt.Sprintf("file:%s", filepath.ToSlash(tmpfile.Name())),
|
||||
}
|
||||
|
||||
configString := RenderConfig(serialConfig, map[string]string{})
|
||||
|
||||
builderT.Test(t, builderT.TestCase{
|
||||
Builder: &Builder{},
|
||||
Template: configString,
|
||||
Check: func(a []packersdk.Artifact) error {
|
||||
_, err := os.Stat(tmpfile.Name())
|
||||
if err != nil {
|
||||
return fmt.Errorf("VMware builder did not create a file for serial port: %s", err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Teardown: func() error {
|
||||
f, _ := os.Stat(tmpfile.Name())
|
||||
if f != nil {
|
||||
if err := os.Remove(tmpfile.Name()); err != nil {
|
||||
return fmt.Errorf("Unable to remove file %s: %s", tmpfile.Name(), err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestStepCreateVmx_SerialPort(t *testing.T) {
|
||||
if os.Getenv("PACKER_ACC") == "" {
|
||||
t.Skip("This test is only run with PACKER_ACC=1 due to the requirement of access to the VMware binaries.")
|
||||
}
|
||||
|
||||
var defaultSerial string
|
||||
if runtime.GOOS == "windows" {
|
||||
defaultSerial = "COM1"
|
||||
} else {
|
||||
defaultSerial = "/dev/ttyS0"
|
||||
}
|
||||
|
||||
config := map[string]interface{}{
|
||||
"serial": fmt.Sprintf("device:%s", filepath.ToSlash(defaultSerial)),
|
||||
}
|
||||
provision := map[string]string{
|
||||
"inline": "dmesg | egrep -o '^serial8250: ttyS1 at' > /dev/fd0",
|
||||
}
|
||||
|
||||
// where to write output
|
||||
output, vmxData, err := createFloppyOutput("SerialPortOutput.")
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating output: %s", err)
|
||||
}
|
||||
|
||||
config["vmx_data"] = vmxData
|
||||
configString := RenderConfig(config, provision)
|
||||
builderT.Test(t, builderT.TestCase{
|
||||
Builder: &Builder{},
|
||||
Template: configString,
|
||||
Check: func(a []packersdk.Artifact) error {
|
||||
_, err := os.Stat(output)
|
||||
if err != nil {
|
||||
return fmt.Errorf("VMware builder did not create a file for serial port: %s", err)
|
||||
}
|
||||
// check the output
|
||||
data, err := readFloppyOutput(output)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s", err)
|
||||
}
|
||||
|
||||
if data != "serial8250: ttyS1 at\n" {
|
||||
return fmt.Errorf("Serial port not detected : %v", data)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Teardown: func() error {
|
||||
if _, err := os.Stat(output); err == nil {
|
||||
os.Remove(output)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestStepCreateVmx_ParallelPort(t *testing.T) {
|
||||
if os.Getenv("PACKER_ACC") == "" {
|
||||
t.Skip("This test is only run with PACKER_ACC=1 due to the requirement of access to the VMware binaries.")
|
||||
}
|
||||
|
||||
var defaultParallel string
|
||||
if runtime.GOOS == "windows" {
|
||||
defaultParallel = "LPT1"
|
||||
} else {
|
||||
defaultParallel = "/dev/lp0"
|
||||
}
|
||||
|
||||
config := map[string]interface{}{
|
||||
"parallel": fmt.Sprintf("device:%s,uni", filepath.ToSlash(defaultParallel)),
|
||||
}
|
||||
provision := map[string]string{
|
||||
"inline": "cat /proc/modules | egrep -o '^parport ' > /dev/fd0",
|
||||
}
|
||||
|
||||
// where to write output
|
||||
output, vmxData, err := createFloppyOutput("ParallelPortOutput.")
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating output: %s", err)
|
||||
}
|
||||
|
||||
config["vmx_data"] = vmxData
|
||||
configString := RenderConfig(config, provision)
|
||||
builderT.Test(t, builderT.TestCase{
|
||||
Builder: &Builder{},
|
||||
Template: configString,
|
||||
Check: func(a []packersdk.Artifact) error {
|
||||
_, err := os.Stat(output)
|
||||
if err != nil {
|
||||
return fmt.Errorf("VMware builder did not create a file for serial port: %s", err)
|
||||
}
|
||||
// check the output
|
||||
data, err := readFloppyOutput(output)
|
||||
if err != nil {
|
||||
t.Errorf("%s", err)
|
||||
}
|
||||
|
||||
if data != "parport \n" {
|
||||
t.Errorf("Parallel port not detected : %v", data)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Teardown: func() error {
|
||||
if _, err := os.Stat(output); err == nil {
|
||||
os.Remove(output)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestStepCreateVmx_Usb(t *testing.T) {
|
||||
if os.Getenv("PACKER_ACC") == "" {
|
||||
t.Skip("This test is only run with PACKER_ACC=1 due to the requirement of access to the VMware binaries.")
|
||||
}
|
||||
|
||||
config := map[string]interface{}{
|
||||
"usb": "TRUE",
|
||||
}
|
||||
provision := map[string]string{
|
||||
"inline": "dmesg | egrep -m1 -o 'USB hub found$' > /dev/fd0",
|
||||
}
|
||||
|
||||
output, vmxData, err := createFloppyOutput("UsbOutput.")
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating output: %s", err)
|
||||
}
|
||||
|
||||
config["vmx_data"] = vmxData
|
||||
configString := RenderConfig(config, provision)
|
||||
builderT.Test(t, builderT.TestCase{
|
||||
Builder: &Builder{},
|
||||
Template: configString,
|
||||
Check: func(a []packersdk.Artifact) error {
|
||||
_, err := os.Stat(output)
|
||||
if err != nil {
|
||||
return fmt.Errorf("VMware builder did not create a file for serial port: %s", err)
|
||||
}
|
||||
// check the output
|
||||
data, err := readFloppyOutput(output)
|
||||
if err != nil {
|
||||
t.Errorf("%s", err)
|
||||
}
|
||||
|
||||
if data != "USB hub found\n" {
|
||||
t.Errorf("USB support not detected : %v", data)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Teardown: func() error {
|
||||
if _, err := os.Stat(output); err == nil {
|
||||
os.Remove(output)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestStepCreateVmx_Sound(t *testing.T) {
|
||||
if os.Getenv("PACKER_ACC") == "" {
|
||||
t.Skip("This test is only run with PACKER_ACC=1 due to the requirement of access to the VMware binaries.")
|
||||
}
|
||||
|
||||
config := map[string]interface{}{
|
||||
"sound": "TRUE",
|
||||
}
|
||||
provision := map[string]string{
|
||||
"inline": "cat /proc/modules | egrep -o '^soundcore' > /dev/fd0",
|
||||
}
|
||||
|
||||
// where to write output
|
||||
output, vmxData, err := createFloppyOutput("SoundOutput.")
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating output: %s", err)
|
||||
}
|
||||
defer func() {
|
||||
if _, err := os.Stat(output); err == nil {
|
||||
os.Remove(output)
|
||||
}
|
||||
}()
|
||||
|
||||
config["vmx_data"] = vmxData
|
||||
configString := RenderConfig(config, provision)
|
||||
builderT.Test(t, builderT.TestCase{
|
||||
Builder: &Builder{},
|
||||
Template: configString,
|
||||
Check: func(a []packersdk.Artifact) error {
|
||||
_, err := os.Stat(output)
|
||||
if err != nil {
|
||||
return fmt.Errorf("VMware builder did not create a file for serial port: %s", err)
|
||||
}
|
||||
// check the output
|
||||
data, err := readFloppyOutput(output)
|
||||
if err != nil {
|
||||
t.Errorf("%s", err)
|
||||
}
|
||||
|
||||
if data != "soundcore\n" {
|
||||
t.Errorf("Soundcard not detected : %v", data)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Teardown: func() error {
|
||||
if _, err := os.Stat(output); err == nil {
|
||||
os.Remove(output)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
# Preseeding only locale sets language, country and locale.
|
||||
d-i debian-installer/locale string en_US
|
||||
|
||||
# Keyboard selection.
|
||||
d-i console-setup/ask_detect boolean false
|
||||
d-i keyboard-configuration/xkb-keymap select us
|
||||
|
||||
choose-mirror-bin mirror/http/proxy string
|
||||
d-i base-installer/kernel/override-image string linux-server
|
||||
d-i clock-setup/utc boolean true
|
||||
d-i clock-setup/utc-auto boolean true
|
||||
d-i finish-install/reboot_in_progress note
|
||||
d-i grub-installer/only_debian boolean true
|
||||
d-i grub-installer/with_other_os boolean true
|
||||
d-i mirror/country string manual
|
||||
d-i mirror/http/directory string /ubuntu/
|
||||
d-i mirror/http/hostname string archive.ubuntu.com
|
||||
d-i mirror/http/proxy string
|
||||
d-i partman-auto-lvm/guided_size string max
|
||||
d-i partman-auto/choose_recipe select atomic
|
||||
d-i partman-auto/method string lvm
|
||||
d-i partman-lvm/confirm boolean true
|
||||
d-i partman-lvm/confirm boolean true
|
||||
d-i partman-lvm/confirm_nooverwrite boolean true
|
||||
d-i partman-lvm/device_remove_lvm boolean true
|
||||
d-i partman/choose_partition select finish
|
||||
d-i partman/confirm boolean true
|
||||
d-i partman/confirm_nooverwrite boolean true
|
||||
d-i partman/confirm_write_new_label boolean true
|
||||
d-i passwd/user-fullname string vagrant
|
||||
d-i passwd/user-uid string 1000
|
||||
d-i passwd/user-password password vagrant
|
||||
d-i passwd/user-password-again password vagrant
|
||||
d-i passwd/username string vagrant
|
||||
d-i pkgsel/include string openssh-server cryptsetup build-essential libssl-dev libreadline-dev zlib1g-dev linux-source dkms nfs-kernel-server nfs-common linux-headers-$(uname -r) perl
|
||||
d-i pkgsel/install-language-support boolean false
|
||||
d-i pkgsel/update-policy select none
|
||||
d-i pkgsel/upgrade select full-upgrade
|
||||
d-i time/zone string UTC
|
||||
d-i user-setup/allow-password-weak boolean true
|
||||
d-i user-setup/encrypt-home boolean false
|
||||
tasksel tasksel/first multiselect standard, server
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"builders": [
|
||||
{
|
||||
"type": "vmware-iso",
|
||||
"boot_command": [
|
||||
"<esc><wait>",
|
||||
"<esc><wait>",
|
||||
"<enter><wait>",
|
||||
"/install/vmlinuz<wait>",
|
||||
" initrd=/install/initrd.gz",
|
||||
" auto-install/enable=true",
|
||||
" debconf/priority=critical",
|
||||
" preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg<wait>",
|
||||
" -- <wait>",
|
||||
"<enter><wait>"
|
||||
],
|
||||
"boot_wait": "10s",
|
||||
"guest_os_type": "ubuntu-64",
|
||||
"http_directory": "./testdata/http",
|
||||
"iso_checksum": "sha256:946a6077af6f5f95a51f82fdc44051c7aa19f9cfc5f737954845a6050543d7c2",
|
||||
"iso_url": "http://old-releases.ubuntu.com/releases/14.04.1/ubuntu-14.04.1-server-amd64.iso",
|
||||
"shutdown_command": "echo 'vagrant' | sudo -S shutdown -P now",
|
||||
"headless": true,
|
||||
"ssh_password": "vagrant",
|
||||
"ssh_username": "vagrant",
|
||||
"ssh_timeout": "10000s",
|
||||
"tools_upload_flavor": "linux"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package version
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/packer-plugin-sdk/version"
|
||||
packerVersion "github.com/hashicorp/packer/version"
|
||||
)
|
||||
|
||||
var VMwarePluginVersion *version.PluginVersion
|
||||
|
||||
func init() {
|
||||
VMwarePluginVersion = version.InitializePluginVersion(
|
||||
packerVersion.Version, packerVersion.VersionPrerelease)
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package vmx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
func TestBuilderPrepare_FloppyFiles(t *testing.T) {
|
||||
var b Builder
|
||||
|
||||
tf, err := ioutil.TempFile("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
tf.Close()
|
||||
defer os.Remove(tf.Name())
|
||||
|
||||
config := testConfig(t)
|
||||
config["source_path"] = tf.Name()
|
||||
|
||||
delete(config, "floppy_files")
|
||||
_, warns, err := b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("bad err: %s", err)
|
||||
}
|
||||
|
||||
if len(b.config.FloppyFiles) != 0 {
|
||||
t.Fatalf("bad: %#v", b.config.FloppyFiles)
|
||||
}
|
||||
|
||||
floppies_path := "../../test-fixtures/floppies"
|
||||
config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)}
|
||||
b = Builder{}
|
||||
_, warns, err = b.Prepare(config)
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
expected := []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)}
|
||||
if !reflect.DeepEqual(b.config.FloppyFiles, expected) {
|
||||
t.Fatalf("bad: %#v", b.config.FloppyFiles)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_InvalidFloppies(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig(t)
|
||||
config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"}
|
||||
b = Builder{}
|
||||
_, _, errs := b.Prepare(config)
|
||||
if errs == nil {
|
||||
t.Fatalf("Nonexistent floppies should trigger multierror")
|
||||
}
|
||||
|
||||
if len(errs.(*packersdk.MultiError).Errors) != 2 {
|
||||
t.Fatalf("Multierror should work and report 2 errors")
|
||||
}
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
package vmx
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testConfig(t *testing.T) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"ssh_username": "foo",
|
||||
"shutdown_command": "foo",
|
||||
"source_path": "config_test.go",
|
||||
}
|
||||
}
|
||||
|
||||
func testConfigErr(t *testing.T, warns []string, err error) {
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should error")
|
||||
}
|
||||
}
|
||||
|
||||
func testConfigOk(t *testing.T, warns []string, err error) {
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("bad: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewConfig_sourcePath(t *testing.T) {
|
||||
// Bad
|
||||
cfg := testConfig(t)
|
||||
delete(cfg, "source_path")
|
||||
warns, errs := (&Config{}).Prepare(cfg)
|
||||
testConfigErr(t, warns, errs)
|
||||
|
||||
// Bad
|
||||
cfg = testConfig(t)
|
||||
cfg["source_path"] = "/i/dont/exist"
|
||||
warns, errs = (&Config{}).Prepare(cfg)
|
||||
testConfigErr(t, warns, errs)
|
||||
|
||||
// Good
|
||||
tf, err := ioutil.TempFile("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
tf.Close()
|
||||
defer os.Remove(tf.Name())
|
||||
|
||||
cfg = testConfig(t)
|
||||
cfg["source_path"] = tf.Name()
|
||||
warns, errs = (&Config{}).Prepare(cfg)
|
||||
testConfigOk(t, warns, errs)
|
||||
}
|
||||
|
||||
func TestNewConfig_exportConfig(t *testing.T) {
|
||||
type testCase struct {
|
||||
InputConfigVals map[string]string
|
||||
ExpectedSkipExportValue bool
|
||||
ExpectedFormat string
|
||||
ExpectedErr bool
|
||||
Reason string
|
||||
}
|
||||
testCases := []testCase{
|
||||
{
|
||||
InputConfigVals: map[string]string{
|
||||
"remote_type": "",
|
||||
"format": "",
|
||||
},
|
||||
ExpectedSkipExportValue: true,
|
||||
ExpectedFormat: "vmx",
|
||||
ExpectedErr: false,
|
||||
Reason: "should have defaulted format to vmx.",
|
||||
},
|
||||
{
|
||||
InputConfigVals: map[string]string{
|
||||
"remote_type": "esx5",
|
||||
"format": "",
|
||||
"remote_host": "fakehost.com",
|
||||
"remote_password": "fakepassword",
|
||||
"remote_username": "fakeuser",
|
||||
},
|
||||
ExpectedSkipExportValue: false,
|
||||
ExpectedFormat: "ovf",
|
||||
ExpectedErr: false,
|
||||
Reason: "should have defaulted format to ovf with remote set to esx5.",
|
||||
},
|
||||
{
|
||||
InputConfigVals: map[string]string{
|
||||
"remote_type": "esx5",
|
||||
"format": "",
|
||||
},
|
||||
ExpectedSkipExportValue: false,
|
||||
ExpectedFormat: "ovf",
|
||||
ExpectedErr: true,
|
||||
Reason: "should have errored because remote host isn't set for remote build.",
|
||||
},
|
||||
{
|
||||
InputConfigVals: map[string]string{
|
||||
"remote_type": "invalid",
|
||||
"format": "",
|
||||
"remote_host": "fakehost.com",
|
||||
"remote_password": "fakepassword",
|
||||
"remote_username": "fakeuser",
|
||||
},
|
||||
ExpectedSkipExportValue: false,
|
||||
ExpectedFormat: "ovf",
|
||||
ExpectedErr: true,
|
||||
Reason: "should error with invalid remote type",
|
||||
},
|
||||
{
|
||||
InputConfigVals: map[string]string{
|
||||
"remote_type": "",
|
||||
"format": "invalid",
|
||||
},
|
||||
ExpectedSkipExportValue: false,
|
||||
ExpectedFormat: "invalid",
|
||||
ExpectedErr: true,
|
||||
Reason: "should error with invalid format",
|
||||
},
|
||||
{
|
||||
InputConfigVals: map[string]string{
|
||||
"remote_type": "",
|
||||
"format": "ova",
|
||||
},
|
||||
ExpectedSkipExportValue: false,
|
||||
ExpectedFormat: "ova",
|
||||
ExpectedErr: false,
|
||||
Reason: "should set user-given ova format",
|
||||
},
|
||||
{
|
||||
InputConfigVals: map[string]string{
|
||||
"remote_type": "esx5",
|
||||
"format": "ova",
|
||||
"remote_host": "fakehost.com",
|
||||
"remote_password": "fakepassword",
|
||||
"remote_username": "fakeuser",
|
||||
},
|
||||
ExpectedSkipExportValue: false,
|
||||
ExpectedFormat: "ova",
|
||||
ExpectedErr: false,
|
||||
Reason: "should set user-given ova format",
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
cfg := testConfig(t)
|
||||
for k, v := range tc.InputConfigVals {
|
||||
cfg[k] = v
|
||||
}
|
||||
cfg["skip_validate_credentials"] = true
|
||||
outCfg := &Config{}
|
||||
warns, errs := (outCfg).Prepare(cfg)
|
||||
|
||||
if len(warns) > 0 {
|
||||
t.Fatalf("bad: %#v", warns)
|
||||
}
|
||||
|
||||
if (errs != nil) != tc.ExpectedErr {
|
||||
t.Fatalf("received error: \n %s \n but 'expected err' was %t", errs, tc.ExpectedErr)
|
||||
}
|
||||
|
||||
if outCfg.Format != tc.ExpectedFormat {
|
||||
t.Fatalf("Expected: %s. Actual: %s. Reason: %s", tc.ExpectedFormat,
|
||||
outCfg.Format, tc.Reason)
|
||||
}
|
||||
if outCfg.SkipExport != tc.ExpectedSkipExportValue {
|
||||
t.Fatalf("For SkipExport expected %t but recieved %t",
|
||||
tc.ExpectedSkipExportValue, outCfg.SkipExport)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
package vmx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const (
|
||||
scsiFilename = "scsiDisk.vmdk"
|
||||
sataFilename = "sataDisk.vmdk"
|
||||
nvmeFilename = "nvmeDisk.vmdk"
|
||||
ideFilename = "ideDisk.vmdk"
|
||||
)
|
||||
|
||||
func TestStepCloneVMX_impl(t *testing.T) {
|
||||
var _ multistep.Step = new(StepCloneVMX)
|
||||
}
|
||||
|
||||
func TestStepCloneVMX(t *testing.T) {
|
||||
// Setup some state
|
||||
td, err := ioutil.TempDir("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.RemoveAll(td)
|
||||
|
||||
// Set up mock vmx file contents
|
||||
var testCloneVMX = fmt.Sprintf("scsi0:0.filename = \"%s\"\n"+
|
||||
"sata0:0.filename = \"%s\"\n"+
|
||||
"nvme0:0.filename = \"%s\"\n"+
|
||||
"ide1:0.filename = \"%s\"\n"+
|
||||
"ide0:0.filename = \"auto detect\"\n"+
|
||||
"ethernet0.connectiontype = \"nat\"\n", scsiFilename,
|
||||
sataFilename, nvmeFilename, ideFilename)
|
||||
|
||||
// Set up expected mock disk file paths
|
||||
diskFilenames := []string{scsiFilename, sataFilename, ideFilename, nvmeFilename}
|
||||
var diskFullPaths []string
|
||||
for _, diskFilename := range diskFilenames {
|
||||
diskFullPaths = append(diskFullPaths, filepath.Join(td, diskFilename))
|
||||
}
|
||||
|
||||
// Create the source
|
||||
sourcePath := filepath.Join(td, "source.vmx")
|
||||
if err := ioutil.WriteFile(sourcePath, []byte(testCloneVMX), 0644); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Create the dest because the mock driver won't
|
||||
destPath := filepath.Join(td, "foo.vmx")
|
||||
if err := ioutil.WriteFile(destPath, []byte(testCloneVMX), 0644); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
state := testState(t)
|
||||
step := new(StepCloneVMX)
|
||||
step.OutputDir = &td
|
||||
step.Path = sourcePath
|
||||
step.VMName = "foo"
|
||||
|
||||
driver := state.Get("driver").(*vmwcommon.DriverMock)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
|
||||
// Test we cloned
|
||||
if !driver.CloneCalled {
|
||||
t.Fatal("should call clone")
|
||||
}
|
||||
|
||||
// Test that we have our paths
|
||||
if vmxPath, ok := state.GetOk("vmx_path"); !ok {
|
||||
t.Fatal("should set vmx_path")
|
||||
} else if vmxPath != destPath {
|
||||
t.Fatalf("bad path to vmx: %#v", vmxPath)
|
||||
}
|
||||
|
||||
if stateDiskPaths, ok := state.GetOk("disk_full_paths"); !ok {
|
||||
t.Fatal("should set disk_full_paths")
|
||||
} else {
|
||||
assert.ElementsMatchf(t, stateDiskPaths.([]string), diskFullPaths,
|
||||
"%s\nshould contain the same elements as:\n%s", stateDiskPaths.([]string), diskFullPaths)
|
||||
}
|
||||
|
||||
// Test we got the network type
|
||||
if networkType, ok := state.GetOk("vmnetwork"); !ok {
|
||||
t.Fatal("should set vmnetwork")
|
||||
} else if networkType != "nat" {
|
||||
t.Fatalf("bad network type: %#v", networkType)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user