diff --git a/README.md b/README.md index 1044d8c949..9a3e69159d 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![CircleCI](https://circleci.com/gh/gruntwork-io/terratest.svg?style=svg&circle-token=e48019e09fc3b8bf6e0315a84048501c87c4157c)](https://circleci.com/gh/gruntwork-io/terratest) [![Go Report Card](https://goreportcard.com/badge/github.com/gruntwork-io/terratest)](https://goreportcard.com/report/github.com/gruntwork-io/terratest) [![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/gruntwork-io/terratest?tab=overview) +![go.mod version](https://img.shields.io/github/go-mod/go-version/gruntwork-io/terratest) Terratest is a Go library that makes it easier to write automated tests for your infrastructure code. It provides a diff --git a/examples/azure/README.md b/examples/azure/README.md index f1027de515..8dbca3ec8c 100644 --- a/examples/azure/README.md +++ b/examples/azure/README.md @@ -1,13 +1,13 @@ # Terratest Configuration and Setup -Terratest uses Go to make calls to Azure through the azure-sdk-for-go library and independently confirm the actual Azure resource property matches the expected state provided by Terraform output variables. +Terratest uses Go to make calls to Azure through the azure-sdk-for-go library and independently confirm the actual Azure resource property matches the expected state provided by Terraform output variables. -* Instructions for running each Azure Terratest module are included in each Terraform example sub-folder: - * examples/azure/terraform-azure-*-example/README.md -* Tests wich assert against expected Terraform output values are located in the the respective go files of the folder: - * [test/azure/terraform-azure-*-example_test.go](../../test/azure) -* Test APIs which provide the actual Azure resource property values via the azure-sdk-for-go are located in the folder: - * [modules/azure](../../modules/azure) +- Instructions for running each Azure Terratest module are included in each Terraform example sub-folder: + - examples/azure/terraform-azure-\*-example/README.md +- Tests which assert against expected Terraform output values are located in the the respective go files of the folder: + - [test/azure/terraform-azure-\*-example_test.go](../../test/azure) +- Test APIs which provide the actual Azure resource property values via the azure-sdk-for-go are located in the folder: + - [modules/azure](../../modules/azure) ## Go Dependencies @@ -44,7 +44,7 @@ export ARM_SUBSCRIPTION_ID=your_subscription_id export ARM_TENANT_ID=your_tenant_id ``` -Note, in a Windows environment, these should be set as **system environment variables**. We can use a PowerShell console with administrative rights to update these environment variables: +Note, in a Windows environment, these should be set as **system environment variables**. We can use a PowerShell console with administrative rights to update these environment variables: ```powershell [System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID",$your_app_id,[System.EnvironmentVariableTarget]::Machine) diff --git a/examples/azure/terraform-azure-resourcegroup-example/README.md b/examples/azure/terraform-azure-resourcegroup-example/README.md index 26d305186c..c4df1901a0 100644 --- a/examples/azure/terraform-azure-resourcegroup-example/README.md +++ b/examples/azure/terraform-azure-resourcegroup-example/README.md @@ -5,11 +5,7 @@ how you can use TerraTest to write automated tests for your Azure Terraform code - A [Resource Group](https://docs.microsoft.com/azure/azure-resource-manager/management/overview) with no other resources. - -* A [Resource Group](https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/overview) that gives the module the following: - * [Resource Group](https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/overview) with the value specified in the `resource_group_name` output variable. - -Check out [test/azure/terraform_azure_@module@_test.go](/test/azure/terraform_azure_@module@_test.go) to see how you can write +Check out [test/azure/terraform_azure_resourcegroup_example_test.go](/test/azure/terraform_azure_resourcegroup_example_test.go) to see how you can write automated tests for this module. Note that the Resource Group this module creates does not actually do anything; it just runs the resources for @@ -21,7 +17,7 @@ it should be free, but you are completely responsible for all Azure charges. ## Running this module manually -1. Sign up for [Azure](https://azure.microsoft.com/). +1. Sign up for [Azure](https://azure.microsoft.com/) 1. Configure your Azure credentials using one of the [supported methods for Azure CLI tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest) 1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH` @@ -32,7 +28,7 @@ it should be free, but you are completely responsible for all Azure charges. ## Running automated tests against this module -1. Sign up for [Azure](https://azure.microsoft.com/). +1. Sign up for [Azure](https://azure.microsoft.com/) 1. Configure your Azure credentials using one of the [supported methods for Azure CLI tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest) 1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH` diff --git a/examples/azure/terraform-azure-resourcegroup-example/variables.tf b/examples/azure/terraform-azure-resourcegroup-example/variables.tf index da4edf651a..0adb7137a9 100644 --- a/examples/azure/terraform-azure-resourcegroup-example/variables.tf +++ b/examples/azure/terraform-azure-resourcegroup-example/variables.tf @@ -1,3 +1,23 @@ +# --------------------------------------------------------------------------------------------------------------------- +# ENVIRONMENT VARIABLES +# Define these secrets as environment variables +# --------------------------------------------------------------------------------------------------------------------- + +# ARM_CLIENT_ID +# ARM_CLIENT_SECRET +# ARM_SUBSCRIPTION_ID +# ARM_TENANT_ID + +# --------------------------------------------------------------------------------------------------------------------- +# REQUIRED PARAMETERS +# You must provide a value for each of these parameters. +# --------------------------------------------------------------------------------------------------------------------- + +# --------------------------------------------------------------------------------------------------------------------- +# OPTIONAL PARAMETERS +# These parameters have reasonable defaults. +# --------------------------------------------------------------------------------------------------------------------- + variable "location" { description = "The location to set for the resource group." type = string @@ -7,5 +27,8 @@ variable "location" { variable "postfix" { description = "A postfix string to centrally mitigate resource name collisions." type = string - default = "terratest-resource-group" + default = "resource" } + + + diff --git a/go.sum b/go.sum index a576f9d856..9494f729a1 100644 --- a/go.sum +++ b/go.sum @@ -399,6 +399,7 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vdemeester/k8s-pkg-credentialprovider v0.0.0-20200107171650-7c61ffa44238/go.mod h1:JwQJCMWpUDqjZrB5jpw0f5VbN7U95zxFy1ZDpoEarGo= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= diff --git a/modules/azure/availabilityset.go b/modules/azure/availabilityset.go index 35691f04ec..8dc5cf2db9 100644 --- a/modules/azure/availabilityset.go +++ b/modules/azure/availabilityset.go @@ -5,23 +5,23 @@ import ( "strings" "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute" - "github.com/gruntwork-io/terratest/modules/collections" "github.com/gruntwork-io/terratest/modules/testing" "github.com/stretchr/testify/require" ) -// AvailabilitySetExists indicates whether the speficied Azure Availability Set exists +// AvailabilitySetExists indicates whether the specified Azure Availability Set exists. +// This function would fail the test if there is an error. func AvailabilitySetExists(t testing.TestingT, avsName string, resGroupName string, subscriptionID string) bool { exists, err := AvailabilitySetExistsE(t, avsName, resGroupName, subscriptionID) require.NoError(t, err) return exists } -// AvailabilitySetExistsE indicates whether the speficied Azure Availability Set exists +// AvailabilitySetExistsE indicates whether the specified Azure Availability Set exists func AvailabilitySetExistsE(t testing.TestingT, avsName string, resGroupName string, subscriptionID string) (bool, error) { _, err := GetAvailabilitySetE(t, avsName, resGroupName, subscriptionID) if err != nil { - if strings.Contains(err.Error(), "ResourceNotFound") { + if ResourceNotFoundErrorExists(err) { return false, nil } return false, err @@ -29,25 +29,48 @@ func AvailabilitySetExistsE(t testing.TestingT, avsName string, resGroupName str return true, nil } -// CheckAvailabilitySetContainsVM checks if the Virtual Machine is contained in the Availability Set VMs +// CheckAvailabilitySetContainsVM checks if the Virtual Machine is contained in the Availability Set VMs. +// This function would fail the test if there is an error. func CheckAvailabilitySetContainsVM(t testing.TestingT, vmName string, avsName string, resGroupName string, subscriptionID string) bool { - avsVMs, err := GetAvailabilitySetVMsE(t, avsName, resGroupName, subscriptionID) + success, err := CheckAvailabilitySetContainsVME(t, vmName, avsName, resGroupName, subscriptionID) + require.NoError(t, err) + return success +} + +// CheckAvailabilitySetContainsVME checks if the Virtual Machine is contained in the Availability Set VMs +func CheckAvailabilitySetContainsVME(t testing.TestingT, vmName string, avsName string, resGroupName string, subscriptionID string) (bool, error) { + client, err := GetAvailabilitySetClientE(subscriptionID) + if err != nil { + return false, err + } + + // Get the Availability Set + avs, err := client.Get(context.Background(), resGroupName, avsName) if err != nil { - return false + return false, err + } + + // Check if the VM is found in the AVS VM collection and return true + for _, vm := range *avs.VirtualMachines { + // VM IDs are always ALL CAPS in this property so ignoring case + if strings.EqualFold(vmName, GetNameFromResourceID(*vm.ID)) { + return true, nil + } } - return collections.ListContains(avsVMs, strings.ToLower(vmName)) + return false, NewNotFoundError("Virtual Machine", vmName, avsName) } -// GetAvailabilitySetVMs gets a list of VM names in the specified Azure Availability Set -func GetAvailabilitySetVMs(t testing.TestingT, avsName string, resGroupName string, subscriptionID string) []string { - vms, err := GetAvailabilitySetVMsE(t, avsName, resGroupName, subscriptionID) +// GetAvailabilitySetVMNamesInCaps gets a list of VM names in the specified Azure Availability Set. +// This function would fail the test if there is an error. +func GetAvailabilitySetVMNamesInCaps(t testing.TestingT, avsName string, resGroupName string, subscriptionID string) []string { + vms, err := GetAvailabilitySetVMNamesInCapsE(t, avsName, resGroupName, subscriptionID) require.NoError(t, err) return vms } -// GetAvailabilitySetVMsE gets a list of VM names in the specified Azure Availability Set -func GetAvailabilitySetVMsE(t testing.TestingT, avsName string, resGroupName string, subscriptionID string) ([]string, error) { +// GetAvailabilitySetVMNamesInCapsE gets a list of VM names in the specified Azure Availability Set +func GetAvailabilitySetVMNamesInCapsE(t testing.TestingT, avsName string, resGroupName string, subscriptionID string) ([]string, error) { client, err := GetAvailabilitySetClientE(subscriptionID) if err != nil { return nil, err @@ -60,33 +83,31 @@ func GetAvailabilitySetVMsE(t testing.TestingT, avsName string, resGroupName str vms := []string{} + // Get the names for all VMs in the Availability Set for _, vm := range *avs.VirtualMachines { - vms = append(vms, strings.ToLower(GetNameFromResourceID(*vm.ID))) + // IDs are returned in ALL CAPS for this property + if vmName := GetNameFromResourceID(*vm.ID); len(vmName) > 0 { + vms = append(vms, vmName) + } } return vms, nil } -// GetAvailabilitySetFaultDomainCount gets the Fault Domain Count for the specified Azure Availability Set +// GetAvailabilitySetFaultDomainCount gets the Fault Domain Count for the specified Azure Availability Set. +// This function would fail the test if there is an error. func GetAvailabilitySetFaultDomainCount(t testing.TestingT, avsName string, resGroupName string, subscriptionID string) int32 { avsFaultDomainCount, err := GetAvailabilitySetFaultDomainCountE(t, avsName, resGroupName, subscriptionID) require.NoError(t, err) - return avsFaultDomainCount } // GetAvailabilitySetFaultDomainCountE gets the Fault Domain Count for the specified Azure Availability Set func GetAvailabilitySetFaultDomainCountE(t testing.TestingT, avsName string, resGroupName string, subscriptionID string) (int32, error) { - client, err := GetAvailabilitySetClientE(subscriptionID) + avs, err := GetAvailabilitySetE(t, avsName, resGroupName, subscriptionID) if err != nil { return -1, err } - - avs, err := client.Get(context.Background(), resGroupName, avsName) - if err != nil { - return -1, err - } - return *avs.PlatformFaultDomainCount, nil } diff --git a/modules/azure/common.go b/modules/azure/common.go index d73923cc53..e664d5a41e 100644 --- a/modules/azure/common.go +++ b/modules/azure/common.go @@ -52,3 +52,19 @@ func getTargetAzureResourceGroupName(resourceGroupName string) (string, error) { return resourceGroupName, nil } + +// safePtrToString converts a string pointer to a non-pointer string value, or to "" if the pointer is nil. +func safePtrToString(raw *string) string { + if raw == nil { + return "" + } + return *raw +} + +// safePtrToInt32 converts a int32 pointer to a non-pointer int32 value, or to 0 if the pointer is nil. +func safePtrToInt32(raw *int32) int32 { + if raw == nil { + return 0 + } + return *raw +} diff --git a/modules/azure/common_test.go b/modules/azure/common_test.go index 6647c6c317..71bc609db2 100644 --- a/modules/azure/common_test.go +++ b/modules/azure/common_test.go @@ -9,6 +9,7 @@ import ( "os" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/modules/azure/compute.go b/modules/azure/compute.go index ef7a81cbd3..2a31a85b84 100644 --- a/modules/azure/compute.go +++ b/modules/azure/compute.go @@ -37,6 +37,90 @@ func GetVirtualMachineClientE(subscriptionID string) (*compute.VirtualMachinesCl return &vmClient, nil } +// VirtualMachineExists indicates whether the specifcied Azure Virtual Machine exists. +// This function would fail the test if there is an error. +func VirtualMachineExists(t testing.TestingT, vmName string, resGroupName string, subscriptionID string) bool { + exists, err := VirtualMachineExistsE(vmName, resGroupName, subscriptionID) + require.NoError(t, err) + return exists +} + +// VirtualMachineExistsE indicates whether the specifcied Azure Virtual Machine exists. +func VirtualMachineExistsE(vmName string, resGroupName string, subscriptionID string) (bool, error) { + // Get VM Object + _, err := GetVirtualMachineE(vmName, resGroupName, subscriptionID) + if err != nil { + if ResourceNotFoundErrorExists(err) { + return false, nil + } + return false, err + } + return true, nil +} + +// GetVirtualMachineNics gets a list of Network Interface names for a specifcied Azure Virtual Machine. +// This function would fail the test if there is an error. +func GetVirtualMachineNics(t testing.TestingT, vmName string, resGroupName string, subscriptionID string) []string { + nicList, err := GetVirtualMachineNicsE(vmName, resGroupName, subscriptionID) + require.NoError(t, err) + + return nicList +} + +// GetVirtualMachineNicsE gets a list of Network Interface names for a specified Azure Virtual Machine. +func GetVirtualMachineNicsE(vmName string, resGroupName string, subscriptionID string) ([]string, error) { + + // Get VM Object + vm, err := GetVirtualMachineE(vmName, resGroupName, subscriptionID) + if err != nil { + return nil, err + } + + // Get VM NIC(s); value always present, no nil checks needed. + vmNICs := *vm.NetworkProfile.NetworkInterfaces + + nics := make([]string, len(vmNICs)) + for i, nic := range vmNICs { + // Get ID from resource string. + nicName, err := GetNameFromResourceIDE(*nic.ID) + if err == nil { + nics[i] = nicName + } + } + return nics, nil +} + +// GetVirtualMachineManagedDisks gets the list of Managed Disk names of the specified Azure Virtual Machine. +// This function would fail the test if there is an error. +func GetVirtualMachineManagedDisks(t testing.TestingT, vmName string, resGroupName string, subscriptionID string) []string { + diskNames, err := GetVirtualMachineManagedDisksE(vmName, resGroupName, subscriptionID) + require.NoError(t, err) + + return diskNames +} + +// GetVirtualMachineManagedDisksE gets the list of Managed Disk names of the specified Azure Virtual Machine. +func GetVirtualMachineManagedDisksE(vmName string, resGroupName string, subscriptionID string) ([]string, error) { + + // Get VM Object + vm, err := GetVirtualMachineE(vmName, resGroupName, subscriptionID) + if err != nil { + return nil, err + } + + // Get VM attached Disks; value always present even if no disks attached, no nil check needed. + vmDisks := *vm.StorageProfile.DataDisks + + // Get the Names of the attached Managed Disks + diskNames := make([]string, len(vmDisks)) + for i, v := range vmDisks { + // Disk names are required, no nil check needed. + diskNames[i] = *v.Name + } + + return diskNames, nil +} + // GetVirtualMachineOSDiskName gets the OS Disk name of the specified Azure Virtual Machine. // This function would fail the test if there is an error. func GetVirtualMachineOSDiskName(t testing.TestingT, vmName string, resGroupName string, subscriptionID string) string { @@ -164,12 +248,28 @@ func GetVirtualMachineTagsE(vmName string, resGroupName string, subscriptionID s return nil, err } - // Range through existing tags and populate above map accordingly - for k, v := range vm.Tags { - tags[k] = *v + return &vm, nil +} + +// GetVirtualMachineClientE creates a Azure Virtual Machine client in the specified Azure Subscription. +func GetVirtualMachineClientE(subscriptionID string) (*compute.VirtualMachinesClient, error) { + // Validate Azure subscription ID + subscriptionID, err := getTargetAzureSubscription(subscriptionID) + if err != nil { + return nil, err } - return tags, nil + // Get the VM client + client := compute.NewVirtualMachinesClient(subscriptionID) + + // Create an authorizer + authorizer, err := NewAuthorizer() + if err != nil { + return nil, err + } + client.Authorizer = *authorizer + + return &client, nil } // ***************************************************** // @@ -271,7 +371,7 @@ func GetVirtualMachineE(vmName string, resGroupName string, subscriptionID strin return nil, err } - // Get the client refrence + // Get the client reference client, err := GetVirtualMachineClientE(subscriptionID) if err != nil { return nil, err @@ -284,24 +384,3 @@ func GetVirtualMachineE(vmName string, resGroupName string, subscriptionID strin return &vm, nil } - -// GetVirtualMachineClientE creates a Azure Virtual Machine client in the specified Azure Subscription. -func GetVirtualMachineClientE(subscriptionID string) (*compute.VirtualMachinesClient, error) { - // Validate Azure subscription ID - subscriptionID, err := getTargetAzureSubscription(subscriptionID) - if err != nil { - return nil, err - } - - // Get the VM client - client := compute.NewVirtualMachinesClient(subscriptionID) - - // Create an authorizer - authorizer, err := NewAuthorizer() - if err != nil { - return nil, err - } - client.Authorizer = *authorizer - - return &client, nil -} diff --git a/modules/azure/networkinterface.go b/modules/azure/networkinterface.go index 6a370730f8..14c6de0d0d 100644 --- a/modules/azure/networkinterface.go +++ b/modules/azure/networkinterface.go @@ -2,7 +2,6 @@ package azure import ( "context" - "reflect" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" "github.com/gruntwork-io/terratest/modules/testing" @@ -12,16 +11,19 @@ import ( // NetworkInterfaceExists indicates whether the specified Azure Network Interface exists. // This function would fail the test if there is an error. func NetworkInterfaceExists(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) bool { - exists, err := NetworkInterfaceExistsE(t, nicName, resGroupName, subscriptionID) + exists, err := NetworkInterfaceExistsE(nicName, resGroupName, subscriptionID) require.NoError(t, err) return exists } // NetworkInterfaceExistsE indicates whether the specified Azure Network Interface exists. -func NetworkInterfaceExistsE(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) (bool, error) { +func NetworkInterfaceExistsE(nicName string, resGroupName string, subscriptionID string) (bool, error) { // Get the Network Interface - _, err := GetNetworkInterfaceE(t, nicName, resGroupName, subscriptionID) + _, err := GetNetworkInterfaceE(nicName, resGroupName, subscriptionID) if err != nil { + if ResourceNotFoundErrorExists(err) { + return false, nil + } return false, err } return true, nil @@ -30,18 +32,18 @@ func NetworkInterfaceExistsE(t testing.TestingT, nicName string, resGroupName st // GetNetworkInterfacePrivateIPs gets a list of the Private IPs of a Network Interface configs. // This function would fail the test if there is an error. func GetNetworkInterfacePrivateIPs(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) []string { - IPs, err := GetNetworkInterfacePrivateIPsE(t, nicName, resGroupName, subscriptionID) + IPs, err := GetNetworkInterfacePrivateIPsE(nicName, resGroupName, subscriptionID) require.NoError(t, err) return IPs } // GetNetworkInterfacePrivateIPsE gets a list of the Private IPs of a Network Interface configs. -func GetNetworkInterfacePrivateIPsE(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) ([]string, error) { +func GetNetworkInterfacePrivateIPsE(nicName string, resGroupName string, subscriptionID string) ([]string, error) { var privateIPs []string // Get the Network Interface client - nic, err := GetNetworkInterfaceE(t, nicName, resGroupName, subscriptionID) + nic, err := GetNetworkInterfaceE(nicName, resGroupName, subscriptionID) if err != nil { return privateIPs, err } @@ -57,17 +59,17 @@ func GetNetworkInterfacePrivateIPsE(t testing.TestingT, nicName string, resGroup // GetNetworkInterfacePublicIPs returns a list of all the Public IPs found in the Network Interface configurations. // This function would fail the test if there is an error. func GetNetworkInterfacePublicIPs(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) []string { - IPs, err := GetNetworkInterfacePublicIPsE(t, nicName, resGroupName, subscriptionID) + IPs, err := GetNetworkInterfacePublicIPsE(nicName, resGroupName, subscriptionID) require.NoError(t, err) return IPs } // GetNetworkInterfacePublicIPsE returns a list of all the Public IPs found in the Network Interface configurations. -func GetNetworkInterfacePublicIPsE(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) ([]string, error) { +func GetNetworkInterfacePublicIPsE(nicName string, resGroupName string, subscriptionID string) ([]string, error) { var publicIPs []string // Get the Network Interface client - nic, err := GetNetworkInterfaceE(t, nicName, resGroupName, subscriptionID) + nic, err := GetNetworkInterfaceE(nicName, resGroupName, subscriptionID) if err != nil { return publicIPs, err } @@ -75,12 +77,12 @@ func GetNetworkInterfacePublicIPsE(t testing.TestingT, nicName string, resGroupN // Get the Public IPs from each configuration available for _, IPConfiguration := range *nic.IPConfigurations { // Iterate each config, for successful configurations check for a Public Address reference. - // Not failing on errors as as this is an optimistic accumulator. - nicConfig, err := GetNetworkInterfaceConfigurationE(t, nicName, *IPConfiguration.Name, resGroupName, subscriptionID) + // Not failing on errors as this is an optimistic accumulator. + nicConfig, err := GetNetworkInterfaceConfigurationE(nicName, *IPConfiguration.Name, resGroupName, subscriptionID) if err == nil { - if publicAddressID := nicConfig.PublicIPAddress; !reflect.ValueOf(nicConfig.PublicIPAddress).IsNil() { - // Get Public Address IP for configs with using Public Address client - publicIP, err := GetPublicAddressIPE(t, GetNameFromResourceID(*publicAddressID.ID), resGroupName, subscriptionID) + if nicConfig.PublicIPAddress != nil { + publicAddressID := GetNameFromResourceID(*nicConfig.PublicIPAddress.ID) + publicIP, err := GetIPOfPublicIPAddressByNameE(publicAddressID, resGroupName, subscriptionID) if err == nil { publicIPs = append(publicIPs, publicIP) } @@ -92,7 +94,7 @@ func GetNetworkInterfacePublicIPsE(t testing.TestingT, nicName string, resGroupN } // GetNetworkInterfaceConfigurationE gets a Network Interface Configuration in the specified Azure Resource Group. -func GetNetworkInterfaceConfigurationE(t testing.TestingT, nicName string, nicConfigName string, resGroupName string, subscriptionID string) (*network.InterfaceIPConfiguration, error) { +func GetNetworkInterfaceConfigurationE(nicName string, nicConfigName string, resGroupName string, subscriptionID string) (*network.InterfaceIPConfiguration, error) { // Validate Azure Resource Group resGroupName, err := getTargetAzureResourceGroupName(resGroupName) if err != nil { @@ -136,7 +138,7 @@ func GetNetworkInterfaceConfigurationClientE(subscriptionID string) (*network.In } // GetNetworkInterfaceE gets a Network Interface in the specified Azure Resource Group. -func GetNetworkInterfaceE(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) (*network.Interface, error) { +func GetNetworkInterfaceE(nicName string, resGroupName string, subscriptionID string) (*network.Interface, error) { // Validate Azure Resource Group resGroupName, err := getTargetAzureResourceGroupName(resGroupName) if err != nil { diff --git a/modules/azure/networkinterface_test.go b/modules/azure/networkinterface_test.go index 25c704b6ae..f5a962258c 100644 --- a/modules/azure/networkinterface_test.go +++ b/modules/azure/networkinterface_test.go @@ -23,7 +23,7 @@ func TestGetNetworkInterfaceE(t *testing.T) { rgName := "" subID := "" - _, err := GetNetworkInterfaceE(t, nicName, rgName, subID) + _, err := GetNetworkInterfaceE(nicName, rgName, subID) require.Error(t, err) } @@ -35,7 +35,7 @@ func TestGetNetworkInterfacePrivateIPsE(t *testing.T) { rgName := "" subID := "" - _, err := GetNetworkInterfacePrivateIPsE(t, nicName, rgName, subID) + _, err := GetNetworkInterfacePrivateIPsE(nicName, rgName, subID) require.Error(t, err) } @@ -47,7 +47,7 @@ func TestGetNetworkInterfacePublicIPsE(t *testing.T) { rgName := "" subID := "" - _, err := GetNetworkInterfacePublicIPsE(t, nicName, rgName, subID) + _, err := GetNetworkInterfacePublicIPsE(nicName, rgName, subID) require.Error(t, err) } @@ -59,7 +59,7 @@ func TestNetworkInterfaceExistsE(t *testing.T) { rgName := "" subID := "" - _, err := NetworkInterfaceExistsE(t, nicName, rgName, subID) + _, err := NetworkInterfaceExistsE(nicName, rgName, subID) require.Error(t, err) } diff --git a/modules/azure/publicaddress.go b/modules/azure/publicaddress.go index 89417d122a..28eea1cf63 100644 --- a/modules/azure/publicaddress.go +++ b/modules/azure/publicaddress.go @@ -11,32 +11,36 @@ import ( // PublicAddressExists indicates whether the specified AzurePublic Address exists. // This function would fail the test if there is an error. func PublicAddressExists(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) bool { - exists, err := PublicAddressExistsE(t, publicAddressName, resGroupName, subscriptionID) + exists, err := PublicAddressExistsE(publicAddressName, resGroupName, subscriptionID) require.NoError(t, err) return exists } // PublicAddressExistsE indicates whether the specified AzurePublic Address exists. -func PublicAddressExistsE(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) (bool, error) { +func PublicAddressExistsE(publicAddressName string, resGroupName string, subscriptionID string) (bool, error) { // Get the Public Address - _, err := GetPublicIPAddressE(t, publicAddressName, resGroupName, subscriptionID) + _, err := GetPublicIPAddressE(publicAddressName, resGroupName, subscriptionID) if err != nil { + if ResourceNotFoundErrorExists(err) { + return false, nil + } return false, err } return true, nil } -// GetPublicAddressIP gets the IP of a Public IP Address. This function would fail the test if there is an error. -func GetPublicAddressIP(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) string { - IP, err := GetPublicAddressIPE(t, publicAddressName, resGroupName, subscriptionID) +// GetIPOfPublicIPAddressByName gets the Public IP of the Public IP Address specified. +// This function would fail the test if there is an error. +func GetIPOfPublicIPAddressByName(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) string { + IP, err := GetIPOfPublicIPAddressByNameE(publicAddressName, resGroupName, subscriptionID) require.NoError(t, err) return IP } -// GetPublicAddressIPE gets the IP of a Public IP Address. -func GetPublicAddressIPE(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) (string, error) { +// GetIPOfPublicIPAddressByNameE gets the Public IP of the Public IP Address specified. +func GetIPOfPublicIPAddressByNameE(publicAddressName string, resGroupName string, subscriptionID string) (string, error) { // Create a NIC client - pip, err := GetPublicIPAddressE(t, publicAddressName, resGroupName, subscriptionID) + pip, err := GetPublicIPAddressE(publicAddressName, resGroupName, subscriptionID) if err != nil { return "", err } @@ -47,7 +51,7 @@ func GetPublicAddressIPE(t testing.TestingT, publicAddressName string, resGroupN // CheckPublicDNSNameAvailability checks whether a Domain Name in the cloudapp.azure.com zone // is available for use. This function would fail the test if there is an error. func CheckPublicDNSNameAvailability(t testing.TestingT, location string, domainNameLabel string, subscriptionID string) bool { - available, err := CheckPublicDNSNameAvailabilityE(t, location, domainNameLabel, subscriptionID) + available, err := CheckPublicDNSNameAvailabilityE(location, domainNameLabel, subscriptionID) if err != nil { return false } @@ -55,7 +59,7 @@ func CheckPublicDNSNameAvailability(t testing.TestingT, location string, domainN } // CheckPublicDNSNameAvailabilityE checks whether a Domain Name in the cloudapp.azure.com zone is available for use. -func CheckPublicDNSNameAvailabilityE(t testing.TestingT, location string, domainNameLabel string, subscriptionID string) (bool, error) { +func CheckPublicDNSNameAvailabilityE(location string, domainNameLabel string, subscriptionID string) (bool, error) { client, err := GetPublicIPAddressClientE(subscriptionID) if err != nil { return false, err @@ -70,7 +74,7 @@ func CheckPublicDNSNameAvailabilityE(t testing.TestingT, location string, domain } // GetPublicIPAddressE gets a Public IP Addresses in the specified Azure Resource Group. -func GetPublicIPAddressE(t testing.TestingT, publicIPAddressName string, resGroupName string, subscriptionID string) (*network.PublicIPAddress, error) { +func GetPublicIPAddressE(publicIPAddressName string, resGroupName string, subscriptionID string) (*network.PublicIPAddress, error) { // Validate resource group name and subscription ID resGroupName, err := getTargetAzureResourceGroupName(resGroupName) if err != nil { diff --git a/modules/azure/publicaddress_test.go b/modules/azure/publicaddress_test.go index 265844e0d0..d37aa175eb 100644 --- a/modules/azure/publicaddress_test.go +++ b/modules/azure/publicaddress_test.go @@ -23,7 +23,7 @@ func TestGetPublicIPAddressE(t *testing.T) { rgName := "" subID := "" - _, err := GetPublicIPAddressE(t, paName, rgName, subID) + _, err := GetPublicIPAddressE(paName, rgName, subID) require.Error(t, err) } @@ -35,19 +35,19 @@ func TestCheckPublicDNSNameAvailabilityE(t *testing.T) { domain := "" subID := "" - _, err := CheckPublicDNSNameAvailabilityE(t, location, domain, subID) + _, err := CheckPublicDNSNameAvailabilityE(location, domain, subID) require.Error(t, err) } -func TestGetPublicAddressIPE(t *testing.T) { +func TestGetIPOfPublicIPAddressByNameE(t *testing.T) { t.Parallel() paName := "" rgName := "" subID := "" - _, err := GetPublicAddressIPE(t, paName, rgName, subID) + _, err := GetIPOfPublicIPAddressByNameE(paName, rgName, subID) require.Error(t, err) } @@ -59,7 +59,7 @@ func TestPublicAddressExistsE(t *testing.T) { rgName := "" subID := "" - _, err := PublicAddressExistsE(t, paName, rgName, subID) + _, err := PublicAddressExistsE(paName, rgName, subID) require.Error(t, err) } diff --git a/modules/azure/virtualnetwork.go b/modules/azure/virtualnetwork.go index f75304ac29..c810b0fc44 100644 --- a/modules/azure/virtualnetwork.go +++ b/modules/azure/virtualnetwork.go @@ -12,16 +12,19 @@ import ( // VirtualNetworkExists indicates whether the specified Azure Virtual Network exists. // This function would fail the test if there is an error. func VirtualNetworkExists(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) bool { - exists, err := VirtualNetworkExistsE(t, vnetName, resGroupName, subscriptionID) + exists, err := VirtualNetworkExistsE(vnetName, resGroupName, subscriptionID) require.NoError(t, err) return exists } // VirtualNetworkExistsE indicates whether the specified Azure Virtual Network exists. -func VirtualNetworkExistsE(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) (bool, error) { +func VirtualNetworkExistsE(vnetName string, resGroupName string, subscriptionID string) (bool, error) { // Get the Virtual Network - _, err := GetVirtualNetworkE(t, vnetName, resGroupName, subscriptionID) + _, err := GetVirtualNetworkE(vnetName, resGroupName, subscriptionID) if err != nil { + if ResourceNotFoundErrorExists(err) { + return false, nil + } return false, err } return true, nil @@ -30,16 +33,19 @@ func VirtualNetworkExistsE(t testing.TestingT, vnetName string, resGroupName str // SubnetExists indicates whether the specified Azure Virtual Network Subnet exists. // This function would fail the test if there is an error. func SubnetExists(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) bool { - exists, err := SubnetExistsE(t, subnetName, vnetName, resGroupName, subscriptionID) + exists, err := SubnetExistsE(subnetName, vnetName, resGroupName, subscriptionID) require.NoError(t, err) return exists } // SubnetExistsE indicates whether the specified Azure Virtual Network Subnet exists. -func SubnetExistsE(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) (bool, error) { +func SubnetExistsE(subnetName string, vnetName string, resGroupName string, subscriptionID string) (bool, error) { // Get the Subnet - _, err := GetSubnetE(t, subnetName, vnetName, resGroupName, subscriptionID) + _, err := GetSubnetE(subnetName, vnetName, resGroupName, subscriptionID) if err != nil { + if ResourceNotFoundErrorExists(err) { + return false, nil + } return false, err } return true, nil @@ -48,13 +54,13 @@ func SubnetExistsE(t testing.TestingT, subnetName string, vnetName string, resGr // CheckSubnetContainsIP checks if the Private IP is contined in the Subnet Address Range. // This function would fail the test if there is an error. func CheckSubnetContainsIP(t testing.TestingT, IP string, subnetName string, vnetName string, resGroupName string, subscriptionID string) bool { - inRange, err := CheckSubnetContainsIPE(t, IP, subnetName, vnetName, resGroupName, subscriptionID) + inRange, err := CheckSubnetContainsIPE(IP, subnetName, vnetName, resGroupName, subscriptionID) require.NoError(t, err) return inRange } // CheckSubnetContainsIPE checks if the Private IP is contined in the Subnet Address Range. -func CheckSubnetContainsIPE(t testing.TestingT, ipAddress string, subnetName string, vnetName string, resGroupName string, subscriptionID string) (bool, error) { +func CheckSubnetContainsIPE(ipAddress string, subnetName string, vnetName string, resGroupName string, subscriptionID string) (bool, error) { // Convert the IP to a net IP address ip := net.ParseIP(ipAddress) if ip == nil { @@ -62,7 +68,7 @@ func CheckSubnetContainsIPE(t testing.TestingT, ipAddress string, subnetName str } // Get Subnet - subnet, err := GetSubnetE(t, subnetName, vnetName, resGroupName, subscriptionID) + subnet, err := GetSubnetE(subnetName, vnetName, resGroupName, subscriptionID) if err != nil { return false, err } @@ -82,14 +88,14 @@ func CheckSubnetContainsIPE(t testing.TestingT, ipAddress string, subnetName str // GetVirtualNetworkSubnets gets all Subnet names and their respective address prefixes in the // specified Virtual Network. This function would fail the test if there is an error. func GetVirtualNetworkSubnets(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) map[string]string { - subnets, err := GetVirtualNetworkSubnetsE(t, vnetName, resGroupName, subscriptionID) + subnets, err := GetVirtualNetworkSubnetsE(vnetName, resGroupName, subscriptionID) require.NoError(t, err) return subnets } // GetVirtualNetworkSubnetsE gets all Subnet names and their respective address prefixes in the specified Virtual Network. // Returning both the name and prefix together helps reduce calls for these frequently accessed properties. -func GetVirtualNetworkSubnetsE(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) (map[string]string, error) { +func GetVirtualNetworkSubnetsE(vnetName string, resGroupName string, subscriptionID string) (map[string]string, error) { subNetDetails := map[string]string{} client, err := GetSubnetClientE(subscriptionID) @@ -114,16 +120,16 @@ func GetVirtualNetworkSubnetsE(t testing.TestingT, vnetName string, resGroupName // GetVirtualNetworkDNSServerIPs gets a list of all Virtual Network DNS server IPs. // This function would fail the test if there is an error. func GetVirtualNetworkDNSServerIPs(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) []string { - vnetDNSIPs, err := GetVirtualNetworkDNSServerIPsE(t, vnetName, resGroupName, subscriptionID) + vnetDNSIPs, err := GetVirtualNetworkDNSServerIPsE(vnetName, resGroupName, subscriptionID) require.NoError(t, err) return vnetDNSIPs } // GetVirtualNetworkDNSServerIPsE gets a list of all Virtual Network DNS server IPs with Error. -func GetVirtualNetworkDNSServerIPsE(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) ([]string, error) { +func GetVirtualNetworkDNSServerIPsE(vnetName string, resGroupName string, subscriptionID string) ([]string, error) { // Get Virtual Network - vnet, err := GetVirtualNetworkE(t, vnetName, resGroupName, subscriptionID) + vnet, err := GetVirtualNetworkE(vnetName, resGroupName, subscriptionID) if err != nil { return nil, err } @@ -132,7 +138,7 @@ func GetVirtualNetworkDNSServerIPsE(t testing.TestingT, vnetName string, resGrou } // GetSubnetE gets a subnet. -func GetSubnetE(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) (*network.Subnet, error) { +func GetSubnetE(subnetName string, vnetName string, resGroupName string, subscriptionID string) (*network.Subnet, error) { // Validate Azure Resource Group resGroupName, err := getTargetAzureResourceGroupName(resGroupName) if err != nil { @@ -176,7 +182,7 @@ func GetSubnetClientE(subscriptionID string) (*network.SubnetsClient, error) { } // GetVirtualNetworkE gets Virtual Network in the specified Azure Resource Group. -func GetVirtualNetworkE(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) (*network.VirtualNetwork, error) { +func GetVirtualNetworkE(vnetName string, resGroupName string, subscriptionID string) (*network.VirtualNetwork, error) { // Validate Azure Resource Group resGroupName, err := getTargetAzureResourceGroupName(resGroupName) if err != nil { diff --git a/modules/azure/virtualnetwork_test.go b/modules/azure/virtualnetwork_test.go index 2c22d4071f..988e8acd3b 100644 --- a/modules/azure/virtualnetwork_test.go +++ b/modules/azure/virtualnetwork_test.go @@ -23,7 +23,7 @@ func TestGetVirtualNetworkE(t *testing.T) { rgName := "" subID := "" - _, err := GetVirtualNetworkE(t, vnetName, rgName, subID) + _, err := GetVirtualNetworkE(vnetName, rgName, subID) require.Error(t, err) } @@ -36,7 +36,7 @@ func TestGetSubnetE(t *testing.T) { rgName := "" subID := "" - _, err := GetSubnetE(t, subnetName, vnetName, rgName, subID) + _, err := GetSubnetE(subnetName, vnetName, rgName, subID) require.Error(t, err) } @@ -48,7 +48,7 @@ func TestGetVirtualNetworkDNSServerIPsE(t *testing.T) { rgName := "" subID := "" - _, err := GetVirtualNetworkDNSServerIPsE(t, vnetName, rgName, subID) + _, err := GetVirtualNetworkDNSServerIPsE(vnetName, rgName, subID) require.Error(t, err) } @@ -60,7 +60,7 @@ func TestGetVirtualNetworkSubnetsE(t *testing.T) { rgName := "" subID := "" - _, err := GetVirtualNetworkSubnetsE(t, vnetName, rgName, subID) + _, err := GetVirtualNetworkSubnetsE(vnetName, rgName, subID) require.Error(t, err) } @@ -74,7 +74,7 @@ func TestCheckSubnetContainsIPE(t *testing.T) { rgName := "" subID := "" - _, err := CheckSubnetContainsIPE(t, ipAddress, subnetName, vnetName, rgName, subID) + _, err := CheckSubnetContainsIPE(ipAddress, subnetName, vnetName, rgName, subID) require.Error(t, err) } @@ -87,7 +87,7 @@ func TestSubnetExistsE(t *testing.T) { rgName := "" subID := "" - _, err := SubnetExistsE(t, subnetName, vnetName, rgName, subID) + _, err := SubnetExistsE(subnetName, vnetName, rgName, subID) require.Error(t, err) } @@ -99,7 +99,7 @@ func TestVirtualNetworkExistsE(t *testing.T) { rgName := "" subID := "" - _, err := VirtualNetworkExistsE(t, vnetName, rgName, subID) + _, err := VirtualNetworkExistsE(vnetName, rgName, subID) require.Error(t, err) } diff --git a/modules/terraform/options.go b/modules/terraform/options.go index b98f8dcf82..596ab398d8 100644 --- a/modules/terraform/options.go +++ b/modules/terraform/options.go @@ -73,28 +73,11 @@ type Options struct { // NOTE: options.SshAgent and options.Logger CANNOT be deep copied (e.g., the SshAgent struct contains channels and // listeners that can't be meaningfully copied), so the original values are retained. func (options *Options) Clone() (*Options, error) { - newOptions := Options{} - if err := copier.Copy(&newOptions, options); err != nil { + newOptions := &Options{} + if err := copier.Copy(newOptions, options); err != nil { return nil, err } - - // Deep copy nested structs by calling the copier and updating the ref. This is necessary because the copier library - // does not handle struct pointers for the deep copy. - // See https://github.com/jinzhu/copier/issues/61 - // Logger - clonedLogger := logger.Logger{} - if err := copier.Copy(&clonedLogger, options.Logger); err != nil { - return nil, err - } - newOptions.Logger = &clonedLogger - // SshAgent - clonedSshAgent := ssh.SshAgent{} - if err := copier.Copy(&clonedSshAgent, options.SshAgent); err != nil { - return nil, err - } - newOptions.SshAgent = &clonedSshAgent - - return &newOptions, nil + return newOptions, nil } // WithDefaultRetryableErrors makes a copy of the Options object and returns an updated object with sensible defaults diff --git a/test/azure/terraform_azure_resourcegroup_example_test.go b/test/azure/terraform_azure_resourcegroup_example_test.go index 967b9b52d8..d53c357586 100644 --- a/test/azure/terraform_azure_resourcegroup_example_test.go +++ b/test/azure/terraform_azure_resourcegroup_example_test.go @@ -6,7 +6,6 @@ package test import ( - "fmt" "testing" "github.com/gruntwork-io/terratest/modules/azure"