github.com/tomaszheflik/terraform@v0.7.3-0.20160827060421-32f990b41594/terraform/transform_config.go (about)

     1  package terraform
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"github.com/hashicorp/go-multierror"
     8  	"github.com/hashicorp/terraform/config"
     9  	"github.com/hashicorp/terraform/config/module"
    10  )
    11  
    12  // ConfigTransformer is a GraphTransformer that adds the configuration
    13  // to the graph. The module used to configure this transformer must be
    14  // the root module. We'll look up the child module by the Path in the
    15  // Graph.
    16  type ConfigTransformer struct {
    17  	Module *module.Tree
    18  }
    19  
    20  func (t *ConfigTransformer) Transform(g *Graph) error {
    21  	// A module is required and also must be completely loaded.
    22  	if t.Module == nil {
    23  		return errors.New("module must not be nil")
    24  	}
    25  	if !t.Module.Loaded() {
    26  		return errors.New("module must be loaded")
    27  	}
    28  
    29  	// Get the module we care about
    30  	module := t.Module.Child(g.Path[1:])
    31  	if module == nil {
    32  		return nil
    33  	}
    34  
    35  	// Get the configuration for this module
    36  	config := module.Config()
    37  
    38  	// Create the node list we'll use for the graph
    39  	nodes := make([]graphNodeConfig, 0,
    40  		(len(config.Variables)+
    41  			len(config.ProviderConfigs)+
    42  			len(config.Modules)+
    43  			len(config.Resources)+
    44  			len(config.Outputs))*2)
    45  
    46  	// Write all the variables out
    47  	for _, v := range config.Variables {
    48  		nodes = append(nodes, &GraphNodeConfigVariable{
    49  			Variable:   v,
    50  			ModuleTree: t.Module,
    51  			ModulePath: g.Path,
    52  		})
    53  	}
    54  
    55  	// Write all the provider configs out
    56  	for _, pc := range config.ProviderConfigs {
    57  		nodes = append(nodes, &GraphNodeConfigProvider{Provider: pc})
    58  	}
    59  
    60  	// Write all the resources out
    61  	for _, r := range config.Resources {
    62  		nodes = append(nodes, &GraphNodeConfigResource{
    63  			Resource: r,
    64  			Path:     g.Path,
    65  		})
    66  	}
    67  
    68  	// Write all the modules out
    69  	children := module.Children()
    70  	for _, m := range config.Modules {
    71  		path := make([]string, len(g.Path), len(g.Path)+1)
    72  		copy(path, g.Path)
    73  		path = append(path, m.Name)
    74  
    75  		nodes = append(nodes, &GraphNodeConfigModule{
    76  			Path:   path,
    77  			Module: m,
    78  			Tree:   children[m.Name],
    79  		})
    80  	}
    81  
    82  	// Write all the outputs out
    83  	for _, o := range config.Outputs {
    84  		nodes = append(nodes, &GraphNodeConfigOutput{Output: o})
    85  	}
    86  
    87  	// Err is where the final error value will go if there is one
    88  	var err error
    89  
    90  	// Build the graph vertices
    91  	for _, n := range nodes {
    92  		g.Add(n)
    93  	}
    94  
    95  	// Build up the dependencies. We have to do this outside of the above
    96  	// loop since the nodes need to be in place for us to build the deps.
    97  	for _, n := range nodes {
    98  		if missing := g.ConnectDependent(n); len(missing) > 0 {
    99  			for _, m := range missing {
   100  				err = multierror.Append(err, fmt.Errorf(
   101  					"%s: missing dependency: %s", n.Name(), m))
   102  			}
   103  		}
   104  	}
   105  
   106  	return err
   107  }
   108  
   109  // varNameForVar returns the VarName value for an interpolated variable.
   110  // This value is compared to the VarName() value for the nodes within the
   111  // graph to build the graph edges.
   112  func varNameForVar(raw config.InterpolatedVariable) string {
   113  	switch v := raw.(type) {
   114  	case *config.ModuleVariable:
   115  		return fmt.Sprintf("module.%s.output.%s", v.Name, v.Field)
   116  	case *config.ResourceVariable:
   117  		return v.ResourceId()
   118  	case *config.UserVariable:
   119  		return fmt.Sprintf("var.%s", v.Name)
   120  	default:
   121  		return ""
   122  	}
   123  }