Contents
In today’s post, we’ll take a look on some tips and tricks about the use of Azure Bicep and how you can speed up your daily Bicep writing even further.
If you haven’t heard of Azure Bicep till now, Bicep is a domain-specific language (DSL) that uses declarative syntax to deploy Azure resources. In other words: it’s the language we use to declare our Azure resources and their configuration, before we hand it over to the Azure Resource Manager (ARM) to take over the deployment. You might have heard of ARM templates, which is the underlying framework based on JSON.
Important to know: Azure Resource Manager only speaks ARM (JSON), that’s why you see inputs and outputs from your Deployments in JSON in your Azure Portal. When you deploy a Bicep File, it’ll always be compiled into an ARM file before further processed by the Azure Resource Manager. If you want to know more about Azure Bicep and ARM, head to the end of the blog post to find some useful resources.
Tip #1: Use modules
The goal of using modules is to minimize duplicated code as well as standardization. A Bicep module is simply a collection of one or more resources in a separate file, which you can then call from another Bicep file.
Let’s assume you plan to deploy an Azure Key Vault including a Private Endpoint, which in turn are the following Bicep resources (assuming you already have a vNet and Private DNS Zone in place):
- Azure Key Vault (Microsoft.KeyVault/vaults)
- Private Endpoint (Microsoft.Network/privateEndpoints)
-
Private DNS Zone Groups (Microsoft.Network/privateEndpoints/privateDnsZoneGroups)
You probably don’t want to write down the same three resources each time you deploy a Key Vault. The solution: Put all the needed components into one module, while using parameters for values that change, e.g. the Key Vault name or location. You can then call this module file in your main Bicep file while solely providing a few parameters and very little code.
Where do I store my modules?
As mentioned before, modules are separate *.bicep files, therefore you could store them in a separate folder and at the same time use Git to version not only your code but also your modules. While this is a good start, I’ll recommend that you provide your modules in a more centralized location, e.g. an Azure Container Registry. Check this blog post from Michael to see how it’s done: How to build a bicep module library with proper versioning (miru.ch)
Here you can find further information on Bicep modules: Bicep modules
Tip #2 – Use the new parameters files
In general, use parameters and variables to simplify your Bicep files, as you would with PowerShell (hopefully 😋). While it’s possible to declare parameters inside your main Bicep file next to your resources or modules, it’s sometimes useful to outsource parameters into a separate file, e.g. if you want to differentiate environments based on different parameter files while using the same code.
Until recently, the declaration of parameters was only supported in JSON format and therefore harder to maintain. You can now enjoy the same Bicep language for parameter files including linting as well. Make sure you file extension is .bicepparam
and you have the following minimum versions installed:
- Bicep CLI version 0.18.4 or newer (How to update)
- Azure CLI version 2.47.0 or newer (How to update)
Here’s a quick example of the new Bicep parameter declaration:
using 'main.bicep' param location string = 'switzerlandnorth' param keyVaultName string = 'kva01' param accessPolicies = []
More information about the new parameters file: Create parameters files for Bicep deployment
Tip #3: Configure your Bicep environment using bicepconfig.json
The bicepconfig.json
file enables you to modify and customize Bicep’s behaviour, e.g. throw an error if there are any unused variables. If the file is not present, Bicep will use default values.
To customize the values, make sure to create the bicepconfig.json
file in the same directory where your Bicep files are stored. It is possible to have multiple bicepconfig.json
files in different directories, while the configuration file closest to the Bicep file in the directory hierarchy will be used.
My favourite configs are:
- Set credential precedence for linting like reading modules in an Azure Container Registry
Module setting for Bicep config - Configure linter settings for error handling
Linter settings for Bicep config - Set aliases for your Azure Container Registry paths for better usability and readability
Module setting for Bicep config
Get started: Create the config file in Visual Studio Code
Tip #4: Quickly insert existing resources in your Bicep code
Sometimes when writing Bicep code, you probably first want to get to know the resources and deploy it using the clicky Azure Portal first. After that you somehow need to transform your newly created resources into code. There are some possibilities to do that, next to writing all by hand.
Insert a single resource using VSCode
If you’re using VSCode and the Bicep Extension, there is a built-in feature to insert an existing resource as Bicep code into an existing file. Here’s how you do that:
- Locate your resource in the Azure portal and copy the resource id
- Open VSCode and a random .bicep file
- Open the command palette (Ctrl + Shift + p) and search for Bicep: Insert Resource…
- Choose your Bicep file and insert the resource id you copied in step 1
- Et voilà: Your Bicep resource is added into your Bicep file
Export an entire resource group
If you have multiple Azure resources or even resource groups, you probably want to export all at once. This is possible by using Azure CLI’s az group export
command:
# Export resource group and it's resources to ARM templates az group export --name myResourceGroup > mainExport.json # Decompile ARM template to Bicep az bicep decompile --file mainExport.json
The conversion isn’t always at it’s best and mostly brings some errors with it. Although, it’s usually a good starting point, even it it’s just for comparing some settings or values.
More information: Export template in Azure CLI
Tip #5: Use loops and functions
Bicep is not only a new DSL, it also brings functions to further simplify deployments, like looping through an array of parameters and create resources for each – or if/else statements, e.g. where if the parameter env
is set to prod
, the value is X
– else it’s Y
.
My favourite functions are:
- If/else
Conditional deployment with Bicep - Iterative loops
Iterative loops in Bicep - CIDR function
Bicep functions – CIDR - String conversion functions
Bicep functions – string
Resources
- Azure Resource Manager overview – Azure Resource Manager | Microsoft Learn
- Bicep language for deploying Azure resources – Azure Resource Manager | Microsoft Learn
- Templates overview – Azure Resource Manager | Microsoft Learn
- Compare syntax for Azure Resource Manager templates in JSON and Bicep – Azure Resource Manager | Microsoft Learn