github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/terraform/graph_config_node_variable.go (about) 1 package terraform 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/terraform/config" 7 "github.com/hashicorp/terraform/dag" 8 ) 9 10 // GraphNodeConfigVariable represents a Variable in the config. 11 type GraphNodeConfigVariable struct { 12 Variable *config.Variable 13 14 // Value, if non-nil, will be used to set the value of the variable 15 // during evaluation. If this is nil, evaluation will do nothing. 16 // 17 // Module is the name of the module to set the variables on. 18 Module string 19 Value *config.RawConfig 20 21 depPrefix string 22 } 23 24 func (n *GraphNodeConfigVariable) Name() string { 25 return fmt.Sprintf("var.%s", n.Variable.Name) 26 } 27 28 func (n *GraphNodeConfigVariable) ConfigType() GraphNodeConfigType { 29 return GraphNodeConfigTypeVariable 30 } 31 32 func (n *GraphNodeConfigVariable) DependableName() []string { 33 return []string{n.Name()} 34 } 35 36 func (n *GraphNodeConfigVariable) DependentOn() []string { 37 // If we don't have any value set, we don't depend on anything 38 if n.Value == nil { 39 return nil 40 } 41 42 // Get what we depend on based on our value 43 vars := n.Value.Variables 44 result := make([]string, 0, len(vars)) 45 for _, v := range vars { 46 if vn := varNameForVar(v); vn != "" { 47 result = append(result, vn) 48 } 49 } 50 51 return result 52 } 53 54 func (n *GraphNodeConfigVariable) VariableName() string { 55 return n.Variable.Name 56 } 57 58 // GraphNodeDestroyEdgeInclude impl. 59 func (n *GraphNodeConfigVariable) DestroyEdgeInclude(v dag.Vertex) bool { 60 // Only include this variable in a destroy edge if the source vertex 61 // "v" has a count dependency on this variable. 62 cv, ok := v.(GraphNodeCountDependent) 63 if !ok { 64 return false 65 } 66 67 for _, d := range cv.CountDependentOn() { 68 for _, d2 := range n.DependableName() { 69 if d == d2 { 70 return true 71 } 72 } 73 } 74 75 return false 76 } 77 78 // GraphNodeNoopPrunable 79 func (n *GraphNodeConfigVariable) Noop(opts *NoopOpts) bool { 80 // If we have no diff, always keep this in the graph. We have to do 81 // this primarily for validation: we want to validate that variable 82 // interpolations are valid even if there are no resources that 83 // depend on them. 84 if opts.Diff == nil || opts.Diff.Empty() { 85 return false 86 } 87 88 for _, v := range opts.Graph.UpEdges(opts.Vertex).List() { 89 // This is terrible, but I can't think of a better way to do this. 90 if dag.VertexName(v) == rootNodeName { 91 continue 92 } 93 94 return false 95 } 96 97 return true 98 } 99 100 // GraphNodeProxy impl. 101 func (n *GraphNodeConfigVariable) Proxy() bool { 102 return true 103 } 104 105 // GraphNodeEvalable impl. 106 func (n *GraphNodeConfigVariable) EvalTree() EvalNode { 107 // If we have no value, do nothing 108 if n.Value == nil { 109 return &EvalNoop{} 110 } 111 112 // Otherwise, interpolate the value of this variable and set it 113 // within the variables mapping. 114 var config *ResourceConfig 115 variables := make(map[string]string) 116 return &EvalSequence{ 117 Nodes: []EvalNode{ 118 &EvalInterpolate{ 119 Config: n.Value, 120 Output: &config, 121 }, 122 123 &EvalVariableBlock{ 124 Config: &config, 125 Variables: variables, 126 }, 127 128 &EvalSetVariables{ 129 Module: &n.Module, 130 Variables: variables, 131 }, 132 }, 133 } 134 } 135 136 // GraphNodeFlattenable impl. 137 func (n *GraphNodeConfigVariable) Flatten(p []string) (dag.Vertex, error) { 138 return &GraphNodeConfigVariableFlat{ 139 GraphNodeConfigVariable: n, 140 PathValue: p, 141 }, nil 142 } 143 144 type GraphNodeConfigVariableFlat struct { 145 *GraphNodeConfigVariable 146 147 PathValue []string 148 } 149 150 func (n *GraphNodeConfigVariableFlat) Name() string { 151 return fmt.Sprintf( 152 "%s.%s", modulePrefixStr(n.PathValue), n.GraphNodeConfigVariable.Name()) 153 } 154 155 func (n *GraphNodeConfigVariableFlat) DependableName() []string { 156 return []string{n.Name()} 157 } 158 159 func (n *GraphNodeConfigVariableFlat) DependentOn() []string { 160 // We only wrap the dependencies and such if we have a path that is 161 // longer than 2 elements (root, child, more). This is because when 162 // flattened, variables can point outside the graph. 163 prefix := "" 164 if len(n.PathValue) > 2 { 165 prefix = modulePrefixStr(n.PathValue[:len(n.PathValue)-1]) 166 } 167 168 return modulePrefixList( 169 n.GraphNodeConfigVariable.DependentOn(), 170 prefix) 171 } 172 173 func (n *GraphNodeConfigVariableFlat) Path() []string { 174 if len(n.PathValue) > 2 { 175 return n.PathValue[:len(n.PathValue)-1] 176 } 177 178 return nil 179 }