Src/Public/New-Diagrammer.ps1
function New-Diagrammer { <# .SYNOPSIS Diagram the configuration of IT infrastructure in PDF/SVG/DOT/PNG formats using PSGraph and Graphviz. .DESCRIPTION Diagram the configuration of IT infrastructure in PDF/SVG/DOT/PNG formats using PSGraph and Graphviz. .PARAMETER Format Specifies the output format of the diagram. The supported output formats are PDF, PNG, DOT & SVG. Multiple output formats may be specified, separated by a comma. .PARAMETER Direction Set the direction in which resource are plotted on the visualization The supported directions are: 'top-to-bottom', 'left-to-right' By default, direction will be set to top-to-bottom. .PARAMETER NodeSeparation Controls Node separation ratio in visualization By default, NodeSeparation will be set to .60. .PARAMETER SectionSeparation Controls Section (Subgraph) separation ratio in visualization By default, NodeSeparation will be set to .75. .PARAMETER EdgeType Controls how edges lines appear in visualization The supported edge type are: 'polyline', 'curved', 'ortho', 'line', 'spline' By default, EdgeType will be set to spline. References: https://graphviz.org/docs/attrs/splines/ .PARAMETER OutputFolderPath Specifies the folder path to save the diagram. .PARAMETER Filename Specifies a filename for the diagram. .PARAMETER EnableEdgeDebug Control to enable edge debugging ( Dummy Edge and Node lines ). .PARAMETER EnableSubGraphDebug Control to enable subgraph debugging ( Subgraph Lines ). .PARAMETER EnableErrorDebug Control to enable error debugging. .PARAMETER AuthorName Allow to set footer signature Author Name. .PARAMETER CompanyName Allow to set footer signature Company Name. .PARAMETER Logo Allow to change the Main logo to a custom one. Image should be 400px x 100px or less in size. .PARAMETER SignatureLogo Allow to change the signature logo to a custom one. Image should be 120px x 130px or less in size. .PARAMETER Signature Allow the creation of footer signature. AuthorName and CompanyName must be set to use this property. .NOTES Version: 0.3.0 Author(s): Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux Credits: Kevin Marquette (@KevinMarquette) - PSGraph module Credits: Prateek Singh (@PrateekKumarSingh) - AzViz module .LINK https://github.com/rebelinux/ https://github.com/KevinMarquette/PSGraph https://github.com/PrateekKumarSingh/AzViz #> [Diagnostics.CodeAnalysis.SuppressMessage( 'PSUseShouldProcessForStateChangingFunctions', '' )] [CmdletBinding( PositionalBinding = $false, DefaultParameterSetName = 'Credential' )] param ( [Parameter( Position = 4, Mandatory = $false, HelpMessage = 'Please provide the diagram output format' )] [ValidateNotNullOrEmpty()] [ValidateSet('pdf', 'svg', 'png', 'dot', 'base64')] [Array] $Format = 'pdf', [Parameter( Mandatory = $false, HelpMessage = 'Direction in which resource are plotted on the visualization' )] [ValidateSet('left-to-right', 'top-to-bottom')] [string] $Direction = 'top-to-bottom', [Parameter( Mandatory = $false, HelpMessage = 'Please provide the path to the diagram output file' )] [ValidateScript( { if (Test-Path -Path $_) { $true } else { throw "Path $_ not found!" } })] [string] $OutputFolderPath = [System.IO.Path]::GetTempPath(), [Parameter( Mandatory = $false, HelpMessage = 'Please provide the path to the custom logo used for Signature' )] [ValidateScript( { if (Test-Path -Path $_) { $true } else { throw "File $_ not found!" } })] [string] $SignatureLogo, [Parameter( Mandatory = $false, HelpMessage = 'Please provide the path to the custom logo' )] [ValidateScript( { if (Test-Path -Path $_) { $true } else { throw "File $_ not found!" } })] [string] $Logo, [Parameter( Mandatory = $false, HelpMessage = 'Specify the diagram output file name path' )] [ValidateNotNullOrEmpty()] [ValidateScript({ if ($Format.count -lt 2) { $true } else { throw "Format value must be unique if Filename is especified." } if (-Not $_.EndsWith($Format)) { throw "The file specified in the path argument must be of type $Format" } return $true })] [String] $Filename, [Parameter( Mandatory = $false, HelpMessage = 'Controls how edges lines appear in visualization' )] [ValidateSet('polyline', 'curved', 'ortho', 'line', 'spline')] [string] $EdgeType = 'line', [Parameter( Mandatory = $false, HelpMessage = 'Controls Node separation ratio in visualization' )] [ValidateSet(0, 1, 2, 3)] [string] $NodeSeparation = .60, [Parameter( Mandatory = $false, HelpMessage = 'Controls Section (Subgraph) separation ratio in visualization' )] [ValidateSet(0, 1, 2, 3)] [string] $SectionSeparation = .75, [Parameter( Mandatory = $false, HelpMessage = 'Allow to enable edge debugging ( Dummy Edge and Node lines)' )] [Switch] $EnableEdgeDebug = $false, [Parameter( Mandatory = $false, HelpMessage = 'Allow to enable subgraph debugging ( Subgraph Lines )' )] [Switch] $EnableSubGraphDebug = $false, [Parameter( Mandatory = $false, HelpMessage = 'Allow to enable error debugging' )] [Switch] $EnableErrorDebug = $false, [Parameter( Mandatory = $false, HelpMessage = 'Allow to set footer signature Author Name' )] [string] $AuthorName, [Parameter( Mandatory = $false, HelpMessage = 'Allow to set footer signature Company Name' )] [string] $CompanyName, [Parameter( Mandatory = $false, HelpMessage = 'Allow the creation of footer signature' )] [Switch] $Signature = $false, [Parameter( Mandatory = $true, HelpMessage = 'Set the Main Label used at the top of the diagram' )] [string] $MainDiagramLabel ) begin { # Variable translating Icon to Image Path ($IconPath) $script:Images = @{ "Main_Logo" = "Diagrammer.png" "Logo_Footer" = "Diagrammer_footer.png" } if (($Format -ne "base64") -and !(Test-Path $OutputFolderPath)) { Write-Error "OutputFolderPath '$OutputFolderPath' is not a valid folder path." break } if ($Signature -and (([string]::IsNullOrEmpty($AuthorName)) -or ([string]::IsNullOrEmpty($CompanyName)))) { throw "New-Diagrammer: AuthorName and CompanyName must be defined if the Signature option is specified" } $IconDebug = $false if ($EnableEdgeDebug) { $EdgeDebug = @{style = 'filled'; color = 'red' } $IconDebug = $true } else { $EdgeDebug = @{style = 'invis'; color = 'red' } } if ($EnableSubGraphDebug) { $SubGraphDebug = @{style = 'dashed'; color = 'red' } $NodeDebug = @{color = 'black'; style = 'red'; shape = 'plain' } $NodeDebugEdge = @{color = 'black'; style = 'red'; shape = 'plain' } $IconDebug = $true } else { $SubGraphDebug = @{style = 'invis'; color = 'gray' } $NodeDebug = @{color = 'transparent'; style = 'transparent'; shape = 'point' } $NodeDebugEdge = @{color = 'transparent'; style = 'transparent'; shape = 'none' } } $RootPath = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent $IconPath = Join-Path $RootPath 'icons' $Dir = switch ($Direction) { 'top-to-bottom' { 'TB' } 'left-to-right' { 'LR' } } # Validate Custom logo if ($Logo) { $CustomLogo = Test-Logo -LogoPath (Get-ChildItem -Path $Logo).FullName -IconPath $IconPath -ImagesObj $Images } else { $CustomLogo = "Main_Logo" } # Validate Custom Signature Logo if ($SignatureLogo) { $CustomSignatureLogo = Test-Logo -LogoPath (Get-ChildItem -Path $SignatureLogo).FullName -IconPath $IconPath -ImagesObj $Images } $MainGraphAttributes = @{ pad = 1 rankdir = $Dir overlap = 'false' splines = $EdgeType penwidth = 1.5 fontname = "Segoe Ui Black" fontcolor = '#005f4b' fontsize = 32 style = "dashed" labelloc = 't' imagepath = $IconPath nodesep = $NodeSeparation ranksep = $SectionSeparation } } process { # Graph default atrributes $script:Graph = Graph -Name Root -Attributes $MainGraphAttributes { # Node default theme Node @{ label = '' shape = 'none' labelloc = 't' style = 'filled' fillColor = '#71797E' fontsize = 14; imagescale = $true } # Edge default theme Edge @{ style = 'dashed' dir = 'both' arrowtail = 'dot' color = '#71797E' penwidth = 3 arrowsize = 1 } # Signature Section if ($Signature) { Write-PScriboMessage "Generating diagram signature" if ($CustomSignatureLogo) { $Signature = (Get-DiaHTMLTable -ImagesObj $Images -Rows "Author: $($AuthorName)", "Company: $($CompanyName)" -TableBorder 2 -CellBorder 0 -Align 'left' -Logo $CustomSignatureLogo -IconDebug $IconDebug) } else { $Signature = (Get-DiaHTMLTable -ImagesObj $Images -Rows "Author: $($AuthorName)", "Company: $($CompanyName)" -TableBorder 2 -CellBorder 0 -Align 'left' -Logo "Logo_Footer" -IconDebug $IconDebug) } } else { Write-PScriboMessage "No diagram signature specified" $Signature = " " } #---------------------------------------------------------------------------------------------# # Graphviz Clusters (SubGraph) Section # # SubGraph can be use to bungle the Nodes together like a single entity # # SubGraph allow you to have a graph within a graph # # PSgraph: https://psgraph.readthedocs.io/en/latest/Command-SubGraph/ # # Graphviz: https://graphviz.org/docs/attrs/cluster/ # #---------------------------------------------------------------------------------------------# # Subgraph OUTERDRAWBOARD1 used to draw the footer signature (bottom-right corner) SubGraph OUTERDRAWBOARD1 -Attributes @{Label = $Signature; fontsize = 24; penwidth = 1.5; labelloc = 'b'; labeljust = "r"; style = $SubGraphDebug.style; color = $SubGraphDebug.color } { # Subgraph MainGraph used to draw the main drawboard. SubGraph MainGraph -Attributes @{Label = (Get-DiaHTMLLabel -ImagesObj $Images -Label $MainDiagramLabel -IconType $CustomLogo -IconDebug $IconDebug -IconWidth 250 -IconHeight 80); fontsize = 24; penwidth = 0; labelloc = 't'; labeljust = "c" } { } } } } end { #Export the Diagram Export-Diagrammer -GraphObj ($Graph | Select-String -Pattern '"([A-Z])\w+"\s\[label="";style="invis";shape="point";]' -NotMatch) -ErrorDebug $EnableErrorDebug -Format $Format -Filename $Filename -OutputFolderPath $OutputFolderPath -WaterMarkText $Options.DiagramWaterMark -WaterMarkColor "Green" } } |