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 }