Destroy
Short lab to tear down the environment.
Overview
In this lab you will
- selectively destroy a resource with commenting
- destroy the whole environment with
terraform destroy
- check the state file
Starting point
Your files should look similar to this:
-
provider.tf
terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = "~>3.1" } } } provider "azurerm" { features {} storage_use_azuread = true }
-
variables.tf
variable "resource_group_name" { description = "Name for the resource group" type = string default = "terraform-basics" } variable "location" { description = "Azure region" type = string default = "West Europe" } variable "container_group_name" { description = "Name of the container group" type = string default = "terraform-basics" }
-
main.tf
locals { uniq = substr(sha1(azurerm_resource_group.basics.id), 0, 8) } resource "azurerm_resource_group" "basics" { name = var.resource_group_name location = var.location lifecycle { ignore_changes = [ tags, ] } } resource "azurerm_container_group" "basics" { name = var.container_group_name location = azurerm_resource_group.basics.location resource_group_name = azurerm_resource_group.basics.name ip_address_type = "Public" dns_name_label = "${var.container_group_name}-${local.uniq}" os_type = "Linux" container { name = "inspectorgadget" image = "jelledruyts/inspectorgadget:latest" cpu = "0.5" memory = "1.0" ports { port = 80 protocol = "TCP" } } } resource "azurerm_storage_account" "import_example" { name = "richeney27182818" resource_group_name = azurerm_resource_group.basics.name location = azurerm_resource_group.basics.location account_tier = "Standard" account_replication_type = "LRS" allow_nested_items_to_be_public = false is_hns_enabled = true nfsv3_enabled = true public_network_access_enabled = false }
⚠️ Your storage account name will be different.
-
outputs.tf
output "ip_address" { value = azurerm_container_group.basics.ip_address } output "fqdn" { value = "http://${azurerm_container_group.basics.fqdn}" }
-
terraform.tfvars
location = "UK South"
You may have set a different value for location.
Commenting and renaming
Before we clean up the environment, take a look at how commenting blocks and renaming files can change the behaviour of the CLI commands.
-
Comment out the container instance
You can comment individual lines by prepending with either
#
or//
.You can comment multiple lines by surrounding the block with
/*
and*/
, as shown below./* resource "azurerm_container_group" "basics" { name = var.container_group_name location = azurerm_resource_group.basics.location resource_group_name = azurerm_resource_group.basics.name ip_address_type = "public" dns_name_label = "${var.container_group_name}-${local.uniq}" os_type = "Linux" container { name = "inspectorgadget" image = "jelledruyts/inspectorgadget:latest" cpu = "0.5" memory = "1.0" ports { port = 80 protocol = "TCP" } } } */
Users of vscode can also highlight multiple lines and use the
CTRL
+K
,CTRL
+C
chord to comment, andCTRL
+K
,CTRL
+U
to uncomment. -
terraform plan
terraform plan
You should see errors based on the outputs.
-
Rename the outputs.tf file
When Terraform runs its commands it is looking at all files in the current directory that match
*.tf
. You can rename file suffixes and it will ignore those files.Rename the outputs files so that it is completely ignored in the diff.
mv outputs.tf outputs.tf.ignore
-
terraform plan
terraform plan
azurerm_resource_group.basics: Refreshing state... [id=/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/terraform-basics] azurerm_container_group.basics: Refreshing state... [id=/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/terraform-basics/providers/Microsoft.ContainerInstance/containerGroups/terraform-basics] azurerm_storage_account.import_example: Refreshing state... [id=/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/terraform-basics/providers/Microsoft.Storage/storageAccounts/richeney27182818] Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: - destroy Terraform will perform the following actions: # azurerm_container_group.basics will be destroyed # (because azurerm_container_group.basics is not in configuration) - resource "azurerm_container_group" "basics" { - dns_name_label = "terraform-basics-c3818179" -> null - exposed_port = [ - { - port = 80 - protocol = "TCP" }, ] -> null - fqdn = "terraform-basics-c3818179.uksouth.azurecontainer.io" -> null - id = "/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/terraform-basics/providers/Microsoft.ContainerInstance/containerGroups/terraform-basics" -> null - ip_address = "20.108.193.216" -> null - ip_address_type = "Public" -> null - location = "uksouth" -> null - name = "terraform-basics" -> null - os_type = "Linux" -> null - resource_group_name = "terraform-basics" -> null - restart_policy = "Always" -> null - tags = {} -> null - container { - commands = [] -> null - cpu = 0.5 -> null - environment_variables = {} -> null - image = "jelledruyts/inspectorgadget:latest" -> null - memory = 1 -> null - name = "inspectorgadget" -> null - secure_environment_variables = (sensitive value) - ports { - port = 80 -> null - protocol = "TCP" -> null } } } Plan: 0 to add, 0 to change, 1 to destroy. Changes to Outputs: - fqdn = "http://terraform-basics-c3818179.uksouth.azurecontainer.io" -> null - ip_address = "20.108.193.216" -> null ───────────────────────────────────────────────────────────────────────────── Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
The resource is no longer in the config and so Terraform plans to remove it.
Some of you will be familiar with ARM templates or Bicep and the standard incremental mode, which only ever contributes resources idempotently. If you were to remove resources from the resources array in an ARM template then those resources would remain in the resource group and would have to be manually deleted.
The Terraform behaviour here is closer to the less commonly used complete mode in ARM / Bicep.
-
Apply the change
terraform apply
Approve the change. The container group will be deleted.
terraform destroy
We’ll finish with a command that you will use rarely in production. The terraform destroy
command will update state, show the current resources and remove any defined in your files.
-
Destroy the environment
terraform destroy
Example output:
azurerm_resource_group.basics: Refreshing state... [id=/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/terraform-basics] azurerm_storage_account.import_example: Refreshing state... [id=/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/terraform-basics/providers/Microsoft.Storage/storageAccounts/richeney27182818] Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: - destroy Terraform will perform the following actions: # azurerm_resource_group.basics will be destroyed - resource "azurerm_resource_group" "basics" { - id = "/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/terraform-basics" -> null - location = "uksouth" -> null - name = "terraform-basics" -> null - tags = { - "source" = "terraform" } -> null } # azurerm_storage_account.import_example will be destroyed - resource "azurerm_storage_account" "import_example" { - access_tier = "Hot" -> null - account_kind = "StorageV2" -> null - account_replication_type = "LRS" -> null - account_tier = "Standard" -> null - allow_nested_items_to_be_public = true -> null - enable_https_traffic_only = true -> null - id = "/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/terraform-basics/providers/Microsoft.Storage/storageAccounts/richeney27182818" -> null - infrastructure_encryption_enabled = false -> null - is_hns_enabled = true -> null - location = "uksouth" -> null - min_tls_version = "TLS1_2" -> null - name = "richeney27182818" -> null - nfsv3_enabled = true -> null - primary_access_key = (sensitive value) - primary_blob_connection_string = (sensitive value) - primary_blob_endpoint = "https://richeney27182818.blob.core.windows.net/" -> null - primary_blob_host = "richeney27182818.blob.core.windows.net" -> null - primary_connection_string = (sensitive value) - primary_dfs_endpoint = "https://richeney27182818.dfs.core.windows.net/" -> null - primary_dfs_host = "richeney27182818.dfs.core.windows.net" -> null - primary_file_endpoint = "https://richeney27182818.file.core.windows.net/" -> null - primary_file_host = "richeney27182818.file.core.windows.net" -> null - primary_location = "uksouth" -> null - primary_queue_endpoint = "https://richeney27182818.queue.core.windows.net/" -> null - primary_queue_host = "richeney27182818.queue.core.windows.net" -> null - primary_table_endpoint = "https://richeney27182818.table.core.windows.net/" -> null - primary_table_host = "richeney27182818.table.core.windows.net" -> null - primary_web_endpoint = "https://richeney27182818.z33.web.core.windows.net/" -> null - primary_web_host = "richeney27182818.z33.web.core.windows.net" -> null - queue_encryption_key_type = "Service" -> null - resource_group_name = "terraform-basics" -> null - secondary_access_key = (sensitive value) - secondary_connection_string = (sensitive value) - shared_access_key_enabled = true -> null - table_encryption_key_type = "Service" -> null - tags = {} -> null - blob_properties { - change_feed_enabled = false -> null - last_access_time_enabled = false -> null - versioning_enabled = false -> null - delete_retention_policy { - days = 7 -> null } } - network_rules { - bypass = [ - "AzureServices", ] -> null - default_action = "Deny" -> null - ip_rules = [] -> null - virtual_network_subnet_ids = [] -> null } - queue_properties { - hour_metrics { - enabled = true -> null - include_apis = true -> null - retention_policy_days = 7 -> null - version = "1.0" -> null } - logging { - delete = false -> null - read = false -> null - retention_policy_days = 0 -> null - version = "1.0" -> null - write = false -> null } - minute_metrics { - enabled = false -> null - include_apis = false -> null - retention_policy_days = 0 -> null - version = "1.0" -> null } } - share_properties { - retention_policy { - days = 7 -> null } } - timeouts {} } 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_storage_account.import_example: Destroying... [id=/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/terraform-basics/providers/Microsoft.Storage/storageAccounts/richeney27182818] azurerm_storage_account.import_example: Destruction complete after 2s azurerm_resource_group.basics: Destroying... [id=/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/terraform-basics] azurerm_resource_group.basics: Still destroying... [id=/subscriptions/2ca40be1-7e80-4f2b-92f7-...3a68cc/resourceGroups/terraform-basics, 10s elapsed] azurerm_resource_group.basics: Destruction complete after 15s Destroy complete! Resources: 2 destroyed.
Summary
Done! 😊
You have learnt how to initialise Terraform, install providers, format and validate HCL files, how to add resources and plan and apply your configs. You have also worked with simple expressions, locals and outputs, manipulated the state file - including an import - and then managed the destroy phase.
Help us improve
Azure Citadel is a community site built on GitHub, please contribute and send a pull request
Make a change