github.com/swisspost/terratest@v0.0.0-20230214120104-7ec6de2e1ae0/test/azure/terraform_azure_vm_example_test.go (about) 1 //go:build azure || (azureslim && compute) 2 // +build azure azureslim,compute 3 4 // NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for 5 // CircleCI. 6 7 package test 8 9 import ( 10 "fmt" 11 "strings" 12 "testing" 13 14 "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute" 15 "github.com/gruntwork-io/terratest/modules/azure" 16 "github.com/gruntwork-io/terratest/modules/random" 17 "github.com/gruntwork-io/terratest/modules/terraform" 18 "github.com/stretchr/testify/assert" 19 ) 20 21 func TestTerraformAzureVmExample(t *testing.T) { 22 t.Parallel() 23 24 subscriptionID := "" 25 uniquePostfix := random.UniqueId() 26 27 // Configure Terraform setting up a path to Terraform code. 28 terraformOptions := &terraform.Options{ 29 // The path to where our Terraform code is located. 30 TerraformDir: "../../examples/azure/terraform-azure-vm-example", 31 32 // Variables to pass to our Terraform code using -var options. 33 Vars: map[string]interface{}{ 34 "postfix": uniquePostfix, 35 }, 36 } 37 38 // At the end of the test, run `terraform destroy` to clean up any resources that were created. 39 defer terraform.Destroy(t, terraformOptions) 40 41 // Run `terraform init` and `terraform apply`. Fail the test if there are any errors. 42 terraform.InitAndApply(t, terraformOptions) 43 44 // Run tests for the Virtual Machine. 45 testStrategiesForVMs(t, terraformOptions, subscriptionID) 46 testMultipleVMs(t, terraformOptions, subscriptionID) 47 testInformationOfVM(t, terraformOptions, subscriptionID) 48 testDisksOfVM(t, terraformOptions, subscriptionID) 49 testNetworkOfVM(t, terraformOptions, subscriptionID) 50 } 51 52 // These 3 tests check for the same property but illustrate different testing strategies for 53 // retriving the data. The first strategy is used in the other tests of this module while 54 // the other two can be extended by the user as needed. 55 func testStrategiesForVMs(t *testing.T, terraformOptions *terraform.Options, subscriptionID string) { 56 // Run `terraform output` to get the values of output variables. 57 resourceGroupName := terraform.Output(t, terraformOptions, "resource_group_name") 58 virtualMachineName := terraform.Output(t, terraformOptions, "vm_name") 59 expectedVMSize := compute.VirtualMachineSizeTypes(terraform.Output(t, terraformOptions, "vm_size")) 60 61 // 1. Check the VM Size directly. This strategy gets one specific property of the VM per method. 62 actualVMSize := azure.GetSizeOfVirtualMachine(t, virtualMachineName, resourceGroupName, subscriptionID) 63 assert.Equal(t, expectedVMSize, actualVMSize) 64 65 // 2. Check the VM size by reference. This strategy is beneficial when checking multiple properties 66 // by using one VM reference. Optional parameters have to be checked first to avoid nil panics. 67 vmByRef := azure.GetVirtualMachine(t, virtualMachineName, resourceGroupName, subscriptionID) 68 actualVMSize = vmByRef.HardwareProfile.VMSize 69 assert.Equal(t, expectedVMSize, actualVMSize) 70 71 // 3. Check the VM size by instance. This strategy is beneficial when checking multiple properties 72 // by using one VM instance and making calls against it with the added benefit of property check abstraction. 73 vmInstance := azure.Instance{VirtualMachine: vmByRef} 74 actualVMSize = vmInstance.GetVirtualMachineInstanceSize() 75 assert.Equal(t, expectedVMSize, actualVMSize) 76 } 77 78 // These tests check for the multiple Virtual Machines in a Resource Group. 79 func testMultipleVMs(t *testing.T, terraformOptions *terraform.Options, subscriptionID string) { 80 // Run `terraform output` to get the values of output variables. 81 resourceGroupName := terraform.Output(t, terraformOptions, "resource_group_name") 82 expectedVMName := terraform.Output(t, terraformOptions, "vm_name") 83 expectedVMSize := compute.VirtualMachineSizeTypes(terraform.Output(t, terraformOptions, "vm_size")) 84 expectedAvsName := terraform.Output(t, terraformOptions, "availability_set_name") 85 86 // Check against all VM names in a Resource Group. 87 vmList := azure.ListVirtualMachinesForResourceGroup(t, resourceGroupName, subscriptionID) 88 expectedVMCount := 1 89 assert.Equal(t, expectedVMCount, len(vmList)) 90 assert.Contains(t, vmList, expectedVMName) 91 92 // Check Availability Set for multiple VMs. 93 actualVMsInAvs := azure.GetAvailabilitySetVMNamesInCaps(t, expectedAvsName, resourceGroupName, subscriptionID) 94 assert.Contains(t, actualVMsInAvs, strings.ToUpper(expectedVMName)) 95 96 // Get all VMs in a Resource Group, including their properties, therefore avoiding 97 // multiple SDK calls. The penalty for this approach is introducing direct references 98 // which need to be checked for nil for optional configurations. 99 vmsByRef := azure.GetVirtualMachinesForResourceGroup(t, resourceGroupName, subscriptionID) 100 thisVM := vmsByRef[expectedVMName] 101 assert.Equal(t, expectedVMSize, thisVM.HardwareProfile.VMSize) 102 103 // Check for the VM negative test. 104 fakeVM := fmt.Sprintf("vm-%s", random.UniqueId()) 105 assert.Nil(t, vmsByRef[fakeVM].VMID) 106 } 107 108 // These tests check information directly related to the specified Azure Virtual Machine. 109 func testInformationOfVM(t *testing.T, terraformOptions *terraform.Options, subscriptionID string) { 110 // Run `terraform output` to get the values of output variables. 111 resourceGroupName := terraform.Output(t, terraformOptions, "resource_group_name") 112 virtualMachineName := terraform.Output(t, terraformOptions, "vm_name") 113 expectedVmAdminUser := terraform.OutputList(t, terraformOptions, "vm_admin_username") 114 expectedImageSKU := terraform.OutputList(t, terraformOptions, "vm_image_sku") 115 expectedImageVersion := terraform.OutputList(t, terraformOptions, "vm_image_version") 116 expectedAvsName := terraform.Output(t, terraformOptions, "availability_set_name") 117 expectedVMTags := terraform.OutputMap(t, terraformOptions, "vm_tags") 118 119 // Check if the Virtual Machine exists. 120 assert.True(t, azure.VirtualMachineExists(t, virtualMachineName, resourceGroupName, subscriptionID)) 121 122 // Check the Admin User of the VM. 123 actualVM := azure.GetVirtualMachine(t, virtualMachineName, resourceGroupName, subscriptionID) 124 actualVmAdminUser := *actualVM.OsProfile.AdminUsername 125 assert.Equal(t, expectedVmAdminUser[0], actualVmAdminUser) 126 127 // Check the Storage Image properties of the VM. 128 actualImage := azure.GetVirtualMachineImage(t, virtualMachineName, resourceGroupName, subscriptionID) 129 assert.Contains(t, expectedImageSKU[0], actualImage.SKU) 130 assert.Contains(t, expectedImageVersion[0], actualImage.Version) 131 132 // Check the Availability Set of the VM. 133 // The AVS ID returned from the VM is always CAPS so ignoring case in the assertion. 134 actualexpectedAvsName := azure.GetVirtualMachineAvailabilitySetID(t, virtualMachineName, resourceGroupName, subscriptionID) 135 assert.True(t, strings.EqualFold(expectedAvsName, actualexpectedAvsName)) 136 137 // Check the assigned Tags of the VM, assert empty if no tags. 138 actualVMTags := azure.GetVirtualMachineTags(t, virtualMachineName, resourceGroupName, "") 139 assert.Equal(t, expectedVMTags, actualVMTags) 140 } 141 142 // These tests check the OS Disk and Attached Managed Disks for the Azure Virtual Machine. 143 // The following Terratest Azure module is utilized in addition to the compute module: 144 // - disk 145 // See the terraform_azure_disk_example_test.go for other related tests. 146 func testDisksOfVM(t *testing.T, terraformOptions *terraform.Options, subscriptionID string) { 147 // Run `terraform output` to get the values of output variables. 148 resourceGroupName := terraform.Output(t, terraformOptions, "resource_group_name") 149 virtualMachineName := terraform.Output(t, terraformOptions, "vm_name") 150 expectedOSDiskName := terraform.Output(t, terraformOptions, "os_disk_name") 151 expectedDiskName := terraform.Output(t, terraformOptions, "managed_disk_name") 152 expectedDiskType := terraform.Output(t, terraformOptions, "managed_disk_type") 153 154 // Check the OS Disk name of the VM. 155 actualOSDiskName := azure.GetVirtualMachineOSDiskName(t, virtualMachineName, resourceGroupName, subscriptionID) 156 assert.Equal(t, expectedOSDiskName, actualOSDiskName) 157 158 // Check the VM Managed Disk exists in the list of all VM Managed Disks. 159 actualManagedDiskNames := azure.GetVirtualMachineManagedDisks(t, virtualMachineName, resourceGroupName, subscriptionID) 160 assert.Contains(t, actualManagedDiskNames, expectedDiskName) 161 162 // Check the Managed Disk count of the VM. 163 expectedManagedDiskCount := 1 164 assert.Equal(t, expectedManagedDiskCount, len(actualManagedDiskNames)) 165 166 // Check the Disk Type of the Managed Disk of the VM. 167 // This does not apply to VHD disks saved under a storage account. 168 actualDisk := azure.GetDisk(t, expectedDiskName, resourceGroupName, subscriptionID) 169 actualDiskType := actualDisk.Sku.Name 170 assert.Equal(t, compute.DiskStorageAccountTypes(expectedDiskType), actualDiskType) 171 } 172 173 // These tests check the underlying Virtual Network, Network Interface and associated Public IP Address. 174 // The following Terratest Azure modules are utilized in addition to the compute module: 175 // - networkinterface 176 // - publicaddress 177 // - virtualnetwork 178 // See the terraform_azure_network_example_test.go for other related tests. 179 func testNetworkOfVM(t *testing.T, terraformOptions *terraform.Options, subscriptionID string) { 180 // Run `terraform output` to get the values of output variables. 181 resourceGroupName := terraform.Output(t, terraformOptions, "resource_group_name") 182 virtualMachineName := terraform.Output(t, terraformOptions, "vm_name") 183 expectedVNetName := terraform.Output(t, terraformOptions, "virtual_network_name") 184 expectedSubnetName := terraform.Output(t, terraformOptions, "subnet_name") 185 expectedPublicAddressName := terraform.Output(t, terraformOptions, "public_ip_name") 186 expectedNicName := terraform.Output(t, terraformOptions, "network_interface_name") 187 expectedPrivateIPAddress := terraform.Output(t, terraformOptions, "private_ip") 188 189 // VirtualNetwork and Subnet tests 190 // Check the Subnet exists in the Virtual Network. 191 actualVnetSubnets := azure.GetVirtualNetworkSubnets(t, expectedVNetName, resourceGroupName, subscriptionID) 192 assert.NotNil(t, actualVnetSubnets[expectedVNetName]) 193 194 // Check the Private IP is in the Subnet Range. 195 actualVMNicIPInSubnet := azure.CheckSubnetContainsIP(t, expectedPrivateIPAddress, expectedSubnetName, expectedVNetName, resourceGroupName, subscriptionID) 196 assert.True(t, actualVMNicIPInSubnet) 197 198 // Network Interface Card tests 199 // Check the VM Network Interface exists in the list of all VM Network Interfaces. 200 actualNics := azure.GetVirtualMachineNics(t, virtualMachineName, resourceGroupName, subscriptionID) 201 assert.Contains(t, actualNics, expectedNicName) 202 203 // Check the Network Interface count of the VM. 204 expectedNICCount := 1 205 assert.Equal(t, expectedNICCount, len(actualNics)) 206 207 // Check for the Private IP in the NICs IP list. 208 actualPrivateIPAddress := azure.GetNetworkInterfacePrivateIPs(t, expectedNicName, resourceGroupName, subscriptionID) 209 assert.Contains(t, actualPrivateIPAddress, expectedPrivateIPAddress) 210 211 // Public IP Address test 212 // Check for the Public IP for the NIC. No expected value since it is assigned runtime. 213 actualPublicIP := azure.GetIPOfPublicIPAddressByName(t, expectedPublicAddressName, resourceGroupName, subscriptionID) 214 assert.NotNil(t, actualPublicIP) 215 216 }