Post-Image

Azure ADF and the ARM Testing Toolkit

Recently I was asked to work on a deployment pipeline for ADF. It turns out that deployment pipelines in ADF are quite easy due to the nature of the entire service being built/programmed by ARM api calls, which can ultimately be templated. You can read more in depth about the desired process here (https://docs.microsoft.com/en-us/azure/data-factory/continuous-integration-deployment).

For those who don’t like to click links, the process goes like so:

  1. Developers work in feature branches to use the UI to craft their pipelines and dependent resources
  2. Changes are merged (by magic surely, or pull requests if you are a pro) to the “master” branch
  3. Changes in the master branch can then be published by hitting the publish button (fancy)
  4. The ADF service updates an “adf_publish” branch with a set of ARM templates that represents the current state of the “code”
  5. CD pipelines can be created to take those arm templates and deploy in target environments

This is all well in good, but what if we want to introduce tests on top of our ADF code. For example, I want to ensure that all linked services are backed by key vaults, and do not rely on secrets passed in via parameters.

The one obvious way is to enforce a code review process in step (2) above. This way an approved person (or lead developer) can review the changes and look for discrepancies. As with anything manual like this, it can get tedious to do at scale.

In comes the Azure ARM Testing Toolkit (arm-ttk). You can find out more and read about it here.

The idea behind the arm-ttk is to provide a framework for writing tests that can be run against ARM templates. The project contains a bunch of utilities that help you read and parse ARM templates. Further, it contains all the current testing that is done by Microsoft when companies publish ARM templates to the marketplace. Lastly, it is designed to allow for extensibility, which is exactly what we are going to do.

Once you have the project cloned, you can take a quick read through arm-ttk/Test-AzTemplate.ps1 which has the meat of the code you’ll be interested in. By default, the code looks under the current directory for a folder called testcases. It is from here that it loads the tests you will like to run.

The Test-Case function in that file contains all the magic. Here you can see that if your tests are passed in as a script, they are executed inline whereas if they are passed in as a string it uses the following snip of code to execute:

$testCmd = $ExecutionContext.SessionState.InvokeCommand.GetCommand($TheTest, 'ExternalScript')

In my case, I am creating a file, so I can just create a standard ps1 and add it to an appropriate directory (under testcases).

The script that you will write takes in a single parameter called $TemplateObject. This is a parsed Azure ARM template and you can look at the other bits of code to understand what you can do with it. For example, here is some code that will iterate through the list of linked services in the target ARM template.

param(
    [Parameter(Mandatory=$true)]
    [PSObject]
    $TemplateObject
)
$linkedServices = $TemplateObject | Find-JsonContent -key type -Value "Microsoft.DataFactory/factories/linkedServices"
foreach ($linkedService in $linkedServices){
    $typeProperties = $linkedService.properties.typeProperties
    $type = $linkedService.properties.type
    $name = $linkedService.name
// YOUR CODE HERE
}

Accessing the properties of a given resource is just simple JSON navigation. Here is an example of what you’d look for in the AzureBlobFS ($type) linked service.

        "AzureBlobFS"{
            if (!($typeProperties.PSObject.Properties.Name -contains "servicePrincipalKey")){
                Write-Error "$type connection info misconfigured" -TargetObject $linkedService
                break
            }
            $servicePrincipalKeyType = $typeProperties.servicePrincipalKey.type
            if ($servicePrincipalKeyType -ne "AzureKeyVaultSecret"){
                Write-Error "$type Key misconfigured" -TargetObject $linkedService
            }
        }

Once you have that down, you can start to add your own custom tests to ensure your ADF pipelines and dependant resources meet your organizational policies. Enjoy!

 

Share This Article

Comments