Start multiple VMs using parameters with Azure DevOps pipeline

In this article I will explain how one can start multiple VMs on Azure using a pipeline automation. The steps you need to follow:

First create a service connection with your subscription. You should navigate to service connections -> azure resource manager and then select service principal (automatic)

You will then have to select the scope* the subscription or resource group this service connection will access.

In my scenario I added a friendly name of the subscription as Azure Subscription Service Connection

trigger: none
pr: none
parameters:
– name: vms
type: object
default: ["ubuntu1","windows-1"]
pool:
vmImage: ubuntu-latest
jobs:
– job: startvmjob
displayName: Start VMs
steps:
– checkout: none
– ${{ each vm in parameters.vms }}:
– task: AzureCLI@2
displayName: starting vm ${{vm}}
inputs:
azureSubscription: 'Azure Subscription Service Connection'
scriptType: 'pscore'
scriptLocation: 'inlineScript'
inlineScript: |
$vmrequest = az vm list | ConvertFrom-Json | Where-Object {$_.Name -Match "${{vm}}"}
az vm start –resource-group $vmrequest.resourcegroup –name $vmrequest.name

When you run the pipeline you will need to provide the VM names. You can also run this pipeline on a schedule using a cron task. My vms are ubuntu1, windows-1

By running the pipeline

Then by navigating on Azure you can notice the VM as started.

Video tutorial on YouTube:

Azure DevOps agent cannot checkout GitHub repository

Recently I faced an issue with my Azure DevOps self hosted container agents. They could not checkout the git repositories and the build stopped due to the default timeout of 60 minutes per run.

This happened for multiple builds, as a result I had to investigate the reason behind this error.

By checking the logs inside the container on the C:\agent\_diag folder I could recognize an error message like the below:

A session for this agent already exists.
Agent connect error: The task agent xxx already has an active session for owner xxx.. Retrying until reconnected.

By searching online, I figured out that this is a reported bug on previous agents versions. In order to resolve, I updated and reconfigured the agent. You can update the agent, either from the GUI or by creating a new container and installing the latest version of azure devops agent.

In order to reconfigure the agent I first took an interactive shell on it.

docker exec -it agent-name powershell.exe

Then inside C:\agent run the below commands.

Reconfigure the agent

This is a temporary fix for your agent. If the problem persists you should open a support ticket on Microsoft to troubleshoot the issue.

Update variable group using Azure DevOps rest API – pipeline example

Following my previous article about how to update a variable group using POSTMAN, I will now document how to implement the same behavior through a pipeline.

First things first you will need a PAT. I have included this PAT in a different variable group than the one that I will update. this is because when you update the variable group, all the variables that are inside will get lost. If you need to retain them, you should have to get them first and then add them again on the variable group.

For this reason I have created a variable group named token-group which holds my PAT. I also made this variable a secret.

The variable group that I will update has the name of var-group and the id of 5.

The pipeline includes two tasks. The first task will loop through the variables on the group and print them out. The second task will update the variable group based on the JSON that you provided. You should change your ORG and project URLs.

trigger:
– none
pr: none
pool:
vmImage: ubuntu-latest
variables:
– group: token-group
steps:
– task: PowerShell@2
displayName: Get variables from variable-group
inputs:
targetType: 'inline'
script: |
$connectionToken="$(PAT)"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$URL = "https://dev.azure.com/geralexgr/test-project/_apis/distributedtask/variablegroups?groupIds=5&api-version=7.1-preview.1"
$Result = Invoke-RestMethod -Uri $URL -Headers @{authorization = "Basic $base64AuthInfo"} -Method Get
$Variable = $Result.value.variables | ConvertTo-Json -Depth 100
Write-Host $Variable
– task: PowerShell@2
displayName: add variables on variable-group
inputs:
targetType: 'inline'
script: |
$connectionToken="$(PAT)"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$URL = "https://dev.azure.com/GeralexGR/test-project/_apis/distributedtask/variablegroups/5?api-version=5.1-preview.1"
$body = '{"id":5,"type":"Vsts","name":"var-group","variables":{"rest-var1":{"isSecret":false,"value":"rest-var-value-1"},"rest-var2":{"isSecret":false,"value":"rest-var-value-2"},"rest-var3":{"isSecret":false,"value":"rest-var-value-3"}}}'
$Result = Invoke-RestMethod -Uri $URL -Headers @{authorization = "Basic $base64AuthInfo"} -Method Put -Body $body -ContentType "application/json"
$Variable = $Result.value.variables | ConvertTo-Json -Depth 100
Write-Host $Variable

After running the pipeline you will notice a null output on the update of the variable group. This is the requested result and as task has not failed your var group will get updated.

Variables inside json

Powershell options for tasks – Azure Devops

Powershell is used very often on Azure DevOps tasks, as with it you can implement functionality that is not supported out of the box.

In this article I will explain some options that you may need during your executions.

You can fail a task on Azure Devops with powershell checks. For instance you can integrate your logic and if you get a response that is not the requested you can fail the task.

Fail a powershell task on Azure DevOps

$json = WebServiceCall ConvertFrom-Json
if ($json.value-eq "correct") { Write-Host success }  else { exit 1  }

Continue a failed task on Azure DevOps.

Under control options you should enable continue on error

This will result on a partial success.


Retry a failed task on failure

Run the task under certain conditions

Change working directory of powershell

When running a file path and not an inline script you can also define arguments