Table of Contents
Overview
I was looking for the easiest way to test Azure infrastructure. I take a look into great project like Molecule, Terratest and so on. Even if they are very cool and powerful, I wanted to find something easier (or lazier).
I already use pester for testing purpose, so I manage to use pester for testing Azure infrastructure, using the Gherkin syntax and I’ll show you, how you can do that.
Workstation preparation
I work on 3 kind of platform : macOs, Ubuntu and Windows 10, and my tests are working on all of them.
You will need to install :
- PowerShell (6.2.3 at least)
- Powershell Az module
- Pester (at least 4.9)
- VS Code
Install Powershell and modules
Powershell 6
Manual installation
First, download the suitable version of powershell for your system on GitHub. Yes, if you miss it, that is now fully open source.
https://github.com/PowerShell/PowerShell/releases
Package Manager
macOS
If you use macOs, brew can manage it for you:
brew install powershell
Ubuntu
On Ubuntu, snap can do the job also :
sudo snap install powershell --classic
Windows
On Windows, Chocolatey is working well:
choco install pwsh
Modules
Installing module in PowerShell is quite easy. You only need to type the following :
Install-PackageProvider Nuget -ForceBootstrap -Force
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
Update-Module
Install-Module -Name Pester -Force -SkipPublisherCheck
Install-Module -Name Az -force
Some command may not be useful on your setup, but this way ensure that you have the latest version of each module
Visual Studio Code
You can install Vs Code manually or by using a Package Manager using choco, snap or brew. I’ll not detail this part.
Extensions installation
To install the extension, you can use the GUI of Vs Code or the cmdline. For Gui, take a look at the doc here.
For the cmdline :
code --install-extension alexkrechik.cucumberautocomplete
code --install-extension ms-vscode.powershell
on Linux and macOs, you’ll need to add the following in your profile, adapt the path to Vs Code to yours :
bash:
cat << EOF >> ~/.bash_profile # Add Visual Studio Code (code) export PATH="\$PATH:/Applications/Visual Studio Code.app/Contents/Resources/app/bin" EOF
zsh:
cat << EOF >> ~/.zsh_profile # Add Visual Studio Code (code) export PATH="\$PATH:/Applications/Visual Studio Code.app/Contents/Resources/app/bin" EOF
Create the first tests
Pester, Gherkin and testing
First of all, you will need some detail on Pester, Gherkin and testing like I think they can be useful and easy as possible.
Pester, is a world community framework for testing in Powershell. So, if you know a bit in PowerShell, you won’t be lost at all. This module add some new function to do the magic of testing.
Gherkin, is a syntax for BDD (Behavior-Driven Development) testing. To explain a bit, for me, in our infrastructure testing purpose, is to have some human readable scenario to show to management/customers.
Fortunately, Pester support the Gherkin syntax using the Invoke-Gherkin
cmdlet and do a bit of magic for us.
Let’s play
We need to create our workspace, so do it like that (Using PowerShell’s Shell):
Set-Location ~
New-Item ./Documents/GherkinTests -type Directory
code ./Documents/GherkinTests
Create few file :
- etienne_exo.feature <— This is the Gherkin File
- etienne_exo.steps.ps1 <— This is our magic
In the Feature File write the following :
# GherkinTests/etienne_exo.feature
Feature: Validate Azure Deployment
Scenario: We should have some subscriptions to work
Given we list the subscriptions using powershell
Then we should be able to have at least one
# GherkinTests/etienne_exo.steps.ps1
Given "we list the subscriptions using powershell"{
Get-AzSubscription | Should -not -throw
}
Then "we should be able to have at least one" {
(Get-AzSubscription).Count | Should -Not -BeNullOrEmpty
}
Now, let’s run that to check if the test are working or not :
❯ Invoke-Gherkin
Pester v4.10.0
Executing all tests in '/home/etienne/Documents/GherkinTests'
Feature: Validate Azure Deployment
Scenario: We should have some subscriptions to work
[+] Given we list the subscriptions using powershell 6.17s
[+] Then we should be able to have at least one 5.01s
Tests completed in 11.39s
Tests Passed: 2, Failed: 0, Skipped: 0, Pending: 0, Inconclusive: 0
Ok, tests are working, and we have something to show to customers/management.
Wait, can’t we do nothing better ? Are we lazy enough ? Of course, not, let’s wait for the next blog part.
Azure Devops
Azure Devops CLI
Get a Personal Access Token here : https://dev.azure.com/<YourOrganisation>/_usersSettings/tokens
az extension add --name azure-devops
az devops login
# paste your PAT
az login
# with the sam
az account set -s <YOUR SUB>
az devops configure --defaults 'organization=https://dev.azure.com/etiennedeneuve'
az devops project create --name GherkinTest
# Store the repo git url to configure the repo locally, you will need a SSH Key for that.
$repo=$(az repos list --project GherkinTest --query [].sshUrl -o tsv)
Configure the repo locally
cd ~/GherkinTest
git init
git remote add origin $repo
git add .
git commit -m 'inital commit'
git push origin master
Create the pipeline
az pipelines create --name "GherkinTest"
Answer the questions like :
This command is in preview. It may be changed/removed in a future release.
Which template do you want to use for this pipeline?
[1] Starter pipeline
[2] Android
[3] Ant
[4] ASP.NET
[5] ASP.NET Core
[6] .NET Core Function App to Windows on Azure
[7] ASP.NET Core (.NET Framework)
Please enter a choice [Default choice(1)]: Starter pipeline
Do you want to view/edit the template yaml before proceeding?
Please enter a choice [Default choice(1)]: Continue with generated yaml
Files to be added to your repository (1)
1) azure-pipelines.yml
How do you want to commit the files to the repository?
Please enter a choice [Default choice(1)]: Create a new branch for this commit and start a pull request.
Enter new branch name to create: features/cicd
Checking in file azure-pipelines.yml in the Azure repo c279436a-e2f4-4e01-8f41-a30f660f7515
Created a Pull Request - https://dev.azure.com/etiennedeneuve/6874897d-6d09-412e-b73b-4b2966c04b64/_apis/git/repositories/c279436a-e2f4-4e01-8f41-a30f660f7515/pullRequests/1
Successfully created a pipeline with Name: GherkinTest, Id: 25.
{
"agentSpecification": null,
"buildNumber": "20200214.1",
"buildNumberRevision": 1,
"controller": null
}
Create the Service Endpoint for Azure RM Subscription
First we need to create a SPN in Azure AD :
az ad sp create-for-rbac --name AzureDevops
Changing "AzureDevops" to a valid URI of "http://AzureDevops", which is the required format used for service principal names
Creating a role assignment under the scope of "/subscriptions/1417c648-XXXX"
{
"appId": "41176fe8-XXXXX",
"displayName": "AzureDevops",
"name": "http://AzureDevops",
"password": "7eaeb380-XXXXX",
"tenant": "06329ce4-XXXX"
}
Take note of the appId, Name, Password and Tenant.
Now, list your subscriptions :
az account show
{
"environmentName": "AzureCloud",
"id": "1417c648-XXXXX",
"isDefault": true,
"name": "Microsoft XXXX",
"state": "Enabled",
"tenantId": "06329ce4-XXXX",
"user": {
"name": "etienne@deneuve.xyz",
"type": "user"
}
}
Take note of the Id, Name, and Tenant.
And then create the service endpoint in Azure DevOps :
az devops service-endpoint azurerm create --name 'Azure MVP' `
>> --azure-rm-tenant-id "YourTenantId" `
>> --azure-rm-service-principal-id "AppID" `
>> --azure-rm-subscription-id "SubID" `
>> --azure-rm-subscription-name "Name of the Sub"
Azure RM service principal key: "Password"
Confirm Azure RM service principal key: "Password"
{
"administratorsGroup": null,
< shortened >
"type": "azurerm",
"url": "https://management.azure.com/"
}
Configure the pipeline
Now, checkout to the newly created branch :
# change branch
git checkout features/cicd
# get latests info from remote
git pull
# open code in the current folder
code .
Add the following snippet into azure-pipelines.yml
:
# ./azure-pipelines.yml
# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml
trigger:
- master
pool:
vmImage: 'windows-latest'
steps:
- task: AzurePowerShell@5
inputs:
azurePowerShellVersion: LatestVersion
azureSubscription: 'Azure MVP'
Inline: |
Install-Module -Name Pester -Force
ScriptType: InlineScript
pwsh: true
workingDirectory: $(Build.Repository.LocalPath)
displayName: 'Install Pester'
- task: AzurePowerShell@5
inputs:
azurePowerShellVersion: LatestVersion
azureSubscription: 'Azure MVP'
Inline: |
Invoke-Gherkin -OutputFile result.xml -OutputFormat NUnitXml
ScriptType: InlineScript
pwsh: true
workingDirectory: $(Build.Repository.LocalPath)
displayName: 'Launch Test'
- task: PublishTestResults@2
inputs:
buildConfiguration: Azure
buildPlatform: Azure
publishRunAttachments: true
testResultsFiles: result.xml
testResultsFormat: NUnit
testRunTitle: ValidateAzure
Commit the file :
git add azure-pipelines.yaml
git commit -m 'feat: add cicd for tests'
git push origin features/cicd
Go in your Azure Devops project, select your new pipeline, and go in Tests, you should have something like my public repo :
Et Voila!
Working with the tests
Now, if we want to deploy something in our new infra, we will need to write the tests before deploying the resources themselves.
Adding some tests
In this scenario, we want to deploy a VM, in our subscription. Let’s do a quick list of what we should have after a successful deployment :
- 1 Subscription
- 1 Resource Group
- 1 Virtual Network
- 1 Subnet
- 1 Network Interface
- 1 Disk
- 1 VM
- Optionally: 1 Public IP
With our list, we can now write the test we want, in the feature file:
# GherkinTests/etienne_exo.feature
Feature: Validate Azure Deployment
Scenario: Someone start a new vm deployment
Given someone start a new vm deployment in the subscription
When the deployment is completed we should have 1 resource group
Then we should have 1 Virtual Network
And 1 Subnet
And 1 Network interface
And 1 Disk
And 1 VM
And 1 Public IP
Now, in our steps.ps1 file we will update it:
# GherkinTests/etienne_exo.steps.ps1
Given "someone start a new vm deployment in the subscription"{
Get-AzSubscription | Should -not -throw
}
When "the deployment is completed we should have 1 resource group" {
Get-AzResourceGroup -name RG-GherkinTests | Should -exists
}
Then "We should have 1 Virtual Network"{
}
And "1 Subnet"{
}
And "1 Network interface"{
}
And "1 Disk"{
}
And "1 VM"{
}
And "1 Public IP"{
}