Posts Advanced Concepts in Azure Bicep Syntax
Post
Cancel

Advanced Concepts in Azure Bicep Syntax

Advanced Concepts in Azure Bicep Syntax

As you continue to work with Azure Bicep, you’ll likely discover even more benefits and use cases for this powerful tool. And you will also discover the need for more advanced concepts and features in your templates. We are going to cover some of these concepts in this article.

By adopting Bicep for your infrastructure as code needs, you can streamline your deployment process, reduce errors and complexity, and better manage your cloud resources on Azure.

Azure Bicep Blog series:

To learn more about Azure Bicep, you can check out my other blog posts in this series:

#Title
1Simplify Your Resource Deployments With Azure Bicep
2Key Concepts in Azure Bicep Syntax
3Advanced Concepts in Azure Bicep Syntax (This article)
4Using External Configuration File with Azure Bicep

Loops and Conditions

Azure Bicep provides constructs for loops and conditions, which can be used to iterate over lists or perform conditional logic. Loops are defined using the for keyword, and conditions are defined using the if keyword. Here’s an example that uses a loop to create multiple virtual machines:

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
26
27
28
29
30
31
32
33
34
resource vms 'Microsoft.Compute/virtualMachines@2021-03-01' = [
  for i in range(1, 4): {
    name: 'vm-${i}'
    location: 'westus2'
    properties: {
      hardwareProfile: {
        vmSize: 'Standard_DS1_v2'
      }
      storageProfile: {
        imageReference: {
          publisher: 'Canonical'
          offer: 'UbuntuServer'
          sku: '20.04-LTS'
          version: 'latest'
        }
        osDisk: {
          createOption: 'fromImage'
        }
      }
      osProfile: {
        computerName: 'vm-${i}'
        adminUsername: 'azureuser'
        adminPassword: '<your-password-here>'
      }
      networkProfile: {
        networkInterfaces: [
          {
            id: nic.id
          }
        ]
      }
    }
  }
]

This resource uses a loop to create three virtual machine resources, with names vm-1, vm-2, and vm-3. The loop iterates over a range of values from 1 to 4, and uses string interpolation to create the VM names.

Conditions can be used to selectively include or exclude resources or properties based on runtime conditions. Here’s an example that uses a condition to include a data disk only if a parameter is 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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
param attachDataDisk bool = false

resource vm 'Microsoft.Compute/virtualMachines@2021-03-01' = {
  name: 'my-vm'
  location: 'westus2'
  properties: {
    hardwareProfile: {
      vmSize: 'Standard_DS1_v2'
    }
    storageProfile: {
      imageReference: {
        publisher: 'Canonical'
        offer: 'UbuntuServer'
        sku: '20.04-LTS'
        version: 'latest'
      }
      osDisk: {
        createOption: 'fromImage'
      }
      # Include a data disk if the attachDataDisk parameter is true
      dataDisks: if (attachDataDisk) [
        {
          lun: 0
          createOption: 'empty'
          diskSizeGB: 128
        }
      ]
    }
    osProfile: {
      computerName: 'my-vm'
      adminUsername: 'azureuser'
      adminPassword: '<your-password-here>'
    }
    networkProfile: {
      networkInterfaces: [
        {
          id: nic.id
        }
      ]
    }
  }
}

This resource uses a condition to include a data disk in the VM’s storage profile only if the attachDataDisk parameter is set to true. The if keyword is used to conditionally include the dataDisks property, which is set to an empty list if the parameter is false.


Function and Expression Syntax

Azure Bicep provides a number of built-in functions and expressions that can be used to manipulate values and perform calculations. Functions are invoked using a function name followed by parentheses (), and expressions are enclosed in square brackets []. Here are a few examples:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Get the current UTC date and time as a string
var timestamp = utcnow().toUpper().replace('-', '').replace

# Get the length of a string
var length = length('hello')

# Join two strings with a separator
var joined = join('-', ['hello', 'world'])

# Concatenate two lists
var concatenated = concat([1, 2, 3], [4, 5, 6])

# Multiply two numbers
var product = 3 * 4

# Calculate a modulus
var remainder = 10 % 3

# Get the value of a property using a string
var value = resourceGroup().location

In addition to these built-in functions and expressions, Azure Bicep also supports user-defined functions, which can be defined using the function keyword. Here’s an example:

1
2
3
4
5
function addNumbers(a: int, b: int) => int {
  return a + b
}

output sum int = addNumbers(3, 4)

This code defines a user-defined function called addNumbers that takes two integer parameters and returns their sum. The output keyword is used to call the function and assign the result to an output variable.


Modules

Azure Bicep supports modularization, which allows you to organize your code into reusable modules. A module is a collection of resources, parameters, variables, and outputs that can be packaged and shared independently. Modules can be defined in separate Bicep files and referenced using the module keyword. Here’s an example:

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
26
27
28
29
30
31
32
33
34
35
36
37
// Virtual machine module

param vmName string
param location string
param vmSize string
param imageReference object
param nicId string
param adminUsername string
param adminPassword string

resource vm 'Microsoft.Compute/virtualMachines@2021-03-01' = {
  name: vmName
  location: location
  properties: {
    hardwareProfile: {
      vmSize: vmSize
    }
    storageProfile: {
      imageReference: imageReference
      osDisk: {
        createOption: 'fromImage'
      }
    }
    osProfile: {
      computerName: vmName
      adminUsername: adminUsername
      adminPassword: adminPassword
    }
    networkProfile: {
      networkInterfaces: [
        {
          id: nicId
        }
      ]
    }
  }
}

This code defines a virtual machine module that takes several parameters and creates a virtual machine resource. The module keyword can be used to reference this module from another Bicep file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Main template file

module vm 'vm.bicep' = {
  name: 'my-vm'
  params: {
    vmName: 'my-vm'
    location: 'westus2'
    vmSize: 'Standard_DS1_v2'
    imageReference: {
      publisher: 'Canonical'
      offer: 'UbuntuServer'
      sku: '20.04-LTS'
      version: 'latest'
    }
    nicId: nic.id
    adminUsername: 'azureuser'
    adminPassword: '<your-password-here>'
  }
}

This code references the virtual machine module from a main template file and provides values for its parameters.


External References

Azure Bicep also supports external references, which allow you to include resources that are defined in other Bicep or ARM template files. External references are defined using the resource keyword and can be used to reference resources from other resource groups, subscriptions, or even other Azure accounts. Here’s an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
resource extNic 'Microsoft.Network/networkInterfaces@2021-02-01' = {
    name: 'my-ext-nic'
    location: 'eastus'
    properties: {
        ipConfigurations: [
            {
            name:
            properties: {
                subnet: {
                    id: '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/virtualNetworks/{vnetName}/subnets/{subnetName}'
                }
                publicIpAddress: {
                    id: '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/publicIpAddresses/{publicIpName}'
                }
            }
            }
        ]
    }
}

This code defines an external network interface resource that references a subnet and a public IP address that are defined in another Bicep or ARM template file.

To continue learning about Azure Bicep, check out the following article: Using External Configuration File with Azure Bicep

I hope this was helpful.

Vukasin Terzic

Updated Feb 23, 2023 2023-02-23T21:23:26+01:00
This post is licensed under CC BY 4.0