The Anatomy of a Bicep Template
Stephen Tulp
December 5, 2023
6 minutes to read
Introduction
In this blog post, we will go over the various elements that make up a Bicep file, this will help understand the structure, syntax and properties of a Bicep template.
Bicep Template Elements
Bicep is a declarative language, which means the elements can appear in any order. Unlike imperative languages, the order of elements doesn’t affect how the deployment is processed.
A typical Bicep file has the following elements, User-Defined Data Types and User-Defined Functions have been excluded and we will address these later in the month.
metadata <metadata-name> = ANY
targetScope = '<scope>'
@<decorator>(<argument>)
param <parameter-name> <parameter-data-type> = <default-value>
var <variable-name> = <variable-value>
resource <resource-symbolic-name> '<resource-type>@<api-version>' = {
<resource-properties>
}
module <module-symbolic-name> '<path-to-file>' = {
name: '<linked-deployment-name>'
params: {
<parameter-names-and-values>
}
}
output <output-name> <output-data-type> = <output-value>
Metadata
Metadata in Bicep is an untyped value that can be included in a Bicep file. It allows supplementary information about your Bicep files, including details like its name, description and author.
metadata name = 'Azure Landing Zone Vending Machine'
metadata description = 'Creates a repeatable and scalable Azure Landing Zone deployment using Bicep'
metadata author = 'Stephen Tulp - Insight'
Target scope
By default, the target scope is set to resourceGroup
. If you’re deploying at the resource group level it is optional.
The allowed values are:
- resourceGroup - default value, used for resource group deployments.
- subscription - used for subscription deployments.
- managementGroup - used for management group deployments.
- tenant - used for tenant deployments.
targetScope = 'managementGroup'
Parameters
Parameters are used for values that need to change and you can define a default value for the parameter that is used if no value is provided during deployment.
For example, virtualNetworkEnabled
default value is set to true but could be overwritten in a template parameter file, while envPrefix
will be required in a template parameter file.
param virtualNetworkEnabled bool = true
param envPrefix string
Parameter decorators
You can add one or more decorators for each parameter. These decorators describe the parameter and define constraints for the values that are passed in. The following example shows one decorator for envPrefix
and we have updated it to use a default value.
@allowed([
'dev'
'test'
'prod'
])
param envPrefix string = 'dev'
Variables
You can make your Bicep file more readable by encapsulating complex expressions in a variable. This is used for concatenating names of resources and resource groups for example.
var resourceGroups = {
network: '${argPrefix}-network'
shared: '${argPrefix}-shared'
}
Apply this variable wherever you need the complex expression.
resource resourceGroupNetwork 'Microsoft.Resources/resourceGroups@2021-04-01' = {
name: resourceGroups.network
}
resource resourceGroupShared 'Microsoft.Resources/resourceGroups@2021-04-01' = {
name: resourceGroups.shared
}
Resources
Use the resource
keyword to define a resource to deploy, this includes a symbolic name for the resource. The symbolic name can be used in other parts of the Bicep file to get a value from the resource.
The resource declaration includes the resource type and API version within the body of the resource declaration and includes properties that are specific to the resource type.
resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = {
name: resourceGroupName
location: location
tags: tags
}
Modules
Modules enable the reuse code from a Bicep file in other Bicep files. In the module declaration, you link to the file to reuse. When you deploy the Bicep file, the resources in the module are also deployed.
module resourceGroup '../resourceGroup/resourceGroup.bicep' = {
name: 'resourceGroup-${guid(deployment().name)}'
scope: subscription(subscriptionId)
params: {
resourceGroupName: resourceGroups.network
location: location
tags: tags
}
}
Outputs
Use outputs to return values from the deployment. Typically, you return a value from a deployed resource when you need to reuse that value for another operation.
output resourceGroupShared string = resourceGroupShared.name
output resourceGroupNetwork string = resourceGroupNetwork.name
Comments
Use //
for single-line comments or /* ... */
for multi-line comments
The following example shows a single-line comment.
// Resource: Resource Group
resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = {
...
}
Conclusion
The following example shows an implementation of all these elements outlined above. Later in the month, we will go into more detail to include other pieces that will make up the Landing Zone.
metadata name = 'Resource Group Bicep Template'
metadata description = 'Resource Group Example'
metadata author = 'Stephen Tulp - Insight'
targetScope = 'subscription'
@description('The Azure Region to deploy the resources into.')
param location string = deployment().location
@description('An object of Tag key & value pairs to be appended to a Subscription.')
param tags object = {
applicationName: 'SAP Landing Zone'
owner: 'Platform Team'
criticality: 'Tier1'
costCenter: '1234'
contactEmail: 'test@test.com'
dataClassification: 'Internal'
}
var resourceGroups = {
network: 'arg-syd-sap-prd-network'
shared: 'arg-syd-sap-prd-shared'
}
// Module: Resource Group (Shared)
module resourceGroupShared 'resource-group/main.bicep' = {
name: 'resourceGroupShared-${guid(deployment().name)}'
params: {
name: resourceGroups.shared
location: location
tags: tags
}
}
// Resource: Resource Group (Network)
resource resourceGroupNetwork 'Microsoft.Resources/resourceGroups@2021-04-01' = {
name: resourceGroups.network
location: location
tags: tags
}
output resourceGroupShared string = resourceGroupShared.name
output resourceGroupNetwork string = resourceGroupNetwork.name
The above example is available in the Insight Bicep Advent Calendar GitHub Repository
Further Reading
Some further reading on the topics covered in this post: