2

I have a PowerShell script which is collecting vm image version lists and sorting into descending order with the highest value:

$imagegallery = Get-AzGallery -ResourceGroupName rg-shared-inva-eastus
Write-Output $imagegallery.Name

$imagegallerydefinitioninfo = @("PeriscopeMQ","PeriscopeApp","PeriscopeWeb")

foreach ($imagedefinition in $imagegallerydefinitioninfo) {
      $imagegalleryimageversion = Get-AzGalleryImageVersion -GalleryName $imagegallery.Name -ResourceGroupName $imagegallery.ResourceGroupName -GalleryImageDefinitionName $imagedefinition
      Write-Output $imagegalleryimageversion.Tags.PeriscopeVmImageVersion |Sort-Object -Descending { [regex]::Replace($_, '\d+', { $args[0].Value.PadLeft(2)}) }   
}

Output is :

5.11.4
5.11.3
5.11.2
5.11.1
5.11.0
5.10.56
5.10.55
5.10.9
5.10.8
5.10.7
5.10.6
5.9.98
5.9.97
5.9.96
5.9.93
5.8.90

I want to convert this into 2 places decimals like:

5.11
5.10
5.9
5.8

and, find the highest version which is 5.11 and skip the 02, and delete the third version.

Can anyone please help me with this?

Thanks

1 Answers1

2

Use the .ToString(int fieldCount) overload to print [version] (System.Version) instances only by their first two fields (.Major and .Minor); a simple example:

# -> '1.2'
([version] '1.2.3.4').ToString(2)

Note that you can sort [version] instances as-is, which allows you to apply the .ToString() call to the result of your Sort-Object call; if the .PeriscopeVmImageVersion property values are version strings rather than [version] instances, you can cast to [version[]]:

[version[]] $imagegalleryimageversion.Tags.PeriscopeVmImageVersion |
  Sort-Object -Descending |
  ForEach-Object ToString 2 | 
  Get-Unique

Note:
* ForEach-Object ToString 2 is simplified syntax for: ForEach-Object { $_.ToString(2) }
* Write-Output is intentionally not used; the command relies on PowerShell's implicit output behavior in the first pipeline segment, which is both more concise and efficient (and doesn't change the syntax requirements). For background information, see this answer.

The (rarely used) Get-Unique cmdlet is used to output only one string for each group of versions sharing the same major and minor values.Tip of the hat to Andrew Morton.


To apply the sorting and formatting across all loop iterations (across all image-gallery definitions), use the following (note the switch to ForEach-Object and the use of the automatic $_ variable to refer to the pipeline input object at hand:

$imagegallerydefinitioninfo |
  ForEach-Object {
    $imagegalleryimageversion = Get-AzGalleryImageVersion -GalleryName $imagegallery.Name -ResourceGroupName $imagegallery.ResourceGroupName -GalleryImageDefinitionName $_
    [version[]] $imagegalleryimageversion.Tags.PeriscopeVmImageVersion
  } |
  Sort-Object -Descending |
  ForEach-Object ToString 2 | 
  Get-Unique

To address your final requirement, which I understand to be the following:

  • In each group of version numbers sharing the same major and minor field values, find the highest one.

  • From the 2 groups representing the highest version numbers overall, remove the highest version each, representing the images to keep.

  • Output the remaining versions in descending order.

$groupIndex = 0
$imagegallerydefinitioninfo |
  ForEach-Object {
    $imagegalleryimageversion = Get-AzGalleryImageVersion -GalleryName $imagegallery.Name -ResourceGroupName $imagegallery.ResourceGroupName -GalleryImageDefinitionName $_
    [version[]] $imagegalleryimageversion.Tags.PeriscopeVmImageVersion
  } |
  Group-Object -Property Major, Minor | 
  Sort-Object -Descending { $_.Group[0] } |
  ForEach-Object { 
    if (++$groupIndex -le 2) {
      $_.Group | Sort-Object -Descending | Select-Object -Skip 1
    } else {
      $_.Group | Sort-Object -Descending
    } 
  } |
  ForEach-Object ToString # ... process further as needed.
  • Group-Object is used to group the version numbers by shared major and minor field values.

  • For-EachObject ToString prints the [version] objects as strings with all fields, so you can verify that the correct versions are reported; you may want to capture the [version] output as-is, so you can use it in a VM removal command.

With your sample input, this in effect eliminates the following two version numbers from the input: 5.11.4 and 5.10.56.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Hi @mklement0, The last part didn't worked well, gettiing below output: Major Minor Build Revision ----- ----- ----- -------- 5 10 62 -1 5 11 9 -1 5 4 416 -1 5 5 102 -1 5 6 247 -1 its not arranging with Descending order and not skipping correct version – Sheikh Sadique Mar 06 '23 at 05:33
  • @SheikhSadique, yes, there were logic errors in the solution, sorry. Please see my update, which hopefully now produces the desired output - assuming I understood the requirements correctly.. – mklement0 Mar 06 '23 at 08:44
  • No, I want , supoose I have these images 5.11.4 5.11.3 5.11.2 5.11.1 5.11.0 5.10.56 5.10.55 5.10.9 5.10.8 5.10.7 5.10.6 5.9.98 5.9.97 5.9.96 5.9.93 5.8.90 5.8.10 5.7.98 so it should take 5.11.* is latest or highest version And, skip 2 more versions like 5.10.* and 5.9.* and delete all remaining older versions e.g 5.8.90 5.8.10 5.7.98, in this – Sheikh Sadique Mar 06 '23 at 12:04
  • @SheikhSadique, I'm still unclear on your requirements. Are you saying you want the highest version numbers from the first 3 groups _returned_ rather than _removed_? Using your latest sample data, please spell out the desired result _in full_. – mklement0 Mar 06 '23 at 13:34
  • @SheikhSadique, without clear requirements, no one will be able to help you. If you have trouble expressing the requirements in the limited space and with the limited formatting capabilities in _comments_, consider asking a _new question_ that focuses only on the one remaining task. – mklement0 Mar 07 '23 at 19:01