How can I delete a resource with ARM template?
Tags: azure, devops, iac
Published: 2020-07-19 20:52:44

A few days ago, someone asked me this question, what is the command in ARM templates to delete resources in Azure? It is not a trivial question; it is more the reflection of a misconception about how ARM Templates and Infrastructure as Code works and how resources are organized in Azure. 
Before answering the question, let's make a little digression.

ARM templates is a declarative language based on JSON used to define the desired state of Azure resources. JSON files used by ARM can define objects at various scopes, Azure Tenant, Management groups, subscriptions, and resource groups.

The resource group scope lets you set your VM, infrastructure, and services for one resource group. In fact, at this scope, an ARM template intends to define the entire resource group. 
A resource group is a logical container that will group objects you want to manage as a group. Objects in a resource group must share the same life cycle, and a resource group helps you to define who can manage resources via RBAC.
But it’s easier to says than done. Take a simple web application, you may have network resources like VNET and LB, VMs with disk and NIC and maybe some databases. 
Do all objects share the same life cycle? 
It is not so simple. Take network-related resources, they can be shared across the subscription and used by other applications. More, you will change your VNET setting less often than your application.
But about databases and web application resources? They are linked together, more the web application may not work without the database and the database is useless without the application. But do they share the same lifecycle? 
Thinks about how you can change the application architecture. You can run the web application in a VM, a container instance, an Azure Web App, or an orchestrator. It's the same for the database, it can be a managed service, a database server in a VM. The choice of these two components is independent. Going from Azure Container Instance to AKS does not affect the database services you run and changing the database service from IaaS to PaaS must not harm your application.

And if you add the access control to the equation the division between network, database, and application is clearer as you may not want everyone to manage all resources.
In conclusion, even if the two services are linked, they do not have the same life cycle.

Now that I finished the digression and you know how to design your resource groups, yes you can delete Azure object

 using ARM template.  
There is two modes for ARM template deployment, incremental and complete mode.
The incremental mode is the default one. It doesn't care if a resource in the target resource group in Azure is not present in the template. It will only add/update resources present in the template. 
The complete mode is different. In this mode, the template is the ultimate source of truth. Everything defined in the template will be created or updated in the target resource group, just like in the incremental mode. But every resource in the target resource group not defined in the template will be deleted (except if the parent resource is not deleted, or if the resource group is locked). 

The complete mode is only possible at the root level of a template deployment. You cannot use this mode in a linked template. 
Other points of attention condition and loops. If in your template you use a condition to deploy an object, and if the condition is false, the resource will be deleted with the most recent tools (CLI or PowerShell) and the latest API. 
You should take care of loops. If you use it to create several instances of a resource be sure to have the same number of iteration if not it may end with an unwanted object deletion. 
 
To deploy a template in the incremental mode you have nothing to do as it's the default behavior in both Azure PowerShell module and Azure CLI. For the complete mode, you need to specify the mode.

```powershell 
New-AzResourceGroupDeployment -Mode
``` 

```bash 
az deployment group create –-mode Complete
```