github.com/paybyphone/terraform@v0.9.5-0.20170613192930-9706042ddd51/terraform/transform_module_variable.go (about) 1 package terraform 2 3 import ( 4 "log" 5 6 "github.com/hashicorp/terraform/config" 7 "github.com/hashicorp/terraform/config/module" 8 "github.com/hashicorp/terraform/dag" 9 ) 10 11 // ModuleVariableTransformer is a GraphTransformer that adds all the variables 12 // in the configuration to the graph. 13 // 14 // This only adds variables that are referenced by other things in the graph. 15 // If a module variable is not referenced, it won't be added to the graph. 16 type ModuleVariableTransformer struct { 17 Module *module.Tree 18 19 DisablePrune bool // True if pruning unreferenced should be disabled 20 } 21 22 func (t *ModuleVariableTransformer) Transform(g *Graph) error { 23 return t.transform(g, nil, t.Module) 24 } 25 26 func (t *ModuleVariableTransformer) transform(g *Graph, parent, m *module.Tree) error { 27 // If no config, no variables 28 if m == nil { 29 return nil 30 } 31 32 // Transform all the children. This must be done BEFORE the transform 33 // above since child module variables can reference parent module variables. 34 for _, c := range m.Children() { 35 if err := t.transform(g, m, c); err != nil { 36 return err 37 } 38 } 39 40 // If we have a parent, we can determine if a module variable is being 41 // used, so we transform this. 42 if parent != nil { 43 if err := t.transformSingle(g, parent, m); err != nil { 44 return err 45 } 46 } 47 48 return nil 49 } 50 51 func (t *ModuleVariableTransformer) transformSingle(g *Graph, parent, m *module.Tree) error { 52 // If we have no vars, we're done! 53 vars := m.Config().Variables 54 if len(vars) == 0 { 55 log.Printf("[TRACE] Module %#v has no variables, skipping.", m.Path()) 56 return nil 57 } 58 59 // Look for usage of this module 60 var mod *config.Module 61 for _, modUse := range parent.Config().Modules { 62 if modUse.Name == m.Name() { 63 mod = modUse 64 break 65 } 66 } 67 if mod == nil { 68 log.Printf("[INFO] Module %#v not used, not adding variables", m.Path()) 69 return nil 70 } 71 72 // Build the reference map so we can determine if we're referencing things. 73 refMap := NewReferenceMap(g.Vertices()) 74 75 // Add all variables here 76 for _, v := range vars { 77 // Determine the value of the variable. If it isn't in the 78 // configuration then it was never set and that's not a problem. 79 var value *config.RawConfig 80 if raw, ok := mod.RawConfig.Raw[v.Name]; ok { 81 var err error 82 value, err = config.NewRawConfig(map[string]interface{}{ 83 v.Name: raw, 84 }) 85 if err != nil { 86 // This shouldn't happen because it is already in 87 // a RawConfig above meaning it worked once before. 88 panic(err) 89 } 90 } 91 92 // Build the node. 93 // 94 // NOTE: For now this is just an "applyable" variable. As we build 95 // new graph builders for the other operations I suspect we'll 96 // find a way to parameterize this, require new transforms, etc. 97 node := &NodeApplyableModuleVariable{ 98 PathValue: normalizeModulePath(m.Path()), 99 Config: v, 100 Value: value, 101 Module: t.Module, 102 } 103 104 if !t.DisablePrune { 105 // If the node is not referenced by anything, then we don't need 106 // to include it since it won't be used. 107 if matches := refMap.ReferencedBy(node); len(matches) == 0 { 108 log.Printf( 109 "[INFO] Not including %q in graph, nothing depends on it", 110 dag.VertexName(node)) 111 continue 112 } 113 } 114 115 // Add it! 116 g.Add(node) 117 } 118 119 return nil 120 }