Convert ARM Template to Bicep and Deploy with Azure DevOps - Part 4 - Test

2022, Apr 14

This is the fourth part of the series where an ARM Template is converted to Bicep. In this article, we should continue on Phase 4 - Test.

Phased Migration

As a reference to Part 3, Microsoft suggests a migration in 5 phases, to convert the ARM Template into Bicep Template.

Five-Phases

The comprehensive details provided by Microsoft Docs are available as a reference1.

Phase 4 - Test

In this phase, it is important to validate the integrity of the new bicep template, by performing tests in a Test environment.

Check the PlayGoKids repository for this article demo.

Some actions need to be verified to give us confidence that the migrated template will work:

  • Deployment what-if operation

This is a very clever way of checking any possible differences in the templates, by running the what-if operation. It compares the state of components/services deployed in Azure, by checking the current state of the deployed services with the new state of the converted template. The beauty of it is that it doesn't apply the changes to the environment, but the tool gives you an output of findings. There are 2 modes that you can run the tool: Incremental and Complete mode.

  • Run a test deployment

Define a strategy to release the new template, either with a parallel release or an in-place release. The important thing is that this is thoroughly tested and validated.

what-if operation

Before you get an ARM/Bicep template released, you can preview the changes. That's what this tool allows you to do, preview without applying any changes.

If you remember the original ARM Template from Phase 1 - Convert, it had params:

Partial File: azuredeploy.json

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "environment": {
      "type": "string",
      "minLength": 1,
      "maxLength": 3
    },
    "hostingPlanName": {
      "type": "string",
      "minLength": 3
    },
    "skuName": {
      "type": "string",
      "defaultValue": "F1",
      "allowedValues": [
        "F1",
        "D1",
        "B1",
        "B2",
        "B3",
        "S1",
        "S2",
        "S3",
        "P1",
        "P2",
        "P3",
        "P4"
      ],
      "metadata": {
        "description": "Describes plan's pricing tier and capacity. Check details at https://azure.microsoft.com/en-us/pricing/details/app-service/"
      }
    }
  },
  ...
}

They were environment, hostingPlanName and skuName.

What about the new Bicep file?

Partial File: azuredeploy.bicep

@minLength(1)
@maxLength(3)
param environment string

@minLength(3)
param appPlanName string

@description('Describes plan\'s pricing tier and capacity. Check details at https://azure.microsoft.com/en-us/pricing/details/app-service/')
@allowed([
  'F1'
  'D1'
  'B1'
  'B2'
  'B3'
  'S1'
  'S2'
  'S3'
  'P1'
  'P2'
  'P3'
  'P4'
])
param appPlanSku string = 'F1'
...

They are environment, appPlanName and appPlanSku.

In summary, the changes were:

Before After
environment environment
hostingPlanName appPlanName
skuName appPlanSku

To be able to run the what-if operation, we need to provide those parameters, but how is that done? We need to use the parameters file. This file should be already created for each environment (as a DevOps best practice). So looking at the directory folders we should have something like this:

|--ExistingARMTemplate
|--|--azuredeploy.json
|--|--azuredeploy.parameters.dev.json
|--|--azuredeploy.parameters.tst.json
|--|--azuredeploy.parameters.uat.json
|--|--azuredeploy.parameters.prd.json
|--ConvertedBicepTemplate
|--|--azuredeploy.bicep
|--|--azuredeploy.parameters.dev.json
|--|--azuredeploy.parameters.tst.json
|--|--azuredeploy.parameters.uat.json
|--|--azuredeploy.parameters.prd.json
|--|--modules
|--|--|--appPlan.bicep
|--|--|--apps.bicep
|--|--|--insights.bicep

Because of the Before and After changes, make sure the parameters' names match.

File: azuredeploy.parameters.dev.json from ExistingARMTemplate

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "environment": {
      "value": "dev"
    },
    "hostingPlanName": {
      "value": "sample-app-nonprd"
    },
    "skuName": {
      "value": "B1"
    }
  }
}

File: azuredeploy.parameters.dev.json from ConvertedBicepTemplate

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "environment": {
      "value": "dev"
    },
    "appPlanName": {
      "value": "sample-app-nonprd"
    },
    "appPlanSku": {
      "value": "B1"
    }
  }
}

Now we can run the what-if operation.

To be able to compare the differences, run these commands with az cli, although you could also run with PowerShell:

// This will create the Resource group
az group create --name sample-rg-nonprd --location "Australia East"

// This will provision the dev environment using the old ARM definition
az deployment group create --resource-group sample-rg-nonprd --template-file .\azuredeploy.json --parameters .\azuredeploy.parameters.dev.json

// Here is the comparison we've been waiting for
az deployment group what-if --resource-group sample-rg-nonprd --template-file .\azuredeploy.bicep --parameters .\azuredeploy.parameters.dev.json

what-if operation results

What-If

This is the result we got after converting the ARM Template onto Bicep. It is important to notice that through visual colours you can see the changes:

What-If-Colours

Is that going to break the resources? That's a question you need to be able to answer for your own templates. On this one, they seem to be very minor, and wouldn't break the template I need, so I'm accepting the Resource changes.

Run the following command:

Mode = Complete

az deployment group create --mode Complete --confirm-with-what-if --resource-group sample-rg-nonprd --template-file .\azuredeploy.bicep --parameters .\azuredeploy.parameters.dev.json

Complete-Mode-What-If

What is interesting is that because I enforced the mode Complete, the resource was displayed as to be deleted during confirmation. What it did was to delete and reprovision the resource, because in the end the webApp was there with the updated information.

Mode = Incremental

az deployment group create --mode Incremental --confirm-with-what-if --resource-group sample-rg-nonprd --template-file .\azuredeploy.bicep --parameters .\azuredeploy.parameters.dev.json

Incremental-Mode-What-If

On Incremental mode, we get the same level of warnings when we run the previous what-if command.

Services provisioned and updated

In both cases the same objects were there provisioned:

Objects

To understand more about the modes, check this link

In Phase 5 we'll check the Deploy Phase, prepping for Continuous Deployment.

Full Series

Phase 1 - Convert

Phase 2 - Migration

Phase 3 - Refactor

Phase 4 - Test

Phase 5 - Deploy


  1. References: Migrate to Bicep