3

We have a powershell script that executes in our pipeline and it has a few commands which should not stop if any error occurs. I tried putting the script block inside a try/catch but the pipeline still stopes with error:

enter image description here

This is the code:

    try {   
        az network dns record-set txt add-record `
            -g $ResourceGroup `
            -n "asuid.$DomainName" `
            -v $VerificationId `
            -z $Zone
    
        $record = az network dns record-set cname create `
            -g $ResourceGroup `
            -n $DomainName `
            -z $Zone `
            -o json | ConvertFrom-Json
    
        az network dns record-set cname set-record `
            -g $ResourceGroup `
            -n $record.name `
            -c $Alias `
            -z $Zone
    }
    catch {
        Write-Warning "Creating a DNS record was not possible. Consider creating it by hand or review the error:"
        Write-Warning $_
    }

I know a few workarounds for that like telling the pipeline to continue on error or just executing the cmdLet with -ErrorAction Continue, but for me it does not make any sense why this wouldn't work the way I did. At least for me who comes from C# and other languages, that would the default bahavior if you don't want to rethrow the exception.

What concept am I missing?

EDIT 1

Here is the part of the yaml with the task which is failling:

  - task: AzureCLI@2
    name: create_dns_record
    displayName: "Creates a DNS record for CNAME and TXT on DNS Zone"
    inputs:
      azureSubscription: 'some-azure-subscription'
      scriptType: 'pscore'
      scriptLocation: 'inlineScript'
      inlineScript: |
        . $(System.DefaultWorkingDirectory)/cd/NewDNSRecordSet.ps1
          
        New-DNSRecordSet `
            -ResourceGroup 'rg_zones' `
            -DomainName '$(domain_name)' `
            -Zone '$(dns_zone)' `
            -VerificationId '$(verificationId)' `
            -Alias '$(defaultHostName)' # verificationId and defaultHostName as output from the task CreateInfrastructure.ps1

Here is the output of the pipeline:

Creating DNS Recordset for 'mytest.dev' zone.
Adding txt record: asuid.mytest
ResourceNotFoundError: Resource group 'rg_zones' could not be found.
Creating CNAME record: mytest
ResourceNotFoundError: Resource group 'rg_zones' could not be found.
WARNING: Creating a DNS record was not possible.
##[error]Script failed with exit code: 1
DAG
  • 2,460
  • 5
  • 33
  • 61
  • Which command of these 3 fail? It's the first one? And if it's the first one, does the other two get executed? – Vivere Apr 19 '21 at 18:00
  • Normally `az` commands are idempotent. The ony failling is the last one because `$record` is **null**. it's a null reference exception. I added a `if ($record)..` but the pipeline still stops with an error. – DAG Apr 19 '21 at 18:26
  • That's because of the `$LASTEXITCODE` automatic variable. You should also set `$ErrorActionPreference = 'Stop'` – Vivere Apr 19 '21 at 18:28
  • But I don't want to stop, the pipeline should continue... `$ErrorActionPreference = 'Stop'` would make my pipeline stop – DAG Apr 19 '21 at 18:33
  • 1
    If your [$ErrorActionPreference](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_preference_variables?view=powershell-7.1#erroractionpreference) is set to `Continue/SilentlyContinue` a command that would throw an error is instead running fine, meaning that if you have something in your try block that **could** throw, it will never go in the catch block. And from what I see in your post, it is exactly something that you don't expect. Test your script locally first. – Vivere Apr 19 '21 at 18:40

1 Answers1

2

So to test my assumption I wrote this bit of code locally in my PowerShell:

$ErrorActionPreference = 'Stop'

try {
    & 'az' @('group', 'show', '--name', 'foo')

    Write-Host "in try: $LASTEXITCODE"
}
catch {
    $_
    Write-Host "in catch: $LASTEXITCODE"
}

I get the output:

Resource group 'foo' could not be found.
in try: 3

So the az command failed, with a non-zero exit code but it didn't throw an error. The try block executes fine and my script ends.

If you run this in a pipeline, the non-zero exit code would result in the pipeline failing. My proposition is to create some kind of helper method for executing az CLI commands in PowerShell, verify the $LASTEXITCODE and throw an error yourself so you could catch it later.

Vivere
  • 1,919
  • 4
  • 16
  • 35
  • That is a good one. I think the error is with the `AzureCLI` task in Azure DevOps, so I don't understand what is the AzureCLI task doing behind the scenes. The try catch should do the job. I'll update my thread with the yaml part. – DAG Apr 19 '21 at 18:20
  • good stuff. I Ended up indeed writing a helper – XWIKO Dec 16 '21 at 13:54