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