Bicep
Introduction
Section titled “Introduction”Bicep is a domain-specific language for declaring Azure resources. It is the recommended authoring format for Azure Resource Manager: the Azure CLI transpiles Bicep to ARM JSON and submits that to Resource Manager, so a Bicep deployment is an ARM deployment underneath.
Bicep needs no special configuration for the emulator.
Once lstk az start-interception redirects the Azure CLI to the emulator, az deployment group create deploys Bicep files to the emulator.
Most of the Azure samples provide a Bicep deployment, next to Azure CLI scripts and a Terraform configuration for the same stack.
Getting started
Section titled “Getting started”This guide shows you how to deploy a storage account and a blob container with a Bicep file and a parameter file, and how to inspect the deployment.
Prerequisites
Section titled “Prerequisites”- The Azure CLI with the Bicep CLI. Run
az bicep install, or let the Azure CLI install Bicep the first time that you use it. - LocalStack for Azure and the
lstkCLI, with the emulator running. For more information, see Installation.
Redirect the az commands to the emulator, and check that the Bicep CLI is installed:
lstk az start-interceptionaz bicep versionlstk az start-interception changes your global Azure CLI configuration to use the LocalStack cloud until you run lstk az stop-interception.
For more information, see Azure CLI.
Write a template
Section titled “Write a template”Create a Bicep file that declares a storage account, its blob service, and a blob container, and returns the resource ID of the storage account as an output:
@minLength(3)param storageAccountName string
param location string = resourceGroup().location
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = { name: storageAccountName location: location sku: { name: 'Standard_LRS' } kind: 'StorageV2'}
resource blobService 'Microsoft.Storage/storageAccounts/blobServices@2023-01-01' = { parent: storageAccount name: 'default'}
resource container 'Microsoft.Storage/storageAccounts/blobServices/containers@2023-01-01' = { parent: blobService name: 'activities' properties: { publicAccess: 'None' }}
output storageAccountId string = storageAccount.idA parameter file keeps the values out of the template:
using 'main.bicep'
param storageAccountName = 'lsdocsbicep001'Create a resource group
Section titled “Create a resource group”Create the resource group that the template deploys to:
az group create --name MyResourceGroup --location westeuropeCheck the template
Section titled “Check the template”az bicep build transpiles the Bicep file to ARM JSON without contacting Azure or the emulator, which makes it a fast syntax and type check:
az bicep build --file main.bicep --stdoutaz deployment group validate also runs against the emulator, but the emulator doesn’t validate the template: it returns an empty result for every request.
az deployment group validate \ --resource-group MyResourceGroup \ --template-file main.bicep \ --parameters main.bicepparam{ "error": null, "id": null, "name": null, "properties": null, "type": null}Before it calls the emulator, the Azure CLI compiles the Bicep file and checks that every parameter has a value.
A zero exit code therefore rules out syntax errors and missing parameters, but not the values that Azure rejects during validation, such as a parameter value that violates a @minLength constraint.
Deploy the template
Section titled “Deploy the template”Deploy the Bicep file with the parameter file:
az deployment group create \ --resource-group MyResourceGroup \ --name my-deployment \ --template-file main.bicep \ --parameters main.bicepparam \ --query "{state:properties.provisioningState, outputs:properties.outputs}"The --query argument reduces the deployment to its provisioning state and the template outputs:
{ "outputs": { "storageAccountId": { "type": "String", "value": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MyResourceGroup/providers/Microsoft.Storage/storageAccounts/lsdocsbicep001" } }, "state": "Succeeded"}Inspect the deployment
Section titled “Inspect the deployment”List the resources of the resource group:
az resource list --resource-group MyResourceGroup --output tableName ResourceGroup Location Type Status-------------- --------------- ---------- --------------------------------- ---------lsdocsbicep001 MyResourceGroup westeurope Microsoft.Storage/storageAccounts SucceededThe list contains only top-level resources: the blob service and the container are child resources of the storage account.
When a deployment reports Failed, list the deployment operations to see which resource failed and why, rather than reading the whole response:
az deployment operation group list \ --resource-group MyResourceGroup --name my-deployment \ --query "[].{resource:properties.targetResource.resourceType, \ state:properties.provisioningState, \ message:properties.statusMessage.error.message}" -o tableClean up
Section titled “Clean up”Delete the resource group and the resources that it contains:
az group delete --name MyResourceGroup --yesTo make the az commands target Azure again, stop the interception:
lstk az stop-interceptionModules
Section titled “Modules”Bicep modules work as they do against Azure.
The Function App with Service Bus sample splits its deployment into modules for the virtual network and its NAT gateway, the storage account, Service Bus, the private endpoints and private DNS zones, Log Analytics and Application Insights, and the Function App.
The modules pass values to each other through their outputs.
For example, each private DNS zone links to the virtual network that the network module creates:
module blobStoragePrivateDnsZone 'modules/private-dns-zone.bicep' = { name: 'blobStoragePrivateDnsZone' params: { name: 'privatelink.blob.core.windows.net' vnetId: network.outputs.virtualNetworkId tags: tags }}Examples
Section titled “Examples”The following samples deploy their stack with Bicep, and also provide Azure CLI scripts and a Terraform configuration for the same stack:
- Container Instances with Blob Storage and Key Vault
- Function App with Service Bus over private endpoints
- Function App with storage triggers and bindings
- Web App with PostgreSQL Flexible Server
The AKS cluster with tags, labels and taints tutorial deploys a full AKS stack with Bicep.
Limitations
Section titled “Limitations”az deployment group what-ifisn’t supported: the emulator doesn’t implement the What-If operation, so the command fails.az deployment group validatedoesn’t validate the template. For more information, see Check the template.- The emulator doesn’t delete resources in Complete mode. For more information, see Deployment modes.
For the other limitations of the Resource Manager emulator, see Resource Manager.
- Resource types with a global name scope, such as storage accounts, key vaults, and container registries, collide across deployments as they do in Azure. Give each stack a distinct prefix or suffix, or reset the emulator state between runs.
- Creating a key vault can take up to two minutes on the emulator. Allow for that in pipeline timeouts.
- A template that references a container image expects the image to exist in the registry. The samples build and push the image before they deploy the template, and a template-only deployment leaves the container resource in a failed state.