Powershell output in Octopus Step

Hi,

I have a step that is trying to tag an AWS instance with the Octopus release number. This is the script:


# Get instanceid
$resourceID = Invoke-RestMethod "http://169.254.169.254/latest/meta-data/instance-id"
Write-Output "resourceID is $resourceID"

# set a tag for "Release Version"
$Tags = @( @{key="Release Version";value=$releaseversion} )
$cmd = New-EC2Tag -ResourceId $resourceID -Tags $Tags -Region "ap-southeast-2"

if($cmd){
    Write-Output "Instance $resourceID tagged with $($tags.key) $($tags.value)"
}

My problem is the firest Write-Output writes to screen ok, but the second never shows anything, even though the instance is tagged correctly.
Am I missing something with how the Powershell pipeline works with Octopus Deploy?

Hi Kirk,
According to the documentation of New-EC2Tag cmdlet may conditionally return no output. If this is happening in your particular case then I would expect the 2nd Write-Output to not get invoked. Could you confirm that the $cmd value is indeed getting set with a value after this invocation.
Powershell should follow the same standard rules when invoked via an Octopus Deploy process.
Look forward to hearing your reply,
Cheers
Robert

Hi Robert,

Thanks for responding.
Even if there was no output from $cmd, I would expect the boolean eval for
it to have to been true, as that does not require an output, just whether
the command ran successfully.

As a test, I ran the following intentionally failing script - once from the
Octopus tasks console, and once from the Powershell ISE.


# Get instanceid
$resourceID = "i-wiegfsik"
$releaseversion = "1234"

Write-Output "resourceID is $resourceID"

# set a tag for "Release Version"
$Tags = @( @{key="Release Version";value=$releaseversion} )
$cmd = New-EC2Tag -ResourceId $resourceID -Tags $Tags -Region
"ap-southeast-2"

$?

if($cmd){
    Write-Output "Instance $resourceID tagged with $($tags.key)
$($tags.value)"
} else {
    Write-Output "Instance $resourceID could not be tagged with
$($tags.key) $($tags.value)"
}

In this script, $resourceID is invalid.

Output from Octopus Tasks console:

resourceID is i-wiegfsik
New-EC2Tag : The ID ‘i-wiegfsik’ is not valid
At C:\Octopus\Work\20151006025448-9365\Script.ps1:9 char:8

  • $cmd = New-EC2Tag -ResourceId $resourceID -Tags $Tags -Region “ap-southeast-2”
 + CategoryInfo : InvalidOperation: (Amazon.PowerShe...NewEC2TagCm 
 dlet:NewEC2TagCmdlet) [New-EC2Tag], InvalidOperationException
 + FullyQualifiedErrorId :
Amazon.EC2.AmazonEC2Exception,Amazon.PowerShell. 
 Cmdlets.EC2.NewEC2TagCmdlet
Info
Exit code: 1
The remote script failed with exit code 1

Output from Powershell ISE:

resourceID is i-wiegfsik
New-EC2Tag : The ID 'i-wiegfsik' is not valid At
line:9 char:8 + $cmd = New-EC2Tag -ResourceId $resourceID -Tags $Tags
-Region "ap-southeast-2" +
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
CategoryInfo : InvalidOperation:
(Amazon.PowerShe...NewEC2TagCmdlet:NewEC2TagCmdle t) [New-EC2Tag],
InvalidOperationException + FullyQualifiedErrorId :
Amazon.EC2.AmazonEC2Exception,Amazon.PowerShell.Cmdlets.EC2.NewEC2T
agCmdlet
False
Instance i-wiegfsik could not be tagged with Release Version
1234

As you can see, $? is correctly evaluated to False, as the command failed.
As well, the IF condition is successfully hit, with the else statement
processed.

We are using Octopus 3.0.14.2400 if that makes any difference.

Thanks,

Kirk

Hi Kirk,
You are right that there is a behavioral difference here. When we execute user-provided PowerShell scripts we execute them with the $ErrorActionPreference set to 'Stop' so that a failing deployment stops immediately (msdn). By default this value is set to Continue

So while your script might be

$g = Nothing
Write-Host "I Shouldn't Apppear if Errors Stop Execution"

Which outputs
Error..... I Shouldn't Apppear if Errors Stop Execution

When run from within OctopusDeploy it actually looks closer to

$ErrorActionPreference = 'Stop'
$g = Nothing
Write-Host "I Shouldn't Apppear if Errors Stop Execution"

resulting in just
Error....

If the New-EC2Tag cmdlet is indeed throwing an error as in your intentionally failing script then you might want to think about wrapping it with some try..catch logic.
Something along the lines of

# Get instanceid
$resourceID = Invoke-RestMethod "http://169.254.169.254/latest/meta-data/instance-id"
Write-Output "resourceID is $resourceID"

# set a tag for "Release Version"
$Tags = @( @{key="Release Version";value=$releaseversion} )

Try {
  $cmd = New-EC2Tag -ResourceId $resourceID -Tags $Tags -Region "ap-southeast-2"
}
Catch {
  #Do Something?
}
Finally {
  if($cmd){
      Write-Output "Instance $resourceID tagged with $($tags.key) $($tags.value)"
  }
}

Give this approach a go and let me know if this makes sense & solves your problem.
Thanks,
Rob

Hi Robert,

This is my new script body:


# Get instanceid
$resourceID = Invoke-RestMethod "http://169.254.169.254/latest/meta-data/instance-id"
Write-output "resourceid is $resourceid"

$releaseversion = "1234"

# set a tag for "Release Version"
$Tags = @( @{key="Release Version";value=$releaseversion} )
$cmd = New-EC2Tag -ResourceId $resourceID -Tags $Tags -Region "ap-southeast-2"

Try {
  $cmd = New-EC2Tag -ResourceId $resourceID -Tags $Tags -Region "ap-southeast-2"
}
Catch {
  $error[0].exception
}
Finally {
  if($cmd){
      Write-Output "Instance $resourceID tagged with $($tags.key) $($tags.value)"
  } else {
      Write-Output "Instance $resourceID could not be tagged with $($tags.key) $($tags.value)"
  }
}

This is the response:


Executing script on tentacle 'WIN-600OE1PUR11'
resourceid is i-757603ab
Instance i-757603ab could not be tagged with Release Version 1234
Exit code: 0

Changing the script to intentionally fail:


# Get instanceid
$resourceID = "i-osidakl"
Write-output "resourceid is $resourceid"

$releaseversion = "1234"

# set a tag for "Release Version"
$Tags = @( @{key="Release Version";value=$releaseversion} )

Try {
  $cmd = New-EC2Tag -ResourceId $resourceID -Tags $Tags -Region "ap-southeast-2"
}
Catch {
  $error[0].exception
}
Finally {
  if($cmd){
      Write-Output "Instance $resourceID tagged with $($tags.key) $($tags.value)"
  } else {
      Write-Output "Instance $resourceID could not be tagged with $($tags.key) $($tags.value)"
  }
}

Output is:


Executing script on tentacle 'WIN-600OE1PUR11'
resourceid is i-osidakl
The ID 'i-osidakl' is not valid
Instance i-osidakl could not be tagged with Release Version 1234
Exit code: 0

So it looks like it :

  1. Set the tag on the instance correctly
  2. Hit the Finally statement, but hit the else condition incorrectly.

Still seems like the boolean eval for the return code of $cmd is not surfacing to be checked.

Hi Kirk,
I think this looks correct to me. Since New-EC2Tag is returning nothing in both cases, whether its a valid tag or not, if($null) is resolving as false.

$val
Write-Host "(" $val ")"
if($val) {
Write-Host "Will Never Appear"
}

will only result in
( )

I think you are expecting $cmd to return the exit code but as I pointed out earlier that’s not what the documentation indicates.
Am I understanding this correctly?
Cheers,
Robert