9 "github.com/hashicorp/terraform/config"
10 "github.com/hashicorp/terraform/config/module"
11 "github.com/hashicorp/terraform/dag"
14 // ConfigTransformer is a GraphTransformer that adds all the resources
15 // from the configuration to the graph.
17 // The module used to configure this transformer must be the root module.
19 // Only resources are added to the graph. Variables, outputs, and
20 // providers must be added via other transforms.
22 // Unlike ConfigTransformerOld, this transformer creates a graph with
23 // all resources including module resources, rather than creating module
24 // nodes that are then "flattened".
25 type ConfigTransformer struct {
26 Concrete ConcreteResourceNodeFunc
28 // Module is the module to add resources from.
31 // Unique will only add resources that aren't already present in the graph.
34 // Mode will only add resources that match the given mode
36 Mode config.ResourceMode
39 uniqueMap map[string]struct{}
42 func (t *ConfigTransformer) Transform(g *Graph) error {
43 // Lock since we use some internal state
47 // If no module is given, we don't do anything
52 // If the module isn't loaded, that is simply an error
53 if !t.Module.Loaded() {
54 return errors.New("module must be loaded for ConfigTransformer")
57 // Reset the uniqueness map. If we're tracking uniques, then populate
59 t.uniqueMap = make(map[string]struct{})
60 defer func() { t.uniqueMap = nil }()
62 for _, v := range g.Vertices() {
63 if rn, ok := v.(GraphNodeResource); ok {
64 t.uniqueMap[rn.ResourceAddr().String()] = struct{}{}
69 // Start the transformation process
70 return t.transform(g, t.Module)
73 func (t *ConfigTransformer) transform(g *Graph, m *module.Tree) error {
74 // If no config, do nothing
80 if err := t.transformSingle(g, m); err != nil {
84 // Transform all the children.
85 for _, c := range m.Children() {
86 if err := t.transform(g, c); err != nil {
94 func (t *ConfigTransformer) transformSingle(g *Graph, m *module.Tree) error {
95 log.Printf("[TRACE] ConfigTransformer: Starting for path: %v", m.Path())
97 // Get the configuration for this module
100 // Build the path we're at
103 // Write all the resources out
104 for _, r := range conf.Resources {
105 // Build the resource address
106 addr, err := parseResourceAddressConfig(r)
109 "Error parsing config address, this is a bug: %#v", r))
113 // If this is already in our uniqueness map, don't add it again
114 if _, ok := t.uniqueMap[addr.String()]; ok {
118 // Remove non-matching modes
119 if t.ModeFilter && addr.Mode != t.Mode {
123 // Build the abstract node and the concrete one
124 abstract := &NodeAbstractResource{Addr: addr}
125 var node dag.Vertex = abstract
126 if f := t.Concrete; f != nil {
130 // Add it to the graph