diff --git a/tools/FindAgentsNotCompatibleWithAgent/QueryAgentPoolsForCompatibleOSV4.ps1 b/tools/FindAgentsNotCompatibleWithAgent/QueryAgentPoolsForCompatibleOSV4.ps1 deleted file mode 100644 index 65db0cada9..0000000000 --- a/tools/FindAgentsNotCompatibleWithAgent/QueryAgentPoolsForCompatibleOSV4.ps1 +++ /dev/null @@ -1,610 +0,0 @@ -#!/usr/bin/env pwsh -<# -.SYNOPSIS - Predict whether agents will be able to upgrade from pipeline agent v3 to agent v4 - -.DESCRIPTION - The Azure Pipeline 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. - - This script requires a PAT token with read access on 'Agent Pools' scope. - - For more information, go to https://aka.ms/azdo-pipeline-agent-version. - -.EXAMPLE - ./QueryAgentPoolsForCompatibleOSV4.ps1 -Token "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -.EXAMPLE - $env:AZURE_DEVOPS_EXT_PAT = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - ./QueryAgentPoolsForCompatibleOSV4.ps1 -PoolId 1234 -Filter V4InCompatible -Verbose -OpenCsv -#> - -#Requires -Version 7.2 - -[CmdletBinding(DefaultParameterSetName="pool")] -param ( - [parameter(Mandatory=$false,ParameterSetName="pool")] - [string] - $OrganizationUrl=$env:AZDO_ORG_SERVICE_URL, - - [parameter(Mandatory=$false,ParameterSetName="pool")] - [int[]] - $PoolId, - - [parameter(Mandatory=$false,ParameterSetName="pool")] - [int] - $MaxPools=4096, - - [parameter(Mandatory=$false,HelpMessage="PAT token with read access on 'Agent Pools' scope",ParameterSetName="pool")] - [string] - $Token=($env:AZURE_DEVOPS_EXT_PAT ?? $env:AZDO_PERSONAL_ACCESS_TOKEN), - - [parameter(Mandatory=$false,ParameterSetName="os")] - [string[]] - $OS, - - [parameter(Mandatory=$false)] - [parameter(ParameterSetName="pool")] - [parameter(ParameterSetName="os")] - [ValidateSet("All", "ExcludeMissingOS", "MissingOS", "V4Compatible", "V4CompatibilityIssues", "V4CompatibilityUnknown", "V4InCompatible")] - [string] - $Filter="V4CompatibilityIssues", - - [parameter(Mandatory=$false)] - [switch] - $OpenCsv=$false, - - [parameter(Mandatory=$false)] - [switch] - $IncludeMissingOSInStatistics=$false, - - [parameter(Mandatory=$false,HelpMessage="Do not ask for input to start processing",ParameterSetName="pool")] - [switch] - $Force=$false -) - -class ClassificationResult { - hidden [int]$_sortOrder = 1 - hidden [string]$_upgradeStatement = "OS (version) unknown, v3 agent won't upgrade to v4 automatically" - [ValidateSet($null, $true, $false)] - hidden [object]$_v4AgentSupportsOS - [ValidateSet("MissingOS", "Unsupported", "Unknown", "UnknownOS", "UnknownOSVersion", "UnsupportedOSVersion", "Supported")] - hidden [string]$_v4AgentSupportsOSText = "Unknown" - [string]$_reason - - ClassificationResult() { - $this | Add-Member -Name Reason -MemberType ScriptProperty -Value { - # Get - return $this._reason - } -SecondValue { - # Set - param($value) - $this._reason = $value - Write-Debug "ClassificationResult.Reason = ${value}" - } - $this | Add-Member -Name SortOrder -MemberType ScriptProperty -Value { - return $this._sortOrder - } - $this | Add-Member -Name UpgradeStatement -MemberType ScriptProperty -Value { - # Get - return $this._upgradeStatement - } -SecondValue { - # Set - param($value) - - $this._upgradeStatement = $value - } - $this | Add-Member -Name V4AgentSupportsOS -MemberType ScriptProperty -Value { - # Get - return $this._v4AgentSupportsOS - } -SecondValue { - # Set - param($value) - - $this._v4AgentSupportsOS = $value - if ($null -eq $value) { - $this._sortOrder = 1 - $this._v4AgentSupportsOSText = "Unknown" - $this._upgradeStatement = "OS (version) unknown, v3 agent won't upgrade to v4 automatically" - } elseif ($value) { - $this._sortOrder = 2 - $this._v4AgentSupportsOSText = "Supported" - $this._upgradeStatement = "OS supported by v4 agent, v3 agent will automatically upgrade to v4" - } else { - $this._sortOrder = 0 - $this._v4AgentSupportsOSText = "Unsupported" - $this._upgradeStatement = "OS not supported by v4 agent, v3 agent won't upgrade to v4" - } - } - $this | Add-Member -Name V4AgentSupportsOSText -MemberType ScriptProperty -Value { - # Get - return $this._v4AgentSupportsOSText - } -SecondValue { - # Set - param($value) - - $this._v4AgentSupportsOSText = $value - } - } -} - -function Classify-OS ( - [parameter(Mandatory=$false)][string]$AgentOS, - [parameter(Mandatory=$true)][psobject]$Agent -) { - Write-Debug "AgentOS: ${AgentOS}" - $result = Validate-OS -OSDescription $AgentOS - $Agent | Add-Member -NotePropertyName ValidationResult -NotePropertyValue $result -} - -function Filter-Agents ( - [parameter(Mandatory=$true,ValueFromPipeline=$true)][psobject[]]$Agents, - [parameter(Mandatory=$true)][string]$AgentFilter -) { - process { - switch ($AgentFilter) { - "All" { - $Agents - } - "ExcludeMissingOS" { - $Agents | Where-Object {![string]::IsNullOrWhiteSpace($_.OS)} - } - "MissingOS" { - $Agents | Where-Object {[string]::IsNullOrWhiteSpace($_.OS)} - } - "V4Compatible" { - $Agents | Where-Object {$_.ValidationResult.V4AgentSupportsOS -eq $true} - } - "V4CompatibilityIssues" { - $Agents | Where-Object {$_.ValidationResult.V4AgentSupportsOS -ne $true} | Where-Object {![string]::IsNullOrWhiteSpace($_.OS)} - } - "V4CompatibilityUnknown" { - $Agents | Where-Object {$null -eq $_.ValidationResult.V4AgentSupportsOS} - } - "V4InCompatible" { - $Agents | Where-Object {$_.ValidationResult.V4AgentSupportsOS -eq $false} - } - default { - $Agents - } - } - } -} - -function Open-Document ( - [parameter(Mandatory=$true)][string]$Document -) { - if ($IsMacOS) { - open $Document - return - } - if ($IsWindows) { - Start-Process $Document - return - } -} - -function Validate-OS { - [OutputType([ClassificationResult])] - param ( - [parameter(Mandatory=$false)][string]$OSDescription - ) - - $result = [ClassificationResult]::new() - - if (!$OSDescription) { - $result = [ClassificationResult]::new() - $result.UpgradeStatement = "OS description missing" - $result.V4AgentSupportsOSText = "MissingOS" - return $result - } - - # Parse operating system description - switch -regex ($OSDescription) { - # Debian "Linux 4.9.0-16-amd64 #1 SMP Debian 4.9.272-2 (2021-07-19)" - "(?im)^Linux.* Debian (?[\d]+)(\.(?[\d]+))(\.(?[\d]+))?.*$" { - Write-Debug "Debian: '$OSDescription'" - [version]$kernelVersion = ("{0}.{1}" -f $Matches["Major"],$Matches["Minor"]) - Write-Debug "Debian Linux Kernel $($kernelVersion.ToString())" - [version]$minKernelVersion = '5.10' # https://wiki.debian.org/DebianBullseye - - if ($kernelVersion -ge $minKernelVersion) { - $result.Reason = "Supported Debian Linux kernel version: ${kernelVersion}" - $result.V4AgentSupportsOS = $true - return $result - } else { - $result.Reason = "Unsupported Debian Linux kernel version: ${kernelVersion} (see https://wiki.debian.org/DebianReleases)" - $result.V4AgentSupportsOS = $false - $result.V4AgentSupportsOSText = "UnsupportedOSVersion" - return $result - } - } - # Fedora "Linux 5.11.22-100.fc32.x86_64 #1 SMP Wed May 19 18:58:25 UTC 2021" - "(?im)^Linux.*\.fc(?[\d]+)\..*$" { - Write-Debug "Fedora: '$OSDescription'" - [int]$fedoraVersion = $Matches["Major"] - Write-Debug "Fedora ${fedoraVersion}" - - if ($fedoraVersion -ge 38) { - $result.Reason = "Supported Fedora version: ${fedoraVersion}" - $result.V4AgentSupportsOS = $true - return $result - } else { - $result.Reason = "Unsupported Fedora version: ${fedoraVersion}" - $result.V4AgentSupportsOS = $false - $result.V4AgentSupportsOSText = "UnsupportedOSVersion" - return $result - } - } - # Red Hat / CentOS "Linux 4.18.0-425.3.1.el8.x86_64 #1 SMP Fri Sep 30 11:45:06 EDT 2022" - "(?im)^Linux.*\.el(?[\d]+).*$" { - Write-Debug "Red Hat / CentOS / Oracle Linux: '$OSDescription'" - [int]$majorVersion = $Matches["Major"] - Write-Debug "Red Hat ${majorVersion}" - - if ($majorVersion -ge 8) { - $result.Reason = "Supported RHEL / CentOS / Oracle Linux version: ${majorVersion}" - $result.V4AgentSupportsOS = $true - return $result - } else { - $result.Reason = "Unsupported RHEL / CentOS / Oracle Linux version: ${majorVersion}" - $result.V4AgentSupportsOS = $false - $result.V4AgentSupportsOSText = "UnsupportedOSVersion" - return $result - } - } - # Ubuntu "Linux 4.15.0-1113-azure #126~16.04.1-Ubuntu SMP Tue Apr 13 16:55:24 UTC 2021" - "(?im)^Linux.*[^\d]+((?[\d]+)((\.(?[\d]+))(\.(?[\d]+)))(\.(?[\d]+))?)-Ubuntu.*$" { - Write-Debug "Ubuntu: '$OSDescription'" - [int]$majorVersion = $Matches["Major"] - Write-Debug "Ubuntu ${majorVersion}" - - if ($majorVersion -lt 20) { - $result.Reason = "Unsupported Ubuntu version: ${majorVersion}" - $result.V4AgentSupportsOS = $false - $result.V4AgentSupportsOSText = "UnsupportedOSVersion" - return $result - } - if (($majorVersion % 2) -ne 0) { - $result.Reason = "non-LTS Ubuntu version: ${majorVersion}" - $result.V4AgentSupportsOSText = "UnsupportedOSVersion" - return $result - } - Write-Debug "Supported Ubuntu version: ${majorVersion}" - $result.V4AgentSupportsOS = $true - return $result - } - # Ubuntu "Linux 3.19.0-26-generic #28-Ubuntu SMP Tue Aug 11 14:16:32 UTC 2015" - # Ubuntu 22 "Linux 5.15.0-1023-azure #29-Ubuntu SMP Wed Oct 19 22:37:08 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux" - "(?im)^Linux (?[\d]+)(\.(?[\d]+)).*-Ubuntu.*$" { - Write-Debug "Ubuntu (no version declared): '$OSDescription'" - [version]$kernelVersion = ("{0}.{1}" -f $Matches["KernelMajor"],$Matches["KernelMinor"]) - Write-Debug "Ubuntu Linux Kernel $($kernelVersion.ToString())" - [version[]]$supportedKernelVersions = @( - '5.4', # 20.04 - '5.8', # 20.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.V4AgentSupportsOS = $false - $result.V4AgentSupportsOSText = "UnsupportedOSVersion" - return $result - } - if ($kernelVersion -in $supportedKernelVersions) { - $result.Reason = "Supported Ubuntu Linux kernel version: ${kernelVersion}" - $result.V4AgentSupportsOS = $true - return $result - } - - $result.Reason = "Unknown Ubuntu version: '$OSDescription'" - $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" - "(?im)^Darwin (?[\d]+)(\.(?[\d]+)).*$" { - Write-Debug "macOS (Darwin): '$OSDescription'" - [version]$darwinVersion = ("{0}.{1}" -f $Matches["DarwinMajor"],$Matches["DarwinMinor"]) - Write-Debug "Darwin $($darwinVersion.ToString())" - [version]$minDarwinVersion = '21.0' - - if ($darwinVersion -ge $minDarwinVersion) { - $result.Reason = "Supported Darwin (macOS) version: ${darwinVersion}" - $result.V4AgentSupportsOS = $true - return $result - } else { - $result.Reason = "Unsupported Darwin (macOS) version): ${darwinVersion} (see https://en.wikipedia.org/wiki/Darwin_(operating_system)" - $result.V4AgentSupportsOS = $false - $result.V4AgentSupportsOSText = "UnsupportedOSVersion" - return $result - } - } - # 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"] - [int]$windowsBuild = $Matches["Build"] - [version]$windowsVersion = ("{0}.{1}.{2}" -f $Matches["Major"],$Matches["Minor"],$Matches["Build"]) - Write-Debug "Windows: '$OSDescription'" - Write-Debug "Windows $($windowsVersion.ToString())" - 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 build: ${windowsVersion}" - $result.V4AgentSupportsOS = $false - $result.V4AgentSupportsOSText = "UnsupportedOSVersion" - return $result - } - } - 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) -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 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.V4AgentSupportsOSText = "UnknownOSVersion" - return $result - } - default { - $result.Reason = "Unknown operating system: '$OSDescription'" - $result.V4AgentSupportsOSText = "UnknownOS" - return $result - } - } -} - -if (!$OS -and !$OrganizationUrl) { - Get-Help $MyInvocation.MyCommand.Definition - return -} - -if ($OS) { - # Process OS parameter set - $OS | ForEach-Object { - New-Object PSObject -Property @{ - OS = $_ - } | Set-Variable agent - Classify-OS -AgentOS $_ -Agent $agent - Write-Output $agent - } | Filter-Agents -AgentFilter $Filter ` - | Format-Table -Property OS,` - @{Label="UpgradeStatement"; Expression={ - if ($_.ValidationResult.V4AgentSupportsOS -eq $null) { - "$($PSStyle.Formatting.Warning)$($_.ValidationResult.UpgradeStatement)$($PSStyle.Reset)" - } elseif ($_.ValidationResult.V4AgentSupportsOS) { - $_.ValidationResult.UpgradeStatement - } else { - "$($PSStyle.Formatting.Error)$($_.ValidationResult.UpgradeStatement)$($PSStyle.Reset)" - } - }} - | Out-Host -Paging - - return -} - -# Process pool parameter set -if (!$OrganizationUrl) { - Write-Warning "OrganizationUrl is required. Please specify -OrganizationUrl or set the AZDO_ORG_SERVICE_URL environment variable." - exit 1 -} -$OrganizationUrl = $OrganizationUrl -replace "/$","" # Strip trailing '/' -if (!$Token) { - Write-Warning "No access token found. Please specify -Token or set the AZURE_DEVOPS_EXT_PAT or AZDO_PERSONAL_ACCESS_TOKEN environment variable." - exit 1 -} -if (!(Get-Command az -ErrorAction SilentlyContinue)) { - Write-Warning "Azure CLI not found. Please install it." - exit 1 -} -if (!(az extension list --query "[?name=='azure-devops'].version" -o tsv)) { - Write-Host "Adding Azure CLI extension 'azure-devops'..." - az extension add -n azure-devops -y -} - -Write-Host "`n$($PSStyle.Formatting.FormatAccent)This script will process all self-hosted pools in organization '${OrganizationUrl}' to:$($PSStyle.Reset)" -Write-Host "$($PSStyle.Formatting.FormatAccent)- Create an aggregated list of agents filtered by '${Filter}'$($PSStyle.Reset)" -Write-Host "$($PSStyle.Formatting.FormatAccent)- Create a CSV export of that list (so you can walk away from the computer when this runs)$($PSStyle.Reset)" -Write-Host "$($PSStyle.Formatting.FormatAccent)- Show list of agents filtered by '${Filter}' (list repeated at the end of script output)$($PSStyle.Reset)" -Write-Host "$($PSStyle.Formatting.FormatAccent)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.$($PSStyle.Reset)" -if (!$Force) { - # Prompt to continue - $choices = @( - [System.Management.Automation.Host.ChoiceDescription]::new("&Continue", "Process pools") - [System.Management.Automation.Host.ChoiceDescription]::new("&Exit", "Abort") - ) - $defaultChoice = 0 - $decision = $Host.UI.PromptForChoice("Continue", "Do you wish to proceed retrieving data for agents in all pools in '${OrganizationUrl}'?", $choices, $defaultChoice) - - if ($decision -eq 0) { - Write-Host "$($choices[$decision].HelpMessage)" - } else { - Write-Host "$($PSStyle.Formatting.Warning)$($choices[$decision].HelpMessage)$($PSStyle.Reset)" - exit - } -} - -Write-Host "`nAuthenticating to organization ${OrganizationUrl}..." -$Token | az devops login --organization $OrganizationUrl -az devops configure --defaults organization=$OrganizationUrl - -if (!$PoolId) { - Write-Host "Retrieving self-hosted pools for organization ${OrganizationUrl}..." - az pipelines pool list --query "[?!isHosted].id" ` - -o tsv ` - | Set-Variable PoolId -} -$PoolId | Measure-Object ` - | Select-Object -ExpandProperty Count ` - | Set-Variable totalNumberOfPools - - -$script:allAgents = [System.Collections.ArrayList]@() -try { - $poolIndex = 0; - $totalNumberOfAgents = 0; - $numberOfPoolsToProcess = [math]::min($MaxPools,$totalNumberOfPools) - foreach ($individualPoolId in $PoolId) { - $poolIndex++ - if ($poolIndex -gt $MaxPools) { - break - } - $OuterLoopProgressParameters = @{ - ID = 0 - Activity = "Processing pools" - Status = "Pool ${poolIndex} of ${numberOfPoolsToProcess}" - PercentComplete = ($poolIndex / $totalNumberOfPools) * 100 - CurrentOperation = 'OuterLoop' - } - Write-Progress @OuterLoopProgressParameters - $agents = $null - $poolUrl = ("{0}/_settings/agentpools?poolId={1}" -f $OrganizationUrl,$individualPoolId) - Write-Verbose "Retrieving pool with id '${individualPoolId}' in (${OrganizationUrl})..." - az pipelines pool show --id $individualPoolId ` - --query "name" ` - -o tsv ` - | Set-Variable poolName - - Write-Host "Retrieving v3 agents for pool '${poolName}' (${poolUrl})..." - Write-Debug "az pipelines agent list --pool-id ${individualPoolId} --include-capabilities --query `"[?starts_with(version,'3.') ]`"" - az pipelines agent list --pool-id $individualPoolId ` - --include-capabilities ` - --query "[?starts_with(version,'3.') ]" ` - -o json ` - | ConvertFrom-Json ` - | Set-Variable agents - if ($agents) { - $agents | Measure-Object ` - | Select-Object -ExpandProperty Count ` - | Set-Variable totalNumberOfAgentsInPool - $agentIndex = 0 - $agents | ForEach-Object { - $agentIndex++ - $totalNumberOfAgents++ - $osConsolidated = $_.osDescription - $capabilityOSDescription = ("{0} {1}" -f $_.systemCapabilities."Agent.OS",$_.systemCapabilities."Agent.OSVersion") - if ($capabilityOSDescription -and !$osConsolidated -and ![string]::IsNullOrWhiteSpace($capabilityOSDescription)) { - $osConsolidated = $capabilityOSDescription - } - Write-Debug "osConsolidated: ${osConsolidated}" - Write-Debug "capabilityOSDescription: ${capabilityOSDescription}" - Classify-OS -AgentOS $osConsolidated -Agent $_ - $agentUrl = "{0}/_settings/agentpools?agentId={2}&poolId={1}" -f $OrganizationUrl,$individualPoolId,$_.id - $_ | Add-Member -NotePropertyName AgentUrl -NotePropertyValue $agentUrl - $_ | Add-Member -NotePropertyName OS -NotePropertyValue $osConsolidated - $_ | Add-Member -NotePropertyName PoolName -NotePropertyValue $poolName - } - $agents | Filter-Agents -AgentFilter $Filter ` - | Format-Table -Property @{Label="Name"; Expression={$_.name}},` - OS,` - AgentUrl - - $script:allAgents.Add($agents) | Out-Null - } else { - Write-Host "There are no agents in pool '${poolName}' (${poolUrl})" - } - } -} finally { - Write-Progress Id 0 -Completed - Write-Progress Id 1 -Completed - - - $script:allAgents | ForEach-Object { # Flatten nested arrays - $_ - } ` - | Set-Variable allAgents -Scope script - - $script:allAgents | Sort-Object -Property @{Expression = {$_.ValidationResult.SortOrder}; Descending = $false}, ` - @{Expression = "PoolName"; Descending = $false}, ` - @{Expression = "name"; Descending = $false} ` - | Set-Variable allAgents -Scope script - - $exportFilePath = (Join-Path ([System.IO.Path]::GetTempPath()) "$([guid]::newguid().ToString()).csv") - $script:allAgents | Filter-Agents -AgentFilter $Filter ` - | Select-Object -Property @{Label="Name"; Expression={$_.name}},` - @{Label="Id"; Expression={$_.id}},` - @{Label="OS"; Expression={$_.OS -replace ";",""}},` - @{Label="V4OS"; Expression={$_.ValidationResult.V4AgentSupportsOSText}},` - @{Label="UpgradeStatement"; Expression={$_.ValidationResult.UpgradeStatement}},` - @{Label="Reason"; Expression={$_.ValidationResult.Reason}},` - @{Label="CreatedOn"; Expression={$_.createdOn}},` - @{Label="StatusChangedOn"; Expression={$_.statusChangedOn}},` - @{Label="Status"; Expression={$_.status}},` - @{Label="Version"; Expression={$_.version}},` - PoolName,` - AgentUrl ` - | Export-Csv -Path $exportFilePath - if ($OpenCsv) { - Open-Document -Document $exportFilePath - } - - try { - # Try block, in case the user cancels paging through results - Write-Host "`nRetrieved agents with filter '${Filter}' in organization (${OrganizationUrl}) have been saved to ${exportFilePath}, and are repeated below" - $script:allAgents | Filter-Agents -AgentFilter $Filter ` - | Format-Table -Property @{Label="Name"; Expression={$_.name}},` - OS,` - @{Label="UpgradeStatement"; Expression={ - if ($_.ValidationResult.V4AgentSupportsOS -eq $null) { - "$($PSStyle.Formatting.Warning)$($_.ValidationResult.UpgradeStatement)$($PSStyle.Reset)" - } elseif ($_.ValidationResult.V4AgentSupportsOS) { - $_.ValidationResult.UpgradeStatement - } else { - "$($PSStyle.Formatting.Error)$($_.ValidationResult.UpgradeStatement)$($PSStyle.Reset)" - } - }},` - @{Label="V4OS"; Expression={$_.ValidationResult.V4AgentSupportsOSText}},` - PoolName,` - AgentUrl ` - | Out-Host -Paging - - } catch [System.Management.Automation.HaltCommandException] { - Write-Warning "Skipped paging through results" - } finally { - if ($script:allAgents) { - 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 v3 -> v4 compatibility (${statisticsFilter}):" - - $script:allAgents | Filter-Agents -AgentFilter $statisticsFilter ` - | 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="V4AgentSupportsOS"; Expression={$_.Name}},` - Count,` - @{Label="Percentage"; Expression={($_.Count / $totalNumberOfFilteredAgents).ToString("p")}} - } - } -} \ No newline at end of file