Azure Bicep output and accessing nested child resources

In this post, I am going to write about what an Azure Bicep output is and how you can work with output, and how you can access nested child resources in Azure Bicep.

Using outputs can be useful to retrieve specific resource or module properties (for example resourceIds or names) and pass these to input parameters for resources or modules.

Output definition

Let’s take a look at what an output is, what it can do and how you define one and use it.

What is it?

An output is a value that is used to return values from the deployed resources. When an output is defined, it always has a data type. This data type can be: string, array, bool, int, or an object

What can you do with it?

Output can be used to pass through return values from a resource or module to another resource or model. You can compare it to a return value from a method in programming languages.

Virtual Network default outputs

In the example above, you see the list of outputs the resRemoveVirtualNetwork (virtual network) has. These values are default outputs that the virtual network resource has, and these outputs can be used in other modules or resources.

Define an output in Bicep

Azure Bicep provides resources with default properties. In the last example, you saw an example for a virtual network, which has properties like name, id or apiVersion, and so on. These are the outputs for the virtual network resources. When you write your own Bicep modules and, you want that module to have certain outputs, you have to define these yourself.

The definition of output is as follows:

output <name> <data-type> = <value>

Let’s work with an example. You need to create a module to create network interface cards (NIC) for virtual machines. You also add a subnet and a network security group (NSG). In this module, you define the following resources:

  • Virtual Network (existing)
  • Network Security Group
  • Network Interface Card

You want to access the properties from outside the module, so you have to define the output of the network interface resourceId because you want to use this id for your virtual machine. In your module, define the resources and add the outputs:

param parVnetObject object
param parNsgObject object
param parNicObject object
resource resVirtualNetwork 'Microsoft.Network/virtualNetworks@2021-08-01' existing = {
name: parVnetObject.name
}
resource resNetworkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2021-08-01' = {
name: parNsgObject.Name
properties: {
securityRules: parNsgObject.securityRules
}
}
resource resNic 'Microsoft.Network/networkInterfaces@2021-08-01' = {
name: parNicObject.name
properties:{
ipConfigurations: [
{
name: 'ipconfig1'
properties: {
subnet: resVirtualNetwork.properties.subnets[0]
}
}
]
networkSecurityGroup: {
id: resNetworkSecurityGroup.id
}
}
}
output outNicId string = resNic.id

Now when you reference this module in a Bicep file, you can access the defined output. Let’s define the module and reference the exposed output outNicId to the network interface id for a virtual machine:

module modNetworking 'networking.bicep' = {
name: 'deploy-network-components'
params: {
parNicObject: {
name: 'my-nic'
}
parNsgObject: {
name: 'my-nsg'
securityRules: []
}
parVnetObject: {
name: 'my-existing-vnet'
}
}
}
resource resMyVm 'Microsoft.Compute/virtualMachines@2021-11-01' = {
name: 'my-vm'
properties: {
networkProfile: {
networkInterfaces: [
{
id: modNetworking.outputs.outNicId
}
]
}
}
}

Create a module called modNetworking and create a compute resource called resMyVm. The virtual machine resource requests a network interface id for the network interface card. By using the function accessor using the . (dot) you can access the output you defined in the module:

Result accessing output from modNetworking module

The Bicep extension for Visual Studio Code gives access to autocomplete functions.

Access a nested resource using :: the child accessor operator

To access a nested child resource, there is a different approach. The problem with accessing a child resource is that you can’t reference the symbolic name of the child directly. You have to access the child through the parent. This is where the :: operator comes to play.

Let’s take a look at the following example:

resource resMyExistingVnet 'Microsoft.Network/virtualNetworks@2021-08-01' = {
name: 'my-exiting-virtual-network-name'
resource resMyFirstSubnet 'subnets' existing = {
name: 'my-existing-first-subnet'
}
resource resMyOtherSubnet 'subnets' existing = {
name: 'my-other-subnet'
}
}

In this example, you see an existing virtual network with two dependency subnets. With Azure Bicep, you can define a parent and child construction to create child resources using the parent resource type.

If you want to get the resourceId of the child resMyOtherSubnet you cannot get this the regular way by accessing the outputs of the parent. To get the resourceId of resMyOtherSubnet you have to use the operator :: . The :: operator allows accessing a child resource within its parent. You have to use this with the symbolic name of the parent and child resource.

A nested resource declaration must appear at the top level of syntax of the parent resource.

Accessing a child resource using the parent
resource resMyExistingVnet 'Microsoft.Network/virtualNetworks@2021-08-01' existing = {
name: 'my-exiting-virtual-network-name'
resource resMyFirstSubnet 'subnets' existing = {
name: 'my-existing-first-subnet'
}
resource resMyOtherSubnet 'subnets' existing = {
name: 'my-other-subnet'
}
}
output outFirstSubnet string = resMyExistingVnet::resMyFirstSubnet.id
output outOtherSubnet string = resMyExistingVnet::resMyOtherSubnet.id
output outVnetId string = resMyExistingVnet.id

Conclusion

In this blog, you read how you can work with outputs and how you can access outputs of nested child resources with a special operator. Outputs from modules are not limited to resourceIds, this can also be a name of a resource or manipulated values. You can also work with conditional outputs, dynamic outputs and use these outputs in scripts.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s