Search code examples
powershellaws-clipowershell-4.0

Add values inside foreach powershell


I have the following code:

foreach ($region in (Get-AWSRegion)) {
    $images = aws ec2 describe-instances --output text --query 'Reservations[*].Instances[*].[ImageId]' | sort | uniq -c
}

$images

Above code gives me something like:

3 ami-123**

But I am trying to get all AMI's inside all regions together so it should be something like:

9 ami-123**

When I try something like:

$images += aws ec2 describe-instances --output text --query 'Reservations[*].Instances[*].[ImageId]' | sort | uniq -c

I get: 3 ami-123** 3 ami-123** 3 ami-123**

Is there a way to do this?


Solution

  • Three immediate problems - first, you keep overwriting the value of $images inside the loop, and as you've found you can solve that by adding to the previous result set.

    Second problem is that you're not actually targeting the $region, so you keep getting the same result from the default region configured for aws - specify --region $region inside the loop (assuming that Get-AWSRegion returns the region identifier as a string).

    Third problem is a bit more... fundamental - the aws cli returns a string, so you'll need to manually parse that and aggregate the results - you could do so with a [hashtable] and a simple regex pattern:

    # Create hashtable to aggregate results
    $ImageIDCounts = @{}
    
    foreach($region in Get-AWSRegion){
        $perRegionCount = aws ec2 describe-instances --region $region --output text --query 'Reservations[*].Instances[*].[ImageId]' | sort | uniq -c
        foreach($entry in $perRegionCount){
            if($entry -match '^\s*(\d+)\s+(.*)$'){
                $Count = $Matches[1] -as [int]
                $ImageID = $Matches[2].Trim()
    
                $ImageIDCounts[$ImageID] += $Count 
            }
        }
    }
    

    $ImageIDCounts now contains one entry per unique ImageID, so you can do:

    $ami123count = $ImageIDCounts['ami-123']