Skip to content

Commit

Permalink
config: make Merge an exported func
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchellh committed Jul 19, 2014
1 parent 9cd1018 commit 3d67c96
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 67 deletions.
68 changes: 2 additions & 66 deletions config/config_tree.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package config

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 {
Expand Down Expand Up @@ -36,72 +32,12 @@ func (t *configTree) Flatten() (*Config, error) {
childConfigs = childConfigs[1:]
for _, config2 := range childConfigs {
var err error
config, err = mergeConfig(config, config2)
config, err = Merge(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
}

// Merge outputs: If they collide, just take the latest one for now. In
// the future, we might provide smarter merge functionality.
c.Outputs = make(map[string]*Output)
for k, v := range c1.Outputs {
c.Outputs[k] = v
}
for k, v := range c2.Outputs {
c.Outputs[k] = v
}

// Merge provider configs: If they collide, we just take the latest one
// for now. In the future, we might provide smarter merge functionality.
c.ProviderConfigs = make(map[string]*ProviderConfig)
for k, v := range c1.ProviderConfigs {
c.ProviderConfigs[k] = v
}
for k, v := range c2.ProviderConfigs {
c.ProviderConfigs[k] = v
}

// Merge resources: If they collide, we just take the latest one
// for now. In the future, we might provide smarter merge functionality.
resources := make(map[string]*Resource)
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
}

c.Resources = make([]*Resource, 0, len(resources))
for _, r := range resources {
c.Resources = append(c.Resources, r)
}

return c, nil
return Merge(config, t.Config)
}
2 changes: 1 addition & 1 deletion config/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func LoadDir(path string) (*Config, error) {
}

if result != nil {
result, err = mergeConfig(result, c)
result, err = Merge(result, c)
if err != nil {
return nil, err
}
Expand Down
65 changes: 65 additions & 0 deletions config/merge.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package config

import (
"fmt"
)

func Merge(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
}

// Merge outputs: If they collide, just take the latest one for now. In
// the future, we might provide smarter merge functionality.
c.Outputs = make(map[string]*Output)
for k, v := range c1.Outputs {
c.Outputs[k] = v
}
for k, v := range c2.Outputs {
c.Outputs[k] = v
}

// Merge provider configs: If they collide, we just take the latest one
// for now. In the future, we might provide smarter merge functionality.
c.ProviderConfigs = make(map[string]*ProviderConfig)
for k, v := range c1.ProviderConfigs {
c.ProviderConfigs[k] = v
}
for k, v := range c2.ProviderConfigs {
c.ProviderConfigs[k] = v
}

// Merge resources: If they collide, we just take the latest one
// for now. In the future, we might provide smarter merge functionality.
resources := make(map[string]*Resource)
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
}

c.Resources = make([]*Resource, 0, len(resources))
for _, r := range resources {
c.Resources = append(c.Resources, r)
}

return c, nil
}

0 comments on commit 3d67c96

Please sign in to comment.