From 57ad896afa35f0e6133f2531cb108a0b11c7da23 Mon Sep 17 00:00:00 2001 From: Aleksandr Levochkin <107044793+aleksandrlevochkin@users.noreply.github.com> Date: Tue, 24 Sep 2024 14:04:02 +0200 Subject: [PATCH] Add script for checking if agents support upgrade to v4 (#4995) * Add script for checking if agents support upgrade to v4 * Change comments * Refactor existing script to support v2/v3 -> v4 migration * Remove unnecessary V4 script --------- Co-authored-by: v-levockina --- .../QueryAgentPoolsForCompatibleOS.ps1 | 210 +++++++++--------- 1 file changed, 105 insertions(+), 105 deletions(-) diff --git a/tools/FindAgentsNotCompatibleWithAgent/QueryAgentPoolsForCompatibleOS.ps1 b/tools/FindAgentsNotCompatibleWithAgent/QueryAgentPoolsForCompatibleOS.ps1 index 3927fd7b40..37318a5d30 100644 --- a/tools/FindAgentsNotCompatibleWithAgent/QueryAgentPoolsForCompatibleOS.ps1 +++ b/tools/FindAgentsNotCompatibleWithAgent/QueryAgentPoolsForCompatibleOS.ps1 @@ -1,10 +1,10 @@ #!/usr/bin/env pwsh <# .SYNOPSIS - Predict whether agents will be able to upgrade from pipeline agent v2 to agent v3 + Predict whether agents will be able to upgrade from pipeline agent v2 or v3 to agent v4 .DESCRIPTION - The Azure Pipeline agent v2 uses .NET 3.1 Core, while agent v3 runs on .NET 6. This means agent v3 will drop support for operating systems not supported by .NET 6 (https://github.com/dotnet/core/blob/main/release-notes/6.0/supported-os.md) + The Azure Pipeline agent v2 uses .NET 3.1 Core, and agent v3 uses .NET 6, while agent v4 runs on .NET 8. This means agent v4 will drop support for operating systems not supported by .NET 8 (https://github.com/dotnet/core/blob/main/release-notes/8.0/supported-os.md) This script will try to predict whether an agent will be able to upgrade, using the osDescription attribute of the agent. For Linux and macOS, this contains the output of 'uname -a`. Note the Pipeline agent has more context about the operating system of the host it is running on (e.g. 'lsb_release -a' output), and is able to make a better informed decision on whether to upgrade or not. Hence the output of this script is an indication wrt what the agent will do, but will include results where there is no sufficient information to include a prediction. @@ -17,7 +17,7 @@ ./QueryAgentPoolsForCompatibleOS.ps1 -Token "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" .EXAMPLE $env:AZURE_DEVOPS_EXT_PAT = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - ./QueryAgentPoolsForCompatibleOS.ps1 -PoolId 1234 -Filter V3InCompatible -Verbose -OpenCsv + ./QueryAgentPoolsForCompatibleOS.ps1 -PoolId 1234 -Filter V4InCompatible -Verbose -OpenCsv #> #Requires -Version 7.2 @@ -47,9 +47,9 @@ param ( [parameter(Mandatory=$false)] [parameter(ParameterSetName="pool")] [parameter(ParameterSetName="os")] - [ValidateSet("All", "ExcludeMissingOS", "MissingOS", "V3Compatible", "V3CompatibilityIssues", "V3CompatibilityUnknown", "V3InCompatible")] + [ValidateSet("All", "ExcludeMissingOS", "MissingOS", "V4Compatible", "V4CompatibilityIssues", "V4CompatibilityUnknown", "V4InCompatible")] [string] - $Filter="V3CompatibilityIssues", + $Filter="V4CompatibilityIssues", [parameter(Mandatory=$false)] [switch] @@ -66,11 +66,11 @@ param ( class ClassificationResult { hidden [int]$_sortOrder = 1 - hidden [string]$_upgradeStatement = "OS (version) unknown, v2 agent won't upgrade to v3 automatically" + hidden [string]$_upgradeStatement = "OS (version) unknown, agent won't upgrade to v4 automatically" [ValidateSet($null, $true, $false)] - hidden [object]$_v3AgentSupportsOS + hidden [object]$_v4AgentSupportsOS [ValidateSet("MissingOS", "Unsupported", "Unknown", "UnknownOS", "UnknownOSVersion", "UnsupportedOSVersion", "Supported")] - hidden [string]$_v3AgentSupportsOSText = "Unknown" + hidden [string]$_v4AgentSupportsOSText = "Unknown" [string]$_reason ClassificationResult() { @@ -95,36 +95,36 @@ class ClassificationResult { $this._upgradeStatement = $value } - $this | Add-Member -Name V3AgentSupportsOS -MemberType ScriptProperty -Value { + $this | Add-Member -Name V4AgentSupportsOS -MemberType ScriptProperty -Value { # Get - return $this._v3AgentSupportsOS + return $this._v4AgentSupportsOS } -SecondValue { # Set param($value) - $this._v3AgentSupportsOS = $value - if ($value -eq $null) { + $this._v4AgentSupportsOS = $value + if ($null -eq $value) { $this._sortOrder = 1 - $this._v3AgentSupportsOSText = "Unknown" - $this._upgradeStatement = "OS (version) unknown, v2 agent won't upgrade to v3 automatically" + $this._v4AgentSupportsOSText = "Unknown" + $this._upgradeStatement = "OS (version) unknown, agent won't upgrade to v4 automatically" } elseif ($value) { $this._sortOrder = 2 - $this._v3AgentSupportsOSText = "Supported" - $this._upgradeStatement = "OS supported by v3 agent, v2 agent will automatically upgrade to v3" + $this._v4AgentSupportsOSText = "Supported" + $this._upgradeStatement = "OS supported by v4 agent, agent will automatically upgrade to v4" } else { $this._sortOrder = 0 - $this._v3AgentSupportsOSText = "Unsupported" - $this._upgradeStatement = "OS not supported by v3 agent, v2 agent won't upgrade to v3" + $this._v4AgentSupportsOSText = "Unsupported" + $this._upgradeStatement = "OS not supported by v4 agent, agent won't upgrade to v4" } } - $this | Add-Member -Name V3AgentSupportsOSText -MemberType ScriptProperty -Value { + $this | Add-Member -Name V4AgentSupportsOSText -MemberType ScriptProperty -Value { # Get - return $this._v3AgentSupportsOSText + return $this._v4AgentSupportsOSText } -SecondValue { # Set param($value) - $this._v3AgentSupportsOSText = $value + $this._v4AgentSupportsOSText = $value } } } @@ -153,17 +153,17 @@ function Filter-Agents ( "MissingOS" { $Agents | Where-Object {[string]::IsNullOrWhiteSpace($_.OS)} } - "V3Compatible" { - $Agents | Where-Object {$_.ValidationResult.V3AgentSupportsOS -eq $true} + "V4Compatible" { + $Agents | Where-Object {$_.ValidationResult.V4AgentSupportsOS -eq $true} } - "V3CompatibilityIssues" { - $Agents | Where-Object {$_.ValidationResult.V3AgentSupportsOS -ne $true} | Where-Object {![string]::IsNullOrWhiteSpace($_.OS)} + "V4CompatibilityIssues" { + $Agents | Where-Object {$_.ValidationResult.V4AgentSupportsOS -ne $true} | Where-Object {![string]::IsNullOrWhiteSpace($_.OS)} } - "V3CompatibilityUnknown" { - $Agents | Where-Object {$_.ValidationResult.V3AgentSupportsOS -eq $null} + "V4CompatibilityUnknown" { + $Agents | Where-Object {$null -eq $_.ValidationResult.V4AgentSupportsOS} } - "V3InCompatible" { - $Agents | Where-Object {$_.ValidationResult.V3AgentSupportsOS -eq $false} + "V4InCompatible" { + $Agents | Where-Object {$_.ValidationResult.V4AgentSupportsOS -eq $false} } default { $Agents @@ -180,7 +180,7 @@ function Open-Document ( return } if ($IsWindows) { - start $Document + Start-Process $Document return } } @@ -196,7 +196,7 @@ function Validate-OS { if (!$OSDescription) { $result = [ClassificationResult]::new() $result.UpgradeStatement = "OS description missing" - $result.V3AgentSupportsOSText = "MissingOS" + $result.V4AgentSupportsOSText = "MissingOS" return $result } @@ -207,16 +207,16 @@ function Validate-OS { Write-Debug "Debian: '$OSDescription'" [version]$kernelVersion = ("{0}.{1}" -f $Matches["Major"],$Matches["Minor"]) Write-Debug "Debian Linux Kernel $($kernelVersion.ToString())" - [version]$minKernelVersion = '4.19' # https://wiki.debian.org/DebianBuster + [version]$minKernelVersion = '5.10' # https://wiki.debian.org/DebianBullseye if ($kernelVersion -ge $minKernelVersion) { $result.Reason = "Supported Debian Linux kernel version: ${kernelVersion}" - $result.V3AgentSupportsOS = $true + $result.V4AgentSupportsOS = $true return $result } else { $result.Reason = "Unsupported Debian Linux kernel version: ${kernelVersion} (see https://wiki.debian.org/DebianReleases)" - $result.V3AgentSupportsOS = $false - $result.V3AgentSupportsOSText = "UnsupportedOSVersion" + $result.V4AgentSupportsOS = $false + $result.V4AgentSupportsOSText = "UnsupportedOSVersion" return $result } } @@ -226,14 +226,14 @@ function Validate-OS { [int]$fedoraVersion = $Matches["Major"] Write-Debug "Fedora ${fedoraVersion}" - if ($fedoraVersion -ge 33) { + if ($fedoraVersion -ge 38) { $result.Reason = "Supported Fedora version: ${fedoraVersion}" - $result.V3AgentSupportsOS = $true + $result.V4AgentSupportsOS = $true return $result } else { $result.Reason = "Unsupported Fedora version: ${fedoraVersion}" - $result.V3AgentSupportsOS = $false - $result.V3AgentSupportsOSText = "UnsupportedOSVersion" + $result.V4AgentSupportsOS = $false + $result.V4AgentSupportsOSText = "UnsupportedOSVersion" return $result } } @@ -243,14 +243,14 @@ function Validate-OS { [int]$majorVersion = $Matches["Major"] Write-Debug "Red Hat ${majorVersion}" - if ($majorVersion -ge 7) { + if ($majorVersion -ge 8) { $result.Reason = "Supported RHEL / CentOS / Oracle Linux version: ${majorVersion}" - $result.V3AgentSupportsOS = $true + $result.V4AgentSupportsOS = $true return $result } else { $result.Reason = "Unsupported RHEL / CentOS / Oracle Linux version: ${majorVersion}" - $result.V3AgentSupportsOS = $false - $result.V3AgentSupportsOSText = "UnsupportedOSVersion" + $result.V4AgentSupportsOS = $false + $result.V4AgentSupportsOSText = "UnsupportedOSVersion" return $result } } @@ -260,19 +260,19 @@ function Validate-OS { [int]$majorVersion = $Matches["Major"] Write-Debug "Ubuntu ${majorVersion}" - if ($majorVersion -lt 16) { + if ($majorVersion -lt 20) { $result.Reason = "Unsupported Ubuntu version: ${majorVersion}" - $result.V3AgentSupportsOS = $false - $result.V3AgentSupportsOSText = "UnsupportedOSVersion" + $result.V4AgentSupportsOS = $false + $result.V4AgentSupportsOSText = "UnsupportedOSVersion" return $result } if (($majorVersion % 2) -ne 0) { $result.Reason = "non-LTS Ubuntu version: ${majorVersion}" - $result.V3AgentSupportsOSText = "UnsupportedOSVersion" + $result.V4AgentSupportsOSText = "UnsupportedOSVersion" return $result } Write-Debug "Supported Ubuntu version: ${majorVersion}" - $result.V3AgentSupportsOS = $true + $result.V4AgentSupportsOS = $true return $result } # Ubuntu "Linux 3.19.0-26-generic #28-Ubuntu SMP Tue Aug 11 14:16:32 UTC 2015" @@ -282,30 +282,27 @@ function Validate-OS { [version]$kernelVersion = ("{0}.{1}" -f $Matches["KernelMajor"],$Matches["KernelMinor"]) Write-Debug "Ubuntu Linux Kernel $($kernelVersion.ToString())" [version[]]$supportedKernelVersions = @( - '4.4', # 16.04 - '4.8', # 16.10 - '4.15', # 18.04 - '4.18', # 18.04 '5.4', # 20.04 '5.8', # 20.04 - '5.15' # 22.04 + '5.15', # 22.04 + '6.18' # 24.04 ) [version]$minKernelVersion = ($supportedKernelVersions | Measure-Object -Minimum | Select-Object -ExpandProperty Minimum) if ($kernelVersion -lt $minKernelVersion ) { $result.Reason = "Unsupported Ubuntu Linux kernel version: ${kernelVersion}` (see https://ubuntu.com/kernel/lifecycle)" - $result.V3AgentSupportsOS = $false - $result.V3AgentSupportsOSText = "UnsupportedOSVersion" + $result.V4AgentSupportsOS = $false + $result.V4AgentSupportsOSText = "UnsupportedOSVersion" return $result } if ($kernelVersion -in $supportedKernelVersions) { $result.Reason = "Supported Ubuntu Linux kernel version: ${kernelVersion}" - $result.V3AgentSupportsOS = $true + $result.V4AgentSupportsOS = $true return $result } $result.Reason = "Unknown Ubuntu version: '$OSDescription'" - $result.V3AgentSupportsOSText = "UnknownOSVersion" + $result.V4AgentSupportsOSText = "UnknownOSVersion" return $result } # macOS "Darwin 17.6.0 Darwin Kernel Version 17.6.0: Tue May 8 15:22:16 PDT 2018; root:xnu-4570.61.1~1/RELEASE_X86_64" @@ -313,20 +310,20 @@ function Validate-OS { Write-Debug "macOS (Darwin): '$OSDescription'" [version]$darwinVersion = ("{0}.{1}" -f $Matches["DarwinMajor"],$Matches["DarwinMinor"]) Write-Debug "Darwin $($darwinVersion.ToString())" - [version]$minDarwinVersion = '19.0' + [version]$minDarwinVersion = '21.0' if ($darwinVersion -ge $minDarwinVersion) { $result.Reason = "Supported Darwin (macOS) version: ${darwinVersion}" - $result.V3AgentSupportsOS = $true + $result.V4AgentSupportsOS = $true return $result } else { $result.Reason = "Unsupported Darwin (macOS) version): ${darwinVersion} (see https://en.wikipedia.org/wiki/Darwin_(operating_system)" - $result.V3AgentSupportsOS = $false - $result.V3AgentSupportsOSText = "UnsupportedOSVersion" + $result.V4AgentSupportsOS = $false + $result.V4AgentSupportsOSText = "UnsupportedOSVersion" return $result } } - # Windows 10 / Server 2016+ "Microsoft Windows 10.0.20348" + # Windows 10 / 11 / Server 2016+ "Microsoft Windows 10.0.20348" "(?im)^(Microsoft Windows|Windows_NT) (?[\d]+)(\.(?[\d]+))(\.(?[\d]+)).*$" { [int]$windowsMajorVersion = $Matches["Major"] [int]$windowsMinorVersion = $Matches["Minor"] @@ -334,52 +331,55 @@ function Validate-OS { [version]$windowsVersion = ("{0}.{1}.{2}" -f $Matches["Major"],$Matches["Minor"],$Matches["Build"]) Write-Debug "Windows: '$OSDescription'" Write-Debug "Windows $($windowsVersion.ToString())" - if (($windowsMajorVersion -eq 6) -and ($windowsMinorVersion -eq 1)) { - # Windows 7 - if ($windowsBuild -ge 7601) { - $result.Reason = "Supported Windows 7 build: ${windowsVersion}" - $result.V3AgentSupportsOS = $true + if (($windowsMajorVersion -eq 10) -and ($windowsMinorVersion -eq 0)) { + if ($windowsBuild -eq 14393) { + # Windows 10 / Windows Server 2016 + $result.Reason = "Supported Windows build: ${windowsVersion}" + $result.V4AgentSupportsOS = $true + return $result + } elseif ($windowsBuild -eq 17763) { + # Windows 10 / Windows Server 2019 + $result.Reason = "Supported Windows build: ${windowsVersion}" + $result.V4AgentSupportsOS = $true + return $result + } elseif ($windowsBuild -ge 19044) { + # Windows 10 / Windows Server 2022 / Windows 11 + $result.Reason = "Supported Windows build: ${windowsVersion}" + $result.V4AgentSupportsOS = $true return $result } else { - $result.Reason = "Unsupported Windows 7 build: ${windowsVersion}" - $result.V3AgentSupportsOS = $false - $result.V3AgentSupportsOSText = "UnsupportedOSVersion" + $result.Reason = "Unsupported Windows build: ${windowsVersion}" + $result.V4AgentSupportsOS = $false + $result.V4AgentSupportsOSText = "UnsupportedOSVersion" return $result } } - if (($windowsMajorVersion -eq 6) -and ($windowsMinorVersion -eq 2)) { - # Windows 8 / Windows Server 2012 R1 - $result.Reason = "Windows 8 is not supported: ${windowsVersion}" - $result.V3AgentSupportsOS = $false - $result.V3AgentSupportsOSText = "UnsupportedOSVersion" + if (($windowsMajorVersion -eq 6) -and ($windowsMinorVersion -eq 2) -and ($windowsBuild -eq 9200)) { + # Windows Server 2012 + $result.Reason = "Supported Windows Server 2012 version: ${windowsVersion}" + $result.V4AgentSupportsOS = $true return $result } - if (($windowsMajorVersion -eq 6) -and ($windowsMinorVersion -eq 3)) { - # Windows 8.1 / Windows Server 2012 R2 - $result.Reason = "Supported Windows 8.1 version: ${windowsVersion}" - $result.V3AgentSupportsOS = $true + if (($windowsMajorVersion -eq 6) -and ($windowsMinorVersion -eq 3) -and ($windowsBuild -eq 9600)) { + # Windows Server 2012 R2 + $result.Reason = "Supported Windows Server 2012-R2 version: ${windowsVersion}" + $result.V4AgentSupportsOS = $true return $result } - if ($windowsMajorVersion -eq 10) { - # Windows 10 / Windows Server 2016+ - if ($windowsBuild -ge 14393) { - $result.Reason = "Supported Windows 10 / Windows Server 2016+ build: ${windowsVersion}" - $result.V3AgentSupportsOS = $true - return $result - } else { - $result.Reason = "Unsupported Windows 10 / Windows Server 2016+ build: ${windowsVersion}" - $result.V3AgentSupportsOS = $false - $result.V3AgentSupportsOSText = "UnsupportedOSVersion" - return $result - } + if ($windowsMajorVersion -eq 6) { + # Windows 7 / 8 / Windows Server 2012 R1 + $result.Reason = "Windows 7 / Windows 8 / Windows Server 2012-R1 is not supported: ${windowsVersion}" + $result.V4AgentSupportsOS = $false + $result.V4AgentSupportsOSText = "UnsupportedOSVersion" + return $result } $result.Reason = "Unknown Windows version: '${OSDescription}'" - $result.V3AgentSupportsOSText = "UnknownOSVersion" + $result.V4AgentSupportsOSText = "UnknownOSVersion" return $result } default { $result.Reason = "Unknown operating system: '$OSDescription'" - $result.V3AgentSupportsOSText = "UnknownOS" + $result.V4AgentSupportsOSText = "UnknownOS" return $result } } @@ -401,9 +401,9 @@ if ($OS) { } | Filter-Agents -AgentFilter $Filter ` | Format-Table -Property OS,` @{Label="UpgradeStatement"; Expression={ - if ($_.ValidationResult.V3AgentSupportsOS -eq $null) { + if ($_.ValidationResult.V4AgentSupportsOS -eq $null) { "$($PSStyle.Formatting.Warning)$($_.ValidationResult.UpgradeStatement)$($PSStyle.Reset)" - } elseif ($_.ValidationResult.V3AgentSupportsOS) { + } elseif ($_.ValidationResult.V4AgentSupportsOS) { $_.ValidationResult.UpgradeStatement } else { "$($PSStyle.Formatting.Error)$($_.ValidationResult.UpgradeStatement)$($PSStyle.Reset)" @@ -496,11 +496,11 @@ try { -o tsv ` | Set-Variable poolName - Write-Host "Retrieving v2 agents for pool '${poolName}' (${poolUrl})..." - Write-Debug "az pipelines agent list --pool-id ${individualPoolId} --include-capabilities --query `"[?starts_with(version,'2.') ]`"" + Write-Host "Retrieving v2 and v3 agents for pool '${poolName}' (${poolUrl})..." + Write-Debug "az pipelines agent list --pool-id ${individualPoolId} --include-capabilities --query `"[?starts_with(version,'2.') || starts_with(version,'3.')]`"" az pipelines agent list --pool-id $individualPoolId ` --include-capabilities ` - --query "[?starts_with(version,'2.') ]" ` + --query "[?starts_with(version,'2.') || starts_with(version,'3.')]" ` -o json ` | ConvertFrom-Json ` | Set-Variable agents @@ -555,7 +555,7 @@ try { | Select-Object -Property @{Label="Name"; Expression={$_.name}},` @{Label="Id"; Expression={$_.id}},` @{Label="OS"; Expression={$_.OS -replace ";",""}},` - @{Label="V3OS"; Expression={$_.ValidationResult.V3AgentSupportsOSText}},` + @{Label="V4OS"; Expression={$_.ValidationResult.V4AgentSupportsOSText}},` @{Label="UpgradeStatement"; Expression={$_.ValidationResult.UpgradeStatement}},` @{Label="Reason"; Expression={$_.ValidationResult.Reason}},` @{Label="CreatedOn"; Expression={$_.createdOn}},` @@ -576,15 +576,15 @@ try { | Format-Table -Property @{Label="Name"; Expression={$_.name}},` OS,` @{Label="UpgradeStatement"; Expression={ - if ($_.ValidationResult.V3AgentSupportsOS -eq $null) { + if ($_.ValidationResult.V4AgentSupportsOS -eq $null) { "$($PSStyle.Formatting.Warning)$($_.ValidationResult.UpgradeStatement)$($PSStyle.Reset)" - } elseif ($_.ValidationResult.V3AgentSupportsOS) { + } elseif ($_.ValidationResult.V4AgentSupportsOS) { $_.ValidationResult.UpgradeStatement } else { "$($PSStyle.Formatting.Error)$($_.ValidationResult.UpgradeStatement)$($PSStyle.Reset)" } }},` - @{Label="V3OS"; Expression={$_.ValidationResult.V3AgentSupportsOSText}},` + @{Label="V4OS"; Expression={$_.ValidationResult.V4AgentSupportsOSText}},` PoolName,` AgentUrl ` | Out-Host -Paging @@ -596,13 +596,13 @@ try { Write-Host "`nRetrieved agents with filter '${Filter}' in organization (${OrganizationUrl}) have been saved to ${exportFilePath}" Write-Host "Processed ${totalNumberOfAgents} agents in ${totalNumberOfPools} in organization '${OrganizationUrl}'" $statisticsFilter = (($Filter -ieq "All") -or $IncludeMissingOSInStatistics ? "All" : "ExcludeMissingOS") - Write-Host "`nAgents by v2 -> v3 compatibility (${statisticsFilter}):" + Write-Host "`nAgents by v2/v3 -> v4 compatibility (${statisticsFilter}):" $script:allAgents | Filter-Agents -AgentFilter $statisticsFilter ` - | Group-Object {$_.ValidationResult.V3AgentSupportsOSText} ` + | Group-Object {$_.ValidationResult.V4AgentSupportsOSText} ` | Set-Variable agentsSummary $agentsSummary | Measure-Object -Property Count -Sum | Select-Object -ExpandProperty Sum | Set-Variable totalNumberOfFilteredAgents - $agentsSummary | Format-Table -Property @{Label="V3AgentSupportsOS"; Expression={$_.Name}},` + $agentsSummary | Format-Table -Property @{Label="V4AgentSupportsOS"; Expression={$_.Name}},` Count,` @{Label="Percentage"; Expression={($_.Count / $totalNumberOfFilteredAgents).ToString("p")}} }