Ansible, Windows and PowerShell: the Basics – Part 5, Example PowerShell Error Handling

In Part 5 of this series we’ll continue our journey with Ansible, Windows and PowerShell and look at how we can lay out code in PowerShell scripts in order to return error codes to Ansible to determine the success or failure of a task.

In my experience different automation and orchestration toolsets can require you to return errors from PowerShell scripts in different ways. So far with Ansible I have found that returning an exit code of 0 (success) or 1 (failure) from the PowerShell script to Ansible will result in the success or failure of that task in the Playbook. I experimented with other numbers for return codes to see if I could use them to establish different types of failure, but Ansible did not appear to support that. (If you have other experiences with PowerShell, return codes and Ansible then please leave them in the comments below.)

So the following example will demonstrate how to ensure that an exit code of 0 or 1 is returned from the PowerShell script executed by Ansible to the task which executed it.

Our job template in AWX is _4_example-errorhandling

The contents of _4_example-errorhandling.yml are are follows:

The first task copies the PowerShell script with the example error handling to the target and the second task executes that script.

The contents of Example-ErrorHandling.ps1 are as follows:

Two things to note:

Setting $ErrorActionPreference to Stop

Not all errors generated in PowerShell by cmdlets are the same! There are two types, terminating and non-terminating, and only terminating errors will take you into the catch block. Consequently, you may get errors in your script that are non-terminating, but the script could still be determined a success. Sometimes you may be surprised about what a cmdlet author determined to be a non-terminating error - this has caught me out a number of times in the past.

So, depending on how you want to handle this scenario, you may wish to set $ErrorActionPreference to Stop. This will force even non-terminating errors to take the code into the catch block and consequently exit the script with a return code of 1.

ErrorAction Continue

On a similar note, watch out for the -ErrorAction Continue added to the end of the Write-Error lines in the catch block. A consequence of setting $ErrorActionPreference to Stop means that Write-Error will generate a terminating error, not the non-terminating error that is its default behaviour. Without forcing the ErrorAction to be Continue for those to lines only, the script would exit at line 10 and the extra error lines won’t be present in the output.

Running a job from the _2 example-errorhandling job template produces the failed result we are looking for:

Looking at more detail to the task with the error, we can observe that we received an exit code of 1 and the detailed error info from the catch block: