ARM template vs Bicep
Published: 2024-03-01 23:56:43

If you've used ARM templates to deploy resources, you must have seen it gets a little messy to maintain if there are a lot of resource.
Bicep is a new language that offers the same capabilities as ARM templates but with a syntax that's easier to use.

You can have modules to divide your arm templates into multiple groups. And you refer the existing resources to get their property values. (You can do this in ARM also, the syntax is easier in Bicep).

You also have a [VSCode Bicep extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-bicep) with intelli-sense to help you write Bicep templates. 

## ARM to Bicep

### with CLI

Once, you have installed [bicep-tools](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/install), you can use the command `az bicep decompile --file <armTemplateFile>.json` to convert them to bicep.
Although it is a best effort decompilation. It attempts to convert the file, but there is no guaranteed mapping from ARM template JSON to Bicep. You may need to fix warnings and errors in the generated Bicep file. Or, decompilation can fail if an accurate conversion isn't possible.

### manual

Once you have decompiled, you can manually reduce the errors and warnings. Or you can convert the entire template.

If you have worked with ARM template, there format is
```json
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",

  "parameters": {
    // parameters
  },
  "resources": [
    {
      "type": "<resourceType>",
      "apiVersion": "<apiVersion>",
      "name": "<resourceName>",
      "location": "<resourceLocation>",
      "properties": {
        // resource properties
      }
    }
  ],
  "outputs": {
    // trimmed
  }
}
```

So all of the properties and values are still the same. But the syntax is a little different. (bicep syntax highlighting is not available here)

```bicep
resource <resourceSymbolicName> '<resourceType>@<apiVersion>' = {
  name: '<resourceName>'
  location: 'resourceLocation'
  properties: {
    // properties
  }
}
```

## Example

Lets say you want to create key azure key vault.

### with ARM

```json
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "parameters": {
    "name": {
      "type": "string",
      "metadata": {
        "description": "Required. key vault name."
      }
    },
    "location": {
      "type": "string",
      "metadata": {
        "description": "Required. location of the key vault"
      }
    }
  },
  "resources": [
    {
      "type": "Microsoft.KeyVault/vaults",
      "apiVersion": "2023-02-01",
      "name": "[parameters('name')]",
      "location": "[parameters('location')]",
      "properties": {
        "sku": {
          "family": "A",
          "name": "standard"
        },
        "tenantId": "[subscription().tenantId]",
        "enabledForDeployment": true,
        "enabledForTemplateDeployment": true,
        "enabledForDiskEncryption": false,
        "enableSoftDelete": true
      }
    }
  ],
  "outputs": {
    "name": {
      "type": "string",
      "value": "[parameters('name')]"
    },
    "vaultUri": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.KeyVault/vaults', parameters('name')), '2023-02-01').vaultUri]"
    }
  }
}
```

This template deploys the key vault and has some properties set for the resource.

### with Bicep

You can have the same template as above in Bicep as below. (again no syntax highlighting for Bicep yet)

```bicep
@description('Required. key vault name.')
param name string

@description('Required. location of the key vault')
param location string

resource kv 'Microsoft.KeyVault/vaults@2023-02-01' = {
  name: name
  location: location
  properties: {
    sku: {
      family: 'A'
      name: 'standard'
    }
    tenantId: subscription().tenantId
    enabledForDeployment: true
    enabledForTemplateDeployment: true
    enabledForDiskEncryption: false
    enableSoftDelete: true
  }
}

// outputs
output name string = kv.name
output vaultUri string = kv.properties.vaultUri
```

Now if you match, you can see this is just easier to write and the intelli-sense from VSCode Bicep Extension will help alot.

And all the other things that Bicep brings, like modules and using dot operator to access the properties of existing resource.

### PostScript

Read more at [bicep-documentation](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/). Feel free to reach out to me if you need any help.


[linkedin.com/in/ankurcharan](https://www.linkedin.com/in/ankurcharan/)
[instagram.com/ankurcharan](https://www.instagram.com/ankurcharan/)
[dev.to/ankurcharan](https://dev.to/ankurcharan)
[twitter.com/ankurcharan](https://twitter.com/ankurcharan)
[ankurcharan.hashnode.dev](https://ankurcharan.hashnode.dev/)