From f8d49988bc11b99abb0d6d0e5bc665b85d969292 Mon Sep 17 00:00:00 2001 From: Jan Faurskov <22591930+jfaurskov@users.noreply.github.com> Date: Thu, 27 Nov 2025 10:49:22 +0100 Subject: [PATCH 1/5] Initial commit --- 1-Collect/Get-AzureServices.ps1 | 25 +++++++++++++------ .../Get-AvailabilityInformation.ps1 | 21 ++++++++-------- 7-Report/Get-Report.ps1 | 12 ++++++--- 3 files changed, 35 insertions(+), 23 deletions(-) diff --git a/1-Collect/Get-AzureServices.ps1 b/1-Collect/Get-AzureServices.ps1 index 1e65484..ec94b4b 100644 --- a/1-Collect/Get-AzureServices.ps1 +++ b/1-Collect/Get-AzureServices.ps1 @@ -377,16 +377,25 @@ foreach ($group in $groupedResources) { if ($uniqueLocations -isnot [System.Array]) { $uniqueLocations = @($uniqueLocations) } - If ($group.Group.ResourceSku -ne 'N/A') { - - $uniqueSkus = $group.Group.ResourceSku | Select-Object * -Unique - if ( $uniqueSkus -isnot [System.Array]) { - $uniqueSkus = @($uniqueSkus) + if ($group.Group.ResourceSku -ne 'N/A') { + $skuCounts = $group.Group | + Where-Object { $_.ResourceSku -is [object] } | + Group-Object -Property { + $_.ResourceSku | ConvertTo-Json -Compress + } + $implementedSkus = foreach ($skuGroup in $skuCounts) { + $skuObj = $skuGroup.Group[0].ResourceSku + $newSku = [ordered]@{} + foreach ($prop in $skuObj.PSObject.Properties) { + $newSku[$prop.Name] = $prop.Value + } + $newSku["count"] = $skuGroup.Count + [PSCustomObject]$newSku } - $summary += [PSCustomObject]@{ResourceCount = $group.Count; ResourceType = $resourceType; ImplementedSkus = $uniqueSkus; ImplementedRegions = $uniqueLocations; meterIds = $uniqueMeterIds } + $summary += [PSCustomObject]@{ResourceCount = $group.Count; ResourceType = $resourceType; ImplementedSkus = $implementedSkus; ImplementedRegions = $uniqueLocations; MeterIds = $uniqueMeterIds } } - Else { - $summary += [PSCustomObject]@{ResourceCount = $group.Count; ResourceType = $resourceType; ImplementedSkus = @("N/A"); ImplementedRegions = $uniqueLocations; meterIds = $uniqueMeterIds } + else { + $summary += [PSCustomObject]@{ResourceCount = $group.Count; ResourceType = $resourceType; ImplementedSkus = @("N/A"); ImplementedRegions = $uniqueLocations; MeterIds = $uniqueMeterIds } } } $summary | ConvertTo-Json -Depth 100 | Out-File -FilePath $summaryOutputFile \ No newline at end of file diff --git a/2-AvailabilityCheck/Get-AvailabilityInformation.ps1 b/2-AvailabilityCheck/Get-AvailabilityInformation.ps1 index 2ec8264..cb89d60 100644 --- a/2-AvailabilityCheck/Get-AvailabilityInformation.ps1 +++ b/2-AvailabilityCheck/Get-AvailabilityInformation.ps1 @@ -155,22 +155,21 @@ Function Get-ResourceTypeParameters { function Compare-ObjectsStrict { param( [psobject]$Object1, - [psobject]$Object2 + [psobject]$Object2, + [string[]]$ExcludeProperty = @("count") ) - write-verbose "Entering Compare-ObjectsStrict" - $norm1 = ($Object1.PSObject.Properties | + Write-Verbose "Entering Compare-ObjectsStrict" + # Filter out excluded properties + $props1 = $Object1.PSObject.Properties | Where-Object { $ExcludeProperty -notcontains $_.Name } + $props2 = $Object2.PSObject.Properties | Where-Object { $ExcludeProperty -notcontains $_.Name } + $norm1 = ($props1 | Sort-Object Name | ForEach-Object { "$($_.Name)=$($_.Value)" }) -join ';' + $norm2 = ($props2 | Sort-Object Name | ForEach-Object { "$($_.Name)=$($_.Value)" }) -join ';' - - $norm2 = ($Object2.PSObject.Properties | - Sort-Object Name | - ForEach-Object { "$($_.Name)=$($_.Value)" }) -join ';' - Write-Verbose "Comparing objects:" - Write-Verbose " Object1: $norm1" - Write-Verbose " Object2: $norm2" + Write-Verbose " Object1 (norm): $norm1" + Write-Verbose " Object2 (norm): $norm2" Write-Verbose " Match: $($norm1 -eq $norm2)" - return $norm1 -eq $norm2 } diff --git a/7-Report/Get-Report.ps1 b/7-Report/Get-Report.ps1 index ffb5e06..2261986 100644 --- a/7-Report/Get-Report.ps1 +++ b/7-Report/Get-Report.ps1 @@ -98,6 +98,7 @@ Function Set-SvcAvailReportObj { [string]$resourceType, [int]$resourceCount, [array]$implementedRegions, + [string]$skuCount, [string]$sku, [string]$skuAvailability, [string]$serviceAvailability @@ -116,6 +117,7 @@ Function Set-SvcAvailReportObj { ResourceType = $resourceType ResourceCount = $resourceCount ImplementedRegions = ($implementedRegions -join ", ") + SKUCount = $skuCount sku = $sku "SKU available" = $skuAvailability "Service available" = $serviceAvailability @@ -145,21 +147,23 @@ If ($availabilityInfoPath) { if ($item.ImplementedSkus -and $item.ImplementedSkus[0] -ne "N/A") { if ( $regionAvailability -eq "Available") { ForEach ($sku in $item.SelectedRegion.SKUs) { - $skuName = ($sku.PSObject.Properties | Where-Object { $_.Name -ne 'available' } | ForEach-Object { $_.Value }) -join "_" - $reportItem = Set-SvcAvailReportObj -resourceType $resourceType -resourceCount $itemCount -implementedRegions $item.ImplementedRegions -sku $skuName -skuAvailability $sku.available -serviceAvailability $regionAvailability + $skuName = ($sku.PSObject.Properties | Where-Object { $_.Name -ne 'available'-and $_.Name -ne 'count' } | ForEach-Object { $_.Value }) -join "_" + $skuCount = $sku.count + $reportItem = Set-SvcAvailReportObj -resourceType $resourceType -resourceCount $itemCount -implementedRegions $item.ImplementedRegions -skuCount $skuCount -sku $skuName -skuAvailability $sku.available -serviceAvailability $regionAvailability $reportData += $reportItem } } else { ForEach ($sku in $item.ImplementedSkus) { $skuName = ($sku.PSObject.Properties | Where-Object { $_.Name -ne 'available' } | ForEach-Object { $_.Value }) -join "_" - $reportItem = Set-SvcAvailReportObj -resourceType $resourceType -resourceCount $itemCount -implementedRegions $item.ImplementedRegions -sku $skuName -skuAvailability "false" -serviceAvailability $regionAvailability + $skuCount = $sku.count + $reportItem = Set-SvcAvailReportObj -resourceType $resourceType -resourceCount $itemCount -implementedRegions $item.ImplementedRegions -skuCount $skuCount -sku $skuName -skuAvailability "false" -serviceAvailability $regionAvailability $reportData += $reportItem } } } else { - $reportItem = Set-SvcAvailReportObj -resourceType $resourceType -resourceCount $itemCount -implementedRegions $item.ImplementedRegions -sku "N/A" -skuAvailability "N/A" -serviceAvailability $regionAvailability + $reportItem = Set-SvcAvailReportObj -resourceType $resourceType -resourceCount $itemCount -implementedRegions $item.ImplementedRegions -skuCount "N/A" -sku "N/A" -skuAvailability "N/A" -serviceAvailability $regionAvailability $reportData += $reportItem } } From 6707dda73f63728bb88248031ce20106dff8e904 Mon Sep 17 00:00:00 2001 From: Jan Faurskov <22591930+jfaurskov@users.noreply.github.com> Date: Thu, 27 Nov 2025 10:56:57 +0100 Subject: [PATCH 2/5] Update 7-Report/Get-Report.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- 7-Report/Get-Report.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/7-Report/Get-Report.ps1 b/7-Report/Get-Report.ps1 index 2261986..9e63fea 100644 --- a/7-Report/Get-Report.ps1 +++ b/7-Report/Get-Report.ps1 @@ -147,7 +147,7 @@ If ($availabilityInfoPath) { if ($item.ImplementedSkus -and $item.ImplementedSkus[0] -ne "N/A") { if ( $regionAvailability -eq "Available") { ForEach ($sku in $item.SelectedRegion.SKUs) { - $skuName = ($sku.PSObject.Properties | Where-Object { $_.Name -ne 'available'-and $_.Name -ne 'count' } | ForEach-Object { $_.Value }) -join "_" + $skuName = ($sku.PSObject.Properties | Where-Object { $_.Name -ne 'available' -and $_.Name -ne 'count' } | ForEach-Object { $_.Value }) -join "_" $skuCount = $sku.count $reportItem = Set-SvcAvailReportObj -resourceType $resourceType -resourceCount $itemCount -implementedRegions $item.ImplementedRegions -skuCount $skuCount -sku $skuName -skuAvailability $sku.available -serviceAvailability $regionAvailability $reportData += $reportItem From f5fd61ed1d6f6542ca9f2ffaf4a7816f96f4b94f Mon Sep 17 00:00:00 2001 From: Jan Faurskov <22591930+jfaurskov@users.noreply.github.com> Date: Thu, 27 Nov 2025 10:59:33 +0100 Subject: [PATCH 3/5] Update 7-Report/Get-Report.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- 7-Report/Get-Report.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/7-Report/Get-Report.ps1 b/7-Report/Get-Report.ps1 index 9e63fea..edacf63 100644 --- a/7-Report/Get-Report.ps1 +++ b/7-Report/Get-Report.ps1 @@ -155,7 +155,7 @@ If ($availabilityInfoPath) { } else { ForEach ($sku in $item.ImplementedSkus) { - $skuName = ($sku.PSObject.Properties | Where-Object { $_.Name -ne 'available' } | ForEach-Object { $_.Value }) -join "_" + $skuName = ($sku.PSObject.Properties | Where-Object { $_.Name -ne 'available' -and $_.Name -ne 'count' } | ForEach-Object { $_.Value }) -join "_" $skuCount = $sku.count $reportItem = Set-SvcAvailReportObj -resourceType $resourceType -resourceCount $itemCount -implementedRegions $item.ImplementedRegions -skuCount $skuCount -sku $skuName -skuAvailability "false" -serviceAvailability $regionAvailability $reportData += $reportItem From 7d870af3ef12bd5a05b279ade0c81d82ffde8718 Mon Sep 17 00:00:00 2001 From: Jan Faurskov <22591930+jfaurskov@users.noreply.github.com> Date: Thu, 27 Nov 2025 11:04:20 +0100 Subject: [PATCH 4/5] meterIds --- 1-Collect/Get-AzureServices.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/1-Collect/Get-AzureServices.ps1 b/1-Collect/Get-AzureServices.ps1 index ec94b4b..6336b1f 100644 --- a/1-Collect/Get-AzureServices.ps1 +++ b/1-Collect/Get-AzureServices.ps1 @@ -392,10 +392,10 @@ foreach ($group in $groupedResources) { $newSku["count"] = $skuGroup.Count [PSCustomObject]$newSku } - $summary += [PSCustomObject]@{ResourceCount = $group.Count; ResourceType = $resourceType; ImplementedSkus = $implementedSkus; ImplementedRegions = $uniqueLocations; MeterIds = $uniqueMeterIds } + $summary += [PSCustomObject]@{ResourceCount = $group.Count; ResourceType = $resourceType; ImplementedSkus = $implementedSkus; ImplementedRegions = $uniqueLocations; meterIds = $uniqueMeterIds } } else { - $summary += [PSCustomObject]@{ResourceCount = $group.Count; ResourceType = $resourceType; ImplementedSkus = @("N/A"); ImplementedRegions = $uniqueLocations; MeterIds = $uniqueMeterIds } + $summary += [PSCustomObject]@{ResourceCount = $group.Count; ResourceType = $resourceType; ImplementedSkus = @("N/A"); ImplementedRegions = $uniqueLocations; meterIds = $uniqueMeterIds } } } $summary | ConvertTo-Json -Depth 100 | Out-File -FilePath $summaryOutputFile \ No newline at end of file From e72c64cdbf10eb5b3d2efaca439aece78db171b4 Mon Sep 17 00:00:00 2001 From: Jan Faurskov <22591930+jfaurskov@users.noreply.github.com> Date: Thu, 27 Nov 2025 12:32:02 +0100 Subject: [PATCH 5/5] flexible file path for get-AvailabilityInformation.ps1 --- 2-AvailabilityCheck/Get-AvailabilityInformation.ps1 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/2-AvailabilityCheck/Get-AvailabilityInformation.ps1 b/2-AvailabilityCheck/Get-AvailabilityInformation.ps1 index cb89d60..1f4f3c7 100644 --- a/2-AvailabilityCheck/Get-AvailabilityInformation.ps1 +++ b/2-AvailabilityCheck/Get-AvailabilityInformation.ps1 @@ -24,6 +24,9 @@ .NOTES - Requires Azure PowerShell module to be installed and authenticated. #> +param( + [Parameter(Mandatory = $false)][string]$SummaryFilePath = "$(Get-Location)\..\1-Collect\summary.json" +) function Out-JSONFile { param ( @@ -295,14 +298,13 @@ Function Get-ResourceType { } function Import-CurrentEnvironment { - $SummaryFilePath = "$(Get-Location)\..\1-Collect\summary.json" # Check if the summary file exists and load it if (Test-Path $SummaryFilePath) { - Write-Output " Loading summary file: ../1-Collect/summary.json" | Out-Host + Write-Output " Loading summary file: $SummaryFilePath" | Out-Host $CurrentEnvironment = Get-Content -Path $SummaryFilePath -raw | ConvertFrom-Json -depth 10 } else { - Write-Output "File 'summary.json' not found in '../1-Collect/summary.json'." + Write-Output "File '$SummaryFilePath' not found." exit 1 } # Check for empty SKUs and remove 'ResourceSkus' property if its value is 'N/A' in the current implementation data