Your first Bicep file from 3.2.1 had fixed values: dev in the name, dev in the tag. For a second environment you would have to copy the file,
and you’d already have two truths. In this lesson you learn the language far enough that one file is enough for all environments and
wrong values are rejected before anything happens in Azure.
At the end, infra/main.bicep describes the first two building blocks the Kladde runs on in Azure: a Log Analytics workspace
and a Container Apps environment.
Parameters and decorators
A parameter is a value the file receives from outside. A decorator stands in front of it with @ and restricts or describes it:
@description('Short name of the environment: dev, test or prod.')
@allowed([
'dev'
'test'
'prod'
])
param environmentName string
@description('Days that Log Analytics keeps the data.')
@minValue(30)
@maxValue(730)
param logRetentionDays int = 30
The most important decorators:
@description('…')explains the parameter. The Bicep extension shows the text when you hover over the name, and the portal shows it in a deployment by hand. Write it for every parameter.@allowed([…])allows only the values listed.@minLength(…)and@maxLength(…)limit the length of strings and arrays,@minValue(…)and@maxValue(…)the range of numbers.@secure()marks a secret value. ARM doesn’t write it to the deployment history or to logs. In the Kladde there will still not be a single such parameter: what isn’t passed as a parameter in the first place can’t leak anywhere (module 3.3).
The linter built into the Bicep CLI watches for secret values even without settings of your own. This file:
@description('Not like this: a secret parameter with a fixed value.')
@secure()
param apiKey string = 'abc123'
output used string = length(apiKey) > 0 ? 'yes' : 'no'
produces two warnings when compiled (shortened):
Warning secure-parameter-default: Secure parameters should not have hardcoded defaults (except for empty or newGuid()).
Warning outputs-should-not-contain-secrets: Outputs should not contain secrets. Found possible secret: secure value 'apiKey'
A trap with @allowed
The obvious thing would be to limit the region to a list of EU regions and take the resource group’s region as the default:
@allowed([
'germanywestcentral'
'swedencentral'
'francecentral'
'westeurope'
'northeurope'
])
param location string = resourceGroup().location
Bicep doesn’t compile that:
Error BCP033: Expected a value of type "'francecentral' | 'germanywestcentral' | 'northeurope' | 'swedencentral' | 'westeurope'" but the provided value is of type "string".
At compile time, Bicep can’t know which region the resource group is in, so it can’t prove that the default value is in the list. Leave out the default value; then every deployment must name the region, and that’s exactly what you want here. The “Allowed locations” policy from 3.1.5 stays in place anyway: the list in Bicep catches mistakes before the deployment, the policy everything that doesn’t come from your code.