FinOpsToolkitExt.BenefitRecommendations.psm1
|
function Get-BenefitRecommendation { <# .SYNOPSIS Queries the Azure Cost Management Benefit Recommendations API. .DESCRIPTION Retrieves savings plan purchase recommendations for a billing account. Uses Invoke-AzRestMethod for authentication (requires Connect-AzAccount). .PARAMETER BillingAccountId The billing account ID (e.g., "90846601"). .PARAMETER LookBackPeriod The look-back period for usage analysis. Default: Last60Days. .PARAMETER Term The commitment term. Default: P3Y. .PARAMETER Scope Recommendation scope. Default: Shared. .PARAMETER ExpandUsage Include hourly usage data in the response. .PARAMETER ExpandAllRecommendationDetails Include all recommendation detail tiers in the response. .EXAMPLE Get-BenefitRecommendation -BillingAccountId "90846601" -LookBackPeriod Last30Days -Term P3Y -ExpandUsage -ExpandAllRecommendationDetails #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$BillingAccountId, [ValidateSet('Last7Days', 'Last30Days', 'Last60Days')] [string]$LookBackPeriod = 'Last60Days', [ValidateSet('P1Y', 'P3Y')] [string]$Term = 'P3Y', [ValidateSet('Single', 'Shared')] [string]$Scope = 'Shared', [switch]$ExpandUsage, [switch]$ExpandAllRecommendationDetails ) $path = "/providers/Microsoft.Billing/billingAccounts/$BillingAccountId/providers/Microsoft.CostManagement/benefitRecommendations" $filter = "properties/lookBackPeriod eq '$LookBackPeriod' AND properties/term eq '$Term' AND properties/scope eq '$Scope'" $expandParts = @() if ($ExpandUsage) { $expandParts += 'properties/usage' } if ($ExpandAllRecommendationDetails) { $expandParts += 'properties/allRecommendationDetails' } $queryString = "api-version=2025-03-01&`$filter=$filter" if ($expandParts.Count -gt 0) { $queryString += "&`$expand=$($expandParts -join ',')" } $fullPath = "${path}?${queryString}" Write-Verbose "Calling: $fullPath" $result = Invoke-AzRestMethod -Method GET -Path $fullPath -ErrorAction Stop if ($result.StatusCode -ne 200) { throw "API returned $($result.StatusCode): $($result.Content)" } $response = $result.Content | ConvertFrom-Json $count = ($response.value | Measure-Object).Count Write-Host "Retrieved $count benefit recommendation(s) for billing account $BillingAccountId" -ForegroundColor Green return $response.value } function Export-BenefitRecommendation { <# .SYNOPSIS Exports benefit recommendations to a JSON file for Kusto ingestion. .DESCRIPTION Takes benefit recommendation objects (from Get-BenefitRecommendation) and saves them as a JSON file ready for ingestion into the SavingsPlanRecommendations_raw table. Outputs the .set-or-append command to run in Azure Data Explorer. .PARAMETER Recommendations The recommendation array from Get-BenefitRecommendation. Accepts pipeline input. .PARAMETER OutputPath The output JSON file path. Default: BenefitRecommendations_<timestamp>.json in the current directory. .PARAMETER Table The target table name (used in the generated Kusto command). Default: SavingsPlanRecommendations_raw. .EXAMPLE Get-BenefitRecommendation -BillingAccountId "90846601" | Export-BenefitRecommendation .EXAMPLE $recs = Get-BenefitRecommendation -BillingAccountId "90846601" Export-BenefitRecommendation -Recommendations $recs -OutputPath "./recs.json" #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)] [object]$Recommendations, [string]$OutputPath, [string]$Table = 'SavingsPlanRecommendations_raw' ) begin { $collected = [System.Collections.Generic.List[object]]::new() } process { if ($Recommendations -is [System.Collections.IEnumerable] -and $Recommendations -isnot [string]) { foreach ($item in $Recommendations) { $collected.Add($item) } } else { $collected.Add($Recommendations) } } end { if ($collected.Count -eq 0) { Write-Warning "No recommendations to export." return } $jsonArray = @($collected) | ConvertTo-Json -Depth 100 -Compress -AsArray $command = ".set-or-append $Table <| print Recommendation=dynamic($jsonArray)" if ($OutputPath) { $command | Set-Content -Path $OutputPath -Encoding UTF8 Write-Host "Exported Kusto command to $OutputPath" -ForegroundColor Green } Write-Host "Run this in Azure Data Explorer:" -ForegroundColor Yellow return $command } } |