Azure Bicep v0.3.1
Tags: azure, iac, devops, azuredevops
Published: 2021-03-05 21:09:32

If you follow me on dev.to, you already know that I love Bicep, the Azure new Resource Manager template DSL. Until yesterday, it could be considered experimental. You can use it to test and play with it, but you can not use it for production workload. But starting with version, 0.3.1, Bicep is supported by Microsoft support plans. 
One of the features we were waiting for, loops. The Loop feature is out of the box. 
How to use loops with Bicep? Before answering this question, we need to see how loops are used in ARM Templates. You can see the Microsoft Doc dedicated page, [Resource iteration in ARM templates](https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/copy-resources?WT.mc_id=AZ-MVP-5003620). 
How to create resource iteration with Bicep. Let’s try with an example. Imagine you need to deploy several Azure Postgresql servers. There are few differences between them, the name and the amount of storage needed. So, you know you need to create an array storing several objects containing the server name and the required storage. 

```
var azPgSqlServers = [
  {
    name: 'my-prd-srv'
    storageMb: 512000
  }
  {
    suffix: 'my-dev-srv'
    storageMb: 256000
  }
]

param sqlAdminName string

param sqlAdminPassword string {
  secure: true
}
``` 

To iterate the array azPgSqlServer, you will need the “for” and “in” keywords with [ ]
In the "for" part, you define a variable you can use in the resource define inside the []. The "in" part lets you select the variable or the parameter you want to iterate. 

``` 
 resource azServer 'Microsoft.DBForPostgreSQL/servers@2017-12-01' = [for srv in azPgSqlServers: {
    name: srv.name 
    location: 'westeurope'
    sku: {
      name: 'GP_Gen5_2'
      tier: 'GeneralPurpose'
      family: 'Gen5'
      capacity: 2
    }
    properties: {
      storageProfile: {
          storageMB: srv.storageMb
          backupRetentionDays: 30
          geoRedundantBackup: 'Enabled'
          storageAutogrow: 'Enabled'
      }
      version: '11'
      createMode: 'Default'
      administratorLogin: sqlAdminName
      administratorLoginPassword: sqlAdminPassword
    }
  }]
```

After compiling the bicep file with bicep build, the resultant JSON file will have a DBForPostgreSql/Servers resource with a copy element.

If you take a look JSON file carefully, you will also find a new element, metadata. The template metadata object in an ARM template allows you to add any kind of information.
Bicep add a “_generator” object with the Bicep version, the template hash, and the name of the generator, bicep

```json
 "_generator": {
      "name": "bicep",
      "version": "0.3.1.62928",
      "templateHash": "15593105574464543895"
    }
``` 

This information can be useful if you need to debug or review templates later. 


Another missing piece in the previous version of Bicep was conditional deployment. You can check this [Microsoft Doc page]( https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-tutorial-use-conditions?WT.mc_id=AZ-MVP-5003620) or [this blog post]( https://dev.to/omiossec/arm-templates-conditional-deployments-in-azure-5kc).

With version 0.3.1, it's possible to add a condition to resource deployment. Imagine you need to deploy a VNET only if a condition is met. In an ARM template, you will need to use the "condition" keyword with a Boolean value. With Bicep, you just need to add an “if” keyword followed by a Boolean expression.

```
param  vnetName string
param  vnetPrefix string
param vnetLocation string = resourceGroup().location
param deployVnet bool = true

// VNET 
resource vnet 'Microsoft.Network/virtualNetworks@2020-06-01' = if(deployVnet) {
  name: vnetName
  location: vnetLocation
  properties: {
    addressSpace: {
      addressPrefixes: [
        vnetPrefix
      ]
    }
    subnets: [
      {
        name: 'defaultSubnet'
        properties: {
          addressPrefix: vnetPrefix
        }
      }
    ]
  }
}
``` 

In this example, the deployVnet parameter is a Boolean. It is used in an "if" expression for the VNET resource. If the deployVnet param is true the VNET is deployed, if false the deployment is skipped. You can use any expression returning a Boolean in the if section. This includes binary, equality, relational expressions.
The compilation of the template file will translate the if expression into the ARM condition statement. 

Another possibility offered by this new version is the possibility to translate a JSON template into a Bicep file. This possibility is called decompilation. You take a JSON file and use decompile instead of build to create a Bicep file. 

bicep decompile ./armTemplate.json
But there are some limitations, simple templates work well, as well as templates with a condition. For example, the copy keyword is not implemented yet. 
Decompiled templates should be a starting point and not the final journey. 


Bicep v0.3 is now ready for production, but there are more to come. Bicep should continue to enhance and the team will deliver new features in the future. 
If you have time, watch the session from MS Ignite 2021 [Learn everything about the next generation of ARM Templates]( https://myignite.microsoft.com/sessions/54873305-d4a9-46ac-8764-ec25f0860276).