Modules/Diagram/ARIDiagramOrganization.psm1
<#
.Synopsis Organization Module for Draw.io Diagram .DESCRIPTION This module is use for the Organization topology in the Draw.io Diagram. .Link https://github.com/microsoft/ARI/Modules/Extras/ARIDiagramOrganization.psm1 .COMPONENT This powershell Module is part of Azure Resource Inventory (ARI) .NOTES Version: 4.0.1 First Release Date: 15th Oct, 2024 Authors: Claudio Merola #> Function Invoke-ARIDiagramOrganization { Param($ResourceContainers,$DiagramCache,$LogFile) Start-Job -Name 'Diagram_Organization' -ScriptBlock { Import-Module AzureResourceInventory $Script:ResourceContainers = $($args[0]) $Script:DiagramCache = $($args[1]) Function Icon { Param($Style,$x,$y,$w,$h,$p) $Script:XmlWriter.WriteStartElement('mxCell') $Script:XmlWriter.WriteAttributeString('style', $Style) $Script:XmlWriter.WriteAttributeString('vertex', "1") $Script:XmlWriter.WriteAttributeString('parent', $p) $Script:XmlWriter.WriteStartElement('mxGeometry') $Script:XmlWriter.WriteAttributeString('x', $x) $Script:XmlWriter.WriteAttributeString('y', $y) $Script:XmlWriter.WriteAttributeString('width', $w) $Script:XmlWriter.WriteAttributeString('height', $h) $Script:XmlWriter.WriteAttributeString('as', "geometry") $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteEndElement() } Function Connect { Param($Source,$Target,$Parent) if($Parent){$Parent = $Parent}else{$Parent = 1} $Script:XmlWriter.WriteStartElement('mxCell') $Script:XmlWriter.WriteAttributeString('id', ($Script:CellID+'-'+($Script:IDNum++))) $Script:XmlWriter.WriteAttributeString('style', "edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;") $Script:XmlWriter.WriteAttributeString('edge', "1") $Script:XmlWriter.WriteAttributeString('vertex', "1") $Script:XmlWriter.WriteAttributeString('parent', $Parent) $Script:XmlWriter.WriteAttributeString('source', $Source) $Script:XmlWriter.WriteAttributeString('target', $Target) $Script:XmlWriter.WriteStartElement('mxGeometry') $Script:XmlWriter.WriteAttributeString('relative', "1") $Script:XmlWriter.WriteAttributeString('as', "geometry") $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteEndElement() } Function Container0 { Param($x,$y,$w,$h,$title) $Script:ContID0 = (-join ((65..90) + (97..122) | Get-Random -Count 20 | ForEach-Object {[char]$_})+'-'+1) $Script:XmlWriter.WriteStartElement('mxCell') $Script:XmlWriter.WriteAttributeString('id', $Script:ContID0) $Script:XmlWriter.WriteAttributeString('value', "$title") $Script:XmlWriter.WriteAttributeString('style', "swimlane;whiteSpace=wrap;html=1;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;swimlaneFillColor=#F5F5F5;rounded=1;") $Script:XmlWriter.WriteAttributeString('vertex', "1") $Script:XmlWriter.WriteAttributeString('parent', "1") $Script:XmlWriter.WriteStartElement('mxGeometry') $Script:XmlWriter.WriteAttributeString('x', $x) $Script:XmlWriter.WriteAttributeString('y', $y) $Script:XmlWriter.WriteAttributeString('width', $w) $Script:XmlWriter.WriteAttributeString('height', $h) $Script:XmlWriter.WriteAttributeString('as', "geometry") $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteEndElement() } Function Container1 { Param($x,$y,$w,$h,$title) $Script:ContID = (-join ((65..90) + (97..122) | Get-Random -Count 20 | ForEach-Object {[char]$_})+'-'+1) $Script:XmlWriter.WriteStartElement('mxCell') $Script:XmlWriter.WriteAttributeString('id', $Script:ContID) $Script:XmlWriter.WriteAttributeString('value', "$title") $Script:XmlWriter.WriteAttributeString('style', "swimlane;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;swimlaneFillColor=#D5E8D4;rounded=1;") $Script:XmlWriter.WriteAttributeString('vertex', "1") $Script:XmlWriter.WriteAttributeString('parent', "1") $Script:XmlWriter.WriteStartElement('mxGeometry') $Script:XmlWriter.WriteAttributeString('x', $x) $Script:XmlWriter.WriteAttributeString('y', $y) $Script:XmlWriter.WriteAttributeString('width', $w) $Script:XmlWriter.WriteAttributeString('height', $h) $Script:XmlWriter.WriteAttributeString('as', "geometry") $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteEndElement() } Function Container2 { Param($x,$y,$w,$h,$title,$p) $Script:ContID2 = (-join ((65..90) + (97..122) | Get-Random -Count 20 | ForEach-Object {[char]$_})+'-'+1) $Script:XmlWriter.WriteStartElement('mxCell') $Script:XmlWriter.WriteAttributeString('id', $Script:ContID2) $Script:XmlWriter.WriteAttributeString('value', "$title") $Script:XmlWriter.WriteAttributeString('style', "swimlane;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;swimlaneFillColor=#DAE8FC;rounded=1;") $Script:XmlWriter.WriteAttributeString('vertex', "1") $Script:XmlWriter.WriteAttributeString('parent', $p) $Script:XmlWriter.WriteStartElement('mxGeometry') $Script:XmlWriter.WriteAttributeString('x', $x) $Script:XmlWriter.WriteAttributeString('y', $y) $Script:XmlWriter.WriteAttributeString('width', $w) $Script:XmlWriter.WriteAttributeString('height', $h) $Script:XmlWriter.WriteAttributeString('as', "geometry") $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteEndElement() } Function Container3 { Param($x,$y,$w,$h,$title,$p) $Script:ContID3 = (-join ((65..90) + (97..122) | Get-Random -Count 20 | ForEach-Object {[char]$_})+'-'+1) $Script:XmlWriter.WriteStartElement('mxCell') $Script:XmlWriter.WriteAttributeString('id', $Script:ContID3) $Script:XmlWriter.WriteAttributeString('value', "$title") $Script:XmlWriter.WriteAttributeString('style', "swimlane;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;swimlaneFillColor=#FFE6CC;rounded=1;") $Script:XmlWriter.WriteAttributeString('vertex', "1") $Script:XmlWriter.WriteAttributeString('parent', $p) $Script:XmlWriter.WriteStartElement('mxGeometry') $Script:XmlWriter.WriteAttributeString('x', $x) $Script:XmlWriter.WriteAttributeString('y', $y) $Script:XmlWriter.WriteAttributeString('width', $w) $Script:XmlWriter.WriteAttributeString('height', $h) $Script:XmlWriter.WriteAttributeString('as', "geometry") $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteEndElement() } Function Container4 { Param($x,$y,$w,$h,$title,$p) $Script:ContID4 = (-join ((65..90) + (97..122) | Get-Random -Count 20 | ForEach-Object {[char]$_})+'-'+1) $Script:XmlWriter.WriteStartElement('mxCell') $Script:XmlWriter.WriteAttributeString('id', $Script:ContID4) $Script:XmlWriter.WriteAttributeString('value', "$title") $Script:XmlWriter.WriteAttributeString('style', "swimlane;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;swimlaneFillColor=#FFE6CC;rounded=1;") $Script:XmlWriter.WriteAttributeString('vertex', "1") $Script:XmlWriter.WriteAttributeString('parent', $p) $Script:XmlWriter.WriteStartElement('mxGeometry') $Script:XmlWriter.WriteAttributeString('x', $x) $Script:XmlWriter.WriteAttributeString('y', $y) $Script:XmlWriter.WriteAttributeString('width', $w) $Script:XmlWriter.WriteAttributeString('height', $h) $Script:XmlWriter.WriteAttributeString('as', "geometry") $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteEndElement() } Function Stencils { $Script:IconSubscription = "aspect=fixed;html=1;points=[];align=center;image;fontSize=20;image=img/lib/azure2/general/Subscriptions.svg;" #width="44" height="71" $Script:IconMgmtGroup = "aspect=fixed;html=1;points=[];align=center;image;fontSize=20;image=img/lib/azure2/general/Management_Groups.svg;" #width="44" height="71" $Script:Ret = "rounded=1;whiteSpace=wrap;fontSize=16;html=1;sketch=0;fontFamily=Helvetica;" $Script:Ret1 = "rounded=1;whiteSpace=wrap;fontSize=16;html=1;sketch=0;fontFamily=Helvetica;fillColor=#b0e3e6;strokeColor=#0e8088;" $Script:Ret2 = "rounded=1;whiteSpace=wrap;fontSize=16;html=1;sketch=0;fontFamily=Helvetica;fillColor=#b1ddf0;strokeColor=#10739e;" $Script:Ret3 = "rounded=1;whiteSpace=wrap;fontSize=16;html=1;sketch=0;fontFamily=Helvetica;fillColor=#fad7ac;strokeColor=#b46504;" $Script:Ret4 = "rounded=1;whiteSpace=wrap;fontSize=16;html=1;sketch=0;fontFamily=Helvetica;fillColor=#e1d5e7;strokeColor=#9673a6;" } Function Org { $OrgObjs = $Script:ResourceContainers | Where-Object {$_.Type -eq 'microsoft.resources/subscriptions'} $Script:1stLevel = @() $Lvl2 = @() $Lvl3 = @() $Lvl4 = @() foreach($org in $OrgObjs) { if($org.properties.managementgroupancestorschain.count -eq 2) { $Script:1stLevel += $org.properties.managementgroupancestorschain.displayname[0] } if($org.properties.managementgroupancestorschain.count -eq 3) { $Lvl2 += $org.properties.managementgroupancestorschain.name[0] $Script:1stLevel += $org.properties.managementgroupancestorschain.displayname[1] } if($org.properties.managementgroupancestorschain.count -eq 4) { $Lvl3 += $org.properties.managementgroupancestorschain.name[0] $Lvl2 += $org.properties.managementgroupancestorschain.name[1] $Script:1stLevel += $org.properties.managementgroupancestorschain.displayname[2] } if($org.properties.managementgroupancestorschain.count -eq 5) { $Lvl4 += $org.properties.managementgroupancestorschain.name[0] $Lvl3 += $org.properties.managementgroupancestorschain.name[1] $Lvl2 += $org.properties.managementgroupancestorschain.name[2] $Script:1stLevel += $org.properties.managementgroupancestorschain.displayname[3] } } $Script:1stLevel = $Script:1stLevel | Select-Object -Unique $Lvl2 = $Lvl2 | Select-Object -Unique $Lvl3 = $Lvl3 | Select-Object -Unique $Lvl4 = $Lvl4 | Select-Object -Unique $Script:XLeft = 0 $Script:XTop = 100 $XXLeft = 100 $Script:XTop = $Script:XTop + 200 $RoundSubs00 = @() foreach($Sub in $OrgObjs) { if($Sub.properties.managementgroupancestorschain[0].displayname -eq 'tenant root group') { $RoundSubs00 += $Sub } } $MgmtHeight0 = (($RoundSubs00.id.count * 70) + 80) Container0 '0' '0' '200' $MgmtHeight0 'tenant root group' $Script:XmlWriter.WriteStartElement('object') $Script:XmlWriter.WriteAttributeString('label', '') $Script:XmlWriter.WriteAttributeString('ManagementGroup', 'tenant root group') $Script:XmlWriter.WriteAttributeString('id', ($Script:CellID+'-'+($Script:IDNum++))) if($RoundSubs00) { icon $Script:IconMgmtGroup '-30' ($MgmtHeight0-15) '50' '50' $Script:ContID0 } else { icon $Script:IconMgmtGroup '75' '27' '50' '50' $Script:ContID0 } $Script:XmlWriter.WriteEndElement() $LocalTop = 50 $LocalLeft = 25 foreach($Sub in $RoundSubs00) { $RGs = $Script:ResourceContainers | Where-Object {$_.Type -eq 'microsoft.resources/subscriptions/resourcegroups' -and $_.subscriptionid -eq $sub.subscriptionid} $Script:XmlWriter.WriteStartElement('object') $Script:XmlWriter.WriteAttributeString('label', $sub.name) $Script:XmlWriter.WriteAttributeString('id', ($Script:CellIDRes+'-'+($Script:CelNum++))) Icon $Ret1 $LocalLeft $LocalTop '150' '70' $Script:ContID0 $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteStartElement('object') $Script:XmlWriter.WriteAttributeString('label', '') $RGNum = 1 foreach($RG in $RGs) { $Attr = ('ResourceGroup_'+[string]$RGNum) $Script:XmlWriter.WriteAttributeString($Attr, [string]$RG.Name) $RGNum++ } $Script:XmlWriter.WriteAttributeString('id', ($Script:CellID+'-'+($Script:IDNum++))) icon $Script:IconSubscription ($LocalLeft+140) ($LocalTop+40) '31' '51' $Script:ContID0 $Script:XmlWriter.WriteEndElement() $LocalTop = $LocalTop + 90 } foreach($1stlvl in $Script:1stLevel) { $RoundSubs0 = @() foreach($Sub in $OrgObjs) { if($Sub.properties.managementgroupancestorschain.displayname[0] -eq $1stlvl) { $RoundSubs0 += $Sub } } $MgmtHeight = (($RoundSubs0.id.count * 70) + 80) Container1 $XLeft $XTop '200' $MgmtHeight $1stlvl $Script:ContID0 $Script:XmlWriter.WriteStartElement('object') $Script:XmlWriter.WriteAttributeString('label', '') $Script:XmlWriter.WriteAttributeString('ManagementGroup', [string]$1stlvl) $Script:XmlWriter.WriteAttributeString('id', ($Script:CellID+'-'+($Script:IDNum++))) if($RoundSubs0) { icon $Script:IconMgmtGroup '-30' ($MgmtHeight-15) '50' '50' $Script:ContID } else { icon $Script:IconMgmtGroup '75' '27' '50' '50' $Script:ContID } $Script:XmlWriter.WriteEndElement() Connect $Script:ContID0 $Script:ContID $LocalTop = 50 $LocalLeft = 25 foreach($Sub in $RoundSubs0) { $RGs = $Script:ResourceContainers | Where-Object {$_.Type -eq 'microsoft.resources/subscriptions/resourcegroups' -and $_.subscriptionid -eq $sub.subscriptionid} $Script:XmlWriter.WriteStartElement('object') $Script:XmlWriter.WriteAttributeString('label', $sub.name) $Script:XmlWriter.WriteAttributeString('id', ($Script:CellIDRes+'-'+($Script:CelNum++))) Icon $Ret1 $LocalLeft $LocalTop '150' '70' $Script:ContID $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteStartElement('object') $Script:XmlWriter.WriteAttributeString('label', '') $RGNum = 1 foreach($RG in $RGs) { $Attr = ('ResourceGroup_'+[string]$RGNum) $Script:XmlWriter.WriteAttributeString($Attr, [string]$RG.Name) $RGNum++ } $Script:XmlWriter.WriteAttributeString('id', ($Script:CellID+'-'+($Script:IDNum++))) icon $Script:IconSubscription ($LocalLeft+140) ($LocalTop+40) '31' '51' $Script:ContID $Script:XmlWriter.WriteEndElement() $LocalTop = $LocalTop + 90 } ######################################## 2ND LEVEL ############################################## $2ndLevel = @() foreach($sub2nd in $OrgObjs) { if($sub2nd.properties.managementgroupancestorschain.displayname[1] -eq $1stlvl) { $2ndLevel += $sub2nd.properties.managementgroupancestorschain.name[0] } if($sub2nd.properties.managementgroupancestorschain.displayname[2] -eq $1stlvl) { $2ndLevel += $sub2nd.properties.managementgroupancestorschain.name[1] } if($sub2nd.properties.managementgroupancestorschain.displayname[3] -eq $1stlvl) { $2ndLevel += $sub2nd.properties.managementgroupancestorschain.name[2] } } $2ndLevel = $2ndLevel | Select-Object -Unique $XXLeft = 0 if($2ndLevel.count % 2 -eq 1 ) { $Align = $true $loops = -[Math]::ceiling($2ndLevel.count /2 - 1) } else { $Align = $false $loops = [Math]::ceiling($2ndLevel.count / 2) } if($2ndLevel.count -eq 1) { $loops = 1 } $TempSon = 0 foreach($2nd in $2ndLevel) { $RoundSubs = @() $Temp3rd = @() $Temp4rd = @() $Temp5th = @() foreach($Sub in $OrgObjs) { if($Sub.properties.managementgroupancestorschain.name[0] -eq $2nd) { $RoundSubs += $Sub } if($Sub.properties.managementgroupancestorschain.name[1] -eq $2nd) { $Temp3rd += $Sub.properties.managementgroupancestorschain.name[0] } if($Sub.properties.managementgroupancestorschain.name[2] -eq $2nd) { $Temp4rd += $Sub.properties.managementgroupancestorschain.name[0] $Temp3rd += $Sub.properties.managementgroupancestorschain.name[1] } if($Sub.properties.managementgroupancestorschain.name[3] -eq $2nd) { $Temp5th += $Sub.properties.managementgroupancestorschain.name[0] $Temp4rd += $Sub.properties.managementgroupancestorschain.name[1] $Temp3rd += $Sub.properties.managementgroupancestorschain.name[2] } } $Temp3rd = $Temp3rd | Select-Object -Unique $Temp4rd = $Temp4rd | Select-Object -Unique $Temp5th = $Temp5th | Select-Object -Unique if($XXLeft -eq 0 -and $Align -eq $true) { } elseif($XXLeft -eq 0 -and $Align -eq $false) { $XXLeft = -150 + -((((($Temp3rd.count)+($Temp4rd.count)+($Temp5th.count)))*300)/2) $loops++ } elseif($Align -eq $false -and $loops -eq 0) { $XXLeft = 150 + ((((($Temp3rd.count)+($Temp4rd.count)+($Temp5th.count)))*300)/2) $loops++ } elseif($loops -gt 0 -and $XXLeft -eq 0) { $XXLeft = $XXLeft + ($2ndLevel.count*300)/2 + ((((($Temp3rd.count)+($Temp4rd.count)+($Temp5th.count)))*300)/2) $loops++ } elseif($XXLeft -le 0 -and $loops -lt 0) { $XXTemp = if(((((($Temp3rd.count)+($Temp4rd.count)+($Temp5th.count)+$TempSon))*150)) -eq 0){300}else{((((($Temp3rd.count)+($Temp4rd.count)+($Temp5th.count)+$TempSon))*150))} $XXLeft = $XXLeft + -$XXTemp $loops++ } elseif($XXLeft -gt 0 -and $loops -ge 0) { $XXTemp = if(((((($Temp3rd.count)+($Temp4rd.count)+($Temp5th.count)+$TempSon))*150)) -eq 0){300}else{((((($Temp3rd.count)+($Temp4rd.count)+($Temp5th.count)+$TempSon))*150))} $XXLeft = $XXLeft + $XXTemp $loops++ } else { $XXTemp = if(((((($Temp3rd.count)+($Temp4rd.count)+($Temp5th.count)+$TempSon))*300)) -eq 0){300}else{((((($Temp3rd.count)+($Temp4rd.count)+($Temp5th.count)+$TempSon))*300))} $XXLeft = $XXLeft + $XXTemp $loops++ } $MgmtHeight1 = if((($RoundSubs.id.count * 90) + 50) -eq 50){80}else{(($RoundSubs.id.count * 90) + 50)} $XXTop = $MgmtHeight + 200 Container2 $XXLeft $XXTop '200' $MgmtHeight1 $2nd $Script:ContID $Script:XmlWriter.WriteStartElement('object') $Script:XmlWriter.WriteAttributeString('label', '') $Script:XmlWriter.WriteAttributeString('ManagementGroup', [string]$2nd) $Script:XmlWriter.WriteAttributeString('id', ($Script:CellID+'-'+($Script:IDNum++))) if($RoundSubs) { icon $Script:IconMgmtGroup '-30' ($MgmtHeight1-15) '50' '50' $Script:ContID2 } else { icon $Script:IconMgmtGroup '75' '27' '50' '50' $Script:ContID2 } $Script:XmlWriter.WriteEndElement() Connect $Script:ContID $Script:ContID2 $TempSon = (($Temp3rd.count)+($Temp4rd.count)+($Temp5th.count)) if($XXLeft -eq 0 -and $loops -lt 0) { $XXLeft = -1 } elseif($XXLeft -lt 0 -and $loops -ge 0) { $XXLeft = 1 } $LocalTop = 50 $LocalLeft = 25 foreach($Sub in $RoundSubs) { $RGs = $Script:ResourceContainers | Where-Object {$_.Type -eq 'microsoft.resources/subscriptions/resourcegroups' -and $_.subscriptionid -eq $sub.subscriptionid} $Script:XmlWriter.WriteStartElement('object') $Script:XmlWriter.WriteAttributeString('label', $sub.name) $Script:XmlWriter.WriteAttributeString('id', ($Script:CellIDRes+'-'+($Script:CelNum++))) Icon $Ret2 $LocalLeft $LocalTop '150' '70' $Script:ContID2 $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteStartElement('object') $Script:XmlWriter.WriteAttributeString('label', '') $RGNum = 1 foreach($RG in $RGs) { $Attr = ('ResourceGroup_'+[string]$RGNum) $Script:XmlWriter.WriteAttributeString($Attr, [string]$RG.Name) $RGNum++ } $Script:XmlWriter.WriteAttributeString('id', ($Script:CellID+'-'+($Script:IDNum++))) icon $Script:IconSubscription ($LocalLeft+140) ($LocalTop+40) '31' '51' $Script:ContID2 $Script:XmlWriter.WriteEndElement() $LocalTop = $LocalTop + 90 } ######################################## 3RD LEVEL ############################################## $3rdLevel = @() foreach($sub3rd in $OrgObjs) { if($sub3rd.properties.managementgroupancestorschain.name[1] -eq $2nd) { $3rdLevel += $sub3rd.properties.managementgroupancestorschain.name[0] } if($sub3rd.properties.managementgroupancestorschain.name[2] -eq $2nd) { $3rdLevel += $sub3rd.properties.managementgroupancestorschain.name[1] } if($sub3rd.properties.managementgroupancestorschain.name[3] -eq $2nd) { $3rdLevel += $sub3rd.properties.managementgroupancestorschain.name[2] } } $3rdLevel = $3rdLevel | Select-Object -Unique $XXXLeft = 0 if($3rdLevel.count % 2 -eq 1 ) { $Align3 = $true $loops3 = -[Math]::ceiling($3rdLevel.count / 2 - 1) } else { $Align3 = $false $loops3 = [Math]::ceiling($3rdLevel.count / 2) - 1 } if($3rdLevel.count -eq 1) { $loops3 = 1 } foreach($3rd in $3rdLevel) { $RoundSubs3 = @() $Temp4rd3 = @() $Temp5th3 = @() foreach($Sub in $OrgObjs) { if($Sub.properties.managementgroupancestorschain.name[0] -eq $3rd) { $RoundSubs3 += $Sub } if($Sub.properties.managementgroupancestorschain.name[1] -eq $3rd) { $Temp4rd3 += $Sub.properties.managementgroupancestorschain.name[0] } if($Sub.properties.managementgroupancestorschain.name[2] -eq $3rd) { $Temp5th3 += $Sub.properties.managementgroupancestorschain.name[0] $Temp4rd3 += $Sub.properties.managementgroupancestorschain.name[1] } } $Temp4rd3 = $Temp4rd3 | Select-Object -Unique $Temp5th3 = $Temp5th3 | Select-Object -Unique if($XXXLeft -eq 0 -and $Align3 -eq $true) { } elseif($XXXLeft -eq 0 -and $Align3 -eq $false) { $XXXLeft = -150 + -((((($Temp4rd3.count)+($Temp5th3.count)))*150)/2) $loops3++ } elseif($Align3 -eq $false -and $loops3 -eq 0) { $XXXLeft = 150 + ((((($Temp4rd3.count)+($Temp5th3.count)))*150)/2) $loops3++ } elseif($loops3 -gt 0 -and $XXXLeft -eq 0) { $XXXLeft = $XXXLeft + ($3rdLevel.count*300)/2 + ((((($Temp4rd3.count)+($Temp5th3.count)))*300)/2) $loops3++ } elseif($XXXLeft -eq 0 -and $loops3 -lt 0) { $XXXTemp = if(((((($Temp4rd3.count)+($Temp5th3.count)))*300)) -eq 0){300}else{((((($Temp4rd3.count)+($Temp5th3.count)))*300))} $XXXLeft = $XXXLeft + -$XXXTemp $loops3++ } elseif($XXXLeft -lt 0 -and $loops3 -lt 0) { $XXXTemp = if(((((($Temp4rd3.count)+($Temp5th3.count)))*300)) -eq 0){300}else{((((($Temp4rd3.count)+($Temp5th3.count)))*300))} $XXXLeft = $XXXLeft + -$XXXTemp $loops3++ } elseif($XXXLeft -eq 1 -and $loops3 -gt 0) { $XXXLeft = 150 + ((((($Temp4rd3.count)+($Temp5th3.count)))*150)) $loops3++ } else { $XXXTemp = if(((((($Temp4rd3.count)+($Temp5th3.count)))*300)) -eq 0){300}else{((((($Temp4rd3.count)+($Temp5th3.count)))*300))} $XXXLeft = $XXXLeft + $XXXTemp $loops3++ } $MgmtHeight2 = if((($RoundSubs3.id.count * 90) + 50) -eq 50){80}else{(($RoundSubs3.id.count * 90) + 50)} $XXXTop = $MgmtHeight1 + 200 Container3 $XXXLeft $XXXTop '200' $MgmtHeight2 $3rd $Script:ContID2 $Script:XmlWriter.WriteStartElement('object') $Script:XmlWriter.WriteAttributeString('label', '') $Script:XmlWriter.WriteAttributeString('ManagementGroup', [string]$3rd) $Script:XmlWriter.WriteAttributeString('id', ($Script:CellID+'-'+($Script:IDNum++))) if($RoundSubs3) { icon $Script:IconMgmtGroup '-30' ($MgmtHeight2-15) '50' '50' $Script:ContID3 } else { icon $Script:IconMgmtGroup '75' '27' '50' '50' $Script:ContID3 } $Script:XmlWriter.WriteEndElement() Connect $Script:ContID2 $Script:ContID3 if($XXXLeft -eq 0 -and $loops3 -lt 0) { $XXXLeft = -1 } elseif($XXXLeft -lt 0 -and $loops3 -ge 0) { $XXXLeft = 1 } $LocalTop = 50 $LocalLeft = 25 foreach($Sub in $RoundSubs3) { $RGs = $Script:ResourceContainers | Where-Object {$_.Type -eq 'microsoft.resources/subscriptions/resourcegroups' -and $_.subscriptionid -eq $sub.subscriptionid} $Script:XmlWriter.WriteStartElement('object') $Script:XmlWriter.WriteAttributeString('label', $sub.name) $Script:XmlWriter.WriteAttributeString('id', ($Script:CellIDRes+'-'+($Script:CelNum++))) Icon $Ret3 $LocalLeft $LocalTop '150' '70' $Script:ContID3 $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteStartElement('object') $Script:XmlWriter.WriteAttributeString('label', '') $RGNum = 1 foreach($RG in $RGs) { $Attr = ('ResourceGroup_'+[string]$RGNum) $Script:XmlWriter.WriteAttributeString($Attr, [string]$RG.Name) $RGNum++ } $Script:XmlWriter.WriteAttributeString('id', ($Script:CellID+'-'+($Script:IDNum++))) icon $Script:IconSubscription ($LocalLeft+140) ($LocalTop+40) '31' '51' $Script:ContID3 $Script:XmlWriter.WriteEndElement() $LocalTop = $LocalTop + 90 } ######################################## 4TH LEVEL ############################################## $4thLevel = @() foreach($sub4th in $OrgObjs) { if($sub4th.properties.managementgroupancestorschain.name[1] -eq $3rd) { $4thLevel += $sub4th.properties.managementgroupancestorschain.name[0] } if($sub4th.properties.managementgroupancestorschain.name[2] -eq $3rd) { $4thLevel += $sub4th.properties.managementgroupancestorschain.name[1] } if($sub4th.properties.managementgroupancestorschain.name[3] -eq $3rd) { $4thLevel += $sub4th.properties.managementgroupancestorschain.name[2] } } $4thLevel = $4thLevel | Select-Object -Unique $XXXXLeft = 0 if($4thLevel.count % 2 -eq 1 ) { $Align4 = $true $loops4 = -[Math]::ceiling($sub4th.count / 2 - 1) } else { $Align4 = $false $loops4 = [Math]::ceiling($sub4th.count / 2) - 1 } if($4thLevel.count -eq 1) { $loops4 = 1 } foreach($4th in $4thLevel) { $RoundSubs4 = @() $Temp5th4 = @() foreach($Sub in $OrgObjs) { if($Sub.properties.managementgroupancestorschain.name[0] -eq $4th) { $RoundSubs4 += $Sub } if($Sub.properties.managementgroupancestorschain.name[1] -eq $4th) { $Temp5th4 += $Sub.properties.managementgroupancestorschain.name[0] } if($Sub.properties.managementgroupancestorschain.name[2] -eq $4th) { $Temp5th4 += $Sub.properties.managementgroupancestorschain.name[0] } } $Temp5th4 = $Temp5th4 | Select-Object -Unique if($XXXXLeft -eq 0 -and $Align4 -eq $true) { } elseif($XXXXLeft -eq 0 -and $Align4 -eq $false) { $XXXXLeft = -150 + -((((($Temp4rd4.count)+($Temp5th4.count)))*150)/2) $loops4++ } elseif($Align4 -eq $false -and $loops4 -eq 0) { $XXXXLeft = 150 + ((((($Temp4rd4.count)+($Temp5th4.count)))*150)/2) $loops4++ } elseif($loops4 -gt 0 -and $XXXXLeft -eq 0) { $XXXXLeft = $XXXXLeft + ($4thLevel.count*300)/2 + ((((($Temp5th4.count)))*300)/2) $loops4++ } elseif($XXXXLeft -eq 0 -and $loops4 -lt 0) { $XXXXTemp = if(((((($Temp5th4.count)))*300)) -eq 0){300}else{((((($Temp5th4.count)))*300))} $XXXXLeft = $XXXXLeft + -$XXXXTemp $loops4++ } elseif($XXXXLeft -lt 0 -and $loops4 -lt 0) { $XXXXTemp = if(((((($Temp5th4.count)))*300)) -eq 0){300}else{((((($Temp5th4.count)))*300))} $XXXXLeft = $XXXXLeft + -$XXXXTemp $loops4++ } elseif($XXXXLeft -eq 1 -and $loops4 -gt 0) { $XXXXLeft = 150 + ((((($Temp5th4.count)))*150)) $loops4++ } else { $XXXXTemp = if(((((($Temp5th4.count)))*300)) -eq 0){300}else{((((($Temp5th4.count)))*300))} $XXXXLeft = $XXXXLeft + $XXXXTemp $loops4++ } $MgmtHeight3 = if((($RoundSubs4.id.count * 90) + 50) -eq 50){80}else{(($RoundSubs4.id.count * 90) + 50)} $XXXXTop = $MgmtHeight2 + 200 Container4 $XXXXLeft $XXXXTop '200' $MgmtHeight3 $4th $Script:ContID3 $Script:XmlWriter.WriteStartElement('object') $Script:XmlWriter.WriteAttributeString('label', '') $Script:XmlWriter.WriteAttributeString('ManagementGroup', [string]$4th) $Script:XmlWriter.WriteAttributeString('id', ($Script:CellID+'-'+($Script:IDNum++))) if($RoundSubs4) { icon $Script:IconMgmtGroup '-30' ($MgmtHeight3-15) '50' '50' $Script:ContID4 } else { icon $Script:IconMgmtGroup '75' '27' '50' '50' $Script:ContID4 } $Script:XmlWriter.WriteEndElement() Connect $Script:ContID3 $Script:ContID4 if($XXXXLeft -eq 0 -and $loops4 -lt 0) { $XXXXLeft = -1 } elseif($XXXXLeft -lt 0 -and $loops4 -ge 0) { $XXXXLeft = 1 } $LocalTop = 50 $LocalLeft = 25 foreach($Sub in $RoundSubs4) { $RGs = $Script:ResourceContainers | Where-Object {$_.Type -eq 'microsoft.resources/subscriptions/resourcegroups' -and $_.subscriptionid -eq $sub.subscriptionid} $Script:XmlWriter.WriteStartElement('object') $Script:XmlWriter.WriteAttributeString('label', $sub.name) $Script:XmlWriter.WriteAttributeString('id', ($Script:CellIDRes+'-'+($Script:CelNum++))) Icon $Ret4 $LocalLeft $LocalTop '150' '70' $Script:ContID4 $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteStartElement('object') $Script:XmlWriter.WriteAttributeString('label', '') $RGNum = 1 foreach($RG in $RGs) { $Attr = ('ResourceGroup_'+[string]$RGNum) $Script:XmlWriter.WriteAttributeString($Attr, [string]$RG.Name) $RGNum++ } $Script:XmlWriter.WriteAttributeString('id', ($Script:CellID+'-'+($Script:IDNum++))) icon $Script:IconSubscription ($LocalLeft+140) ($LocalTop+40) '31' '51' $Script:ContID4 $Script:XmlWriter.WriteEndElement() $LocalTop = $LocalTop + 90 } } } } } } Stencils $OrgFile = ($DiagramCache+'Organization.xml') $Script:etag = -join ((65..90) + (97..122) | Get-Random -Count 20 | ForEach-Object {[char]$_}) $Script:DiagID = -join ((65..90) + (97..122) | Get-Random -Count 20 | ForEach-Object {[char]$_}) $Script:CellID = -join ((65..90) + (97..122) | Get-Random -Count 20 | ForEach-Object {[char]$_}) $Script:IDNum = 0 $Script:CelNum = 0 $Script:XmlWriter = New-Object System.XMl.XmlTextWriter($OrgFile,$Null) $Script:XmlWriter.Formatting = 'Indented' $Script:XmlWriter.Indentation = 2 $Script:XmlWriter.WriteStartDocument() $Script:XmlWriter.WriteStartElement('mxfile') $Script:XmlWriter.WriteAttributeString('host', 'Electron') $Script:XmlWriter.WriteAttributeString('modified', '2021-10-01T21:45:40.561Z') $Script:XmlWriter.WriteAttributeString('agent', '5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/15.4.0 Chrome/91.0.4472.164 Electron/13.5.0 Safari/537.36') $Script:XmlWriter.WriteAttributeString('etag', $etag) $Script:XmlWriter.WriteAttributeString('version', '15.4.0') $Script:XmlWriter.WriteAttributeString('type', 'device') $Script:XmlWriter.WriteStartElement('diagram') $Script:XmlWriter.WriteAttributeString('id', $DiagID) $Script:XmlWriter.WriteAttributeString('name', 'Organization') $Script:XmlWriter.WriteStartElement('mxGraphModel') $Script:XmlWriter.WriteAttributeString('dx', "1326") $Script:XmlWriter.WriteAttributeString('dy', "798") $Script:XmlWriter.WriteAttributeString('grid', "1") $Script:XmlWriter.WriteAttributeString('gridSize', "10") $Script:XmlWriter.WriteAttributeString('guides', "1") $Script:XmlWriter.WriteAttributeString('tooltips', "1") $Script:XmlWriter.WriteAttributeString('connect', "1") $Script:XmlWriter.WriteAttributeString('arrows', "1") $Script:XmlWriter.WriteAttributeString('fold', "1") $Script:XmlWriter.WriteAttributeString('page', "1") $Script:XmlWriter.WriteAttributeString('pageScale', "1") $Script:XmlWriter.WriteAttributeString('pageWidth', "850") $Script:XmlWriter.WriteAttributeString('pageHeight', "1100") $Script:XmlWriter.WriteAttributeString('math', "0") $Script:XmlWriter.WriteAttributeString('shadow', "0") $Script:XmlWriter.WriteStartElement('root') $Script:XmlWriter.WriteStartElement('mxCell') $Script:XmlWriter.WriteAttributeString('id', "0") $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteStartElement('mxCell') $Script:XmlWriter.WriteAttributeString('id', "1") $Script:XmlWriter.WriteAttributeString('parent', "0") $Script:XmlWriter.WriteEndElement() Org $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteEndElement() $Script:XmlWriter.WriteEndDocument() $Script:XmlWriter.Flush() $Script:XmlWriter.Close() } -ArgumentList $ResourceContainers,$DiagramCache } |