Src/Private/Diagram/Get-AbrDiagAzManagementGroup.ps1
|
function Get-AbrDiagAzManagementGroup { [CmdletBinding()] param ( [Parameter(Mandatory)] [Object] $RootManagementGroup ) begin { $LocalizedData = $reportTranslate.GetAbrAzManagementGroup } process { try { $DiagramTheme = if ($Options.DiagramTheme) { $Options.DiagramTheme } else { 'White' } $DiagramDpi = if ($Options.DiagramDpi) { $Options.DiagramDpi } else { 96 } # PScribo's Image -Percent scales off raw pixel count assuming a fixed 96 DPI baseline, # so a higher render DPI must be offset by a proportionally lower Percent to keep the # printed size on the page the same while still gaining pixel density. $DiagramPercent = [Math]::Max(1, [Math]::Round(9600 / $DiagramDpi)) $FontColor = if ($DiagramTheme -eq 'Black') { '#FFFFFF' } else { '#000000' } $EdgeColor = if ($DiagramTheme -eq 'Black') { '#AAAAAA' } else { '#333333' } $CellBgColor = if ($DiagramTheme -eq 'Black') { '#2D2D2D' } else { '#FFFFFF' } $TableBorderColor = if ($DiagramTheme -eq 'Black') { '#AAAAAA' } else { '#333333' } $ModuleBase = (Get-Module -Name 'AsBuiltReport.Microsoft.Azure').ModuleBase $IconPath = [System.IO.FileInfo](Join-Path $ModuleBase 'Icons') $ImagesObj = @{ 'MG' = 'management-groups.png' 'Sub' = 'subscriptions.png' 'Blank' = 'blank.png' } # Pass 1: BFS to collect all MG info in root-to-leaf order $MgList = [System.Collections.Generic.List[hashtable]]::new() $MgQueue = [System.Collections.Queue]::new() $MgQueue.Enqueue(@{ MG = $RootManagementGroup; ParentId = $null }) while ($MgQueue.Count -gt 0) { $Item = $MgQueue.Dequeue() $CurrentMG = $Item.MG $DirectSubs = @($CurrentMG.Children | Where-Object { $_.Type -like '*subscriptions*' } | Select-Object -ExpandProperty DisplayName) $ChildMgIds = @($CurrentMG.Children | Where-Object { $_.Type -like '*managementGroups*' } | Select-Object -ExpandProperty Name) $MgList.Add(@{ Id = $CurrentMG.Name DisplayName = $CurrentMG.DisplayName ParentId = $Item.ParentId Subscriptions = $DirectSubs ChildMgIds = $ChildMgIds }) foreach ($MgChild in $CurrentMG.Children) { if ($MgChild.Type -like '*managementGroups*') { $MgQueue.Enqueue(@{ MG = $MgChild; ParentId = $CurrentMG.Name }) } } } # Pass 2: propagate "has subscriptions in subtree" from leaves to root. # Reverse BFS order guarantees children are processed before their parents. $HasSubsInSubtree = [System.Collections.Generic.HashSet[string]]::new() for ($i = $MgList.Count - 1; $i -ge 0; $i--) { $MgInfo = $MgList[$i] $ChildWithSubs = $MgInfo.ChildMgIds | Where-Object { $HasSubsInSubtree.Contains($_) } if ($MgInfo.Subscriptions.Count -gt 0 -or $ChildWithSubs) { $null = $HasSubsInSubtree.Add($MgInfo.Id) } } # Build PSGraph content — no outer graph{} wrapper. # Each MG is a simple icon node. Subscriptions are SEPARATE collection nodes # connected by edges so Graphviz places them at the same rank as sibling child MGs. $DiagramGraph = & { # MG nodes — all rendered as simple icon + name nodes foreach ($MgInfo in $MgList) { if (-not $HasSubsInSubtree.Contains($MgInfo.Id)) { continue } $SafeId = 'MG_' + ($MgInfo.Id -replace '[^a-zA-Z0-9]', '_') Add-HtmlNodeTable ` -Name $SafeId ` -ImagesObj $ImagesObj ` -inputObject @($MgInfo.DisplayName) ` -iconType 'MG' ` -IconWidth 60 ` -IconHeight 60 ` -FontColor $FontColor ` -CellBackgroundColor $CellBgColor ` -NodeObject } # Subscription collection nodes — one per MG that has direct subscriptions. # Kept separate so Graphviz ranks them alongside sibling child MGs. foreach ($MgInfo in $MgList) { if (-not $HasSubsInSubtree.Contains($MgInfo.Id)) { continue } if ($MgInfo.Subscriptions.Count -eq 0) { continue } $SubNodeId = 'Sub_' + ($MgInfo.Id -replace '[^a-zA-Z0-9]', '_') $SubLabel = "$($MgInfo.Subscriptions.Count) $($LocalizedData.SubscriptionCount)" Add-HtmlNodeTable ` -Name $SubNodeId ` -ImagesObj $ImagesObj ` -inputObject ([string[]]$MgInfo.Subscriptions) ` -iconType 'Blank' ` -Subgraph ` -SubgraphLabel $SubLabel ` -SubgraphIconType 'Sub' ` -SubgraphIconWidth 60 ` -SubgraphIconHeight 60 ` -SubgraphLabelPos 'top' ` -ColumnSize 1 ` -TableBorderColor $TableBorderColor ` -CellBackgroundColor $CellBgColor ` -FontColor $FontColor ` -NodeObject } # Edges: MG → parent MG, and MG → its subscription collection node foreach ($MgInfo in $MgList) { if (-not $HasSubsInSubtree.Contains($MgInfo.Id)) { continue } $SafeId = 'MG_' + ($MgInfo.Id -replace '[^a-zA-Z0-9]', '_') if ($null -ne $MgInfo.ParentId -and $HasSubsInSubtree.Contains($MgInfo.ParentId)) { $SafeParentId = 'MG_' + ($MgInfo.ParentId -replace '[^a-zA-Z0-9]', '_') Edge $SafeParentId $SafeId @{ color = $EdgeColor; style = 'solid' } } if ($MgInfo.Subscriptions.Count -gt 0) { $SubNodeId = 'Sub_' + ($MgInfo.Id -replace '[^a-zA-Z0-9]', '_') Edge $SafeId $SubNodeId @{ color = $EdgeColor; style = 'solid' } } } } $DiagramResult = New-AbrDiagram ` -InputObject $DiagramGraph ` -Format base64 ` -MainDiagramLabel $LocalizedData.DiagramHeading ` -IconPath $IconPath ` -ImagesObj $ImagesObj ` -MainGraphSize '6.5,9' ` -Dpi $DiagramDpi ` -DisableMainDiagramLogo if ($DiagramResult) { Image -Base64 $DiagramResult -Text $LocalizedData.DiagramAltText -Percent $DiagramPercent BlankLine } } catch { Write-PScriboMessage -IsWarning $_.Exception.Message } } end {} } |