github.com/rhenning/terraform@v0.8.0-beta2/terraform/graph_config_node_module.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/hashicorp/terraform/config"
     8  	"github.com/hashicorp/terraform/config/module"
     9  	"github.com/hashicorp/terraform/dag"
    10  )
    11  
    12  // GraphNodeConfigModule represents a module within the configuration graph.
    13  type GraphNodeConfigModule struct {
    14  	Path   []string
    15  	Module *config.Module
    16  	Tree   *module.Tree
    17  }
    18  
    19  func (n *GraphNodeConfigModule) ConfigType() GraphNodeConfigType {
    20  	return GraphNodeConfigTypeModule
    21  }
    22  
    23  func (n *GraphNodeConfigModule) DependableName() []string {
    24  	config := n.Tree.Config()
    25  
    26  	result := make([]string, 1, len(config.Outputs)+1)
    27  	result[0] = n.Name()
    28  	for _, o := range config.Outputs {
    29  		result = append(result, fmt.Sprintf("%s.output.%s", n.Name(), o.Name))
    30  	}
    31  
    32  	return result
    33  }
    34  
    35  func (n *GraphNodeConfigModule) DependentOn() []string {
    36  	vars := n.Module.RawConfig.Variables
    37  	result := make([]string, 0, len(vars))
    38  	for _, v := range vars {
    39  		if vn := varNameForVar(v); vn != "" {
    40  			result = append(result, vn)
    41  		}
    42  	}
    43  
    44  	return result
    45  }
    46  
    47  func (n *GraphNodeConfigModule) Name() string {
    48  	return fmt.Sprintf("module.%s", n.Module.Name)
    49  }
    50  
    51  // GraphNodeExpandable
    52  func (n *GraphNodeConfigModule) Expand(b GraphBuilder) (GraphNodeSubgraph, error) {
    53  	// Build the graph first
    54  	graph, err := b.Build(n.Path)
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  
    59  	{
    60  		// Add the destroy marker to the graph
    61  		t := &ModuleDestroyTransformerOld{}
    62  		if err := t.Transform(graph); err != nil {
    63  			return nil, err
    64  		}
    65  	}
    66  
    67  	// Build the actual subgraph node
    68  	return &graphNodeModuleExpanded{
    69  		Original:  n,
    70  		Graph:     graph,
    71  		Variables: make(map[string]interface{}),
    72  	}, nil
    73  }
    74  
    75  // GraphNodeExpandable
    76  func (n *GraphNodeConfigModule) ProvidedBy() []string {
    77  	// Build up the list of providers by simply going over our configuration
    78  	// to find the providers that are configured there as well as the
    79  	// providers that the resources use.
    80  	config := n.Tree.Config()
    81  	providers := make(map[string]struct{})
    82  	for _, p := range config.ProviderConfigs {
    83  		providers[p.Name] = struct{}{}
    84  	}
    85  	for _, r := range config.Resources {
    86  		providers[resourceProvider(r.Type, r.Provider)] = struct{}{}
    87  	}
    88  
    89  	// Turn the map into a string. This makes sure that the list is
    90  	// de-dupped since we could be going over potentially many resources.
    91  	result := make([]string, 0, len(providers))
    92  	for p, _ := range providers {
    93  		result = append(result, p)
    94  	}
    95  
    96  	return result
    97  }
    98  
    99  // graphNodeModuleExpanded represents a module where the graph has
   100  // been expanded. It stores the graph of the module as well as a reference
   101  // to the map of variables.
   102  type graphNodeModuleExpanded struct {
   103  	Original *GraphNodeConfigModule
   104  	Graph    *Graph
   105  
   106  	// Variables is a map of the input variables. This reference should
   107  	// be shared with ModuleInputTransformer in order to create a connection
   108  	// where the variables are set properly.
   109  	Variables map[string]interface{}
   110  }
   111  
   112  func (n *graphNodeModuleExpanded) Name() string {
   113  	return fmt.Sprintf("%s (expanded)", dag.VertexName(n.Original))
   114  }
   115  
   116  func (n *graphNodeModuleExpanded) ConfigType() GraphNodeConfigType {
   117  	return GraphNodeConfigTypeModule
   118  }
   119  
   120  // GraphNodeDependable
   121  func (n *graphNodeModuleExpanded) DependableName() []string {
   122  	return n.Original.DependableName()
   123  }
   124  
   125  // GraphNodeDependent
   126  func (n *graphNodeModuleExpanded) DependentOn() []string {
   127  	return n.Original.DependentOn()
   128  }
   129  
   130  // GraphNodeDotter impl.
   131  func (n *graphNodeModuleExpanded) DotNode(name string, opts *dag.DotOpts) *dag.DotNode {
   132  	return &dag.DotNode{
   133  		Name: name,
   134  		Attrs: map[string]string{
   135  			"label": dag.VertexName(n.Original),
   136  			"shape": "component",
   137  		},
   138  	}
   139  }
   140  
   141  // GraphNodeEvalable impl.
   142  func (n *graphNodeModuleExpanded) EvalTree() EvalNode {
   143  	var resourceConfig *ResourceConfig
   144  	return &EvalSequence{
   145  		Nodes: []EvalNode{
   146  			&EvalInterpolate{
   147  				Config: n.Original.Module.RawConfig,
   148  				Output: &resourceConfig,
   149  			},
   150  
   151  			&EvalVariableBlock{
   152  				Config:         &resourceConfig,
   153  				VariableValues: n.Variables,
   154  			},
   155  		},
   156  	}
   157  }
   158  
   159  // GraphNodeFlattenable impl.
   160  func (n *graphNodeModuleExpanded) FlattenGraph() *Graph {
   161  	graph := n.Subgraph().(*Graph)
   162  	input := n.Original.Module.RawConfig
   163  
   164  	// Go over each vertex and do some modifications to the graph for
   165  	// flattening. We have to skip some nodes (graphNodeModuleSkippable)
   166  	// as well as setup the variable values.
   167  	for _, v := range graph.Vertices() {
   168  		// If this is a variable, then look it up in the raw configuration.
   169  		// If it exists in the raw configuration, set the value of it.
   170  		if vn, ok := v.(*GraphNodeConfigVariable); ok && input != nil {
   171  			key := vn.VariableName()
   172  			if v, ok := input.Raw[key]; ok {
   173  				config, err := config.NewRawConfig(map[string]interface{}{
   174  					key: v,
   175  				})
   176  				if err != nil {
   177  					// This shouldn't happen because it is already in
   178  					// a RawConfig above meaning it worked once before.
   179  					panic(err)
   180  				}
   181  
   182  				// Set the variable value so it is interpolated properly.
   183  				// Also set the module so we set the value on it properly.
   184  				vn.Module = graph.Path[len(graph.Path)-1]
   185  				vn.Value = config
   186  			}
   187  		}
   188  	}
   189  
   190  	return graph
   191  }
   192  
   193  // GraphNodeSubgraph impl.
   194  func (n *graphNodeModuleExpanded) Subgraph() dag.Grapher {
   195  	return n.Graph
   196  }
   197  
   198  func modulePrefixStr(p []string) string {
   199  	parts := make([]string, 0, len(p)*2)
   200  	for _, p := range p[1:] {
   201  		parts = append(parts, "module", p)
   202  	}
   203  
   204  	return strings.Join(parts, ".")
   205  }
   206  
   207  func modulePrefixList(result []string, prefix string) []string {
   208  	if prefix != "" {
   209  		for i, v := range result {
   210  			result[i] = fmt.Sprintf("%s.%s", prefix, v)
   211  		}
   212  	}
   213  
   214  	return result
   215  }