I am writing a number of functions for starting and stopping EC2 instances by the name tag not the ID. First I wrote a reporting function that can be found below.
Function Get-EC2InstanceReport{
If((Get-Module -Name AWSPowerShell).Name -ne 'AWSPowerShell'){
Throw 'AWSPowerShell module is not loaded'
}
Get-EC2Tag | `
Where-Object {$_.ResourceType -eq 'instance' -and $_.Key -eq 'Name'} | `
Select-Object @{Name='InstanceID'; Expression={$_.ResourceID}}, @{Name='Name'; Expression={$_.Value}}, `
@{Name='Status'; Expression={Get-EC2InstanceStatus -IncludeAllInstances $true -InstanceId $_.ResourceID | % {$_.InstanceState.Name}}}
}
And the function to start the instance works without error.
Function Start-EC2InstanceByName ([string]$Name){
If((Get-Module -Name AWSPowerShell).Name -ne 'AWSPowerShell'){
Throw 'AWSPowerShell module is not loaded'
}
[object]$EC2Instance = Get-EC2InstanceReport | Where-Object {$_.Name -eq $Name}
Try{
If($EC2Instance[0].Status -eq 'stopped'){
Start-EC2Instance -InstanceId $EC2Instance[0].InstanceId | Out-Null
Test-EC2InstanceStatus -Name $Name -EndState 'running'
}
Else{
$ErrorMsg = "EC2 instance " + $EC2Instance[0].Name + " is not in the stopped state. It is " + $EC2Instance[0].Status + "."
Throw $ErrorMsg
}
}
Catch{
$_
}
}
But when using a similar method to stop the instance I get an error.
Function Stop-EC2InstanceByName ([string]$Name){
If((Get-Module -Name AWSPowerShell).Name -ne 'AWSPowerShell'){
Throw 'AWSPowerShell module is not loaded'
}
[object]$EC2Instance = Get-EC2InstanceReport | Where-Object {$_.Name -eq $Name}
Try{
If($EC2Instance[0].Status -eq 'running'){
Stop-EC2Instance -Instance $EC2Instance[0].InstanceID | Out-Null
Test-EC2InstanceStatus -Name $Name -EndState 'stopped'
}
Else{
$ErrorMsg = "EC2 instance " + $EC2Instance[0].Name + " is not in the running state. It is " + $EC2Instance[0].Status + "."
Throw $ErrorMsg
}
}
Catch{
$_
}
}
The error can be found below.
Stop-EC2Instance : No instances specified
At C:\GitProjects\DBA\aws-powershell-scripts\AWSFunctions.psm1:61 char:4
+ Stop-EC2Instance -Instance $EC2Instance[0].InstanceID | Out-Null
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Stop-EC2Instance], AmazonEC2Exception
+ FullyQualifiedErrorId : Amazon.EC2.AmazonEC2Exception,Amazon.PowerShell.Cmdlets.EC2.StopEC2InstanceCmdlet
Any help would be greatly appreciated. If you require any further info please let me know.
Further progress.
Right, not resolved why the error occurs and have that open on the AWS forum over at amazon https://forums.aws.amazon.com/thread.jspa?threadID=143319
But the desired behaviour can be created by changing the function to that below.
Function Stop-EC2InstanceByName ([string]$Name){ If((Get-Module -Name AWSPowerShell).Name -ne 'AWSPowerShell'){ Throw 'AWSPowerShell module is not loaded' } [object]$EC2Instance = Get-EC2InstanceReport | Where-Object {$_.Name -eq $Name}
Try{
If($EC2Instance[0].Status -eq 'running'){
Get-EC2Instance -Filter @{Name="tag:Name"; Value=$Name} | Stop-EC2Instance | Out-Null
Test-EC2InstanceStatus -Name $Name -EndState 'stopped'
}
Else{
$ErrorMsg = "EC2 instance " + $EC2Instance[0].Name + " is not in the running state. It is " + $EC2Instance[0].Status + "."
Throw $ErrorMsg
}
}
Catch{
$_
}
}
Simply converting via .ToString()
got the desired result for me, without having to pass input via pipeline.
# Failed attempt
PS C:\> Stop-EC2Instance -Instance $myInstance.InstanceId
Stop-EC2Instance : No instances specified
At line:1 char:17
+ Stop-EC2Instance <<<< -Instance $myInstance.InstanceId
+ CategoryInfo : NotSpecified: (:) [Stop-EC2Instance], AmazonEC2Exception
+ FullyQualifiedErrorId : Amazon.EC2.AmazonEC2Exception,Amazon.PowerShell.Cmdlets.EC2.StopEC2InstanceCmdlet
# Successful attempt
PS C:\> Stop-EC2Instance -Instance $myInstance.InstanceId.ToString()
# Goodnight instance...
Which is... odd, because when we use Get-Member
on your instance object we can see that there is a string defined there in InstanceID:
TypeName: Selected.Amazon.EC2.Model.ResourceTag
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
InstanceID NoteProperty System.String InstanceID=i-abcd1234
Name NoteProperty System.String Name=MyInstance
Status NoteProperty Status=null
Passing the InstanceID via pipeline input worked because it can accept System.Object[]
, whereas it seems explicitly using -Instance
would rather you use a string Instance ID. The Stop-EC2Instance documentation corroborates this:
-Instance <Object[]>
Identifies the set of instances to stop or terminate. Accepts a string instance ID or a collection of RunningInstance or Reservation objects. If a Reservation object is supplied, all of the instances in the reservation are processed.
Required? False
Position? 1
Accept pipeline input? True (ByValue, )