terraform/config/config_tree.go

88 lines
2.0 KiB
Go
Raw Normal View History

package config
2014-05-24 01:25:54 +02:00
import (
"fmt"
)
// configTree represents a tree of configurations where the root is the
// first file and its children are the configurations it has imported.
type configTree struct {
Path string
Config *Config
Children []*configTree
}
// Flatten flattens the entire tree down to a single merged Config
// structure.
func (t *configTree) Flatten() (*Config, error) {
2014-05-24 01:09:41 +02:00
// No children is easy: we're already merged!
if len(t.Children) == 0 {
return t.Config, nil
}
// Depth-first, merge all the children first.
childConfigs := make([]*Config, len(t.Children))
for i, ct := range t.Children {
c, err := ct.Flatten()
if err != nil {
return nil, err
}
childConfigs[i] = c
}
// Merge all the children in order
config := childConfigs[0]
childConfigs = childConfigs[1:]
for _, config2 := range childConfigs {
var err error
config, err = mergeConfig(config, config2)
if err != nil {
return nil, err
}
}
// Merge the final merged child config with our own
return mergeConfig(config, t.Config)
}
func mergeConfig(c1, c2 *Config) (*Config, error) {
c := new(Config)
// Merge variables: Variable merging is quite simple. Set fields in
// later set variables override those earlier.
c.Variables = c1.Variables
for k, v2 := range c2.Variables {
v1, ok := c.Variables[k]
if ok {
if v2.Default == "" {
v2.Default = v1.Default
}
if v2.Description == "" {
v2.Description = v1.Description
}
}
c.Variables[k] = v2
}
2014-05-24 01:25:54 +02:00
// Merge resources: If they collide, we just take the latest one
// for now. In the future, we might provide smarter merge functionality.
2014-05-24 22:57:51 +02:00
resources := make(map[string]*Resource)
2014-05-24 01:25:54 +02:00
for _, r := range c1.Resources {
id := fmt.Sprintf("%s[%s]", r.Type, r.Name)
resources[id] = r
}
for _, r := range c2.Resources {
id := fmt.Sprintf("%s[%s]", r.Type, r.Name)
resources[id] = r
}
2014-05-24 22:57:51 +02:00
c.Resources = make([]*Resource, 0, len(resources))
2014-05-24 01:25:54 +02:00
for _, r := range resources {
c.Resources = append(c.Resources, r)
}
2014-05-24 01:09:41 +02:00
return c, nil
}