diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 85ee62c..d523386 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -22,13 +22,12 @@ Add needed variables/secrets to github project: HC_PASSWORD=todo ``` -TEMP: create VM named `testtf-src`. - Prior to running acceptance tests we need to setup: 1. Virtual machine - a. has one disk + a. has one disk, type VIRTIO, size 1.2 GB b. has one nic c. boot order is configured as [disk, nic] 2. Virtual disk (as standalone not attached to the testing VM) 3. Add names and UUIDs to the env.txt file in /tests/acceptance/setup directory + - There are multiple env-*.txt files, for different test HyperCore clusters. 4. Virtual machine needs to be powered off diff --git a/GNUmakefile b/GNUmakefile index 0655769..cfee16a 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -54,6 +54,7 @@ test: ## run unit tests go test -v -cover -timeout=120s -parallel=10 ./... testacc: ## acceptance tests + set -a; . ./internal/provider/tests/acceptance/setup/env.txt; set +a; \ TF_ACC=1 go test -v -cover -count=1 -timeout 120m ./... .PHONY: help all local_provider fmt lint test testacc build install generate force_reinit_local apply_with_logs run diff --git a/internal/provider/tests/acceptance/hypercore_vm_resource_clone_acc_test.go b/internal/provider/tests/acceptance/hypercore_vm_resource_clone_acc_test.go index 6f09351..163cadd 100644 --- a/internal/provider/tests/acceptance/hypercore_vm_resource_clone_acc_test.go +++ b/internal/provider/tests/acceptance/hypercore_vm_resource_clone_acc_test.go @@ -8,12 +8,10 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-hypercore/internal/utils" ) -// UUID of VM with name "testtf_src" -// var testtf_src_uuid string = "27af8248-88ee-4420-85d7-78b735415064" // https://172.31.6.11 -var testtf_src_uuid string = "ff36479e-06bb-4141-bad5-0097c8c1a4a6" // https://10.5.11.205 - func TestAccHypercoreVMResourceClone(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -21,19 +19,23 @@ func TestAccHypercoreVMResourceClone(t *testing.T) { Steps: []resource.TestStep{ // Create and Read testing { - Config: testAccHypercoreVMResourceCloneConfig("testtf-vm", testtf_src_uuid), + Config: testAccHypercoreVMResourceCloneConfig("testtf-vm"), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("hypercore_vm.test", "description", "testtf-vm-description"), resource.TestCheckResourceAttr("hypercore_vm.test", "memory", "4096"), resource.TestCheckResourceAttr("hypercore_vm.test", "group", "testtf"), resource.TestCheckResourceAttr("hypercore_vm.test", "clone.meta_data", ""), resource.TestCheckResourceAttr("hypercore_vm.test", "clone.user_data", ""), - resource.TestCheckResourceAttr("hypercore_vm.test", "clone.source_vm_uuid", testtf_src_uuid), + resource.TestCheckResourceAttr("hypercore_vm.test", "clone.source_vm_uuid", source_vm_uuid), resource.TestCheckResourceAttr("hypercore_vm.test", "name", "testtf-vm"), resource.TestCheckResourceAttr("hypercore_vm.test", "vcpu", "4"), // resource.TestCheckResourceAttr("hypercore_vm.test", "power_state", requested_power_state), ), }, + { + Config: testAccHypercoreVMResourceCloneConfig("testtf-vm"), + Check: checkDiskSize, + }, // TODO make ImportState test pass again. /* // ImportState testing @@ -63,7 +65,7 @@ func TestAccHypercoreVMResourceClone(t *testing.T) { */ // Update and Read testing { - Config: testAccHypercoreVMResourceCloneConfig("testtf-vm", testtf_src_uuid), + Config: testAccHypercoreVMResourceCloneConfig("testtf-vm"), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("hypercore_vm.test", "name", "testtf-vm"), resource.TestCheckResourceAttr("hypercore_vm.test", "description", "testtf-vm-description"), @@ -78,7 +80,31 @@ func TestAccHypercoreVMResourceClone(t *testing.T) { }) } -func testAccHypercoreVMResourceCloneConfig(vm_name string, source_vm_uuid string) string { +func checkDiskSize(s *terraform.State) error { + vm_name := "testtf-vm" + expected_disk_size_b := 1.2 * 1000 * 1000 * 1000 + + restClient := SetupRestClient() + // query := map[string]any{} + // restClient.ListRecords("/rest/v1/VirDomain", query, 60.0, false) + query := map[string]any{"name": vm_name} + all_vms := utils.GetVM(query, *restClient) + if len(all_vms) != 1 { + return fmt.Errorf("Expected exactly one VM with name %s, got %d VMs", vm_name, len(all_vms)) + } + vm := all_vms[0] + disks := utils.AnyToListOfMap(vm["blockDevs"]) + if len(disks) != 1 { + return fmt.Errorf("Expected exactly one disk, VM name %s, got %d disks", vm_name, len(disks)) + } + disk_size_b := utils.AnyToFloat64(disks[0]["capacity"]) + if disk_size_b != expected_disk_size_b { + return fmt.Errorf("Expected disk size %f, VM name %s, got %f size", expected_disk_size_b, vm_name, disk_size_b) + } + return nil +} + +func testAccHypercoreVMResourceCloneConfig(vm_name string) string { return fmt.Sprintf(` resource "hypercore_vm" "test" { name = %[1]q diff --git a/internal/provider/tests/acceptance/provider_acc_test.go b/internal/provider/tests/acceptance/provider_acc_test.go index dc05ec6..2df1c8a 100644 --- a/internal/provider/tests/acceptance/provider_acc_test.go +++ b/internal/provider/tests/acceptance/provider_acc_test.go @@ -10,9 +10,11 @@ import ( "github.com/hashicorp/terraform-plugin-framework/providerserver" "github.com/hashicorp/terraform-plugin-go/tfprotov6" "github.com/hashicorp/terraform-provider-hypercore/internal/provider" + "github.com/hashicorp/terraform-provider-hypercore/internal/utils" ) var source_vm_name = os.Getenv("SOURCE_VM_NAME") +var source_vm_uuid = os.Getenv("SOURCE_VM_UUID") var existing_vdisk_uuid = os.Getenv("EXISTING_VDISK_UUID") var source_nic_uuid = os.Getenv("SOURCE_NIC_UUID") var source_disk_uuid = os.Getenv("SOURCE_DISK_UUID") @@ -36,4 +38,48 @@ func testAccPreCheck(t *testing.T) { // Prechecks // Don't use terraform CRUD operations here, this is ran prior to the test and will not cleanup + // Check environ variables are loaded (env.txt file) + mandatory_env_vars := []string{ + "SOURCE_VM_NAME", + "SOURCE_VM_UUID", + "EXISTING_VDISK_UUID", + "SOURCE_NIC_UUID", + "SOURCE_DISK_UUID", + "SMB_SERVER", + "SMB_USERNAME", + "SMB_PASSWORD", + "SMB_PATH", + "SMB_FILENAME", + } + for _, key := range mandatory_env_vars { + value := os.Getenv(key) + if value == "" { + t.Fatalf("Environ variable %s must be set for acceptance tests", key) + } + } +} + +var testAccRestClient *utils.RestClient + +func SetupRestClient() *utils.RestClient { + scHost := os.Getenv("HC_HOST") + scUsername := os.Getenv("HC_USERNAME") + scPassword := os.Getenv("HC_PASSWORD") + scAuthMethod := os.Getenv("HC_AUTH_METHOD") + scTimeoutF := 60.0 + // scTimeout := os.Getenv("HC_TIMEOUT") + + if testAccRestClient == nil { + testAccRestClient, _ = utils.NewRestClient( + scHost, + scUsername, + scPassword, + scAuthMethod, + scTimeoutF, + ) + testAccRestClient.Login() + // tflog.Debug(ctx, fmt.Sprintf("Logged in with session ID: %s\n", restClient.AuthHeader["Cookie"])) + } + + return testAccRestClient } diff --git a/internal/provider/tests/acceptance/setup/env-205.txt b/internal/provider/tests/acceptance/setup/env-205.txt new file mode 100644 index 0000000..a8b2aef --- /dev/null +++ b/internal/provider/tests/acceptance/setup/env-205.txt @@ -0,0 +1,12 @@ +HC_VM_SHUTDOWN_TIMEOUT=30 + +SOURCE_VM_UUID="97904009-1878-4881-b6df-83c85ab7dc1a" +EXISTING_VDISK_UUID="33c78baf-c3c6-4600-8432-9c7a2a3008ab" +SOURCE_VM_NAME="integration-test-vm" +SOURCE_NIC_UUID="7a79893f-129f-4d35-8800-35a947ff4a51" +SOURCE_DISK_UUID="c508da75-eb88-401e-9c29-4563d1574555" +SMB_SERVER="x" +SMB_USERNAME="x" +SMB_PASSWORD="x" +SMB_PATH="x" +SMB_FILENAME="x" diff --git a/internal/provider/tests/acceptance/setup/env-x11.txt b/internal/provider/tests/acceptance/setup/env-x11.txt new file mode 100644 index 0000000..4a7d66c --- /dev/null +++ b/internal/provider/tests/acceptance/setup/env-x11.txt @@ -0,0 +1,13 @@ +HC_VM_SHUTDOWN_TIMEOUT=30 + +SOURCE_VM_UUID="c6ce1356-7487-4fd3-97f4-bff1c3b3d86a" +# testtf-ci-virtual-disk.img - https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/cloud/generic_alpine-3.21.2-x86_64-bios-tiny-r0.qcow2 +EXISTING_VDISK_UUID="ac8c5105-6c42-474b-a445-61fc32e177e9" +SOURCE_VM_NAME="integration-test-vm" +SOURCE_NIC_UUID="e51c9076-b1ec-438a-8485-d653b627cdcb" +SOURCE_DISK_UUID="3c4db35c-c38c-4cdb-999a-46632058d29a" +SMB_SERVER="x" +SMB_USERNAME="x" +SMB_PASSWORD="x" +SMB_PATH="x" +SMB_FILENAME="x" diff --git a/internal/provider/tests/acceptance/setup/env.txt b/internal/provider/tests/acceptance/setup/env.txt deleted file mode 100644 index ea8e7bf..0000000 --- a/internal/provider/tests/acceptance/setup/env.txt +++ /dev/null @@ -1,7 +0,0 @@ -HC_VM_SHUTDOWN_TIMEOUT=30 - -SOURCE_VM_UUID="97904009-1878-4881-b6df-83c85ab7dc1a" -EXISTING_VDISK_UUID="33c78baf-c3c6-4600-8432-9c7a2a3008ab" -SOURCE_VM_NAME="integration-test-vm" -SOURCE_NIC_UUID="7a79893f-129f-4d35-8800-35a947ff4a51" -SOURCE_DISK_UUID="46dac49c-9726-4e4f-950f-f2b06fcf2e24" diff --git a/internal/provider/tests/acceptance/setup/env.txt b/internal/provider/tests/acceptance/setup/env.txt new file mode 120000 index 0000000..184db6c --- /dev/null +++ b/internal/provider/tests/acceptance/setup/env.txt @@ -0,0 +1 @@ +env-205.txt \ No newline at end of file diff --git a/internal/utils/vm.go b/internal/utils/vm.go index 327e6a5..c57b804 100644 --- a/internal/utils/vm.go +++ b/internal/utils/vm.go @@ -605,6 +605,10 @@ func GetOneVM(uuid string, restClient RestClient) map[string]any { if len(records) == 0 { panic(fmt.Errorf("VM not found: uuid=%v", uuid)) } + if len(records) > 1 { + // uuid == "" + panic(fmt.Errorf("Multiple VMs found: uuid=%v", uuid)) + } return records[0] } diff --git a/local/env.sh.example b/local/env.sh.example index 05a3d53..04a8a94 100644 --- a/local/env.sh.example +++ b/local/env.sh.example @@ -14,3 +14,4 @@ export HC_PASSWORD=hypercore-password # optionals export HC_AUTH_METHOD=local export HC_TIMEOUT=60.0 +export HC_VM_SHUTDOWN_TIMEOUT=300