Remove dot package
Unify all dot functionality in the dag package
This commit is contained in:
parent
8a5d71b0ac
commit
6f347ebb3a
12
dag/dot.go
12
dag/dot.go
|
@ -5,8 +5,6 @@ import (
|
|||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform/dot"
|
||||
)
|
||||
|
||||
// DotOpts are the options for generating a dot formatted Graph.
|
||||
|
@ -28,13 +26,19 @@ type DotOpts struct {
|
|||
// GraphNodeDotter can be implemented by a node to cause it to be included
|
||||
// in the dot graph. The Dot method will be called which is expected to
|
||||
// return a representation of this node.
|
||||
// TODO remove the dot package dependency
|
||||
type GraphNodeDotter interface {
|
||||
// Dot is called to return the dot formatting for the node.
|
||||
// The first parameter is the title of the node.
|
||||
// The second parameter includes user-specified options that affect the dot
|
||||
// graph. See GraphDotOpts below for details.
|
||||
DotNode(string, *DotOpts) *dot.Node
|
||||
DotNode(string, *DotOpts) *DotNode
|
||||
}
|
||||
|
||||
// DotNode provides a structure for Vertices to return in order to specify their
|
||||
// dot format.
|
||||
type DotNode struct {
|
||||
Name string
|
||||
Attrs map[string]string
|
||||
}
|
||||
|
||||
// Returns the DOT representation of this Graph.
|
||||
|
|
|
@ -301,11 +301,6 @@ func (g *Graph) String() string {
|
|||
return buf.String()
|
||||
}
|
||||
|
||||
func (g *Graph) Marshal() ([]byte, error) {
|
||||
dg := newMarshalGraph("", g)
|
||||
return json.MarshalIndent(dg, "", " ")
|
||||
}
|
||||
|
||||
func (g *Graph) Dot(opts *DotOpts) []byte {
|
||||
return newMarshalGraph("", g).Dot(opts)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
// the marshal* structs are for serialization of the graph data.
|
||||
type marshalGraph struct {
|
||||
// Each marshal structure require a unique ID so that it can be references
|
||||
// Each marshal structure requires a unique ID so that it can be referenced
|
||||
// by other structures.
|
||||
ID string `json:",omitempty"`
|
||||
|
||||
|
@ -52,7 +52,7 @@ type marshalVertex struct {
|
|||
Attrs map[string]string `json:",omitempty"`
|
||||
|
||||
// This is to help transition from the old Dot interfaces. We record if the
|
||||
// node was a GraphNodeDotter here, so know if it should be included in the
|
||||
// node was a GraphNodeDotter here, so we know if it should be included in the
|
||||
// dot output
|
||||
graphNodeDotter bool
|
||||
}
|
||||
|
|
237
dot/graph.go
237
dot/graph.go
|
@ -1,237 +0,0 @@
|
|||
// The dot package contains utilities for working with DOT graphs.
|
||||
package dot
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Graph is a representation of a drawable DOT graph.
|
||||
type Graph struct {
|
||||
// Whether this is a "digraph" or just a "graph"
|
||||
Directed bool
|
||||
|
||||
// Used for K/V settings in the DOT
|
||||
Attrs map[string]string
|
||||
|
||||
Nodes []*Node
|
||||
Edges []*Edge
|
||||
Subgraphs []*Subgraph
|
||||
|
||||
nodesByName map[string]*Node
|
||||
}
|
||||
|
||||
// Subgraph is a Graph that lives inside a Parent graph, and contains some
|
||||
// additional parameters to control how it is drawn.
|
||||
type Subgraph struct {
|
||||
Graph
|
||||
Name string
|
||||
Parent *Graph
|
||||
Cluster bool
|
||||
}
|
||||
|
||||
// An Edge in a DOT graph, as expressed by recording the Name of the Node at
|
||||
// each end.
|
||||
type Edge struct {
|
||||
// Name of source node.
|
||||
Source string
|
||||
|
||||
// Name of dest node.
|
||||
Dest string
|
||||
|
||||
// List of K/V attributes for this edge.
|
||||
Attrs map[string]string
|
||||
}
|
||||
|
||||
// A Node in a DOT graph.
|
||||
type Node struct {
|
||||
Name string
|
||||
Attrs map[string]string
|
||||
}
|
||||
|
||||
// Creates a properly initialized DOT Graph.
|
||||
func NewGraph(attrs map[string]string) *Graph {
|
||||
return &Graph{
|
||||
Attrs: attrs,
|
||||
nodesByName: make(map[string]*Node),
|
||||
}
|
||||
}
|
||||
|
||||
func NewEdge(src, dst string, attrs map[string]string) *Edge {
|
||||
return &Edge{
|
||||
Source: src,
|
||||
Dest: dst,
|
||||
Attrs: attrs,
|
||||
}
|
||||
}
|
||||
|
||||
func NewNode(n string, attrs map[string]string) *Node {
|
||||
return &Node{
|
||||
Name: n,
|
||||
Attrs: attrs,
|
||||
}
|
||||
}
|
||||
|
||||
// Initializes a Subgraph with the provided name, attaches is to this Graph,
|
||||
// and returns it.
|
||||
func (g *Graph) AddSubgraph(name string) *Subgraph {
|
||||
subgraph := &Subgraph{
|
||||
Graph: *NewGraph(map[string]string{}),
|
||||
Parent: g,
|
||||
Name: name,
|
||||
}
|
||||
g.Subgraphs = append(g.Subgraphs, subgraph)
|
||||
return subgraph
|
||||
}
|
||||
|
||||
func (g *Graph) AddAttr(k, v string) {
|
||||
g.Attrs[k] = v
|
||||
}
|
||||
|
||||
func (g *Graph) AddNode(n *Node) {
|
||||
g.Nodes = append(g.Nodes, n)
|
||||
g.nodesByName[n.Name] = n
|
||||
}
|
||||
|
||||
func (g *Graph) AddEdge(e *Edge) {
|
||||
g.Edges = append(g.Edges, e)
|
||||
}
|
||||
|
||||
// Adds an edge between two Nodes.
|
||||
//
|
||||
// Note this does not do any verification of the existence of these nodes,
|
||||
// which means that any strings you provide that are not existing nodes will
|
||||
// result in extra auto-defined nodes in your resulting DOT.
|
||||
func (g *Graph) AddEdgeBetween(src, dst string, attrs map[string]string) error {
|
||||
g.AddEdge(NewEdge(src, dst, attrs))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Look up a node by name
|
||||
func (g *Graph) GetNode(name string) (*Node, error) {
|
||||
node, ok := g.nodesByName[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Could not find node: %s", name)
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
// Returns the DOT representation of this Graph.
|
||||
func (g *Graph) String() string {
|
||||
w := newGraphWriter()
|
||||
|
||||
g.drawHeader(w)
|
||||
w.Indent()
|
||||
g.drawBody(w)
|
||||
w.Unindent()
|
||||
g.drawFooter(w)
|
||||
|
||||
return w.String()
|
||||
}
|
||||
|
||||
// Returns the DOT representation of this Graph.
|
||||
func (g *Graph) Bytes() []byte {
|
||||
w := newGraphWriter()
|
||||
|
||||
g.drawHeader(w)
|
||||
w.Indent()
|
||||
g.drawBody(w)
|
||||
w.Unindent()
|
||||
g.drawFooter(w)
|
||||
|
||||
return w.Bytes()
|
||||
}
|
||||
|
||||
func (g *Graph) drawHeader(w *graphWriter) {
|
||||
if g.Directed {
|
||||
w.Printf("digraph {\n")
|
||||
} else {
|
||||
w.Printf("graph {\n")
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Graph) drawBody(w *graphWriter) {
|
||||
for _, as := range attrStrings(g.Attrs) {
|
||||
w.Printf("%s\n", as)
|
||||
}
|
||||
|
||||
nodeStrings := make([]string, 0, len(g.Nodes))
|
||||
for _, n := range g.Nodes {
|
||||
nodeStrings = append(nodeStrings, n.String())
|
||||
}
|
||||
sort.Strings(nodeStrings)
|
||||
for _, ns := range nodeStrings {
|
||||
w.Printf(ns)
|
||||
}
|
||||
|
||||
edgeStrings := make([]string, 0, len(g.Edges))
|
||||
for _, e := range g.Edges {
|
||||
edgeStrings = append(edgeStrings, e.String())
|
||||
}
|
||||
sort.Strings(edgeStrings)
|
||||
for _, es := range edgeStrings {
|
||||
w.Printf(es)
|
||||
}
|
||||
|
||||
for _, s := range g.Subgraphs {
|
||||
s.drawHeader(w)
|
||||
w.Indent()
|
||||
s.drawBody(w)
|
||||
w.Unindent()
|
||||
s.drawFooter(w)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Graph) drawFooter(w *graphWriter) {
|
||||
w.Printf("}\n")
|
||||
}
|
||||
|
||||
// Returns the DOT representation of this Edge.
|
||||
func (e *Edge) String() string {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(
|
||||
fmt.Sprintf(
|
||||
"%q -> %q", e.Source, e.Dest))
|
||||
writeAttrs(&buf, e.Attrs)
|
||||
buf.WriteString("\n")
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (s *Subgraph) drawHeader(w *graphWriter) {
|
||||
name := s.Name
|
||||
if s.Cluster {
|
||||
name = fmt.Sprintf("cluster_%s", name)
|
||||
}
|
||||
w.Printf("subgraph %q {\n", name)
|
||||
}
|
||||
|
||||
// Returns the DOT representation of this Node.
|
||||
func (n *Node) String() string {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(fmt.Sprintf("%q", n.Name))
|
||||
writeAttrs(&buf, n.Attrs)
|
||||
buf.WriteString("\n")
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func writeAttrs(buf *bytes.Buffer, attrs map[string]string) {
|
||||
if len(attrs) > 0 {
|
||||
buf.WriteString(" [")
|
||||
buf.WriteString(strings.Join(attrStrings(attrs), ", "))
|
||||
buf.WriteString("]")
|
||||
}
|
||||
}
|
||||
|
||||
func attrStrings(attrs map[string]string) []string {
|
||||
strings := make([]string, 0, len(attrs))
|
||||
for k, v := range attrs {
|
||||
strings = append(strings, fmt.Sprintf("%s = %q", k, v))
|
||||
}
|
||||
sort.Strings(strings)
|
||||
return strings
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
package dot
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// graphWriter wraps a bytes.Buffer and tracks indent level levels.
|
||||
type graphWriter struct {
|
||||
bytes.Buffer
|
||||
indent int
|
||||
indentStr string
|
||||
}
|
||||
|
||||
// Returns an initialized graphWriter at indent level 0.
|
||||
func newGraphWriter() *graphWriter {
|
||||
w := &graphWriter{
|
||||
indent: 0,
|
||||
}
|
||||
w.init()
|
||||
return w
|
||||
}
|
||||
|
||||
// Prints to the buffer at the current indent level.
|
||||
func (w *graphWriter) Printf(s string, args ...interface{}) {
|
||||
w.WriteString(w.indentStr + fmt.Sprintf(s, args...))
|
||||
}
|
||||
|
||||
// Increase the indent level.
|
||||
func (w *graphWriter) Indent() {
|
||||
w.indent++
|
||||
w.init()
|
||||
}
|
||||
|
||||
// Decrease the indent level.
|
||||
func (w *graphWriter) Unindent() {
|
||||
w.indent--
|
||||
w.init()
|
||||
}
|
||||
|
||||
func (w *graphWriter) init() {
|
||||
indentBuf := new(bytes.Buffer)
|
||||
for i := 0; i < w.indent; i++ {
|
||||
indentBuf.WriteString("\t")
|
||||
}
|
||||
w.indentStr = indentBuf.String()
|
||||
}
|
|
@ -7,7 +7,6 @@ import (
|
|||
"github.com/hashicorp/terraform/config"
|
||||
"github.com/hashicorp/terraform/config/module"
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
"github.com/hashicorp/terraform/dot"
|
||||
)
|
||||
|
||||
// GraphNodeConfigModule represents a module within the configuration graph.
|
||||
|
@ -129,11 +128,14 @@ func (n *graphNodeModuleExpanded) DependentOn() []string {
|
|||
}
|
||||
|
||||
// GraphNodeDotter impl.
|
||||
func (n *graphNodeModuleExpanded) DotNode(name string, opts *dag.DotOpts) *dot.Node {
|
||||
return dot.NewNode(name, map[string]string{
|
||||
func (n *graphNodeModuleExpanded) DotNode(name string, opts *dag.DotOpts) *dag.DotNode {
|
||||
return &dag.DotNode{
|
||||
Name: name,
|
||||
Attrs: map[string]string{
|
||||
"label": dag.VertexName(n.Original),
|
||||
"shape": "component",
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// GraphNodeEvalable impl.
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
|
||||
"github.com/hashicorp/terraform/config"
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
"github.com/hashicorp/terraform/dot"
|
||||
)
|
||||
|
||||
// GraphNodeConfigProvider represents a configured provider within the
|
||||
|
@ -59,11 +58,14 @@ func (n *GraphNodeConfigProvider) ProviderConfig() *config.RawConfig {
|
|||
}
|
||||
|
||||
// GraphNodeDotter impl.
|
||||
func (n *GraphNodeConfigProvider) DotNode(name string, opts *dag.DotOpts) *dot.Node {
|
||||
return dot.NewNode(name, map[string]string{
|
||||
func (n *GraphNodeConfigProvider) DotNode(name string, opts *dag.DotOpts) *dag.DotNode {
|
||||
return &dag.DotNode{
|
||||
Name: name,
|
||||
Attrs: map[string]string{
|
||||
"label": n.Name(),
|
||||
"shape": "diamond",
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// GraphNodeDotterOrigin impl.
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
|
||||
"github.com/hashicorp/terraform/config"
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
"github.com/hashicorp/terraform/dot"
|
||||
)
|
||||
|
||||
// GraphNodeCountDependent is implemented by resources for giving only
|
||||
|
@ -128,14 +127,17 @@ func (n *GraphNodeConfigResource) Name() string {
|
|||
}
|
||||
|
||||
// GraphNodeDotter impl.
|
||||
func (n *GraphNodeConfigResource) DotNode(name string, opts *dag.DotOpts) *dot.Node {
|
||||
func (n *GraphNodeConfigResource) DotNode(name string, opts *dag.DotOpts) *dag.DotNode {
|
||||
if n.Destroy && !opts.Verbose {
|
||||
return nil
|
||||
}
|
||||
return dot.NewNode(name, map[string]string{
|
||||
return &dag.DotNode{
|
||||
Name: name,
|
||||
Attrs: map[string]string{
|
||||
"label": n.Name(),
|
||||
"shape": "box",
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// GraphNodeFlattenable impl.
|
||||
|
|
|
@ -1,20 +1,6 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
"github.com/hashicorp/terraform/dot"
|
||||
)
|
||||
|
||||
// GraphNodeDotter can be implemented by a node to cause it to be included
|
||||
// in the dot graph. The Dot method will be called which is expected to
|
||||
// return a representation of this node.
|
||||
type GraphNodeDotter interface {
|
||||
// Dot is called to return the dot formatting for the node.
|
||||
// The first parameter is the title of the node.
|
||||
// The second parameter includes user-specified options that affect the dot
|
||||
// graph. See GraphDotOpts below for details.
|
||||
DotNode(string, *dag.DotOpts) *dot.Node
|
||||
}
|
||||
import "github.com/hashicorp/terraform/dag"
|
||||
|
||||
// GraphDot returns the dot formatting of a visual representation of
|
||||
// the given Terraform graph.
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
"github.com/hashicorp/terraform/dot"
|
||||
)
|
||||
|
||||
func TestGraphDot(t *testing.T) {
|
||||
|
@ -263,8 +262,8 @@ type testDrawable struct {
|
|||
func (node *testDrawable) Name() string {
|
||||
return node.VertexName
|
||||
}
|
||||
func (node *testDrawable) DotNode(n string, opts *dag.DotOpts) *dot.Node {
|
||||
return dot.NewNode(n, map[string]string{})
|
||||
func (node *testDrawable) DotNode(n string, opts *dag.DotOpts) *dag.DotNode {
|
||||
return &dag.DotNode{Name: n, Attrs: map[string]string{}}
|
||||
}
|
||||
func (node *testDrawable) DependableName() []string {
|
||||
return []string{node.VertexName}
|
||||
|
@ -280,8 +279,8 @@ type testDrawableOrigin struct {
|
|||
func (node *testDrawableOrigin) Name() string {
|
||||
return node.VertexName
|
||||
}
|
||||
func (node *testDrawableOrigin) DotNode(n string, opts *dag.DotOpts) *dot.Node {
|
||||
return dot.NewNode(n, map[string]string{})
|
||||
func (node *testDrawableOrigin) DotNode(n string, opts *dag.DotOpts) *dag.DotNode {
|
||||
return &dag.DotNode{Name: n, Attrs: map[string]string{}}
|
||||
}
|
||||
func (node *testDrawableOrigin) DotOrigin() bool {
|
||||
return true
|
||||
|
@ -302,8 +301,8 @@ func (node *testDrawableSubgraph) Name() string {
|
|||
func (node *testDrawableSubgraph) Subgraph() dag.Grapher {
|
||||
return node.SubgraphMock
|
||||
}
|
||||
func (node *testDrawableSubgraph) DotNode(n string, opts *dag.DotOpts) *dot.Node {
|
||||
return dot.NewNode(n, map[string]string{})
|
||||
func (node *testDrawableSubgraph) DotNode(n string, opts *dag.DotOpts) *dag.DotNode {
|
||||
return &dag.DotNode{Name: n, Attrs: map[string]string{}}
|
||||
}
|
||||
func (node *testDrawableSubgraph) DependentOn() []string {
|
||||
return node.DependentOnMock
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/hashicorp/terraform/config"
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
"github.com/hashicorp/terraform/dot"
|
||||
)
|
||||
|
||||
// GraphNodeProvider is an interface that nodes that can be a provider
|
||||
|
@ -355,14 +354,17 @@ func (n *graphNodeCloseProvider) CloseProviderName() string {
|
|||
}
|
||||
|
||||
// GraphNodeDotter impl.
|
||||
func (n *graphNodeCloseProvider) DotNode(name string, opts *dag.DotOpts) *dot.Node {
|
||||
func (n *graphNodeCloseProvider) DotNode(name string, opts *dag.DotOpts) *dag.DotNode {
|
||||
if !opts.Verbose {
|
||||
return nil
|
||||
}
|
||||
return dot.NewNode(name, map[string]string{
|
||||
return &dag.DotNode{
|
||||
Name: name,
|
||||
Attrs: map[string]string{
|
||||
"label": n.Name(),
|
||||
"shape": "diamond",
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type graphNodeProvider struct {
|
||||
|
@ -393,11 +395,14 @@ func (n *graphNodeProvider) ProviderConfig() *config.RawConfig {
|
|||
}
|
||||
|
||||
// GraphNodeDotter impl.
|
||||
func (n *graphNodeProvider) DotNode(name string, opts *dag.DotOpts) *dot.Node {
|
||||
return dot.NewNode(name, map[string]string{
|
||||
func (n *graphNodeProvider) DotNode(name string, opts *dag.DotOpts) *dag.DotNode {
|
||||
return &dag.DotNode{
|
||||
Name: name,
|
||||
Attrs: map[string]string{
|
||||
"label": n.Name(),
|
||||
"shape": "diamond",
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// GraphNodeDotterOrigin impl.
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
|
||||
"github.com/hashicorp/terraform/config"
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
"github.com/hashicorp/terraform/dot"
|
||||
)
|
||||
|
||||
// DisableProviderTransformer "disables" any providers that are only
|
||||
|
@ -102,11 +101,14 @@ func (n *graphNodeDisabledProvider) Name() string {
|
|||
}
|
||||
|
||||
// GraphNodeDotter impl.
|
||||
func (n *graphNodeDisabledProvider) DotNode(name string, opts *dag.DotOpts) *dot.Node {
|
||||
return dot.NewNode(name, map[string]string{
|
||||
func (n *graphNodeDisabledProvider) DotNode(name string, opts *dag.DotOpts) *dag.DotNode {
|
||||
return &dag.DotNode{
|
||||
Name: name,
|
||||
Attrs: map[string]string{
|
||||
"label": n.Name(),
|
||||
"shape": "diamond",
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// GraphNodeDotterOrigin impl.
|
||||
|
|
Loading…
Reference in New Issue