github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/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{Variable: v}) 49 } 50 51 // Write all the provider configs out 52 for _, pc := range config.ProviderConfigs { 53 nodes = append(nodes, &GraphNodeConfigProvider{Provider: pc}) 54 } 55 56 // Write all the resources out 57 for _, r := range config.Resources { 58 nodes = append(nodes, &GraphNodeConfigResource{ 59 Resource: r, 60 Path: g.Path, 61 }) 62 } 63 64 // Write all the modules out 65 children := module.Children() 66 for _, m := range config.Modules { 67 path := make([]string, len(g.Path), len(g.Path)+1) 68 copy(path, g.Path) 69 path = append(path, m.Name) 70 71 nodes = append(nodes, &GraphNodeConfigModule{ 72 Path: path, 73 Module: m, 74 Tree: children[m.Name], 75 }) 76 } 77 78 // Write all the outputs out 79 for _, o := range config.Outputs { 80 nodes = append(nodes, &GraphNodeConfigOutput{Output: o}) 81 } 82 83 // Err is where the final error value will go if there is one 84 var err error 85 86 // Build the graph vertices 87 for _, n := range nodes { 88 g.Add(n) 89 } 90 91 // Build up the dependencies. We have to do this outside of the above 92 // loop since the nodes need to be in place for us to build the deps. 93 for _, n := range nodes { 94 if missing := g.ConnectDependent(n); len(missing) > 0 { 95 for _, m := range missing { 96 err = multierror.Append(err, fmt.Errorf( 97 "%s: missing dependency: %s", n.Name(), m)) 98 } 99 } 100 } 101 102 return err 103 } 104 105 // varNameForVar returns the VarName value for an interpolated variable. 106 // This value is compared to the VarName() value for the nodes within the 107 // graph to build the graph edges. 108 func varNameForVar(raw config.InterpolatedVariable) string { 109 switch v := raw.(type) { 110 case *config.ModuleVariable: 111 return fmt.Sprintf("module.%s.output.%s", v.Name, v.Field) 112 case *config.ResourceVariable: 113 return v.ResourceId() 114 case *config.UserVariable: 115 return fmt.Sprintf("var.%s", v.Name) 116 default: 117 return "" 118 } 119 }