The AzureRM provider (RM stands for Resource Manager) for Terraform has been improving a lot since I started using it a few years ago. However, there is one thing with this provider that still bugs me: the features block.
You always have to include a provider block in your Terraform configuration, and at the very least this block has to contain an empty features block:
provider "azurerm" {
features {}
}This is true even if you use other means to configure authentication for Azure (perhaps using the Azure CLI).
A great enhancement for the AzureRM provider would be to not force me to configure an empty features block. For now, we are stuck with it. A follow-up question is: what can we use the features block for?
As the name of the block suggests this allows you to tweak certain features that determines how the provider will behave during terraform apply and terraform destroy. In this short blog post I want to cover a few of the features that I think could be useful.
Features of the AzureRM provider#
The first thing I will say is that a lot of the available options in the features block concerns services I never use. In the following sections I will cover what features I think could be useful, and I might even have used them at one point or more in the past.
Azure Key Vault#
Configuring an Azure Key Vault resource with Terraform is a common thing to do. In this Azure Key Vault you keep your secrets, keys, and certificates. What happens when you run terraform destroy for the Terraform configuration managing this Key Vault?
Turns out there are a lot of behavior to configure for this scenario, all of them concerning soft-deleted objects within the vault:
provider "azurerm" {
features {
key_vault {
purge_soft_delete_on_destroy = true
purge_soft_deleted_certificates_on_destroy = true
purge_soft_deleted_hardware_security_module_keys_on_destroy = true
purge_soft_deleted_hardware_security_modules_on_destroy = true
purge_soft_deleted_keys_on_destroy = true
purge_soft_deleted_secrets_on_destroy = true
recover_soft_deleted_certificates = true
recover_soft_deleted_hardware_security_module_keys = true
recover_soft_deleted_key_vaults = true
recover_soft_deleted_keys = true
recover_soft_deleted_secrets = true
}
}
}There are two categories of features: purging and recovering soft deleted objects in the vault.
If you manage important objects in your vault, then it is a good idea to not purge anything on delete:
provider "azurerm" {
features {
key_vault {
purge_soft_delete_on_destroy = false
purge_soft_deleted_certificates_on_destroy = false
purge_soft_deleted_hardware_security_module_keys_on_destroy = false
purge_soft_deleted_hardware_security_modules_on_destroy = false
purge_soft_deleted_keys_on_destroy = false
purge_soft_deleted_secrets_on_destroy = false
}
}
}I would not rely solely on this feature for anything around protecting my key vault and the objects within. Use prevent_destroy for important vaults (and any other resource for that matter):
resource "azurerm_key_vault" "name" {
# ... details omitted ...
lifecycle {
prevent_destroy = false
}
}To be fair, the items we are talking about are soft-deleted already. Chances are you will not need them anymore, because you deleted them for a reason. However, there are also a reason why the soft-delete feature even exists - because sometimes you delete items prematurely or by mistake.
Application Insights#
When you configure a resource with Terraform you expect that Terraform will be the sole decider of what resources are created. You generally do not want bonus resources to be created, because that is just … weird.
In my experience there are a few (perhaps even more than a few) of these cases on Azure. You create a resource, you get one otw two other resources for free.
One example of this is: create an application insights resource and you get an action group and a smart detector alert rule for free. You can disable this behavior using a feature:
provider "azurerm" {
features {
application_insights {
disable_generated_rule = true
}
}
}This should work, at least in theory. In the test I just ran it didn’t work! The generated rule still appears in my resource group. I think there is an opportunity to file a bug report here …
Resource groups#
My favorite service on Azure is not a service at all, it’s a way to organize resources: resource groups. Resource groups truly sets Azure apart from AWS and GCP. You almost have to compare Azure resource groups with AWS accounts or GCP projects to get something similar in behavior1.
Every resource you create on Azure must live in a resource group. When you experiment or try something on Azure, create a resource group, perform the experiment and create resources in this resource group, and then delete the resource group and all the resources from your experiment goes away with it. It is very easy to clean up after yourself!
This superpower comes with a great responsibility. Since everything in your resource group disappears if you delete the resource group, well … Let’s just say that things can go horribly wrong!
There is a feature in the features block to prevent Terraform from destroying a resource group if it still contains resources. Perhaps this can save you one day:
provider "azurerm" {
features {
resource_group {
prevent_deletion_if_contains_resources = true
}
}
}This features defaults to true so it might already have saved you even if you were unaware of it.
What does this feature mean in practice? It simply means you have to destroy all the resources within a resource group before you can destroy the resource group itself. This is typically handled by Terraform automatically since every resource has a dependency on the resource group (remember the DAG?).
However, what if another resource has made it into the resource group from outside your Terraform configuration? If this is true, and you run a terraform destroy operation for your Terraform configuration you will end up in a process where Terraform still appears trying to delete the resource group but eventually fails (after 10 minutes) with an error message:
Error: deleting Resource Group "rg-production-environment":
the Resource Group still contains Resources.
...If you do not expect (or care) that resources could appear in your resource group that are not part of your Terraform configuration you can set the flag to false:
provider "azurerm" {
features {
resource_group {
prevent_deletion_if_contains_resources = false
}
}
}In this case Terraform will succeed with the destruction of the resource group and any resource that happens to be part of it (but not part of your Terraform configuration). In essence, this gives you the same experience as deleting resource groups using the Azure portal.
Subscriptions#
To be fair, I currently do not manage any Azure subscriptions using Terraform. However, if I did then this feature would come in handy:
provider "azurerm" {
features {
subscription {
prevent_cancellation_on_destroy = true
}
}
}This would give you an extra safety mechanism when you accidentally run terraform destroy for one or more Azure subscriptions.
Virtual machines and virtual machine scale sets#
Something I have used in the past are features around virtual machines and virtual machine scale sets. Usually I set some of the flags shown below to true simply to streamline running terraform destroy for experimental infrastructure.
provider "azurerm" {
features {
virtual_machine {
delete_os_disk_on_deletion = true
detach_implicit_data_disk_on_deletion = true
skip_shutdown_and_force_delete = true
}
virtual_machine_scale_set {
force_delete = true
roll_instances_when_required = true
scale_to_zero_before_deletion = true
reimage_on_manual_upgrade = true
}
}
}These features allow you to control what happens during terraform destroy, as well as some features around updates for virtual machine scale sets. If you manage a lot of virtual machines with Terraform you should spend some time thinking through what to set these feature values to.
Conclusions#
I don’t love that the AzureRM provider forces me to configure an empty features block even if I am not planning on using anything other than the default features. However, for now we are stuck with it.
There are a few features available that could be beneficial for your Terraform experience with Azure. I would not say that there are any must-have features, because some of the features are really covered already if you use sensible Terraform practices.
AWS has resource groups as well, but they are not the same thing. ↩︎




