Private/Azure/Get-AdvisorRetirementData.ps1
|
function Get-AdvisorRetirementData { <# .SYNOPSIS Queries Azure Advisor for VM SKU retirement recommendations. .DESCRIPTION Fetches ServiceUpgradeAndRetirement recommendations from the Advisor API and builds a hashtable keyed by retirement series grouping for fast lookup. Results are cached in $script:RunContext.Caches.AdvisorRetirement for the session. #> param( [string]$SubscriptionId, [string]$ArmUrl = 'https://management.azure.com', [string]$BearerToken, [int]$MaxRetries = 3 ) # Return cached data if available # Return cached data if available (keyed by subscription) if ($script:RunContext -and $script:RunContext.Caches.AdvisorRetirement -and $script:RunContext.Caches.AdvisorRetirement.ContainsKey($SubscriptionId)) { return $script:RunContext.Caches.AdvisorRetirement[$SubscriptionId] } $result = @{} try { $uri = "$($ArmUrl.TrimEnd('/'))/subscriptions/$SubscriptionId/providers/Microsoft.Advisor/recommendations?api-version=2023-01-01&`$filter=Category eq 'HighAvailability'" $headers = @{ Authorization = "Bearer $BearerToken" } $advisorResp = Invoke-WithRetry -ScriptBlock { Invoke-RestMethod -Uri $uri -Headers $headers -Method Get -TimeoutSec 30 -ErrorAction Stop } -MaxRetries $MaxRetries if ($advisorResp.value) { foreach ($rec in $advisorResp.value) { $props = $rec.properties if ($props.extendedProperties.recommendationSubCategory -ne 'ServiceUpgradeAndRetirement') { continue } if ($props.impactedField -notmatch 'VIRTUALMACHINES') { continue } $retireDate = $props.extendedProperties.retirementDate $seriesName = $props.extendedProperties.retirementFeatureName $vmName = $props.impactedValue if ($seriesName -and $retireDate) { if (-not $result[$seriesName]) { $result[$seriesName] = @{ RetireDate = $retireDate Series = $seriesName Impact = $props.impact Status = if ([datetime]$retireDate -lt [datetime]::UtcNow) { 'Retired' } else { 'Retiring' } VMs = [System.Collections.Generic.List[string]]::new() } } $result[$seriesName].VMs.Add($vmName) } } } Write-Verbose "Advisor: found $($result.Count) retirement group(s) covering $(@($result.Values | ForEach-Object { $_.VMs.Count } | Measure-Object -Sum).Sum) VM(s)" } catch { Write-Verbose "Advisor retirement query failed (non-fatal, falling back to pattern table): $_" } # Cache the result keyed by subscription if ($script:RunContext -and $script:RunContext.Caches) { if (-not $script:RunContext.Caches.AdvisorRetirement) { $script:RunContext.Caches.AdvisorRetirement = @{} } $script:RunContext.Caches.AdvisorRetirement[$SubscriptionId] = $result } return $result } |