Private/ConvertTo-AACResourceSummaryMap.ps1
|
function ConvertTo-AACResourceSummaryMap { <# .SYNOPSIS Turns every resource into the resource map's model as ARI's "resources" view draws it: each subscription a box, holding a node per resource type with how many there are - for Invoke-AACAssessment's <name>-Resources.html. .DESCRIPTION A node per subscription and resource type: the type's Azure icon and name, the count, and the locations and resource groups they're in. It stays readable at any tenant size, where a node per resource wouldn't (-DiagramFullEnvironment's network diagram draws those). -Resource: rows with type and subscriptionId (and location, resourceGroup); -IconType: type -> icon key; -IconLabel: icon key -> product name. Returns @{ Clusters; Nodes; Edges; Stats } as ConvertTo-AACResourceMap does. #> [CmdletBinding()] [OutputType([hashtable])] param( [AllowEmptyCollection()] [object[]] $Resource = @(), [hashtable] $SubscriptionName = @{}, [hashtable] $IconType = @{}, [hashtable] $IconLabel = @{} ) $value = { param($Row, [string] $Key) if ($Row -is [System.Collections.IDictionary]) { if ($Row.Contains($Key)) { $Row[$Key] } } elseif ($null -ne $Row) { Get-AACPropertyValue -InputObject $Row -Name $Key } } $clusters = [System.Collections.Generic.List[hashtable]]::new() $nodes = [System.Collections.Generic.List[hashtable]]::new() $bySubscription = @($Resource | Group-Object { ([string](& $value $_ 'subscriptionId')).ToLowerInvariant() } | Sort-Object { if ($SubscriptionName.Contains($_.Name)) { $SubscriptionName[$_.Name] } else { $_.Name } }) foreach ($subscription in $bySubscription) { $sub = $subscription.Name $subName = if ($SubscriptionName.Contains($sub)) { $SubscriptionName[$sub] } else { $sub } $types = @($subscription.Group | Group-Object { ([string](& $value $_ 'type')).ToLowerInvariant() } | Sort-Object Count -Descending) $clusters.Add(@{ id = "/subscriptions/$sub"; kind = 'subscription'; parent = ''; name = $subName; detail = @($sub, "$($subscription.Count) resource(s)", "$($types.Count) type(s)"); icon = 'subscription'; external = $false; badges = @(); chips = @() }) foreach ($type in $types) { $icon = if ($IconType.Contains($type.Name)) { $IconType[$type.Name] } else { 'resource' } $label = if ($icon -ne 'resource' -and $IconLabel.Contains($icon) -and $IconLabel[$icon]) { $IconLabel[$icon] } else { ($type.Name -split '/')[-1] } $locations = @($type.Group | ForEach-Object { [string](& $value $_ 'location') } | Where-Object { $_ } | Sort-Object -Unique) $groups = @($type.Group | ForEach-Object { [string](& $value $_ 'resourceGroup') } | Where-Object { $_ } | Sort-Object -Unique) $nodes.Add(@{ id = "/subscriptions/$sub/types/$($type.Name)"; parent = "/subscriptions/$sub"; name = "$label ($($type.Count))"; type = $type.Name; typeLabel = $label; icon = $icon; kind = '' location = ($locations -join ', '); resourceGroup = ''; subscriptionId = $sub; subscription = $subName; sku = '' facts = @("$($type.Count) resource(s)", "$($groups.Count) resource group(s)", $(if ($locations.Count -le 4) { $locations -join ', ' } else { "$($locations.Count) locations" })) tags = $null; orphan = ''; external = $false; chips = @(); chip = ''; appliedTo = @(); risk = ''; rules = @(); routes = @(); propagation = '' }) } } @{ Clusters = $clusters.ToArray() Nodes = $nodes.ToArray() Edges = @() Stats = @{ Subscriptions = $clusters.Count; Types = $nodes.Count; Resources = @($Resource).Count; Connections = 0 } } } |