Outputs in Bicep
This article describes how to define output values in a Bicep file. You use outputs when you need to return values from the deployed resources. You're limited to 64 outputs in a Bicep file. For more information, see Template limits.
Define outputs
The syntax for defining an output value is:
output <name> <data-type or type-expression> = <value>
An output can have the same name as a parameter, variable, module, or resource. Each output value must resolve to one of the data types, or user-defined data type expression.
The following example shows how to return a property from a deployed resource. In the example, publicIP
is the symbolic name for a public IP address that is deployed in the Bicep file. The output value gets the fully qualified domain name for the public IP address.
output hostname string = publicIP.properties.dnsSettings.fqdn
The next example shows how to return outputs of different types.
output stringOutput string = deployment().name
output integerOutput int = length(environment().authentication.audiences)
output booleanOutput bool = contains(deployment().name, 'demo')
output arrayOutput array = environment().authentication.audiences
output objectOutput object = subscription()
If you need to output a property that has a hyphen in the name, use brackets around the name instead of dot notation. For example, use ['property-name']
instead of .property-name
.
var user = {
'user-name': 'Test Person'
}
output stringOutput string = user['user-name']
The following example shows how to use type expression:
param foo 'a' | 'b' = 'a'
output out 'a' | 'b' = foo
For more information, see User-defined data types.
Use decorators
Decorators are written in the format @expression
and are placed above output declarations. The following table shows the available decorators for outputs.
Decorator | Apply to | Argument | Description |
---|---|---|---|
description | all | string | Provide descriptions for the output. |
discriminator | object | string | Use this decorator to ensure the correct subclass is identified and managed. For more information, see Custom-tagged union data type. |
maxLength | array, string | int | The maximum length for string and array outputs. The value is inclusive. |
maxValue | int | int | The maximum value for the integer output. This value is inclusive. |
metadata | all | object | Custom properties to apply to the output. Can include a description property that is equivalent to the description decorator. |
minLength | array, string | int | The minimum length for string and array outputs. The value is inclusive. |
minValue | int | int | The minimum value for the integer output. This value is inclusive. |
sealed | object | none | Elevate BCP089 from a warning to an error when a property name of a use-define data type is likely a typo. For more information, see Elevate error level. |
Decorators are in the sys namespace. If you need to differentiate a decorator from another item with the same name, preface the decorator with sys
. For example, if your Bicep file includes a parameter named description
, you must add the sys namespace when using the description decorator.
@sys.description('The name of the instance.')
param name string
@sys.description('The description of the instance to display.')
param description string
Description
To add explanation, add a description to output declarations. For example:
@description('Conditionally output the endpoint.')
output endpoint string = deployStorage ? myStorageAccount.properties.primaryEndpoints.blob : ''
Markdown-formatted text can be used for the description text.
Discriminator
See Custom-tagged union data type.
Integer constraints
You can set minimum and maximum values for integer outputs. You can set one or both constraints.
var thisMonth = 3
@minValue(1)
@maxValue(12)
output month int = thisMonth
Length constraints
You can specify minimum and maximum lengths for string and array outputs. You can set one or both constraints. For strings, the length indicates the number of characters. For arrays, the length indicates the number of items in the array.
The following example declares two outputs. One output is for a storage account name that must have 3-24 characters. The other output is an array that must have from 1-5 items.
var accountName = uniqueString(resourceGroup().id)
var appNames = [
'SyncSphere'
'DataWhiz'
'FlowMatrix'
]
@minLength(3)
@maxLength(24)
output storageAccountName string = accountName
@minLength(1)
@maxLength(5)
output applicationNames array = appNames
Metadata
If you have custom properties that you want to apply to an output, add a metadata decorator. Within the metadata, define an object with the custom names and values. The object you define for the metadata can contain properties of any name and type.
You might use this decorator to track information about the output that doesn't make sense to add to the description.
var obj = {}
@description('Configuration values that are applied when the application starts.')
@metadata({
source: 'database'
contact: 'Web team'
})
output settings object = obj
When you provide a @metadata()
decorator with a property that conflicts with another decorator, that decorator always takes precedence over anything in the @metadata()
decorator. So, the conflicting property within the @metadata()
value is redundant and will be replaced. For more information, see No conflicting metadata.
Sealed
See Elevate error level.
Conditional output
When the value to return depends on a condition in the deployment, use the ?
operator.
output <name> <data-type> = <condition> ? <true-value> : <false-value>
Typically, you use a conditional output when you've conditionally deployed a resource. The following example shows how to conditionally return the resource ID for a public IP address based on whether a new one was deployed.
To specify a conditional output in Bicep, use the ?
operator. The following example either returns an endpoint URL or an empty string depending on a condition.
param deployStorage bool = true
param storageName string
param location string = resourceGroup().location
resource myStorageAccount 'Microsoft.Storage/storageAccounts@2023-04-01' = if (deployStorage) {
name: storageName
location: location
kind: 'StorageV2'
sku:{
name:'Standard_LRS'
tier: 'Standard'
}
properties: {
accessTier: 'Hot'
}
}
output endpoint string = deployStorage ? myStorageAccount.properties.primaryEndpoints.blob : ''
Dynamic number of outputs
In some scenarios, you don't know the number of instances of a value you need to return when creating the template. You can return a variable number of values by using the for
expression.
output <name> <data-type> = [for <item> in <collection>: {
...
}]
The following example iterates over an array.
param nsgLocation string = resourceGroup().location
param orgNames array = [
'Contoso'
'Fabrikam'
'Coho'
]
resource nsg 'Microsoft.Network/networkSecurityGroups@2023-11-01' = [for name in orgNames: {
name: 'nsg-${name}'
location: nsgLocation
}]
output deployedNSGs array = [for (name, i) in orgNames: {
orgName: name
nsgName: nsg[i].name
resourceId: nsg[i].id
}]
For more information about loops, see Iterative loops in Bicep.
Outputs from modules
To get an output value from a module, use the following syntax:
<module-name>.outputs.<property-name>
The following example shows how to set the IP address on a load balancer by retrieving a value from a module.
module publicIP 'modules/public-ip-address.bicep' = {
name: 'public-ip-address-module'
}
resource loadBalancer 'Microsoft.Network/loadBalancers@2023-11-01' = {
name: loadBalancerName
location: location
properties: {
frontendIPConfigurations: [
{
name: 'name'
properties: {
publicIPAddress: {
id: publicIP.outputs.resourceId
}
}
}
]
// ...
}
}
Get output values
When the deployment succeeds, the output values are automatically returned in the results of the deployment.
To get output values from the deployment history, you can use Azure CLI or Azure PowerShell script.
(Get-AzResourceGroupDeployment `
-ResourceGroupName <resource-group-name> `
-Name <deployment-name>).Outputs.resourceID.value
Object sorting in outputs
In JSON, an object is an unordered collection of zero or more key/value pairs. The ordering can be different depending on the implementations. For example, the Bicep items() function sorts the objects in the alphabetical order. In other places, the original ordering can be preserved. Because of this non-determinism, avoid making any assumptions about the ordering of object keys when writing code, which interacts with deployments parameters & outputs.
Next steps
- To learn about the available properties for outputs, see Understand the structure and syntax of Bicep.