func (t *VertexTransformer) Transform(g *Graph) error {
	for _, v := range g.Vertices() {
		for _, vt := range t.Transforms {
			newV, err := vt.Transform(v)
			if err != nil {
				return err
			}

			// If the vertex didn't change, then don't do anything more
			if newV == v {
				continue
			}

			// Vertex changed, replace it within the graph
			if ok := g.Replace(v, newV); !ok {
				// This should never happen, big problem
				return fmt.Errorf(
					"Failed to replace %s with %s!\n\nSource: %#v\n\nTarget: %#v",
					dag.VertexName(v), dag.VertexName(newV), v, newV)
			}

			// Replace v so that future transforms use the proper vertex
			v = newV
		}
	}

	return nil
}
func (w *ContextGraphWalker) ExitEvalTree(
	v dag.Vertex, output interface{}, err error) error {
	// Release the semaphore
	w.Context.parallelSem.Release()

	if err == nil {
		return nil
	}

	// Acquire the lock because anything is going to require a lock.
	w.errorLock.Lock()
	defer w.errorLock.Unlock()

	// Try to get a validation error out of it. If its not a validation
	// error, then just record the normal error.
	verr, ok := err.(*EvalValidateError)
	if !ok {
		return err
	}

	for _, msg := range verr.Warnings {
		w.ValidationWarnings = append(
			w.ValidationWarnings,
			fmt.Sprintf("%s: %s", dag.VertexName(v), msg))
	}
	for _, e := range verr.Errors {
		w.ValidationErrors = append(
			w.ValidationErrors,
			errwrap.Wrapf(fmt.Sprintf("%s: {{err}}", dag.VertexName(v)), e))
	}

	return nil
}
func (t *ExpandTransform) Transform(v dag.Vertex) (dag.Vertex, error) {
	ev, ok := v.(GraphNodeExpandable)
	if !ok {
		// This isn't an expandable vertex, so just ignore it.
		return v, nil
	}

	// Expand the subgraph!
	log.Printf("[DEBUG] vertex %s: static expanding", dag.VertexName(ev))
	return ev.Expand(t.Builder)
}
// GraphNodeDestroyable impl.
func (n *GraphNodeConfigResourceFlat) DestroyNode(mode GraphNodeDestroyMode) GraphNodeDestroy {
	// Get our parent destroy node. If we don't have any, just return
	raw := n.GraphNodeConfigResource.DestroyNode(mode)
	if raw == nil {
		return nil
	}

	node, ok := raw.(*graphNodeResourceDestroy)
	if !ok {
		panic(fmt.Sprintf("unknown destroy node: %s %T", dag.VertexName(raw), raw))
	}

	// Otherwise, wrap it so that it gets the proper module treatment.
	return &graphNodeResourceDestroyFlat{
		graphNodeResourceDestroy: node,
		PathValue:                n.PathValue,
		FlatCreateNode:           n,
	}
}
func (t *DisableProviderTransformer) Transform(g *Graph) error {
	for _, v := range g.Vertices() {
		// We only care about providers
		pn, ok := v.(GraphNodeProvider)
		if !ok || pn.ProviderName() == "" {
			continue
		}

		// Go through all the up-edges (things that depend on this
		// provider) and if any is not a module, then ignore this node.
		nonModule := false
		for _, sourceRaw := range g.UpEdges(v).List() {
			source := sourceRaw.(dag.Vertex)
			cn, ok := source.(graphNodeConfig)
			if !ok {
				nonModule = true
				break
			}

			if cn.ConfigType() != GraphNodeConfigTypeModule {
				nonModule = true
				break
			}
		}
		if nonModule {
			// We found something that depends on this provider that
			// isn't a module, so skip it.
			continue
		}

		// Disable the provider by replacing it with a "disabled" provider
		disabled := &graphNodeDisabledProvider{GraphNodeProvider: pn}
		if !g.Replace(v, disabled) {
			panic(fmt.Sprintf(
				"vertex disappeared from under us: %s",
				dag.VertexName(v)))
		}
	}

	return nil
}
func (t *ProviderTransformer) Transform(g *Graph) error {
	// Go through the other nodes and match them to providers they need
	var err error
	m := providerVertexMap(g)
	for _, v := range g.Vertices() {
		if pv, ok := v.(GraphNodeProviderConsumer); ok {
			for _, p := range pv.ProvidedBy() {
				target := m[p]
				if target == nil {
					err = multierror.Append(err, fmt.Errorf(
						"%s: provider %s couldn't be found",
						dag.VertexName(v), p))
					continue
				}

				g.Connect(dag.BasicEdge(v, target))
			}
		}
	}

	return err
}
// GraphNodeDotter impl.
func (n *graphNodeModuleExpanded) DotNode(name string, opts *GraphDotOpts) *dot.Node {
	return dot.NewNode(name, map[string]string{
		"label": dag.VertexName(n.Original),
		"shape": "component",
	})
}
func (n *graphNodeModuleExpanded) Name() string {
	return fmt.Sprintf("%s (expanded)", dag.VertexName(n.Original))
}
func (n *graphNodeDisabledProvider) Name() string {
	return fmt.Sprintf("%s (disabled)", dag.VertexName(n.GraphNodeProvider))
}
func (t *FlattenTransformer) Transform(g *Graph) error {
	for _, v := range g.Vertices() {
		fn, ok := v.(GraphNodeFlatGraph)
		if !ok {
			continue
		}

		// If we don't want to be flattened, don't do it
		subgraph := fn.FlattenGraph()
		if subgraph == nil {
			continue
		}

		// Get all the things that depend on this node. We'll re-connect
		// dependents later. We have to copy these here since the UpEdges
		// value will be deleted after the Remove below.
		dependents := make([]dag.Vertex, 0, 5)
		for _, v := range g.UpEdges(v).List() {
			dependents = append(dependents, v)
		}

		// Remove the old node
		g.Remove(v)

		// Go through the subgraph and flatten all the nodes
		for _, sv := range subgraph.Vertices() {
			// If the vertex already has a subpath then we assume it has
			// already been flattened. Ignore it.
			if _, ok := sv.(GraphNodeSubPath); ok {
				continue
			}

			fn, ok := sv.(GraphNodeFlattenable)
			if !ok {
				return fmt.Errorf(
					"unflattenable node: %s %T",
					dag.VertexName(sv), sv)
			}

			v, err := fn.Flatten(subgraph.Path)
			if err != nil {
				return fmt.Errorf(
					"error flattening %s (%T): %s",
					dag.VertexName(sv), sv, err)
			}

			if v == nil {
				subgraph.Remove(v)
			} else {
				subgraph.Replace(sv, v)
			}
		}

		// Now that we've handled any changes to the graph that are
		// needed, we can add them all to our graph along with their edges.
		for _, sv := range subgraph.Vertices() {
			g.Add(sv)
		}
		for _, se := range subgraph.Edges() {
			g.Connect(se)
		}

		// Connect the dependencies for all the new nodes that we added.
		// This will properly connect variables to their sources, for example.
		for _, sv := range subgraph.Vertices() {
			g.ConnectDependent(sv)
		}

		// Re-connect all the things that dependend on the graph
		// we just flattened. This should connect them back into the
		// correct nodes if their DependentOn() is setup correctly.
		for _, v := range dependents {
			g.ConnectDependent(v)
		}
	}

	return nil
}
func graphDotSubgraph(
	dg *dot.Graph, modName string, g *Graph, opts *GraphDotOpts, modDepth int) error {
	// Respect user-specified module depth
	if opts.MaxDepth >= 0 && modDepth > opts.MaxDepth {
		return nil
	}

	// Begin module subgraph
	var sg *dot.Subgraph
	if modDepth == 0 {
		sg = dg.AddSubgraph(modName)
	} else {
		sg = dg.AddSubgraph(modName)
		sg.Cluster = true
		sg.AddAttr("label", modName)
	}

	origins, err := graphDotFindOrigins(g)
	if err != nil {
		return err
	}

	drawableVertices := make(map[dag.Vertex]struct{})
	toDraw := make([]dag.Vertex, 0, len(g.Vertices()))
	subgraphVertices := make(map[dag.Vertex]*Graph)

	walk := func(v dag.Vertex, depth int) error {
		// We only care about nodes that yield non-empty Dot strings.
		if dn, ok := v.(GraphNodeDotter); !ok {
			return nil
		} else if dn.DotNode("fake", opts) == nil {
			return nil
		}

		drawableVertices[v] = struct{}{}
		toDraw = append(toDraw, v)

		if sn, ok := v.(GraphNodeSubgraph); ok {
			subgraphVertices[v] = sn.Subgraph()
		}
		return nil
	}

	if err := g.ReverseDepthFirstWalk(origins, walk); err != nil {
		return err
	}

	for _, v := range toDraw {
		dn := v.(GraphNodeDotter)
		nodeName := graphDotNodeName(modName, v)
		sg.AddNode(dn.DotNode(nodeName, opts))

		// Draw all the edges from this vertex to other nodes
		targets := dag.AsVertexList(g.DownEdges(v))
		for _, t := range targets {
			target := t.(dag.Vertex)
			// Only want edges where both sides are drawable.
			if _, ok := drawableVertices[target]; !ok {
				continue
			}

			if err := sg.AddEdgeBetween(
				graphDotNodeName(modName, v),
				graphDotNodeName(modName, target),
				map[string]string{}); err != nil {
				return err
			}
		}
	}

	// Recurse into any subgraphs
	for _, v := range toDraw {
		subgraph, ok := subgraphVertices[v]
		if !ok {
			continue
		}

		err := graphDotSubgraph(dg, dag.VertexName(v), subgraph, opts, modDepth+1)
		if err != nil {
			return err
		}
	}

	if opts.DrawCycles {
		colors := []string{"red", "green", "blue"}
		for ci, cycle := range g.Cycles() {
			for i, c := range cycle {
				// Catch the last wrapping edge of the cycle
				if i+1 >= len(cycle) {
					i = -1
				}
				edgeAttrs := map[string]string{
					"color":    colors[ci%len(colors)],
					"penwidth": "2.0",
				}

				if err := sg.AddEdgeBetween(
					graphDotNodeName(modName, c),
					graphDotNodeName(modName, cycle[i+1]),
					edgeAttrs); err != nil {
					return err
				}

			}
		}
	}

	return nil
}
func graphDotNodeName(modName, v dag.Vertex) string {
	return fmt.Sprintf("[%s] %s", modName, dag.VertexName(v))
}