3 Ways To Check If Resource Exists In Azure Bicep
Azure Bicep and ARM templates are designed to be idempotent, this means that running a template multiple times should result in the same end state of the resources.
However, there are still cases when we might want to know during deployment if a particular resource exists, for example, when dealing with Key Vault access policies.
There are multiple ways to check whether a resource exists while deploying an Azure Bicep template. Three approaches described in this post are using resource tags, leveraging Azure PowerShell or CLI scripting, or running a deployment script.
As of May 2022, Azure Bicep does not provide a built-in way to check if a resource exists, however, the approaches described in this post provide a workaround which can be helpful in your use case.
Contents:
- Overview
- Track If Resource Exist Using Tags
- Use Azure PowerShell Or CLI To Check If Resource Exists
- Use Deployment Script To Check If Resource Exists
- Related Posts
- Useful Links
Overview
In this post, we discuss 3 different approaches how to check if a particular resource is already created, for example, it could be previously deployed through our Bicep template or created manually by an operator.
The first approach is to use tags to keep track if our resource exists. A specific tag is set during the first resource deployment, and later we check the tag to understand if resource was already deployed. It is very important to keep the tag value in sync with the resource state.
The second approach leverages Azure PowerShell or Azure CLI to fetch information about resource, in our case, whether it exists or not, and then the value is passed to the Bicep template. It has an advantage that the Bicep code is very simple, but the downside that we need some environment to run the script (usually CI/CD pipeline).
The third approach makes it possible to keep everything within Bicep template(s) by using deployment scripts resource in Azure Resource Manager.
There must be more ways to check if resource exists in Azure Bicep, and this post only contains a few ways which I’m aware of. Please let me know if you have better ways to achieve this.
Track If Resource Exist Using Tags
Any resource in Azure can have tags, a set of key-value pairs where values are arbitrary strings. Users can use tags for whatever purposes they want, but usually tags are used to keep some metadata related to the resources.
The idea here is to use tags of the resource’s container to store information about whether the resource was deployed. Here, the container means a resource group for an individual resource, or a subscription for a resource group.
Keep in mind that this is a workaround and might be not the best way to test whether the resource exists. We simply rely on tags to track state of the resource.
NOTE: Our tag’s value must be consistent with the state of the resource in question, and it is our responsibility to keep them in sync. If the tag is removed or the resource is deleted/created without updating the tag, then this approach will not work properly.
Our solution consists of two files: resource template and parent template, these are described in the following sections.
Resource Template: storage-account.bicep
This is a Bicep file that deploys our resource, in this case a storage account, and sets the tag on the resource group. Here are some notes for the code below:
- Line 3: Parameter
resourceExists
provides information whether resource already exists; the template uses this parameter to decide what to do, for example, whether deploy or not (line 6). - Line 6: Storage account is used as an example of a resource, this could be any other resource or module.
- Line 15: Setting a tag on the resource group in which scope this template is deployed; the tag name is provided through
resourceExistsTagName
parameter.- If
resourceExists == false
: the resource (storage account) is created and the tag is set. - If
resourceExists == true
: the resource already exists so the tag must already be set, this operation sets the same tag with the same value, basically does nothing. - NOTE: Due to the nature of Azure Bicep, all existing tags will be removed and only the tags specified in the template will be set. So, if you want to preserve other tags, you might need to pass existing tags as a parameter and include them in the tags deployment.
- If
- Line 22: The tags are set only after the resource deployment step is completed. If the storage account deployment fails, then the tag is not set.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// =============== storage-account.bicep ===============
param resourceExists bool
param resourceExistsTagName string
resource storageAccount 'Microsoft.Storage/storageAccounts@2021-08-01' = if (!resourceExists) {
name: 'stcontoso'
location: resourceGroup().location
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
}
resource tags 'Microsoft.Resources/tags@2021-04-01' = {
name: 'default'
properties: {
tags: {
'${resourceExistsTagName}': 'true'
}
}
dependsOn: [
storageAccount
]
}
Parent Template: main.bicep
This is a main template which retrieves the tag from the resource group and then deploys our storage-account.bicep as a module while passing the resourceExists
flag.
- Line 3: Target scope of the template is
subscription
(by default, it isresourceGroup
); subscription scope allows us to retrieve the resource group and get its tags. - Line 5: The template assumes that resource group already exists, so we create a symbolic name for it; read more about how to Reference New Or Existing Resource In Azure Bicep.
- Line 10: Checking if the resource group has our tag and whether it is set to true.
- Line 12: Deploying our previous template
resource.bicep
as a module; see Learn Modules In Azure Bicep. Note that we specify the resource group as the scope for the module deployment (line 18).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// =============== main.bicep ===============
targetScope = 'subscription'
resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' existing = {
name: 'rg-contoso'
}
var tagName = 'isResourceDeployed'
var resourceExists = contains(resourceGroup.tags, tagName) && resourceGroup.tags[tagName] == 'true'
module resourceDeployment 'resource.bicep' = {
name: 'resourceDeployment'
params: {
resourceExists: resourceExists
resourceExistsTagName: tagName
}
scope: resourceGroup
}
Use Azure PowerShell Or CLI To Check If Resource Exists
In many cases, we deploy our infrastructure using Azure Bicep template as part of CI/CD pipeline. In case of Azure, we have Azure Pipelines (part of Azure DevOps offering) which are commonly used to create and manage deployment pipelines, releases, etc.
Every CI/CD pipeline allows running scripts in some scripting language such as Bash, PowerShell, or Python. This is a fundamental capability of any deployment pipeline.
We will use Azure PowerShell or Azure CLI to check if the resource exists and pass this information to the Bicep template during deployment.
First, we define a Bicep template, it accepts a boolean parameter which indicates whether the resource already exists or not. Next, we provide examples of how to check resource existence using Azure PowerShell and Azure CLI.
Here are high-level steps how to do it in Azure Pipelines:
- Execute Azure PowerShell or Azure CLI script to find out if the resource exists.
- At the end of the script, set pipeline variable to hold the information if resource exists, see How To Set Azure Pipeline Variable In Scripts.
- Use the pipeline variable from the previous step to pass value for the parameter
resourceExists
in our Bicep template while deploying resources, see details in Deploy Azure Bicep In YAML and Classic Release Pipelines (CI/CD).
Bicep Template
The Bicep file accepts a boolean parameter resourceExists
and acts based on this information. In our simple example, the storage account is deployed if it doesn’t exist yet.
// =============== storage-account.bicep ===============
param resourceExists bool
// Some business logic based on the information whether resource already exists
resource storageAccount 'Microsoft.Storage/storageAccounts@2021-08-01' = if (!resourceExists) {
name: 'stcontoso'
location: resourceGroup().location
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
}
Azure PowerShell Script
There are multiple ways in Azure PowerShell to check if a particular resource exists. To begin with, each Azure resource has its own module with resource-specific commands.
For example, Az.Storage module contains Get-AzStorageAccount function which can be used to check if a particular storage account exists. Note that we specify -ErrorAction SilentlyContinue
so that the function returns null
if storage account cannot be found.
$StorageAccount = Get-AzStorageAccount -Name stcontoso -ResourceGroupName rg-contoso -ErrorAction SilentlyContinue
# ResourceExists variable holds boolean value indicating whether storage account exists
$ResourceExists = $null -eq $StorageAccount
Write-Host $ResourceExists # Outputs True or False
Alternatively, one can use the generic Get-AzResource function instead which allows retrieving any resource by name, type, etc. Here’s a simple example similar to the previous one.
$StorageAccount = Get-AzResource -ResourceName stcontoso -ResourceType 'Microsoft.Storage/storageAccounts' -ResourceGroupName rg-contoso -ErrorAction SilentlyContinue
$ResourceExists = $null -eq $StorageAccount
Write-Host $ResourceExists
Azure CLI Script
Azure CLI is another powerful way to interact with and manage Azure resources. Personally, I usually use Azure PowerShell when working with resources in command line, but Azure CLI is also a great option.
To check if resource exists, we can come up with something like the following in Bash for a storage account using az storage account show. Note that 2>nul
suppresses stderr so that no error is thrown when resource cannot be not found.
NOTE: Azure CLI can be used within both PowerShell and Bash, here we chose Bash since the previous example already covers PowerShell case.
storage_account=$(az storage account show --name stcontoso --resource-group rg-contoso 2>nul)
resource_exists=$(if [ -z "$storage_account" ]; then echo 0; else echo 1; fi)
echo $resource_exists
Use Deployment Script To Check If Resource Exists
In the previous section, we discussed how to use Azure CLI or PowerShell as one of the steps in the CI/CD pipeline to check resource existence before deploying a Bicep template.
But what if we want to keep all logic within an Azure Bicep template? Without using any additional steps in the deployment pipeline. Here’s where deployment scripts might come handy.
Deployment scripts help extend Azure Bicep functionality by allowing users to perform custom steps through Azure PowerShell or Azure CLI commands.
Now, we can combine deployment scripts with the knowledge from the previous section about PowerShell and CLI. In this post, we will not dive into details but provide high-level steps to help you get started:
- Define a Microsoft.Resources/deploymentScripts resource in your Bicep template, for example,
deploymentScriptResource
.- Set up necessary authentication and authorization so that script can access information about resources in Azure.
- Make
forceUpdateTag
unique for each deployment, for example, usingutcNow
, so that the script is run every time. - Run Azure CLI or PowerShell commands to check whether resource exists and return this information from the deployment script. To return a value, in PowerShell use special
$DeploymentScriptOutputs
variable:$DeploymentScriptOutputs = @{} $DeploymentScriptOutputs['resourceExists'] = $ResourceExists
- In the Bicep template, retrieve the value from the outputs:
deploymentScriptResource.properties.outputs.resourceExists
- Now, you can use the
resourceExists
value in your template’s logic. You might also want to leverage Modules In Azure Bicep to keep Bicep code clean and maintainable.
The setup with deployment scripts is usually more involved compared to other approaches we discussed in this post. However, deployment scripts is a powerful tool which might come in handy in many other use cases thanks to its flexibility. I’d recommend reading Use deployment scripts in Bicep to learn more about it.
Related Posts
- 5 Ways To Deploy Bicep File With Parameters - Azure DevOps, PowerShell, CLI, Portal, Cloud Shell
- Parameters In Azure Bicep - Ultimate Guide With Examples
- Variables In Azure Bicep - From Basics To Advanced
- Learn Modules In Azure Bicep - Basics To Advanced, How It Works, Nested Modules, Outputs, Scopes
- Reference New Or Existing Resource In Azure Bicep
- Child Resources In Azure Bicep - 3 Ways To Declare, Loops, Conditions
- Key Vault & Secrets Management With Azure Bicep - Create, Reference, Output Examples
Useful Links
- Tag resources, resource groups, and subscriptions | Microsoft Docs
- What is Azure PowerShell | Microsoft Docs
- What is the Azure CLI? | Microsoft Docs
- Use deployment scripts in Bicep | Microsoft Docs
- How to check the resource exists in the arm template - Stack Overflow
- Check if resource exists · Issue #4023 · Azure/bicep (github.com)