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  }