From d1b2b768435d370a978af7b594cd525cb667574c Mon Sep 17 00:00:00 2001 From: Andrei Tonkikh Date: Wed, 15 Nov 2017 00:19:32 +0300 Subject: [PATCH] Add more acceptance tests for VM. Merge them into 1 table-driven test --- builder_acc_test.go | 35 +++++-- driver/test.sh | 1 - driver/vm.go | 6 +- driver/vm_acc_test.go | 225 ++++++++++++++++++++++++++---------------- 4 files changed, 174 insertions(+), 93 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" - "fmt" - "github.com/hashicorp/packer/packer" "encoding/json" - "math/rand" + "fmt" + builderT "github.com/hashicorp/packer/helper/builder/testing" + "github.com/hashicorp/packer/packer" "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) + 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) + }) } - - 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() +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 TestVMAcc_running(t *testing.T) { - _ /*d*/, vm, vmName, vmDestructor := initVMAccTest(t) - defer vmDestructor() +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) + } - stopper := startVM(t, vm, vmName) + 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 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) + } +} + +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) + } + } +}