From d90580dd63fd912bf869a79e45ebb54de78121d0 Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Tue, 15 Sep 2020 08:42:23 -0400 Subject: [PATCH 01/20] feat: adding Azure Network module --- .../terraform-azure-network-example/README.md | 159 +++++++++++++ .../terraform-azure-network-example/main.tf | 88 +++++++ .../outputs.tf | 25 ++ .../variables.tf | 60 +++++ modules/azure/networkinterface.go | 147 ++++++++++++ modules/azure/publicaddress.go | 117 +++++++++ modules/azure/resourceid.go | 36 +++ modules/azure/virtualnetwork.go | 225 ++++++++++++++++++ test/azure/networkinterface_test.go | 76 ++++++ test/azure/publicaddress_test.go | 76 ++++++ test/azure/resourceid_test.go | 96 ++++++++ .../terraform_azure_network_example_test.go | 130 ++++++++++ test/azure/virtualnetwork_test.go | 139 +++++++++++ 13 files changed, 1374 insertions(+) create mode 100644 examples/azure/terraform-azure-network-example/README.md create mode 100644 examples/azure/terraform-azure-network-example/main.tf create mode 100644 examples/azure/terraform-azure-network-example/outputs.tf create mode 100644 examples/azure/terraform-azure-network-example/variables.tf create mode 100644 modules/azure/networkinterface.go create mode 100644 modules/azure/publicaddress.go create mode 100644 modules/azure/resourceid.go create mode 100644 modules/azure/virtualnetwork.go create mode 100644 test/azure/networkinterface_test.go create mode 100644 test/azure/publicaddress_test.go create mode 100644 test/azure/resourceid_test.go create mode 100644 test/azure/terraform_azure_network_example_test.go create mode 100644 test/azure/virtualnetwork_test.go diff --git a/examples/azure/terraform-azure-network-example/README.md b/examples/azure/terraform-azure-network-example/README.md new file mode 100644 index 000000000..54e931340 --- /dev/null +++ b/examples/azure/terraform-azure-network-example/README.md @@ -0,0 +1,159 @@ +# Terraform Azure Network Example + +This folder contains a simple Terraform module that deploys resources in [Azure](https://azure.microsoft.com/) to demonstrate +how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys to a Virtual Network two Network Interface Cards, one with an internal only IP and another with an internal and external Public IP. + +* A [Virtual Network](https://azure.microsoft.com/en-us/services/virtual-network/) module that gives the following resources: + * [Virtual Network](https://docs.microsoft.com/en-us/azure/virtual-network/) with the name specified in the `virtual_network_name` variable. + * [Subnet](https://docs.microsoft.com/en-us/rest/api/virtualnetwork/subnets) with the name specified in the `subnet_name` variable. + * [Public Address](https://docs.microsoft.com/en-us/azure/virtual-network/public-ip-addresses) with the name specified in the `public_ip_name` variable. + * [Internal Network Interface](https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-network-interface) with the name specified in the `network_interface_internal` variable. + * [ExternalNetwork Interface](https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-network-interface) with the name specified in the `network_interface_external` variable. + +Check out [test/azure/terraform_azure_network_test.go](/test/azure/terraform_azure_network_example_test.go) to see how you can write +automated tests for this module. + +Note that the Azure Virtual Network, Subnet, Network Interface and Public IP resources in this module don't actually do anything; it just runs the resources for +demonstration purposes. + +**WARNING**: This module and the automated tests for it deploy real resources into your Azure account which can cost you +money. The resources are all part of the [Azure Free Account](https://azure.microsoft.com/en-us/free/), so if you haven't used that up, +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. Configure your Azure credentials using one of the [supported methods for Azure CLI + tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest). +1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`. +1. Run `terraform init`. +1. Run `terraform apply`. +1. When you're done, run `terraform destroy`. + +## Running automated tests against this module + +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/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest). +1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`. +1. [Review environment variables](#review-environment-variables). +1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`. +1. `cd test` +1. Make sure [the azure-sdk-for-go versions match](#check-go-dependencies) in [/go.mod](/go.mod) and in [test/terraform_azure_network_example_test.go](/test/azure/terraform_azure_network_example_test.go). +1. `go build terraform_azure_network_example_test.go` +1. `go test -v -run TestTerraformAzureNetworkExample` + +## Module test APIs + +These modules expose the following API methods: + +### Virtual Networks and Subnets +- `VirtualNetworkExists` indicates whether the speficied Azure Virtual Network exists\ +func VirtualNetworkExists(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) bool + +- `SubnetExists` indicates whether the speficied Azure Virtual Network Subnet exists\ +func SubnetExists(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) bool + +- `CheckSubnetContainsIP` checks if the Private IP is contined in the Subnet Address Range\ +func CheckSubnetContainsIP(t testing.TestingT, IP string, subnetName string, vnetName string, resGroupName string, subscriptionID string) bool + +- `GetSubnetIPRange` gets the IPv4 Range of the specified Subnet\ +func GetSubnetIPRange(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) string + +- `GetVirtualNetworkDNSServerIPs` gets a list of all Virtual Network DNS server IPs\ +func GetVirtualNetworkDNSServerIPs(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) []string + +- `GetVirtualNetworkSubnets` gets all Subnet names and their respective addres prefixes in the specified Virtual Network\ +func GetVirtualNetworkSubnets(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) map[string]string + +- `GetVirtualNetworkE` gets Virtual Network in the specified Azure Resource Group\ +func GetVirtualNetworkE(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) (*network.VirtualNetwork, error) + +- `GetVirtualNetworksClientE` creates a virtual network client in the specified Azure Subscription\ +func GetVirtualNetworksClientE(subscriptionID string) (*network.VirtualNetworksClient, error) + +- `GetSubnetE` gets a subnet\ +func GetSubnetE(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) (*network.Subnet, error) + +- `GetSubnetClientE` creates a subnet client\ +func GetSubnetClientE(subscriptionID string) (*network.SubnetsClient, error) + + + +### Network Interfaces +- `NetworkInterfaceExists` indicates whether the speficied Azure Network Interface exists\ +func NetworkInterfaceExists(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) bool + +- `GetNetworkInterfacePrivateIPs` gets a list of the Private IPs of a Network Interface configs\ +func GetNetworkInterfacePrivateIPs(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) []string + +- `GetNetworkInterfacePublicIPs` returns a list of all the Public IPs found in the Network Interface configurations\ +func GetNetworkInterfacePublicIPs(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) []string + +- `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) + +- `GetNetworkInterfaceClientE` creates a new Network Interface client in the specified Azure Subscription\ +func GetNetworkInterfaceClientE(subscriptionID string) (*network.InterfacesClient, error) + +### Public Addresses +- `PublicAddressExists` indicates whether the speficied AzurePublic Address exists\ +func PublicAddressExists(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) bool + +- `GetPublicAddressIP` gets the IP of a Public IP Address\ +func GetPublicAddressIP(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) string + +- `CheckPublicDNSNameAvailability` checks whether a Domain Name in the cloudapp.azure.com zone is available for use\ +func CheckPublicDNSNameAvailability(t testing.TestingT, location string, domainNameLabel string, subscriptionID string) bool + +- `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) + +- `GetPublicIPAddressClientE` creates a Public IP Addresses client in the specified Azure Subscription\ +func GetPublicIPAddressClientE(subscriptionID string) (*network.PublicIPAddressesClient, error) + + + +## Check Go Dependencies + +Check that the `github.com/Azure/azure-sdk-for-go` version in your generated `go.mod` for this test matches the version in the terratest [go.mod](https://github.com/gruntwork-io/terratest/blob/master/go.mod) file. + +> This was tested with **go1.14.4**. + +### Check Azure-sdk-for-go version + +Let's make sure [go.mod](https://github.com/gruntwork-io/terratest/blob/master/go.mod) includes the appropriate [azure-sdk-for-go version](https://github.com/Azure/azure-sdk-for-go/releases/tag/v46.1.0): + +```go +require ( + ... + github.com/Azure/azure-sdk-for-go v46.1.0+incompatible + ... +) +``` + +If we make changes to either the **go.mod** or the **go test file**, we should make sure that the go build command works still. + +```powershell +go build terraform_azure_network_example_test.go +``` + +## Review Environment Variables + +As part of configuring terraform for Azure, we'll want to check that we have set the appropriate [credentials](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#set-up-terraform-access-to-azure) and also that we set the [environment variables](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#configure-terraform-environment-variables) on the testing host. + +```bash +export ARM_CLIENT_ID=your_app_id +export ARM_CLIENT_SECRET=your_password +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: + +```powershell +[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID",$your_app_id,[System.EnvironmentVariableTarget]::Machine) +[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_SECRET",$your_password,[System.EnvironmentVariableTarget]::Machine) +[System.Environment]::SetEnvironmentVariable("ARM_SUBSCRIPTION_ID",$your_subscription_id,[System.EnvironmentVariableTarget]::Machine) +[System.Environment]::SetEnvironmentVariable("ARM_TENANT_ID",$your_tenant_id,[System.EnvironmentVariableTarget]::Machine) +``` \ No newline at end of file diff --git a/examples/azure/terraform-azure-network-example/main.tf b/examples/azure/terraform-azure-network-example/main.tf new file mode 100644 index 000000000..4fa67c720 --- /dev/null +++ b/examples/azure/terraform-azure-network-example/main.tf @@ -0,0 +1,88 @@ +provider "azurerm" { + version = "=2.20.0" + features {} +} + +# --------------------------------------------------------------------------------------------------------------------- +# PIN TERRAFORM VERSION TO >= 0.12 +# The examples have been upgraded to 0.12 syntax +# --------------------------------------------------------------------------------------------------------------------- + +terraform { + required_version = ">= 0.12" +} + +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY A RESOURCE GROUP +# See test/terraform_azure_example_test.go for how to write automated tests for this code. +# --------------------------------------------------------------------------------------------------------------------- + +resource "azurerm_resource_group" "main" { + name = "${var.prefix}-resources" + location = var.location +} + +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY VIRTUAL NETWORK +# --------------------------------------------------------------------------------------------------------------------- + +resource "azurerm_virtual_network" "main" { + name = "${var.prefix}-network" + location = azurerm_resource_group.main.location + resource_group_name = azurerm_resource_group.main.name + address_space = ["10.0.0.0/16"] + dns_servers = [var.dns_ip_01, var.dns_ip_02] +} + +resource "azurerm_subnet" "main" { + name = "${var.prefix}-subnet" + resource_group_name = azurerm_resource_group.main.name + virtual_network_name = azurerm_virtual_network.main.name + address_prefixes = [var.subnet_prefix] +} + +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY INTERNAL NETWORK INTERFACE +# --------------------------------------------------------------------------------------------------------------------- + +resource "azurerm_network_interface" "internal" { + name = "${var.prefix}-nic-01" + location = azurerm_resource_group.main.location + resource_group_name = azurerm_resource_group.main.name + + ip_configuration { + name = "terratestconfiguration1" + subnet_id = azurerm_subnet.main.id + private_ip_address_allocation = "Static" + private_ip_address = var.private_ip + } +} + +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY EXTERNAL NETWORK INTERFACE AND PUBLIC IP +# --------------------------------------------------------------------------------------------------------------------- + +resource "azurerm_public_ip" "main" { + name = "${var.prefix}-pip" + resource_group_name = azurerm_resource_group.main.name + location = azurerm_resource_group.main.location + allocation_method = "Static" + ip_version = "IPv4" + sku = "Standard" + idle_timeout_in_minutes = "4" + domain_name_label = var.domain_name_label +} + +resource "azurerm_network_interface" "external" { + name = "${var.prefix}-nic-02" + location = azurerm_resource_group.main.location + resource_group_name = azurerm_resource_group.main.name + + ip_configuration { + name = "terratestconfiguration1" + subnet_id = azurerm_subnet.main.id + private_ip_address_allocation = "Dynamic" + public_ip_address_id = azurerm_public_ip.main.id + } +} + diff --git a/examples/azure/terraform-azure-network-example/outputs.tf b/examples/azure/terraform-azure-network-example/outputs.tf new file mode 100644 index 000000000..ef4d3f6f5 --- /dev/null +++ b/examples/azure/terraform-azure-network-example/outputs.tf @@ -0,0 +1,25 @@ +output "resource_group_name" { + value = azurerm_resource_group.main.name +} + +output "virtual_network_name" { + value = azurerm_virtual_network.main.name +} + +output "subnet_name" { + value = azurerm_subnet.main.name +} + +output "public_address_name" { + value = azurerm_public_ip.main.name +} + +output "network_interface_internal" { + value = azurerm_network_interface.internal.name +} + +output "network_interface_external" { + value = azurerm_network_interface.external.name +} + + diff --git a/examples/azure/terraform-azure-network-example/variables.tf b/examples/azure/terraform-azure-network-example/variables.tf new file mode 100644 index 000000000..530a36851 --- /dev/null +++ b/examples/azure/terraform-azure-network-example/variables.tf @@ -0,0 +1,60 @@ +# --------------------------------------------------------------------------------------------------------------------- +# 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. +# --------------------------------------------------------------------------------------------------------------------- + +variable "domain_name_label" { + description = "The Domain Name Label for the Public IP Address" + type = string +} + +# --------------------------------------------------------------------------------------------------------------------- +# OPTIONAL PARAMETERS +# These parameters have reasonable defaults. +# --------------------------------------------------------------------------------------------------------------------- + +variable "dns_ip_01" { + description = "The first DNS Server IP for the Virtual Network" + type = string + default = "10.0.0.5" +} + +variable "dns_ip_02" { + description = "The second DNS Server IP for the Virtual Network" + type = string + default = "10.0.0.6" +} + +variable "location" { + description = "The Azure Region to deploy resources too" + type = string + default = "East US" +} + +variable "prefix" { + description = "The prefix that will be attached to all resources deployed" + type = string + default = "terratest-net" +} + +variable "private_ip" { + description = "The Static Private IP for the Internal NIC" + type = string + default = "10.0.20.5" +} + +variable "subnet_prefix" { + description = "The subnet range of IPs for the Virtual Network" + type = string + default = "10.0.20.0/24" +} diff --git a/modules/azure/networkinterface.go b/modules/azure/networkinterface.go new file mode 100644 index 000000000..44249dc06 --- /dev/null +++ b/modules/azure/networkinterface.go @@ -0,0 +1,147 @@ +package azure + +import ( + "context" + "encoding/json" + "strings" + + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" + "github.com/gruntwork-io/terratest/modules/testing" + "github.com/stretchr/testify/require" +) + +// NetworkInterfaceExists indicates whether the speficied Azure Network Interface exists +func NetworkInterfaceExists(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) bool { + exists, err := NetworkInterfaceExistsE(t, nicName, resGroupName, subscriptionID) + require.NoError(t, err) + return exists +} + +// NetworkInterfaceExistsE indicates whether the speficied Azure Network Interface exists +func NetworkInterfaceExistsE(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) (bool, error) { + // Get the Network Interface + _, err := GetNetworkInterfaceE(t, nicName, resGroupName, subscriptionID) + if err != nil { + return false, err + } + return true, nil +} + +// GetNetworkInterfacePublicIPs returns a list of all the Public IPs found in the Network Interface configurations +func GetNetworkInterfacePublicIPs(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) []string { + IPs, err := GetNetworkInterfacePublicIPsE(t, 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) { + publicIPs := []string{} + + // Get the Network Interface client + nic, err := GetNetworkInterfaceE(t, nicName, resGroupName, subscriptionID) + if err != nil { + return publicIPs, err + } + + // Get the Public IPs from each configuration + for _, IPConfiguration := range *nic.IPConfigurations { + if ipConfigHasPublicIP(&IPConfiguration) { + publicAddressID := GetNameFromResourceID(*IPConfiguration.PublicIPAddress.ID) + + // Get the Public Ip from the Public Address resource + publicIP := GetPublicAddressIP(t, publicAddressID, resGroupName, subscriptionID) + publicIPs = append(publicIPs, publicIP) + } + } + + return publicIPs, nil +} + +// ipConfigHasPublicIP returns true if an IP Configuration has a Public IP Address +// This helper method was created since a config without a public address causes a nil pointer panic +func ipConfigHasPublicIP(ipConfig *network.InterfaceIPConfiguration) bool { + var byteIPConfig []byte + + byteIPConfig, err := json.Marshal(ipConfig) + if err != nil { + return false + } + + stringIPConfig := string(byteIPConfig) + if !(strings.Contains(stringIPConfig, "publicIPAddress")) { + return false + } + + return true +} + +// GetNetworkInterfacePrivateIPs gets a list of the Private IPs of a Network Interface configs +func GetNetworkInterfacePrivateIPs(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) []string { + IPs, err := GetNetworkInterfacePrivateIPsE(t, 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) { + privateIPs := []string{} + + // Get the Network Interface client + nic, err := GetNetworkInterfaceE(t, nicName, resGroupName, subscriptionID) + if err != nil { + return privateIPs, err + } + + // Get the Private IPs from each configuration + for _, IPConfiguration := range *nic.IPConfigurations { + privateIPs = append(privateIPs, *IPConfiguration.PrivateIPAddress) + } + + return privateIPs, nil +} + +// 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) { + // Validate Azure Resource Group + resGroupName, err := getTargetAzureResourceGroupName(resGroupName) + if err != nil { + return nil, err + } + + // Get the client refrence + client, err := GetNetworkInterfaceClientE(subscriptionID) + if err != nil { + return nil, err + } + + // Get the Network Interface + nic, err := client.Get(context.Background(), resGroupName, nicName, "") + if err != nil { + return nil, err + } + + return &nic, nil +} + +// GetNetworkInterfaceClientE creates a new Network Interface client in the specified Azure Subscription +func GetNetworkInterfaceClientE(subscriptionID string) (*network.InterfacesClient, error) { + // Validate Azure Subscription ID + subscriptionID, err := getTargetAzureSubscription(subscriptionID) + if err != nil { + return nil, err + } + + // Get the NIC client + client := network.NewInterfacesClient(subscriptionID) + + // Create an authorizer + authorizer, err := NewAuthorizer() + if err != nil { + return nil, err + } + client.Authorizer = *authorizer + + return &client, nil +} diff --git a/modules/azure/publicaddress.go b/modules/azure/publicaddress.go new file mode 100644 index 000000000..647aab0e4 --- /dev/null +++ b/modules/azure/publicaddress.go @@ -0,0 +1,117 @@ +package azure + +import ( + "context" + + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" + "github.com/gruntwork-io/terratest/modules/testing" + "github.com/stretchr/testify/require" +) + +// PublicAddressExists indicates whether the speficied AzurePublic Address exists +func PublicAddressExists(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) bool { + exists, err := PublicAddressExistsE(t, publicAddressName, resGroupName, subscriptionID) + require.NoError(t, err) + return exists +} + +// PublicAddressExistsE indicates whether the speficied AzurePublic Address exists +func PublicAddressExistsE(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) (bool, error) { + // Get the Public Address + _, err := GetPublicIPAddressE(t, publicAddressName, resGroupName, subscriptionID) + if err != nil { + return false, err + } + return true, nil +} + +// GetPublicAddressIP gets the IP of a Public IP Address +func GetPublicAddressIP(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) string { + IP, err := GetPublicAddressIPE(t, publicAddressName, resGroupName, subscriptionID) + require.NoError(t, err) + return IP +} + +// GetPublicAddressIPE gets the IP of a Public IP Address with error +func GetPublicAddressIPE(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) (string, error) { + // Validate Azure subscription ID + subscriptionID, err := getTargetAzureSubscription(subscriptionID) + if err != nil { + return "", err + } + + // Create a NIC client + pip, err := GetPublicIPAddressE(t, publicAddressName, resGroupName, subscriptionID) + if err != nil { + return "", err + } + + return *pip.IPAddress, nil +} + +// CheckPublicDNSNameAvailability checks whether a Domain Name in the cloudapp.azure.com zone is available for use +func CheckPublicDNSNameAvailability(t testing.TestingT, location string, domainNameLabel string, subscriptionID string) bool { + available, err := CheckPublicDNSNameAvailabilityE(t, location, domainNameLabel, subscriptionID) + if err != nil { + return false + } + return available +} + +// 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) { + client, err := GetPublicIPAddressClientE(subscriptionID) + if err != nil { + return false, err + } + + res, err := client.CheckDNSNameAvailability(context.Background(), location, domainNameLabel) + if err != nil { + return false, err + } + + return *res.Available, nil +} + +// 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) { + // Validate resource group name and subscription ID + resGroupName, err := getTargetAzureResourceGroupName(resGroupName) + if err != nil { + return nil, err + } + + // Get the client refrence + client, err := GetPublicIPAddressClientE(subscriptionID) + if err != nil { + return nil, err + } + + // Get the Public IP Address + pip, err := client.Get(context.Background(), resGroupName, publicIPAddressName, "") + if err != nil { + return nil, err + } + return &pip, nil +} + +// GetPublicIPAddressClientE creates a Public IP Addresses client in the specified Azure Subscription +func GetPublicIPAddressClientE(subscriptionID string) (*network.PublicIPAddressesClient, error) { + // Validate Azure subscription ID + subscriptionID, err := getTargetAzureSubscription(subscriptionID) + if err != nil { + return nil, err + } + + // Get the Public IP Address client + client := network.NewPublicIPAddressesClient(subscriptionID) + + // Create an authorizer + authorizer, err := NewAuthorizer() + if err != nil { + return nil, err + } + client.Authorizer = *authorizer + + return &client, nil +} diff --git a/modules/azure/resourceid.go b/modules/azure/resourceid.go new file mode 100644 index 000000000..815313f60 --- /dev/null +++ b/modules/azure/resourceid.go @@ -0,0 +1,36 @@ +package azure + +import ( + "errors" + "strings" +) + +// GetNameFromResourceID gets the Name from an Azure Resource ID +func GetNameFromResourceID(resourceID string) string { + lastValue, err := GetSliceLastValueE(resourceID, "/") + if err != nil { + return "" + } + return lastValue +} + +// GetSliceLastValueE will take a source string and returns the last value when split by the seperaror char +func GetSliceLastValueE(source string, seperator string) (string, error) { + if !(len(source) == 0 || len(seperator) == 0 || !strings.Contains(source, seperator)) { + tmp := strings.Split(source, seperator) + return tmp[len(tmp)-1], nil + } + return "", errors.New("invalid input or no slice available") +} + +// GetSliceIndexValueE will take a source string and returns the value at the given index when split by the seperaror char +func GetSliceIndexValueE(source string, seperator string, index int) (string, error) { + if !(len(source) == 0 || len(seperator) == 0 || !strings.Contains(source, seperator) || index < 0) { + tmp := strings.Split(source, seperator) + if !(len(tmp) >= index) { + return "", errors.New("index out of slice range") + } + return tmp[index], nil + } + return "", errors.New("invalid input or no slice available") +} diff --git a/modules/azure/virtualnetwork.go b/modules/azure/virtualnetwork.go new file mode 100644 index 000000000..f05b4d2e7 --- /dev/null +++ b/modules/azure/virtualnetwork.go @@ -0,0 +1,225 @@ +package azure + +import ( + "context" + "fmt" + "net" + + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" + "github.com/gruntwork-io/terratest/modules/testing" + "github.com/stretchr/testify/require" +) + +// VirtualNetworkExists indicates whether the speficied Azure Virtual Network exists +func VirtualNetworkExists(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) bool { + exists, err := VirtualNetworkExistsE(t, vnetName, resGroupName, subscriptionID) + require.NoError(t, err) + return exists +} + +// VirtualNetworkExistsE indicates whether the speficied Azure Virtual Network exists +func VirtualNetworkExistsE(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) (bool, error) { + // Get the Virtual Network + _, err := GetVirtualNetworkE(t, vnetName, resGroupName, subscriptionID) + if err != nil { + return false, err + } + return true, nil +} + +// SubnetExists indicates whether the speficied Azure Virtual Network Subnet exists +func SubnetExists(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) bool { + exists, err := SubnetExistsE(t, subnetName, vnetName, resGroupName, subscriptionID) + require.NoError(t, err) + return exists +} + +// SubnetExistsE indicates whether the speficied Azure Virtual Network Subnet exists +func SubnetExistsE(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) (bool, error) { + // Get the Subnet + _, err := GetSubnetE(t, subnetName, vnetName, resGroupName, subscriptionID) + if err != nil { + return false, err + } + return true, nil +} + +// CheckSubnetContainsIP checks if the Private IP is contined in the Subnet Address Range +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) + 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) { + subnetPrefix := GetSubnetIPRange(t, subnetName, vnetName, resGroupName, subscriptionID) + + // Convert the IP to a net IP address + ip := net.ParseIP(ipAddress) + + if ip == nil { + return false, fmt.Errorf("Failed to parse IP address %s", ipAddress) + } + + // Check if the IP is in the Subnet Range + _, ipNet, err := net.ParseCIDR(subnetPrefix) + if err != nil { + return false, fmt.Errorf("Failed to parse subnet range %s", subnetPrefix) + } + + return ipNet.Contains(ip), nil +} + +// GetSubnetIPRange gets the IPv4 Range of the specified Subnet +func GetSubnetIPRange(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) string { + vnetDNSIPs, err := GetSubnetIPRangeE(t, subnetName, vnetName, resGroupName, subscriptionID) + require.NoError(t, err) + return vnetDNSIPs +} + +// GetSubnetIPRangeE gets the IPv4 Range of the specified Subnet +func GetSubnetIPRangeE(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) (string, error) { + // Get Subnet + subnet, err := GetSubnetE(t, subnetName, vnetName, resGroupName, subscriptionID) + if err != nil { + return "", err + } + + return *subnet.AddressPrefix, nil +} + +// GetVirtualNetworkSubnets gets all Subnet names and their respective address prefixes in the specified Virtual Network +func GetVirtualNetworkSubnets(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) map[string]string { + subnets, err := GetVirtualNetworkSubnetsE(t, vnetName, resGroupName, subscriptionID) + require.NoError(t, err) + return subnets +} + +// GetVirtualNetworkSubnetsE gets all Subnet names and their respective address prefixes in the specified Virtual Network +func GetVirtualNetworkSubnetsE(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) (map[string]string, error) { + client, err := GetSubnetClientE(subscriptionID) + if err != nil { + return nil, err + } + + subnets, err := client.List(context.Background(), resGroupName, vnetName) + if err != nil { + return nil, err + } + + subNetDetails := make(map[string]string) + for _, v := range subnets.Values() { + subnetName := v.Name + subNetAddressPrefix := v.AddressPrefix + + subNetDetails[string(*subnetName)] = string(*subNetAddressPrefix) + } + return subNetDetails, nil +} + +// GetVirtualNetworkDNSServerIPs gets a list of all Virtual Network DNS server IPs +func GetVirtualNetworkDNSServerIPs(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) []string { + vnetDNSIPs, err := GetVirtualNetworkDNSServerIPsE(t, 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) { + // Get Virtual Network + vnet, err := GetVirtualNetworkE(t, vnetName, resGroupName, subscriptionID) + if err != nil { + return nil, err + } + + return *vnet.DhcpOptions.DNSServers, nil +} + +// GetSubnetE gets a subnet +func GetSubnetE(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) (*network.Subnet, error) { + // Validate Azure Resource Group + resGroupName, err := getTargetAzureResourceGroupName(resGroupName) + if err != nil { + return nil, err + } + + // Get the client refrence + client, err := GetSubnetClientE(subscriptionID) + if err != nil { + return nil, err + } + + // Get the Subnet + subnet, err := client.Get(context.Background(), resGroupName, vnetName, subnetName, "") + if err != nil { + return nil, err + } + + return &subnet, nil +} + +// GetSubnetClientE creates a subnet client +func GetSubnetClientE(subscriptionID string) (*network.SubnetsClient, error) { + // Validate Azure subscription ID + subscriptionID, err := getTargetAzureSubscription(subscriptionID) + if err != nil { + return nil, err + } + + // Get the Subnet client + client := network.NewSubnetsClient(subscriptionID) + + // Create an authorizer + authorizer, err := NewAuthorizer() + if err != nil { + return nil, err + } + client.Authorizer = *authorizer + + return &client, nil +} + +// GetVirtualNetworkE gets Virtual Network in the specified Azure Resource Group +func GetVirtualNetworkE(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) (*network.VirtualNetwork, error) { + // Validate Azure Resource Group + resGroupName, err := getTargetAzureResourceGroupName(resGroupName) + if err != nil { + return nil, err + } + + // Get the client refrence + client, err := GetVirtualNetworksClientE(subscriptionID) + if err != nil { + return nil, err + } + + // Get the Virtual Network + vnet, err := client.Get(context.Background(), resGroupName, vnetName, "") + if err != nil { + return nil, err + } + return &vnet, nil +} + +// GetVirtualNetworksClientE creates a virtual network client in the specified Azure Subscription +func GetVirtualNetworksClientE(subscriptionID string) (*network.VirtualNetworksClient, error) { + // Validate Azure subscription ID + subscriptionID, err := getTargetAzureSubscription(subscriptionID) + if err != nil { + return nil, err + } + + // Get the Virtual Network client + client := network.NewVirtualNetworksClient(subscriptionID) + + // Create an authorizer + authorizer, err := NewAuthorizer() + if err != nil { + return nil, err + } + client.Authorizer = *authorizer + + return &client, nil +} diff --git a/test/azure/networkinterface_test.go b/test/azure/networkinterface_test.go new file mode 100644 index 000000000..4219f1003 --- /dev/null +++ b/test/azure/networkinterface_test.go @@ -0,0 +1,76 @@ +// +build azure azureslim,network + +// NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for +// CircleCI. + +package test + +import ( + "testing" + + "github.com/gruntwork-io/terratest/modules/azure" + "github.com/stretchr/testify/require" +) + +/* +The below tests are currently stubbed out, with the expectation that they will throw errors. +If/when methods can be mocked or Create/Delete APIs are added, these tests can be extended. +*/ + +func TestGetNetworkInterfaceClientE(t *testing.T) { + t.Parallel() + + subID := "" + + _, err := azure.GetNetworkInterfaceClientE(subID) + + require.Error(t, err) +} + +func TestGetNetworkInterfaceE(t *testing.T) { + t.Parallel() + + nicName := "" + rgName := "" + subID := "" + + _, err := azure.GetNetworkInterfaceE(t, nicName, rgName, subID) + + require.Error(t, err) +} + +func TestGetNetworkInterfacePrivateIPsE(t *testing.T) { + t.Parallel() + + nicName := "" + rgName := "" + subID := "" + + _, err := azure.GetNetworkInterfacePrivateIPsE(t, nicName, rgName, subID) + + require.Error(t, err) +} + +func TestGetNetworkInterfacePublicIPsE(t *testing.T) { + t.Parallel() + + nicName := "" + rgName := "" + subID := "" + + _, err := azure.GetNetworkInterfacePublicIPsE(t, nicName, rgName, subID) + + require.Error(t, err) +} + +func TestNetworkInterfaceExistsE(t *testing.T) { + t.Parallel() + + nicName := "" + rgName := "" + subID := "" + + _, err := azure.NetworkInterfaceExistsE(t, nicName, rgName, subID) + + require.Error(t, err) +} diff --git a/test/azure/publicaddress_test.go b/test/azure/publicaddress_test.go new file mode 100644 index 000000000..e4fa6a18a --- /dev/null +++ b/test/azure/publicaddress_test.go @@ -0,0 +1,76 @@ +// +build azure azureslim,network + +// NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for +// CircleCI. + +package test + +import ( + "testing" + + "github.com/gruntwork-io/terratest/modules/azure" + "github.com/stretchr/testify/require" +) + +/* +The below tests are currently stubbed out, with the expectation that they will throw errors. +If/when methods can be mocked or Create/Delete APIs are added, these tests can be extended. +*/ + +func TestGetPublicIPAddressClientE(t *testing.T) { + t.Parallel() + + subID := "" + + _, err := azure.GetPublicIPAddressClientE(subID) + + require.Error(t, err) +} + +func TestGetPublicIPAddressE(t *testing.T) { + t.Parallel() + + paName := "" + rgName := "" + subID := "" + + _, err := azure.GetPublicIPAddressE(t, paName, rgName, subID) + + require.Error(t, err) +} + +func TestCheckPublicDNSNameAvailabilityE(t *testing.T) { + t.Parallel() + + location := "" + domain := "" + subID := "" + + _, err := azure.CheckPublicDNSNameAvailabilityE(t, location, domain, subID) + + require.Error(t, err) +} + +func TestGetPublicAddressIPE(t *testing.T) { + t.Parallel() + + paName := "" + rgName := "" + subID := "" + + _, err := azure.GetPublicAddressIPE(t, paName, rgName, subID) + + require.Error(t, err) +} + +func TestPublicAddressExistsE(t *testing.T) { + t.Parallel() + + paName := "" + rgName := "" + subID := "" + + _, err := azure.PublicAddressExistsE(t, paName, rgName, subID) + + require.Error(t, err) +} diff --git a/test/azure/resourceid_test.go b/test/azure/resourceid_test.go new file mode 100644 index 000000000..9aa66c6f7 --- /dev/null +++ b/test/azure/resourceid_test.go @@ -0,0 +1,96 @@ +// +build azure + +// NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for +// CircleCI. + +package test + +import ( + "testing" + + "github.com/gruntwork-io/terratest/modules/azure" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGetNameFromResourceID(t *testing.T) { + // set slice variables + sliceSource := "this/is/a/long/slash/separated/string/ResourceID" + sliceResult := "ResourceID" + sliceNotFound := "noresourcepresent" + + // verify success + resultSuccess := azure.GetNameFromResourceID(sliceSource) + assert.Equal(t, sliceResult, resultSuccess) + + // verify error when seperator not found + resultBadSeperator := azure.GetNameFromResourceID(sliceNotFound) + assert.Equal(t, "", resultBadSeperator) +} + +func TestGetSliceLastValue(t *testing.T) { + // set slice variables + sliceSeperator := "/" + sliceBadSeperator := "*" + sliceNotFound := "noslicepresent" + sliceSource := "this/is/a/long/slash/separated/string/success" + sliceResult := "success" + + // verify success + resultSuccess, err := azure.GetSliceLastValueE(sliceSource, sliceSeperator) + require.NoError(t, err) + assert.Equal(t, sliceResult, resultSuccess) + + // verify error when seperator not found + resultBadSeperator, err := azure.GetSliceLastValueE(sliceSource, sliceBadSeperator) + require.Error(t, err) + assert.Equal(t, err.Error(), "invalid input or no slice available") + assert.Equal(t, "", resultBadSeperator) + + // verify error when slice does not have seperator + resultNotFound, err := azure.GetSliceLastValueE(sliceNotFound, sliceSeperator) + require.Error(t, err) + assert.Equal(t, err.Error(), "invalid input or no slice available") + assert.Equal(t, "", resultNotFound) +} + +func TestGetSliceIndexValue(t *testing.T) { + // set slice variables + sliceSource := "this/is/a/long/slash/separated/string/success" + sliceSeperator := "/" + sliceSelectorNeg := -1 + sliceSelector0 := 0 + sliceSelector4 := 4 + sliceSelector7 := 7 + sliceSelector10 := 10 + sliceResult0 := "this" + sliceResult4 := "slash" + sliceResult7 := "success" + + // verify success index 0 + resultSuccess0, err := azure.GetSliceIndexValueE(sliceSource, sliceSeperator, sliceSelector0) + require.NoError(t, err) + assert.Equal(t, sliceResult0, resultSuccess0) + + // verify success index 4 + resultSuccess4, err := azure.GetSliceIndexValueE(sliceSource, sliceSeperator, sliceSelector4) + require.NoError(t, err) + assert.Equal(t, sliceResult4, resultSuccess4) + + // verify success index 7 + resultSuccess7, err := azure.GetSliceIndexValueE(sliceSource, sliceSeperator, sliceSelector7) + require.NoError(t, err) + assert.Equal(t, sliceResult7, resultSuccess7) + + // verify error with negative index + resultNegIndex, err := azure.GetSliceIndexValueE(sliceSource, sliceSeperator, sliceSelectorNeg) + require.Error(t, err) + assert.Equal(t, err.Error(), "invalid input or no slice available") + assert.Equal(t, "", resultNegIndex) + + // verify error when seperator not found + resultBadIndex10, err := azure.GetSliceIndexValueE(sliceSource, sliceSeperator, sliceSelector10) + require.Error(t, err) + assert.Equal(t, err.Error(), "index out of slice range") + assert.Equal(t, "", resultBadIndex10) +} diff --git a/test/azure/terraform_azure_network_example_test.go b/test/azure/terraform_azure_network_example_test.go new file mode 100644 index 000000000..a0f9d3b5f --- /dev/null +++ b/test/azure/terraform_azure_network_example_test.go @@ -0,0 +1,130 @@ +// +build azure azureslim,network + +// NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for +// CircleCI. + +package test + +import ( + "fmt" + "strings" + "testing" + + "github.com/gruntwork-io/terratest/modules/azure" + "github.com/gruntwork-io/terratest/modules/random" + "github.com/gruntwork-io/terratest/modules/terraform" + "github.com/stretchr/testify/assert" +) + +func TestTerraformAzureNetworkExample(t *testing.T) { + t.Parallel() + + subscriptionID := "" // Subscription ID, leave blank if available as an Environment Var + prefix := "terratest-net" + expectedSubnetRange := "10.0.20.0/24" + expectedPrivateIP := "10.0.20.5" + expectedDnsIp01 := "10.0.0.5" + expectedDnsIp02 := "10.0.0.6" + expectedLocation := "eastus2" + + exectedDNSLabel := fmt.Sprintf("%s-%s", prefix, strings.ToLower(random.UniqueId())) + + // Configure Terraform setting up a path to Terraform code. + terraformOptions := &terraform.Options{ + // Relative path to the Terraform dir + TerraformDir: "../../examples/azure/terraform-azure-network-example", + + // Variables to pass to our Terraform code using -var options + Vars: map[string]interface{}{ + "prefix": prefix, + "subnet_prefix": expectedSubnetRange, + "private_ip": expectedPrivateIP, + "dns_ip_01": expectedDnsIp01, + "dns_ip_02": expectedDnsIp02, + "location": expectedLocation, + "domain_name_label": exectedDNSLabel, + }, + } + + // At the end of the test, run `terraform destroy` to clean up any resources that were created + defer terraform.Destroy(t, terraformOptions) + + // Run `terraform init` and `terraform apply`. Fail the test if there are any errors. + terraform.InitAndApply(t, terraformOptions) + + // Run `terraform output` to get the values of output variables + resourceGroupName := terraform.Output(t, terraformOptions, "resource_group_name") + virtualNetworkName := terraform.Output(t, terraformOptions, "virtual_network_name") + subnetName := terraform.Output(t, terraformOptions, "subnet_name") + publicAddressName := terraform.Output(t, terraformOptions, "public_address_name") + nicInternalName := terraform.Output(t, terraformOptions, "network_interface_internal") + nicExternalName := terraform.Output(t, terraformOptions, "network_interface_external") + + // Sub-tests for integrated resources + + t.Run("VirtualNetwork_Subnet", func(t *testing.T) { + // Check the Subnet exists in the Virtual Network Subnets + actualVnetSubnets := azure.GetVirtualNetworkSubnets(t, virtualNetworkName, resourceGroupName, subscriptionID) + assert.NotNil(t, actualVnetSubnets[subnetName]) + }) + + t.Run("NIC_PublicAddress", func(t *testing.T) { + // Check the internal network interface does NOT have a public IP + actualPrivateIPOnly := azure.GetNetworkInterfacePublicIPs(t, nicInternalName, resourceGroupName, subscriptionID) + assert.True(t, len(actualPrivateIPOnly) == 0) + + // Check the external network interface has a public IP + actualPublicIPs := azure.GetNetworkInterfacePublicIPs(t, nicExternalName, resourceGroupName, subscriptionID) + assert.True(t, len(actualPublicIPs) == 1) + }) + + t.Run("Subnet_NIC", func(t *testing.T) { + // Check the private IP is in the subnet range + checkPrivateIpInSubnet := azure.CheckSubnetContainsIP(t, expectedPrivateIP, subnetName, virtualNetworkName, resourceGroupName, subscriptionID) + assert.True(t, checkPrivateIpInSubnet) + }) + + // Sub-tests for individual resources + + t.Run("NetworkResources", func(t *testing.T) { + // Check the Virtual Network exists + assert.True(t, azure.VirtualNetworkExists(t, virtualNetworkName, resourceGroupName, subscriptionID)) + + // Check the Subnet exists + assert.True(t, azure.SubnetExists(t, subnetName, virtualNetworkName, resourceGroupName, subscriptionID)) + + // Check the Network Interface exists + assert.True(t, azure.NetworkInterfaceExists(t, nicInternalName, resourceGroupName, subscriptionID)) + assert.True(t, azure.NetworkInterfaceExists(t, nicExternalName, resourceGroupName, subscriptionID)) + + // Check Public Address exists + assert.True(t, azure.PublicAddressExists(t, publicAddressName, resourceGroupName, subscriptionID)) + + // Check the Virtual Network DNS server IPs + actualDNSIPs := azure.GetVirtualNetworkDNSServerIPs(t, virtualNetworkName, resourceGroupName, subscriptionID) + assert.Contains(t, actualDNSIPs, expectedDnsIp01) + assert.Contains(t, actualDNSIPs, expectedDnsIp02) + + // Check Subnet address range + actualSubnetRange := azure.GetSubnetIPRange(t, subnetName, virtualNetworkName, resourceGroupName, subscriptionID) + assert.Equal(t, expectedSubnetRange, actualSubnetRange) + + // Check the Network Interface private IP + actualPrivateIPs := azure.GetNetworkInterfacePrivateIPs(t, nicInternalName, resourceGroupName, subscriptionID) + assert.Contains(t, actualPrivateIPs, expectedPrivateIP) + + // Check the Public Address public IP + actualPublicIP := azure.GetPublicAddressIP(t, publicAddressName, resourceGroupName, subscriptionID) + assert.True(t, len(actualPublicIP) > 0) + + // Check DNS created for this example is not available for use + actualDnsNotAvailable := azure.CheckPublicDNSNameAvailability(t, expectedLocation, exectedDNSLabel, subscriptionID) + assert.False(t, actualDnsNotAvailable) + + // Check new DNS created is available + newDNSLabel := fmt.Sprintf("%s-%s", prefix, strings.ToLower(random.UniqueId())) + actualDnsAvailable := azure.CheckPublicDNSNameAvailability(t, expectedLocation, newDNSLabel, subscriptionID) + assert.True(t, actualDnsAvailable) + }) + +} diff --git a/test/azure/virtualnetwork_test.go b/test/azure/virtualnetwork_test.go new file mode 100644 index 000000000..8edd71553 --- /dev/null +++ b/test/azure/virtualnetwork_test.go @@ -0,0 +1,139 @@ +// +build azure azureslim,network + +// NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for +// CircleCI. + +package test + +import ( + "testing" + + "github.com/gruntwork-io/terratest/modules/azure" + "github.com/stretchr/testify/require" +) + +/* +The below tests are currently stubbed out, with the expectation that they will throw errors. +If/when methods can be mocked or Create/Delete APIs are added, these tests can be extended. +*/ + +func TestGetVirtualNetworksClientE(t *testing.T) { + t.Parallel() + + subID := "" + + _, err := azure.GetVirtualNetworksClientE(subID) + + require.Error(t, err) +} + +func TestGetVirtualNetworkE(t *testing.T) { + t.Parallel() + + vnetName := "" + rgName := "" + subID := "" + + _, err := azure.GetVirtualNetworkE(t, vnetName, rgName, subID) + + require.Error(t, err) +} + +func TestGetSubnetClientE(t *testing.T) { + t.Parallel() + + subID := "" + + _, err := azure.GetSubnetClientE(subID) + + require.Error(t, err) +} + +func TestGetSubnetE(t *testing.T) { + t.Parallel() + + subnetName := "" + vnetName := "" + rgName := "" + subID := "" + + _, err := azure.GetSubnetE(t, subnetName, vnetName, rgName, subID) + + require.Error(t, err) +} + +func TestGetVirtualNetworkDNSServerIPsE(t *testing.T) { + t.Parallel() + + vnetName := "" + rgName := "" + subID := "" + + _, err := azure.GetVirtualNetworkDNSServerIPsE(t, vnetName, rgName, subID) + + require.Error(t, err) +} + +func TestGetVirtualNetworkSubnetsE(t *testing.T) { + t.Parallel() + + vnetName := "" + rgName := "" + subID := "" + + _, err := azure.GetVirtualNetworkSubnetsE(t, vnetName, rgName, subID) + + require.Error(t, err) +} + +func TestGetSubnetIPRangeE(t *testing.T) { + t.Parallel() + + subnetName := "" + vnetName := "" + rgName := "" + subID := "" + + _, err := azure.GetSubnetIPRangeE(t, subnetName, vnetName, rgName, subID) + + require.Error(t, err) +} + +func TestCheckSubnetContainsIPE(t *testing.T) { + t.Parallel() + + ipAddress := "" + subnetName := "" + vnetName := "" + rgName := "" + subID := "" + + _, err := azure.CheckSubnetContainsIPE(t, ipAddress, subnetName, vnetName, rgName, subID) + + require.Error(t, err) +} + +func TestSubnetExistsE(t *testing.T) { + t.Parallel() + + subnetName := "" + vnetName := "" + rgName := "" + subID := "" + + _, err := azure.SubnetExistsE(t, subnetName, vnetName, rgName, subID) + + require.Error(t, err) +} + +func TestVirtualNetworkExistsE(t *testing.T) { + t.Parallel() + + vnetName := "" + rgName := "" + subID := "" + + _, err := azure.VirtualNetworkExistsE(t, vnetName, rgName, subID) + + require.Error(t, err) +} From ec1d19415c00821cfc0bfaa14bbd72f5df18c9e8 Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Tue, 15 Sep 2020 14:24:39 -0400 Subject: [PATCH 02/20] Fixed lint issue --- modules/azure/networkinterface.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/modules/azure/networkinterface.go b/modules/azure/networkinterface.go index 44249dc06..74184f6c2 100644 --- a/modules/azure/networkinterface.go +++ b/modules/azure/networkinterface.go @@ -68,12 +68,7 @@ func ipConfigHasPublicIP(ipConfig *network.InterfaceIPConfiguration) bool { return false } - stringIPConfig := string(byteIPConfig) - if !(strings.Contains(stringIPConfig, "publicIPAddress")) { - return false - } - - return true + return strings.Contains(string(byteIPConfig), "publicIPAddress") } // GetNetworkInterfacePrivateIPs gets a list of the Private IPs of a Network Interface configs From 42c73c225381c2d3b92eff7303d4b822d5ec91b2 Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Tue, 15 Sep 2020 17:24:12 -0400 Subject: [PATCH 03/20] Fixed CheckSubnetContainsIP test fail --- modules/azure/virtualnetwork.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/azure/virtualnetwork.go b/modules/azure/virtualnetwork.go index f05b4d2e7..366dea241 100644 --- a/modules/azure/virtualnetwork.go +++ b/modules/azure/virtualnetwork.go @@ -53,7 +53,10 @@ func CheckSubnetContainsIP(t testing.TestingT, IP string, subnetName string, vne // 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) { - subnetPrefix := GetSubnetIPRange(t, subnetName, vnetName, resGroupName, subscriptionID) + subnetPrefix, err := GetSubnetIPRangeE(t, subnetName, vnetName, resGroupName, subscriptionID) + if err != nil { + return false, err + } // Convert the IP to a net IP address ip := net.ParseIP(ipAddress) From 4aeb05cbc1b223007cc6955eb33eb69b2d0a79c6 Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Tue, 15 Sep 2020 17:36:46 -0400 Subject: [PATCH 04/20] Removed extra stub test --- test/azure/networkinterface_test.go | 10 ---------- test/azure/publicaddress_test.go | 10 ---------- test/azure/virtualnetwork_test.go | 20 -------------------- 3 files changed, 40 deletions(-) diff --git a/test/azure/networkinterface_test.go b/test/azure/networkinterface_test.go index 4219f1003..a5cfa4876 100644 --- a/test/azure/networkinterface_test.go +++ b/test/azure/networkinterface_test.go @@ -17,16 +17,6 @@ The below tests are currently stubbed out, with the expectation that they will t If/when methods can be mocked or Create/Delete APIs are added, these tests can be extended. */ -func TestGetNetworkInterfaceClientE(t *testing.T) { - t.Parallel() - - subID := "" - - _, err := azure.GetNetworkInterfaceClientE(subID) - - require.Error(t, err) -} - func TestGetNetworkInterfaceE(t *testing.T) { t.Parallel() diff --git a/test/azure/publicaddress_test.go b/test/azure/publicaddress_test.go index e4fa6a18a..330cebf76 100644 --- a/test/azure/publicaddress_test.go +++ b/test/azure/publicaddress_test.go @@ -17,16 +17,6 @@ The below tests are currently stubbed out, with the expectation that they will t If/when methods can be mocked or Create/Delete APIs are added, these tests can be extended. */ -func TestGetPublicIPAddressClientE(t *testing.T) { - t.Parallel() - - subID := "" - - _, err := azure.GetPublicIPAddressClientE(subID) - - require.Error(t, err) -} - func TestGetPublicIPAddressE(t *testing.T) { t.Parallel() diff --git a/test/azure/virtualnetwork_test.go b/test/azure/virtualnetwork_test.go index 8edd71553..3a774bf3f 100644 --- a/test/azure/virtualnetwork_test.go +++ b/test/azure/virtualnetwork_test.go @@ -17,16 +17,6 @@ The below tests are currently stubbed out, with the expectation that they will t If/when methods can be mocked or Create/Delete APIs are added, these tests can be extended. */ -func TestGetVirtualNetworksClientE(t *testing.T) { - t.Parallel() - - subID := "" - - _, err := azure.GetVirtualNetworksClientE(subID) - - require.Error(t, err) -} - func TestGetVirtualNetworkE(t *testing.T) { t.Parallel() @@ -39,16 +29,6 @@ func TestGetVirtualNetworkE(t *testing.T) { require.Error(t, err) } -func TestGetSubnetClientE(t *testing.T) { - t.Parallel() - - subID := "" - - _, err := azure.GetSubnetClientE(subID) - - require.Error(t, err) -} - func TestGetSubnetE(t *testing.T) { t.Parallel() From b096a2cd162fa0af40f029551ce006ec2fea7c56 Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Tue, 22 Sep 2020 09:55:18 -0400 Subject: [PATCH 05/20] Updates to match feedback from PR 626 --- .../terraform-azure-network-example/README.md | 151 ++---------------- .../terraform-azure-network-example/main.tf | 48 +++--- .../outputs.tf | 12 +- {test => modules}/azure/common_test.go | 11 +- {test => modules}/azure/compute_test.go | 8 +- modules/azure/errors.go | 15 ++ modules/azure/networkinterface.go | 6 +- .../azure/networkinterface_test.go | 11 +- modules/azure/publicaddress.go | 6 - {test => modules}/azure/publicaddress_test.go | 11 +- {test => modules}/azure/region_test.go | 8 +- modules/azure/resourceid.go | 30 +--- modules/azure/resourceid_test.go | 29 ++++ modules/azure/virtualnetwork.go | 44 ++--- .../azure/virtualnetwork_test.go | 30 +--- modules/collections/errors.go | 17 ++ modules/collections/stringslicevalue.go | 26 +++ modules/collections/stringslicevalue_test.go | 77 +++++++++ test/azure/resourceid_test.go | 96 ----------- .../terraform_azure_network_example_test.go | 35 ++-- 20 files changed, 280 insertions(+), 391 deletions(-) rename {test => modules}/azure/common_test.go (78%) rename {test => modules}/azure/compute_test.go (77%) rename {test => modules}/azure/networkinterface_test.go (73%) rename {test => modules}/azure/publicaddress_test.go (74%) rename {test => modules}/azure/region_test.go (88%) create mode 100644 modules/azure/resourceid_test.go rename {test => modules}/azure/virtualnetwork_test.go (64%) create mode 100644 modules/collections/errors.go create mode 100644 modules/collections/stringslicevalue.go create mode 100644 modules/collections/stringslicevalue_test.go delete mode 100644 test/azure/resourceid_test.go diff --git a/examples/azure/terraform-azure-network-example/README.md b/examples/azure/terraform-azure-network-example/README.md index 54e931340..54e56fcb3 100644 --- a/examples/azure/terraform-azure-network-example/README.md +++ b/examples/azure/terraform-azure-network-example/README.md @@ -3,12 +3,12 @@ This folder contains a simple Terraform module that deploys resources in [Azure](https://azure.microsoft.com/) to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys to a Virtual Network two Network Interface Cards, one with an internal only IP and another with an internal and external Public IP. -* A [Virtual Network](https://azure.microsoft.com/en-us/services/virtual-network/) module that gives the following resources: - * [Virtual Network](https://docs.microsoft.com/en-us/azure/virtual-network/) with the name specified in the `virtual_network_name` variable. - * [Subnet](https://docs.microsoft.com/en-us/rest/api/virtualnetwork/subnets) with the name specified in the `subnet_name` variable. - * [Public Address](https://docs.microsoft.com/en-us/azure/virtual-network/public-ip-addresses) with the name specified in the `public_ip_name` variable. - * [Internal Network Interface](https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-network-interface) with the name specified in the `network_interface_internal` variable. - * [ExternalNetwork Interface](https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-network-interface) with the name specified in the `network_interface_external` variable. +- A [Virtual Network](https://azure.microsoft.com/en-us/services/virtual-network/) module that includes the following resources: + - [Virtual Network](https://docs.microsoft.com/en-us/azure/virtual-network/) with the name specified in the `virtual_network_name` variable. + - [Subnet](https://docs.microsoft.com/en-us/rest/api/virtualnetwork/subnets) with the name specified in the `subnet_name` variable. + - [Public Address](https://docs.microsoft.com/en-us/azure/virtual-network/public-ip-addresses) with the name specified in the `public_ip_name` variable. + - [Internal Network Interface](https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-network-interface) with the name specified in the `network_interface_internal` variable. + - [ExternalNetwork Interface](https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-network-interface) with the name specified in the `network_interface_external` variable. Check out [test/azure/terraform_azure_network_test.go](/test/azure/terraform_azure_network_example_test.go) to see how you can write automated tests for this module. @@ -22,138 +22,21 @@ 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/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest). -1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`. -1. Run `terraform init`. -1. Run `terraform apply`. -1. When you're done, run `terraform destroy`. + tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest) +1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH` +1. Run `terraform init` +1. Run `terraform apply` +1. When you're done, run `terraform destroy` ## 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/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest). -1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`. -1. [Review environment variables](#review-environment-variables). -1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`. -1. `cd test` -1. Make sure [the azure-sdk-for-go versions match](#check-go-dependencies) in [/go.mod](/go.mod) and in [test/terraform_azure_network_example_test.go](/test/azure/terraform_azure_network_example_test.go). + tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest) +1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH` +1. Configure your Terratest [Go test environment](../README.md) +1. `cd test/azure` 1. `go build terraform_azure_network_example_test.go` 1. `go test -v -run TestTerraformAzureNetworkExample` - -## Module test APIs - -These modules expose the following API methods: - -### Virtual Networks and Subnets -- `VirtualNetworkExists` indicates whether the speficied Azure Virtual Network exists\ -func VirtualNetworkExists(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) bool - -- `SubnetExists` indicates whether the speficied Azure Virtual Network Subnet exists\ -func SubnetExists(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) bool - -- `CheckSubnetContainsIP` checks if the Private IP is contined in the Subnet Address Range\ -func CheckSubnetContainsIP(t testing.TestingT, IP string, subnetName string, vnetName string, resGroupName string, subscriptionID string) bool - -- `GetSubnetIPRange` gets the IPv4 Range of the specified Subnet\ -func GetSubnetIPRange(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) string - -- `GetVirtualNetworkDNSServerIPs` gets a list of all Virtual Network DNS server IPs\ -func GetVirtualNetworkDNSServerIPs(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) []string - -- `GetVirtualNetworkSubnets` gets all Subnet names and their respective addres prefixes in the specified Virtual Network\ -func GetVirtualNetworkSubnets(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) map[string]string - -- `GetVirtualNetworkE` gets Virtual Network in the specified Azure Resource Group\ -func GetVirtualNetworkE(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) (*network.VirtualNetwork, error) - -- `GetVirtualNetworksClientE` creates a virtual network client in the specified Azure Subscription\ -func GetVirtualNetworksClientE(subscriptionID string) (*network.VirtualNetworksClient, error) - -- `GetSubnetE` gets a subnet\ -func GetSubnetE(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) (*network.Subnet, error) - -- `GetSubnetClientE` creates a subnet client\ -func GetSubnetClientE(subscriptionID string) (*network.SubnetsClient, error) - - - -### Network Interfaces -- `NetworkInterfaceExists` indicates whether the speficied Azure Network Interface exists\ -func NetworkInterfaceExists(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) bool - -- `GetNetworkInterfacePrivateIPs` gets a list of the Private IPs of a Network Interface configs\ -func GetNetworkInterfacePrivateIPs(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) []string - -- `GetNetworkInterfacePublicIPs` returns a list of all the Public IPs found in the Network Interface configurations\ -func GetNetworkInterfacePublicIPs(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) []string - -- `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) - -- `GetNetworkInterfaceClientE` creates a new Network Interface client in the specified Azure Subscription\ -func GetNetworkInterfaceClientE(subscriptionID string) (*network.InterfacesClient, error) - -### Public Addresses -- `PublicAddressExists` indicates whether the speficied AzurePublic Address exists\ -func PublicAddressExists(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) bool - -- `GetPublicAddressIP` gets the IP of a Public IP Address\ -func GetPublicAddressIP(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) string - -- `CheckPublicDNSNameAvailability` checks whether a Domain Name in the cloudapp.azure.com zone is available for use\ -func CheckPublicDNSNameAvailability(t testing.TestingT, location string, domainNameLabel string, subscriptionID string) bool - -- `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) - -- `GetPublicIPAddressClientE` creates a Public IP Addresses client in the specified Azure Subscription\ -func GetPublicIPAddressClientE(subscriptionID string) (*network.PublicIPAddressesClient, error) - - - -## Check Go Dependencies - -Check that the `github.com/Azure/azure-sdk-for-go` version in your generated `go.mod` for this test matches the version in the terratest [go.mod](https://github.com/gruntwork-io/terratest/blob/master/go.mod) file. - -> This was tested with **go1.14.4**. - -### Check Azure-sdk-for-go version - -Let's make sure [go.mod](https://github.com/gruntwork-io/terratest/blob/master/go.mod) includes the appropriate [azure-sdk-for-go version](https://github.com/Azure/azure-sdk-for-go/releases/tag/v46.1.0): - -```go -require ( - ... - github.com/Azure/azure-sdk-for-go v46.1.0+incompatible - ... -) -``` - -If we make changes to either the **go.mod** or the **go test file**, we should make sure that the go build command works still. - -```powershell -go build terraform_azure_network_example_test.go -``` - -## Review Environment Variables - -As part of configuring terraform for Azure, we'll want to check that we have set the appropriate [credentials](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#set-up-terraform-access-to-azure) and also that we set the [environment variables](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#configure-terraform-environment-variables) on the testing host. - -```bash -export ARM_CLIENT_ID=your_app_id -export ARM_CLIENT_SECRET=your_password -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: - -```powershell -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID",$your_app_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_SECRET",$your_password,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_SUBSCRIPTION_ID",$your_subscription_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_TENANT_ID",$your_tenant_id,[System.EnvironmentVariableTarget]::Machine) -``` \ No newline at end of file diff --git a/examples/azure/terraform-azure-network-example/main.tf b/examples/azure/terraform-azure-network-example/main.tf index 4fa67c720..dacf0b5d9 100644 --- a/examples/azure/terraform-azure-network-example/main.tf +++ b/examples/azure/terraform-azure-network-example/main.tf @@ -12,60 +12,62 @@ terraform { required_version = ">= 0.12" } +# --------------------------------------------------------------------------------------------------------------------- +# See test/azure/terraform_azure_network_example_test.go for how to write automated tests for this code. # --------------------------------------------------------------------------------------------------------------------- # DEPLOY A RESOURCE GROUP -# See test/terraform_azure_example_test.go for how to write automated tests for this code. # --------------------------------------------------------------------------------------------------------------------- -resource "azurerm_resource_group" "main" { +resource "azurerm_resource_group" "net" { name = "${var.prefix}-resources" location = var.location } # --------------------------------------------------------------------------------------------------------------------- # DEPLOY VIRTUAL NETWORK +# Note this network dosen't actually do anything and is only created for the example. # --------------------------------------------------------------------------------------------------------------------- -resource "azurerm_virtual_network" "main" { - name = "${var.prefix}-network" - location = azurerm_resource_group.main.location - resource_group_name = azurerm_resource_group.main.name +resource "azurerm_virtual_network" "net" { + name = "${var.prefix}-vnet" + location = azurerm_resource_group.net.location + resource_group_name = azurerm_resource_group.net.name address_space = ["10.0.0.0/16"] dns_servers = [var.dns_ip_01, var.dns_ip_02] } -resource "azurerm_subnet" "main" { +resource "azurerm_subnet" "net" { name = "${var.prefix}-subnet" - resource_group_name = azurerm_resource_group.main.name - virtual_network_name = azurerm_virtual_network.main.name - address_prefixes = [var.subnet_prefix] + resource_group_name = azurerm_resource_group.net.name + virtual_network_name = azurerm_virtual_network.net.name + address_prefixes = [var.subnet_prefix] } # --------------------------------------------------------------------------------------------------------------------- # DEPLOY INTERNAL NETWORK INTERFACE # --------------------------------------------------------------------------------------------------------------------- -resource "azurerm_network_interface" "internal" { +resource "azurerm_network_interface" "net01" { name = "${var.prefix}-nic-01" - location = azurerm_resource_group.main.location - resource_group_name = azurerm_resource_group.main.name + location = azurerm_resource_group.net.location + resource_group_name = azurerm_resource_group.net.name ip_configuration { name = "terratestconfiguration1" - subnet_id = azurerm_subnet.main.id + subnet_id = azurerm_subnet.net.id private_ip_address_allocation = "Static" private_ip_address = var.private_ip } } # --------------------------------------------------------------------------------------------------------------------- -# DEPLOY EXTERNAL NETWORK INTERFACE AND PUBLIC IP +# DEPLOY PUBLIC IP AND EXTERNAL NETWORK INTERFACE # --------------------------------------------------------------------------------------------------------------------- -resource "azurerm_public_ip" "main" { +resource "azurerm_public_ip" "net" { name = "${var.prefix}-pip" - resource_group_name = azurerm_resource_group.main.name - location = azurerm_resource_group.main.location + resource_group_name = azurerm_resource_group.net.name + location = azurerm_resource_group.net.location allocation_method = "Static" ip_version = "IPv4" sku = "Standard" @@ -73,16 +75,16 @@ resource "azurerm_public_ip" "main" { domain_name_label = var.domain_name_label } -resource "azurerm_network_interface" "external" { +resource "azurerm_network_interface" "net02" { name = "${var.prefix}-nic-02" - location = azurerm_resource_group.main.location - resource_group_name = azurerm_resource_group.main.name + location = azurerm_resource_group.net.location + resource_group_name = azurerm_resource_group.net.name ip_configuration { name = "terratestconfiguration1" - subnet_id = azurerm_subnet.main.id + subnet_id = azurerm_subnet.net.id private_ip_address_allocation = "Dynamic" - public_ip_address_id = azurerm_public_ip.main.id + public_ip_address_id = azurerm_public_ip.net.id } } diff --git a/examples/azure/terraform-azure-network-example/outputs.tf b/examples/azure/terraform-azure-network-example/outputs.tf index ef4d3f6f5..888c038f2 100644 --- a/examples/azure/terraform-azure-network-example/outputs.tf +++ b/examples/azure/terraform-azure-network-example/outputs.tf @@ -1,25 +1,25 @@ output "resource_group_name" { - value = azurerm_resource_group.main.name + value = azurerm_resource_group.net.name } output "virtual_network_name" { - value = azurerm_virtual_network.main.name + value = azurerm_virtual_network.net.name } output "subnet_name" { - value = azurerm_subnet.main.name + value = azurerm_subnet.net.name } output "public_address_name" { - value = azurerm_public_ip.main.name + value = azurerm_public_ip.net.name } output "network_interface_internal" { - value = azurerm_network_interface.internal.name + value = azurerm_network_interface.net01.name } output "network_interface_external" { - value = azurerm_network_interface.external.name + value = azurerm_network_interface.net02.name } diff --git a/test/azure/common_test.go b/modules/azure/common_test.go similarity index 78% rename from test/azure/common_test.go rename to modules/azure/common_test.go index 66fa16be1..403dd01bf 100644 --- a/test/azure/common_test.go +++ b/modules/azure/common_test.go @@ -3,13 +3,12 @@ // NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for // CircleCI. -package test +package azure import ( "os" "testing" - "github.com/gruntwork-io/terratest/modules/azure" "github.com/stretchr/testify/require" ) @@ -17,7 +16,7 @@ func TestGetTargetAzureSubscription(t *testing.T) { t.Parallel() //Check that ARM_SUBSCRIPTION_ID env variable is set, CI requires this value to run all test. - require.NotEmpty(t, os.Getenv(azure.AzureSubscriptionID), "ARM_SUBSCRIPTION_ID environment variable not set.") + require.NotEmpty(t, os.Getenv(AzureSubscriptionID), "ARM_SUBSCRIPTION_ID environment variable not set.") type args struct { subID string @@ -30,12 +29,12 @@ func TestGetTargetAzureSubscription(t *testing.T) { wantErr bool }{ {name: "subIDProvidedAsArg", args: args{subID: "test"}, want: "test", wantErr: false}, - {name: "subIDNotProvidedFallbackToEnv", args: args{subID: ""}, want: os.Getenv(azure.AzureSubscriptionID), wantErr: false}, + {name: "subIDNotProvidedFallbackToEnv", args: args{subID: ""}, want: os.Getenv(AzureSubscriptionID), wantErr: false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := azure.GetTargetAzureSubscription(tt.args.subID) + got, err := GetTargetAzureSubscription(tt.args.subID) if tt.wantErr { require.Error(t, err) @@ -65,7 +64,7 @@ func TestGetTargetAzureResourceGroupName(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := azure.GetTargetAzureResourceGroupName(tt.args.rgName) + got, err := GetTargetAzureResourceGroupName(tt.args.rgName) if tt.wantErr { require.Error(t, err) diff --git a/test/azure/compute_test.go b/modules/azure/compute_test.go similarity index 77% rename from test/azure/compute_test.go rename to modules/azure/compute_test.go index 600952a6e..e3aea5672 100644 --- a/test/azure/compute_test.go +++ b/modules/azure/compute_test.go @@ -3,13 +3,11 @@ // NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for // CircleCI. -package test +package azure import ( "testing" - "github.com/gruntwork-io/terratest/modules/azure" - "github.com/stretchr/testify/require" ) @@ -26,7 +24,7 @@ func TestGetTagsForVirtualMachineE(t *testing.T) { rgName := "" subID := "" - _, err := azure.GetTagsForVirtualMachineE(t, vmName, rgName, subID) + _, err := GetTagsForVirtualMachineE(t, vmName, rgName, subID) require.Error(t, err) } @@ -38,7 +36,7 @@ func TestGetSizeOfVirtualMachineE(t *testing.T) { rgName := "" subID := "" - _, err := azure.GetSizeOfVirtualMachineE(t, vmName, rgName, subID) + _, err := GetSizeOfVirtualMachineE(t, vmName, rgName, subID) require.Error(t, err) } diff --git a/modules/azure/errors.go b/modules/azure/errors.go index 148957d16..f8ea4a896 100644 --- a/modules/azure/errors.go +++ b/modules/azure/errors.go @@ -15,3 +15,18 @@ type ResourceGroupNameNotFound struct{} func (err ResourceGroupNameNotFound) Error() string { return fmt.Sprintf("Could not find an Azure Resource Group name in expected environment variable %s and one was not provided for this test.", AzureResGroupName) } + +// FailedToParseError is returned when an object cannot be parsed +type FailedToParseError struct { + objectType string + objectID string +} + +func (err FailedToParseError) Error() string { + return fmt.Sprintf("Failed to parse %s with ID %s", err.objectType, err.objectID) +} + +// NewFailedToParseError creates a new not found error when an expected object is not found in the search space +func NewFailedToParseError(objectType string, objectID string) FailedToParseError { + return FailedToParseError{objectType, objectID} +} diff --git a/modules/azure/networkinterface.go b/modules/azure/networkinterface.go index 74184f6c2..a17c576c9 100644 --- a/modules/azure/networkinterface.go +++ b/modules/azure/networkinterface.go @@ -44,12 +44,13 @@ func GetNetworkInterfacePublicIPsE(t testing.TestingT, nicName string, resGroupN return publicIPs, err } - // Get the Public IPs from each configuration + // Get the Public IPs from each configuration available for _, IPConfiguration := range *nic.IPConfigurations { if ipConfigHasPublicIP(&IPConfiguration) { + // Get the ID from the long string NIC representation publicAddressID := GetNameFromResourceID(*IPConfiguration.PublicIPAddress.ID) - // Get the Public Ip from the Public Address resource + // Get the Public Ip from the Public Address client publicIP := GetPublicAddressIP(t, publicAddressID, resGroupName, subscriptionID) publicIPs = append(publicIPs, publicIP) } @@ -60,6 +61,7 @@ func GetNetworkInterfacePublicIPsE(t testing.TestingT, nicName string, resGroupN // ipConfigHasPublicIP returns true if an IP Configuration has a Public IP Address // This helper method was created since a config without a public address causes a nil pointer panic +// and the string representation is searched for the publicIPAddress text to identify it's presence. func ipConfigHasPublicIP(ipConfig *network.InterfaceIPConfiguration) bool { var byteIPConfig []byte diff --git a/test/azure/networkinterface_test.go b/modules/azure/networkinterface_test.go similarity index 73% rename from test/azure/networkinterface_test.go rename to modules/azure/networkinterface_test.go index a5cfa4876..25c704b6a 100644 --- a/test/azure/networkinterface_test.go +++ b/modules/azure/networkinterface_test.go @@ -3,12 +3,11 @@ // NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for // CircleCI. -package test +package azure import ( "testing" - "github.com/gruntwork-io/terratest/modules/azure" "github.com/stretchr/testify/require" ) @@ -24,7 +23,7 @@ func TestGetNetworkInterfaceE(t *testing.T) { rgName := "" subID := "" - _, err := azure.GetNetworkInterfaceE(t, nicName, rgName, subID) + _, err := GetNetworkInterfaceE(t, nicName, rgName, subID) require.Error(t, err) } @@ -36,7 +35,7 @@ func TestGetNetworkInterfacePrivateIPsE(t *testing.T) { rgName := "" subID := "" - _, err := azure.GetNetworkInterfacePrivateIPsE(t, nicName, rgName, subID) + _, err := GetNetworkInterfacePrivateIPsE(t, nicName, rgName, subID) require.Error(t, err) } @@ -48,7 +47,7 @@ func TestGetNetworkInterfacePublicIPsE(t *testing.T) { rgName := "" subID := "" - _, err := azure.GetNetworkInterfacePublicIPsE(t, nicName, rgName, subID) + _, err := GetNetworkInterfacePublicIPsE(t, nicName, rgName, subID) require.Error(t, err) } @@ -60,7 +59,7 @@ func TestNetworkInterfaceExistsE(t *testing.T) { rgName := "" subID := "" - _, err := azure.NetworkInterfaceExistsE(t, nicName, rgName, subID) + _, err := NetworkInterfaceExistsE(t, nicName, rgName, subID) require.Error(t, err) } diff --git a/modules/azure/publicaddress.go b/modules/azure/publicaddress.go index 647aab0e4..98e720492 100644 --- a/modules/azure/publicaddress.go +++ b/modules/azure/publicaddress.go @@ -34,12 +34,6 @@ func GetPublicAddressIP(t testing.TestingT, publicAddressName string, resGroupNa // GetPublicAddressIPE gets the IP of a Public IP Address with error func GetPublicAddressIPE(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) (string, error) { - // Validate Azure subscription ID - subscriptionID, err := getTargetAzureSubscription(subscriptionID) - if err != nil { - return "", err - } - // Create a NIC client pip, err := GetPublicIPAddressE(t, publicAddressName, resGroupName, subscriptionID) if err != nil { diff --git a/test/azure/publicaddress_test.go b/modules/azure/publicaddress_test.go similarity index 74% rename from test/azure/publicaddress_test.go rename to modules/azure/publicaddress_test.go index 330cebf76..265844e0d 100644 --- a/test/azure/publicaddress_test.go +++ b/modules/azure/publicaddress_test.go @@ -3,12 +3,11 @@ // NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for // CircleCI. -package test +package azure import ( "testing" - "github.com/gruntwork-io/terratest/modules/azure" "github.com/stretchr/testify/require" ) @@ -24,7 +23,7 @@ func TestGetPublicIPAddressE(t *testing.T) { rgName := "" subID := "" - _, err := azure.GetPublicIPAddressE(t, paName, rgName, subID) + _, err := GetPublicIPAddressE(t, paName, rgName, subID) require.Error(t, err) } @@ -36,7 +35,7 @@ func TestCheckPublicDNSNameAvailabilityE(t *testing.T) { domain := "" subID := "" - _, err := azure.CheckPublicDNSNameAvailabilityE(t, location, domain, subID) + _, err := CheckPublicDNSNameAvailabilityE(t, location, domain, subID) require.Error(t, err) } @@ -48,7 +47,7 @@ func TestGetPublicAddressIPE(t *testing.T) { rgName := "" subID := "" - _, err := azure.GetPublicAddressIPE(t, paName, rgName, subID) + _, err := GetPublicAddressIPE(t, paName, rgName, subID) require.Error(t, err) } @@ -60,7 +59,7 @@ func TestPublicAddressExistsE(t *testing.T) { rgName := "" subID := "" - _, err := azure.PublicAddressExistsE(t, paName, rgName, subID) + _, err := PublicAddressExistsE(t, paName, rgName, subID) require.Error(t, err) } diff --git a/test/azure/region_test.go b/modules/azure/region_test.go similarity index 88% rename from test/azure/region_test.go rename to modules/azure/region_test.go index 9d986056f..eeb45807d 100644 --- a/test/azure/region_test.go +++ b/modules/azure/region_test.go @@ -3,7 +3,7 @@ // NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for // CircleCI. -package test +package azure import ( "testing" @@ -26,8 +26,8 @@ func TestGetRandomRegionExcludesForbiddenRegions(t *testing.T) { approvedRegions := []string{"canadacentral", "eastus", "eastus2", "westus", "westus2", "westeurope", "northeurope", "uksouth", "southeastasia", "eastasia", "japaneast", "australiacentral"} forbiddenRegions := []string{"westus2", "japaneast"} - for i := 0; i < 1000; i++ { - randomRegion := azure.GetRandomRegion(t, approvedRegions, forbiddenRegions, "") + for i := 0; i < 48; i++ { + randomRegion := GetRandomRegion(t, approvedRegions, forbiddenRegions, "") assert.NotContains(t, forbiddenRegions, randomRegion) } } @@ -35,7 +35,7 @@ func TestGetRandomRegionExcludesForbiddenRegions(t *testing.T) { func TestGetAllAzureRegions(t *testing.T) { t.Parallel() - regions := azure.GetAllAzureRegions(t, "") + regions := GetAllAzureRegions(t, "") // The typical subscription had access to 30+ live regions as of July 2019: https://azure.microsoft.com/en-us/global-infrastructure/regions/ assert.True(t, len(regions) >= 30, "Number of regions: %d", len(regions)) diff --git a/modules/azure/resourceid.go b/modules/azure/resourceid.go index 815313f60..8d13ef51e 100644 --- a/modules/azure/resourceid.go +++ b/modules/azure/resourceid.go @@ -1,36 +1,12 @@ package azure -import ( - "errors" - "strings" -) +import "github.com/gruntwork-io/terratest/modules/collections" // GetNameFromResourceID gets the Name from an Azure Resource ID func GetNameFromResourceID(resourceID string) string { - lastValue, err := GetSliceLastValueE(resourceID, "/") + id, err := collections.GetSliceLastValueE(resourceID, "/") if err != nil { return "" } - return lastValue -} - -// GetSliceLastValueE will take a source string and returns the last value when split by the seperaror char -func GetSliceLastValueE(source string, seperator string) (string, error) { - if !(len(source) == 0 || len(seperator) == 0 || !strings.Contains(source, seperator)) { - tmp := strings.Split(source, seperator) - return tmp[len(tmp)-1], nil - } - return "", errors.New("invalid input or no slice available") -} - -// GetSliceIndexValueE will take a source string and returns the value at the given index when split by the seperaror char -func GetSliceIndexValueE(source string, seperator string, index int) (string, error) { - if !(len(source) == 0 || len(seperator) == 0 || !strings.Contains(source, seperator) || index < 0) { - tmp := strings.Split(source, seperator) - if !(len(tmp) >= index) { - return "", errors.New("index out of slice range") - } - return tmp[index], nil - } - return "", errors.New("invalid input or no slice available") + return id } diff --git a/modules/azure/resourceid_test.go b/modules/azure/resourceid_test.go new file mode 100644 index 000000000..dac80ed2f --- /dev/null +++ b/modules/azure/resourceid_test.go @@ -0,0 +1,29 @@ +// +build azure + +// NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for +// CircleCI. + +package azure + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetNameFromResourceID(t *testing.T) { + t.Parallel() + + // set slice variables + sliceSource := "this/is/a/long/slash/separated/string/ResourceID" + sliceResult := "ResourceID" + sliceNotFound := "noresourcepresent" + + // verify success + resultSuccess := GetNameFromResourceID(sliceSource) + assert.Equal(t, sliceResult, resultSuccess) + + // verify error when seperator not found + resultBadSeperator := GetNameFromResourceID(sliceNotFound) + assert.Equal(t, "", resultBadSeperator) +} diff --git a/modules/azure/virtualnetwork.go b/modules/azure/virtualnetwork.go index 366dea241..1cb149bc9 100644 --- a/modules/azure/virtualnetwork.go +++ b/modules/azure/virtualnetwork.go @@ -2,7 +2,6 @@ package azure import ( "context" - "fmt" "net" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" @@ -53,43 +52,28 @@ func CheckSubnetContainsIP(t testing.TestingT, IP string, subnetName string, vne // 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) { - subnetPrefix, err := GetSubnetIPRangeE(t, subnetName, vnetName, resGroupName, subscriptionID) - if err != nil { - return false, err - } - // Convert the IP to a net IP address ip := net.ParseIP(ipAddress) - if ip == nil { - return false, fmt.Errorf("Failed to parse IP address %s", ipAddress) + return false, NewFailedToParseError("IP Address", ipAddress) } - // Check if the IP is in the Subnet Range - _, ipNet, err := net.ParseCIDR(subnetPrefix) + // Get Subnet + subnet, err := GetSubnetE(t, subnetName, vnetName, resGroupName, subscriptionID) if err != nil { - return false, fmt.Errorf("Failed to parse subnet range %s", subnetPrefix) + return false, err } - return ipNet.Contains(ip), nil -} - -// GetSubnetIPRange gets the IPv4 Range of the specified Subnet -func GetSubnetIPRange(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) string { - vnetDNSIPs, err := GetSubnetIPRangeE(t, subnetName, vnetName, resGroupName, subscriptionID) - require.NoError(t, err) - return vnetDNSIPs -} + // Get Subnet IP range, this required field is never nil therefore no exception handling required + subnetPrefix := *subnet.AddressPrefix -// GetSubnetIPRangeE gets the IPv4 Range of the specified Subnet -func GetSubnetIPRangeE(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) (string, error) { - // Get Subnet - subnet, err := GetSubnetE(t, subnetName, vnetName, resGroupName, subscriptionID) + // Check if the IP is in the Subnet Range using the net package + _, ipNet, err := net.ParseCIDR(subnetPrefix) if err != nil { - return "", err + return false, NewFailedToParseError("Subnet Range", subnetPrefix) } - return *subnet.AddressPrefix, nil + return ipNet.Contains(ip), nil } // GetVirtualNetworkSubnets gets all Subnet names and their respective address prefixes in the specified Virtual Network @@ -100,18 +84,20 @@ func GetVirtualNetworkSubnets(t testing.TestingT, vnetName string, resGroupName } // 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 commonly accessed properties func GetVirtualNetworkSubnetsE(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) (map[string]string, error) { + subNetDetails := map[string]string{} + client, err := GetSubnetClientE(subscriptionID) if err != nil { - return nil, err + return subNetDetails, err } subnets, err := client.List(context.Background(), resGroupName, vnetName) if err != nil { - return nil, err + return subNetDetails, err } - subNetDetails := make(map[string]string) for _, v := range subnets.Values() { subnetName := v.Name subNetAddressPrefix := v.AddressPrefix diff --git a/test/azure/virtualnetwork_test.go b/modules/azure/virtualnetwork_test.go similarity index 64% rename from test/azure/virtualnetwork_test.go rename to modules/azure/virtualnetwork_test.go index 3a774bf3f..2c22d4071 100644 --- a/test/azure/virtualnetwork_test.go +++ b/modules/azure/virtualnetwork_test.go @@ -3,12 +3,11 @@ // NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for // CircleCI. -package test +package azure import ( "testing" - "github.com/gruntwork-io/terratest/modules/azure" "github.com/stretchr/testify/require" ) @@ -24,7 +23,7 @@ func TestGetVirtualNetworkE(t *testing.T) { rgName := "" subID := "" - _, err := azure.GetVirtualNetworkE(t, vnetName, rgName, subID) + _, err := GetVirtualNetworkE(t, vnetName, rgName, subID) require.Error(t, err) } @@ -37,7 +36,7 @@ func TestGetSubnetE(t *testing.T) { rgName := "" subID := "" - _, err := azure.GetSubnetE(t, subnetName, vnetName, rgName, subID) + _, err := GetSubnetE(t, subnetName, vnetName, rgName, subID) require.Error(t, err) } @@ -49,7 +48,7 @@ func TestGetVirtualNetworkDNSServerIPsE(t *testing.T) { rgName := "" subID := "" - _, err := azure.GetVirtualNetworkDNSServerIPsE(t, vnetName, rgName, subID) + _, err := GetVirtualNetworkDNSServerIPsE(t, vnetName, rgName, subID) require.Error(t, err) } @@ -61,20 +60,7 @@ func TestGetVirtualNetworkSubnetsE(t *testing.T) { rgName := "" subID := "" - _, err := azure.GetVirtualNetworkSubnetsE(t, vnetName, rgName, subID) - - require.Error(t, err) -} - -func TestGetSubnetIPRangeE(t *testing.T) { - t.Parallel() - - subnetName := "" - vnetName := "" - rgName := "" - subID := "" - - _, err := azure.GetSubnetIPRangeE(t, subnetName, vnetName, rgName, subID) + _, err := GetVirtualNetworkSubnetsE(t, vnetName, rgName, subID) require.Error(t, err) } @@ -88,7 +74,7 @@ func TestCheckSubnetContainsIPE(t *testing.T) { rgName := "" subID := "" - _, err := azure.CheckSubnetContainsIPE(t, ipAddress, subnetName, vnetName, rgName, subID) + _, err := CheckSubnetContainsIPE(t, ipAddress, subnetName, vnetName, rgName, subID) require.Error(t, err) } @@ -101,7 +87,7 @@ func TestSubnetExistsE(t *testing.T) { rgName := "" subID := "" - _, err := azure.SubnetExistsE(t, subnetName, vnetName, rgName, subID) + _, err := SubnetExistsE(t, subnetName, vnetName, rgName, subID) require.Error(t, err) } @@ -113,7 +99,7 @@ func TestVirtualNetworkExistsE(t *testing.T) { rgName := "" subID := "" - _, err := azure.VirtualNetworkExistsE(t, vnetName, rgName, subID) + _, err := VirtualNetworkExistsE(t, vnetName, rgName, subID) require.Error(t, err) } diff --git a/modules/collections/errors.go b/modules/collections/errors.go new file mode 100644 index 000000000..56afccea2 --- /dev/null +++ b/modules/collections/errors.go @@ -0,0 +1,17 @@ +package collections + +import "fmt" + +// SliceValueNotFoundError is returned when a provided values file input is not found on the host path. +type SliceValueNotFoundError struct { + sourceString string +} + +func (err SliceValueNotFoundError) Error() string { + return fmt.Sprintf("Could not resolve requested slice value from string %s", err.sourceString) +} + +// NewSliceValueNotFoundError creates a new slice found error +func NewSliceValueNotFoundError(sourceString string) SliceValueNotFoundError { + return SliceValueNotFoundError{sourceString} +} diff --git a/modules/collections/stringslicevalue.go b/modules/collections/stringslicevalue.go new file mode 100644 index 000000000..2d93212c0 --- /dev/null +++ b/modules/collections/stringslicevalue.go @@ -0,0 +1,26 @@ +package collections + +import ( + "strings" +) + +// GetSliceLastValueE will take a source string and returns the last value when split by the seperaror char +func GetSliceLastValueE(source string, seperator string) (string, error) { + if len(source) > 0 && len(seperator) > 0 && strings.Contains(source, seperator) { + tmp := strings.Split(source, seperator) + return tmp[len(tmp)-1], nil + } + return "", NewSliceValueNotFoundError(source) +} + +// GetSliceIndexValueE will take a source string and returns the value at the given index when split by the seperaror char +func GetSliceIndexValueE(source string, seperator string, index int) (string, error) { + if len(source) > 0 && len(seperator) > 0 && strings.Contains(source, seperator) && index >= 0 { + tmp := strings.Split(source, seperator) + if index > len(tmp) { + return "", NewSliceValueNotFoundError(source) + } + return tmp[index], nil + } + return "", NewSliceValueNotFoundError(source) +} diff --git a/modules/collections/stringslicevalue_test.go b/modules/collections/stringslicevalue_test.go new file mode 100644 index 000000000..06448b360 --- /dev/null +++ b/modules/collections/stringslicevalue_test.go @@ -0,0 +1,77 @@ +package collections + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGetSliceLastValue(t *testing.T) { + t.Parallel() + + var testCases = []struct { + testName string + sliceSource string + sliceSeperator string + expectedReturn string + expectedError bool + }{ + {"longSlice", "this/is/a/long/slash/separated/string/success", "/", "success", false}, + {"shortendSlice", "this/is/a/long/slash/separated", "/", "separated", false}, + {"dashSlice", "this-is-a-long-dash-separated-string-success", "-", "success", false}, + {"seperatorNotPresent", "this-is-a-long-dash-separated-string-success", "/", "", true}, + {"sourceNoSeperator", "noslicepresent", "/", "", true}, + {"emptyStrings", "", "", "", true}, + } + + for _, tc := range testCases { + testFor := tc //necessary range capture + + t.Run(testFor.testName, func(t *testing.T) { + actualReturn, err := GetSliceLastValueE(testFor.sliceSource, testFor.sliceSeperator) + switch testFor.expectedError { + case true: + require.Error(t, err) + case false: + require.NoError(t, err) + } + assert.Equal(t, testFor.expectedReturn, actualReturn) + }) + } +} + +func TestGetSliceIndexValue(t *testing.T) { + t.Parallel() + + var testCases = []struct { + sliceIndex int + expectedReturn string + expectedError bool + }{ + {-1, "", true}, + {0, "this", false}, + {4, "slash", false}, + {7, "success", false}, + {10, "", true}, + } + + sliceSource := "this/is/a/long/slash/separated/string/success" + sliceSeperator := "/" + + for _, tc := range testCases { + testFor := tc //necessary range capture + + t.Run(fmt.Sprintf("Index_%v", testFor.sliceIndex), func(t *testing.T) { + actualReturn, err := GetSliceIndexValueE(sliceSource, sliceSeperator, testFor.sliceIndex) + switch testFor.expectedError { + case true: + require.Error(t, err) + case false: + require.NoError(t, err) + } + assert.Equal(t, testFor.expectedReturn, actualReturn) + }) + } +} diff --git a/test/azure/resourceid_test.go b/test/azure/resourceid_test.go deleted file mode 100644 index 9aa66c6f7..000000000 --- a/test/azure/resourceid_test.go +++ /dev/null @@ -1,96 +0,0 @@ -// +build azure - -// NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for -// CircleCI. - -package test - -import ( - "testing" - - "github.com/gruntwork-io/terratest/modules/azure" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestGetNameFromResourceID(t *testing.T) { - // set slice variables - sliceSource := "this/is/a/long/slash/separated/string/ResourceID" - sliceResult := "ResourceID" - sliceNotFound := "noresourcepresent" - - // verify success - resultSuccess := azure.GetNameFromResourceID(sliceSource) - assert.Equal(t, sliceResult, resultSuccess) - - // verify error when seperator not found - resultBadSeperator := azure.GetNameFromResourceID(sliceNotFound) - assert.Equal(t, "", resultBadSeperator) -} - -func TestGetSliceLastValue(t *testing.T) { - // set slice variables - sliceSeperator := "/" - sliceBadSeperator := "*" - sliceNotFound := "noslicepresent" - sliceSource := "this/is/a/long/slash/separated/string/success" - sliceResult := "success" - - // verify success - resultSuccess, err := azure.GetSliceLastValueE(sliceSource, sliceSeperator) - require.NoError(t, err) - assert.Equal(t, sliceResult, resultSuccess) - - // verify error when seperator not found - resultBadSeperator, err := azure.GetSliceLastValueE(sliceSource, sliceBadSeperator) - require.Error(t, err) - assert.Equal(t, err.Error(), "invalid input or no slice available") - assert.Equal(t, "", resultBadSeperator) - - // verify error when slice does not have seperator - resultNotFound, err := azure.GetSliceLastValueE(sliceNotFound, sliceSeperator) - require.Error(t, err) - assert.Equal(t, err.Error(), "invalid input or no slice available") - assert.Equal(t, "", resultNotFound) -} - -func TestGetSliceIndexValue(t *testing.T) { - // set slice variables - sliceSource := "this/is/a/long/slash/separated/string/success" - sliceSeperator := "/" - sliceSelectorNeg := -1 - sliceSelector0 := 0 - sliceSelector4 := 4 - sliceSelector7 := 7 - sliceSelector10 := 10 - sliceResult0 := "this" - sliceResult4 := "slash" - sliceResult7 := "success" - - // verify success index 0 - resultSuccess0, err := azure.GetSliceIndexValueE(sliceSource, sliceSeperator, sliceSelector0) - require.NoError(t, err) - assert.Equal(t, sliceResult0, resultSuccess0) - - // verify success index 4 - resultSuccess4, err := azure.GetSliceIndexValueE(sliceSource, sliceSeperator, sliceSelector4) - require.NoError(t, err) - assert.Equal(t, sliceResult4, resultSuccess4) - - // verify success index 7 - resultSuccess7, err := azure.GetSliceIndexValueE(sliceSource, sliceSeperator, sliceSelector7) - require.NoError(t, err) - assert.Equal(t, sliceResult7, resultSuccess7) - - // verify error with negative index - resultNegIndex, err := azure.GetSliceIndexValueE(sliceSource, sliceSeperator, sliceSelectorNeg) - require.Error(t, err) - assert.Equal(t, err.Error(), "invalid input or no slice available") - assert.Equal(t, "", resultNegIndex) - - // verify error when seperator not found - resultBadIndex10, err := azure.GetSliceIndexValueE(sliceSource, sliceSeperator, sliceSelector10) - require.Error(t, err) - assert.Equal(t, err.Error(), "index out of slice range") - assert.Equal(t, "", resultBadIndex10) -} diff --git a/test/azure/terraform_azure_network_example_test.go b/test/azure/terraform_azure_network_example_test.go index a0f9d3b5f..25c91012a 100644 --- a/test/azure/terraform_azure_network_example_test.go +++ b/test/azure/terraform_azure_network_example_test.go @@ -19,15 +19,15 @@ import ( func TestTerraformAzureNetworkExample(t *testing.T) { t.Parallel() - subscriptionID := "" // Subscription ID, leave blank if available as an Environment Var - prefix := "terratest-net" + // Create values for Terraform + subscriptionID := "" // leave blank if available as an Environment Var + prefix := fmt.Sprintf("terratest-net-%s", random.UniqueId()) + expectedLocation := "eastus2" expectedSubnetRange := "10.0.20.0/24" expectedPrivateIP := "10.0.20.5" expectedDnsIp01 := "10.0.0.5" expectedDnsIp02 := "10.0.0.6" - expectedLocation := "eastus2" - - exectedDNSLabel := fmt.Sprintf("%s-%s", prefix, strings.ToLower(random.UniqueId())) + exectedDNSLabel := strings.ToLower(prefix) // only lowercase, numeric and hyphens allowed // Configure Terraform setting up a path to Terraform code. terraformOptions := &terraform.Options{ @@ -49,7 +49,7 @@ func TestTerraformAzureNetworkExample(t *testing.T) { // At the end of the test, run `terraform destroy` to clean up any resources that were created defer terraform.Destroy(t, terraformOptions) - // Run `terraform init` and `terraform apply`. Fail the test if there are any errors. + // Run `terraform init` and `terraform apply`. Fail the test if there are any errors terraform.InitAndApply(t, terraformOptions) // Run `terraform output` to get the values of output variables @@ -60,12 +60,14 @@ func TestTerraformAzureNetworkExample(t *testing.T) { nicInternalName := terraform.Output(t, terraformOptions, "network_interface_internal") nicExternalName := terraform.Output(t, terraformOptions, "network_interface_external") - // Sub-tests for integrated resources + // Tests are separated into subtests to differentiate integrated tests and pure resource tests + // Integrated network resource tests t.Run("VirtualNetwork_Subnet", func(t *testing.T) { - // Check the Subnet exists in the Virtual Network Subnets + // Check the Subnet exists in the Virtual Network Subnets with the expected Address Prefix actualVnetSubnets := azure.GetVirtualNetworkSubnets(t, virtualNetworkName, resourceGroupName, subscriptionID) assert.NotNil(t, actualVnetSubnets[subnetName]) + assert.Equal(t, expectedSubnetRange, actualVnetSubnets[subnetName]) }) t.Run("NIC_PublicAddress", func(t *testing.T) { @@ -84,16 +86,15 @@ func TestTerraformAzureNetworkExample(t *testing.T) { assert.True(t, checkPrivateIpInSubnet) }) - // Sub-tests for individual resources - - t.Run("NetworkResources", func(t *testing.T) { + // Tests for individual network resources + t.Run("Network", func(t *testing.T) { // Check the Virtual Network exists assert.True(t, azure.VirtualNetworkExists(t, virtualNetworkName, resourceGroupName, subscriptionID)) // Check the Subnet exists assert.True(t, azure.SubnetExists(t, subnetName, virtualNetworkName, resourceGroupName, subscriptionID)) - // Check the Network Interface exists + // Check the Network Interfaces exist assert.True(t, azure.NetworkInterfaceExists(t, nicInternalName, resourceGroupName, subscriptionID)) assert.True(t, azure.NetworkInterfaceExists(t, nicExternalName, resourceGroupName, subscriptionID)) @@ -105,10 +106,6 @@ func TestTerraformAzureNetworkExample(t *testing.T) { assert.Contains(t, actualDNSIPs, expectedDnsIp01) assert.Contains(t, actualDNSIPs, expectedDnsIp02) - // Check Subnet address range - actualSubnetRange := azure.GetSubnetIPRange(t, subnetName, virtualNetworkName, resourceGroupName, subscriptionID) - assert.Equal(t, expectedSubnetRange, actualSubnetRange) - // Check the Network Interface private IP actualPrivateIPs := azure.GetNetworkInterfacePrivateIPs(t, nicInternalName, resourceGroupName, subscriptionID) assert.Contains(t, actualPrivateIPs, expectedPrivateIP) @@ -117,12 +114,12 @@ func TestTerraformAzureNetworkExample(t *testing.T) { actualPublicIP := azure.GetPublicAddressIP(t, publicAddressName, resourceGroupName, subscriptionID) assert.True(t, len(actualPublicIP) > 0) - // Check DNS created for this example is not available for use + // Check DNS created for this example is reserved actualDnsNotAvailable := azure.CheckPublicDNSNameAvailability(t, expectedLocation, exectedDNSLabel, subscriptionID) assert.False(t, actualDnsNotAvailable) - // Check new DNS created is available - newDNSLabel := fmt.Sprintf("%s-%s", prefix, strings.ToLower(random.UniqueId())) + // Check new randomized DNS is available + newDNSLabel := strings.ToLower(fmt.Sprintf("%s-%s-%s", prefix, random.UniqueId(), random.UniqueId())) actualDnsAvailable := azure.CheckPublicDNSNameAvailability(t, expectedLocation, newDNSLabel, subscriptionID) assert.True(t, actualDnsAvailable) }) From 0429b1fea02be5f497b50bd10d82ddfd02f8d02c Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Tue, 22 Sep 2020 16:44:55 -0400 Subject: [PATCH 06/20] Updates based on feedback from PR 626 --- examples/azure/README.md | 54 +++++++++++++++++++ .../terraform-azure-network-example/README.md | 1 + .../terraform-azure-network-example/main.tf | 16 ++++-- modules/azure/compute.go | 12 +++-- modules/azure/networkinterface.go | 21 ++++---- modules/azure/publicaddress.go | 18 ++++--- modules/azure/region_test.go | 3 +- modules/azure/virtualnetwork.go | 37 +++++++------ modules/collections/stringslicevalue.go | 17 +++--- .../terraform_azure_network_example_test.go | 4 +- 10 files changed, 130 insertions(+), 53 deletions(-) create mode 100644 examples/azure/README.md diff --git a/examples/azure/README.md b/examples/azure/README.md new file mode 100644 index 000000000..42cf21ea0 --- /dev/null +++ b/examples/azure/README.md @@ -0,0 +1,54 @@ +# 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. + +- 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) + +## Go Dependencies + +Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH` + +These modules are currently using the latest version of Go and was tested with **go1.14.4**. + +## Azure-sdk-for-go version + +Let's make sure [go.mod](https://github.com/gruntwork-io/terratest/blob/master/go.mod) includes the appropriate [azure-sdk-for-go version](https://github.com/Azure/azure-sdk-for-go/releases/tag/v46.1.0): + +```go +require ( + ... + github.com/Azure/azure-sdk-for-go v46.1.0+incompatible + ... +) +``` + +If we make changes to either the **go.mod** or the **go test file**, we should make sure that the go build command works still. + +```powershell +go build terraform_azure_*_test.go +``` + +## Review Environment Variables + +As part of configuring terraform for Azure, we'll want to check that we have set the appropriate [credentials](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#set-up-terraform-access-to-azure) and also that we set the [environment variables](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#configure-terraform-environment-variables) on the testing host. + +```bash +export ARM_CLIENT_ID=your_app_id +export ARM_CLIENT_SECRET=your_password +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: + +```powershell +[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID",$your_app_id,[System.EnvironmentVariableTarget]::Machine) +[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_SECRET",$your_password,[System.EnvironmentVariableTarget]::Machine) +[System.Environment]::SetEnvironmentVariable("ARM_SUBSCRIPTION_ID",$your_subscription_id,[System.EnvironmentVariableTarget]::Machine) +[System.Environment]::SetEnvironmentVariable("ARM_TENANT_ID",$your_tenant_id,[System.EnvironmentVariableTarget]::Machine) +``` diff --git a/examples/azure/terraform-azure-network-example/README.md b/examples/azure/terraform-azure-network-example/README.md index 54e56fcb3..edf057ee0 100644 --- a/examples/azure/terraform-azure-network-example/README.md +++ b/examples/azure/terraform-azure-network-example/README.md @@ -26,6 +26,7 @@ it should be free, but you are completely responsible for all Azure charges. 1. Configure your Azure credentials using one of the [supported methods for Azure CLI tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest) 1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH` +1. Ensure [environment variables](../README.md#review-environment-variables) are available 1. Run `terraform init` 1. Run `terraform apply` 1. When you're done, run `terraform destroy` diff --git a/examples/azure/terraform-azure-network-example/main.tf b/examples/azure/terraform-azure-network-example/main.tf index dacf0b5d9..8aaa3ae24 100644 --- a/examples/azure/terraform-azure-network-example/main.tf +++ b/examples/azure/terraform-azure-network-example/main.tf @@ -1,3 +1,11 @@ +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY AN AZURE NETWORK +# This is an example of how to deploy frequent Azure Networking Resources. Note this network dosen't actually do +# anything and is only created for the example to test their commonly needed and integrated propeties. +# --------------------------------------------------------------------------------------------------------------------- +# See test/azure/terraform_azure_network_example_test.go for how to write automated tests for this code. +# --------------------------------------------------------------------------------------------------------------------- + provider "azurerm" { version = "=2.20.0" features {} @@ -9,11 +17,12 @@ provider "azurerm" { # --------------------------------------------------------------------------------------------------------------------- terraform { - required_version = ">= 0.12" + # This module is now only being tested with Terraform 0.13.x. However, to make upgrading easier, we are setting + # 0.12.26 as the minimum version, as that version added support for required_providers with source URLs, making it + # forwards compatible with 0.13.x code. + required_version = ">= 0.12.26" } -# --------------------------------------------------------------------------------------------------------------------- -# See test/azure/terraform_azure_network_example_test.go for how to write automated tests for this code. # --------------------------------------------------------------------------------------------------------------------- # DEPLOY A RESOURCE GROUP # --------------------------------------------------------------------------------------------------------------------- @@ -25,7 +34,6 @@ resource "azurerm_resource_group" "net" { # --------------------------------------------------------------------------------------------------------------------- # DEPLOY VIRTUAL NETWORK -# Note this network dosen't actually do anything and is only created for the example. # --------------------------------------------------------------------------------------------------------------------- resource "azurerm_virtual_network" "net" { diff --git a/modules/azure/compute.go b/modules/azure/compute.go index 8607176fc..33da0d707 100644 --- a/modules/azure/compute.go +++ b/modules/azure/compute.go @@ -8,8 +8,9 @@ import ( "github.com/stretchr/testify/require" ) -// GetVirtualMachineClient is a helper function that will setup an Azure Virtual Machine client on your behalf -func GetVirtualMachineClient(subscriptionID string) (*compute.VirtualMachinesClient, error) { +// GetVirtualMachineClientE is a helper function that will setup an Azure Virtual Machine client on your behalf. +// This function would fail the test if there is an error. +func GetVirtualMachineClientE(subscriptionID string) (*compute.VirtualMachinesClient, error) { // Validate Azure subscription ID subscriptionID, err := getTargetAzureSubscription(subscriptionID) if err != nil { @@ -31,7 +32,8 @@ func GetVirtualMachineClient(subscriptionID string) (*compute.VirtualMachinesCli return &vmClient, nil } -// GetSizeOfVirtualMachine gets the size type of the given Azure Virtual Machine +// GetSizeOfVirtualMachine gets the size type of the given Azure Virtual Machine. +// This function would fail the test if there is an error. func GetSizeOfVirtualMachine(t testing.TestingT, vmName string, resGroupName string, subscriptionID string) compute.VirtualMachineSizeTypes { size, err := GetSizeOfVirtualMachineE(t, vmName, resGroupName, subscriptionID) require.NoError(t, err) @@ -48,7 +50,7 @@ func GetSizeOfVirtualMachineE(t testing.TestingT, vmName string, resGroupName st } // Create a VM client - vmClient, err := GetVirtualMachineClient(subscriptionID) + vmClient, err := GetVirtualMachineClientE(subscriptionID) if err != nil { return "", err } @@ -82,7 +84,7 @@ func GetTagsForVirtualMachineE(t testing.TestingT, vmName string, resGroupName s } // Create a VM client - vmClient, err := GetVirtualMachineClient(subscriptionID) + vmClient, err := GetVirtualMachineClientE(subscriptionID) if err != nil { return tags, err } diff --git a/modules/azure/networkinterface.go b/modules/azure/networkinterface.go index a17c576c9..5bbe3a394 100644 --- a/modules/azure/networkinterface.go +++ b/modules/azure/networkinterface.go @@ -10,14 +10,15 @@ import ( "github.com/stretchr/testify/require" ) -// NetworkInterfaceExists indicates whether the speficied Azure Network Interface exists +// NetworkInterfaceExists indicates whether the speficied 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) require.NoError(t, err) return exists } -// NetworkInterfaceExistsE indicates whether the speficied Azure Network Interface exists +// NetworkInterfaceExistsE indicates whether the speficied Azure Network Interface exists. func NetworkInterfaceExistsE(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) (bool, error) { // Get the Network Interface _, err := GetNetworkInterfaceE(t, nicName, resGroupName, subscriptionID) @@ -27,14 +28,15 @@ func NetworkInterfaceExistsE(t testing.TestingT, nicName string, resGroupName st return true, nil } -// GetNetworkInterfacePublicIPs returns a list of all the Public IPs found in the Network Interface configurations +// 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) require.NoError(t, err) return IPs } -// GetNetworkInterfacePublicIPsE returns a list of all the Public IPs found in the Network Interface configurations +// 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) { publicIPs := []string{} @@ -59,7 +61,7 @@ func GetNetworkInterfacePublicIPsE(t testing.TestingT, nicName string, resGroupN return publicIPs, nil } -// ipConfigHasPublicIP returns true if an IP Configuration has a Public IP Address +// ipConfigHasPublicIP returns true if an IP Configuration has a Public IP Address. // This helper method was created since a config without a public address causes a nil pointer panic // and the string representation is searched for the publicIPAddress text to identify it's presence. func ipConfigHasPublicIP(ipConfig *network.InterfaceIPConfiguration) bool { @@ -73,7 +75,8 @@ func ipConfigHasPublicIP(ipConfig *network.InterfaceIPConfiguration) bool { return strings.Contains(string(byteIPConfig), "publicIPAddress") } -// GetNetworkInterfacePrivateIPs gets a list of the Private IPs of a Network Interface configs +// 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) require.NoError(t, err) @@ -81,7 +84,7 @@ func GetNetworkInterfacePrivateIPs(t testing.TestingT, nicName string, resGroupN return IPs } -// GetNetworkInterfacePrivateIPsE gets a list of the Private IPs of a Network Interface configs +// 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) { privateIPs := []string{} @@ -99,7 +102,7 @@ func GetNetworkInterfacePrivateIPsE(t testing.TestingT, nicName string, resGroup return privateIPs, nil } -// GetNetworkInterfaceE gets a Network Interface in the specified Azure Resource Group +// 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) { // Validate Azure Resource Group resGroupName, err := getTargetAzureResourceGroupName(resGroupName) @@ -122,7 +125,7 @@ func GetNetworkInterfaceE(t testing.TestingT, nicName string, resGroupName strin return &nic, nil } -// GetNetworkInterfaceClientE creates a new Network Interface client in the specified Azure Subscription +// GetNetworkInterfaceClientE creates a new Network Interface client in the specified Azure Subscription. func GetNetworkInterfaceClientE(subscriptionID string) (*network.InterfacesClient, error) { // Validate Azure Subscription ID subscriptionID, err := getTargetAzureSubscription(subscriptionID) diff --git a/modules/azure/publicaddress.go b/modules/azure/publicaddress.go index 98e720492..713dd68e2 100644 --- a/modules/azure/publicaddress.go +++ b/modules/azure/publicaddress.go @@ -8,14 +8,15 @@ import ( "github.com/stretchr/testify/require" ) -// PublicAddressExists indicates whether the speficied AzurePublic Address exists +// PublicAddressExists indicates whether the speficied 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) require.NoError(t, err) return exists } -// PublicAddressExistsE indicates whether the speficied AzurePublic Address exists +// PublicAddressExistsE indicates whether the speficied AzurePublic Address exists. func PublicAddressExistsE(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) (bool, error) { // Get the Public Address _, err := GetPublicIPAddressE(t, publicAddressName, resGroupName, subscriptionID) @@ -25,14 +26,14 @@ func PublicAddressExistsE(t testing.TestingT, publicAddressName string, resGroup return true, nil } -// GetPublicAddressIP gets the IP of a Public IP Address +// 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) require.NoError(t, err) return IP } -// GetPublicAddressIPE gets the IP of a Public IP Address with error +// GetPublicAddressIPE gets the IP of a Public IP Address. func GetPublicAddressIPE(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) (string, error) { // Create a NIC client pip, err := GetPublicIPAddressE(t, publicAddressName, resGroupName, subscriptionID) @@ -43,7 +44,8 @@ func GetPublicAddressIPE(t testing.TestingT, publicAddressName string, resGroupN return *pip.IPAddress, nil } -// CheckPublicDNSNameAvailability checks whether a Domain Name in the cloudapp.azure.com zone is available for use +// 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) if err != nil { @@ -52,7 +54,7 @@ func CheckPublicDNSNameAvailability(t testing.TestingT, location string, domainN return available } -// CheckPublicDNSNameAvailabilityE checks whether a Domain Name in the cloudapp.azure.com zone is available for use +// 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) { client, err := GetPublicIPAddressClientE(subscriptionID) if err != nil { @@ -67,7 +69,7 @@ func CheckPublicDNSNameAvailabilityE(t testing.TestingT, location string, domain return *res.Available, nil } -// GetPublicIPAddressE gets a Public IP Addresses in the specified Azure Resource Group +// 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) { // Validate resource group name and subscription ID resGroupName, err := getTargetAzureResourceGroupName(resGroupName) @@ -89,7 +91,7 @@ func GetPublicIPAddressE(t testing.TestingT, publicIPAddressName string, resGrou return &pip, nil } -// GetPublicIPAddressClientE creates a Public IP Addresses client in the specified Azure Subscription +// GetPublicIPAddressClientE creates a Public IP Addresses client in the specified Azure Subscription. func GetPublicIPAddressClientE(subscriptionID string) (*network.PublicIPAddressesClient, error) { // Validate Azure subscription ID subscriptionID, err := getTargetAzureSubscription(subscriptionID) diff --git a/modules/azure/region_test.go b/modules/azure/region_test.go index eeb45807d..8b3d041f1 100644 --- a/modules/azure/region_test.go +++ b/modules/azure/region_test.go @@ -37,7 +37,8 @@ func TestGetAllAzureRegions(t *testing.T) { regions := GetAllAzureRegions(t, "") - // The typical subscription had access to 30+ live regions as of July 2019: https://azure.microsoft.com/en-us/global-infrastructure/regions/ + // The typical subscription had access to 30+ live regions as of + // July 2019: https://azure.microsoft.com/en-us/global-infrastructure/regions/ assert.True(t, len(regions) >= 30, "Number of regions: %d", len(regions)) for _, region := range regions { assertLooksLikeRegionName(t, region) diff --git a/modules/azure/virtualnetwork.go b/modules/azure/virtualnetwork.go index 1cb149bc9..ecbb6bc87 100644 --- a/modules/azure/virtualnetwork.go +++ b/modules/azure/virtualnetwork.go @@ -9,14 +9,15 @@ import ( "github.com/stretchr/testify/require" ) -// VirtualNetworkExists indicates whether the speficied Azure Virtual Network exists +// VirtualNetworkExists indicates whether the speficied 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) require.NoError(t, err) return exists } -// VirtualNetworkExistsE indicates whether the speficied Azure Virtual Network exists +// VirtualNetworkExistsE indicates whether the speficied Azure Virtual Network exists. func VirtualNetworkExistsE(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) (bool, error) { // Get the Virtual Network _, err := GetVirtualNetworkE(t, vnetName, resGroupName, subscriptionID) @@ -26,14 +27,15 @@ func VirtualNetworkExistsE(t testing.TestingT, vnetName string, resGroupName str return true, nil } -// SubnetExists indicates whether the speficied Azure Virtual Network Subnet exists +// SubnetExists indicates whether the speficied 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) require.NoError(t, err) return exists } -// SubnetExistsE indicates whether the speficied Azure Virtual Network Subnet exists +// SubnetExistsE indicates whether the speficied Azure Virtual Network Subnet exists. func SubnetExistsE(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) (bool, error) { // Get the Subnet _, err := GetSubnetE(t, subnetName, vnetName, resGroupName, subscriptionID) @@ -43,14 +45,15 @@ func SubnetExistsE(t testing.TestingT, subnetName string, vnetName string, resGr return true, nil } -// CheckSubnetContainsIP checks if the Private IP is contined in the Subnet Address Range +// 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) require.NoError(t, err) return inRange } -// CheckSubnetContainsIPE checks if the Private IP is contined in the Subnet Address Range +// 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) { // Convert the IP to a net IP address ip := net.ParseIP(ipAddress) @@ -64,7 +67,7 @@ func CheckSubnetContainsIPE(t testing.TestingT, ipAddress string, subnetName str return false, err } - // Get Subnet IP range, this required field is never nil therefore no exception handling required + // Get Subnet IP range, this required field is never nil therefore no exception handling required. subnetPrefix := *subnet.AddressPrefix // Check if the IP is in the Subnet Range using the net package @@ -76,15 +79,16 @@ func CheckSubnetContainsIPE(t testing.TestingT, ipAddress string, subnetName str return ipNet.Contains(ip), nil } -// GetVirtualNetworkSubnets gets all Subnet names and their respective address prefixes in the specified Virtual Network +// 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) 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 commonly accessed properties +// 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) { subNetDetails := map[string]string{} @@ -107,7 +111,8 @@ func GetVirtualNetworkSubnetsE(t testing.TestingT, vnetName string, resGroupName return subNetDetails, nil } -// GetVirtualNetworkDNSServerIPs gets a list of all Virtual Network DNS server IPs +// 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) require.NoError(t, err) @@ -115,7 +120,7 @@ func GetVirtualNetworkDNSServerIPs(t testing.TestingT, vnetName string, resGroup return vnetDNSIPs } -// GetVirtualNetworkDNSServerIPsE gets a list of all Virtual Network DNS server IPs with Error +// 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) { // Get Virtual Network vnet, err := GetVirtualNetworkE(t, vnetName, resGroupName, subscriptionID) @@ -126,7 +131,7 @@ func GetVirtualNetworkDNSServerIPsE(t testing.TestingT, vnetName string, resGrou return *vnet.DhcpOptions.DNSServers, nil } -// GetSubnetE gets a subnet +// GetSubnetE gets a subnet. func GetSubnetE(t testing.TestingT, subnetName string, vnetName string, resGroupName string, subscriptionID string) (*network.Subnet, error) { // Validate Azure Resource Group resGroupName, err := getTargetAzureResourceGroupName(resGroupName) @@ -149,7 +154,7 @@ func GetSubnetE(t testing.TestingT, subnetName string, vnetName string, resGroup return &subnet, nil } -// GetSubnetClientE creates a subnet client +// GetSubnetClientE creates a subnet client. func GetSubnetClientE(subscriptionID string) (*network.SubnetsClient, error) { // Validate Azure subscription ID subscriptionID, err := getTargetAzureSubscription(subscriptionID) @@ -170,7 +175,7 @@ func GetSubnetClientE(subscriptionID string) (*network.SubnetsClient, error) { return &client, nil } -// GetVirtualNetworkE gets Virtual Network in the specified Azure Resource Group +// GetVirtualNetworkE gets Virtual Network in the specified Azure Resource Group. func GetVirtualNetworkE(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) (*network.VirtualNetwork, error) { // Validate Azure Resource Group resGroupName, err := getTargetAzureResourceGroupName(resGroupName) @@ -192,7 +197,7 @@ func GetVirtualNetworkE(t testing.TestingT, vnetName string, resGroupName string return &vnet, nil } -// GetVirtualNetworksClientE creates a virtual network client in the specified Azure Subscription +// GetVirtualNetworksClientE creates a virtual network client in the specified Azure Subscription. func GetVirtualNetworksClientE(subscriptionID string) (*network.VirtualNetworksClient, error) { // Validate Azure subscription ID subscriptionID, err := getTargetAzureSubscription(subscriptionID) diff --git a/modules/collections/stringslicevalue.go b/modules/collections/stringslicevalue.go index 2d93212c0..0fede5e41 100644 --- a/modules/collections/stringslicevalue.go +++ b/modules/collections/stringslicevalue.go @@ -4,19 +4,20 @@ import ( "strings" ) -// GetSliceLastValueE will take a source string and returns the last value when split by the seperaror char -func GetSliceLastValueE(source string, seperator string) (string, error) { - if len(source) > 0 && len(seperator) > 0 && strings.Contains(source, seperator) { - tmp := strings.Split(source, seperator) +// GetSliceLastValueE will take a source string and returns the last value when split by the separator char. +func GetSliceLastValueE(source string, separator string) (string, error) { + if len(source) > 0 && len(separator) > 0 && strings.Contains(source, separator) { + tmp := strings.Split(source, separator) return tmp[len(tmp)-1], nil } return "", NewSliceValueNotFoundError(source) } -// GetSliceIndexValueE will take a source string and returns the value at the given index when split by the seperaror char -func GetSliceIndexValueE(source string, seperator string, index int) (string, error) { - if len(source) > 0 && len(seperator) > 0 && strings.Contains(source, seperator) && index >= 0 { - tmp := strings.Split(source, seperator) +// GetSliceIndexValueE will take a source string and returns the value at the given index when split by +// the separator char. +func GetSliceIndexValueE(source string, separator string, index int) (string, error) { + if len(source) > 0 && len(separator) > 0 && strings.Contains(source, separator) && index >= 0 { + tmp := strings.Split(source, separator) if index > len(tmp) { return "", NewSliceValueNotFoundError(source) } diff --git a/test/azure/terraform_azure_network_example_test.go b/test/azure/terraform_azure_network_example_test.go index 25c91012a..73ec937b8 100644 --- a/test/azure/terraform_azure_network_example_test.go +++ b/test/azure/terraform_azure_network_example_test.go @@ -20,14 +20,14 @@ func TestTerraformAzureNetworkExample(t *testing.T) { t.Parallel() // Create values for Terraform - subscriptionID := "" // leave blank if available as an Environment Var + subscriptionID := "" // subscriptionID is overridden by the environment variable "ARM_SUBSCRIPTION_ID" prefix := fmt.Sprintf("terratest-net-%s", random.UniqueId()) expectedLocation := "eastus2" expectedSubnetRange := "10.0.20.0/24" expectedPrivateIP := "10.0.20.5" expectedDnsIp01 := "10.0.0.5" expectedDnsIp02 := "10.0.0.6" - exectedDNSLabel := strings.ToLower(prefix) // only lowercase, numeric and hyphens allowed + exectedDNSLabel := strings.ToLower(prefix) // only lowercase, numeric and hyphens chars allowed for DNS // Configure Terraform setting up a path to Terraform code. terraformOptions := &terraform.Options{ From 3d88757f4d136b4044e578b352f4ff5fbeffe964 Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Wed, 23 Sep 2020 15:08:14 -0400 Subject: [PATCH 07/20] Changed to postfix tf var --- .../terraform-azure-network-example/main.tf | 18 +++---- .../variables.tf | 4 +- .../terraform_azure_network_example_test.go | 52 +++++++++---------- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/examples/azure/terraform-azure-network-example/main.tf b/examples/azure/terraform-azure-network-example/main.tf index 8aaa3ae24..ba1db6fd0 100644 --- a/examples/azure/terraform-azure-network-example/main.tf +++ b/examples/azure/terraform-azure-network-example/main.tf @@ -28,7 +28,7 @@ terraform { # --------------------------------------------------------------------------------------------------------------------- resource "azurerm_resource_group" "net" { - name = "${var.prefix}-resources" + name = "terratest-net-rg-${var.postfix}" location = var.location } @@ -37,7 +37,7 @@ resource "azurerm_resource_group" "net" { # --------------------------------------------------------------------------------------------------------------------- resource "azurerm_virtual_network" "net" { - name = "${var.prefix}-vnet" + name = "vnet-${var.postfix}" location = azurerm_resource_group.net.location resource_group_name = azurerm_resource_group.net.name address_space = ["10.0.0.0/16"] @@ -45,18 +45,18 @@ resource "azurerm_virtual_network" "net" { } resource "azurerm_subnet" "net" { - name = "${var.prefix}-subnet" + name = "subnet-${var.postfix}" resource_group_name = azurerm_resource_group.net.name virtual_network_name = azurerm_virtual_network.net.name address_prefixes = [var.subnet_prefix] } # --------------------------------------------------------------------------------------------------------------------- -# DEPLOY INTERNAL NETWORK INTERFACE +# DEPLOY PRIVATE NETWORK INTERFACE # --------------------------------------------------------------------------------------------------------------------- resource "azurerm_network_interface" "net01" { - name = "${var.prefix}-nic-01" + name = "nic-private-${var.postfix}" location = azurerm_resource_group.net.location resource_group_name = azurerm_resource_group.net.name @@ -69,22 +69,22 @@ resource "azurerm_network_interface" "net01" { } # --------------------------------------------------------------------------------------------------------------------- -# DEPLOY PUBLIC IP AND EXTERNAL NETWORK INTERFACE +# DEPLOY PUBLIC IP AND NETWORK INTERFACE # --------------------------------------------------------------------------------------------------------------------- resource "azurerm_public_ip" "net" { - name = "${var.prefix}-pip" + name = "pip-${var.postfix}" resource_group_name = azurerm_resource_group.net.name location = azurerm_resource_group.net.location allocation_method = "Static" ip_version = "IPv4" - sku = "Standard" + sku = "Basic" idle_timeout_in_minutes = "4" domain_name_label = var.domain_name_label } resource "azurerm_network_interface" "net02" { - name = "${var.prefix}-nic-02" + name = "nic-public-${var.postfix}" location = azurerm_resource_group.net.location resource_group_name = azurerm_resource_group.net.name diff --git a/examples/azure/terraform-azure-network-example/variables.tf b/examples/azure/terraform-azure-network-example/variables.tf index 530a36851..0ed2219a7 100644 --- a/examples/azure/terraform-azure-network-example/variables.tf +++ b/examples/azure/terraform-azure-network-example/variables.tf @@ -41,8 +41,8 @@ variable "location" { default = "East US" } -variable "prefix" { - description = "The prefix that will be attached to all resources deployed" +variable "postfix" { + description = "The postfix that will be attached to all resources deployed" type = string default = "terratest-net" } diff --git a/test/azure/terraform_azure_network_example_test.go b/test/azure/terraform_azure_network_example_test.go index 73ec937b8..19411af17 100644 --- a/test/azure/terraform_azure_network_example_test.go +++ b/test/azure/terraform_azure_network_example_test.go @@ -21,13 +21,13 @@ func TestTerraformAzureNetworkExample(t *testing.T) { // Create values for Terraform subscriptionID := "" // subscriptionID is overridden by the environment variable "ARM_SUBSCRIPTION_ID" - prefix := fmt.Sprintf("terratest-net-%s", random.UniqueId()) + uniquePostfix := random.UniqueId() expectedLocation := "eastus2" expectedSubnetRange := "10.0.20.0/24" expectedPrivateIP := "10.0.20.5" expectedDnsIp01 := "10.0.0.5" expectedDnsIp02 := "10.0.0.6" - exectedDNSLabel := strings.ToLower(prefix) // only lowercase, numeric and hyphens chars allowed for DNS + exectedDNSLabel := fmt.Sprintf("dns-terratest-%s", strings.ToLower(uniquePostfix)) // only lowercase, numeric and hyphens chars allowed for DNS // Configure Terraform setting up a path to Terraform code. terraformOptions := &terraform.Options{ @@ -36,7 +36,7 @@ func TestTerraformAzureNetworkExample(t *testing.T) { // Variables to pass to our Terraform code using -var options Vars: map[string]interface{}{ - "prefix": prefix, + "postfix": uniquePostfix, "subnet_prefix": expectedSubnetRange, "private_ip": expectedPrivateIP, "dns_ip_01": expectedDnsIp01, @@ -53,65 +53,65 @@ func TestTerraformAzureNetworkExample(t *testing.T) { terraform.InitAndApply(t, terraformOptions) // Run `terraform output` to get the values of output variables - resourceGroupName := terraform.Output(t, terraformOptions, "resource_group_name") - virtualNetworkName := terraform.Output(t, terraformOptions, "virtual_network_name") - subnetName := terraform.Output(t, terraformOptions, "subnet_name") - publicAddressName := terraform.Output(t, terraformOptions, "public_address_name") - nicInternalName := terraform.Output(t, terraformOptions, "network_interface_internal") - nicExternalName := terraform.Output(t, terraformOptions, "network_interface_external") + expectedRgName := terraform.Output(t, terraformOptions, "resource_group_name") + expectedVNetName := terraform.Output(t, terraformOptions, "virtual_network_name") + expectedSubnetName := terraform.Output(t, terraformOptions, "subnet_name") + expectedPublicAddressName := terraform.Output(t, terraformOptions, "public_address_name") + expectedPrivateNicName := terraform.Output(t, terraformOptions, "network_interface_internal") + expectedPublicNicName := terraform.Output(t, terraformOptions, "network_interface_external") // Tests are separated into subtests to differentiate integrated tests and pure resource tests // Integrated network resource tests t.Run("VirtualNetwork_Subnet", func(t *testing.T) { // Check the Subnet exists in the Virtual Network Subnets with the expected Address Prefix - actualVnetSubnets := azure.GetVirtualNetworkSubnets(t, virtualNetworkName, resourceGroupName, subscriptionID) - assert.NotNil(t, actualVnetSubnets[subnetName]) - assert.Equal(t, expectedSubnetRange, actualVnetSubnets[subnetName]) + actualVnetSubnets := azure.GetVirtualNetworkSubnets(t, expectedVNetName, expectedRgName, subscriptionID) + assert.NotNil(t, actualVnetSubnets[expectedSubnetName]) + assert.Equal(t, expectedSubnetRange, actualVnetSubnets[expectedSubnetName]) }) t.Run("NIC_PublicAddress", func(t *testing.T) { // Check the internal network interface does NOT have a public IP - actualPrivateIPOnly := azure.GetNetworkInterfacePublicIPs(t, nicInternalName, resourceGroupName, subscriptionID) - assert.True(t, len(actualPrivateIPOnly) == 0) + actualPrivateIPOnly := azure.GetNetworkInterfacePublicIPs(t, expectedPrivateNicName, expectedRgName, subscriptionID) + assert.Nil(t, actualPrivateIPOnly) // Check the external network interface has a public IP - actualPublicIPs := azure.GetNetworkInterfacePublicIPs(t, nicExternalName, resourceGroupName, subscriptionID) + actualPublicIPs := azure.GetNetworkInterfacePublicIPs(t, expectedPublicNicName, expectedRgName, subscriptionID) assert.True(t, len(actualPublicIPs) == 1) }) t.Run("Subnet_NIC", func(t *testing.T) { // Check the private IP is in the subnet range - checkPrivateIpInSubnet := azure.CheckSubnetContainsIP(t, expectedPrivateIP, subnetName, virtualNetworkName, resourceGroupName, subscriptionID) + checkPrivateIpInSubnet := azure.CheckSubnetContainsIP(t, expectedPrivateIP, expectedSubnetName, expectedVNetName, expectedRgName, subscriptionID) assert.True(t, checkPrivateIpInSubnet) }) // Tests for individual network resources t.Run("Network", func(t *testing.T) { // Check the Virtual Network exists - assert.True(t, azure.VirtualNetworkExists(t, virtualNetworkName, resourceGroupName, subscriptionID)) + assert.True(t, azure.VirtualNetworkExists(t, expectedVNetName, expectedRgName, subscriptionID)) // Check the Subnet exists - assert.True(t, azure.SubnetExists(t, subnetName, virtualNetworkName, resourceGroupName, subscriptionID)) + assert.True(t, azure.SubnetExists(t, expectedSubnetName, expectedVNetName, expectedRgName, subscriptionID)) // Check the Network Interfaces exist - assert.True(t, azure.NetworkInterfaceExists(t, nicInternalName, resourceGroupName, subscriptionID)) - assert.True(t, azure.NetworkInterfaceExists(t, nicExternalName, resourceGroupName, subscriptionID)) + assert.True(t, azure.NetworkInterfaceExists(t, expectedPrivateNicName, expectedRgName, subscriptionID)) + assert.True(t, azure.NetworkInterfaceExists(t, expectedPublicNicName, expectedRgName, subscriptionID)) // Check Public Address exists - assert.True(t, azure.PublicAddressExists(t, publicAddressName, resourceGroupName, subscriptionID)) + assert.True(t, azure.PublicAddressExists(t, expectedPublicAddressName, expectedRgName, subscriptionID)) // Check the Virtual Network DNS server IPs - actualDNSIPs := azure.GetVirtualNetworkDNSServerIPs(t, virtualNetworkName, resourceGroupName, subscriptionID) + actualDNSIPs := azure.GetVirtualNetworkDNSServerIPs(t, expectedVNetName, expectedRgName, subscriptionID) assert.Contains(t, actualDNSIPs, expectedDnsIp01) assert.Contains(t, actualDNSIPs, expectedDnsIp02) // Check the Network Interface private IP - actualPrivateIPs := azure.GetNetworkInterfacePrivateIPs(t, nicInternalName, resourceGroupName, subscriptionID) + actualPrivateIPs := azure.GetNetworkInterfacePrivateIPs(t, expectedPrivateNicName, expectedRgName, subscriptionID) assert.Contains(t, actualPrivateIPs, expectedPrivateIP) - // Check the Public Address public IP - actualPublicIP := azure.GetPublicAddressIP(t, publicAddressName, resourceGroupName, subscriptionID) + // Check the Public Address public IP is allocated + actualPublicIP := azure.GetPublicAddressIP(t, expectedPublicAddressName, expectedRgName, subscriptionID) assert.True(t, len(actualPublicIP) > 0) // Check DNS created for this example is reserved @@ -119,7 +119,7 @@ func TestTerraformAzureNetworkExample(t *testing.T) { assert.False(t, actualDnsNotAvailable) // Check new randomized DNS is available - newDNSLabel := strings.ToLower(fmt.Sprintf("%s-%s-%s", prefix, random.UniqueId(), random.UniqueId())) + newDNSLabel := fmt.Sprintf("dns-terratest-%s", strings.ToLower(random.UniqueId())) actualDnsAvailable := azure.CheckPublicDNSNameAvailability(t, expectedLocation, newDNSLabel, subscriptionID) assert.True(t, actualDnsAvailable) }) From bff5665c4608bf5f9a482eaab55296b0c8620e44 Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Wed, 23 Sep 2020 18:04:12 -0400 Subject: [PATCH 08/20] Fixed spelling errors --- .../azure/terraform-azure-network-example/main.tf | 4 ++-- modules/azure/networkinterface.go | 6 +++--- modules/azure/publicaddress.go | 6 +++--- modules/azure/virtualnetwork.go | 12 ++++++------ 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/examples/azure/terraform-azure-network-example/main.tf b/examples/azure/terraform-azure-network-example/main.tf index ba1db6fd0..dbc84a8bf 100644 --- a/examples/azure/terraform-azure-network-example/main.tf +++ b/examples/azure/terraform-azure-network-example/main.tf @@ -1,7 +1,7 @@ # --------------------------------------------------------------------------------------------------------------------- # DEPLOY AN AZURE NETWORK -# This is an example of how to deploy frequent Azure Networking Resources. Note this network dosen't actually do -# anything and is only created for the example to test their commonly needed and integrated propeties. +# This is an example of how to deploy frequent Azure Networking Resources. Note this network doesn't actually do +# anything and is only created for the example to test their commonly needed and integrated properties. # --------------------------------------------------------------------------------------------------------------------- # See test/azure/terraform_azure_network_example_test.go for how to write automated tests for this code. # --------------------------------------------------------------------------------------------------------------------- diff --git a/modules/azure/networkinterface.go b/modules/azure/networkinterface.go index 5bbe3a394..541764c54 100644 --- a/modules/azure/networkinterface.go +++ b/modules/azure/networkinterface.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/require" ) -// NetworkInterfaceExists indicates whether the speficied Azure Network Interface exists. +// 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) @@ -18,7 +18,7 @@ func NetworkInterfaceExists(t testing.TestingT, nicName string, resGroupName str return exists } -// NetworkInterfaceExistsE indicates whether the speficied Azure Network Interface exists. +// NetworkInterfaceExistsE indicates whether the specified Azure Network Interface exists. func NetworkInterfaceExistsE(t testing.TestingT, nicName string, resGroupName string, subscriptionID string) (bool, error) { // Get the Network Interface _, err := GetNetworkInterfaceE(t, nicName, resGroupName, subscriptionID) @@ -110,7 +110,7 @@ func GetNetworkInterfaceE(t testing.TestingT, nicName string, resGroupName strin return nil, err } - // Get the client refrence + // Get the client reference client, err := GetNetworkInterfaceClientE(subscriptionID) if err != nil { return nil, err diff --git a/modules/azure/publicaddress.go b/modules/azure/publicaddress.go index 713dd68e2..89417d122 100644 --- a/modules/azure/publicaddress.go +++ b/modules/azure/publicaddress.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" ) -// PublicAddressExists indicates whether the speficied AzurePublic Address exists. +// 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) @@ -16,7 +16,7 @@ func PublicAddressExists(t testing.TestingT, publicAddressName string, resGroupN return exists } -// PublicAddressExistsE indicates whether the speficied AzurePublic Address exists. +// PublicAddressExistsE indicates whether the specified AzurePublic Address exists. func PublicAddressExistsE(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) (bool, error) { // Get the Public Address _, err := GetPublicIPAddressE(t, publicAddressName, resGroupName, subscriptionID) @@ -77,7 +77,7 @@ func GetPublicIPAddressE(t testing.TestingT, publicIPAddressName string, resGrou return nil, err } - // Get the client refrence + // Get the client reference client, err := GetPublicIPAddressClientE(subscriptionID) if err != nil { return nil, err diff --git a/modules/azure/virtualnetwork.go b/modules/azure/virtualnetwork.go index ecbb6bc87..f75304ac2 100644 --- a/modules/azure/virtualnetwork.go +++ b/modules/azure/virtualnetwork.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" ) -// VirtualNetworkExists indicates whether the speficied Azure Virtual Network exists. +// 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) @@ -17,7 +17,7 @@ func VirtualNetworkExists(t testing.TestingT, vnetName string, resGroupName stri return exists } -// VirtualNetworkExistsE indicates whether the speficied Azure Virtual Network exists. +// VirtualNetworkExistsE indicates whether the specified Azure Virtual Network exists. func VirtualNetworkExistsE(t testing.TestingT, vnetName string, resGroupName string, subscriptionID string) (bool, error) { // Get the Virtual Network _, err := GetVirtualNetworkE(t, vnetName, resGroupName, subscriptionID) @@ -27,7 +27,7 @@ func VirtualNetworkExistsE(t testing.TestingT, vnetName string, resGroupName str return true, nil } -// SubnetExists indicates whether the speficied Azure Virtual Network Subnet exists. +// 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) @@ -35,7 +35,7 @@ func SubnetExists(t testing.TestingT, subnetName string, vnetName string, resGro return exists } -// SubnetExistsE indicates whether the speficied Azure Virtual Network Subnet 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) { // Get the Subnet _, err := GetSubnetE(t, subnetName, vnetName, resGroupName, subscriptionID) @@ -139,7 +139,7 @@ func GetSubnetE(t testing.TestingT, subnetName string, vnetName string, resGroup return nil, err } - // Get the client refrence + // Get the client reference client, err := GetSubnetClientE(subscriptionID) if err != nil { return nil, err @@ -183,7 +183,7 @@ func GetVirtualNetworkE(t testing.TestingT, vnetName string, resGroupName string return nil, err } - // Get the client refrence + // Get the client reference client, err := GetVirtualNetworksClientE(subscriptionID) if err != nil { return nil, err From f51816d964ed4a444169056627bf2060ccb211bd Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Thu, 24 Sep 2020 09:49:18 -0400 Subject: [PATCH 09/20] Remove merge backups --- examples/azure/README_BACKUP_4284.md | 69 ---------------------------- examples/azure/README_BACKUP_4391.md | 69 ---------------------------- examples/azure/README_BACKUP_4481.md | 69 ---------------------------- examples/azure/README_BASE_4284.md | 0 examples/azure/README_BASE_4391.md | 0 examples/azure/README_BASE_4481.md | 0 examples/azure/README_LOCAL_4284.md | 54 ---------------------- examples/azure/README_LOCAL_4391.md | 54 ---------------------- examples/azure/README_LOCAL_4481.md | 54 ---------------------- examples/azure/README_REMOTE_4284.md | 54 ---------------------- examples/azure/README_REMOTE_4391.md | 54 ---------------------- examples/azure/README_REMOTE_4481.md | 54 ---------------------- 12 files changed, 531 deletions(-) delete mode 100644 examples/azure/README_BACKUP_4284.md delete mode 100644 examples/azure/README_BACKUP_4391.md delete mode 100644 examples/azure/README_BACKUP_4481.md delete mode 100644 examples/azure/README_BASE_4284.md delete mode 100644 examples/azure/README_BASE_4391.md delete mode 100644 examples/azure/README_BASE_4481.md delete mode 100644 examples/azure/README_LOCAL_4284.md delete mode 100644 examples/azure/README_LOCAL_4391.md delete mode 100644 examples/azure/README_LOCAL_4481.md delete mode 100644 examples/azure/README_REMOTE_4284.md delete mode 100644 examples/azure/README_REMOTE_4391.md delete mode 100644 examples/azure/README_REMOTE_4481.md diff --git a/examples/azure/README_BACKUP_4284.md b/examples/azure/README_BACKUP_4284.md deleted file mode 100644 index f10b3d663..000000000 --- a/examples/azure/README_BACKUP_4284.md +++ /dev/null @@ -1,69 +0,0 @@ -# Terratest Configuration and Setup - -<<<<<<< HEAD -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) -======= -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) ->>>>>>> 0a00d533c915f0dd2c33ef9a3b5f595dee19d74f - -## Go Dependencies - -Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH` - -These modules are currently using the latest version of Go and was tested with **go1.14.4**. - -## Azure-sdk-for-go version - -Let's make sure [go.mod](https://github.com/gruntwork-io/terratest/blob/master/go.mod) includes the appropriate [azure-sdk-for-go version](https://github.com/Azure/azure-sdk-for-go/releases/tag/v46.1.0): - -```go -require ( - ... - github.com/Azure/azure-sdk-for-go v46.1.0+incompatible - ... -) -``` - -If we make changes to either the **go.mod** or the **go test file**, we should make sure that the go build command works still. - -```powershell -go build terraform_azure_*_test.go -``` - -## Review Environment Variables - -As part of configuring terraform for Azure, we'll want to check that we have set the appropriate [credentials](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#set-up-terraform-access-to-azure) and also that we set the [environment variables](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#configure-terraform-environment-variables) on the testing host. - -```bash -export ARM_CLIENT_ID=your_app_id -export ARM_CLIENT_SECRET=your_password -export ARM_SUBSCRIPTION_ID=your_subscription_id -export ARM_TENANT_ID=your_tenant_id -``` - -<<<<<<< HEAD -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: ->>>>>>> 0a00d533c915f0dd2c33ef9a3b5f595dee19d74f - -```powershell -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID",$your_app_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_SECRET",$your_password,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_SUBSCRIPTION_ID",$your_subscription_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_TENANT_ID",$your_tenant_id,[System.EnvironmentVariableTarget]::Machine) -``` diff --git a/examples/azure/README_BACKUP_4391.md b/examples/azure/README_BACKUP_4391.md deleted file mode 100644 index f10b3d663..000000000 --- a/examples/azure/README_BACKUP_4391.md +++ /dev/null @@ -1,69 +0,0 @@ -# Terratest Configuration and Setup - -<<<<<<< HEAD -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) -======= -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) ->>>>>>> 0a00d533c915f0dd2c33ef9a3b5f595dee19d74f - -## Go Dependencies - -Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH` - -These modules are currently using the latest version of Go and was tested with **go1.14.4**. - -## Azure-sdk-for-go version - -Let's make sure [go.mod](https://github.com/gruntwork-io/terratest/blob/master/go.mod) includes the appropriate [azure-sdk-for-go version](https://github.com/Azure/azure-sdk-for-go/releases/tag/v46.1.0): - -```go -require ( - ... - github.com/Azure/azure-sdk-for-go v46.1.0+incompatible - ... -) -``` - -If we make changes to either the **go.mod** or the **go test file**, we should make sure that the go build command works still. - -```powershell -go build terraform_azure_*_test.go -``` - -## Review Environment Variables - -As part of configuring terraform for Azure, we'll want to check that we have set the appropriate [credentials](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#set-up-terraform-access-to-azure) and also that we set the [environment variables](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#configure-terraform-environment-variables) on the testing host. - -```bash -export ARM_CLIENT_ID=your_app_id -export ARM_CLIENT_SECRET=your_password -export ARM_SUBSCRIPTION_ID=your_subscription_id -export ARM_TENANT_ID=your_tenant_id -``` - -<<<<<<< HEAD -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: ->>>>>>> 0a00d533c915f0dd2c33ef9a3b5f595dee19d74f - -```powershell -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID",$your_app_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_SECRET",$your_password,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_SUBSCRIPTION_ID",$your_subscription_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_TENANT_ID",$your_tenant_id,[System.EnvironmentVariableTarget]::Machine) -``` diff --git a/examples/azure/README_BACKUP_4481.md b/examples/azure/README_BACKUP_4481.md deleted file mode 100644 index f10b3d663..000000000 --- a/examples/azure/README_BACKUP_4481.md +++ /dev/null @@ -1,69 +0,0 @@ -# Terratest Configuration and Setup - -<<<<<<< HEAD -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) -======= -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) ->>>>>>> 0a00d533c915f0dd2c33ef9a3b5f595dee19d74f - -## Go Dependencies - -Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH` - -These modules are currently using the latest version of Go and was tested with **go1.14.4**. - -## Azure-sdk-for-go version - -Let's make sure [go.mod](https://github.com/gruntwork-io/terratest/blob/master/go.mod) includes the appropriate [azure-sdk-for-go version](https://github.com/Azure/azure-sdk-for-go/releases/tag/v46.1.0): - -```go -require ( - ... - github.com/Azure/azure-sdk-for-go v46.1.0+incompatible - ... -) -``` - -If we make changes to either the **go.mod** or the **go test file**, we should make sure that the go build command works still. - -```powershell -go build terraform_azure_*_test.go -``` - -## Review Environment Variables - -As part of configuring terraform for Azure, we'll want to check that we have set the appropriate [credentials](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#set-up-terraform-access-to-azure) and also that we set the [environment variables](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#configure-terraform-environment-variables) on the testing host. - -```bash -export ARM_CLIENT_ID=your_app_id -export ARM_CLIENT_SECRET=your_password -export ARM_SUBSCRIPTION_ID=your_subscription_id -export ARM_TENANT_ID=your_tenant_id -``` - -<<<<<<< HEAD -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: ->>>>>>> 0a00d533c915f0dd2c33ef9a3b5f595dee19d74f - -```powershell -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID",$your_app_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_SECRET",$your_password,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_SUBSCRIPTION_ID",$your_subscription_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_TENANT_ID",$your_tenant_id,[System.EnvironmentVariableTarget]::Machine) -``` diff --git a/examples/azure/README_BASE_4284.md b/examples/azure/README_BASE_4284.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/examples/azure/README_BASE_4391.md b/examples/azure/README_BASE_4391.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/examples/azure/README_BASE_4481.md b/examples/azure/README_BASE_4481.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/examples/azure/README_LOCAL_4284.md b/examples/azure/README_LOCAL_4284.md deleted file mode 100644 index 42cf21ea0..000000000 --- a/examples/azure/README_LOCAL_4284.md +++ /dev/null @@ -1,54 +0,0 @@ -# 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. - -- 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) - -## Go Dependencies - -Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH` - -These modules are currently using the latest version of Go and was tested with **go1.14.4**. - -## Azure-sdk-for-go version - -Let's make sure [go.mod](https://github.com/gruntwork-io/terratest/blob/master/go.mod) includes the appropriate [azure-sdk-for-go version](https://github.com/Azure/azure-sdk-for-go/releases/tag/v46.1.0): - -```go -require ( - ... - github.com/Azure/azure-sdk-for-go v46.1.0+incompatible - ... -) -``` - -If we make changes to either the **go.mod** or the **go test file**, we should make sure that the go build command works still. - -```powershell -go build terraform_azure_*_test.go -``` - -## Review Environment Variables - -As part of configuring terraform for Azure, we'll want to check that we have set the appropriate [credentials](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#set-up-terraform-access-to-azure) and also that we set the [environment variables](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#configure-terraform-environment-variables) on the testing host. - -```bash -export ARM_CLIENT_ID=your_app_id -export ARM_CLIENT_SECRET=your_password -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: - -```powershell -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID",$your_app_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_SECRET",$your_password,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_SUBSCRIPTION_ID",$your_subscription_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_TENANT_ID",$your_tenant_id,[System.EnvironmentVariableTarget]::Machine) -``` diff --git a/examples/azure/README_LOCAL_4391.md b/examples/azure/README_LOCAL_4391.md deleted file mode 100644 index 42cf21ea0..000000000 --- a/examples/azure/README_LOCAL_4391.md +++ /dev/null @@ -1,54 +0,0 @@ -# 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. - -- 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) - -## Go Dependencies - -Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH` - -These modules are currently using the latest version of Go and was tested with **go1.14.4**. - -## Azure-sdk-for-go version - -Let's make sure [go.mod](https://github.com/gruntwork-io/terratest/blob/master/go.mod) includes the appropriate [azure-sdk-for-go version](https://github.com/Azure/azure-sdk-for-go/releases/tag/v46.1.0): - -```go -require ( - ... - github.com/Azure/azure-sdk-for-go v46.1.0+incompatible - ... -) -``` - -If we make changes to either the **go.mod** or the **go test file**, we should make sure that the go build command works still. - -```powershell -go build terraform_azure_*_test.go -``` - -## Review Environment Variables - -As part of configuring terraform for Azure, we'll want to check that we have set the appropriate [credentials](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#set-up-terraform-access-to-azure) and also that we set the [environment variables](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#configure-terraform-environment-variables) on the testing host. - -```bash -export ARM_CLIENT_ID=your_app_id -export ARM_CLIENT_SECRET=your_password -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: - -```powershell -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID",$your_app_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_SECRET",$your_password,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_SUBSCRIPTION_ID",$your_subscription_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_TENANT_ID",$your_tenant_id,[System.EnvironmentVariableTarget]::Machine) -``` diff --git a/examples/azure/README_LOCAL_4481.md b/examples/azure/README_LOCAL_4481.md deleted file mode 100644 index 42cf21ea0..000000000 --- a/examples/azure/README_LOCAL_4481.md +++ /dev/null @@ -1,54 +0,0 @@ -# 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. - -- 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) - -## Go Dependencies - -Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH` - -These modules are currently using the latest version of Go and was tested with **go1.14.4**. - -## Azure-sdk-for-go version - -Let's make sure [go.mod](https://github.com/gruntwork-io/terratest/blob/master/go.mod) includes the appropriate [azure-sdk-for-go version](https://github.com/Azure/azure-sdk-for-go/releases/tag/v46.1.0): - -```go -require ( - ... - github.com/Azure/azure-sdk-for-go v46.1.0+incompatible - ... -) -``` - -If we make changes to either the **go.mod** or the **go test file**, we should make sure that the go build command works still. - -```powershell -go build terraform_azure_*_test.go -``` - -## Review Environment Variables - -As part of configuring terraform for Azure, we'll want to check that we have set the appropriate [credentials](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#set-up-terraform-access-to-azure) and also that we set the [environment variables](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#configure-terraform-environment-variables) on the testing host. - -```bash -export ARM_CLIENT_ID=your_app_id -export ARM_CLIENT_SECRET=your_password -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: - -```powershell -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID",$your_app_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_SECRET",$your_password,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_SUBSCRIPTION_ID",$your_subscription_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_TENANT_ID",$your_tenant_id,[System.EnvironmentVariableTarget]::Machine) -``` diff --git a/examples/azure/README_REMOTE_4284.md b/examples/azure/README_REMOTE_4284.md deleted file mode 100644 index 76c1c803b..000000000 --- a/examples/azure/README_REMOTE_4284.md +++ /dev/null @@ -1,54 +0,0 @@ -# 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. - -* 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) - -## Go Dependencies - -Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH` - -These modules are currently using the latest version of Go and was tested with **go1.14.4**. - -## Azure-sdk-for-go version - -Let's make sure [go.mod](https://github.com/gruntwork-io/terratest/blob/master/go.mod) includes the appropriate [azure-sdk-for-go version](https://github.com/Azure/azure-sdk-for-go/releases/tag/v46.1.0): - -```go -require ( - ... - github.com/Azure/azure-sdk-for-go v46.1.0+incompatible - ... -) -``` - -If we make changes to either the **go.mod** or the **go test file**, we should make sure that the go build command works still. - -```powershell -go build terraform_azure_*_test.go -``` - -## Review Environment Variables - -As part of configuring terraform for Azure, we'll want to check that we have set the appropriate [credentials](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#set-up-terraform-access-to-azure) and also that we set the [environment variables](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#configure-terraform-environment-variables) on the testing host. - -```bash -export ARM_CLIENT_ID=your_app_id -export ARM_CLIENT_SECRET=your_password -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: - -```powershell -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID",$your_app_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_SECRET",$your_password,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_SUBSCRIPTION_ID",$your_subscription_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_TENANT_ID",$your_tenant_id,[System.EnvironmentVariableTarget]::Machine) -``` diff --git a/examples/azure/README_REMOTE_4391.md b/examples/azure/README_REMOTE_4391.md deleted file mode 100644 index 76c1c803b..000000000 --- a/examples/azure/README_REMOTE_4391.md +++ /dev/null @@ -1,54 +0,0 @@ -# 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. - -* 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) - -## Go Dependencies - -Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH` - -These modules are currently using the latest version of Go and was tested with **go1.14.4**. - -## Azure-sdk-for-go version - -Let's make sure [go.mod](https://github.com/gruntwork-io/terratest/blob/master/go.mod) includes the appropriate [azure-sdk-for-go version](https://github.com/Azure/azure-sdk-for-go/releases/tag/v46.1.0): - -```go -require ( - ... - github.com/Azure/azure-sdk-for-go v46.1.0+incompatible - ... -) -``` - -If we make changes to either the **go.mod** or the **go test file**, we should make sure that the go build command works still. - -```powershell -go build terraform_azure_*_test.go -``` - -## Review Environment Variables - -As part of configuring terraform for Azure, we'll want to check that we have set the appropriate [credentials](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#set-up-terraform-access-to-azure) and also that we set the [environment variables](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#configure-terraform-environment-variables) on the testing host. - -```bash -export ARM_CLIENT_ID=your_app_id -export ARM_CLIENT_SECRET=your_password -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: - -```powershell -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID",$your_app_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_SECRET",$your_password,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_SUBSCRIPTION_ID",$your_subscription_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_TENANT_ID",$your_tenant_id,[System.EnvironmentVariableTarget]::Machine) -``` diff --git a/examples/azure/README_REMOTE_4481.md b/examples/azure/README_REMOTE_4481.md deleted file mode 100644 index 76c1c803b..000000000 --- a/examples/azure/README_REMOTE_4481.md +++ /dev/null @@ -1,54 +0,0 @@ -# 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. - -* 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) - -## Go Dependencies - -Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH` - -These modules are currently using the latest version of Go and was tested with **go1.14.4**. - -## Azure-sdk-for-go version - -Let's make sure [go.mod](https://github.com/gruntwork-io/terratest/blob/master/go.mod) includes the appropriate [azure-sdk-for-go version](https://github.com/Azure/azure-sdk-for-go/releases/tag/v46.1.0): - -```go -require ( - ... - github.com/Azure/azure-sdk-for-go v46.1.0+incompatible - ... -) -``` - -If we make changes to either the **go.mod** or the **go test file**, we should make sure that the go build command works still. - -```powershell -go build terraform_azure_*_test.go -``` - -## Review Environment Variables - -As part of configuring terraform for Azure, we'll want to check that we have set the appropriate [credentials](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#set-up-terraform-access-to-azure) and also that we set the [environment variables](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#configure-terraform-environment-variables) on the testing host. - -```bash -export ARM_CLIENT_ID=your_app_id -export ARM_CLIENT_SECRET=your_password -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: - -```powershell -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID",$your_app_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_SECRET",$your_password,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_SUBSCRIPTION_ID",$your_subscription_id,[System.EnvironmentVariableTarget]::Machine) -[System.Environment]::SetEnvironmentVariable("ARM_TENANT_ID",$your_tenant_id,[System.EnvironmentVariableTarget]::Machine) -``` From b168925451f62a02d67629f4188293058b2be941 Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Thu, 24 Sep 2020 10:08:06 -0400 Subject: [PATCH 10/20] Fixed merge issues --- examples/azure/terraform-azure-network-example/main.tf | 2 +- examples/azure/terraform-azure-network-example/variables.tf | 2 +- modules/azure/errors.go | 2 ++ test/azure/terraform_azure_network_example_test.go | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/azure/terraform-azure-network-example/main.tf b/examples/azure/terraform-azure-network-example/main.tf index dbc84a8bf..38f8454cd 100644 --- a/examples/azure/terraform-azure-network-example/main.tf +++ b/examples/azure/terraform-azure-network-example/main.tf @@ -28,7 +28,7 @@ terraform { # --------------------------------------------------------------------------------------------------------------------- resource "azurerm_resource_group" "net" { - name = "terratest-net-rg-${var.postfix}" + name = "terratest-network-rg-${var.postfix}" location = var.location } diff --git a/examples/azure/terraform-azure-network-example/variables.tf b/examples/azure/terraform-azure-network-example/variables.tf index 0ed2219a7..799ec3677 100644 --- a/examples/azure/terraform-azure-network-example/variables.tf +++ b/examples/azure/terraform-azure-network-example/variables.tf @@ -44,7 +44,7 @@ variable "location" { variable "postfix" { description = "The postfix that will be attached to all resources deployed" type = string - default = "terratest-net" + default = "resource" } variable "private_ip" { diff --git a/modules/azure/errors.go b/modules/azure/errors.go index 66a2f2473..a0eae1ab7 100644 --- a/modules/azure/errors.go +++ b/modules/azure/errors.go @@ -29,6 +29,8 @@ func (err FailedToParseError) Error() string { // NewFailedToParseError creates a new not found error when an expected object is not found in the search space func NewFailedToParseError(objectType string, objectID string) FailedToParseError { return FailedToParseError{objectType, objectID} +} + // NotFoundError is returned when an expected object is not found in the search spa type NotFoundError struct { objectType string diff --git a/test/azure/terraform_azure_network_example_test.go b/test/azure/terraform_azure_network_example_test.go index 19411af17..336f880c6 100644 --- a/test/azure/terraform_azure_network_example_test.go +++ b/test/azure/terraform_azure_network_example_test.go @@ -73,7 +73,7 @@ func TestTerraformAzureNetworkExample(t *testing.T) { t.Run("NIC_PublicAddress", func(t *testing.T) { // Check the internal network interface does NOT have a public IP actualPrivateIPOnly := azure.GetNetworkInterfacePublicIPs(t, expectedPrivateNicName, expectedRgName, subscriptionID) - assert.Nil(t, actualPrivateIPOnly) + assert.True(t, len(actualPrivateIPOnly) == 0) // Check the external network interface has a public IP actualPublicIPs := azure.GetNetworkInterfacePublicIPs(t, expectedPublicNicName, expectedRgName, subscriptionID) From e0bb6d7cb7f57a98663348ee5f25cd403cd7161f Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Thu, 24 Sep 2020 12:29:27 -0400 Subject: [PATCH 11/20] Update azurerm ver syntax --- examples/azure/terraform-azure-network-example/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/azure/terraform-azure-network-example/main.tf b/examples/azure/terraform-azure-network-example/main.tf index 38f8454cd..5fbbdddf8 100644 --- a/examples/azure/terraform-azure-network-example/main.tf +++ b/examples/azure/terraform-azure-network-example/main.tf @@ -7,7 +7,7 @@ # --------------------------------------------------------------------------------------------------------------------- provider "azurerm" { - version = "=2.20.0" + version = "~>2.20" features {} } @@ -69,7 +69,7 @@ resource "azurerm_network_interface" "net01" { } # --------------------------------------------------------------------------------------------------------------------- -# DEPLOY PUBLIC IP AND NETWORK INTERFACE +# DEPLOY PUBLIC ADDRESS AND NETWORK INTERFACE # --------------------------------------------------------------------------------------------------------------------- resource "azurerm_public_ip" "net" { From 02ff075ca47bd780a94a6112bf3c516044d2aadd Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Thu, 24 Sep 2020 13:06:44 -0400 Subject: [PATCH 12/20] Minor test change --- test/azure/terraform_azure_network_example_test.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/azure/terraform_azure_network_example_test.go b/test/azure/terraform_azure_network_example_test.go index 336f880c6..3784c05f7 100644 --- a/test/azure/terraform_azure_network_example_test.go +++ b/test/azure/terraform_azure_network_example_test.go @@ -86,8 +86,8 @@ func TestTerraformAzureNetworkExample(t *testing.T) { assert.True(t, checkPrivateIpInSubnet) }) - // Tests for individual network resources - t.Run("Network", func(t *testing.T) { + // Test for resource presence + t.Run("Exists", func(t *testing.T) { // Check the Virtual Network exists assert.True(t, azure.VirtualNetworkExists(t, expectedVNetName, expectedRgName, subscriptionID)) @@ -100,7 +100,10 @@ func TestTerraformAzureNetworkExample(t *testing.T) { // Check Public Address exists assert.True(t, azure.PublicAddressExists(t, expectedPublicAddressName, expectedRgName, subscriptionID)) + }) + // Tests for useful network properties + t.Run("Network", func(t *testing.T) { // Check the Virtual Network DNS server IPs actualDNSIPs := azure.GetVirtualNetworkDNSServerIPs(t, expectedVNetName, expectedRgName, subscriptionID) assert.Contains(t, actualDNSIPs, expectedDnsIp01) From f73eedde3f246d37585cc8bf1711211ac63e84d4 Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Fri, 25 Sep 2020 12:44:01 -0400 Subject: [PATCH 13/20] Included Nic Config client reflection --- modules/azure/networkinterface.go | 107 +++++++++++++++++++----------- 1 file changed, 70 insertions(+), 37 deletions(-) diff --git a/modules/azure/networkinterface.go b/modules/azure/networkinterface.go index 541764c54..6a370730f 100644 --- a/modules/azure/networkinterface.go +++ b/modules/azure/networkinterface.go @@ -2,8 +2,7 @@ package azure import ( "context" - "encoding/json" - "strings" + "reflect" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" "github.com/gruntwork-io/terratest/modules/testing" @@ -28,6 +27,33 @@ func NetworkInterfaceExistsE(t testing.TestingT, nicName string, resGroupName st return true, nil } +// 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) + 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) { + var privateIPs []string + + // Get the Network Interface client + nic, err := GetNetworkInterfaceE(t, nicName, resGroupName, subscriptionID) + if err != nil { + return privateIPs, err + } + + // Get the Private IPs from each configuration + for _, IPConfiguration := range *nic.IPConfigurations { + privateIPs = append(privateIPs, *IPConfiguration.PrivateIPAddress) + } + + return privateIPs, nil +} + // 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 { @@ -38,7 +64,7 @@ func GetNetworkInterfacePublicIPs(t testing.TestingT, nicName string, resGroupNa // 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) { - publicIPs := []string{} + var publicIPs []string // Get the Network Interface client nic, err := GetNetworkInterfaceE(t, nicName, resGroupName, subscriptionID) @@ -48,58 +74,65 @@ func GetNetworkInterfacePublicIPsE(t testing.TestingT, nicName string, resGroupN // Get the Public IPs from each configuration available for _, IPConfiguration := range *nic.IPConfigurations { - if ipConfigHasPublicIP(&IPConfiguration) { - // Get the ID from the long string NIC representation - publicAddressID := GetNameFromResourceID(*IPConfiguration.PublicIPAddress.ID) - - // Get the Public Ip from the Public Address client - publicIP := GetPublicAddressIP(t, publicAddressID, resGroupName, subscriptionID) - publicIPs = append(publicIPs, publicIP) + // 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) + 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 err == nil { + publicIPs = append(publicIPs, publicIP) + } + } } } return publicIPs, nil } -// ipConfigHasPublicIP returns true if an IP Configuration has a Public IP Address. -// This helper method was created since a config without a public address causes a nil pointer panic -// and the string representation is searched for the publicIPAddress text to identify it's presence. -func ipConfigHasPublicIP(ipConfig *network.InterfaceIPConfiguration) bool { - var byteIPConfig []byte - - byteIPConfig, err := json.Marshal(ipConfig) +// 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) { + // Validate Azure Resource Group + resGroupName, err := getTargetAzureResourceGroupName(resGroupName) if err != nil { - return false + return nil, err } - return strings.Contains(string(byteIPConfig), "publicIPAddress") -} + // Get the client reference + client, err := GetNetworkInterfaceConfigurationClientE(subscriptionID) + if err != nil { + return nil, err + } -// 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) - require.NoError(t, err) + // Get the Network Interface + nicConfig, err := client.Get(context.Background(), resGroupName, nicName, nicConfigName) + if err != nil { + return nil, err + } - return IPs + return &nicConfig, nil } -// 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) { - privateIPs := []string{} - - // Get the Network Interface client - nic, err := GetNetworkInterfaceE(t, nicName, resGroupName, subscriptionID) +// GetNetworkInterfaceConfigurationClientE creates a new Network Interface Configuration client in the specified Azure Subscription. +func GetNetworkInterfaceConfigurationClientE(subscriptionID string) (*network.InterfaceIPConfigurationsClient, error) { + // Validate Azure Subscription ID + subscriptionID, err := getTargetAzureSubscription(subscriptionID) if err != nil { - return privateIPs, err + return nil, err } - // Get the Private IPs from each configuration - for _, IPConfiguration := range *nic.IPConfigurations { - privateIPs = append(privateIPs, *IPConfiguration.PrivateIPAddress) + // Get the NIC client + client := network.NewInterfaceIPConfigurationsClient(subscriptionID) + + // Create an authorizer + authorizer, err := NewAuthorizer() + if err != nil { + return nil, err } + client.Authorizer = *authorizer - return privateIPs, nil + return &client, nil } // GetNetworkInterfaceE gets a Network Interface in the specified Azure Resource Group. From 7419067aee7d353c6f40fdae31b86c48f7e1e3a7 Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Mon, 28 Sep 2020 16:08:59 -0400 Subject: [PATCH 14/20] Resolved comments --- modules/azure/availabilityset.go | 3 +++ modules/azure/compute.go | 1 - modules/azure/networkinterface.go | 17 ++++++++++++----- modules/azure/publicaddress.go | 15 ++++++++++----- modules/azure/virtualnetwork.go | 7 +++++++ .../terraform_azure_network_example_test.go | 19 +++++++++++-------- 6 files changed, 43 insertions(+), 19 deletions(-) diff --git a/modules/azure/availabilityset.go b/modules/azure/availabilityset.go index 15d1b1e85..9685efd2d 100644 --- a/modules/azure/availabilityset.go +++ b/modules/azure/availabilityset.go @@ -21,6 +21,9 @@ func AvailabilitySetExists(t testing.TestingT, avsName string, resGroupName stri 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") { + return false, nil + } return false, err } return true, nil diff --git a/modules/azure/compute.go b/modules/azure/compute.go index 1309887b8..270a4516b 100644 --- a/modules/azure/compute.go +++ b/modules/azure/compute.go @@ -9,7 +9,6 @@ import ( ) // GetVirtualMachineClientE is a helper function that will setup an Azure Virtual Machine client on your behalf. -// This function would fail the test if there is an error. func GetVirtualMachineClientE(subscriptionID string) (*compute.VirtualMachinesClient, error) { // Validate Azure subscription ID subscriptionID, err := getTargetAzureSubscription(subscriptionID) diff --git a/modules/azure/networkinterface.go b/modules/azure/networkinterface.go index 6a370730f..58cb67061 100644 --- a/modules/azure/networkinterface.go +++ b/modules/azure/networkinterface.go @@ -2,7 +2,7 @@ package azure import ( "context" - "reflect" + "strings" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" "github.com/gruntwork-io/terratest/modules/testing" @@ -22,11 +22,18 @@ func NetworkInterfaceExistsE(t testing.TestingT, nicName string, resGroupName st // Get the Network Interface _, err := GetNetworkInterfaceE(t, nicName, resGroupName, subscriptionID) if err != nil { + if strings.Contains(err.Error(), "ResourceNotFound") { + return false, nil + } return false, err } return true, nil } +/* func (e &network.Error) Error() string { + return fmt.Sprintf("Error code: %v", e.Code) +} */ + // 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 { @@ -75,12 +82,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. + // Not failing on errors as this is an optimistic accumulator. nicConfig, err := GetNetworkInterfaceConfigurationE(t, 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(t, publicAddressID, resGroupName, subscriptionID) if err == nil { publicIPs = append(publicIPs, publicIP) } diff --git a/modules/azure/publicaddress.go b/modules/azure/publicaddress.go index 89417d122..2aa08352e 100644 --- a/modules/azure/publicaddress.go +++ b/modules/azure/publicaddress.go @@ -2,6 +2,7 @@ package azure import ( "context" + "strings" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" "github.com/gruntwork-io/terratest/modules/testing" @@ -21,20 +22,24 @@ func PublicAddressExistsE(t testing.TestingT, publicAddressName string, resGroup // Get the Public Address _, err := GetPublicIPAddressE(t, publicAddressName, resGroupName, subscriptionID) if err != nil { + if strings.Contains(err.Error(), "ResourceNotFound") { + 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(t, 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(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) (string, error) { // Create a NIC client pip, err := GetPublicIPAddressE(t, publicAddressName, resGroupName, subscriptionID) if err != nil { diff --git a/modules/azure/virtualnetwork.go b/modules/azure/virtualnetwork.go index f75304ac2..d6175a0bb 100644 --- a/modules/azure/virtualnetwork.go +++ b/modules/azure/virtualnetwork.go @@ -3,6 +3,7 @@ package azure import ( "context" "net" + "strings" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" "github.com/gruntwork-io/terratest/modules/testing" @@ -22,6 +23,9 @@ func VirtualNetworkExistsE(t testing.TestingT, vnetName string, resGroupName str // Get the Virtual Network _, err := GetVirtualNetworkE(t, vnetName, resGroupName, subscriptionID) if err != nil { + if strings.Contains(err.Error(), "ResourceNotFound") { + return false, nil + } return false, err } return true, nil @@ -40,6 +44,9 @@ func SubnetExistsE(t testing.TestingT, subnetName string, vnetName string, resGr // Get the Subnet _, err := GetSubnetE(t, subnetName, vnetName, resGroupName, subscriptionID) if err != nil { + if strings.Contains(err.Error(), "ResourceNotFound") { + return false, nil + } return false, err } return true, nil diff --git a/test/azure/terraform_azure_network_example_test.go b/test/azure/terraform_azure_network_example_test.go index 3784c05f7..9f7ed3276 100644 --- a/test/azure/terraform_azure_network_example_test.go +++ b/test/azure/terraform_azure_network_example_test.go @@ -20,8 +20,8 @@ func TestTerraformAzureNetworkExample(t *testing.T) { t.Parallel() // Create values for Terraform - subscriptionID := "" // subscriptionID is overridden by the environment variable "ARM_SUBSCRIPTION_ID" - uniquePostfix := random.UniqueId() + subscriptionID := "" // subscriptionID is overridden by the environment variable "ARM_SUBSCRIPTION_ID" + uniquePostfix := random.UniqueId() // "resource" - switch for terratest or manual terraform deployment expectedLocation := "eastus2" expectedSubnetRange := "10.0.20.0/24" expectedPrivateIP := "10.0.20.5" @@ -34,7 +34,7 @@ func TestTerraformAzureNetworkExample(t *testing.T) { // Relative path to the Terraform dir TerraformDir: "../../examples/azure/terraform-azure-network-example", - // Variables to pass to our Terraform code using -var options + // Variables to pass to our Terraform code using -var options. Vars: map[string]interface{}{ "postfix": uniquePostfix, "subnet_prefix": expectedSubnetRange, @@ -73,11 +73,11 @@ func TestTerraformAzureNetworkExample(t *testing.T) { t.Run("NIC_PublicAddress", func(t *testing.T) { // Check the internal network interface does NOT have a public IP actualPrivateIPOnly := azure.GetNetworkInterfacePublicIPs(t, expectedPrivateNicName, expectedRgName, subscriptionID) - assert.True(t, len(actualPrivateIPOnly) == 0) + assert.Equal(t, 0, len(actualPrivateIPOnly)) // Check the external network interface has a public IP actualPublicIPs := azure.GetNetworkInterfacePublicIPs(t, expectedPublicNicName, expectedRgName, subscriptionID) - assert.True(t, len(actualPublicIPs) == 1) + assert.Equal(t, 1, len(actualPublicIPs)) }) t.Run("Subnet_NIC", func(t *testing.T) { @@ -98,6 +98,9 @@ func TestTerraformAzureNetworkExample(t *testing.T) { assert.True(t, azure.NetworkInterfaceExists(t, expectedPrivateNicName, expectedRgName, subscriptionID)) assert.True(t, azure.NetworkInterfaceExists(t, expectedPublicNicName, expectedRgName, subscriptionID)) + // Check Network Interface that does not exist in the Resource Group + assert.False(t, azure.NetworkInterfaceExists(t, "negative-test", expectedRgName, subscriptionID)) + // Check Public Address exists assert.True(t, azure.PublicAddressExists(t, expectedPublicAddressName, expectedRgName, subscriptionID)) }) @@ -113,9 +116,9 @@ func TestTerraformAzureNetworkExample(t *testing.T) { actualPrivateIPs := azure.GetNetworkInterfacePrivateIPs(t, expectedPrivateNicName, expectedRgName, subscriptionID) assert.Contains(t, actualPrivateIPs, expectedPrivateIP) - // Check the Public Address public IP is allocated - actualPublicIP := azure.GetPublicAddressIP(t, expectedPublicAddressName, expectedRgName, subscriptionID) - assert.True(t, len(actualPublicIP) > 0) + // Check the Public Address's Public IP is allocated + actualPublicIP := azure.GetIPOfPublicIPAddressByName(t, expectedPublicAddressName, expectedRgName, subscriptionID) + assert.NotEmpty(t, actualPublicIP) // Check DNS created for this example is reserved actualDnsNotAvailable := azure.CheckPublicDNSNameAvailability(t, expectedLocation, exectedDNSLabel, subscriptionID) From 9585d22211aeef5097bace0c6dd65b854fd98190 Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Mon, 28 Sep 2020 16:13:01 -0400 Subject: [PATCH 15/20] Updated module test --- modules/azure/publicaddress_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/azure/publicaddress_test.go b/modules/azure/publicaddress_test.go index 265844e0d..963cfe350 100644 --- a/modules/azure/publicaddress_test.go +++ b/modules/azure/publicaddress_test.go @@ -40,14 +40,14 @@ func TestCheckPublicDNSNameAvailabilityE(t *testing.T) { 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(t, paName, rgName, subID) require.Error(t, err) } From 4842b91ae1f4553b810666236b3ef4707e0382e1 Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Tue, 29 Sep 2020 12:20:47 -0400 Subject: [PATCH 16/20] Updated Exists error, removed unused t from E func --- modules/azure/networkinterface.go | 38 ++++++++------- modules/azure/networkinterface_test.go | 8 ++-- modules/azure/publicaddress.go | 26 ++++++----- modules/azure/publicaddress_test.go | 8 ++-- modules/azure/virtualnetwork.go | 46 ++++++++++--------- modules/azure/virtualnetwork_test.go | 14 +++--- .../terraform_azure_network_example_test.go | 3 ++ 7 files changed, 75 insertions(+), 68 deletions(-) diff --git a/modules/azure/networkinterface.go b/modules/azure/networkinterface.go index 58cb67061..5509e14da 100644 --- a/modules/azure/networkinterface.go +++ b/modules/azure/networkinterface.go @@ -2,9 +2,9 @@ package azure import ( "context" - "strings" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" + "github.com/Azure/go-autorest/autorest" "github.com/gruntwork-io/terratest/modules/testing" "github.com/stretchr/testify/require" ) @@ -12,43 +12,41 @@ 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 strings.Contains(err.Error(), "ResourceNotFound") { - return false, nil + if autorestError, ok := err.(autorest.DetailedError); ok { + if autorestError.StatusCode.(int) == 404 { + return false, nil + } } return false, err } return true, nil } -/* func (e &network.Error) Error() string { - return fmt.Sprintf("Error code: %v", e.Code) -} */ - // 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 } @@ -64,17 +62,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 } @@ -83,11 +81,11 @@ func GetNetworkInterfacePublicIPsE(t testing.TestingT, nicName string, resGroupN for _, IPConfiguration := range *nic.IPConfigurations { // Iterate each config, for successful configurations check for a Public Address reference. // Not failing on errors as this is an optimistic accumulator. - nicConfig, err := GetNetworkInterfaceConfigurationE(t, nicName, *IPConfiguration.Name, resGroupName, subscriptionID) + nicConfig, err := GetNetworkInterfaceConfigurationE(nicName, *IPConfiguration.Name, resGroupName, subscriptionID) if err == nil { if nicConfig.PublicIPAddress != nil { publicAddressID := GetNameFromResourceID(*nicConfig.PublicIPAddress.ID) - publicIP, err := GetIPOfPublicIPAddressByNameE(t, publicAddressID, resGroupName, subscriptionID) + publicIP, err := GetIPOfPublicIPAddressByNameE(publicAddressID, resGroupName, subscriptionID) if err == nil { publicIPs = append(publicIPs, publicIP) } @@ -99,7 +97,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 { @@ -143,7 +141,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 25c704b6a..f5a962258 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 2aa08352e..dcbf49c72 100644 --- a/modules/azure/publicaddress.go +++ b/modules/azure/publicaddress.go @@ -2,9 +2,9 @@ package azure import ( "context" - "strings" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" + "github.com/Azure/go-autorest/autorest" "github.com/gruntwork-io/terratest/modules/testing" "github.com/stretchr/testify/require" ) @@ -12,18 +12,20 @@ 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 strings.Contains(err.Error(), "ResourceNotFound") { - return false, nil + if autorestError, ok := err.(autorest.DetailedError); ok { + if autorestError.StatusCode.(int) == 404 { + return false, nil + } } return false, err } @@ -33,15 +35,15 @@ func PublicAddressExistsE(t testing.TestingT, publicAddressName string, resGroup // 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(t, publicAddressName, resGroupName, subscriptionID) + IP, err := GetIPOfPublicIPAddressByNameE(publicAddressName, resGroupName, subscriptionID) require.NoError(t, err) return IP } // GetIPOfPublicIPAddressByNameE gets the Public IP of the Public IP Address specified. -func GetIPOfPublicIPAddressByNameE(t testing.TestingT, publicAddressName string, resGroupName string, subscriptionID string) (string, error) { +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 } @@ -52,7 +54,7 @@ func GetIPOfPublicIPAddressByNameE(t testing.TestingT, publicAddressName string, // 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 } @@ -60,7 +62,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 @@ -75,7 +77,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 963cfe350..d37aa175e 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,7 +35,7 @@ func TestCheckPublicDNSNameAvailabilityE(t *testing.T) { domain := "" subID := "" - _, err := CheckPublicDNSNameAvailabilityE(t, location, domain, subID) + _, err := CheckPublicDNSNameAvailabilityE(location, domain, subID) require.Error(t, err) } @@ -47,7 +47,7 @@ func TestGetIPOfPublicIPAddressByNameE(t *testing.T) { rgName := "" subID := "" - _, err := GetIPOfPublicIPAddressByNameE(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 d6175a0bb..acd01766e 100644 --- a/modules/azure/virtualnetwork.go +++ b/modules/azure/virtualnetwork.go @@ -3,9 +3,9 @@ package azure import ( "context" "net" - "strings" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" + "github.com/Azure/go-autorest/autorest" "github.com/gruntwork-io/terratest/modules/testing" "github.com/stretchr/testify/require" ) @@ -13,18 +13,20 @@ 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 strings.Contains(err.Error(), "ResourceNotFound") { - return false, nil + if autorestError, ok := err.(autorest.DetailedError); ok { + if autorestError.StatusCode.(int) == 404 { + return false, nil + } } return false, err } @@ -34,18 +36,20 @@ 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 strings.Contains(err.Error(), "ResourceNotFound") { - return false, nil + if autorestError, ok := err.(autorest.DetailedError); ok { + if autorestError.StatusCode.(int) == 404 { + return false, nil + } } return false, err } @@ -55,13 +59,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 { @@ -69,7 +73,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 } @@ -89,14 +93,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) @@ -121,16 +125,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 } @@ -139,7 +143,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 { @@ -183,7 +187,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 2c22d4071..988e8acd3 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/test/azure/terraform_azure_network_example_test.go b/test/azure/terraform_azure_network_example_test.go index 9f7ed3276..9406bd3c4 100644 --- a/test/azure/terraform_azure_network_example_test.go +++ b/test/azure/terraform_azure_network_example_test.go @@ -101,6 +101,9 @@ func TestTerraformAzureNetworkExample(t *testing.T) { // Check Network Interface that does not exist in the Resource Group assert.False(t, azure.NetworkInterfaceExists(t, "negative-test", expectedRgName, subscriptionID)) + // Check Network Interface that does not exist in the Resource Group + assert.False(t, azure.NetworkInterfaceExists(t, "negative-test", "expectedRgName", subscriptionID)) + // Check Public Address exists assert.True(t, azure.PublicAddressExists(t, expectedPublicAddressName, expectedRgName, subscriptionID)) }) From c0a86ccdd44f73c97e4927e6c87d886f42c3e95a Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Tue, 29 Sep 2020 16:07:50 -0400 Subject: [PATCH 17/20] Updated error check --- modules/azure/availabilityset.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/azure/availabilityset.go b/modules/azure/availabilityset.go index 9685efd2d..f8868ad95 100644 --- a/modules/azure/availabilityset.go +++ b/modules/azure/availabilityset.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute" + "github.com/Azure/go-autorest/autorest" "github.com/gruntwork-io/terratest/modules/testing" "github.com/stretchr/testify/require" ) @@ -21,8 +22,10 @@ func AvailabilitySetExists(t testing.TestingT, avsName string, resGroupName stri 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") { - return false, nil + if autorestError, ok := err.(autorest.DetailedError); ok { + if autorestError.StatusCode.(int) == 404 { + return false, nil + } } return false, err } From cf75fb9167670547317ee9c12fd3bb2be01c892e Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Tue, 29 Sep 2020 22:42:20 -0400 Subject: [PATCH 18/20] Handled specific response error --- modules/azure/availabilityset.go | 7 ++----- modules/azure/errors.go | 21 ++++++++++++++++++- modules/azure/networkinterface.go | 7 ++----- modules/azure/publicaddress.go | 7 ++----- modules/azure/virtualnetwork.go | 13 ++++-------- .../terraform_azure_network_example_test.go | 3 --- 6 files changed, 30 insertions(+), 28 deletions(-) diff --git a/modules/azure/availabilityset.go b/modules/azure/availabilityset.go index f8868ad95..2b20baf9f 100644 --- a/modules/azure/availabilityset.go +++ b/modules/azure/availabilityset.go @@ -5,7 +5,6 @@ import ( "strings" "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute" - "github.com/Azure/go-autorest/autorest" "github.com/gruntwork-io/terratest/modules/testing" "github.com/stretchr/testify/require" ) @@ -22,10 +21,8 @@ func AvailabilitySetExists(t testing.TestingT, avsName string, resGroupName stri func AvailabilitySetExistsE(t testing.TestingT, avsName string, resGroupName string, subscriptionID string) (bool, error) { _, err := GetAvailabilitySetE(t, avsName, resGroupName, subscriptionID) if err != nil { - if autorestError, ok := err.(autorest.DetailedError); ok { - if autorestError.StatusCode.(int) == 404 { - return false, nil - } + if ResourceNotFoundError(err) { + return false, nil } return false, err } diff --git a/modules/azure/errors.go b/modules/azure/errors.go index a0eae1ab7..3105d4547 100644 --- a/modules/azure/errors.go +++ b/modules/azure/errors.go @@ -1,6 +1,11 @@ package azure -import "fmt" +import ( + "fmt" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) // SubscriptionIDNotFound is an error that occurs when the Azure Subscription ID could not be found or was not provided type SubscriptionIDNotFound struct{} @@ -46,3 +51,17 @@ func (err NotFoundError) Error() string { func NewNotFoundError(objectType string, objectID string, region string) NotFoundError { return NotFoundError{objectType, objectID, region} } + +// ResourceNotFoundError gets the Service Error Code from a Autorest err +func ResourceNotFoundError(err error) bool { + if err != nil { + if autorestError, ok := err.(autorest.DetailedError); ok { + if requestError, ok := autorestError.Original.(*azure.RequestError); ok { + if requestError.ServiceError.Code == "ResourceNotFound" { + return true + } + } + } + } + return false +} diff --git a/modules/azure/networkinterface.go b/modules/azure/networkinterface.go index 5509e14da..d18a5e8d7 100644 --- a/modules/azure/networkinterface.go +++ b/modules/azure/networkinterface.go @@ -4,7 +4,6 @@ import ( "context" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" - "github.com/Azure/go-autorest/autorest" "github.com/gruntwork-io/terratest/modules/testing" "github.com/stretchr/testify/require" ) @@ -22,10 +21,8 @@ func NetworkInterfaceExistsE(nicName string, resGroupName string, subscriptionID // Get the Network Interface _, err := GetNetworkInterfaceE(nicName, resGroupName, subscriptionID) if err != nil { - if autorestError, ok := err.(autorest.DetailedError); ok { - if autorestError.StatusCode.(int) == 404 { - return false, nil - } + if ResourceNotFoundError(err) { + return false, nil } return false, err } diff --git a/modules/azure/publicaddress.go b/modules/azure/publicaddress.go index dcbf49c72..0e84ed120 100644 --- a/modules/azure/publicaddress.go +++ b/modules/azure/publicaddress.go @@ -4,7 +4,6 @@ import ( "context" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" - "github.com/Azure/go-autorest/autorest" "github.com/gruntwork-io/terratest/modules/testing" "github.com/stretchr/testify/require" ) @@ -22,10 +21,8 @@ func PublicAddressExistsE(publicAddressName string, resGroupName string, subscri // Get the Public Address _, err := GetPublicIPAddressE(publicAddressName, resGroupName, subscriptionID) if err != nil { - if autorestError, ok := err.(autorest.DetailedError); ok { - if autorestError.StatusCode.(int) == 404 { - return false, nil - } + if ResourceNotFoundError(err) { + return false, nil } return false, err } diff --git a/modules/azure/virtualnetwork.go b/modules/azure/virtualnetwork.go index acd01766e..bf4bbce18 100644 --- a/modules/azure/virtualnetwork.go +++ b/modules/azure/virtualnetwork.go @@ -5,7 +5,6 @@ import ( "net" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" - "github.com/Azure/go-autorest/autorest" "github.com/gruntwork-io/terratest/modules/testing" "github.com/stretchr/testify/require" ) @@ -23,10 +22,8 @@ func VirtualNetworkExistsE(vnetName string, resGroupName string, subscriptionID // Get the Virtual Network _, err := GetVirtualNetworkE(vnetName, resGroupName, subscriptionID) if err != nil { - if autorestError, ok := err.(autorest.DetailedError); ok { - if autorestError.StatusCode.(int) == 404 { - return false, nil - } + if ResourceNotFoundError(err) { + return false, nil } return false, err } @@ -46,10 +43,8 @@ func SubnetExistsE(subnetName string, vnetName string, resGroupName string, subs // Get the Subnet _, err := GetSubnetE(subnetName, vnetName, resGroupName, subscriptionID) if err != nil { - if autorestError, ok := err.(autorest.DetailedError); ok { - if autorestError.StatusCode.(int) == 404 { - return false, nil - } + if ResourceNotFoundError(err) { + return false, nil } return false, err } diff --git a/test/azure/terraform_azure_network_example_test.go b/test/azure/terraform_azure_network_example_test.go index 9406bd3c4..9f7ed3276 100644 --- a/test/azure/terraform_azure_network_example_test.go +++ b/test/azure/terraform_azure_network_example_test.go @@ -101,9 +101,6 @@ func TestTerraformAzureNetworkExample(t *testing.T) { // Check Network Interface that does not exist in the Resource Group assert.False(t, azure.NetworkInterfaceExists(t, "negative-test", expectedRgName, subscriptionID)) - // Check Network Interface that does not exist in the Resource Group - assert.False(t, azure.NetworkInterfaceExists(t, "negative-test", "expectedRgName", subscriptionID)) - // Check Public Address exists assert.True(t, azure.PublicAddressExists(t, expectedPublicAddressName, expectedRgName, subscriptionID)) }) From 876a03aa6adf78c863d0864a73a62434cb9fce25 Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Tue, 29 Sep 2020 23:10:26 -0400 Subject: [PATCH 19/20] Shortened error check logic --- modules/azure/errors.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/azure/errors.go b/modules/azure/errors.go index 3105d4547..825bd3da3 100644 --- a/modules/azure/errors.go +++ b/modules/azure/errors.go @@ -57,9 +57,7 @@ func ResourceNotFoundError(err error) bool { if err != nil { if autorestError, ok := err.(autorest.DetailedError); ok { if requestError, ok := autorestError.Original.(*azure.RequestError); ok { - if requestError.ServiceError.Code == "ResourceNotFound" { - return true - } + return (requestError.ServiceError.Code == "ResourceNotFound") } } } From 7226a3d142477b74eb60729a4159e4ddc7358261 Mon Sep 17 00:00:00 2001 From: Dave Seepersad <“davesee@microsoft.com”> Date: Tue, 29 Sep 2020 23:19:08 -0400 Subject: [PATCH 20/20] Updated error comment and name --- modules/azure/availabilityset.go | 2 +- modules/azure/errors.go | 4 ++-- modules/azure/networkinterface.go | 2 +- modules/azure/publicaddress.go | 2 +- modules/azure/virtualnetwork.go | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/azure/availabilityset.go b/modules/azure/availabilityset.go index 2b20baf9f..6c50da747 100644 --- a/modules/azure/availabilityset.go +++ b/modules/azure/availabilityset.go @@ -21,7 +21,7 @@ func AvailabilitySetExists(t testing.TestingT, avsName string, resGroupName stri func AvailabilitySetExistsE(t testing.TestingT, avsName string, resGroupName string, subscriptionID string) (bool, error) { _, err := GetAvailabilitySetE(t, avsName, resGroupName, subscriptionID) if err != nil { - if ResourceNotFoundError(err) { + if ResourceNotFoundErrorExists(err) { return false, nil } return false, err diff --git a/modules/azure/errors.go b/modules/azure/errors.go index 825bd3da3..36d74454d 100644 --- a/modules/azure/errors.go +++ b/modules/azure/errors.go @@ -52,8 +52,8 @@ func NewNotFoundError(objectType string, objectID string, region string) NotFoun return NotFoundError{objectType, objectID, region} } -// ResourceNotFoundError gets the Service Error Code from a Autorest err -func ResourceNotFoundError(err error) bool { +// ResourceNotFoundErrorExists checks the Service Error Code for the 'Resource Not Found' error +func ResourceNotFoundErrorExists(err error) bool { if err != nil { if autorestError, ok := err.(autorest.DetailedError); ok { if requestError, ok := autorestError.Original.(*azure.RequestError); ok { diff --git a/modules/azure/networkinterface.go b/modules/azure/networkinterface.go index d18a5e8d7..14c6de0d0 100644 --- a/modules/azure/networkinterface.go +++ b/modules/azure/networkinterface.go @@ -21,7 +21,7 @@ func NetworkInterfaceExistsE(nicName string, resGroupName string, subscriptionID // Get the Network Interface _, err := GetNetworkInterfaceE(nicName, resGroupName, subscriptionID) if err != nil { - if ResourceNotFoundError(err) { + if ResourceNotFoundErrorExists(err) { return false, nil } return false, err diff --git a/modules/azure/publicaddress.go b/modules/azure/publicaddress.go index 0e84ed120..28eea1cf6 100644 --- a/modules/azure/publicaddress.go +++ b/modules/azure/publicaddress.go @@ -21,7 +21,7 @@ func PublicAddressExistsE(publicAddressName string, resGroupName string, subscri // Get the Public Address _, err := GetPublicIPAddressE(publicAddressName, resGroupName, subscriptionID) if err != nil { - if ResourceNotFoundError(err) { + if ResourceNotFoundErrorExists(err) { return false, nil } return false, err diff --git a/modules/azure/virtualnetwork.go b/modules/azure/virtualnetwork.go index bf4bbce18..c810b0fc4 100644 --- a/modules/azure/virtualnetwork.go +++ b/modules/azure/virtualnetwork.go @@ -22,7 +22,7 @@ func VirtualNetworkExistsE(vnetName string, resGroupName string, subscriptionID // Get the Virtual Network _, err := GetVirtualNetworkE(vnetName, resGroupName, subscriptionID) if err != nil { - if ResourceNotFoundError(err) { + if ResourceNotFoundErrorExists(err) { return false, nil } return false, err @@ -43,7 +43,7 @@ func SubnetExistsE(subnetName string, vnetName string, resGroupName string, subs // Get the Subnet _, err := GetSubnetE(subnetName, vnetName, resGroupName, subscriptionID) if err != nil { - if ResourceNotFoundError(err) { + if ResourceNotFoundErrorExists(err) { return false, nil } return false, err