File contains notes about learning bicep.
NOTE some bicep and az commands should be interchangeable - commands/function found in bicep should have their counterpart in az command and vice versa.
When defining a resource, we can use existing
keyword to indicate existing resource, that we want just reference in bicep scripts without creation.
When using params
, params provided must match exactly required parameters in module/template.
Of course, there can be multiple values provided to params, in that case there's precedence that will determine which value to use.
But if you don't provide any value for any param, or we provide value for non-existing parameter, the bicep validation will fail.
Bicep also supports loops. When bicep runs loops it deploys resources in parallel. To limit that we can use batchSize
decorator:
@batchSize(2)
resource storageAccounts 'Microsoft.Storage/storageAccounts@2023-05-01' = [for i in range(1, 3): {
name: 'mtwebapp-${i}'
location: resourceGroup().location
kind: 'StorageV2'
sku: {
name: 'Standard_LRS'
}
properties: {
accessTier: 'Cold'
}
}]
Other usages of arrays:
var items = [for i in range(1,5): 'item${i}']
Sometimes, we need to define resources with children, such as SQL server and SQL database, or Storage Account together with some container. There are multiple ways to do that. See example bicep file.
Other ways to write the same:
- Alternative way to define child resource outside parent is to specify property
parent: sqlServer
, as below:resource sqlServer 'Microsoft.Sql/servers@2022-05-01-preview' = { name: sqlServerName location: location properties: { administratorLogin: sqlServerAdministratorLogin administratorLoginPassword: sqlServerAdministratorPassword } } resource sqlDatabase 'Microsoft.Sql/servers/databases@2022-05-01-preview' = { parent: sqlServer name: sqlDatabaseName location: location sku: { name: sqlDatabaseSku.name tier: sqlDatabaseSku.tier } }
- yet another way is to specify parent resource in the string interpolation and add the symoblic name to
dependsOn
resource sqlServer 'Microsoft.Sql/servers@2022-05-01-preview' = { name: sqlServerName location: location properties: { administratorLogin: sqlServerAdministratorLogin administratorLoginPassword: sqlServerAdministratorPassword } } resource sqlDatabase 'Microsoft.Sql/servers/databases@2022-05-01-preview' = { name: '${sqlServerName}/${sqlDatabaseName}' location: location sku: { name: sqlDatabaseSku.name tier: sqlDatabaseSku.tier } dependsOn: [ sqlServer ] }
You can refer to exsiting resources. Not only in the same resource group, but also in the same subscription or even different subscription within Microsoft Entra tenant:
// Resource in different Resource Group
resource vnet 'Microsoft.Network/virtualNetworks@2020-11-01' existing = {
scope: resourceGroup('networking-rg')
name: 'toy-design-vnet'
}
// Resource in different Subscription
resource vnet 'Microsoft.Network/virtualNetworks@2020-11-01' existing = {
scope: resourceGroup('A123b4567c-1234-1a2b-2b1a-1234abc12345', 'networking-rg')
name: 'toy-design-vnet'
}
In order to created extension resource, such as lock on CosmosDB (or any other resource), we would write:
resource cosmosDBAccount 'Microsoft.DocumentDB/databaseAccounts@2020-04-01' = {
name: cosmosDBAccountName
location: location
properties: {
// ...
}
}
And then, to add lock to it we would use scope
property defined as scope: cosmosDBAccount
:
resource lockResource 'Microsoft.Authorization/locks@2016-09-01' = {
scope: cosmosDBAccount
name: 'DontDelete'
properties: {
level: 'CanNotDelete'
notes: 'Prevents deletion of the toy data Cosmos DB account.'
}
}
Extension resources change the way resource behaves, such as locks prevents deletions of the resource (any resource).
Bicep deploys resources in different modes. By default bicep uses incremenetal mode, which means that bicep only adds or updates resources, but does not delete resources not speicified in bicep.
Complete mode - that mode should be specified explicitly. In that mode resources that exist in Azure but that aren't specified in the template are deleted. Some resource types are exempt., and do not get deleted in that mode.
Each resource is deployed to some scope. Defaut scope is resource group, but also resources can be scopes themselves, for example: lock is resource that has to be deployed in scope of some resource.
To define scope for the whole bicep file we need to specify targetScope
to one of the values: resourceGroup
, subscription
, managementGroup
or tenant
. The information what to use exactly (what resource group or what subscription) is provided via command line parameters for AZ cmdlet. Bicep assumes resourceGroup
by default.
Depending on scope at which we want to execute our bicep script, we use different Azure CLI command:
az deployment group create
to deploy to resource groupaz deployment sub create
to deploy to subscriptionaz deployment mg create
to deploy to management groupaz deployment tenant create
to deploy to tenant
In order to override scope set for entire bicep file, modules (and some Azure resources, like extension resources) support scope
property, that can be used to deploy resource to different scope, for example:
targetScope = 'subscription'
module networkModule 'modules/network.bicep' = {
scope: resourceGroup('ToyNetworking')
name: 'networkModule'
}
A template spec is an Azure resource, just like a storage account or virtual machine. It must be created within a resource group, although the template itself can deploy resources to a subscription, management, or tenant scope.
In order to create template spec:
- create usual template (bicep or ARM)
- create template spec resource in Azure and deploy created template to that resource,
CLI to create template spec:
az ts create \
--name StorageWithoutSAS \
--lcoation westus \
--dispaly-name "Storage account with SAS disabled" \
--description "This template spec creates a storage account, which is preconfigured to disable SAS authentication."
--version 1.0 \
--template-file main.bicep
After successfully creating template spec in Azure, we can use it for our deployment, below is az
command to deploy using template spec:
az deployment group create \
--template-spec "/subscriptions/f0750bbe-ea75-4ae5-b24d-a92ca601da2c/resourceGroups/SharedTemplates/providers/Microsoft.Resources/templateSpecs/StorageWithoutSAS"
Of course, we can use template specs at various scopes, such as subscription or tenant.
We also can do usual stuff with template spec, just as with other resources:
az ts show
- show resource (if--version
paramter is specified, output is for specific version of template spec)as ts update
- update existing resourceaz ts delete
- remove resource
Another thing to do is to export template of tepmlate spec:
az ts export \
--resource-group MyResourceGroup \
--name MyTemplateSpec
--version 1.0 \
--output-folder ./mytemplates
We can store bicep files in Bicep registries.
To create Azure Container Registry:
az acr create \
--name YOUR_CONTAINER_REGISTRY_NAME \
--sku Basic \
--location westus
To see content of registry:
az acr repository list --name YOUR_CONTAINER_REGISTRY_NAME
To publish module to registry:
az bicep publish --file module.bicep --target 'br:toycompany.azurecr.io/mymodules/modulename:moduleversion'
Where br:toycompany.azurecr.io/mymodules/modulename:moduleversion
is module path in registry:
br
- schemetoycompany.azurecr.io
- registrymymodules/modulename
- module identifiermoduleversion
- tag
To use existing module from registry, we can use following bicep code:
module myModule 'br:myregistry.azurecr.io/modulepath/modulename:moduleversion' = {
name: 'my-module'
params: {
moduleParameter1: 'value'
}
}
How to create KV? in bicep_POC resource group i created KV, but i was not previliged enough to add secrets there.
Because access to resource does not guarantee the access to what is inside (application like KV or DB - imagine not having db admin login and password, while DB requires authorization)