Below I've added the contents of 3 Bicep files. If you add these to the same directory and run a subscription-based deployment to Azure as follows...
az deployment sub create --name "VerifyBug" --location "northeurope" --template-file .\main.bicep
...you'll get a "Object reference not set to an instance of an object". I've just spent the best part of 24 hours trying to work out what exactly was causing this exception because it was coming from a much larger deployment that this replicates. There is no indication of where the exception is being thrown.
What I've found is that the problem is with the serverfarm.outputs.serverfarmId value. See how this is being used in an object which is later unioned with another object. It seems the problem is a combination of using an ARM output inside a union operator, but I'd love a more technical explanation. I'm mainly posting this here to help anyone else avoid similar pain in the future.
The solution I've found is to break everything after the serverfarm module out of function.bicep into a separate module which takes the server farm ID as a parameter. Everything then works, but I'd love to hear an explanation about why this is.
main.bicep
targetScope = 'subscription'
var location = 'northeurope'
var resourceNamePrefix = 'test-resource'
resource resourceGroup 'Microsoft.Resources/resourceGroups@2020-10-01' = {
name: '${resourceNamePrefix}-rg'
location: location
}
module func 'function.bicep' = {
name: '${deployment().name}-Func'
scope: resourceGroup
params: {
resourceNamePrefix: resourceNamePrefix
location: location
}
}
function.bicep
param location string
param resourceNamePrefix string
param networking object = {}
module serverfarm 'appServicePlan.bicep' = {
name: '${deployment().name}-AppSvcPlan'
params: {
resourceNamePrefix: resourceNamePrefix
location: location
}
}
var siteConfig = {
linuxFxVersion: 'DOTNET-ISOLATED|6.0'
http20Enabled: true
alwaysOn: true
ftpsState: 'Disabled'
functionAppScaleLimit: 1
minimumElasticInstanceCount: 1
vnetRouteAllEnabled: !empty(networking)
}
var basicProperties = {
serverFarmId: serverfarm.outputs.serverfarmId
httpsOnly: true
redundancyMode: 'None'
reserved: true
siteConfig: siteConfig
}
var networkingProperties = empty(networking) ? {} : {
virtualNetworkSubnetId: networking.subnetResourceId
}
var functionProperties = union(basicProperties, networkingProperties)
resource function 'Microsoft.Web/sites@2021-02-01' = {
name: '${resourceNamePrefix}-fn'
location: location
kind: 'functionapp,linux'
properties: functionProperties
}
appServicePlan.bicep
param resourceNamePrefix string
param location string
resource serverfarm 'Microsoft.Web/serverfarms@2021-02-01' = {
kind: 'linux'
name: '${resourceNamePrefix}-appserviceplan'
location: location
sku: {
name: 'S1'
tier: 'Standard'
}
properties: {
reserved: true
maximumElasticWorkerCount: 1
}
}
output serverfarmId string = serverfarm.id
