From f05b1e1e4b087ea06e9ac6ae3425ff9d8354e920 Mon Sep 17 00:00:00 2001 From: Andrey Tonkikh Date: Thu, 12 Oct 2017 08:19:23 +0300 Subject: [PATCH 01/12] Refactor `driver.NewDriver` `driver.NewDriver` used to construct a govnomi client on its own while the same work can be done by calling `govmomi.NewClient`. --- driver/driver.go | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/driver/driver.go b/driver/driver.go index 30ddcce72..d2bd048e7 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -9,8 +9,6 @@ import ( "github.com/vmware/govmomi/object" "time" "github.com/vmware/govmomi/session" - "github.com/vmware/govmomi/vim25/soap" - "github.com/vmware/govmomi/vim25" ) type Driver struct { @@ -35,25 +33,13 @@ func NewDriver(config *ConnectConfig) (*Driver, error) { if err != nil { return nil, err } - credentials := url.UserPassword(config.Username, config.Password) - vcenter_url.User = credentials + vcenter_url.User = url.UserPassword(config.Username, config.Password) - soapClient := soap.NewClient(vcenter_url, config.InsecureConnection) - vimClient, err := vim25.NewClient(ctx, soapClient) - if err != nil { - return nil, err - } - - vimClient.RoundTripper = session.KeepAlive(vimClient.RoundTripper, 10*time.Minute) - client := &govmomi.Client{ - Client: vimClient, - SessionManager: session.NewManager(vimClient), - } - - err = client.SessionManager.Login(ctx, credentials) + client, err := govmomi.NewClient(ctx, vcenter_url, config.InsecureConnection) if err != nil { return nil, err } + client.RoundTripper = session.KeepAlive(client.RoundTripper, 10*time.Minute) finder := find.NewFinder(client.Client, false) datacenter, err := finder.DatacenterOrDefault(ctx, config.Datacenter) From c339fbfb39414a71b44efcdcfe3c5ff3aa84120b Mon Sep 17 00:00:00 2001 From: Andrey Tonkikh Date: Wed, 25 Oct 2017 23:20:59 +0300 Subject: [PATCH 02/12] Add some acceptance tests for `VirtualMachine` and `Datastore` --- builder_acc_test.go | 153 +++++---------------------- driver/test.sh | 5 + driver/testing/config.go | 19 ++++ driver/testing/datastore_acc_test.go | 30 ++++++ driver/testing/utility.go | 142 +++++++++++++++++++++++++ driver/testing/vm_acc_test.go | 131 +++++++++++++++++++++++ driver/vm.go | 9 +- test.sh | 2 +- 8 files changed, 356 insertions(+), 135 deletions(-) create mode 100755 driver/test.sh create mode 100644 driver/testing/config.go create mode 100644 driver/testing/datastore_acc_test.go create mode 100644 driver/testing/utility.go create mode 100644 driver/testing/vm_acc_test.go diff --git a/builder_acc_test.go b/builder_acc_test.go index faa660ade..ab51d4ade 100644 --- a/builder_acc_test.go +++ b/builder_acc_test.go @@ -3,11 +3,10 @@ package main import ( "testing" builderT "github.com/hashicorp/packer/helper/builder/testing" - "fmt" "github.com/hashicorp/packer/packer" "encoding/json" - "math/rand" "github.com/jetbrains-infra/packer-builder-vsphere/driver" + driverT "github.com/jetbrains-infra/packer-builder-vsphere/driver/testing" ) func TestBuilderAcc_default(t *testing.T) { @@ -21,77 +20,26 @@ func TestBuilderAcc_default(t *testing.T) { func defaultConfig() map[string]interface{} { config := map[string]interface{}{ - "vcenter_server": "vcenter.vsphere55.test", - "username": "root", - "password": "jetbrains", + "vcenter_server": driverT.DefaultVCenterServer, + "username": driverT.DefaultVCenterUsername, + "password": driverT.DefaultVCenterPassword, "insecure_connection": true, - "template": "alpine", - "host": "esxi-1.vsphere55.test", + "template": driverT.DefaultTemplate, + "host": driverT.DefaultHost, "ssh_username": "root", "ssh_password": "jetbrains", } - config["vm_name"] = fmt.Sprintf("test-%v", rand.Intn(1000)) + config["vm_name"] = driverT.NewVMName() return config } func checkDefault(t *testing.T, name string, host string, datastore string) builderT.TestCheckFunc { return func(artifacts []packer.Artifact) error { - d := testConn(t) + d := driverT.NewTestDriver(t) vm := getVM(t, d, artifacts) - - vmInfo, err := vm.Info("name", "parent", "runtime.host", "resourcePool", "datastore", "layoutEx.disk") - if err != nil { - t.Fatalf("Cannot read VM properties: %v", err) - } - - if vmInfo.Name != name { - t.Errorf("Invalid VM name: expected '%v', got '%v'", name, vmInfo.Name) - } - - f := d.NewFolder(vmInfo.Parent) - folderPath, err := f.Path() - if err != nil { - t.Fatalf("Cannot read folder name: %v", err) - } - if folderPath != "" { - t.Errorf("Invalid folder: expected '/', got '%v'", folderPath) - } - - h := d.NewHost(vmInfo.Runtime.Host) - hostInfo, err := h.Info("name") - if err != nil { - t.Fatal("Cannot read host properties: ", err) - } - if hostInfo.Name != host { - t.Errorf("Invalid host name: expected '%v', got '%v'", host, hostInfo.Name) - } - - p := d.NewResourcePool(vmInfo.ResourcePool) - poolPath, err := p.Path() - if err != nil { - t.Fatalf("Cannot read resource pool name: %v", err) - } - if poolPath != "" { - t.Error("Invalid resource pool: expected '/', got '%v'", poolPath) - } - - dsr := vmInfo.Datastore[0].Reference() - ds := d.NewDatastore(&dsr) - dsInfo, err := ds.Info("name") - if err != nil { - t.Fatal("Cannot read datastore properties: ", err) - } - if dsInfo.Name != datastore { - t.Errorf("Invalid datastore name: expected '%v', got '%v'", datastore, dsInfo.Name) - } - - if len(vmInfo.LayoutEx.Disk[0].Chain) != 1 { - t.Error("Not a full clone") - } - - return nil + return driverT.VMCheckDefault(t, d, vm, name, host, datastore) } } @@ -137,7 +85,7 @@ func folderConfig() string { func checkFolder(t *testing.T, folder string) builderT.TestCheckFunc { return func(artifacts []packer.Artifact) error { - d := testConn(t) + d := driverT.NewTestDriver(t) vm := getVM(t, d, artifacts) vmInfo, err := vm.Info("parent") @@ -175,7 +123,7 @@ func resourcePoolConfig() string { func checkResourcePool(t *testing.T, pool string) builderT.TestCheckFunc { return func(artifacts []packer.Artifact) error { - d := testConn(t) + d := driverT.NewTestDriver(t) vm := getVM(t, d, artifacts) vmInfo, err := vm.Info("resourcePool") @@ -196,6 +144,7 @@ func checkResourcePool(t *testing.T, pool string) builderT.TestCheckFunc { } } +// FIXME: why do we need this??? Why don't perform these checks in checkDefault? func TestBuilderAcc_datastore(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, @@ -212,7 +161,7 @@ func datastoreConfig() string { func checkDatastore(t *testing.T, name string) builderT.TestCheckFunc { return func(artifacts []packer.Artifact) error { - d := testConn(t) + d := driverT.NewTestDriver(t) vm := getVM(t, d, artifacts) vmInfo, err := vm.Info("datastore") @@ -226,20 +175,14 @@ func checkDatastore(t *testing.T, name string) builderT.TestCheckFunc { } ds := d.NewDatastore(&vmInfo.Datastore[0]) - info, err := ds.Info("name") - if err != nil { - t.Fatalf("Cannot read datastore properties: %v", err) - } - if info.Name != name { - t.Errorf("Wrong datastore. expected: %v, got: %v", name, info.Name) - } + driverT.CheckDatastoreName(t, ds, name) return nil } } func TestBuilderAcc_multipleDatastores(t *testing.T) { - t.Skip("test must fail") + t.Skip("test must fail") // FIXME builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, @@ -269,7 +212,7 @@ func linkedCloneConfig() string { func checkLinkedClone(t *testing.T) builderT.TestCheckFunc { return func(artifacts []packer.Artifact) error { - d := testConn(t) + d := driverT.NewTestDriver(t) vm := getVM(t, d, artifacts) vmInfo, err := vm.Info("layoutEx.disk") @@ -295,11 +238,11 @@ func TestBuilderAcc_hardware(t *testing.T) { func hardwareConfig() string { config := defaultConfig() - config["CPUs"] = 2 - config["CPU_reservation"] = 1000 - config["CPU_limit"] = 1500 - config["RAM"] = 2048 - config["RAM_reservation"] = 1024 + config["CPUs"] = driverT.DefaultCPUs + config["CPU_reservation"] = driverT.DefaultCPUReservation + config["CPU_limit"] = driverT.DefaultCPULimit + config["RAM"] = driverT.DefaultRAM + config["RAM_reservation"] = driverT.DefaultRAMReservation config["linked_clone"] = true // speed up return renderConfig(config) @@ -307,40 +250,9 @@ func hardwareConfig() string { func checkHardware(t *testing.T) builderT.TestCheckFunc { return func(artifacts []packer.Artifact) error { - d := testConn(t) - + d := driverT.NewTestDriver(t) vm := getVM(t, d, artifacts) - vmInfo, err := vm.Info("config") - if err != nil { - t.Fatalf("Cannot read VM properties: %v", err) - } - - cpuSockets := vmInfo.Config.Hardware.NumCPU - if cpuSockets != 2 { - t.Errorf("VM should have 2 CPU sockets, got %v", cpuSockets) - } - - cpuReservation := vmInfo.Config.CpuAllocation.GetResourceAllocationInfo().Reservation - if cpuReservation != 1000 { - t.Errorf("VM should have CPU reservation for 1000 Mhz, got %v", cpuReservation) - } - - cpuLimit := vmInfo.Config.CpuAllocation.GetResourceAllocationInfo().Limit - if cpuLimit != 1500 { - t.Errorf("VM should have CPU reservation for 1500 Mhz, got %v", cpuLimit) - } - - ram := vmInfo.Config.Hardware.MemoryMB - if ram != 2048 { - t.Errorf("VM should have 2048 MB of RAM, got %v", ram) - } - - ramReservation := vmInfo.Config.MemoryAllocation.GetResourceAllocationInfo().Reservation - if ramReservation != 1024 { - t.Errorf("VM should have RAM reservation for 1024 MB, got %v", ramReservation) - } - - return nil + return driverT.VMCheckHardware(t, d, vm) } } @@ -362,7 +274,7 @@ func RAMReservationConfig() string { func checkRAMReservation(t *testing.T) builderT.TestCheckFunc { return func(artifacts []packer.Artifact) error { - d := testConn(t) + d := driverT.NewTestDriver(t) vm := getVM(t, d, artifacts) vmInfo, err := vm.Info("config") @@ -409,7 +321,7 @@ func snapshotConfig() string { func checkSnapshot(t *testing.T) builderT.TestCheckFunc { return func(artifacts []packer.Artifact) error { - d := testConn(t) + d := driverT.NewTestDriver(t) vm := getVM(t, d, artifacts) vmInfo, err := vm.Info("layoutEx.disk") @@ -443,7 +355,7 @@ func templateConfig() string { func checkTemplate(t *testing.T) builderT.TestCheckFunc { return func(artifacts []packer.Artifact) error { - d := testConn(t) + d := driverT.NewTestDriver(t) vm := getVM(t, d, artifacts) vmInfo, err := vm.Info("config.template") @@ -475,19 +387,6 @@ func renderConfig(config map[string]interface{}) string { return string(j) } -func testConn(t *testing.T) *driver.Driver { - d, err := driver.NewDriver(&driver.ConnectConfig{ - VCenterServer: "vcenter.vsphere55.test", - Username: "root", - Password: "jetbrains", - InsecureConnection: true, - }) - if err != nil { - t.Fatal("Cannot connect: ", err) - } - return d -} - func getVM(t *testing.T, d *driver.Driver, artifacts []packer.Artifact) *driver.VirtualMachine { artifactRaw := artifacts[0] artifact, _ := artifactRaw.(*Artifact) diff --git a/driver/test.sh b/driver/test.sh new file mode 100755 index 000000000..a2bf973cb --- /dev/null +++ b/driver/test.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +export VSPHERE_DRIVER_ACC=1 +cd testing +go test -v "$@" diff --git a/driver/testing/config.go b/driver/testing/config.go new file mode 100644 index 000000000..947aeb90e --- /dev/null +++ b/driver/testing/config.go @@ -0,0 +1,19 @@ +package testing + +// Defines whether acceptance tests should be run +const TestEnvVar = "VSPHERE_DRIVER_ACC" + +// Describe the environment to run tests in +const DefaultDatastore = "datastore1" +const DefaultTemplate = "alpine" +const DefaultHost = "esxi-1.vsphere55.test" +const DefaultVCenterServer = "vcenter.vsphere55.test" +const DefaultVCenterUsername = "root" +const DefaultVCenterPassword = "jetbrains" + +// Default hardware settings for +const DefaultCPUs = 2 +const DefaultCPUReservation = 1000 +const DefaultCPULimit = 1500 +const DefaultRAM = 2048 +const DefaultRAMReservation = 1024 diff --git a/driver/testing/datastore_acc_test.go b/driver/testing/datastore_acc_test.go new file mode 100644 index 000000000..5434e3730 --- /dev/null +++ b/driver/testing/datastore_acc_test.go @@ -0,0 +1,30 @@ +package testing + +import ( + "testing" +) + +var infoParams = [][]string { + //{}, // FIXME: Doesn't work + //{"*"}, // FIXME: Doesn't work + {"host", "vm"}, // TODO: choose something more meaningful +} + +func TestDatastore(t *testing.T) { + initDriverAcceptanceTest(t) + + d := NewTestDriver(t) + ds, err := d.FindDatastore(DefaultDatastore) + if err != nil { + t.Fatalf("`FindDatatore` can't find default datastore '%v'. Error: %v", + DefaultDatastore, err) + } + for _, params := range infoParams { + _, err := ds.Info(params...) + if err != nil { + t.Errorf("Cannot read datastore properties with parameters %v: %v", + params, err) + } + } + // TODO: add more checks +} diff --git a/driver/testing/utility.go b/driver/testing/utility.go new file mode 100644 index 000000000..8b2e007e7 --- /dev/null +++ b/driver/testing/utility.go @@ -0,0 +1,142 @@ +package testing + +import ( + "fmt" + "github.com/jetbrains-infra/packer-builder-vsphere/driver" + "math/rand" + "os" + "testing" + "time" +) + +func NewTestDriver(t *testing.T) *driver.Driver { + d, err := driver.NewDriver(&driver.ConnectConfig{ + VCenterServer: DefaultVCenterServer, + Username: DefaultVCenterUsername, + Password: DefaultVCenterPassword, + InsecureConnection: true, + }) + if err != nil { + t.Fatal("Cannot connect: ", err) + } + return d +} + +func NewVMName() string { + rand.Seed(time.Now().UTC().UnixNano()) + return fmt.Sprintf("test-%v", rand.Intn(1000)) +} + +func CheckDatastoreName(t *testing.T, ds *driver.Datastore, name string) { + info, err := ds.Info("name") + if err != nil { + t.Fatalf("Cannot read datastore properties: %v", err) + } + if info.Name != name { + t.Errorf("Wrong datastore. expected: %v, got: %v", name, info.Name) + } +} + +func initDriverAcceptanceTest(t *testing.T) { + // We only run acceptance tests if an env var is set because they're + // slow and require outside configuration. + if os.Getenv(TestEnvVar) == "" { + t.Skip(fmt.Sprintf( + "Acceptance tests skipped unless env '%s' set", + TestEnvVar)) + } + + // We require verbose mode so that the user knows what is going on. + if !testing.Verbose() { + t.Fatal("Acceptance tests must be run with the -v flag on tests") + } +} + +func VMCheckDefault(t *testing.T, d *driver.Driver, vm *driver.VirtualMachine, + name string, host string, datastore string) error { + vmInfo, err := vm.Info("name", "parent", "runtime.host", "resourcePool", "datastore", "layoutEx.disk") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) + } + + if vmInfo.Name != name { + t.Errorf("Invalid VM name: expected '%v', got '%v'", name, vmInfo.Name) + } + + f := d.NewFolder(vmInfo.Parent) + folderPath, err := f.Path() + if err != nil { + t.Fatalf("Cannot read folder name: %v", err) + } + if folderPath != "" { + t.Errorf("Invalid folder: expected '/', got '%v'", folderPath) + } + + h := d.NewHost(vmInfo.Runtime.Host) + hostInfo, err := h.Info("name") + if err != nil { + t.Fatal("Cannot read host properties: ", err) + } + if hostInfo.Name != host { + t.Errorf("Invalid host name: expected '%v', got '%v'", host, hostInfo.Name) + } + + p := d.NewResourcePool(vmInfo.ResourcePool) + poolPath, err := p.Path() + if err != nil { + t.Fatalf("Cannot read resource pool name: %v", err) + } + if poolPath != "" { + t.Error("Invalid resource pool: expected '/', got '%v'", poolPath) + } + + dsr := vmInfo.Datastore[0].Reference() + ds := d.NewDatastore(&dsr) + dsInfo, err := ds.Info("name") + if err != nil { + t.Fatal("Cannot read datastore properties: ", err) + } + if dsInfo.Name != datastore { + t.Errorf("Invalid datastore name: expected '%v', got '%v'", datastore, dsInfo.Name) + } + + if len(vmInfo.LayoutEx.Disk[0].Chain) != 1 { + t.Error("Not a full clone") + } + + return nil +} + +func VMCheckHardware(t* testing.T, d *driver.Driver, vm *driver.VirtualMachine) error { + vmInfo, err := vm.Info("config") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) + } + + cpuSockets := vmInfo.Config.Hardware.NumCPU + if cpuSockets != 2 { + t.Errorf("VM should have 2 CPU sockets, got %v", cpuSockets) + } + + cpuReservation := vmInfo.Config.CpuAllocation.GetResourceAllocationInfo().Reservation + if cpuReservation != 1000 { + t.Errorf("VM should have CPU reservation for 1000 Mhz, got %v", cpuReservation) + } + + cpuLimit := vmInfo.Config.CpuAllocation.GetResourceAllocationInfo().Limit + if cpuLimit != 1500 { + t.Errorf("VM should have CPU reservation for 1500 Mhz, got %v", cpuLimit) + } + + ram := vmInfo.Config.Hardware.MemoryMB + if ram != 2048 { + t.Errorf("VM should have 2048 MB of RAM, got %v", ram) + } + + ramReservation := vmInfo.Config.MemoryAllocation.GetResourceAllocationInfo().Reservation + if ramReservation != 1024 { + t.Errorf("VM should have RAM reservation for 1024 MB, got %v", ramReservation) + } + + return nil +} diff --git a/driver/testing/vm_acc_test.go b/driver/testing/vm_acc_test.go new file mode 100644 index 000000000..7f93ce59d --- /dev/null +++ b/driver/testing/vm_acc_test.go @@ -0,0 +1,131 @@ +package testing + +import ( + "github.com/jetbrains-infra/packer-builder-vsphere/driver" + "log" + "testing" + "net" + "time" +) + +func initVMAccTest(t *testing.T) (d *driver.Driver, vm *driver.VirtualMachine, vmName string, vmDestructor func()) { + initDriverAcceptanceTest(t) + d = NewTestDriver(t) + + template, err := d.FindVM(DefaultTemplate) // Don't destroy this VM! + if err != nil { + t.Fatalf("Cannot find template vm '%v': %v", DefaultTemplate, err) + } + + log.Printf("[DEBUG] Clonning VM") + vmName = NewVMName() + vm, err = template.Clone(&driver.CloneConfig{ + Name: vmName, + Host: DefaultHost, + }) + if err != nil { + t.Fatalf("Cannot clone vm '%v': %v", DefaultTemplate, err) + } + + vmDestructor = func() { + log.Printf("[DEBUG] Removing the clone") + if err := vm.Destroy(); err != nil { + t.Errorf("!!! ERROR REMOVING VM '%v': %v!!!", vmName, err) + } + + // Check that the clone is no longer exists + if _, err := d.FindVM(vmName); err == nil { + t.Errorf("!!! STILL CAN FIND VM '%v'. IT MIGHT NOT HAVE BEEN DELETED !!!", vmName) + } + } + + return +} + +func TestVMAcc_default(t *testing.T) { + d, vm, vmName, vmDestructor := initVMAccTest(t) + defer vmDestructor() + + // Check that the clone can be found by its name + if _, err := d.FindVM(vmName); err != nil { + t.Errorf("Cannot find created vm '%v': %v", vmName, err) + } + + // Run checks + log.Printf("[DEBUG] Running check function") + VMCheckDefault(t, d, vm, vmName, DefaultHost, DefaultDatastore) +} + +func TestVMAcc_hardware(t *testing.T) { + d, vm, _ /*vmName*/, vmDestructor := initVMAccTest(t) + defer vmDestructor() + + log.Printf("[DEBUG] Configuring the vm") + vm.Configure(&driver.HardwareConfig{ + CPUs: DefaultCPUs, + CPUReservation: DefaultCPUReservation, + CPULimit: DefaultCPULimit, + RAM: DefaultRAM, + RAMReservation: DefaultRAMReservation, + }) + log.Printf("[DEBUG] Running check function") + VMCheckHardware(t, d, vm) +} + +func startVM(t *testing.T, vm *driver.VirtualMachine, vmName string) (stopper func()) { + log.Printf("[DEBUG] Starting the vm") + if err := vm.PowerOn(); err != nil { + t.Fatalf("Cannot start created vm '%v': %v", vmName, err) + } + return func() { + log.Printf("[DEBUG] Powering off the vm") + if err := vm.PowerOff(); err != nil { + t.Errorf("Cannot power off started vm '%v': %v", vmName, err) + } + } +} + +func TestVMAcc_running(t *testing.T) { + _ /*d*/, vm, vmName, vmDestructor := initVMAccTest(t) + defer vmDestructor() + + stopper := startVM(t, vm, vmName) + defer stopper() + + switch ip, err := vm.WaitForIP(); { + case err != nil: + t.Errorf("Cannot obtain IP address from created vm '%v': %v", vmName, err) + case net.ParseIP(ip) == nil: + t.Errorf("'%v' is not a valid ip address", ip) + } + + vm.StartShutdown() + log.Printf("[DEBUG] Waiting max 1m0s for shutdown to complete") + // TODO: there is complex logic in WaitForShutdown. It's better to test it well. It might be reasonable to create + // unit tests for it. + vm.WaitForShutdown(1 * time.Minute) +} + +func TestVMAcc_running_snapshot(t *testing.T) { + _ /*d*/, vm, vmName, vmDestructor := initVMAccTest(t) + defer vmDestructor() + + stopper := startVM(t, vm, vmName) + defer stopper() + + vm.CreateSnapshot("test-snapshot") + // TODO: check +} + +func TestVMAcc_template(t *testing.T) { + _ /*d*/, vm, vmName, vmDestructor := initVMAccTest(t) + defer vmDestructor() + + vm.ConvertToTemplate() + switch info, err := vm.Info("config"); { + case err != nil: + t.Fatalf("Cannot read VM properties for '%v': %v", vmName, err) + case !info.Config.Template: + t.Fatalf("'%v' seems not to be a template", vmName) + } +} diff --git a/driver/vm.go b/driver/vm.go index 0457690df..967264fc9 100644 --- a/driver/vm.go +++ b/driver/vm.go @@ -183,11 +183,7 @@ func (vm *VirtualMachine) PowerOn() error { } func (vm *VirtualMachine) WaitForIP() (string, error) { - ip, err := vm.vm.WaitForIP(vm.driver.ctx) - if err != nil { - return "", err - } - return ip, nil + return vm.vm.WaitForIP(vm.driver.ctx) } func (vm *VirtualMachine) PowerOff() error { @@ -245,6 +241,5 @@ func (vm *VirtualMachine) CreateSnapshot(name string) error { } func (vm *VirtualMachine) ConvertToTemplate() error { - err := vm.vm.MarkAsTemplate(vm.driver.ctx) - return err + return vm.vm.MarkAsTemplate(vm.driver.ctx) } diff --git a/test.sh b/test.sh index 0c7683736..dd91fee3a 100755 --- a/test.sh +++ b/test.sh @@ -1,4 +1,4 @@ #!/bin/sh export PACKER_ACC=1 -go test -v +go test -v "$@" From d154a0ff32aef69332357cfe038c4afd7f0c939f Mon Sep 17 00:00:00 2001 From: Andrey Tonkikh Date: Wed, 25 Oct 2017 23:54:13 +0300 Subject: [PATCH 03/12] Improve `TestVMAcc_running_snapshot` and `TestVMAcc_template` --- builder_acc_test.go | 112 +++++++++------------------------- driver/testing/utility.go | 90 +++++++++++++++++---------- driver/testing/vm_acc_test.go | 13 ++-- 3 files changed, 92 insertions(+), 123 deletions(-) diff --git a/builder_acc_test.go b/builder_acc_test.go index ab51d4ade..b33de8d95 100644 --- a/builder_acc_test.go +++ b/builder_acc_test.go @@ -1,12 +1,12 @@ package main import ( - "testing" + "encoding/json" builderT "github.com/hashicorp/packer/helper/builder/testing" "github.com/hashicorp/packer/packer" - "encoding/json" "github.com/jetbrains-infra/packer-builder-vsphere/driver" driverT "github.com/jetbrains-infra/packer-builder-vsphere/driver/testing" + "testing" ) func TestBuilderAcc_default(t *testing.T) { @@ -14,7 +14,12 @@ func TestBuilderAcc_default(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, Template: renderConfig(config), - Check: checkDefault(t, config["vm_name"].(string), config["host"].(string), "datastore1"), + Check: func(artifacts []packer.Artifact) error { + d := driverT.NewTestDriver(t) + driverT.VMCheckDefault(t, d, getVM(t, d, artifacts), config["vm_name"].(string), + config["host"].(string), driverT.DefaultDatastore) + return nil + }, }) } @@ -35,14 +40,6 @@ func defaultConfig() map[string]interface{} { return config } -func checkDefault(t *testing.T, name string, host string, datastore string) builderT.TestCheckFunc { - return func(artifacts []packer.Artifact) error { - d := driverT.NewTestDriver(t) - vm := getVM(t, d, artifacts) - return driverT.VMCheckDefault(t, d, vm, name, host, datastore) - } -} - func TestBuilderAcc_artifact(t *testing.T) { config := defaultConfig() builderT.Test(t, builderT.TestCase{ @@ -149,7 +146,11 @@ func TestBuilderAcc_datastore(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, Template: datastoreConfig(), - Check: checkDatastore(t, "datastore1"), // on esxi-1.vsphere55.test + Check: func(artifacts []packer.Artifact) error { + d := driverT.NewTestDriver(t) + driverT.VMCheckDatastore(t, d, getVM(t, d, artifacts), driverT.DefaultDatastore) + return nil + }, }) } @@ -159,30 +160,8 @@ func datastoreConfig() string { return renderConfig(config) } -func checkDatastore(t *testing.T, name string) builderT.TestCheckFunc { - return func(artifacts []packer.Artifact) error { - d := driverT.NewTestDriver(t) - vm := getVM(t, d, artifacts) - - vmInfo, err := vm.Info("datastore") - if err != nil { - t.Fatalf("Cannot read VM properties: %v", err) - } - - n := len(vmInfo.Datastore) - if n != 1 { - t.Fatalf("VM should have 1 datastore, got %v", n) - } - - ds := d.NewDatastore(&vmInfo.Datastore[0]) - driverT.CheckDatastoreName(t, ds, name) - - return nil - } -} - func TestBuilderAcc_multipleDatastores(t *testing.T) { - t.Skip("test must fail") // FIXME + t.Skip("test must fail") builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, @@ -232,7 +211,11 @@ func TestBuilderAcc_hardware(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, Template: hardwareConfig(), - Check: checkHardware(t), + Check: func(artifacts []packer.Artifact) error { + d := driverT.NewTestDriver(t) + driverT.VMCheckHardware(t, d, getVM(t, d, artifacts)) + return nil + }, }) } @@ -248,14 +231,6 @@ func hardwareConfig() string { return renderConfig(config) } -func checkHardware(t *testing.T) builderT.TestCheckFunc { - return func(artifacts []packer.Artifact) error { - d := driverT.NewTestDriver(t) - vm := getVM(t, d, artifacts) - return driverT.VMCheckHardware(t, d, vm) - } -} - func TestBuilderAcc_RAMReservation(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, @@ -309,7 +284,11 @@ func TestBuilderAcc_snapshot(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, Template: snapshotConfig(), - Check: checkSnapshot(t), + Check: func(artifacts []packer.Artifact) error { + d := driverT.NewTestDriver(t) + driverT.VMCheckSnapshor(t, d, getVM(t, d, artifacts)) + return nil + }, }) } @@ -319,30 +298,15 @@ func snapshotConfig() string { return renderConfig(config) } -func checkSnapshot(t *testing.T) builderT.TestCheckFunc { - return func(artifacts []packer.Artifact) error { - d := driverT.NewTestDriver(t) - - vm := getVM(t, d, artifacts) - vmInfo, err := vm.Info("layoutEx.disk") - if err != nil { - t.Fatalf("Cannot read VM properties: %v", err) - } - - layers := len(vmInfo.LayoutEx.Disk[0].Chain) - if layers != 2 { - t.Errorf("VM should have a single snapshot. expected 2 disk layers, got %v", layers) - } - - return nil - } -} - func TestBuilderAcc_template(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, Template: templateConfig(), - Check: checkTemplate(t), + Check: func(artifacts []packer.Artifact) error { + d := driverT.NewTestDriver(t) + driverT.VMCheckTemplate(t, d, getVM(t, d, artifacts)) + return nil + }, }) } @@ -353,24 +317,6 @@ func templateConfig() string { return renderConfig(config) } -func checkTemplate(t *testing.T) builderT.TestCheckFunc { - return func(artifacts []packer.Artifact) error { - d := driverT.NewTestDriver(t) - - vm := getVM(t, d, artifacts) - vmInfo, err := vm.Info("config.template") - if err != nil { - t.Fatalf("Cannot read VM properties: %v", err) - } - - if vmInfo.Config.Template != true { - t.Error("Not a template") - } - - return nil - } -} - func renderConfig(config map[string]interface{}) string { t := map[string][]map[string]interface{}{ "builders": { diff --git a/driver/testing/utility.go b/driver/testing/utility.go index 8b2e007e7..3c1170ebd 100644 --- a/driver/testing/utility.go +++ b/driver/testing/utility.go @@ -17,7 +17,7 @@ func NewTestDriver(t *testing.T) *driver.Driver { InsecureConnection: true, }) if err != nil { - t.Fatal("Cannot connect: ", err) + t.Fatalf("Cannot connect: %v", err) } return d } @@ -28,11 +28,10 @@ func NewVMName() string { } func CheckDatastoreName(t *testing.T, ds *driver.Datastore, name string) { - info, err := ds.Info("name") - if err != nil { - t.Fatalf("Cannot read datastore properties: %v", err) - } - if info.Name != name { + switch info, err := ds.Info("name"); { + case err != nil: + t.Errorf("Cannot read datastore properties: %v", err) + case info.Name != name: t.Errorf("Wrong datastore. expected: %v, got: %v", name, info.Name) } } @@ -53,7 +52,7 @@ func initDriverAcceptanceTest(t *testing.T) { } func VMCheckDefault(t *testing.T, d *driver.Driver, vm *driver.VirtualMachine, - name string, host string, datastore string) error { + name string, host string, datastore string) { vmInfo, err := vm.Info("name", "parent", "runtime.host", "resourcePool", "datastore", "layoutEx.disk") if err != nil { t.Fatalf("Cannot read VM properties: %v", err) @@ -64,50 +63,45 @@ func VMCheckDefault(t *testing.T, d *driver.Driver, vm *driver.VirtualMachine, } f := d.NewFolder(vmInfo.Parent) - folderPath, err := f.Path() - if err != nil { - t.Fatalf("Cannot read folder name: %v", err) - } - if folderPath != "" { + switch folderPath, err := f.Path(); { + case err != nil: + t.Errorf("Cannot read folder name: %v", err) + case folderPath != "": t.Errorf("Invalid folder: expected '/', got '%v'", folderPath) } h := d.NewHost(vmInfo.Runtime.Host) - hostInfo, err := h.Info("name") - if err != nil { - t.Fatal("Cannot read host properties: ", err) - } - if hostInfo.Name != host { + switch hostInfo, err := h.Info("name"); { + case err != nil: + t.Errorf("Cannot read host properties: %v", err) + case hostInfo.Name != host: t.Errorf("Invalid host name: expected '%v', got '%v'", host, hostInfo.Name) } p := d.NewResourcePool(vmInfo.ResourcePool) - poolPath, err := p.Path() - if err != nil { - t.Fatalf("Cannot read resource pool name: %v", err) - } - if poolPath != "" { + switch poolPath, err := p.Path(); { + case err != nil: + t.Errorf("Cannot read resource pool name: %v", err) + case poolPath != "": t.Error("Invalid resource pool: expected '/', got '%v'", poolPath) } + dsr := vmInfo.Datastore[0].Reference() ds := d.NewDatastore(&dsr) - dsInfo, err := ds.Info("name") - if err != nil { - t.Fatal("Cannot read datastore properties: ", err) - } - if dsInfo.Name != datastore { + switch dsInfo, err := ds.Info("name"); { + case err != nil: + t.Errorf("Cannot read datastore properties: %v", err) + case dsInfo.Name != datastore: t.Errorf("Invalid datastore name: expected '%v', got '%v'", datastore, dsInfo.Name) } if len(vmInfo.LayoutEx.Disk[0].Chain) != 1 { t.Error("Not a full clone") } - - return nil } -func VMCheckHardware(t* testing.T, d *driver.Driver, vm *driver.VirtualMachine) error { +func VMCheckHardware(t* testing.T, d *driver.Driver, vm *driver.VirtualMachine) { vmInfo, err := vm.Info("config") if err != nil { t.Fatalf("Cannot read VM properties: %v", err) @@ -137,6 +131,40 @@ func VMCheckHardware(t* testing.T, d *driver.Driver, vm *driver.VirtualMachine) if ramReservation != 1024 { t.Errorf("VM should have RAM reservation for 1024 MB, got %v", ramReservation) } +} - return nil +func VMCheckTemplate(t* testing.T, d *driver.Driver, vm *driver.VirtualMachine) { + switch vmInfo, err := vm.Info("config.template"); { + case err != nil: + t.Errorf("Cannot read VM properties: %v", err) + case !vmInfo.Config.Template: + t.Error("Not a template") + } +} + +func VMCheckDatastore(t* testing.T, d *driver.Driver, vm *driver.VirtualMachine, name string) { + vmInfo, err := vm.Info("datastore") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) + } + + n := len(vmInfo.Datastore) + if n != 1 { + t.Fatalf("VM should have 1 datastore, got %v", n) + } + + ds := d.NewDatastore(&vmInfo.Datastore[0]) + CheckDatastoreName(t, ds, name) +} + +func VMCheckSnapshor(t* testing.T, d *driver.Driver, vm *driver.VirtualMachine) { + vmInfo, err := vm.Info("layoutEx.disk") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) + } + + layers := len(vmInfo.LayoutEx.Disk[0].Chain) + if layers != 2 { + t.Errorf("VM should have a single snapshot. expected 2 disk layers, got %v", layers) + } } diff --git a/driver/testing/vm_acc_test.go b/driver/testing/vm_acc_test.go index 7f93ce59d..b216a7c48 100644 --- a/driver/testing/vm_acc_test.go +++ b/driver/testing/vm_acc_test.go @@ -107,25 +107,20 @@ func TestVMAcc_running(t *testing.T) { } func TestVMAcc_running_snapshot(t *testing.T) { - _ /*d*/, vm, vmName, vmDestructor := initVMAccTest(t) + d, vm, vmName, vmDestructor := initVMAccTest(t) defer vmDestructor() stopper := startVM(t, vm, vmName) defer stopper() vm.CreateSnapshot("test-snapshot") - // TODO: check + VMCheckSnapshor(t, d, vm) } func TestVMAcc_template(t *testing.T) { - _ /*d*/, vm, vmName, vmDestructor := initVMAccTest(t) + d, vm, _ /*vmName*/, vmDestructor := initVMAccTest(t) defer vmDestructor() vm.ConvertToTemplate() - switch info, err := vm.Info("config"); { - case err != nil: - t.Fatalf("Cannot read VM properties for '%v': %v", vmName, err) - case !info.Config.Template: - t.Fatalf("'%v' seems not to be a template", vmName) - } + VMCheckTemplate(t, d, vm) } From dc5a2e52cd37eab787a305afd8c9d5f227769458 Mon Sep 17 00:00:00 2001 From: Andrey Tonkikh Date: Thu, 26 Oct 2017 00:38:33 +0300 Subject: [PATCH 04/12] Simplify datastore test --- driver/testing/datastore_acc_test.go | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/driver/testing/datastore_acc_test.go b/driver/testing/datastore_acc_test.go index 5434e3730..ca0bcb726 100644 --- a/driver/testing/datastore_acc_test.go +++ b/driver/testing/datastore_acc_test.go @@ -2,29 +2,17 @@ package testing import ( "testing" + "github.com/vmware/govmomi/vim25/mo" + "github.com/jetbrains-infra/packer-builder-vsphere/driver" ) -var infoParams = [][]string { - //{}, // FIXME: Doesn't work - //{"*"}, // FIXME: Doesn't work - {"host", "vm"}, // TODO: choose something more meaningful -} - -func TestDatastore(t *testing.T) { +func TestDatastoreAcc(t *testing.T) { initDriverAcceptanceTest(t) d := NewTestDriver(t) ds, err := d.FindDatastore(DefaultDatastore) if err != nil { - t.Fatalf("`FindDatatore` can't find default datastore '%v'. Error: %v", - DefaultDatastore, err) - } - for _, params := range infoParams { - _, err := ds.Info(params...) - if err != nil { - t.Errorf("Cannot read datastore properties with parameters %v: %v", - params, err) - } + t.Fatalf("Cannot find default datastore '%v': %v", DefaultDatastore, err) } - // TODO: add more checks + CheckDatastoreName(t, ds, DefaultDatastore) } From d33ffc178d80b860d8f38dfa5c597a76e65f9af9 Mon Sep 17 00:00:00 2001 From: Andrey Tonkikh Date: Thu, 26 Oct 2017 00:51:54 +0300 Subject: [PATCH 05/12] Add an acceptance test for `driver.ResourcePool` --- builder_acc_test.go | 43 ++++++++++-------------- driver/testing/config.go | 27 ++++++++------- driver/testing/datastore_acc_test.go | 8 ++--- driver/testing/resource_pool_acc_test.go | 14 ++++++++ driver/testing/utility.go | 18 ++++++++-- driver/testing/vm_acc_test.go | 20 +++++------ 6 files changed, 74 insertions(+), 56 deletions(-) create mode 100644 driver/testing/resource_pool_acc_test.go diff --git a/builder_acc_test.go b/builder_acc_test.go index b33de8d95..0d7e77f6c 100644 --- a/builder_acc_test.go +++ b/builder_acc_test.go @@ -17,7 +17,7 @@ func TestBuilderAcc_default(t *testing.T) { Check: func(artifacts []packer.Artifact) error { d := driverT.NewTestDriver(t) driverT.VMCheckDefault(t, d, getVM(t, d, artifacts), config["vm_name"].(string), - config["host"].(string), driverT.DefaultDatastore) + config["host"].(string), driverT.TestDatastore) return nil }, }) @@ -25,13 +25,13 @@ func TestBuilderAcc_default(t *testing.T) { func defaultConfig() map[string]interface{} { config := map[string]interface{}{ - "vcenter_server": driverT.DefaultVCenterServer, - "username": driverT.DefaultVCenterUsername, - "password": driverT.DefaultVCenterPassword, + "vcenter_server": driverT.TestVCenterServer, + "username": driverT.TestVCenterUsername, + "password": driverT.TestVCenterPassword, "insecure_connection": true, - "template": driverT.DefaultTemplate, - "host": driverT.DefaultHost, + "template": driverT.TestTemplate, + "host": driverT.TestHost, "ssh_username": "root", "ssh_password": "jetbrains", @@ -69,13 +69,13 @@ func TestBuilderAcc_folder(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, Template: folderConfig(), - Check: checkFolder(t, "folder1/folder2"), + Check: checkFolder(t, driverT.TestFolder), }) } func folderConfig() string { config := defaultConfig() - config["folder"] = "folder1/folder2" + config["folder"] = driverT.TestFolder config["linked_clone"] = true // speed up return renderConfig(config) } @@ -107,13 +107,13 @@ func TestBuilderAcc_resourcePool(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, Template: resourcePoolConfig(), - Check: checkResourcePool(t, "pool1/pool2"), + Check: checkResourcePool(t, driverT.TestResourcePool), }) } func resourcePoolConfig() string { config := defaultConfig() - config["resource_pool"] = "pool1/pool2" + config["resource_pool"] = driverT.TestResourcePool config["linked_clone"] = true // speed up return renderConfig(config) } @@ -128,27 +128,18 @@ func checkResourcePool(t *testing.T, pool string) builderT.TestCheckFunc { t.Fatalf("Cannot read VM properties: %v", err) } - p := d.NewResourcePool(vmInfo.ResourcePool) - path, err := p.Path() - if err != nil { - t.Fatalf("Cannot read resource pool name: %v", err) - } - if path != pool { - t.Errorf("Wrong folder. expected: %v, got: %v", pool, path) - } - + driverT.CheckResourcePoolPath(t, d.NewResourcePool(vmInfo.ResourcePool), pool) return nil } } -// FIXME: why do we need this??? Why don't perform these checks in checkDefault? func TestBuilderAcc_datastore(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, Template: datastoreConfig(), Check: func(artifacts []packer.Artifact) error { d := driverT.NewTestDriver(t) - driverT.VMCheckDatastore(t, d, getVM(t, d, artifacts), driverT.DefaultDatastore) + driverT.VMCheckDatastore(t, d, getVM(t, d, artifacts), driverT.TestDatastore) return nil }, }) @@ -221,11 +212,11 @@ func TestBuilderAcc_hardware(t *testing.T) { func hardwareConfig() string { config := defaultConfig() - config["CPUs"] = driverT.DefaultCPUs - config["CPU_reservation"] = driverT.DefaultCPUReservation - config["CPU_limit"] = driverT.DefaultCPULimit - config["RAM"] = driverT.DefaultRAM - config["RAM_reservation"] = driverT.DefaultRAMReservation + config["CPUs"] = driverT.TestCPUs + config["CPU_reservation"] = driverT.TestCPUReservation + config["CPU_limit"] = driverT.TestCPULimit + config["RAM"] = driverT.TestRAM + config["RAM_reservation"] = driverT.TestRAMReservation config["linked_clone"] = true // speed up return renderConfig(config) diff --git a/driver/testing/config.go b/driver/testing/config.go index 947aeb90e..9e085dd6c 100644 --- a/driver/testing/config.go +++ b/driver/testing/config.go @@ -4,16 +4,19 @@ package testing const TestEnvVar = "VSPHERE_DRIVER_ACC" // Describe the environment to run tests in -const DefaultDatastore = "datastore1" -const DefaultTemplate = "alpine" -const DefaultHost = "esxi-1.vsphere55.test" -const DefaultVCenterServer = "vcenter.vsphere55.test" -const DefaultVCenterUsername = "root" -const DefaultVCenterPassword = "jetbrains" +const TestDatastore = "datastore1" +const TestTemplate = "alpine" +const TestHost = "esxi-1.vsphere55.test" +const TestVCenterServer = "vcenter.vsphere55.test" +const TestVCenterUsername = "root" +const TestVCenterPassword = "jetbrains" -// Default hardware settings for -const DefaultCPUs = 2 -const DefaultCPUReservation = 1000 -const DefaultCPULimit = 1500 -const DefaultRAM = 2048 -const DefaultRAMReservation = 1024 +// For test of hardware settings +const TestCPUs = 2 +const TestCPUReservation = 1000 +const TestCPULimit = 1500 +const TestRAM = 2048 +const TestRAMReservation = 1024 + +const TestFolder = "folder1/folder2" +const TestResourcePool = "pool1/pool2" diff --git a/driver/testing/datastore_acc_test.go b/driver/testing/datastore_acc_test.go index ca0bcb726..17eecf1ee 100644 --- a/driver/testing/datastore_acc_test.go +++ b/driver/testing/datastore_acc_test.go @@ -2,17 +2,15 @@ package testing import ( "testing" - "github.com/vmware/govmomi/vim25/mo" - "github.com/jetbrains-infra/packer-builder-vsphere/driver" ) func TestDatastoreAcc(t *testing.T) { initDriverAcceptanceTest(t) d := NewTestDriver(t) - ds, err := d.FindDatastore(DefaultDatastore) + ds, err := d.FindDatastore(TestDatastore) if err != nil { - t.Fatalf("Cannot find default datastore '%v': %v", DefaultDatastore, err) + t.Fatalf("Cannot find the default datastore '%v': %v", TestDatastore, err) } - CheckDatastoreName(t, ds, DefaultDatastore) + CheckDatastoreName(t, ds, TestDatastore) } diff --git a/driver/testing/resource_pool_acc_test.go b/driver/testing/resource_pool_acc_test.go new file mode 100644 index 000000000..7b6177f90 --- /dev/null +++ b/driver/testing/resource_pool_acc_test.go @@ -0,0 +1,14 @@ +package testing + +import "testing" + +func TestResourcePoolAcc(t *testing.T) { + initDriverAcceptanceTest(t) + + d := NewTestDriver(t) + p, err := d.FindResourcePool(TestHost, TestResourcePool) + if err != nil { + t.Fatalf("Cannot find the default resource pool '%v': %v", TestResourcePool, err) + } + CheckResourcePoolPath(t, p, TestResourcePool) +} diff --git a/driver/testing/utility.go b/driver/testing/utility.go index 3c1170ebd..97ea812e6 100644 --- a/driver/testing/utility.go +++ b/driver/testing/utility.go @@ -7,13 +7,14 @@ import ( "os" "testing" "time" + "github.com/vmware/govmomi/govc/pool" ) func NewTestDriver(t *testing.T) *driver.Driver { d, err := driver.NewDriver(&driver.ConnectConfig{ - VCenterServer: DefaultVCenterServer, - Username: DefaultVCenterUsername, - Password: DefaultVCenterPassword, + VCenterServer: TestVCenterServer, + Username: TestVCenterUsername, + Password: TestVCenterPassword, InsecureConnection: true, }) if err != nil { @@ -36,6 +37,15 @@ func CheckDatastoreName(t *testing.T, ds *driver.Datastore, name string) { } } +func CheckResourcePoolPath(t *testing.T, p *driver.ResourcePool, pool string) { + switch path, err := p.Path(); { + case err != nil: + t.Errorf("Cannot read resource pool name: %v", err) + case path != pool: + t.Errorf("Wrong folder. expected: %v, got: %v", pool, path) + } +} + func initDriverAcceptanceTest(t *testing.T) { // We only run acceptance tests if an env var is set because they're // slow and require outside configuration. @@ -168,3 +178,5 @@ func VMCheckSnapshor(t* testing.T, d *driver.Driver, vm *driver.VirtualMachine) t.Errorf("VM should have a single snapshot. expected 2 disk layers, got %v", layers) } } + + diff --git a/driver/testing/vm_acc_test.go b/driver/testing/vm_acc_test.go index b216a7c48..594430ff2 100644 --- a/driver/testing/vm_acc_test.go +++ b/driver/testing/vm_acc_test.go @@ -12,19 +12,19 @@ func initVMAccTest(t *testing.T) (d *driver.Driver, vm *driver.VirtualMachine, v initDriverAcceptanceTest(t) d = NewTestDriver(t) - template, err := d.FindVM(DefaultTemplate) // Don't destroy this VM! + template, err := d.FindVM(TestTemplate) // Don't destroy this VM! if err != nil { - t.Fatalf("Cannot find template vm '%v': %v", DefaultTemplate, err) + t.Fatalf("Cannot find template vm '%v': %v", TestTemplate, err) } log.Printf("[DEBUG] Clonning VM") vmName = NewVMName() vm, err = template.Clone(&driver.CloneConfig{ Name: vmName, - Host: DefaultHost, + Host: TestHost, }) if err != nil { - t.Fatalf("Cannot clone vm '%v': %v", DefaultTemplate, err) + t.Fatalf("Cannot clone vm '%v': %v", TestTemplate, err) } vmDestructor = func() { @@ -53,7 +53,7 @@ func TestVMAcc_default(t *testing.T) { // Run checks log.Printf("[DEBUG] Running check function") - VMCheckDefault(t, d, vm, vmName, DefaultHost, DefaultDatastore) + VMCheckDefault(t, d, vm, vmName, TestHost, TestDatastore) } func TestVMAcc_hardware(t *testing.T) { @@ -62,11 +62,11 @@ func TestVMAcc_hardware(t *testing.T) { log.Printf("[DEBUG] Configuring the vm") vm.Configure(&driver.HardwareConfig{ - CPUs: DefaultCPUs, - CPUReservation: DefaultCPUReservation, - CPULimit: DefaultCPULimit, - RAM: DefaultRAM, - RAMReservation: DefaultRAMReservation, + CPUs: TestCPUs, + CPUReservation: TestCPUReservation, + CPULimit: TestCPULimit, + RAM: TestRAM, + RAMReservation: TestRAMReservation, }) log.Printf("[DEBUG] Running check function") VMCheckHardware(t, d, vm) From 23c6951aa411a8a965a99d7c4e462e8e51e460fd Mon Sep 17 00:00:00 2001 From: Andrey Tonkikh Date: Thu, 26 Oct 2017 01:04:44 +0300 Subject: [PATCH 06/12] Add an acceptance test for `driver.Folder` --- builder_acc_test.go | 8 +------- driver/testing/folder_acc_test.go | 14 ++++++++++++++ driver/testing/utility.go | 16 ++++++++++++---- 3 files changed, 27 insertions(+), 11 deletions(-) create mode 100644 driver/testing/folder_acc_test.go diff --git a/builder_acc_test.go b/builder_acc_test.go index 0d7e77f6c..a18e8d5f0 100644 --- a/builder_acc_test.go +++ b/builder_acc_test.go @@ -91,13 +91,7 @@ func checkFolder(t *testing.T, folder string) builderT.TestCheckFunc { } f := d.NewFolder(vmInfo.Parent) - path, err := f.Path() - if err != nil { - t.Fatalf("Cannot read folder name: %v", err) - } - if path != folder { - t.Errorf("Wrong folder. expected: %v, got: %v", folder, path) - } + driverT.CheckFolderPath(t, f, folder) return nil } diff --git a/driver/testing/folder_acc_test.go b/driver/testing/folder_acc_test.go new file mode 100644 index 000000000..fc436d0a1 --- /dev/null +++ b/driver/testing/folder_acc_test.go @@ -0,0 +1,14 @@ +package testing + +import "testing" + +func TestFolderAcc(t *testing.T) { + initDriverAcceptanceTest(t) + + d := NewTestDriver(t) + f, err := d.FindFolder(TestFolder) + if err != nil { + t.Fatalf("Cannot find the default folder '%v': %v", TestFolder, err) + } + CheckFolderPath(t, f, TestFolder) +} diff --git a/driver/testing/utility.go b/driver/testing/utility.go index 97ea812e6..a9d40e9a3 100644 --- a/driver/testing/utility.go +++ b/driver/testing/utility.go @@ -7,7 +7,6 @@ import ( "os" "testing" "time" - "github.com/vmware/govmomi/govc/pool" ) func NewTestDriver(t *testing.T) *driver.Driver { @@ -28,12 +27,12 @@ func NewVMName() string { return fmt.Sprintf("test-%v", rand.Intn(1000)) } -func CheckDatastoreName(t *testing.T, ds *driver.Datastore, name string) { +func CheckDatastoreName(t *testing.T, ds *driver.Datastore, datastore string) { switch info, err := ds.Info("name"); { case err != nil: t.Errorf("Cannot read datastore properties: %v", err) - case info.Name != name: - t.Errorf("Wrong datastore. expected: %v, got: %v", name, info.Name) + case info.Name != datastore: + t.Errorf("Wrong datastore. expected: %v, got: %v", datastore, info.Name) } } @@ -46,6 +45,15 @@ func CheckResourcePoolPath(t *testing.T, p *driver.ResourcePool, pool string) { } } +func CheckFolderPath(t *testing.T, f *driver.Folder, folder string) { + switch path, err := f.Path(); { + case err != nil: + t.Fatalf("Cannot read folder name: %v", err) + case path != folder: + t.Errorf("Wrong folder. expected: %v, got: %v", folder, path) + } +} + func initDriverAcceptanceTest(t *testing.T) { // We only run acceptance tests if an env var is set because they're // slow and require outside configuration. From 3cb2185c53e6558b17c44627d2957f31f04de641 Mon Sep 17 00:00:00 2001 From: Andrey Tonkikh Date: Thu, 26 Oct 2017 01:07:25 +0300 Subject: [PATCH 07/12] Add an acceptance test for `driver.Host` --- driver/testing/host_acc_test.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 driver/testing/host_acc_test.go diff --git a/driver/testing/host_acc_test.go b/driver/testing/host_acc_test.go new file mode 100644 index 000000000..247d3cdf6 --- /dev/null +++ b/driver/testing/host_acc_test.go @@ -0,0 +1,21 @@ +package testing + +import ( + "testing" +) + +func TestHostAcc(t *testing.T) { + initDriverAcceptanceTest(t) + + d := NewTestDriver(t) + host, err := d.FindHost(TestHost) + if err != nil { + t.Fatalf("Cannot find the default datastore '%v': %v", TestDatastore, err) + } + switch info, err := host.Info("name"); { + case err != nil: + t.Errorf("Cannot read datastore properties: %v", err) + case info.Name != TestHost: + t.Errorf("Wrong datastore. expected: %v, got: %v", TestHost, info.Name) + } +} From c41ee015379747afaa1100c897bcb9af43b5922b Mon Sep 17 00:00:00 2001 From: Andrey Tonkikh Date: Thu, 26 Oct 2017 19:15:54 +0300 Subject: [PATCH 08/12] Correct some error messages in tests --- driver/testing/host_acc_test.go | 6 +++--- driver/testing/utility.go | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/driver/testing/host_acc_test.go b/driver/testing/host_acc_test.go index 247d3cdf6..92b08cf69 100644 --- a/driver/testing/host_acc_test.go +++ b/driver/testing/host_acc_test.go @@ -10,12 +10,12 @@ func TestHostAcc(t *testing.T) { d := NewTestDriver(t) host, err := d.FindHost(TestHost) if err != nil { - t.Fatalf("Cannot find the default datastore '%v': %v", TestDatastore, err) + t.Fatalf("Cannot find the default host '%v': %v", TestDatastore, err) } switch info, err := host.Info("name"); { case err != nil: - t.Errorf("Cannot read datastore properties: %v", err) + t.Errorf("Cannot read host properties: %v", err) case info.Name != TestHost: - t.Errorf("Wrong datastore. expected: %v, got: %v", TestHost, info.Name) + t.Errorf("Wrong host name: expected '%v', got: '%v'", TestHost, info.Name) } } diff --git a/driver/testing/utility.go b/driver/testing/utility.go index a9d40e9a3..96d210370 100644 --- a/driver/testing/utility.go +++ b/driver/testing/utility.go @@ -32,25 +32,25 @@ func CheckDatastoreName(t *testing.T, ds *driver.Datastore, datastore string) { case err != nil: t.Errorf("Cannot read datastore properties: %v", err) case info.Name != datastore: - t.Errorf("Wrong datastore. expected: %v, got: %v", datastore, info.Name) + t.Errorf("Wrong name: expected '%v', got: '%v'", datastore, info.Name) } } func CheckResourcePoolPath(t *testing.T, p *driver.ResourcePool, pool string) { switch path, err := p.Path(); { case err != nil: - t.Errorf("Cannot read resource pool name: %v", err) + t.Errorf("Cannot read resource pool path: %v", err) case path != pool: - t.Errorf("Wrong folder. expected: %v, got: %v", pool, path) + t.Errorf("Wrong name: expected '%v', got: '%v'", pool, path) } } func CheckFolderPath(t *testing.T, f *driver.Folder, folder string) { switch path, err := f.Path(); { case err != nil: - t.Fatalf("Cannot read folder name: %v", err) + t.Fatalf("Cannot read folder path: %v", err) case path != folder: - t.Errorf("Wrong folder. expected: %v, got: %v", folder, path) + t.Errorf("Wrong path: expected '%v', got: '%v'", folder, path) } } From 7794c149a13c6aa1691b77056cc41ff98eb10108 Mon Sep 17 00:00:00 2001 From: Andrey Tonkikh Date: Wed, 8 Nov 2017 19:47:29 +0300 Subject: [PATCH 09/12] Inline test config --- builder_acc_test.go | 32 ++++++++++++------------ driver/testing/config.go | 22 ---------------- driver/testing/datastore_acc_test.go | 6 ++--- driver/testing/folder_acc_test.go | 6 ++--- driver/testing/host_acc_test.go | 9 ++++--- driver/testing/resource_pool_acc_test.go | 6 ++--- driver/testing/utility.go | 3 ++- driver/testing/vm_acc_test.go | 22 ++++++++-------- 8 files changed, 44 insertions(+), 62 deletions(-) delete mode 100644 driver/testing/config.go diff --git a/builder_acc_test.go b/builder_acc_test.go index a18e8d5f0..f18caaab0 100644 --- a/builder_acc_test.go +++ b/builder_acc_test.go @@ -17,7 +17,7 @@ func TestBuilderAcc_default(t *testing.T) { Check: func(artifacts []packer.Artifact) error { d := driverT.NewTestDriver(t) driverT.VMCheckDefault(t, d, getVM(t, d, artifacts), config["vm_name"].(string), - config["host"].(string), driverT.TestDatastore) + config["host"].(string), "datastore1") return nil }, }) @@ -25,13 +25,13 @@ func TestBuilderAcc_default(t *testing.T) { func defaultConfig() map[string]interface{} { config := map[string]interface{}{ - "vcenter_server": driverT.TestVCenterServer, - "username": driverT.TestVCenterUsername, - "password": driverT.TestVCenterPassword, + "vcenter_server": "vcenter.vsphere55.test", + "username": "root", + "password": "jetbrains", "insecure_connection": true, - "template": driverT.TestTemplate, - "host": driverT.TestHost, + "template": "alpine", + "host": "esxi-1.vsphere55.test", "ssh_username": "root", "ssh_password": "jetbrains", @@ -69,13 +69,13 @@ func TestBuilderAcc_folder(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, Template: folderConfig(), - Check: checkFolder(t, driverT.TestFolder), + Check: checkFolder(t, "folder1/folder2"), }) } func folderConfig() string { config := defaultConfig() - config["folder"] = driverT.TestFolder + config["folder"] = "folder1/folder2" config["linked_clone"] = true // speed up return renderConfig(config) } @@ -101,13 +101,13 @@ func TestBuilderAcc_resourcePool(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, Template: resourcePoolConfig(), - Check: checkResourcePool(t, driverT.TestResourcePool), + Check: checkResourcePool(t, "pool1/pool2"), }) } func resourcePoolConfig() string { config := defaultConfig() - config["resource_pool"] = driverT.TestResourcePool + config["resource_pool"] = "pool1/pool2" config["linked_clone"] = true // speed up return renderConfig(config) } @@ -133,7 +133,7 @@ func TestBuilderAcc_datastore(t *testing.T) { Template: datastoreConfig(), Check: func(artifacts []packer.Artifact) error { d := driverT.NewTestDriver(t) - driverT.VMCheckDatastore(t, d, getVM(t, d, artifacts), driverT.TestDatastore) + driverT.VMCheckDatastore(t, d, getVM(t, d, artifacts), "datastore1") return nil }, }) @@ -206,11 +206,11 @@ func TestBuilderAcc_hardware(t *testing.T) { func hardwareConfig() string { config := defaultConfig() - config["CPUs"] = driverT.TestCPUs - config["CPU_reservation"] = driverT.TestCPUReservation - config["CPU_limit"] = driverT.TestCPULimit - config["RAM"] = driverT.TestRAM - config["RAM_reservation"] = driverT.TestRAMReservation + config["CPUs"] = 2 + config["CPU_reservation"] = 1000 + config["CPU_limit"] = 1500 + config["RAM"] = 2048 + config["RAM_reservation"] = 1024 config["linked_clone"] = true // speed up return renderConfig(config) diff --git a/driver/testing/config.go b/driver/testing/config.go deleted file mode 100644 index 9e085dd6c..000000000 --- a/driver/testing/config.go +++ /dev/null @@ -1,22 +0,0 @@ -package testing - -// Defines whether acceptance tests should be run -const TestEnvVar = "VSPHERE_DRIVER_ACC" - -// Describe the environment to run tests in -const TestDatastore = "datastore1" -const TestTemplate = "alpine" -const TestHost = "esxi-1.vsphere55.test" -const TestVCenterServer = "vcenter.vsphere55.test" -const TestVCenterUsername = "root" -const TestVCenterPassword = "jetbrains" - -// For test of hardware settings -const TestCPUs = 2 -const TestCPUReservation = 1000 -const TestCPULimit = 1500 -const TestRAM = 2048 -const TestRAMReservation = 1024 - -const TestFolder = "folder1/folder2" -const TestResourcePool = "pool1/pool2" diff --git a/driver/testing/datastore_acc_test.go b/driver/testing/datastore_acc_test.go index 17eecf1ee..4643c0a5c 100644 --- a/driver/testing/datastore_acc_test.go +++ b/driver/testing/datastore_acc_test.go @@ -8,9 +8,9 @@ func TestDatastoreAcc(t *testing.T) { initDriverAcceptanceTest(t) d := NewTestDriver(t) - ds, err := d.FindDatastore(TestDatastore) + ds, err := d.FindDatastore("datastore1") if err != nil { - t.Fatalf("Cannot find the default datastore '%v': %v", TestDatastore, err) + t.Fatalf("Cannot find the default datastore '%v': %v", "datastore1", err) } - CheckDatastoreName(t, ds, TestDatastore) + CheckDatastoreName(t, ds, "datastore1") } diff --git a/driver/testing/folder_acc_test.go b/driver/testing/folder_acc_test.go index fc436d0a1..8555521fa 100644 --- a/driver/testing/folder_acc_test.go +++ b/driver/testing/folder_acc_test.go @@ -6,9 +6,9 @@ func TestFolderAcc(t *testing.T) { initDriverAcceptanceTest(t) d := NewTestDriver(t) - f, err := d.FindFolder(TestFolder) + f, err := d.FindFolder("folder1/folder2") if err != nil { - t.Fatalf("Cannot find the default folder '%v': %v", TestFolder, err) + t.Fatalf("Cannot find the default folder '%v': %v", "folder1/folder2", err) } - CheckFolderPath(t, f, TestFolder) + CheckFolderPath(t, f, "folder1/folder2") } diff --git a/driver/testing/host_acc_test.go b/driver/testing/host_acc_test.go index 92b08cf69..a9c35af7e 100644 --- a/driver/testing/host_acc_test.go +++ b/driver/testing/host_acc_test.go @@ -6,16 +6,17 @@ import ( func TestHostAcc(t *testing.T) { initDriverAcceptanceTest(t) + hostName := "esxi-1.vsphere55.test" d := NewTestDriver(t) - host, err := d.FindHost(TestHost) + host, err := d.FindHost(hostName) if err != nil { - t.Fatalf("Cannot find the default host '%v': %v", TestDatastore, err) + t.Fatalf("Cannot find the default host '%v': %v", "datastore1", err) } switch info, err := host.Info("name"); { case err != nil: t.Errorf("Cannot read host properties: %v", err) - case info.Name != TestHost: - t.Errorf("Wrong host name: expected '%v', got: '%v'", TestHost, info.Name) + case info.Name != hostName: + t.Errorf("Wrong host name: expected '%v', got: '%v'", hostName, info.Name) } } diff --git a/driver/testing/resource_pool_acc_test.go b/driver/testing/resource_pool_acc_test.go index 7b6177f90..b242e0b08 100644 --- a/driver/testing/resource_pool_acc_test.go +++ b/driver/testing/resource_pool_acc_test.go @@ -6,9 +6,9 @@ func TestResourcePoolAcc(t *testing.T) { initDriverAcceptanceTest(t) d := NewTestDriver(t) - p, err := d.FindResourcePool(TestHost, TestResourcePool) + p, err := d.FindResourcePool("esxi-1.vsphere55.test", "pool1/pool2") if err != nil { - t.Fatalf("Cannot find the default resource pool '%v': %v", TestResourcePool, err) + t.Fatalf("Cannot find the default resource pool '%v': %v", "pool1/pool2", err) } - CheckResourcePoolPath(t, p, TestResourcePool) + CheckResourcePoolPath(t, p, "pool1/pool2") } diff --git a/driver/testing/utility.go b/driver/testing/utility.go index 96d210370..707fc4d18 100644 --- a/driver/testing/utility.go +++ b/driver/testing/utility.go @@ -152,7 +152,8 @@ func VMCheckHardware(t* testing.T, d *driver.Driver, vm *driver.VirtualMachine) } func VMCheckTemplate(t* testing.T, d *driver.Driver, vm *driver.VirtualMachine) { - switch vmInfo, err := vm.Info("config.template"); { + vmInfo, err := vm.Info("config.template") + switch { case err != nil: t.Errorf("Cannot read VM properties: %v", err) case !vmInfo.Config.Template: diff --git a/driver/testing/vm_acc_test.go b/driver/testing/vm_acc_test.go index 594430ff2..b360c0dfc 100644 --- a/driver/testing/vm_acc_test.go +++ b/driver/testing/vm_acc_test.go @@ -10,21 +10,23 @@ import ( func initVMAccTest(t *testing.T) (d *driver.Driver, vm *driver.VirtualMachine, vmName string, vmDestructor func()) { initDriverAcceptanceTest(t) + + templateName := "alpine" d = NewTestDriver(t) - template, err := d.FindVM(TestTemplate) // Don't destroy this VM! + template, err := d.FindVM(templateName) // Don't destroy this VM! if err != nil { - t.Fatalf("Cannot find template vm '%v': %v", TestTemplate, err) + t.Fatalf("Cannot find template vm '%v': %v", templateName, err) } log.Printf("[DEBUG] Clonning VM") vmName = NewVMName() vm, err = template.Clone(&driver.CloneConfig{ Name: vmName, - Host: TestHost, + Host: "esxi-1.vsphere55.test", }) if err != nil { - t.Fatalf("Cannot clone vm '%v': %v", TestTemplate, err) + t.Fatalf("Cannot clone vm '%v': %v", templateName, err) } vmDestructor = func() { @@ -53,7 +55,7 @@ func TestVMAcc_default(t *testing.T) { // Run checks log.Printf("[DEBUG] Running check function") - VMCheckDefault(t, d, vm, vmName, TestHost, TestDatastore) + VMCheckDefault(t, d, vm, vmName, "esxi-1.vsphere55.test", "datastore1") } func TestVMAcc_hardware(t *testing.T) { @@ -62,11 +64,11 @@ func TestVMAcc_hardware(t *testing.T) { log.Printf("[DEBUG] Configuring the vm") vm.Configure(&driver.HardwareConfig{ - CPUs: TestCPUs, - CPUReservation: TestCPUReservation, - CPULimit: TestCPULimit, - RAM: TestRAM, - RAMReservation: TestRAMReservation, + CPUs: 2, + CPUReservation: 1000, + CPULimit: 1500, + RAM: 2048, + RAMReservation: 1024, }) log.Printf("[DEBUG] Running check function") VMCheckHardware(t, d, vm) From 6e3e92e356e300391415812675864bb8c70a05e1 Mon Sep 17 00:00:00 2001 From: Andrei Tonkikh Date: Tue, 14 Nov 2017 00:02:46 +0300 Subject: [PATCH 10/12] Remove driver test utility. Move driver tests to the driver folder --- builder_acc_test.go | 249 ++++++++++++++---- driver/datastore_acc_test.go | 22 ++ driver/driver_test.go | 46 ++++ driver/folder_acc_test.go | 20 ++ driver/{testing => }/host_acc_test.go | 15 +- .../{testing => }/resource_pool_acc_test.go | 13 +- driver/testing/datastore_acc_test.go | 16 -- driver/testing/folder_acc_test.go | 14 - driver/testing/utility.go | 191 -------------- driver/testing/vm_acc_test.go | 128 --------- driver/vm_acc_test.go | 221 ++++++++++++++++ 11 files changed, 525 insertions(+), 410 deletions(-) create mode 100644 driver/datastore_acc_test.go create mode 100644 driver/driver_test.go create mode 100644 driver/folder_acc_test.go rename driver/{testing => }/host_acc_test.go (57%) rename driver/{testing => }/resource_pool_acc_test.go (52%) delete mode 100644 driver/testing/datastore_acc_test.go delete mode 100644 driver/testing/folder_acc_test.go delete mode 100644 driver/testing/utility.go delete mode 100644 driver/testing/vm_acc_test.go create mode 100644 driver/vm_acc_test.go diff --git a/builder_acc_test.go b/builder_acc_test.go index f18caaab0..8ac8f25bf 100644 --- a/builder_acc_test.go +++ b/builder_acc_test.go @@ -1,12 +1,13 @@ package main import ( - "encoding/json" + "testing" builderT "github.com/hashicorp/packer/helper/builder/testing" + "fmt" "github.com/hashicorp/packer/packer" + "encoding/json" + "math/rand" "github.com/jetbrains-infra/packer-builder-vsphere/driver" - driverT "github.com/jetbrains-infra/packer-builder-vsphere/driver/testing" - "testing" ) func TestBuilderAcc_default(t *testing.T) { @@ -14,12 +15,7 @@ func TestBuilderAcc_default(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, Template: renderConfig(config), - Check: func(artifacts []packer.Artifact) error { - d := driverT.NewTestDriver(t) - driverT.VMCheckDefault(t, d, getVM(t, d, artifacts), config["vm_name"].(string), - config["host"].(string), "datastore1") - return nil - }, + Check: checkDefault(t, config["vm_name"].(string), config["host"].(string), "datastore1"), }) } @@ -36,10 +32,69 @@ func defaultConfig() map[string]interface{} { "ssh_username": "root", "ssh_password": "jetbrains", } - config["vm_name"] = driverT.NewVMName() + config["vm_name"] = fmt.Sprintf("test-%v", rand.Intn(1000)) return config } +func checkDefault(t *testing.T, name string, host string, datastore string) builderT.TestCheckFunc { + return func(artifacts []packer.Artifact) error { + d := testConn(t) + vm := getVM(t, d, artifacts) + + vmInfo, err := vm.Info("name", "parent", "runtime.host", "resourcePool", "datastore", "layoutEx.disk") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) + } + + if vmInfo.Name != name { + t.Errorf("Invalid VM name: expected '%v', got '%v'", name, vmInfo.Name) + } + + f := d.NewFolder(vmInfo.Parent) + folderPath, err := f.Path() + if err != nil { + t.Fatalf("Cannot read folder name: %v", err) + } + if folderPath != "" { + t.Errorf("Invalid folder: expected '/', got '%v'", folderPath) + } + + h := d.NewHost(vmInfo.Runtime.Host) + hostInfo, err := h.Info("name") + if err != nil { + t.Fatal("Cannot read host properties: ", err) + } + if hostInfo.Name != host { + t.Errorf("Invalid host name: expected '%v', got '%v'", host, hostInfo.Name) + } + + p := d.NewResourcePool(vmInfo.ResourcePool) + poolPath, err := p.Path() + if err != nil { + t.Fatalf("Cannot read resource pool name: %v", err) + } + if poolPath != "" { + t.Error("Invalid resource pool: expected '/', got '%v'", poolPath) + } + + dsr := vmInfo.Datastore[0].Reference() + ds := d.NewDatastore(&dsr) + dsInfo, err := ds.Info("name") + if err != nil { + t.Fatal("Cannot read datastore properties: ", err) + } + if dsInfo.Name != datastore { + t.Errorf("Invalid datastore name: expected '%v', got '%v'", datastore, dsInfo.Name) + } + + if len(vmInfo.LayoutEx.Disk[0].Chain) != 1 { + t.Error("Not a full clone") + } + + return nil + } +} + func TestBuilderAcc_artifact(t *testing.T) { config := defaultConfig() builderT.Test(t, builderT.TestCase{ @@ -80,23 +135,6 @@ func folderConfig() string { return renderConfig(config) } -func checkFolder(t *testing.T, folder string) builderT.TestCheckFunc { - return func(artifacts []packer.Artifact) error { - d := driverT.NewTestDriver(t) - vm := getVM(t, d, artifacts) - - vmInfo, err := vm.Info("parent") - if err != nil { - t.Fatalf("Cannot read VM properties: %v", err) - } - - f := d.NewFolder(vmInfo.Parent) - driverT.CheckFolderPath(t, f, folder) - - return nil - } -} - func TestBuilderAcc_resourcePool(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, @@ -114,7 +152,7 @@ func resourcePoolConfig() string { func checkResourcePool(t *testing.T, pool string) builderT.TestCheckFunc { return func(artifacts []packer.Artifact) error { - d := driverT.NewTestDriver(t) + d := testConn(t) vm := getVM(t, d, artifacts) vmInfo, err := vm.Info("resourcePool") @@ -122,7 +160,15 @@ func checkResourcePool(t *testing.T, pool string) builderT.TestCheckFunc { t.Fatalf("Cannot read VM properties: %v", err) } - driverT.CheckResourcePoolPath(t, d.NewResourcePool(vmInfo.ResourcePool), pool) + p := d.NewResourcePool(vmInfo.ResourcePool) + path, err := p.Path() + if err != nil { + t.Fatalf("Cannot read resource pool name: %v", err) + } + if path != pool { + t.Errorf("Wrong folder. expected: %v, got: %v", pool, path) + } + return nil } } @@ -131,11 +177,7 @@ func TestBuilderAcc_datastore(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, Template: datastoreConfig(), - Check: func(artifacts []packer.Artifact) error { - d := driverT.NewTestDriver(t) - driverT.VMCheckDatastore(t, d, getVM(t, d, artifacts), "datastore1") - return nil - }, + Check: checkDatastore(t, "datastore1"), // on esxi-1.vsphere55.test }) } @@ -145,6 +187,34 @@ func datastoreConfig() string { return renderConfig(config) } +func checkDatastore(t *testing.T, name string) builderT.TestCheckFunc { + return func(artifacts []packer.Artifact) error { + d := testConn(t) + vm := getVM(t, d, artifacts) + + vmInfo, err := vm.Info("datastore") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) + } + + n := len(vmInfo.Datastore) + if n != 1 { + t.Fatalf("VM should have 1 datastore, got %v", n) + } + + ds := d.NewDatastore(&vmInfo.Datastore[0]) + info, err := ds.Info("name") + if err != nil { + t.Fatalf("Cannot read datastore properties: %v", err) + } + if info.Name != name { + t.Errorf("Wrong datastore. expected: %v, got: %v", name, info.Name) + } + + return nil + } +} + func TestBuilderAcc_multipleDatastores(t *testing.T) { t.Skip("test must fail") @@ -176,7 +246,7 @@ func linkedCloneConfig() string { func checkLinkedClone(t *testing.T) builderT.TestCheckFunc { return func(artifacts []packer.Artifact) error { - d := driverT.NewTestDriver(t) + d := testConn(t) vm := getVM(t, d, artifacts) vmInfo, err := vm.Info("layoutEx.disk") @@ -196,11 +266,7 @@ func TestBuilderAcc_hardware(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, Template: hardwareConfig(), - Check: func(artifacts []packer.Artifact) error { - d := driverT.NewTestDriver(t) - driverT.VMCheckHardware(t, d, getVM(t, d, artifacts)) - return nil - }, + Check: checkHardware(t), }) } @@ -216,6 +282,45 @@ func hardwareConfig() string { return renderConfig(config) } +func checkHardware(t *testing.T) builderT.TestCheckFunc { + return func(artifacts []packer.Artifact) error { + d := testConn(t) + + vm := getVM(t, d, artifacts) + vmInfo, err := vm.Info("config") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) + } + + cpuSockets := vmInfo.Config.Hardware.NumCPU + if cpuSockets != 2 { + t.Errorf("VM should have 2 CPU sockets, got %v", cpuSockets) + } + + cpuReservation := vmInfo.Config.CpuAllocation.GetResourceAllocationInfo().Reservation + if cpuReservation != 1000 { + t.Errorf("VM should have CPU reservation for 1000 Mhz, got %v", cpuReservation) + } + + cpuLimit := vmInfo.Config.CpuAllocation.GetResourceAllocationInfo().Limit + if cpuLimit != 1500 { + t.Errorf("VM should have CPU reservation for 1500 Mhz, got %v", cpuLimit) + } + + ram := vmInfo.Config.Hardware.MemoryMB + if ram != 2048 { + t.Errorf("VM should have 2048 MB of RAM, got %v", ram) + } + + ramReservation := vmInfo.Config.MemoryAllocation.GetResourceAllocationInfo().Reservation + if ramReservation != 1024 { + t.Errorf("VM should have RAM reservation for 1024 MB, got %v", ramReservation) + } + + return nil + } +} + func TestBuilderAcc_RAMReservation(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, @@ -234,7 +339,7 @@ func RAMReservationConfig() string { func checkRAMReservation(t *testing.T) builderT.TestCheckFunc { return func(artifacts []packer.Artifact) error { - d := driverT.NewTestDriver(t) + d := testConn(t) vm := getVM(t, d, artifacts) vmInfo, err := vm.Info("config") @@ -269,11 +374,7 @@ func TestBuilderAcc_snapshot(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, Template: snapshotConfig(), - Check: func(artifacts []packer.Artifact) error { - d := driverT.NewTestDriver(t) - driverT.VMCheckSnapshor(t, d, getVM(t, d, artifacts)) - return nil - }, + Check: checkSnapshot(t), }) } @@ -283,15 +384,30 @@ func snapshotConfig() string { return renderConfig(config) } +func checkSnapshot(t *testing.T) builderT.TestCheckFunc { + return func(artifacts []packer.Artifact) error { + d := testConn(t) + + vm := getVM(t, d, artifacts) + vmInfo, err := vm.Info("layoutEx.disk") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) + } + + layers := len(vmInfo.LayoutEx.Disk[0].Chain) + if layers != 2 { + t.Errorf("VM should have a single snapshot. expected 2 disk layers, got %v", layers) + } + + return nil + } +} + func TestBuilderAcc_template(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, Template: templateConfig(), - Check: func(artifacts []packer.Artifact) error { - d := driverT.NewTestDriver(t) - driverT.VMCheckTemplate(t, d, getVM(t, d, artifacts)) - return nil - }, + Check: checkTemplate(t), }) } @@ -302,6 +418,24 @@ func templateConfig() string { return renderConfig(config) } +func checkTemplate(t *testing.T) builderT.TestCheckFunc { + return func(artifacts []packer.Artifact) error { + d := testConn(t) + + vm := getVM(t, d, artifacts) + vmInfo, err := vm.Info("config.template") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) + } + + if vmInfo.Config.Template != true { + t.Error("Not a template") + } + + return nil + } +} + func renderConfig(config map[string]interface{}) string { t := map[string][]map[string]interface{}{ "builders": { @@ -318,6 +452,19 @@ func renderConfig(config map[string]interface{}) string { return string(j) } +func testConn(t *testing.T) *driver.Driver { + d, err := driver.NewDriver(&driver.ConnectConfig{ + VCenterServer: "vcenter.vsphere55.test", + Username: "root", + Password: "jetbrains", + InsecureConnection: true, + }) + if err != nil { + t.Fatal("Cannot connect: ", err) + } + return d +} + func getVM(t *testing.T, d *driver.Driver, artifacts []packer.Artifact) *driver.VirtualMachine { artifactRaw := artifacts[0] artifact, _ := artifactRaw.(*Artifact) diff --git a/driver/datastore_acc_test.go b/driver/datastore_acc_test.go new file mode 100644 index 000000000..290ae3342 --- /dev/null +++ b/driver/datastore_acc_test.go @@ -0,0 +1,22 @@ +package driver + +import ( + "testing" +) + +func TestDatastoreAcc(t *testing.T) { + initDriverAcceptanceTest(t) + + d := newTestDriver(t) + ds, err := d.FindDatastore("datastore1") + if err != nil { + t.Fatalf("Cannot find the default datastore '%v': %v", "datastore1", err) + } + info, err := ds.Info("name") + if err != nil { + t.Fatalf("Cannot read datastore properties: %v", err) + } + if info.Name != "datastore1" { + t.Errorf("Wrong datastore. expected: 'datastore1', got: '%v'", info.Name) + } +} diff --git a/driver/driver_test.go b/driver/driver_test.go new file mode 100644 index 000000000..e7e347e68 --- /dev/null +++ b/driver/driver_test.go @@ -0,0 +1,46 @@ +package driver + +import ( + "os" + "fmt" + "testing" + "time" + "math/rand" +) + +// Defines whether acceptance tests should be run +const TestEnvVar = "VSPHERE_DRIVER_ACC" +const hostName = "esxi-1.vsphere55.test" + +func newTestDriver(t *testing.T) *Driver { + d, err := NewDriver(&ConnectConfig{ + VCenterServer: "vcenter.vsphere55.test", + Username: "root", + Password: "jetbrains", + InsecureConnection: true, + }) + if err != nil { + t.Fatalf("Cannot connect: %v", err) + } + return d +} + +func newVMName() string { + rand.Seed(time.Now().UTC().UnixNano()) + return fmt.Sprintf("test-%v", rand.Intn(1000)) +} + +func initDriverAcceptanceTest(t *testing.T) { + // We only run acceptance tests if an env var is set because they're + // slow and require outside configuration. + if os.Getenv(TestEnvVar) == "" { + t.Skip(fmt.Sprintf( + "Acceptance tests skipped unless env '%s' set", + TestEnvVar)) + } + + // We require verbose mode so that the user knows what is going on. + if !testing.Verbose() { + t.Fatal("Acceptance tests must be run with the -v flag on tests") + } +} diff --git a/driver/folder_acc_test.go b/driver/folder_acc_test.go new file mode 100644 index 000000000..220f1195e --- /dev/null +++ b/driver/folder_acc_test.go @@ -0,0 +1,20 @@ +package driver + +import "testing" + +func TestFolderAcc(t *testing.T) { + initDriverAcceptanceTest(t) + + d := newTestDriver(t) + f, err := d.FindFolder("folder1/folder2") + if err != nil { + t.Fatalf("Cannot find the default folder '%v': %v", "folder1/folder2", err) + } + path, err := f.Path() + if err != nil { + t.Fatalf("Cannot read folder name: %v", err) + } + if path != "folder1/folder2" { + t.Errorf("Wrong folder. expected: 'folder1/folder2', got: '%v'", path) + } +} diff --git a/driver/testing/host_acc_test.go b/driver/host_acc_test.go similarity index 57% rename from driver/testing/host_acc_test.go rename to driver/host_acc_test.go index a9c35af7e..bba4da7cf 100644 --- a/driver/testing/host_acc_test.go +++ b/driver/host_acc_test.go @@ -1,4 +1,4 @@ -package testing +package driver import ( "testing" @@ -6,17 +6,18 @@ import ( func TestHostAcc(t *testing.T) { initDriverAcceptanceTest(t) - hostName := "esxi-1.vsphere55.test" - d := NewTestDriver(t) + d := newTestDriver(t) host, err := d.FindHost(hostName) if err != nil { t.Fatalf("Cannot find the default host '%v': %v", "datastore1", err) } - switch info, err := host.Info("name"); { - case err != nil: - t.Errorf("Cannot read host properties: %v", err) - case info.Name != hostName: + + info, err := host.Info("name") + if err != nil { + t.Fatalf("Cannot read host properties: %v", err) + } + if info.Name != hostName { t.Errorf("Wrong host name: expected '%v', got: '%v'", hostName, info.Name) } } diff --git a/driver/testing/resource_pool_acc_test.go b/driver/resource_pool_acc_test.go similarity index 52% rename from driver/testing/resource_pool_acc_test.go rename to driver/resource_pool_acc_test.go index b242e0b08..a1f2b47bd 100644 --- a/driver/testing/resource_pool_acc_test.go +++ b/driver/resource_pool_acc_test.go @@ -1,14 +1,21 @@ -package testing +package driver import "testing" func TestResourcePoolAcc(t *testing.T) { initDriverAcceptanceTest(t) - d := NewTestDriver(t) + d := newTestDriver(t) p, err := d.FindResourcePool("esxi-1.vsphere55.test", "pool1/pool2") if err != nil { t.Fatalf("Cannot find the default resource pool '%v': %v", "pool1/pool2", err) } - CheckResourcePoolPath(t, p, "pool1/pool2") + + path, err := p.Path() + if err != nil { + t.Fatalf("Cannot read resource pool name: %v", err) + } + if path != "pool1/pool2" { + t.Errorf("Wrong folder. expected: 'pool1/pool2', got: '%v'", path) + } } diff --git a/driver/testing/datastore_acc_test.go b/driver/testing/datastore_acc_test.go deleted file mode 100644 index 4643c0a5c..000000000 --- a/driver/testing/datastore_acc_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package testing - -import ( - "testing" -) - -func TestDatastoreAcc(t *testing.T) { - initDriverAcceptanceTest(t) - - d := NewTestDriver(t) - ds, err := d.FindDatastore("datastore1") - if err != nil { - t.Fatalf("Cannot find the default datastore '%v': %v", "datastore1", err) - } - CheckDatastoreName(t, ds, "datastore1") -} diff --git a/driver/testing/folder_acc_test.go b/driver/testing/folder_acc_test.go deleted file mode 100644 index 8555521fa..000000000 --- a/driver/testing/folder_acc_test.go +++ /dev/null @@ -1,14 +0,0 @@ -package testing - -import "testing" - -func TestFolderAcc(t *testing.T) { - initDriverAcceptanceTest(t) - - d := NewTestDriver(t) - f, err := d.FindFolder("folder1/folder2") - if err != nil { - t.Fatalf("Cannot find the default folder '%v': %v", "folder1/folder2", err) - } - CheckFolderPath(t, f, "folder1/folder2") -} diff --git a/driver/testing/utility.go b/driver/testing/utility.go deleted file mode 100644 index 707fc4d18..000000000 --- a/driver/testing/utility.go +++ /dev/null @@ -1,191 +0,0 @@ -package testing - -import ( - "fmt" - "github.com/jetbrains-infra/packer-builder-vsphere/driver" - "math/rand" - "os" - "testing" - "time" -) - -func NewTestDriver(t *testing.T) *driver.Driver { - d, err := driver.NewDriver(&driver.ConnectConfig{ - VCenterServer: TestVCenterServer, - Username: TestVCenterUsername, - Password: TestVCenterPassword, - InsecureConnection: true, - }) - if err != nil { - t.Fatalf("Cannot connect: %v", err) - } - return d -} - -func NewVMName() string { - rand.Seed(time.Now().UTC().UnixNano()) - return fmt.Sprintf("test-%v", rand.Intn(1000)) -} - -func CheckDatastoreName(t *testing.T, ds *driver.Datastore, datastore string) { - switch info, err := ds.Info("name"); { - case err != nil: - t.Errorf("Cannot read datastore properties: %v", err) - case info.Name != datastore: - t.Errorf("Wrong name: expected '%v', got: '%v'", datastore, info.Name) - } -} - -func CheckResourcePoolPath(t *testing.T, p *driver.ResourcePool, pool string) { - switch path, err := p.Path(); { - case err != nil: - t.Errorf("Cannot read resource pool path: %v", err) - case path != pool: - t.Errorf("Wrong name: expected '%v', got: '%v'", pool, path) - } -} - -func CheckFolderPath(t *testing.T, f *driver.Folder, folder string) { - switch path, err := f.Path(); { - case err != nil: - t.Fatalf("Cannot read folder path: %v", err) - case path != folder: - t.Errorf("Wrong path: expected '%v', got: '%v'", folder, path) - } -} - -func initDriverAcceptanceTest(t *testing.T) { - // We only run acceptance tests if an env var is set because they're - // slow and require outside configuration. - if os.Getenv(TestEnvVar) == "" { - t.Skip(fmt.Sprintf( - "Acceptance tests skipped unless env '%s' set", - TestEnvVar)) - } - - // We require verbose mode so that the user knows what is going on. - if !testing.Verbose() { - t.Fatal("Acceptance tests must be run with the -v flag on tests") - } -} - -func VMCheckDefault(t *testing.T, d *driver.Driver, vm *driver.VirtualMachine, - name string, host string, datastore string) { - vmInfo, err := vm.Info("name", "parent", "runtime.host", "resourcePool", "datastore", "layoutEx.disk") - if err != nil { - t.Fatalf("Cannot read VM properties: %v", err) - } - - if vmInfo.Name != name { - t.Errorf("Invalid VM name: expected '%v', got '%v'", name, vmInfo.Name) - } - - f := d.NewFolder(vmInfo.Parent) - switch folderPath, err := f.Path(); { - case err != nil: - t.Errorf("Cannot read folder name: %v", err) - case folderPath != "": - t.Errorf("Invalid folder: expected '/', got '%v'", folderPath) - } - - h := d.NewHost(vmInfo.Runtime.Host) - switch hostInfo, err := h.Info("name"); { - case err != nil: - t.Errorf("Cannot read host properties: %v", err) - case hostInfo.Name != host: - t.Errorf("Invalid host name: expected '%v', got '%v'", host, hostInfo.Name) - } - - p := d.NewResourcePool(vmInfo.ResourcePool) - switch poolPath, err := p.Path(); { - case err != nil: - t.Errorf("Cannot read resource pool name: %v", err) - case poolPath != "": - t.Error("Invalid resource pool: expected '/', got '%v'", poolPath) - } - - - dsr := vmInfo.Datastore[0].Reference() - ds := d.NewDatastore(&dsr) - switch dsInfo, err := ds.Info("name"); { - case err != nil: - t.Errorf("Cannot read datastore properties: %v", err) - case dsInfo.Name != datastore: - t.Errorf("Invalid datastore name: expected '%v', got '%v'", datastore, dsInfo.Name) - } - - if len(vmInfo.LayoutEx.Disk[0].Chain) != 1 { - t.Error("Not a full clone") - } -} - -func VMCheckHardware(t* testing.T, d *driver.Driver, vm *driver.VirtualMachine) { - vmInfo, err := vm.Info("config") - if err != nil { - t.Fatalf("Cannot read VM properties: %v", err) - } - - cpuSockets := vmInfo.Config.Hardware.NumCPU - if cpuSockets != 2 { - t.Errorf("VM should have 2 CPU sockets, got %v", cpuSockets) - } - - cpuReservation := vmInfo.Config.CpuAllocation.GetResourceAllocationInfo().Reservation - if cpuReservation != 1000 { - t.Errorf("VM should have CPU reservation for 1000 Mhz, got %v", cpuReservation) - } - - cpuLimit := vmInfo.Config.CpuAllocation.GetResourceAllocationInfo().Limit - if cpuLimit != 1500 { - t.Errorf("VM should have CPU reservation for 1500 Mhz, got %v", cpuLimit) - } - - ram := vmInfo.Config.Hardware.MemoryMB - if ram != 2048 { - t.Errorf("VM should have 2048 MB of RAM, got %v", ram) - } - - ramReservation := vmInfo.Config.MemoryAllocation.GetResourceAllocationInfo().Reservation - if ramReservation != 1024 { - t.Errorf("VM should have RAM reservation for 1024 MB, got %v", ramReservation) - } -} - -func VMCheckTemplate(t* testing.T, d *driver.Driver, vm *driver.VirtualMachine) { - vmInfo, err := vm.Info("config.template") - switch { - case err != nil: - t.Errorf("Cannot read VM properties: %v", err) - case !vmInfo.Config.Template: - t.Error("Not a template") - } -} - -func VMCheckDatastore(t* testing.T, d *driver.Driver, vm *driver.VirtualMachine, name string) { - vmInfo, err := vm.Info("datastore") - if err != nil { - t.Fatalf("Cannot read VM properties: %v", err) - } - - n := len(vmInfo.Datastore) - if n != 1 { - t.Fatalf("VM should have 1 datastore, got %v", n) - } - - ds := d.NewDatastore(&vmInfo.Datastore[0]) - CheckDatastoreName(t, ds, name) -} - -func VMCheckSnapshor(t* testing.T, d *driver.Driver, vm *driver.VirtualMachine) { - vmInfo, err := vm.Info("layoutEx.disk") - if err != nil { - t.Fatalf("Cannot read VM properties: %v", err) - } - - layers := len(vmInfo.LayoutEx.Disk[0].Chain) - if layers != 2 { - t.Errorf("VM should have a single snapshot. expected 2 disk layers, got %v", layers) - } -} - - diff --git a/driver/testing/vm_acc_test.go b/driver/testing/vm_acc_test.go deleted file mode 100644 index b360c0dfc..000000000 --- a/driver/testing/vm_acc_test.go +++ /dev/null @@ -1,128 +0,0 @@ -package testing - -import ( - "github.com/jetbrains-infra/packer-builder-vsphere/driver" - "log" - "testing" - "net" - "time" -) - -func initVMAccTest(t *testing.T) (d *driver.Driver, vm *driver.VirtualMachine, vmName string, vmDestructor func()) { - initDriverAcceptanceTest(t) - - templateName := "alpine" - d = NewTestDriver(t) - - template, err := d.FindVM(templateName) // Don't destroy this VM! - if err != nil { - t.Fatalf("Cannot find template vm '%v': %v", templateName, err) - } - - log.Printf("[DEBUG] Clonning VM") - vmName = NewVMName() - vm, err = template.Clone(&driver.CloneConfig{ - Name: vmName, - Host: "esxi-1.vsphere55.test", - }) - if err != nil { - t.Fatalf("Cannot clone vm '%v': %v", templateName, err) - } - - vmDestructor = func() { - log.Printf("[DEBUG] Removing the clone") - if err := vm.Destroy(); err != nil { - t.Errorf("!!! ERROR REMOVING VM '%v': %v!!!", vmName, err) - } - - // Check that the clone is no longer exists - if _, err := d.FindVM(vmName); err == nil { - t.Errorf("!!! STILL CAN FIND VM '%v'. IT MIGHT NOT HAVE BEEN DELETED !!!", vmName) - } - } - - return -} - -func TestVMAcc_default(t *testing.T) { - d, vm, vmName, vmDestructor := initVMAccTest(t) - defer vmDestructor() - - // Check that the clone can be found by its name - if _, err := d.FindVM(vmName); err != nil { - t.Errorf("Cannot find created vm '%v': %v", vmName, err) - } - - // Run checks - log.Printf("[DEBUG] Running check function") - VMCheckDefault(t, d, vm, vmName, "esxi-1.vsphere55.test", "datastore1") -} - -func TestVMAcc_hardware(t *testing.T) { - d, vm, _ /*vmName*/, vmDestructor := initVMAccTest(t) - defer vmDestructor() - - log.Printf("[DEBUG] Configuring the vm") - vm.Configure(&driver.HardwareConfig{ - CPUs: 2, - CPUReservation: 1000, - CPULimit: 1500, - RAM: 2048, - RAMReservation: 1024, - }) - log.Printf("[DEBUG] Running check function") - VMCheckHardware(t, d, vm) -} - -func startVM(t *testing.T, vm *driver.VirtualMachine, vmName string) (stopper func()) { - log.Printf("[DEBUG] Starting the vm") - if err := vm.PowerOn(); err != nil { - t.Fatalf("Cannot start created vm '%v': %v", vmName, err) - } - return func() { - log.Printf("[DEBUG] Powering off the vm") - if err := vm.PowerOff(); err != nil { - t.Errorf("Cannot power off started vm '%v': %v", vmName, err) - } - } -} - -func TestVMAcc_running(t *testing.T) { - _ /*d*/, vm, vmName, vmDestructor := initVMAccTest(t) - defer vmDestructor() - - stopper := startVM(t, vm, vmName) - defer stopper() - - switch ip, err := vm.WaitForIP(); { - case err != nil: - t.Errorf("Cannot obtain IP address from created vm '%v': %v", vmName, err) - case net.ParseIP(ip) == nil: - t.Errorf("'%v' is not a valid ip address", ip) - } - - vm.StartShutdown() - log.Printf("[DEBUG] Waiting max 1m0s for shutdown to complete") - // TODO: there is complex logic in WaitForShutdown. It's better to test it well. It might be reasonable to create - // unit tests for it. - vm.WaitForShutdown(1 * time.Minute) -} - -func TestVMAcc_running_snapshot(t *testing.T) { - d, vm, vmName, vmDestructor := initVMAccTest(t) - defer vmDestructor() - - stopper := startVM(t, vm, vmName) - defer stopper() - - vm.CreateSnapshot("test-snapshot") - VMCheckSnapshor(t, d, vm) -} - -func TestVMAcc_template(t *testing.T) { - d, vm, _ /*vmName*/, vmDestructor := initVMAccTest(t) - defer vmDestructor() - - vm.ConvertToTemplate() - VMCheckTemplate(t, d, vm) -} diff --git a/driver/vm_acc_test.go b/driver/vm_acc_test.go new file mode 100644 index 000000000..921aca22a --- /dev/null +++ b/driver/vm_acc_test.go @@ -0,0 +1,221 @@ +package driver + +import ( + "log" + "testing" + "net" + "time" +) + +func initVMAccTest(t *testing.T) (d *Driver, vm *VirtualMachine, vmName string, vmDestructor func()) { + initDriverAcceptanceTest(t) + + templateName := "alpine" + d = newTestDriver(t) + + template, err := d.FindVM(templateName) // Don't destroy this VM! + if err != nil { + t.Fatalf("Cannot find template vm '%v': %v", templateName, err) + } + + log.Printf("[DEBUG] Clonning VM") + vmName = newVMName() + vm, err = template.Clone(&CloneConfig{ + Name: vmName, + Host: hostName, + }) + if err != nil { + t.Fatalf("Cannot clone vm '%v': %v", templateName, err) + } + + vmDestructor = func() { + log.Printf("[DEBUG] Removing the clone") + if err := vm.Destroy(); err != nil { + t.Errorf("!!! ERROR REMOVING VM '%v': %v!!!", vmName, err) + } + + // Check that the clone is no longer exists + if _, err := d.FindVM(vmName); err == nil { + t.Errorf("!!! STILL CAN FIND VM '%v'. IT MIGHT NOT HAVE BEEN DELETED !!!", vmName) + } + } + + return +} + +func TestVMAcc_default(t *testing.T) { + d, vm, vmName, vmDestructor := initVMAccTest(t) + defer vmDestructor() + + // Check that the clone can be found by its name + if _, err := d.FindVM(vmName); err != nil { + t.Errorf("Cannot find created vm '%v': %v", vmName, err) + } + + // Run checks + log.Printf("[DEBUG] Running checks") + vmInfo, err := vm.Info("name", "parent", "runtime.host", "resourcePool", "datastore", "layoutEx.disk") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) + } + + if vmInfo.Name != vmName { + t.Errorf("Invalid VM name: expected '%v', got '%v'", vmName, vmInfo.Name) + } + + f := d.NewFolder(vmInfo.Parent) + folderPath, err := f.Path() + if err != nil { + t.Fatalf("Cannot read folder name: %v", err) + } + if folderPath != "" { + t.Errorf("Invalid folder: expected '/', got '%v'", folderPath) + } + + h := d.NewHost(vmInfo.Runtime.Host) + hostInfo, err := h.Info("name") + if err != nil { + t.Fatal("Cannot read host properties: ", err) + } + if hostInfo.Name != hostName { + t.Errorf("Invalid host name: expected '%v', got '%v'", hostName, hostInfo.Name) + } + + p := d.NewResourcePool(vmInfo.ResourcePool) + poolPath, err := p.Path() + if err != nil { + t.Fatalf("Cannot read resource pool name: %v", err) + } + if poolPath != "" { + t.Error("Invalid resource pool: expected '/', got '%v'", poolPath) + } + + dsr := vmInfo.Datastore[0].Reference() + ds := d.NewDatastore(&dsr) + dsInfo, err := ds.Info("name") + if err != nil { + t.Fatal("Cannot read datastore properties: ", err) + } + if dsInfo.Name != "datastore1" { + t.Errorf("Invalid datastore name: expected '%v', got '%v'", "datastore1", dsInfo.Name) + } + + if len(vmInfo.LayoutEx.Disk[0].Chain) != 1 { + t.Error("Not a full clone") + } +} + +func TestVMAcc_folder(t *testing.T) { + +} + +func TestVMAcc_hardware(t *testing.T) { + _ /*d*/, vm, _ /*vmName*/, vmDestructor := initVMAccTest(t) + defer vmDestructor() + + log.Printf("[DEBUG] Configuring the vm") + config := &HardwareConfig{ + CPUs: 2, + CPUReservation: 1000, + CPULimit: 1500, + RAM: 2048, + RAMReservation: 1024, + } + vm.Configure(config) + + log.Printf("[DEBUG] Running checks") + vmInfo, err := vm.Info("config") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) + } + + cpuSockets := vmInfo.Config.Hardware.NumCPU + if cpuSockets != config.CPUs { + t.Errorf("VM should have %v CPU sockets, got %v", config.CPUs, cpuSockets) + } + + cpuReservation := vmInfo.Config.CpuAllocation.GetResourceAllocationInfo().Reservation + if cpuReservation != config.CPUReservation { + t.Errorf("VM should have CPU reservation for %v Mhz, got %v", config.CPUReservation, cpuReservation) + } + + cpuLimit := vmInfo.Config.CpuAllocation.GetResourceAllocationInfo().Limit + if cpuLimit != config.CPULimit { + t.Errorf("VM should have CPU reservation for %v Mhz, got %v", config.CPULimit, cpuLimit) + } + + ram := vmInfo.Config.Hardware.MemoryMB + if int64(ram) != config.RAM { + t.Errorf("VM should have %v MB of RAM, got %v", config.RAM, ram) + } + + ramReservation := vmInfo.Config.MemoryAllocation.GetResourceAllocationInfo().Reservation + if ramReservation != config.RAMReservation { + t.Errorf("VM should have RAM reservation for %v MB, got %v", config.RAMReservation, ramReservation) + } +} + +func startVM(t *testing.T, vm *VirtualMachine, vmName string) (stopper func()) { + log.Printf("[DEBUG] Starting the vm") + if err := vm.PowerOn(); err != nil { + t.Fatalf("Cannot start created vm '%v': %v", vmName, err) + } + return func() { + log.Printf("[DEBUG] Powering off the vm") + if err := vm.PowerOff(); err != nil { + t.Errorf("Cannot power off started vm '%v': %v", vmName, err) + } + } +} + +func TestVMAcc_running(t *testing.T) { + _ /*d*/, vm, vmName, vmDestructor := initVMAccTest(t) + defer vmDestructor() + + stopper := startVM(t, vm, vmName) + defer stopper() + + switch ip, err := vm.WaitForIP(); { + case err != nil: + t.Errorf("Cannot obtain IP address from created vm '%v': %v", vmName, err) + case net.ParseIP(ip) == nil: + t.Errorf("'%v' is not a valid ip address", ip) + } + + vm.StartShutdown() + log.Printf("[DEBUG] Waiting max 1m0s for shutdown to complete") + vm.WaitForShutdown(1 * time.Minute) +} + +func TestVMAcc_snapshot(t *testing.T) { + _ /*d*/, vm, vmName, vmDestructor := initVMAccTest(t) + defer vmDestructor() + + stopper := startVM(t, vm, vmName) + defer stopper() + + vm.CreateSnapshot("test-snapshot") + + vmInfo, err := vm.Info("layoutEx.disk") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) + } + + layers := len(vmInfo.LayoutEx.Disk[0].Chain) + if layers != 2 { + t.Errorf("VM should have a single snapshot. expected 2 disk layers, got %v", layers) + } +} + +func TestVMAcc_template(t *testing.T) { + _ /*d*/, vm, _ /*vmName*/, vmDestructor := initVMAccTest(t) + defer vmDestructor() + + vm.ConvertToTemplate() + vmInfo, err := vm.Info("config.template") + if err != nil { + t.Errorf("Cannot read VM properties: %v", err) + } else if !vmInfo.Config.Template { + t.Error("Not a template") + } +} From 991e1f8fdb305718e4cff5acf0ce66a351ec0c34 Mon Sep 17 00:00:00 2001 From: Andrei Tonkikh Date: Tue, 14 Nov 2017 00:08:32 +0300 Subject: [PATCH 11/12] Revert f05b1e1. That commit introcude a regression from #30 --- driver/driver.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/driver/driver.go b/driver/driver.go index d2bd048e7..30ddcce72 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -9,6 +9,8 @@ import ( "github.com/vmware/govmomi/object" "time" "github.com/vmware/govmomi/session" + "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25" ) type Driver struct { @@ -33,13 +35,25 @@ func NewDriver(config *ConnectConfig) (*Driver, error) { if err != nil { return nil, err } - vcenter_url.User = url.UserPassword(config.Username, config.Password) + credentials := url.UserPassword(config.Username, config.Password) + vcenter_url.User = credentials - client, err := govmomi.NewClient(ctx, vcenter_url, config.InsecureConnection) + soapClient := soap.NewClient(vcenter_url, config.InsecureConnection) + vimClient, err := vim25.NewClient(ctx, soapClient) + if err != nil { + return nil, err + } + + vimClient.RoundTripper = session.KeepAlive(vimClient.RoundTripper, 10*time.Minute) + client := &govmomi.Client{ + Client: vimClient, + SessionManager: session.NewManager(vimClient), + } + + err = client.SessionManager.Login(ctx, credentials) if err != nil { return nil, err } - client.RoundTripper = session.KeepAlive(client.RoundTripper, 10*time.Minute) finder := find.NewFinder(client.Client, false) datacenter, err := finder.DatacenterOrDefault(ctx, config.Datacenter) From d1b2b768435d370a978af7b594cd525cb667574c Mon Sep 17 00:00:00 2001 From: Andrei Tonkikh Date: Wed, 15 Nov 2017 00:19:32 +0300 Subject: [PATCH 12/12] Add more acceptance tests for VM. Merge them into 1 table-driven test --- builder_acc_test.go | 33 ++++++- driver/test.sh | 1 - driver/vm.go | 6 +- driver/vm_acc_test.go | 225 ++++++++++++++++++++++++++---------------- 4 files changed, 173 insertions(+), 92 deletions(-) diff --git a/builder_acc_test.go b/builder_acc_test.go index 8ac8f25bf..43b496da8 100644 --- a/builder_acc_test.go +++ b/builder_acc_test.go @@ -1,13 +1,13 @@ package main import ( - "testing" - builderT "github.com/hashicorp/packer/helper/builder/testing" + "encoding/json" "fmt" + builderT "github.com/hashicorp/packer/helper/builder/testing" "github.com/hashicorp/packer/packer" - "encoding/json" - "math/rand" "github.com/jetbrains-infra/packer-builder-vsphere/driver" + "math/rand" + "testing" ) func TestBuilderAcc_default(t *testing.T) { @@ -74,7 +74,7 @@ func checkDefault(t *testing.T, name string, host string, datastore string) buil t.Fatalf("Cannot read resource pool name: %v", err) } if poolPath != "" { - t.Error("Invalid resource pool: expected '/', got '%v'", poolPath) + t.Errorf("Invalid resource pool: expected '/', got '%v'", poolPath) } dsr := vmInfo.Datastore[0].Reference() @@ -135,6 +135,29 @@ func folderConfig() string { return renderConfig(config) } +func checkFolder(t *testing.T, folder string) builderT.TestCheckFunc { + return func(artifacts []packer.Artifact) error { + d := testConn(t) + vm := getVM(t, d, artifacts) + + vmInfo, err := vm.Info("parent") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) + } + + f := d.NewFolder(vmInfo.Parent) + path, err := f.Path() + if err != nil { + t.Fatalf("Cannot read folder name: %v", err) + } + if path != folder { + t.Errorf("Wrong folder. expected: %v, got: %v", folder, path) + } + + return nil + } +} + func TestBuilderAcc_resourcePool(t *testing.T) { builderT.Test(t, builderT.TestCase{ Builder: &Builder{}, diff --git a/driver/test.sh b/driver/test.sh index a2bf973cb..14607e82e 100755 --- a/driver/test.sh +++ b/driver/test.sh @@ -1,5 +1,4 @@ #!/bin/sh export VSPHERE_DRIVER_ACC=1 -cd testing go test -v "$@" diff --git a/driver/vm.go b/driver/vm.go index 967264fc9..e5536836e 100644 --- a/driver/vm.go +++ b/driver/vm.go @@ -1,12 +1,12 @@ package driver import ( + "errors" + "fmt" "github.com/vmware/govmomi/object" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" - "errors" "time" - "fmt" ) type VirtualMachine struct { @@ -88,7 +88,7 @@ func (template *VirtualMachine) Clone(config *CloneConfig) (*VirtualMachine, err info, err := host.Info("datastore") if err != nil { - return nil, err + return nil, err } if len(info.Datastore) > 1 { diff --git a/driver/vm_acc_test.go b/driver/vm_acc_test.go index 921aca22a..ccde75b47 100644 --- a/driver/vm_acc_test.go +++ b/driver/vm_acc_test.go @@ -2,65 +2,82 @@ package driver import ( "log" - "testing" "net" + "testing" "time" ) -func initVMAccTest(t *testing.T) (d *Driver, vm *VirtualMachine, vmName string, vmDestructor func()) { +func TestVMAcc_clone(t *testing.T) { initDriverAcceptanceTest(t) - templateName := "alpine" - d = newTestDriver(t) - - template, err := d.FindVM(templateName) // Don't destroy this VM! - if err != nil { - t.Fatalf("Cannot find template vm '%v': %v", templateName, err) + testCases := []struct { + name string + config *CloneConfig + checkFunction func(*testing.T, *VirtualMachine, *CloneConfig) + }{ + {"Default", &CloneConfig{}, cloneDefaultCheck}, + {"LinkedClone", &CloneConfig{LinkedClone: true}, cloneLinkedCloneCheck}, + {"Folder", &CloneConfig{LinkedClone: true, Folder: "folder1/folder2"}, cloneFolderCheck}, + {"ResourcePool", &CloneConfig{LinkedClone: true, ResourcePool: "pool1/pool2"}, cloneResourcePoolCheck}, + {"Configure", &CloneConfig{LinkedClone: true}, configureCheck}, + {"Configure_RAMReserveAll", &CloneConfig{LinkedClone: true}, configureRAMReserveAllCheck}, + {"StartAndStop", &CloneConfig{LinkedClone: true}, startAndStopCheck}, + {"Template", &CloneConfig{LinkedClone: true}, templateCheck}, + {"Snapshot", &CloneConfig{}, snapshotCheck}, } - log.Printf("[DEBUG] Clonning VM") - vmName = newVMName() - vm, err = template.Clone(&CloneConfig{ - Name: vmName, - Host: hostName, - }) - if err != nil { - t.Fatalf("Cannot clone vm '%v': %v", templateName, err) - } - - vmDestructor = func() { - log.Printf("[DEBUG] Removing the clone") - if err := vm.Destroy(); err != nil { - t.Errorf("!!! ERROR REMOVING VM '%v': %v!!!", vmName, err) - } - - // Check that the clone is no longer exists - if _, err := d.FindVM(vmName); err == nil { - t.Errorf("!!! STILL CAN FIND VM '%v'. IT MIGHT NOT HAVE BEEN DELETED !!!", vmName) - } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + tc.config.Host = hostName + tc.config.Name = newVMName() + + templateName := "alpine" + d := newTestDriver(t) + + template, err := d.FindVM(templateName) // Don't destroy this VM! + if err != nil { + t.Fatalf("Cannot find template vm '%v': %v", templateName, err) + } + + log.Printf("[DEBUG] Clonning VM") + vm, err := template.Clone(tc.config) + if err != nil { + t.Fatalf("Cannot clone vm '%v': %v", templateName, err) + } + + defer func() { + log.Printf("[DEBUG] Removing the clone") + if err := vm.Destroy(); err != nil { + t.Errorf("!!! ERROR REMOVING VM '%v': %v!!!", tc.config.Name, err) + } + + // Check that the clone is no longer exists + if _, err := d.FindVM(tc.config.Name); err == nil { + t.Errorf("!!! STILL CAN FIND VM '%v'. IT MIGHT NOT HAVE BEEN DELETED !!!", tc.config.Name) + } + }() + + log.Printf("[DEBUG] Running check function") + tc.checkFunction(t, vm, tc.config) + }) } - - return } -func TestVMAcc_default(t *testing.T) { - d, vm, vmName, vmDestructor := initVMAccTest(t) - defer vmDestructor() +func cloneDefaultCheck(t *testing.T, vm *VirtualMachine, config *CloneConfig) { + d := vm.driver // Check that the clone can be found by its name - if _, err := d.FindVM(vmName); err != nil { - t.Errorf("Cannot find created vm '%v': %v", vmName, err) + if _, err := d.FindVM(config.Name); err != nil { + t.Errorf("Cannot find created vm '%v': %v", config.Name, err) } - // Run checks - log.Printf("[DEBUG] Running checks") vmInfo, err := vm.Info("name", "parent", "runtime.host", "resourcePool", "datastore", "layoutEx.disk") if err != nil { t.Fatalf("Cannot read VM properties: %v", err) } - if vmInfo.Name != vmName { - t.Errorf("Invalid VM name: expected '%v', got '%v'", vmName, vmInfo.Name) + if vmInfo.Name != config.Name { + t.Errorf("Invalid VM name: expected '%v', got '%v'", config.Name, vmInfo.Name) } f := d.NewFolder(vmInfo.Parent) @@ -87,7 +104,7 @@ func TestVMAcc_default(t *testing.T) { t.Fatalf("Cannot read resource pool name: %v", err) } if poolPath != "" { - t.Error("Invalid resource pool: expected '/', got '%v'", poolPath) + t.Errorf("Invalid resource pool: expected '/', got '%v'", poolPath) } dsr := vmInfo.Datastore[0].Reference() @@ -105,23 +122,16 @@ func TestVMAcc_default(t *testing.T) { } } -func TestVMAcc_folder(t *testing.T) { - -} - -func TestVMAcc_hardware(t *testing.T) { - _ /*d*/, vm, _ /*vmName*/, vmDestructor := initVMAccTest(t) - defer vmDestructor() - +func configureCheck(t *testing.T, vm *VirtualMachine, _ *CloneConfig) { log.Printf("[DEBUG] Configuring the vm") - config := &HardwareConfig{ + hwConfig := &HardwareConfig{ CPUs: 2, CPUReservation: 1000, CPULimit: 1500, RAM: 2048, RAMReservation: 1024, } - vm.Configure(config) + vm.Configure(hwConfig) log.Printf("[DEBUG] Running checks") vmInfo, err := vm.Info("config") @@ -130,54 +140,96 @@ func TestVMAcc_hardware(t *testing.T) { } cpuSockets := vmInfo.Config.Hardware.NumCPU - if cpuSockets != config.CPUs { - t.Errorf("VM should have %v CPU sockets, got %v", config.CPUs, cpuSockets) + if cpuSockets != hwConfig.CPUs { + t.Errorf("VM should have %v CPU sockets, got %v", hwConfig.CPUs, cpuSockets) } cpuReservation := vmInfo.Config.CpuAllocation.GetResourceAllocationInfo().Reservation - if cpuReservation != config.CPUReservation { - t.Errorf("VM should have CPU reservation for %v Mhz, got %v", config.CPUReservation, cpuReservation) + if cpuReservation != hwConfig.CPUReservation { + t.Errorf("VM should have CPU reservation for %v Mhz, got %v", hwConfig.CPUReservation, cpuReservation) } cpuLimit := vmInfo.Config.CpuAllocation.GetResourceAllocationInfo().Limit - if cpuLimit != config.CPULimit { - t.Errorf("VM should have CPU reservation for %v Mhz, got %v", config.CPULimit, cpuLimit) + if cpuLimit != hwConfig.CPULimit { + t.Errorf("VM should have CPU reservation for %v Mhz, got %v", hwConfig.CPULimit, cpuLimit) } ram := vmInfo.Config.Hardware.MemoryMB - if int64(ram) != config.RAM { - t.Errorf("VM should have %v MB of RAM, got %v", config.RAM, ram) + if int64(ram) != hwConfig.RAM { + t.Errorf("VM should have %v MB of RAM, got %v", hwConfig.RAM, ram) } ramReservation := vmInfo.Config.MemoryAllocation.GetResourceAllocationInfo().Reservation - if ramReservation != config.RAMReservation { - t.Errorf("VM should have RAM reservation for %v MB, got %v", config.RAMReservation, ramReservation) + if ramReservation != hwConfig.RAMReservation { + t.Errorf("VM should have RAM reservation for %v MB, got %v", hwConfig.RAMReservation, ramReservation) } } -func startVM(t *testing.T, vm *VirtualMachine, vmName string) (stopper func()) { - log.Printf("[DEBUG] Starting the vm") - if err := vm.PowerOn(); err != nil { - t.Fatalf("Cannot start created vm '%v': %v", vmName, err) +func configureRAMReserveAllCheck(t *testing.T, vm *VirtualMachine, _ *CloneConfig) { + log.Printf("[DEBUG] Configuring the vm") + vm.Configure(&HardwareConfig{ RAMReserveAll: true }) + + log.Printf("[DEBUG] Running checks") + vmInfo, err := vm.Info("config") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) } - return func() { - log.Printf("[DEBUG] Powering off the vm") - if err := vm.PowerOff(); err != nil { - t.Errorf("Cannot power off started vm '%v': %v", vmName, err) - } + + if *vmInfo.Config.MemoryReservationLockedToMax != true { + t.Errorf("VM should have all RAM reserved") + } +} + +func cloneLinkedCloneCheck(t *testing.T, vm *VirtualMachine, _ *CloneConfig) { + vmInfo, err := vm.Info("layoutEx.disk") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) + } + + if len(vmInfo.LayoutEx.Disk[0].Chain) != 2 { + t.Error("Not a linked clone") + } +} + +func cloneFolderCheck(t *testing.T, vm *VirtualMachine, config *CloneConfig) { + vmInfo, err := vm.Info("parent") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) + } + + f := vm.driver.NewFolder(vmInfo.Parent) + path, err := f.Path() + if err != nil { + t.Fatalf("Cannot read folder name: %v", err) + } + if path != config.Folder { + t.Errorf("Wrong folder. expected: %v, got: %v", config.Folder, path) } } -func TestVMAcc_running(t *testing.T) { - _ /*d*/, vm, vmName, vmDestructor := initVMAccTest(t) - defer vmDestructor() +func cloneResourcePoolCheck(t *testing.T, vm *VirtualMachine, config *CloneConfig) { + vmInfo, err := vm.Info("resourcePool") + if err != nil { + t.Fatalf("Cannot read VM properties: %v", err) + } + + p := vm.driver.NewResourcePool(vmInfo.ResourcePool) + path, err := p.Path() + if err != nil { + t.Fatalf("Cannot read resource pool name: %v", err) + } + if path != config.ResourcePool { + t.Errorf("Wrong folder. expected: %v, got: %v", config.ResourcePool, path) + } +} - stopper := startVM(t, vm, vmName) +func startAndStopCheck(t *testing.T, vm *VirtualMachine, config *CloneConfig) { + stopper := startVM(t, vm, config.Name) defer stopper() switch ip, err := vm.WaitForIP(); { case err != nil: - t.Errorf("Cannot obtain IP address from created vm '%v': %v", vmName, err) + t.Errorf("Cannot obtain IP address from created vm '%v': %v", config.Name, err) case net.ParseIP(ip) == nil: t.Errorf("'%v' is not a valid ip address", ip) } @@ -187,11 +239,8 @@ func TestVMAcc_running(t *testing.T) { vm.WaitForShutdown(1 * time.Minute) } -func TestVMAcc_snapshot(t *testing.T) { - _ /*d*/, vm, vmName, vmDestructor := initVMAccTest(t) - defer vmDestructor() - - stopper := startVM(t, vm, vmName) +func snapshotCheck(t *testing.T, vm *VirtualMachine, config *CloneConfig) { + stopper := startVM(t, vm, config.Name) defer stopper() vm.CreateSnapshot("test-snapshot") @@ -207,10 +256,7 @@ func TestVMAcc_snapshot(t *testing.T) { } } -func TestVMAcc_template(t *testing.T) { - _ /*d*/, vm, _ /*vmName*/, vmDestructor := initVMAccTest(t) - defer vmDestructor() - +func templateCheck(t *testing.T, vm *VirtualMachine, _ *CloneConfig) { vm.ConvertToTemplate() vmInfo, err := vm.Info("config.template") if err != nil { @@ -219,3 +265,16 @@ func TestVMAcc_template(t *testing.T) { t.Error("Not a template") } } + +func startVM(t *testing.T, vm *VirtualMachine, vmName string) (stopper func()) { + log.Printf("[DEBUG] Starting the vm") + if err := vm.PowerOn(); err != nil { + t.Fatalf("Cannot start vm '%v': %v", vmName, err) + } + return func() { + log.Printf("[DEBUG] Powering off the vm") + if err := vm.PowerOff(); err != nil { + t.Errorf("Cannot power off started vm '%v': %v", vmName, err) + } + } +}