diff --git a/dag/dot.go b/dag/dot.go index 15e7ba965..fc7754c12 100644 --- a/dag/dot.go +++ b/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. diff --git a/dag/graph.go b/dag/graph.go index 456eb0826..ff9c9bd89 100644 --- a/dag/graph.go +++ b/dag/graph.go @@ -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) } diff --git a/dag/marshal.go b/dag/marshal.go index 9b601e91a..95790ba3d 100644 --- a/dag/marshal.go +++ b/dag/marshal.go @@ -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 } diff --git a/dot/graph.go b/dot/graph.go deleted file mode 100644 index c224fb557..000000000 --- a/dot/graph.go +++ /dev/null @@ -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 -} diff --git a/dot/graph_writer.go b/dot/graph_writer.go deleted file mode 100644 index 7fa5d9cac..000000000 --- a/dot/graph_writer.go +++ /dev/null @@ -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() -} diff --git a/terraform/graph_config_node_module.go b/terraform/graph_config_node_module.go index 5ba36252b..8a6b52201 100644 --- a/terraform/graph_config_node_module.go +++ b/terraform/graph_config_node_module.go @@ -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{ - "label": dag.VertexName(n.Original), - "shape": "component", - }) +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. diff --git a/terraform/graph_config_node_provider.go b/terraform/graph_config_node_provider.go index f42d1430c..59fbfcb0b 100644 --- a/terraform/graph_config_node_provider.go +++ b/terraform/graph_config_node_provider.go @@ -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{ - "label": n.Name(), - "shape": "diamond", - }) +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. diff --git a/terraform/graph_config_node_resource.go b/terraform/graph_config_node_resource.go index 27654d2bb..70dfc2a2b 100644 --- a/terraform/graph_config_node_resource.go +++ b/terraform/graph_config_node_resource.go @@ -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{ - "label": n.Name(), - "shape": "box", - }) + return &dag.DotNode{ + Name: name, + Attrs: map[string]string{ + "label": n.Name(), + "shape": "box", + }, + } } // GraphNodeFlattenable impl. diff --git a/terraform/graph_dot.go b/terraform/graph_dot.go index 0b390b51b..73e3821fb 100644 --- a/terraform/graph_dot.go +++ b/terraform/graph_dot.go @@ -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. diff --git a/terraform/graph_dot_test.go b/terraform/graph_dot_test.go index 164327b8e..1fad2376d 100644 --- a/terraform/graph_dot_test.go +++ b/terraform/graph_dot_test.go @@ -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 diff --git a/terraform/transform_provider.go b/terraform/transform_provider.go index f46af247c..c995186dc 100644 --- a/terraform/transform_provider.go +++ b/terraform/transform_provider.go @@ -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{ - "label": n.Name(), - "shape": "diamond", - }) + 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{ - "label": n.Name(), - "shape": "diamond", - }) +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. diff --git a/terraform/transform_provider_old.go b/terraform/transform_provider_old.go index 1e49294b7..50b452259 100644 --- a/terraform/transform_provider_old.go +++ b/terraform/transform_provider_old.go @@ -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{ - "label": n.Name(), - "shape": "diamond", - }) +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.