6 "github.com/hashicorp/terraform/config/module"
7 "github.com/hashicorp/terraform/dag"
10 // OutputTransformer is a GraphTransformer that adds all the outputs
11 // in the configuration to the graph.
13 // This is done for the apply graph builder even if dependent nodes
14 // aren't changing since there is no downside: the state will be available
15 // even if the dependent items aren't changing.
16 type OutputTransformer struct {
20 func (t *OutputTransformer) Transform(g *Graph) error {
21 return t.transform(g, t.Module)
24 func (t *OutputTransformer) transform(g *Graph, m *module.Tree) error {
25 // If no config, no outputs
30 // Transform all the children. We must do this first because
31 // we can reference module outputs and they must show up in the
33 for _, c := range m.Children() {
34 if err := t.transform(g, c); err != nil {
39 // If we have no outputs, we're done!
40 os := m.Config().Outputs
45 // Add all outputs here
46 for _, o := range os {
47 node := &NodeApplyableOutput{
48 PathValue: normalizeModulePath(m.Path()),
59 // DestroyOutputTransformer is a GraphTransformer that adds nodes to delete
60 // outputs during destroy. We need to do this to ensure that no stale outputs
61 // are ever left in the state.
62 type DestroyOutputTransformer struct {
65 func (t *DestroyOutputTransformer) Transform(g *Graph) error {
66 for _, v := range g.Vertices() {
67 output, ok := v.(*NodeApplyableOutput)
72 // create the destroy node for this output
73 node := &NodeDestroyableOutput{
74 PathValue: output.PathValue,
75 Config: output.Config,
78 log.Printf("[TRACE] creating %s", node.Name())
81 deps, err := g.Descendents(v)
86 // the destroy node must depend on the eval node
89 for _, d := range deps.List() {
90 log.Printf("[TRACE] %s depends on %s", node.Name(), dag.VertexName(d))
91 g.Connect(dag.BasicEdge(node, d))