6

Situation

My self-hosted Windows Agent runs a pipeline from Azure DevOps. To manage resources in Azure I want to use an Azure CLI task. The AzureCLI task fails, even though Azure CLI is installed in a prior step.

I have two scripts that run from my pipeline.

  • (1) Install Azure CLI --> Success
  • (2) Run Azure CLI commands --> Fails without running ANY of the code inside, even "Hello, World!" does not get executed.
2021-03-05T14:50:02.5986237Z ##[error]Azure CLI 2.x is not installed on this machine.
2021-03-05T14:50:02.6391547Z ##[error]Script failed with error: Error: Unable to locate executable file: 'az'. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.

Microsoft says

  • (1) After you install new software on an agent, you must restart the agent for the new capability to show up in the pool so that the build can run.
  • (2) After the installation is complete, you will need to reopen PowerShell to use the Azure CLI.

The AzureCLI task is unable to find the installed Azure CLI executable. How can I fix this so that I can run the AzureCLI task?

What I tried already

  • Setting the PATH of Azure CLI via PowerShell. Path is set but the Powershell task for Azure CLI task fails.
  • Running AzureCLI commands directly in my installation script, which works but I need to log in to Azure with separate credentials while I want to use the service principal defined in my AzureCLI task.
  • Restarting Microsoft Agent services on the VM, but none of the services mentioned are on my agent (https://learn.microsoft.com/en-us/azure/devops/pipelines/agents/v2-windows?view=azure-devops)
  • Setting a delay before the Azure CLI task gets executed.
  • Using Microsoft Hosted agents, which works 100% but is not compliant for my company so not an option.

Pipeline details

trigger:
  branches:
    exclude:
    - master

pool:
  name: SelfHosted-AgentPool
  vmImage: 'windows-latest'

variables:
  environment.name: 'Test'

stages:
- stage: build_and_deploy
  jobs:
  - deployment: VMBackup_Testing  
    displayName: "Enable Backup Protection"
    environment: '$(environment.name)'
    strategy:
      runOnce:
        deploy:
          steps:
          - checkout: self    
          
         
          - task: PowerShell@2
            inputs:
              filePath: '$(System.DefaultWorkingDirectory)/Templates/Snippets/InstallAzureCLI.ps1'

          - task: AzureCLI@2
            inputs:
              workingDirectory: 'C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin'
              azureSubscription: 'XXX'
              scriptType: 'ps'
              scriptLocation: 'scriptPath'
              scriptPath: '$(System.DefaultWorkingDirectory)/Templates/Snippets/EnableBackupProtection.ps1'

Install Azure CLI script

# Download and Install Azure CLI
Invoke-WebRequest -Uri https://azcliprod.blob.core.windows.net/msi/azure-cli-2.19.1.msi -OutFile .\AzureCLI.msi; Start-Process msiexec.exe -Wait -ArgumentList "/I AzureCLI.msi /quiet"; rm .\AzureCLI.msi

# Update PATH for Powershell to use new installed software
setx /M PATH "$env:Path += ;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin"

# Test if PATH of Azure CLI exists
Test-Path -Path "C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin"

# Reload Shell with new PATH 
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")

# Check if AZ CLI is installed
az version

Azure CLI commands script

# Check if script gets executed
Write-Host "Hello, World!"

# AZ CLI commands to enable Backup Protection
az backup protection enable-for-vm `
    --resource-group XXX`
    --vault-name XXXX`
    --vm $(az vm show -g XXX -n XXX --query id) `
    --policy-name DailyBackup
Falco
  • 101
  • 1
  • 1
  • 8
  • Restarting the agent is recommended to reflect path and other system level setting on the machine for new software installs. Sounds like you are not manually installing the CLI but installing as part of your pipeline, can you ensure that after installation path is set correctly? If you can update the path it should work, however it will be good to install cli and restart the agent on the machine. If it is hosted machine it should not be an issue. – Sujit Singh Mar 06 '21 at 22:44
  • CLI is indeed being installed as part of the pipeline. How can I restart the agent on the machine? I do not see "VSTS Agent" or anything similar running under services. – Falco Mar 07 '21 at 06:48
  • I added tasks to update the path, but even then I run into the same error (Azure CLI 2.x is not installed on this machine.) – Falco Mar 07 '21 at 07:32
  • They appear as Azure DevOps pipeline agents on the machine, after VSTS (Visual Studio Team Services) renamed to Azure DevOps agents also gets installed with different name. – Sujit Singh Mar 07 '21 at 09:07
  • The closest service available is "Windows Azure Guest Agent", but restarting that service results in the same error. – Falco Mar 07 '21 at 09:38
  • 2
    I updated my post to reflect new findings. I am able to install Azure CLI and run ''az version'' successfully as part of a PowerShell task. However I need the AzureCLI@2 task as it uses a Service Principal that I have already configured. This task fails because it cannot find the installed AzureCLI. – Falco Mar 07 '21 at 09:59
  • Hi @Falco, how are things going? Is the suggestion in my answer helpful to you? Please have a check with it. Any update, feel free to tell us. Thanks. – Bright Ran-MSFT Mar 17 '21 at 07:50

2 Answers2

1

Why do you need to install the Azure CLI every time when you run the pipeline on the same self-hosted Windows agent?

Unlike Microsoft-hosted agents, you just need to manually install the required tools on the self-hosted agent machine, then you can use them in the pipelines that run on the agent.

  1. Login to your Windows machine (local or VM) where the self-hosted agent is installed.

  2. Open the web browser to download the MSI installer of the released latest Azure CLI from here.

  3. When installing the Azure CLI via the MSI installer, normally install wizard will automatically add this tool to the system environment variable PATH. After the installation completed, you can open "Edit the system environment variables" on the machine to check it. If it is not added to the system environment variable PATH, you can manually add it.

enter image description here

  1. After above steps, as the documentation has recommended, restart the agent service or restart the machine so that the installed Azure CLI tool can be listed in the capabilities of the agent in the pool.

With this way, when you set a pipeline to run on this self-hosted agent, you can directly call the Azure CLI and no need any step to installing Azure CLI in the pipeline.

Bright Ran-MSFT
  • 5,190
  • 1
  • 5
  • 12
  • 2
    We will only have deployments at most once per quarter, therefore we do not have a need to have an agent running at all times. The time it takes to reinstall Azure CLI is not a blocker, and we prefer to have fresh machines whenever we run a deployment. The current status is that Azure CLI installs fine and that we can use Azure CLI from the generic PowerShell task, however the "AzureCLI@2" built-in task from Azure Pipelines is looking for the executable az in the wrong folder ('C:\a\1\s) instead of Program Files. – Falco Mar 10 '21 at 09:24
  • 1
    Hi @Falco, if you want to have a fresh machine every time when you run a deployment. I recommend you use [Microsoft-hosted agents](https://learn.microsoft.com/en-us/azure/devops/pipelines/agents/agents?view=azure-devops&tabs=browser#microsoft-hosted-agents) or [Azure virtual machine scale set agents](https://learn.microsoft.com/en-us/azure/devops/pipelines/agents/agents?view=azure-devops&tabs=browser#azure-virtual-machine-scale-set-agents), instead of self-hosted agents on your machine. – Bright Ran-MSFT Mar 11 '21 at 06:09
  • 1
    Hi @Falco, how are things going? Have you tried using Microsoft-hosted agents or Azure virtual machine scale set agents? Does it work for you? Please have a try with it. Any update, feel free to tell us. Thanks. – Bright Ran-MSFT Mar 24 '21 at 06:35
  • Ended up using a combination of VMSS Self-hosted agents for non-AZ CLI tasks, and Microsoft-hosted agent for Azure CLI tasks. Restarting the self-hosted made it possible to run AZ CLI tasks, but since we are using a scale set we cannot restart an agent. – Falco Mar 25 '21 at 20:10
  • Hi @Falco, actually you also can restart the VMSS agent via restart the VM within the VMSS. You can manually restart the VM on Azure Portal web UI, or use the '[az vmss restart](https://learn.microsoft.com/en-us/cli/azure/vmss?view=azure-cli-latest#az_vmss_restart)' command. Anyway, glad that the task can work normally in your pipeline now. If my answer is helpful to you to solve the problem maybe you can mark it as the solution of this topic. This could be also very helpful to other people who are looking for solution for the similar questions. Thanks. – Bright Ran-MSFT Mar 26 '21 at 08:09
0

To truly update the PATH for future steps/tasks in the pipeline, try adding:

[Environment]::SetEnvironmentVariable("Path", $env:Path, "Machine")
$azCliPath = "C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin"
echo "##vso[task.prependpath]$azCliPath"

to your InstallAzureCLI.ps1.

I don't if both are needed, maybe just echo "##vso[task.prependpath]....

Documentation about updating the path: https://learn.microsoft.com/en-us/azure/devops/pipelines/scripts/logging-commands?view=azure-devops&tabs=bash#prependpath-prepend-a-path-to-the--path-environment-variable

Justin Harris
  • 1,969
  • 2
  • 23
  • 33