Git Product home page Git Product logo

psgraph's Introduction

Build status Documentation Status

PSGraph

PSGraph is a helper module implemented as a DSL (Domain Specific Language) for generating GraphViz graphs. The goal is to make it easier to generate graphs using Powershell. The DSL adds these commands that are explained below.

What is GraphViz?

Graphviz is open source graph visualization software. Graph visualization is a way of representing structural information as diagrams of abstract graphs and networks. It has important applications in networking, bioinformatics,  software engineering, database and web design, machine learning, and in visual interfaces for other technical domains. 

Project status?

Beta release. The core module work and documentation is fleshed out. The simple features are implemented but there are other features of the DOT language that I have not used much myself. The command names and arguments of the existing commands should be stable now. As always, more testing still needs to be done.

GraphViz and the Dot format basics

The nice thing about GraphViz is that you can define nodes and edges with a simple text file in the Dot format. The GraphViz engine handles the layout, edge routing, rendering and creates an image for you.

Here is a sample Dot file.

digraph g {
    "Start"->"Middle"
    "Middle"->"End"
}

This will produce a graph with 3 nodes with the names Start, Middle and End. There will be an edge line connecting them in order. Go checkout the GraphViz Gallery to see some examples of what you can do with it.

How PSGraph can help

we can create those Dot files with PSGraph in Powershell. Here is that same graph as above.

digraph g {
    edge Start Middle
    edge Middle End
}

Here is a second way to approach it now.

$objects = @("Start","Middle","End")
digraph g {
    edge $objects
}

The real value here is that I can specify a collection to process. This allows the graph to be data driven.

PSGraph Commands

I tried to keep a syntax that was similar to GraphViz but offer the flexibility of Powershell. If you have worked with GraphViz before, then you should feel right at home.

Graph or digraph

This is the container that holds graph elements. Every valid GraphViz graph has one. digraph is just an alias of graph so I am going to use the shorter graph for the rest of the readme.

graph g {        
}

Edge

This defines an edge or connection between nodes. This command accepts a list of strings or an array of strings. It will connect them all in sequence. This should be placed inside a graph or subgraph. -From and -To parameters are available if you want more verbosity.

graph g {
    edge -From first -To Second
    edge one two three four
    edge (1..5)
}

If you supply two arrays, it will cross multiply them. So each item on the left with have a path to each item on the right.

graph g {
    edge (1,3) (2,4)
}

Because this is Powershell, we can mix in normal commands. Take this example.

$folders = Get-ChildItem -Directory -Recurse
graph g {
    $folders | %{edge $_.Name $_.Parent} 
}

I also support edge attributes that are defined in the DOT specification by using a hashtable.

graph g { edge "Point One" "Point Two" @{label='A line'} }

Node

The Node command allows you to introduce a node on the graph before an edge is created. This is used to give specific nodes different attributes or to place them in subgraphs. The node command will also accept an array of values and a hashtable of attributes.

graph g {
    node start @{shape='house'}
    node end @{shape='invhouse'}
    edge start,middle,end
}

This is the exact Dot output generated those node commands.

digraph g {

    "start" [shape="house"]
    "end" [shape="invhouse"]
    "start"->"middle" 
    "middle"->"end" 
}

Rank

The rank command will place the specified nodes at the same level in the chart. The layout can get a bit wild sometime and gives you some control.

graph g {
    rank 2 4 6 8
    rank 1 3 5 7
    edge (1..8)
}

SubGraph

This lets you box of and cluster nodes together in the graph. These can be nested. The catch is that you need to number them starting at 0. Attributes are supported with the -Attributes parameter.

graph g {
    subgraph 0 -Attributes @{label='DMZ'} {
        node Web1,Web2
    }
    edge web1 database
    edge web1 database
}

More complex example

We can pull that all together and generate quite the data driven driven diagram.

$webServers = 'Web1','Web2','web3'
$apiServers = 'api1','api2'
$databaseServers = 'db1'

graph site1 {
    # External/DMZ nodes
    subgraph 0 -Attributes @{label='DMZ'} {
        node 'loadbalancer' @{shape='house'}
        rank $webServers
        node $webServers @{shape='rect'}
        edge 'loadbalancer' $webServers
    }

    subgraph 1 -Attributes @{label='Internal'} {
        # Internal API servers
        rank $apiServers
        node $apiServers   
        edge $webServers -to $apiServers
    
        # Database Servers
        rank $databaseServers
        node $databaseServers @{shape='octagon'}
        edge $apiServers -to $databaseServers
    }    
}

Installing PSGraph

Make sure you are running Powershell 5.0 (WMF 5.0). I don't know that it is a hard requirement at the moment but I plan on using 5.0 features.

# Install GraphViz from the Chocolatey repo
Register-PackageSource -Name Chocolatey -ProviderName Chocolatey -Location http://chocolatey.org/api/v2/
Find-Package graphviz | Install-Package -ForceBootstrap

# Install PSGraph from the Powershell Gallery
Find-Module PSGraph | Install-Module

# Import Module
Import-Module PSGraph

For OSX, you can use brew to install graphviz.

brew install graphviz

Generating a graph image

I am still working out the workflow for this, but for now just do this.

# Create graph in variable
$dot = graph g {
    edge hello world
}

# Save to file
Set-Content -Path $env:temp\hello.vz -Value $dot

Export-PSGraph -Source $env:temp\hello.vz -Destination $env:temp\hello.png -ShowGraph

The export can be done more in line if needed.

graph g {
    edge hello world
} | Export-PSGraph -ShowGraph

psgraph's People

Contributors

eklipzgit avatar kevinmarquette avatar kyahx avatar scrthq avatar stephanevg avatar tigerfansga avatar victorvogelpoel avatar zloeber avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

psgraph's Issues

Struc syntax not recognized

Not sure if this is an issue or I was just doing it wrong, but I was not able to generate a structure using this module, I ended up creating a "dummy" edge and replacing that with the structure syntax after creating the graph object.

Great Project, One Documentation Nuance

I really like this module, thanks for sharing with the community. One small detail which may be worth throwing up on the main readme.md file is that this is really a DSL powershell wrapper for graphviz (which I suppose is a DSL of its own). As you have constructed it like a DSL it is substantially easier to learn and use than a simple PowerShell module.

In any case, great work, thanks again!

Export-PSgraph is throwing errors when there is no source

This simple example is throwing errors on a resolve-path

graph g {
    edge -From Dad -to Alex,Charis
} | Export-PSGraph -ShowGraph

Resolve-Path : Cannot bind argument to parameter 'Path' because it is an empty string.
At C:\Users\kevma\Documents\WindowsPowerShell\Modules\psgraph\0.4.1.95\public\Export-PSGraph.ps1:102 char:44

  •         $fileList = Resolve-Path -Path $Source -ea 0
    

Get-Indent error

I'm getting the following error when creating a graph:

Specified argument was out of the range of valid values.
Parameter name: times
At C:\Program Files\WindowsPowerShell\Modules\psgraph\0.1.2\private\Get-Indent.ps1:8 char:9

  •     (" " * 4 * $depth )
    
  •     ~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : OperationStopped: (:) [], ArgumentOutOfRangeException
    • FullyQualifiedErrorId : System.ArgumentOutOfRangeException

I suspect that the indenting is getting to big because I am nesting graph creations and them plugging the all together afterwards to force positions.

C4 DSL

Your "Record" addition sparked an idea. Adding more DSL-thingies

I am already using PSGraph to plot a certain stucture in a system I am administrating, The system is the authority, PSGraph visualizes it.

I am reading up on Simon Brown's C4 Architecture modelling: define architecture in code. Its Java implementation is able to export the definition to DOT, but the C# version does not. Enter PowerShell and PSGraph...
How about creating a DSL for C4 in PSGraph (perhaps as an extension)?

Add the default names to the LayoutEngine param for Export-PSGraph

I use friendly names for the layout engines but someone consulting the GraphViz documents will not know what engine they are using. I am including both the friendly names and the original names.

I chose to leave the friendly names capital case and the original names lowercase.

Graph name should be optional

I know this was added to be more like the dot language, but I think the graph name should be optional because I don't really know where it gets used (if at all).

graph {
    node test
}

Tuning record a bit more

Hi @KevinMarquette

This would be a feature request (I guess)

I am using your module to generate records:

For example, this code:


$Properties1 = @("one", "two", "three")
$Properties2 = @("4", "5", "5")

$g = Graph {

    Record -Name Woop {
            
        #Properties
    
        if ($Properties) {
    
            Foreach ($pro in $Properties1) {
               
               
                Row -label "$pro"  -Name "Row_$($pro)"
               
    
            }
            Row "-----Seperator-----"  -Name "Row_Separator"

            Foreach ($pro in $Properties2) {
               
               
                Row -label "$pro"  -Name "Row_$($pro)"
               
    
            }
        }
    }
}

$g | Show-PSGraph

generates this record:

image

Request

Perhaps this is already possible, and I simply don't know of it, but I would love to be able to do the following things:

  1. Get rid of the lines between each row
  2. be able to create a 'real' seperator in the record, to seperate a bit 'nicer' one,two,three from 4,5,6

for 1) Perhaps this could be a new -HideLines / -NoLines / -HideRowLines switch on the record cmdlet (Or something close to that)
for 2) I could imagine that a new cmdlet, RowSeparator could be usefull here, which could be something like this:

RowSeperator -LineType [full,dashed,bullets,etc...] -Bold -Italic -Fill

Please let me know if this would be possible.

the Dot spec is case sensitive: shape names could be auto corrected

#35
We should be auto correcting the shape names to the correct case. Or validated to indicate the shape is not usable without the correct case.

Currently we just pass the txt to the dot processor. We don't currently validate much of the output to the actual specification to keep the implementation loosely bound. But there are some common properties that are defined in the spec with all possible values. We could be going more to validate and auto-correct.

Question: 'Records positioning'

Hi, I have the following case, were I have a lot of 'records'. As you can see on the example here below, they keep beeing set one next to each other.

image

Is it somehow possible to say, like after 3 records, put the next one underneath instead of on the right?

Thanks in advance for your Answer

Parameter Attributes on edge cmdlet doesn't work in complex scenario

Hi Kevin,

As discussed on Slack, find here some more details on the problem I am facing:

I am using PSClassUtils in order to create UML diagrams using PSGraph.

I am trying to set the arrow color of my edges from black (default) to white (none) in my diagrams.

I use the following function to actually genere the Graphviz code --> https://github.com/Stephanevg/PSClassUtils/blob/master/PsClassUtils/Functions/Private/Out-CUPSGraph.ps1

(The Edge are actually created at line 174)

edge -From $Child -To $Parent

I thought the change would be as simple as this:

edge -From $Child -To $Parent -Attributes @{arrowhead = "empty"}

or this

edge -From $Child -To $Parent -LiteralAttribute "[arrowhead="empty";]" 

But in both cases, the 'edge' section of the end of the graph, has never the corresponding graphviz data

I have tried using a complex, and more simple example, but in both cases, the data is simply not added:

Current behaviour

I use the code, to generate edges in my diagram:

#Line 174 from Out-CUPSGraph private function of PsClassUtils
edge -From $Child -To $Parent -Attributes @{arrowhead = "empty"}

but it generates:

Graphvizcode


digraph g {
    compound="true";
    subgraph cluster4867be98f6dd {
        label="Inheritance.ps1";
        "4867be98f6dd" [label="";style="invis";shape="point";]
        "Woop" [label=<<TABLE CELLBORDER="1" BORDER="0" CELLSPACING="0"><TR><TD bgcolor="black" align="center"><font color="white"><B>Woop</B></font></TD></TR><TR><TD PORT="Row_String" ALIGN="LEFT">+ [String] $String</TD></TR><TR><TD PORT="Row_number" ALIGN="LEFT">+ [int] $number</TD></TR><TR><TD PORT="Row_Separator_Constructors" ALIGN="LEFT">-----Constructors-----</TD></TR><TR><TD PORT="Row_Woop" ALIGN="LEFT"> Woop([String]$String,[int]$Number)</TD></TR><TR><TD PORT="Row_Separator_Methods" ALIGN="LEFT">-----Methods-----</TD></TR><TR><TD PORT="Row_DoSomething" ALIGN="LEFT">+[String] DoSomething()</TD></TR></TABLE>>;fillcolor="white";shape="none";style="filled";penwidth="1";fontname="Courier New";]
        "Wap" [label=<<TABLE CELLBORDER="1" BORDER="0" CELLSPACING="0"><TR><TD bgcolor="black" align="center"><font color="white"><B>Wap</B></font></TD></TR><TR><TD PORT="Row_prop3" ALIGN="LEFT">+ [String] $prop3</TD></TR><TR><TD PORT="Row_Separator_Constructors" ALIGN="LEFT">-----Constructors-----</TD></TR><TR><TD PORT="Row_Separator_Methods" ALIGN="LEFT">-----Methods-----</TD></TR><TR><TD PORT="Row_DoChildthing" ALIGN="LEFT">+ DoChildthing()</TD></TR></TABLE>>;fillcolor="white";shape="none";style="filled";penwidth="1";fontname="Courier New";]
        "Wep" [label=<<TABLE CELLBORDER="1" BORDER="0" CELLSPACING="0"><TR><TD bgcolor="black" align="center"><font color="white"><B>Wep</B></font></TD></TR><TR><TD PORT="Row_prop4" ALIGN="LEFT">+ [String] $prop4</TD></TR><TR><TD PORT="Row_Separator_Constructors" ALIGN="LEFT">-----Constructors-----</TD></TR><TR><TD PORT="Row_Separator_Methods" ALIGN="LEFT">-----Methods-----</TD></TR><TR><TD PORT="Row_DoOtherChildThing" ALIGN="LEFT">+ DoOtherChildThing()</TD></TR></TABLE>>;fillcolor="white";shape="none";style="filled";penwidth="1";fontname="Courier New";]
    }

    "Woop"->"Wap" 
    "Woop"->"Wep" 
}

Image

image

Expected Bahaviour

This is what I would expect to be generated

digraph g {
    compound="true";
    subgraph cluster4867be98f6dd {
        label="Inheritance.ps1";
        "4867be98f6dd" [label="";style="invis";shape="point";]
        "Woop" [label=<<TABLE CELLBORDER="1" BORDER="0" CELLSPACING="0"><TR><TD bgcolor="black" align="center"><font color="white"><B>Woop</B></font></TD></TR><TR><TD PORT="Row_String" ALIGN="LEFT">+ [String] $String</TD></TR><TR><TD PORT="Row_number" ALIGN="LEFT">+ [int] $number</TD></TR><TR><TD PORT="Row_Separator_Constructors" ALIGN="LEFT">-----Constructors-----</TD></TR><TR><TD PORT="Row_Woop" ALIGN="LEFT"> Woop([String]$String,[int]$Number)</TD></TR><TR><TD PORT="Row_Separator_Methods" ALIGN="LEFT">-----Methods-----</TD></TR><TR><TD PORT="Row_DoSomething" ALIGN="LEFT">+[String] DoSomething()</TD></TR></TABLE>>;fillcolor="white";shape="none";style="filled";penwidth="1";fontname="Courier New";]
        "Wap" [label=<<TABLE CELLBORDER="1" BORDER="0" CELLSPACING="0"><TR><TD bgcolor="black" align="center"><font color="white"><B>Wap</B></font></TD></TR><TR><TD PORT="Row_prop3" ALIGN="LEFT">+ [String] $prop3</TD></TR><TR><TD PORT="Row_Separator_Constructors" ALIGN="LEFT">-----Constructors-----</TD></TR><TR><TD PORT="Row_Separator_Methods" ALIGN="LEFT">-----Methods-----</TD></TR><TR><TD PORT="Row_DoChildthing" ALIGN="LEFT">+ DoChildthing()</TD></TR></TABLE>>;fillcolor="white";shape="none";style="filled";penwidth="1";fontname="Courier New";]
        "Wep" [label=<<TABLE CELLBORDER="1" BORDER="0" CELLSPACING="0"><TR><TD bgcolor="black" align="center"><font color="white"><B>Wep</B></font></TD></TR><TR><TD PORT="Row_prop4" ALIGN="LEFT">+ [String] $prop4</TD></TR><TR><TD PORT="Row_Separator_Constructors" ALIGN="LEFT">-----Constructors-----</TD></TR><TR><TD PORT="Row_Separator_Methods" ALIGN="LEFT">-----Methods-----</TD></TR><TR><TD PORT="Row_DoOtherChildThing" ALIGN="LEFT">+ DoOtherChildThing()</TD></TR></TABLE>>;fillcolor="white";shape="none";style="filled";penwidth="1";fontname="Courier New";]
    }

    "Woop"->"Wap" [arrowhead="empty";]
    "Woop"->"Wep" [arrowhead="empty";]
}

Image

image

Reproduction of the problem

This is how you can reproduce the example:

Download PsClassUtils Install-Module PsClassUtils

Change line 174 of Out-CUPasGraph (located $ModulesFolder\PSClassUtils\Functions\Private\Out-CUPSGraph.ps1)

from

edge -From $Child -To $Parent

to

edge -From $Child -To $Parent -Attributes @{arrowhead = "empty"}

or

edge -From $Child -To $Parent -LiteralAttribute "[arrowhead="empty";]" 

open ps prompt as admin, and type the following:

Write-CUClassDiagram -Path $ClassWithInheritance -Show -Passthru

(-Passthru will output the Graphviz code generated)
If you need a ps1 file with inheritance, check in the example folder: $ModulesFolder\PSClassUtils\Examples\02\Inheritance.ps1

Don't hesitate to shoot me a message on slack, if you want me to test something.

Santé!
#Stéphane

Install-GraphViz fails: No package found.

Output of Install-GraphViz

PS C:\WINDOWS\system32> Install-GraphViz
Find-Package : No match was found for the specified search criteria and package name 'graphviz'. Try Get-PackageSource to see all available registered package sources.
At C:\Program Files\WindowsPowerShell\Modules\PSGraph\0.4.1.114\public\Install-GraphViz.ps1:18 char:9

Output of Get-PackageSource:

PS C:\WINDOWS\system32> Get-PackageSource

Name ProviderName IsTrusted Location


nuget.org NuGet False https://api.nuget.org/v3/index.json
PSGallery PowerShellGet False https://www.powershellgallery.com/api/v2/

Output of $PSVersionTable:

PS C:\WINDOWS\system32> $PSVersionTable

Name Value


PSVersion 5.1.14393.693
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.14393.693
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1

Enable support for edges to and from subgraphs

You cannot draw edges to or from a graph directly in the dot engine. But you can draw edges from one node to another and have it stop at the edge of the subgraph. This gives the appearance of a edge to a subgraph.

Work should be done to make this simpler for the end user.

I am considering creating an invisible node in the subgraph that has the name that the user gives to the subgraph. So when the user does what is natural, they almost get the correct result.

SubGraph source {
    Node a
}
Node b
Edge -From source -To b

I don't know that I can get it that simple, but that is the target syntax.

To make this happen, I will need to set a default value in the parent graph attributes and also inject additional info into the edge attributes when a subgraph is involved. That last one will be tricky because the Edge command has no knolwedge of the outer graph or other elements at this time.

Version miss match gallery / master branch?

I think there is also a problem on the versions between the one available on the gallery, and the one you have on your master branch.

I had the following error: #85

The fix had been implemented and merged in this PR --> #78 (the PSD1 indicates version 2.1.30)

The one I downloaded from the gallery using Install-Module Psgraph is version 2.1.33 (Which I couldn't find in any of your psd1 on any of your branches).

It was actually missing a part of that fix:

it has in Export-PSGraph:

string[]]
        $GraphVizPath = (
            'C:\Program Files\NuGet\Packages\Graphviz*\dot.exe',
            'C:\program files*\GraphViz*\bin\dot.exe',
            '/usr/local/bin/dot'
        ),

instead of:

string[]]
        $GraphVizPath = (
            'C:\Program Files\NuGet\Packages\Graphviz*\dot.exe',
            'C:\program files*\GraphViz*\bin\dot.exe',
            '/usr/local/bin/dot',
            '/usr/bin/dot'
        ),

which caused me a few issues.

I wanted to apply the fix my self, and PR it, but, It seems already been fixed on your master branch, although on the one I download, it is not the case (and is a higher version then the one on github)

Sequential edges require parameter name for attributes

When using the sequential style of edge connections, adding an attribute without using a named parameter will add an extra node called System.Collection.Hashtable

Graph g {

    Edge Home Work @{label='to'}
    Edge a,b,c,d,a @{label='to'}

} | Export-PSGraph -ShowGraph

Export-PSGraph does not find graphviz on Ubuntu in default location

On Ubuntu, the default install location is /usr/bin/dot I feel this should be added to the default search list

        $GraphVizPath = (
            'C:\Program Files\NuGet\Packages\Graphviz*\dot.exe',
            'C:\program files*\GraphViz*\bin\dot.exe',
            '/usr/local/bin/dot'
        ),

If you agree, I can do a PR if you like.

Make the paths to dot dynamic

PSGraph searches for dot.exe (or the dot binary) in 3 locations. I would like to install GraphViz in another directory and I don't have admin rights. That makes it mandatory to pass the dot binary path on ever call to Export-PSGraph. It would be cool to add $env:Path or to make it configurable, so that one could easily add the dot path to %PATH% and is just ready to go

Dot makes PSGraph fail with an `Out of memory` exception

Synopsis

I have programmed a PowerShell function that can analyze a PowerShell module and put out a callgraph over the module. PSGraph is used to generate the graph based on the data retrieved from the module analysis.

The error

When I use Out-PSModuleCallGraph to analyze the code of HealOps I get the following error:

Error: trouble in init_rank
	%0 19
	%0 10
	%0 5
	%0 6
	%0 23
......
  • the list of [%NUMBER NUMBER] is long, so shortened in the above. For the value of info, allow me to mention that commands from the module is mentioned in the list. The error message continues with:
	%0 2
	%0 1
libpath/shortest.c:324: triangulation failed
libpath/shortest.c:192: source point not in any triangle
Error: in routesplines, Pshortestpath failed
dot(82295,0x7fff9a9c9380) malloc: *** mach_vm_map(size=18446744069337296896) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
out of memory
Export-PSGraph : System error.
At /gitRepos/PowerShellTooling/Public/PowerShellInfo/Out-PSModuleCallGraph.ps1:473 char:22
+         $graphData | Export-PSGraph -ShowGraph
+                      ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [Write-Error], ParseException
+ FullyQualifiedErrorId : System.Management.Automation.ParseException,Export-PSGraph

For other modules this error is not thrown. E.g for modules like Plaster or Pester.

Tried

I tried searching for suggestions on the reason behind the error. Some mentions an issue with a circular reference. Others suggests setting max_depth or newrank=true but that draws a graph that does not quite have the layout I would like. However, a graph is actually drawn.

I also tried setting cluster as the name for the subgraph used. This also makes generating the graph go thrugh, however, again not with the layout I would like.

Reproducing

  1. Clone HealOps from the linke to the repo.
  2. Download the release of PowerShellTooling
  3. Import the PowerShellTooling module or dot-source directly to the Out-PSModuleCallGraph.ps1 file.
  4. Execute Out-PSModuleCallGraph and point it to the HealOps module root. E.g. > Out-PSModuleCallGraph -ModuleRoot "PATH_TO_HEALOPS_MODULE_ROOT"/HealOps
  5. The same error I describe above should be thrown.

End notes

It would be great if it was possible to generate a graph over HealOps and modules like it (having the same issue) without the error being thrown. See the attached screenshot for an example of the layout I'm tryng to produce. The screenshot if from analyzing another module I'm working on.

Thank you so much for your time.

qwfyk0gb fq4

Doesn't detect Graphviz on linux

Hi,

I wasn't sure if PSgraph is 'supported' on Linux.
I am on ubuntu 1804, and I have the following error message when I try to create a graph:

image

As you could seem these are automated tests.

I have installed Graphviz using: sudo apt install graphviz (I had to follow this first https://packages.ubuntu.com/trusty/amd64/graphviz/download )

If it is supported on linux, the errors messages are wrong, as there is no program files on Linux

Make Edge cmdlet case insensitive

Hi Kevin,

I have something that bothers me on the 'edge' cmdlet. I don't know if this is by design, but I noticed that the 'edge' cmdlet is case sensitive. I would rather have it be insensitive, and most of the things in PowerShell are case insensitive.

See the example below:

graph g {

    SubGraph MyTests {

        Record -Name "Parent" {
            Row "Parent First Row" -Name "Parent_Row_First"
            Row "Parent second Row" -Name "Parent_Row_Second"
            
        }

        $Childs = @("Pierre","Paul","Jacques")

        Foreach($c in $Childs){
            Record -Name $c {
                Row "$c First Row" -Name "$($c)_Row_First"
                Row "$c second Row" -Name "$($c)_Row_Second"
                Row "$c thrid Row" -Name "$($c)_Row_third"
                
            }
        }

    }

    #This will not work, and create a new circle instead of the existing elements of the graph.
    #This is due to the fact that the case is different then in the $Childs array.
        edge -From "parent" -To "pierre","paul","jacques"
    

    
} |Show-PSGraph

This is the result we would get (But not the one we would expect / want):

edge_debbuging_nok

graph g {

    SubGraph MyTests {

        Record -Name "Parent" {
            Row "Parent First Row" -Name "Parent_Row_First"
            Row "Parent second Row" -Name "Parent_Row_Second"
            
        }

        $Childs = @("Pierre","Paul","Jacques")

        Foreach($c in $Childs){
            Record -Name $c {
                Row "$c First Row" -Name "$($c)_Row_First"
                Row "$c second Row" -Name "$($c)_Row_Second"
                Row "$c thrid Row" -Name "$($c)_Row_third"
                
            }
        }

    }

    #This works, since it has the EXACT same case sensitivy a the strings located in '$Childs'
        edge -From "Parent" -To "Pierre","Paul","Jacques"


} |Show-PSGraph

And in this case, this is what we would get (and actually expect).

edge_debbuging_ok

Although the fix seems trivial, I needed quite some time to realize where it came from, as I was testing it on various scripts with Write-ClassDiagram on scripts that I didn't write. (See issue on PowershellClassUtils here)

I think it would be great if we could remove the case sensitivity, as I don't really see, as a PowerShell scripter, what it actually brings as added value.

RFC: Naming considerations for PSGraph commands

I am looking to expand the commands available to PSGraph and I am concerned that the use of very generic keywords will start to cause issues. I already have scenarios where Node is a keyword used in DSC and is the command name for Node.js

I am looking to introduce Record or Table keywords for graphing datasets. This may lead to several keywords needing to be introduced like Row or Cell. I don't want to pollute the PowerShell command space but I also don't want to make these overly verbose by using approved verbs.

Option 1: Be true to the DSL

Take the approach that PSGraph does whatever is best for the PSGraph DSL. Add whatever keywords are needed and don't complicate things. People can always choose to only import the module when they are working with graphs. The new commands would be called Record and Row to keep in line with current naming.

Option 2: Simple gv prefix

Every command should be given a gv prefix so they stand as unique commands and don't cause conflicts in the PowerShell ecosystem. Commands would be renamed gvGraph,gvEdge',gvNodeand new commands would be calledgvRecord,gvRow`. To maintain backward compatibility, we would add aliases for all the existing commands. ScriptAnalyzer would catch the use of aliases and suggest the scripter use the new names.

Option 3: Private commands

I could make all the commands private, but available when called inside the Graph {...} command. This is something that I have considered before. This would prevent the commands that should be called inside the graph from getting called outside the graph or showing up for Get-Command

I do make those calls quite often when debugging a graph or making a really complex graph. I should be able to adjust easy enough and I don't think most others have considered running it this way.

This would also make the commands less discoverable and I am not sure if VSCode would be able to add intellisense. Users would also lose the ability to call Get-Help on the commands. This could be handled by creating about_* pages for the commands in the module.

Option 4: Other

If you have any feedback or other option ideas, please add a comment.

Should we have a -rank or -ranked switch on the node

Quite often, when I use scripts or variables to define a set of nodes. I often also rank them. I should consider adding a -ranked keyword to the node command.

# using variables
$webServers = 'Web1','Web2','Web3'
$apiServers = 'Api1','Api2'
$databaseServers = 'DB1'

graph site1 {
    # External/DMZ nodes

    node loadbalancer @{shape='house'}
    node $webServers @{shape='rect'} -Ranked
    edge loadbalancer $webServers

    # Internal API servers
    node $apiServers   -Ranked
    edge $webServers -to $apiServers

    # Database Servers
    node $databaseServers @{shape='octagon'} -Ranked
    edge $apiServers -to $databaseServers
  
}  | Export-PSGraph -ShowGraph

Feature request - Implement GVPR.

Had the issue of nodes with no edges in a generated graph. I would like to be able to give the users of Out-PSModuleCallGraph the option of excluding such nodes. Reading up on the documentation of Graphviz I found that the tool GVPR should be able to do this. Do you already have implementing GVPR on the to-do list for PSGraph? If not I would like to request it. I could also help out by trying to integrate it into PSGraph if okay with you @KevinMarquette

Thank you and looking forward to your response.

Foreign letters gets converted to ?

When running Export-PSGraph on foreign letters they get converted to ?. Here is a test on the french ç and the danish ø:

graph g { edge "François" "Sørensen" } | Export-PSGraph -ShowGraph

Everything is fine in the Powershell code.

graph g { edge "François" "Sørensen" }
digraph g {
    compound="true";
    "François"->"Sørensen"
}

It is the creation of the image with dot.exe that introduces the error.
Line 187 in Export-PSGraph.ps1:

$standardInput.ToString() | & $graphViz

This issue should probably be stated to the team creating graphViz.

Naming the subgraph should be optional

If you never reference a subgraph by name, do you even need to name it?

This is how it should look.

graph {
    subgraph {
        node A
    }
    node B
    Edge A -To B
}

Problems with using multiple array variables in rank

Second issue I worked around today is that if you put in arrays to be used by rank in the graph script block you will end up with additional nodes generated with concatenated names. Ie $a = 1,2; $b = 3,4 when used with rank $a,$b will yield nodes (1 2) and (3 4), in my script I add a new variable and add all of the objects into the array then pass it to rank.

Not able to set defaults using new cmds

When trying to set a default arrowhead it ignores it if I use the edge command:

This is ignored:
edge @{arrowhead='none'}
This works:
'edge [arrowhead=none]'

Export-PSGraph does not support PowerShellCore on MacOS

The issue is likely also there on Linux, however only verified on MacOS. The use of $env:temp does not work with PowerShell Core on MacOS (running beta3).

  • I get:
    `Export-PSGraph : Cannot run a document in PowerShell Core: /Users/"USERNAME"/0xanmbp2.y4x.png.
    At /PATH/file.ps1:102 char:40
  • ... graphData | Export-PSGraph -ShowGraph -DestinationPath $destinationPa ...
  •             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : InvalidOperation: (/Users/USERNAME/0xanmbp2.y4x.png:String) [Export-PSGraph], RuntimeException
    • FullyQualifiedErrorId : CantActivateDocumentInPowerShellCore,Export-PSGraph
      `

I managed to handle it in my script by looking at type of os --> generating a path+filename --> then use -destinationpath parameter on the Export-PSGraph cmdlet. However, it would be great if it was handled inside PSGraph directly.

Let me know if the above raises some questions and I'll happily answer those.

Thank you.

Not getting "note" type shape

I'm trying to generate a graph that makes use of the "note" type shape. However, I get what seems to be the "oval" shape instead.

  • I have tried looking through the code here in the repo to see what could be the culprit, but haven't been able to find it. To be fair I didn't spend hours on that.
  • I have read through the DOT language documentation, especially >> http://graphviz.org/content/node-shapes and there I see the "note" shape mentioned. So shouldn't it be available via PSGraph?

what I want

image

what I get

image

Is this a bug or am I misunderstanding something?

Thank you 👍

Support svg as outpu format.

The official documentation on Graphviz states that the svg format is an available output option. Could it be possible to make PSGraph support svg?

Thank you and here is a link to the documentation SVG

SubGraph Example from help doesn't work

Hi,

I was looking into the SubGraph functionality, and noticed that the example in the documentation wasn't working:

graph {
    subgraph -Attributes @{label='DMZ'} {
        node web1,web2,reports
        edge report -To web1,web2
    }        
    edge loadBalancer -To web1,web2
    edge user -To loadBalancer,report
    edge web1,web2,report -To database
} | show-psgraph

this is the the message i get back:

cmdlet SubGraph at command pipeline position 1
Supply values for the following parameters:
ScriptBlock:

Additional inline html issues

Kevin, thanks for all the updates, a lot of them have worked great, the fix for the inline html worked....partially. If the html is multi line we run into the quote issue again:

HTTPS [shape=egg;label=<<TABLE BORDER='0' CELLBORDER='0' CELLSPACING='0'><TR><TD><FONT POINT-SIZE='20'><B><U>HTTPS</U></B></FONT></TD></TR></TABLE>>;]
LoadBalancer [shape=diamond;label="<<TABLE BORDER='0' CELLBORDER='0' CELLSPACING='0'><TR><TD><FONT POINT-SIZE='20'><B><U>LoadBalancer</U></B></FONT></TD></TR>
<TR><TD Align='Center' >10.0.0.0/24</TD></TR></TABLE>";]

Sequential edges are not working as expected

When I run this command,

edge 1,2,3,4

I get this output:

"1"->"" 
"2"->"" 
"3"->"" 
"4"->"" 

But I am expecting this output:

"1"->"2" 
"2"->"3" 
"3"->"4" 

This is causing graphs to render incorrectly.

Problems with inline HTML tagging

First, thanks for the great module, I used it today to write a script to create a graphviz diagram from an imported CSV. However there we some issues that I had to work around. When trying to add the inline HTML the module adds quotes around it so the graph has the whole inline HTML in the node instead of rendering off of it. In my script I fixed it by post processing the graph object to replace the "<< and >>"

Cancellation characters

It appears that backslashes (possibly other special chacters) are not printed when included in labels. imagine I could mitigate this before passing lists to PSGraph but it would be ideal to handle any special character cancellation internally.

Set-NodeFormatScript applies to node @{shape='rect'} and it should not.

When testing ways to work around #30, I discovered that the custom node formatting performed by Set-NodeFormatScript will also apply to the default node syntax.

This line:

digraph g {
    node @{shape='rect'}
    node firstNode
}

should product this output to set default attribute values for all future nodes

digraph g {
    node [shape=rect;]
    firstNode
}

But adding a custom node format script, it also applies to that first empty node when it should not.

Set-NodeFormatScript -ScriptBlock {"--$_--"}
digraph g {
    node @{shape='rect'}
    node firstNode
}

output:

digraph g {
     "--node--" [shape=rect;]
    "--firstNode--"
}

This adds that node to the output and it breaks the ability to set attributes for other nodes that follow.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.