Azure Terraform Getting Started
Hello guys, here I shall show you some examples of Azure configuration with Terraform, because there are a lot information out there and sometimes is kind of crazy a lot of them with a lot of kinds of configuration that there is no start point for a beginner that why I will try to show the basic until the advanced. I will try to write as much as possible in my free time. So let's get started with Azure and Terraform.
My Terraform configuration if you want to reproduce the configurations below.
terraform --version 191ms Sat Apr 4 12:22:01 2020 Terraform v0.12.24 + provider.azurerm v1.44.0
Defining the Provider Azurerm
When we start to work with Terraform and Azure we need to define the provider and there a lot of options we can use here, following the link about the provider documentation take a look: Azure Provider
As we can use the code showed below in a team or another kind of sharing I will approach the configuration via environment variables that I think is the most secure for the how to. If you don't have idea how to set up the SPN for your azure account you can take a look at the following link: Configuring Azure SPN for Terraform
Now we need to configure the environment variables for our project.
The Subscription ID which should be used. This can also be sourced from the ARM_SUBSCRIPTION_ID Environment Variable.
export ARM_SUBSCRIPTION_ID="xxxxxxxx-xxxx-xxxx-xxxx-62f9d45b6957"
The Client ID which should be used. This can also be sourced from the ARM_CLIENT_ID Environment Variable.
export ARM_CLIENT_ID="xxxxxxxx-xxxx-xxxx-xxxx-e684b975d113"
The Client Secret which should be used. This can also be sourced from the ARM_CLIENT_SECRET Environment Variable.
export ARM_CLIENT_SECRET="8Z:s.?3pa@2zjuM4Y-JEoUdlj@w9SXfb"
The Tenant ID which should be used. This can also be sourced from the ARM_TENANT_ID Environment Variable.
export ARM_TENANT_ID="xxxxxxxx-xxxx-xxxx-xxxx-9c8a75bbff3e"
Creating a Resource Group
Now let's create our first resource group, try to make all the resources group by it, so if your configuration grows and you need to remove or change it, it'll be a lot easer than try to figure out what's going on.
Let's create a directory to hold all the configuration about our project.
mkdir terraform-azure
Now let's access it
cd terraform-azure
Now let's create our first resource group
vim main.tf # Provider # https://www.terraform.io/docs/providers/azurerm/index.html provider "azurerm" { # With Terraform 12 we need to stick with 1.27 version = "~> 1.27" # The Subscription ID which should be used. This can also be sourced from the ARM_SUBSCRIPTION_ID Environment Variable. # subscription_id = "${var.subscription_id}" # The Client ID which should be used. This can also be sourced from the ARM_CLIENT_ID Environment Variable. # client_id = "${var.client_id}" # The Client Secret which should be used. This can also be sourced from the ARM_CLIENT_SECRET Environment Variable. # client_secret = "${var.client_secret}" # The Tenant ID which should be used. This can also be sourced from the ARM_TENANT_ID Environment Variable. # tenant_id = "${var.tenant_id}" } # Manages a Resource Group. # https://www.terraform.io/docs/providers/azurerm/r/resource_group.html resource "azurerm_resource_group" "web_server_rg" { # The Name which should be used for this Resource Group. name = "web-rg" # The Azure Region where the Resource Group should exist. location = "westus2" }
Now we need to init the terraform
terraform init 4089ms Sat Apr 4 08:38:21 2020 Initializing the backend... Initializing provider plugins... - Checking for available provider plugins... - Downloading plugin for provider "azurerm" (hashicorp/azurerm) 1.44.0... Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.
Now we can run the terraform plan to take a look what will happen if we apply the configuration
terraform plan Sat Apr 4 08:55:43 2020 Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. ------------------------------------------------------------------------ An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_resource_group.web_server_rg will be created + resource "azurerm_resource_group" "web_server_rg" { + id = (known after apply) + location = "westus2" + name = "web-rg" + tags = (known after apply) } Plan: 1 to add, 0 to change, 0 to destroy. ------------------------------------------------------------------------ Note: You didn't specify an "-out" parameter to save this plan, so Terraform can't guarantee that exactly these actions will be performed if "terraform apply" is subsequently run.
As we can see the terraform plan didn't throw any errors, now we can apply the configuration
terraform apply 7.4s Sat Apr 4 08:56:05 2020 An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_resource_group.web_server_rg will be created + resource "azurerm_resource_group" "web_server_rg" { + id = (known after apply) + location = "westus2" + name = "web-rg" + tags = (known after apply) } Plan: 1 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes azurerm_resource_group.web_server_rg: Creating... azurerm_resource_group.web_server_rg: Creation complete after 7s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg] Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Now we can check if there is a new resource group into Azure Portal or we can check in the command line
az group list 23.7s Sat Apr 4 08:58:48 2020 [ { "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg", "location": "westus2", "managedBy": null, "name": "web-rg", "properties": { "provisioningState": "Succeeded" }, "tags": {}, "type": "Microsoft.Resources/resourceGroups" } ]
As we can see there is a new resource group create by Terraform. Now let's destroy it to continue the configuration.
terraform destroy 2229ms Sat Apr 4 09:00:32 2020 azurerm_resource_group.web_server_rg: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg] An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: - destroy Terraform will perform the following actions: # azurerm_resource_group.web_server_rg will be destroyed - resource "azurerm_resource_group" "web_server_rg" { - id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg" -> null - location = "westus2" -> null - name = "web-rg" -> null - tags = {} -> null } Plan: 0 to add, 0 to change, 1 to destroy. Do you really want to destroy all resources? Terraform will destroy all your managed infrastructure, as shown above. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes azurerm_resource_group.web_server_rg: Destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 10s elapsed] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 20s elapsed] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 30s elapsed] azurerm_resource_group.web_server_rg: Destruction complete after 39s Destroy complete! Resources: 1 destroyed.
Now let's make sure that there is no resource group named web-rg
az group show --name web-rg 1971ms Sat Apr 4 09:05:12 2020 Resource group 'web-rg' could not be found.
Let's list all the resource groups
az group list 58.4s Sat Apr 4 09:04:17 2020 []
Resources:
Terraform Basic Variables
Variables:
- main.tf
- Variable Files “terraform.tfvars or *.auto.tfvars”
- Environment
- Precedence - Command passed, environment & defaults
Example of using a tfvars file and command passed variable
terraform apply -var-file "var.tfvars" -var "server=web"
Let's create a file with some variables to take a look how to handle them
vim variables.tf variable "server_name" { default = "web-server" } variable "locations" { type = map default = { location1 = "westus2" location2 = "westeurope" } } variable "subnets" { type = list default = ["10.0.1.10","10.0.1.11"] } variable "live" { type = string default = false }
Now we can access the terraform console
terraform console 1.8m Sat Apr 4 09:19:28 2020 >
Now lets get the name of server name inside the terraform console
> var.server_name web-server
As we could see the form to get the information of a string is var.variable_name just that simple.
Let's take a look how to get information about a map
> var.locations { "location1" = "westus2" "location2" = "westeurope" }
As we can see we have the information about the map and two values location1 and location2, to get the information about only location1 we can do
var.locations["location1"] westus2
Let's take a look how to get information about a list
> var.subnets [ "10.0.1.10", "10.0.1.11", ]
As we can see we have the information about the list and two values 10.0.1.10 and 10.0.1.11, to get the information about only first id of the list we can do
> var.subnets[0] 10.0.1.10
We can take a look of Terraform Variables in the following link: Input Variables
Azure Locations
We can get the global infrastructure from the following link: Azure locations
But usually we need to get it from the Azure CLI so.
Let's log in
az login --service-principal -u $ARM_CLIENT_ID -p $ARM_CLIENT_SECRET -t $ARM_TENANT_ID
Now we can get the locations
az account list-locations -o table Sat Apr 4 08:19:38 2020 DisplayName Latitude Longitude Name -------------------- ---------- ----------- ------------------ East Asia 22.267 114.188 eastasia Southeast Asia 1.283 103.833 southeastasia Central US 41.5908 -93.6208 centralus East US 37.3719 -79.8164 eastus East US 2 36.6681 -78.3889 eastus2 West US 37.783 -122.417 westus North Central US 41.8819 -87.6278 northcentralus South Central US 29.4167 -98.5 southcentralus North Europe 53.3478 -6.2597 northeurope West Europe 52.3667 4.9 westeurope Japan West 34.6939 135.5022 japanwest Japan East 35.68 139.77 japaneast Brazil South -23.55 -46.633 brazilsouth Australia East -33.86 151.2094 australiaeast Australia Southeast -37.8136 144.9631 australiasoutheast South India 12.9822 80.1636 southindia Central India 18.5822 73.9197 centralindia West India 19.088 72.868 westindia Canada Central 43.653 -79.383 canadacentral Canada East 46.817 -71.217 canadaeast UK South 50.941 -0.799 uksouth UK West 53.427 -3.084 ukwest West Central US 40.890 -110.234 westcentralus West US 2 47.233 -119.852 westus2 Korea Central 37.5665 126.9780 koreacentral Korea South 35.1796 129.0756 koreasouth France Central 46.3772 2.3730 francecentral France South 43.8345 2.1972 francesouth Australia Central -35.3075 149.1244 australiacentral Australia Central 2 -35.3075 149.1244 australiacentral2 UAE Central 24.466667 54.366669 uaecentral UAE North 25.266666 55.316666 uaenorth South Africa North -25.731340 28.218370 southafricanorth South Africa West -34.075691 18.843266 southafricawest Switzerland North 47.451542 8.564572 switzerlandnorth Switzerland West 46.204391 6.143158 switzerlandwest Germany North 53.073635 8.806422 germanynorth Germany West Central 50.110924 8.682127 germanywestcentral Norway West 58.969975 5.733107 norwaywest Norway East 59.913868 10.752245 norwayeast
Refactoring the Resource Group
Let's create the resource group using variables
Now let's create the file that will hold the variables
vim terraform.tfvars # Define the Web server Location web_server_location = "westus2" # Define the Web Server Resource Group Name web_server_rg = "web-rg"
Note: A .tfvars file is used to assign values to variables that have already been declared in .tf files, not to declare new variables.
Now let's refactor the main.tf to use the variables
vim main.tf ## Defining the Variables variable "web_server_location" {} variable "web_server_rg" {} # Provider # https://www.terraform.io/docs/providers/azurerm/index.html provider "azurerm" { # With Terraform 12 we need to stick with 1.27 version = "~> 1.27" # The Subscription ID which should be used. This can also be sourced from the ARM_SUBSCRIPTION_ID Environment Variable. # subscription_id = "${var.subscription_id}" # The Client ID which should be used. This can also be sourced from the ARM_CLIENT_ID Environment Variable. # client_id = "${var.client_id}" # The Client Secret which should be used. This can also be sourced from the ARM_CLIENT_SECRET Environment Variable. # client_secret = "${var.client_secret}" # The Tenant ID which should be used. This can also be sourced from the ARM_TENANT_ID Environment Variable. # tenant_id = "${var.tenant_id}" } # Manages a Resource Group. # https://www.terraform.io/docs/providers/azurerm/r/resource_group.html resource "azurerm_resource_group" "web_server_rg" { # The Name which should be used for this Resource Group. # Here we'll use the variable web_server_rg that was declared into terraform.tfvars name = var.web_server_rg # The Azure Region where the Resource Group should exist. # Here we'll use the variable web_server_location that was declared into terraform.tfvars location = var.web_server_location }
Now we can run the terraform plan to take a look what will happen if we apply the configuration
terraform plan 238ms Sat Apr 4 09:44:02 2020 Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. ------------------------------------------------------------------------ An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_resource_group.web_server_rg will be created + resource "azurerm_resource_group" "web_server_rg" { + id = (known after apply) + location = "westus2" + name = "web-rg" + tags = (known after apply) } Plan: 1 to add, 0 to change, 0 to destroy. ------------------------------------------------------------------------ Note: You didn't specify an "-out" parameter to save this plan, so Terraform can't guarantee that exactly these actions will be performed if "terraform apply" is subsequently run.
As we can see the terraform plan didn't throw any errors, and we have the same configuration as before, now we can apply the configuration
terraform apply 7.5s Sat Apr 4 09:44:20 2020 An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_resource_group.web_server_rg will be created + resource "azurerm_resource_group" "web_server_rg" { + id = (known after apply) + location = "westus2" + name = "web-rg" + tags = (known after apply) } Plan: 1 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes azurerm_resource_group.web_server_rg: Creating... azurerm_resource_group.web_server_rg: Creation complete after 7s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg] Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Now we can check if there is a new resource group into Azure Portal or we can check in the command line
az group list 27.8s Sat Apr 4 09:46:13 2020 [ { "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg", "location": "westus2", "managedBy": null, "name": "web-rg", "properties": { "provisioningState": "Succeeded" }, "tags": {}, "type": "Microsoft.Resources/resourceGroups" } ]
As we can see there is a new resource group create by Terraform. Now let's destroy it to continue the configuration.
terraform destroy 3338ms Sat Apr 4 09:46:17 2020 azurerm_resource_group.web_server_rg: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg] An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: - destroy Terraform will perform the following actions: # azurerm_resource_group.web_server_rg will be destroyed - resource "azurerm_resource_group" "web_server_rg" { - id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg" -> null - location = "westus2" -> null - name = "web-rg" -> null - tags = {} -> null } Plan: 0 to add, 0 to change, 1 to destroy. Do you really want to destroy all resources? Terraform will destroy all your managed infrastructure, as shown above. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes azurerm_resource_group.web_server_rg: Destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 10s elapsed] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 20s elapsed] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 30s elapsed] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 40s elapsed] azurerm_resource_group.web_server_rg: Destruction complete after 42s Destroy complete! Resources: 1 destroyed.
Now let's make sure that there is no resource group named web-rg
az group show --name web-rg 1.2m Sat Apr 4 09:48:24 2020 Resource group 'web-rg' could not be found.
Let's list all the resource groups
az group list 2396ms Sat Apr 4 09:48:26 2020 []
Resources:
Terraform with Azure VNET
Azure VNET:
- Virtual Network
- Logical isolated network
- Address space
- Subnets
- Connectivity - VNET, VPN, Endpoints
- NSG
Let's update the file that will hold the variables with the new variables for the VNET
vim terraform.tfvars # Define the Web server Location web_server_location = "westus2" # Define the Web Server Resource Group Name web_server_rg = "web-rg" # Resource Prefix resource_prefix = "web-server" # Address Space web_server_address_space = "10.0.0.0/22"
Note: A .tfvars file is used to assign values to variables that have already been declared in .tf files, not to declare new variables.
Let's Edit the main.tf to use add the new resource called azurerm_virtual_network
vim main.tf ## Defining the Variables variable "web_server_location" {} variable "web_server_rg" {} variable "resource_prefix" {} variable "web_server_address_space" {} # Provider # https://www.terraform.io/docs/providers/azurerm/index.html provider "azurerm" { # With Terraform 12 we need to stick with 1.27 version = "~> 1.27" # The Subscription ID which should be used. This can also be sourced from the ARM_SUBSCRIPTION_ID Environment Variable. # subscription_id = "${var.subscription_id}" # The Client ID which should be used. This can also be sourced from the ARM_CLIENT_ID Environment Variable. # client_id = "${var.client_id}" # The Client Secret which should be used. This can also be sourced from the ARM_CLIENT_SECRET Environment Variable. # client_secret = "${var.client_secret}" # The Tenant ID which should be used. This can also be sourced from the ARM_TENANT_ID Environment Variable. # tenant_id = "${var.tenant_id}" } # Manages a Resource Group. # https://www.terraform.io/docs/providers/azurerm/r/resource_group.html resource "azurerm_resource_group" "web_server_rg" { # The Name which should be used for this Resource Group. # Here we'll use the variable web_server_rg that was declared into terraform.tfvars name = var.web_server_rg # The Azure Region where the Resource Group should exist. # Here we'll use the variable web_server_location that was declared into terraform.tfvars location = var.web_server_location } # Manages a virtual network including any configured subnets. # Each subnet can optionally be configured with a security group to be associated with the subnet. # https://www.terraform.io/docs/providers/azurerm/r/virtual_network.html resource "azurerm_virtual_network" "web_server_vnet" { # (Required) The name of the virtual network. Changing this forces a new resource to be created. # Note: here as we need to interpolate the variable with some kind of string we need to use "${}-string" inside quotes name = "${var.resource_prefix}-vnet" # (Required) The location/region where the virtual network is created. Changing this forces a new resource to be created. location = var.web_server_location # (Required) The name of the resource group in which to create the virtual network. resource_group_name = azurerm_resource_group.web_server_rg.name # (Required) The address space that is used the virtual network. You can supply more than one address space. Changing this forces a new resource to be created. address_space = [var.web_server_address_space] }
Now we can run the terraform plan to take a look what will happen if we apply the configuration
terraform plan 9.2s Sat Apr 4 10:12:00 2020 Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. ------------------------------------------------------------------------ An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_resource_group.web_server_rg will be created + resource "azurerm_resource_group" "web_server_rg" { + id = (known after apply) + location = "westus2" + name = "web-rg" + tags = (known after apply) } # azurerm_virtual_network.web_server_vnet will be created + resource "azurerm_virtual_network" "web_server_vnet" { + address_space = [ + "10.0.0.0/22", ] + id = (known after apply) + location = "westus2" + name = "web-server-vnet" + resource_group_name = "web-rg" + tags = (known after apply) + subnet { + address_prefix = (known after apply) + id = (known after apply) + name = (known after apply) + security_group = (known after apply) } } Plan: 2 to add, 0 to change, 0 to destroy. ------------------------------------------------------------------------ Note: You didn't specify an "-out" parameter to save this plan, so Terraform can't guarantee that exactly these actions will be performed if "terraform apply" is subsequently run.
As we can see the terraform plan didn't throw any errors, now we can apply the configuration
terraform apply 2674ms Sat Apr 4 10:18:15 2020 An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_resource_group.web_server_rg will be created + resource "azurerm_resource_group" "web_server_rg" { + id = (known after apply) + location = "westus2" + name = "web-rg" + tags = (known after apply) } # azurerm_virtual_network.web_server_vnet will be created + resource "azurerm_virtual_network" "web_server_vnet" { + address_space = [ + "10.0.0.0/22", ] + id = (known after apply) + location = "westus2" + name = "web-server-vnet" + resource_group_name = "web-rg" + tags = (known after apply) + subnet { + address_prefix = (known after apply) + id = (known after apply) + name = (known after apply) + security_group = (known after apply) } } Plan: 2 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes azurerm_resource_group.web_server_rg: Creating... azurerm_resource_group.web_server_rg: Creation complete after 8s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg] azurerm_virtual_network.web_server_vnet: Creating... azurerm_virtual_network.web_server_vnet: Still creating... [10s elapsed] azurerm_virtual_network.web_server_vnet: Creation complete after 14s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet] Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Now we can check if there is a new resource group into Azure Portal or we can check in the command line
az group list 38.2s Sat Apr 4 10:23:07 2020 [ { "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg", "location": "westus2", "managedBy": null, "name": "web-rg", "properties": { "provisioningState": "Succeeded" }, "tags": {}, "type": "Microsoft.Resources/resourceGroups" }, { "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/NetworkWatcherRG", "location": "westus2", "managedBy": null, "name": "NetworkWatcherRG", "properties": { "provisioningState": "Succeeded" }, "tags": null, "type": "Microsoft.Resources/resourceGroups" } ]
Now let's list the VNET
az network vnet list 2261ms Sat Apr 4 10:23:15 2020 [ { "addressSpace": { "addressPrefixes": [ "10.0.0.0/22" ] }, "bgpCommunities": null, "ddosProtectionPlan": null, "dhcpOptions": { "dnsServers": [] }, "enableDdosProtection": false, "enableVmProtection": false, "etag": "W/\"5d2178ea-d82a-438e-81fc-658424826beb\"", "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet", "location": "westus2", "name": "web-server-vnet", "provisioningState": "Succeeded", "resourceGroup": "web-rg", "resourceGuid": "00e0ddcd-1a88-4395-8a1c-980c6bec4bdb", "subnets": [], "tags": {}, "type": "Microsoft.Network/virtualNetworks", "virtualNetworkPeerings": [] } ]
As we can see there is a new resource group create by Terraform. Now let's destroy it to continue the configuration.
terraform destroy 2882ms Sat Apr 4 10:26:53 2020 azurerm_resource_group.web_server_rg: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg] azurerm_virtual_network.web_server_vnet: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet] An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: - destroy Terraform will perform the following actions: # azurerm_resource_group.web_server_rg will be destroyed - resource "azurerm_resource_group" "web_server_rg" { - id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg" -> null - location = "westus2" -> null - name = "web-rg" -> null - tags = {} -> null } # azurerm_virtual_network.web_server_vnet will be destroyed - resource "azurerm_virtual_network" "web_server_vnet" { - address_space = [ - "10.0.0.0/22", ] -> null - dns_servers = [] -> null - id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet" -> null - location = "westus2" -> null - name = "web-server-vnet" -> null - resource_group_name = "web-rg" -> null - tags = {} -> null } Plan: 0 to add, 0 to change, 2 to destroy. Do you really want to destroy all resources? Terraform will destroy all your managed infrastructure, as shown above. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes azurerm_virtual_network.web_server_vnet: Destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet] azurerm_virtual_network.web_server_vnet: Destruction complete after 2s azurerm_resource_group.web_server_rg: Destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 10s elapsed] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 20s elapsed] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 30s elapsed] azurerm_resource_group.web_server_rg: Destruction complete after 38s Destroy complete! Resources: 2 destroyed.
Let's list all the resource groups
az group list 1m Sat Apr 4 10:29:56 2020 [ { "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/NetworkWatcherRG", "location": "westus2", "managedBy": null, "name": "NetworkWatcherRG", "properties": { "provisioningState": "Succeeded" }, "tags": null, "type": "Microsoft.Resources/resourceGroups" } ]
Now we have only one resource group Called: NetworkWatcherRG, bellow the description about it.
Network Watcher is a regional service that enables you to monitor and diagnose conditions at a network scenario level in, to, and from Azure. Scenario level monitoring enables you to diagnose problems at an end to end network level view. Network diagnostic and visualization tools available with Network Watcher help you understand, diagnose, and gain insights to your network in Azure. Network Watcher is enabled through the creation of a Network Watcher resource. This resource allows you to utilize Network Watcher capabilities.
Resources:
Terraform Dependencies
Let's take a look the kinds of dependencies that we may face
This resource has no dependency of another one, it just dependes of the variable web_server_rg and if does not has any default value or declaration when you run plan or apply it will ask you about it.
# No dependency resource "azurerm_resource_group" "web_server_rg" { name = var.web_server_rg } # No dependency resource "azurerm_virtual_network" "web_server_vnet" { name = "${var.resource_prefix}-vnet" resource_group_name = var.web_server_rg }
This resource has indirect dependency of another one, in this case we depend of azurerm_resource_group.web_server_rg.name, when we run the plan or apply and the resource required is not present we shall have a failure about it
# Indirect dependency resource "azurerm_virtual_network" "web_server_vnet" { name = "${var.resource_prefix}-vnet" resource_group_name = azurerm_resource_group.web_server_rg.name }
This resource has direct dependency of this one, in this case we depend of azurerm_resource_group.web_server_rg when we run the plan or apply and the resource required is not present we shall have a failure about it. For example we try to create the virtual network inside the resource group that should've be created before this resource we'll have a failure about the dependency.
# Direct dependency resource "azurerm_virtual_network" "web_server_vnet" { name = "${var.resource_prefix}-vnet" resource_group_name = var.web_server_rg depends_on = [ "azurerm_resource_group.web_server_rg" ] }
Terraform with Azure Subnet
Azure Subnet:
- Subnetwork within a VNET
- Address space
- Segmentation
- NSG
Let's update the file that will hold the variables with the new variables for the Subnets
vim terraform.tfvars # Define the Web server Location web_server_location = "westus2" # Define the Web Server Resource Group Name web_server_rg = "web-rg" # Resource Prefix resource_prefix = "web-server" # Address Space web_server_address_space = "10.0.0.0/22" # Web Server Address Prefix web_server_address_prefix = "10.0.1.0/24"
Note: A .tfvars file is used to assign values to variables that have already been declared in .tf files, not to declare new variables.
Let's Edit the main.tf to use add the new resource called azurerm_subnet
vim main.tf ## Defining the Variables variable "web_server_location" {} variable "web_server_rg" {} variable "resource_prefix" {} variable "web_server_address_space" {} variable "web_server_address_prefix" {} # Provider # https://www.terraform.io/docs/providers/azurerm/index.html provider "azurerm" { # With Terraform 12 we need to stick with 1.27 version = "~> 1.27" # The Subscription ID which should be used. This can also be sourced from the ARM_SUBSCRIPTION_ID Environment Variable. # subscription_id = "${var.subscription_id}" # The Client ID which should be used. This can also be sourced from the ARM_CLIENT_ID Environment Variable. # client_id = "${var.client_id}" # The Client Secret which should be used. This can also be sourced from the ARM_CLIENT_SECRET Environment Variable. # client_secret = "${var.client_secret}" # The Tenant ID which should be used. This can also be sourced from the ARM_TENANT_ID Environment Variable. # tenant_id = "${var.tenant_id}" } # Manages a Resource Group. # https://www.terraform.io/docs/providers/azurerm/r/resource_group.html resource "azurerm_resource_group" "web_server_rg" { # The Name which should be used for this Resource Group. # Here we'll use the variable web_server_rg that was declared into terraform.tfvars name = var.web_server_rg # The Azure Region where the Resource Group should exist. # Here we'll use the variable web_server_location that was declared into terraform.tfvars location = var.web_server_location } # Manages a virtual network including any configured subnets. # Each subnet can optionally be configured with a security group to be associated with the subnet. # https://www.terraform.io/docs/providers/azurerm/r/virtual_network.html resource "azurerm_virtual_network" "web_server_vnet" { # (Required) The name of the virtual network. Changing this forces a new resource to be created. # Note: here as we need to interpolate the variable with some kind of string we need to use "${}-string" inside quotes name = "${var.resource_prefix}-vnet" # (Required) The location/region where the virtual network is created. Changing this forces a new resource to be created. location = var.web_server_location # (Required) The name of the resource group in which to create the virtual network. resource_group_name = azurerm_resource_group.web_server_rg.name # (Required) The address space that is used the virtual network. You can supply more than one address space. Changing this forces a new resource to be created. address_space = [var.web_server_address_space] } # Manages a subnet. Subnets represent network segments within the IP space defined by the virtual network. # https://www.terraform.io/docs/providers/azurerm/r/subnet.html resource "azurerm_subnet" "web_server_subnet" { # (Required) The name of the subnet. Changing this forces a new resource to be created name = "${var.resource_prefix}-subnet" # (Required) The name of the resource group in which to create the subnet. Changing this forces a new resource to be created. resource_group_name = azurerm_resource_group.web_server_rg.name # (Required) The name of the virtual network to which to attach the subnet. Changing this forces a new resource to be created. virtual_network_name = azurerm_virtual_network.web_server_vnet.name # (Required) The address prefix to use for the subnet. address_prefix = var.web_server_address_prefix }
Now we can run the terraform plan to take a look what will happen if we apply the configuration
terraform plan 2688ms Sat Apr 4 10:30:29 2020 Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. ------------------------------------------------------------------------ An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_resource_group.web_server_rg will be created + resource "azurerm_resource_group" "web_server_rg" { + id = (known after apply) + location = "westus2" + name = "web-rg" + tags = (known after apply) } # azurerm_subnet.web_server_subnet will be created + resource "azurerm_subnet" "web_server_subnet" { + address_prefix = "10.0.1.0/24" + enforce_private_link_endpoint_network_policies = false + enforce_private_link_service_network_policies = false + id = (known after apply) + ip_configurations = (known after apply) + name = "web-server-subnet" + resource_group_name = "web-rg" + virtual_network_name = "web-server-vnet" } # azurerm_virtual_network.web_server_vnet will be created + resource "azurerm_virtual_network" "web_server_vnet" { + address_space = [ + "10.0.0.0/22", ] + id = (known after apply) + location = "westus2" + name = "web-server-vnet" + resource_group_name = "web-rg" + tags = (known after apply) + subnet { + address_prefix = (known after apply) + id = (known after apply) + name = (known after apply) + security_group = (known after apply) } } Plan: 3 to add, 0 to change, 0 to destroy. ------------------------------------------------------------------------ Note: You didn't specify an "-out" parameter to save this plan, so Terraform can't guarantee that exactly these actions will be performed if "terraform apply" is subsequently run.
As we can see the terraform plan didn't throw any errors, now we can apply the configuration
terraform apply 7.2s Sat Apr 4 11:14:35 2020 An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_resource_group.web_server_rg will be created + resource "azurerm_resource_group" "web_server_rg" { + id = (known after apply) + location = "westus2" + name = "web-rg" + tags = (known after apply) } # azurerm_subnet.web_server_subnet will be created + resource "azurerm_subnet" "web_server_subnet" { + address_prefix = "10.0.1.0/24" + enforce_private_link_endpoint_network_policies = false + enforce_private_link_service_network_policies = false + id = (known after apply) + ip_configurations = (known after apply) + name = "web-server-subnet" + resource_group_name = "web-rg" + virtual_network_name = "web-server-vnet" } # azurerm_virtual_network.web_server_vnet will be created + resource "azurerm_virtual_network" "web_server_vnet" { + address_space = [ + "10.0.0.0/22", ] + id = (known after apply) + location = "westus2" + name = "web-server-vnet" + resource_group_name = "web-rg" + tags = (known after apply) + subnet { + address_prefix = (known after apply) + id = (known after apply) + name = (known after apply) + security_group = (known after apply) } } Plan: 3 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes azurerm_resource_group.web_server_rg: Creating... azurerm_resource_group.web_server_rg: Creation complete after 4s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg] azurerm_virtual_network.web_server_vnet: Creating... azurerm_virtual_network.web_server_vnet: Still creating... [10s elapsed] azurerm_virtual_network.web_server_vnet: Creation complete after 13s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet] azurerm_subnet.web_server_subnet: Creating... azurerm_subnet.web_server_subnet: Creation complete after 3s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet/subnets/web-server-subnet] Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
Now we can check if there is a new resource group into Azure Portal or we can check in the command line
az group list 43.2s Sat Apr 4 11:22:47 2020 [ { "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/NetworkWatcherRG", "location": "westus2", "managedBy": null, "name": "NetworkWatcherRG", "properties": { "provisioningState": "Succeeded" }, "tags": null, "type": "Microsoft.Resources/resourceGroups" }, { "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg", "location": "westus2", "managedBy": null, "name": "web-rg", "properties": { "provisioningState": "Succeeded" }, "tags": {}, "type": "Microsoft.Resources/resourceGroups" } ]
Now let's list the VNET
az network vnet list 2999ms Sat Apr 4 11:22:53 2020 [ { "addressSpace": { "addressPrefixes": [ "10.0.0.0/22" ] }, "bgpCommunities": null, "ddosProtectionPlan": null, "dhcpOptions": { "dnsServers": [] }, "enableDdosProtection": false, "enableVmProtection": false, "etag": "W/\"41bc2a42-e22f-49c8-a396-6aae118adae3\"", "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet", "location": "westus2", "name": "web-server-vnet", "provisioningState": "Succeeded", "resourceGroup": "web-rg", "resourceGuid": "a1b2d72a-c6c4-4314-8b19-4019519229c6", "subnets": [ { "addressPrefix": "10.0.1.0/24", "addressPrefixes": null, "delegations": [], "etag": "W/\"41bc2a42-e22f-49c8-a396-6aae118adae3\"", "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet/subnets/web-server-subnet", "ipConfigurationProfiles": null, "ipConfigurations": null, "name": "web-server-subnet", "natGateway": null, "networkSecurityGroup": null, "privateEndpointNetworkPolicies": "Enabled", "privateEndpoints": null, "privateLinkServiceNetworkPolicies": "Enabled", "provisioningState": "Succeeded", "purpose": null, "resourceGroup": "web-rg", "resourceNavigationLinks": null, "routeTable": null, "serviceAssociationLinks": null, "serviceEndpointPolicies": null, "serviceEndpoints": [], "type": "Microsoft.Network/virtualNetworks/subnets" } ], "tags": {}, "type": "Microsoft.Network/virtualNetworks", "virtualNetworkPeerings": [] } ]
Now let's list the subnet that we've just created
az network vnet subnet list -g web-rg --vnet-name web-server-vnet 2398ms Sat Apr 4 11:23:48 2020 [ { "addressPrefix": "10.0.1.0/24", "addressPrefixes": null, "delegations": [], "etag": "W/\"41bc2a42-e22f-49c8-a396-6aae118adae3\"", "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet/subnets/web-server-subnet", "ipConfigurationProfiles": null, "ipConfigurations": null, "name": "web-server-subnet", "natGateway": null, "networkSecurityGroup": null, "privateEndpointNetworkPolicies": "Enabled", "privateEndpoints": null, "privateLinkServiceNetworkPolicies": "Enabled", "provisioningState": "Succeeded", "purpose": null, "resourceGroup": "web-rg", "resourceNavigationLinks": null, "routeTable": null, "serviceAssociationLinks": null, "serviceEndpointPolicies": null, "serviceEndpoints": [], "type": "Microsoft.Network/virtualNetworks/subnets" } ]
As we can see there is a new resource group create by Terraform. Now let's destroy it to continue the configuration.
terraform destroy 1657ms Sat Apr 4 11:25:19 2020 azurerm_resource_group.web_server_rg: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg] azurerm_virtual_network.web_server_vnet: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet] azurerm_subnet.web_server_subnet: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet/subnets/web-server-subnet] An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: - destroy Terraform will perform the following actions: # azurerm_resource_group.web_server_rg will be destroyed - resource "azurerm_resource_group" "web_server_rg" { - id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg" -> null - location = "westus2" -> null - name = "web-rg" -> null - tags = {} -> null } # azurerm_subnet.web_server_subnet will be destroyed - resource "azurerm_subnet" "web_server_subnet" { - address_prefix = "10.0.1.0/24" -> null - enforce_private_link_endpoint_network_policies = false -> null - enforce_private_link_service_network_policies = false -> null - id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet/subnets/web-server-subnet" -> null - ip_configurations = [] -> null - name = "web-server-subnet" -> null - resource_group_name = "web-rg" -> null - service_endpoints = [] -> null - virtual_network_name = "web-server-vnet" -> null } # azurerm_virtual_network.web_server_vnet will be destroyed - resource "azurerm_virtual_network" "web_server_vnet" { - address_space = [ - "10.0.0.0/22", ] -> null - dns_servers = [] -> null - id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet" -> null - location = "westus2" -> null - name = "web-server-vnet" -> null - resource_group_name = "web-rg" -> null - tags = {} -> null - subnet { - address_prefix = "10.0.1.0/24" -> null - id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet/subnets/web-server-subnet" -> null - name = "web-server-subnet" -> null } } Plan: 0 to add, 0 to change, 3 to destroy. Do you really want to destroy all resources? Terraform will destroy all your managed infrastructure, as shown above. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes azurerm_subnet.web_server_subnet: Destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet/subnets/web-server-subnet] azurerm_subnet.web_server_subnet: Destruction complete after 2s azurerm_virtual_network.web_server_vnet: Destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet] azurerm_virtual_network.web_server_vnet: Destruction complete after 2s azurerm_resource_group.web_server_rg: Destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 10s elapsed] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 20s elapsed] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 30s elapsed] azurerm_resource_group.web_server_rg: Destruction complete after 39s Destroy complete! Resources: 3 destroyed.
Let's list all the resource groups
az group list 1m Sat Apr 4 11:29:01 2020 [ { "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/NetworkWatcherRG", "location": "westus2", "managedBy": null, "name": "NetworkWatcherRG", "properties": { "provisioningState": "Succeeded" }, "tags": null, "type": "Microsoft.Resources/resourceGroups" } ]
Now we have only one resource group Called: NetworkWatcherRG, bellow the description about it.
Network Watcher is a regional service that enables you to monitor and diagnose conditions at a network scenario level in, to, and from Azure. Scenario level monitoring enables you to diagnose problems at an end to end network level view. Network diagnostic and visualization tools available with Network Watcher help you understand, diagnose, and gain insights to your network in Azure. Network Watcher is enabled through the creation of a Network Watcher resource. This resource allows you to utilize Network Watcher capabilities.
Resources:
Terraform with Azure Network Interface
Azure Network Interface:
- Subnet/VNET
- IP Private and Public
- Static and Dynamic
- DNS Settings
- NSG
Let's update the file that will hold the variables with the new variables for the Network Interfaces
vim terraform.tfvars # Define the Web server Location web_server_location = "westus2" # Define the Web Server Resource Group Name web_server_rg = "web-rg" # Resource Prefix resource_prefix = "web-server" # Address Space web_server_address_space = "10.0.0.0/22" # Web Server Address Prefix web_server_address_prefix = "10.0.1.0/24" # Web Server Name web_server_name = "web-01"
Note: A .tfvars file is used to assign values to variables that have already been declared in .tf files, not to declare new variables.
Let's Edit the main.tf to use add the new resource called azurerm_subnet
vim main.tf ## Defining the Variables variable "web_server_location" {} variable "web_server_rg" {} variable "resource_prefix" {} variable "web_server_address_space" {} variable "web_server_address_prefix" {} variable "web_server_name" {} # Provider # https://www.terraform.io/docs/providers/azurerm/index.html provider "azurerm" { # With Terraform 12 we need to stick with 1.27 version = "~> 1.27" # The Subscription ID which should be used. This can also be sourced from the ARM_SUBSCRIPTION_ID Environment Variable. # subscription_id = "${var.subscription_id}" # The Client ID which should be used. This can also be sourced from the ARM_CLIENT_ID Environment Variable. # client_id = "${var.client_id}" # The Client Secret which should be used. This can also be sourced from the ARM_CLIENT_SECRET Environment Variable. # client_secret = "${var.client_secret}" # The Tenant ID which should be used. This can also be sourced from the ARM_TENANT_ID Environment Variable. # tenant_id = "${var.tenant_id}" } # Manages a Resource Group. # https://www.terraform.io/docs/providers/azurerm/r/resource_group.html resource "azurerm_resource_group" "web_server_rg" { # The Name which should be used for this Resource Group. # Here we'll use the variable web_server_rg that was declared into terraform.tfvars name = var.web_server_rg # The Azure Region where the Resource Group should exist. # Here we'll use the variable web_server_location that was declared into terraform.tfvars location = var.web_server_location } # Manages a virtual network including any configured subnets. # Each subnet can optionally be configured with a security group to be associated with the subnet. # https://www.terraform.io/docs/providers/azurerm/r/virtual_network.html resource "azurerm_virtual_network" "web_server_vnet" { # (Required) The name of the virtual network. Changing this forces a new resource to be created. # Note: here as we need to interpolate the variable with some kind of string we need to use "${}-string" inside quotes name = "${var.resource_prefix}-vnet" # (Required) The location/region where the virtual network is created. Changing this forces a new resource to be created. location = var.web_server_location # (Required) The name of the resource group in which to create the virtual network. resource_group_name = azurerm_resource_group.web_server_rg.name # (Required) The address space that is used the virtual network. You can supply more than one address space. Changing this forces a new resource to be created. address_space = [var.web_server_address_space] } # Manages a subnet. Subnets represent network segments within the IP space defined by the virtual network. # https://www.terraform.io/docs/providers/azurerm/r/subnet.html resource "azurerm_subnet" "web_server_subnet" { # (Required) The name of the subnet. Changing this forces a new resource to be created name = "${var.resource_prefix}-subnet" # (Required) The name of the resource group in which to create the subnet. Changing this forces a new resource to be created. resource_group_name = azurerm_resource_group.web_server_rg.name # (Required) The name of the virtual network to which to attach the subnet. Changing this forces a new resource to be created. virtual_network_name = azurerm_virtual_network.web_server_vnet.name # (Required) The address prefix to use for the subnet. address_prefix = var.web_server_address_prefix } # Manages a Network Interface. # https://www.terraform.io/docs/providers/azurerm/r/network_interface.html resource "azurerm_network_interface" "web_server_nic" { # (Required) The name of the Network Interface. Changing this forces a new resource to be created. name = "${var.web_server_name}-nic" # (Required) The location where the Network Interface should exist. Changing this forces a new resource to be created. location = var.web_server_location # (Required) The name of the Resource Group in which to create the Network Interface. Changing this forces a new resource to be created. resource_group_name = azurerm_resource_group.web_server_rg.name # (Required) One or more ip_configuration blocks as defined below. ip_configuration { # (Required) A name used for this IP Configuration. name = "${var.web_server_name}-ip" # (Optional) The ID of the Subnet where this Network Interface should be located in. subnet_id = azurerm_subnet.web_server_subnet.id # (Optional) The IP Version to use. Possible values are IPv4 or IPv6. Defaults to IPv4. private_ip_address_version = "IPv4" # (Required) The allocation method used for the Private IP Address. Possible values are Dynamic and Static. private_ip_address_allocation = "Dynamic" } }
Now we can run the terraform plan to take a look what will happen if we apply the configuration
terraform plan 3389ms Sat Apr 4 11:29:34 2020 Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. ------------------------------------------------------------------------ An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_network_interface.web_server_nic will be created + resource "azurerm_network_interface" "web_server_nic" { + applied_dns_servers = (known after apply) + dns_servers = (known after apply) + enable_accelerated_networking = false + enable_ip_forwarding = false + id = (known after apply) + internal_dns_name_label = (known after apply) + internal_fqdn = (known after apply) + location = "westus2" + mac_address = (known after apply) + name = "web-01-nic" + private_ip_address = (known after apply) + private_ip_addresses = (known after apply) + resource_group_name = "web-rg" + tags = (known after apply) + virtual_machine_id = (known after apply) + ip_configuration { + application_gateway_backend_address_pools_ids = (known after apply) + application_security_group_ids = (known after apply) + load_balancer_backend_address_pools_ids = (known after apply) + load_balancer_inbound_nat_rules_ids = (known after apply) + name = "web-01-ip" + primary = (known after apply) + private_ip_address = (known after apply) + private_ip_address_allocation = "dynamic" + private_ip_address_version = "IPv4" + subnet_id = (known after apply) } } # azurerm_resource_group.web_server_rg will be created + resource "azurerm_resource_group" "web_server_rg" { + id = (known after apply) + location = "westus2" + name = "web-rg" + tags = (known after apply) } # azurerm_subnet.web_server_subnet will be created + resource "azurerm_subnet" "web_server_subnet" { + address_prefix = "10.0.1.0/24" + enforce_private_link_endpoint_network_policies = false + enforce_private_link_service_network_policies = false + id = (known after apply) + ip_configurations = (known after apply) + name = "web-server-subnet" + resource_group_name = "web-rg" + virtual_network_name = "web-server-vnet" } # azurerm_virtual_network.web_server_vnet will be created + resource "azurerm_virtual_network" "web_server_vnet" { + address_space = [ + "10.0.0.0/22", ] + id = (known after apply) + location = "westus2" + name = "web-server-vnet" + resource_group_name = "web-rg" + tags = (known after apply) + subnet { + address_prefix = (known after apply) + id = (known after apply) + name = (known after apply) + security_group = (known after apply) } } Plan: 4 to add, 0 to change, 0 to destroy. ------------------------------------------------------------------------ Note: You didn't specify an "-out" parameter to save this plan, so Terraform can't guarantee that exactly these actions will be performed if "terraform apply" is subsequently run.
As we can see the terraform plan didn't throw any errors, now we can apply the configuration
terraform apply 9s Sat Apr 4 12:05:28 2020 An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_network_interface.web_server_nic will be created + resource "azurerm_network_interface" "web_server_nic" { + applied_dns_servers = (known after apply) + dns_servers = (known after apply) + enable_accelerated_networking = false + enable_ip_forwarding = false + id = (known after apply) + internal_dns_name_label = (known after apply) + internal_fqdn = (known after apply) + location = "westus2" + mac_address = (known after apply) + name = "web-01-nic" + private_ip_address = (known after apply) + private_ip_addresses = (known after apply) + resource_group_name = "web-rg" + tags = (known after apply) + virtual_machine_id = (known after apply) + ip_configuration { + application_gateway_backend_address_pools_ids = (known after apply) + application_security_group_ids = (known after apply) + load_balancer_backend_address_pools_ids = (known after apply) + load_balancer_inbound_nat_rules_ids = (known after apply) + name = "web-01-ip" + primary = (known after apply) + private_ip_address = (known after apply) + private_ip_address_allocation = "dynamic" + private_ip_address_version = "IPv4" + subnet_id = (known after apply) } } # azurerm_resource_group.web_server_rg will be created + resource "azurerm_resource_group" "web_server_rg" { + id = (known after apply) + location = "westus2" + name = "web-rg" + tags = (known after apply) } # azurerm_subnet.web_server_subnet will be created + resource "azurerm_subnet" "web_server_subnet" { + address_prefix = "10.0.1.0/24" + enforce_private_link_endpoint_network_policies = false + enforce_private_link_service_network_policies = false + id = (known after apply) + ip_configurations = (known after apply) + name = "web-server-subnet" + resource_group_name = "web-rg" + virtual_network_name = "web-server-vnet" } # azurerm_virtual_network.web_server_vnet will be created + resource "azurerm_virtual_network" "web_server_vnet" { + address_space = [ + "10.0.0.0/22", ] + id = (known after apply) + location = "westus2" + name = "web-server-vnet" + resource_group_name = "web-rg" + tags = (known after apply) + subnet { + address_prefix = (known after apply) + id = (known after apply) + name = (known after apply) + security_group = (known after apply) } } Plan: 4 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes azurerm_resource_group.web_server_rg: Creating... azurerm_resource_group.web_server_rg: Creation complete after 8s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg] azurerm_virtual_network.web_server_vnet: Creating... azurerm_virtual_network.web_server_vnet: Still creating... [10s elapsed] azurerm_virtual_network.web_server_vnet: Creation complete after 11s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet] azurerm_subnet.web_server_subnet: Creating... azurerm_subnet.web_server_subnet: Creation complete after 4s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet/subnets/web-server-subnet] azurerm_network_interface.web_server_nic: Creating... azurerm_network_interface.web_server_nic: Still creating... [10s elapsed] azurerm_network_interface.web_server_nic: Creation complete after 11s [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/networkInterfaces/web-01-nic] Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
Now we can check if there is a new resource group into Azure Portal or we can check in the command line
az group list 55.5s Sat Apr 4 12:06:37 2020 [ { "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/NetworkWatcherRG", "location": "westus2", "managedBy": null, "name": "NetworkWatcherRG", "properties": { "provisioningState": "Succeeded" }, "tags": null, "type": "Microsoft.Resources/resourceGroups" }, { "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg", "location": "westus2", "managedBy": null, "name": "web-rg", "properties": { "provisioningState": "Succeeded" }, "tags": {}, "type": "Microsoft.Resources/resourceGroups" } ]
Now let's list the VNET
az network vnet list 2279ms Sat Apr 4 12:07:09 2020 [ { "addressSpace": { "addressPrefixes": [ "10.0.0.0/22" ] }, "bgpCommunities": null, "ddosProtectionPlan": null, "dhcpOptions": { "dnsServers": [] }, "enableDdosProtection": false, "enableVmProtection": false, "etag": "W/\"c02bebd6-a1a2-4f17-adbc-fa6b80d5d8d5\"", "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet", "location": "westus2", "name": "web-server-vnet", "provisioningState": "Succeeded", "resourceGroup": "web-rg", "resourceGuid": "9d8309a8-6867-4f34-93b0-e82af625acd5", "subnets": [ { "addressPrefix": "10.0.1.0/24", "addressPrefixes": null, "delegations": [], "etag": "W/\"c02bebd6-a1a2-4f17-adbc-fa6b80d5d8d5\"", "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet/subnets/web-server-subnet", "ipConfigurationProfiles": null, "ipConfigurations": [ { "etag": null, "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/networkInterfaces/web-01-nic/ipConfigurations/web-01-ip", "name": null, "privateIpAddress": null, "privateIpAllocationMethod": null, "provisioningState": null, "publicIpAddress": null, "resourceGroup": "web-rg", "subnet": null } ], "name": "web-server-subnet", "natGateway": null, "networkSecurityGroup": null, "privateEndpointNetworkPolicies": "Enabled", "privateEndpoints": null, "privateLinkServiceNetworkPolicies": "Enabled", "provisioningState": "Succeeded", "purpose": null, "resourceGroup": "web-rg", "resourceNavigationLinks": null, "routeTable": null, "serviceAssociationLinks": null, "serviceEndpointPolicies": null, "serviceEndpoints": [], "type": "Microsoft.Network/virtualNetworks/subnets" } ], "tags": {}, "type": "Microsoft.Network/virtualNetworks", "virtualNetworkPeerings": [] } ]
Now let's list the subnet that we've just created
az network vnet subnet list -g web-rg --vnet-name web-server-vnet 1799ms Sat Apr 4 12:07:47 2020 [ { "addressPrefix": "10.0.1.0/24", "addressPrefixes": null, "delegations": [], "etag": "W/\"c02bebd6-a1a2-4f17-adbc-fa6b80d5d8d5\"", "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet/subnets/web-server-subnet", "ipConfigurationProfiles": null, "ipConfigurations": [ { "etag": null, "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/networkInterfaces/web-01-nic/ipConfigurations/web-01-ip", "name": null, "privateIpAddress": null, "privateIpAllocationMethod": null, "provisioningState": null, "publicIpAddress": null, "resourceGroup": "web-rg", "subnet": null } ], "name": "web-server-subnet", "natGateway": null, "networkSecurityGroup": null, "privateEndpointNetworkPolicies": "Enabled", "privateEndpoints": null, "privateLinkServiceNetworkPolicies": "Enabled", "provisioningState": "Succeeded", "purpose": null, "resourceGroup": "web-rg", "resourceNavigationLinks": null, "routeTable": null, "serviceAssociationLinks": null, "serviceEndpointPolicies": null, "serviceEndpoints": [], "type": "Microsoft.Network/virtualNetworks/subnets" } ]
Now Let's list the network Interface
az network nic list 1133ms Sat Apr 4 12:16:13 2020 [ { "dnsSettings": { "appliedDnsServers": [], "dnsServers": [], "internalDnsNameLabel": null, "internalDomainNameSuffix": "vaeyhhlhna0e5e3q3avpmjnm0f.xx.internal.cloudapp.net", "internalFqdn": null }, "enableAcceleratedNetworking": false, "enableIpForwarding": false, "etag": "W/\"83c39a33-4a93-4f8a-a57b-3513dbd8f95a\"", "hostedWorkloads": [], "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/networkInterfaces/web-01-nic", "ipConfigurations": [ { "applicationGatewayBackendAddressPools": null, "applicationSecurityGroups": null, "etag": "W/\"83c39a33-4a93-4f8a-a57b-3513dbd8f95a\"", "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/networkInterfaces/web-01-nic/ipConfigurations/web-01-ip", "loadBalancerBackendAddressPools": null, "loadBalancerInboundNatRules": null, "name": "web-01-ip", "primary": true, "privateIpAddress": "10.0.1.4", "privateIpAddressVersion": "IPv4", "privateIpAllocationMethod": "Dynamic", "privateLinkConnectionProperties": null, "provisioningState": "Succeeded", "publicIpAddress": null, "resourceGroup": "web-rg", "subnet": { "addressPrefix": null, "addressPrefixes": null, "delegations": null, "etag": null, "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet/subnets/web-server-subnet", "ipConfigurationProfiles": null, "ipConfigurations": null, "name": null, "natGateway": null, "networkSecurityGroup": null, "privateEndpointNetworkPolicies": null, "privateEndpoints": null, "privateLinkServiceNetworkPolicies": null, "provisioningState": null, "purpose": null, "resourceGroup": "web-rg", "resourceNavigationLinks": null, "routeTable": null, "serviceAssociationLinks": null, "serviceEndpointPolicies": null, "serviceEndpoints": null }, "type": "Microsoft.Network/networkInterfaces/ipConfigurations", "virtualNetworkTaps": null } ], "location": "westus2", "macAddress": null, "name": "web-01-nic", "networkSecurityGroup": null, "primary": null, "privateEndpoint": null, "provisioningState": "Succeeded", "resourceGroup": "web-rg", "resourceGuid": "7f7c3993-8682-41c6-868a-87afaedb4618", "tags": {}, "tapConfigurations": [], "type": "Microsoft.Network/networkInterfaces", "virtualMachine": null } ]
As we can see there is a new resource group create by Terraform. Now let's destroy it to continue the configuration.
terraform destroy 1855ms Sat Apr 4 12:17:05 2020 azurerm_resource_group.web_server_rg: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg] azurerm_virtual_network.web_server_vnet: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet] azurerm_subnet.web_server_subnet: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet/subnets/web-server-subnet] azurerm_network_interface.web_server_nic: Refreshing state... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/networkInterfaces/web-01-nic] An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: - destroy Terraform will perform the following actions: # azurerm_network_interface.web_server_nic will be destroyed - resource "azurerm_network_interface" "web_server_nic" { - applied_dns_servers = [] -> null - dns_servers = [] -> null - enable_accelerated_networking = false -> null - enable_ip_forwarding = false -> null - id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/networkInterfaces/web-01-nic" -> null - location = "westus2" -> null - name = "web-01-nic" -> null - private_ip_address = "10.0.1.4" -> null - private_ip_addresses = [ - "10.0.1.4", ] -> null - resource_group_name = "web-rg" -> null - tags = {} -> null - ip_configuration { - application_gateway_backend_address_pools_ids = [] -> null - application_security_group_ids = [] -> null - load_balancer_backend_address_pools_ids = [] -> null - load_balancer_inbound_nat_rules_ids = [] -> null - name = "web-01-ip" -> null - primary = true -> null - private_ip_address = "10.0.1.4" -> null - private_ip_address_allocation = "dynamic" -> null - private_ip_address_version = "IPv4" -> null - subnet_id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet/subnets/web-server-subnet" -> null } } # azurerm_resource_group.web_server_rg will be destroyed - resource "azurerm_resource_group" "web_server_rg" { - id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg" -> null - location = "westus2" -> null - name = "web-rg" -> null - tags = {} -> null } # azurerm_subnet.web_server_subnet will be destroyed - resource "azurerm_subnet" "web_server_subnet" { - address_prefix = "10.0.1.0/24" -> null - enforce_private_link_endpoint_network_policies = false -> null - enforce_private_link_service_network_policies = false -> null - id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet/subnets/web-server-subnet" -> null - ip_configurations = [ - "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/networkInterfaces/web-01-nic/ipConfigurations/web-01-ip", ] -> null - name = "web-server-subnet" -> null - resource_group_name = "web-rg" -> null - service_endpoints = [] -> null - virtual_network_name = "web-server-vnet" -> null } # azurerm_virtual_network.web_server_vnet will be destroyed - resource "azurerm_virtual_network" "web_server_vnet" { - address_space = [ - "10.0.0.0/22", ] -> null - dns_servers = [] -> null - id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet" -> null - location = "westus2" -> null - name = "web-server-vnet" -> null - resource_group_name = "web-rg" -> null - tags = {} -> null - subnet { - address_prefix = "10.0.1.0/24" -> null - id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet/subnets/web-server-subnet" -> null - name = "web-server-subnet" -> null } } Plan: 0 to add, 0 to change, 4 to destroy. Do you really want to destroy all resources? Terraform will destroy all your managed infrastructure, as shown above. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes azurerm_network_interface.web_server_nic: Destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/networkInterfaces/web-01-nic] azurerm_network_interface.web_server_nic: Destruction complete after 3s azurerm_subnet.web_server_subnet: Destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet/subnets/web-server-subnet] azurerm_subnet.web_server_subnet: Destruction complete after 3s azurerm_virtual_network.web_server_vnet: Destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg/providers/Microsoft.Network/virtualNetworks/web-server-vnet] azurerm_virtual_network.web_server_vnet: Destruction complete after 2s azurerm_resource_group.web_server_rg: Destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 10s elapsed] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 20s elapsed] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 30s elapsed] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 40s elapsed] azurerm_resource_group.web_server_rg: Still destroying... [id=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/web-rg, 50s elapsed] azurerm_resource_group.web_server_rg: Destruction complete after 53s Destroy complete! Resources: 4 destroyed.
Let's list all the resource groups
az group list 1m Sat Apr 4 11:29:01 2020 [ { "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/NetworkWatcherRG", "location": "westus2", "managedBy": null, "name": "NetworkWatcherRG", "properties": { "provisioningState": "Succeeded" }, "tags": null, "type": "Microsoft.Resources/resourceGroups" } ]
Now we have only one resource group Called: NetworkWatcherRG, bellow the description about it.
Network Watcher is a regional service that enables you to monitor and diagnose conditions at a network scenario level in, to, and from Azure. Scenario level monitoring enables you to diagnose problems at an end to end network level view. Network diagnostic and visualization tools available with Network Watcher help you understand, diagnose, and gain insights to your network in Azure. Network Watcher is enabled through the creation of a Network Watcher resource. This resource allows you to utilize Network Watcher capabilities.
Resources: