github.com/hashicorp/terraform-plugin-sdk@v1.17.2/terraform/transform_output.go (about) 1 package terraform 2 3 import ( 4 "log" 5 6 "github.com/hashicorp/terraform-plugin-sdk/internal/configs" 7 "github.com/hashicorp/terraform-plugin-sdk/internal/dag" 8 ) 9 10 // OutputTransformer is a GraphTransformer that adds all the outputs 11 // in the configuration to the graph. 12 // 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 { 17 Config *configs.Config 18 } 19 20 func (t *OutputTransformer) Transform(g *Graph) error { 21 return t.transform(g, t.Config) 22 } 23 24 func (t *OutputTransformer) transform(g *Graph, c *configs.Config) error { 25 // If we have no config then there can be no outputs. 26 if c == nil { 27 return nil 28 } 29 30 // Transform all the children. We must do this first because 31 // we can reference module outputs and they must show up in the 32 // reference map. 33 for _, cc := range c.Children { 34 if err := t.transform(g, cc); err != nil { 35 return err 36 } 37 } 38 39 // Our addressing system distinguishes between modules and module instances, 40 // but we're not yet ready to make that distinction here (since we don't 41 // support "count"/"for_each" on modules) and so we just do a naive 42 // transform of the module path into a module instance path, assuming that 43 // no keys are in use. This should be removed when "count" and "for_each" 44 // are implemented for modules. 45 path := c.Path.UnkeyedInstanceShim() 46 47 for _, o := range c.Module.Outputs { 48 addr := path.OutputValue(o.Name) 49 node := &NodeApplyableOutput{ 50 Addr: addr, 51 Config: o, 52 } 53 g.Add(node) 54 } 55 56 return nil 57 } 58 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 { 63 } 64 65 func (t *DestroyOutputTransformer) Transform(g *Graph) error { 66 for _, v := range g.Vertices() { 67 output, ok := v.(*NodeApplyableOutput) 68 if !ok { 69 continue 70 } 71 72 // create the destroy node for this output 73 node := &NodeDestroyableOutput{ 74 Addr: output.Addr, 75 Config: output.Config, 76 } 77 78 log.Printf("[TRACE] creating %s", node.Name()) 79 g.Add(node) 80 81 deps, err := g.Descendents(v) 82 if err != nil { 83 return err 84 } 85 86 // the destroy node must depend on the eval node 87 deps.Add(v) 88 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)) 92 } 93 } 94 return nil 95 }