1
0
mirror of https://github.com/rancher/os.git synced 2025-08-31 14:23:11 +00:00

Reliably merge the yaml maps data

This commit is contained in:
Darren Shepherd
2015-03-18 06:22:19 -07:00
parent 91dd56e595
commit 3756bbae90
3 changed files with 126 additions and 5 deletions

View File

@@ -1,6 +1,12 @@
package config
import "testing"
import (
"fmt"
"log"
"testing"
"github.com/rancherio/os/util"
)
import "reflect"
func TestParseCmdline(t *testing.T) {
@@ -93,3 +99,92 @@ func TestSet(t *testing.T) {
t.Fatalf("Expected %v, got %v", expected, data)
}
}
type OuterData struct {
One Data `"yaml:one"`
}
type Data struct {
Two bool `"yaml:two"`
Three bool `"yaml:three"`
}
func TestMapMerge(t *testing.T) {
one := `
one:
two: true`
two := `
one:
three: true`
data := make(map[string]map[string]bool)
yaml.Unmarshal([]byte(one), data)
yaml.Unmarshal([]byte(two), data)
if _, ok := data["one"]; !ok {
t.Fatal("one not found")
}
if !data["one"]["three"] {
t.Fatal("three not found")
}
if data["one"]["two"] {
t.Fatal("two not found")
}
data2 := &OuterData{}
yaml.Unmarshal([]byte(one), data2)
yaml.Unmarshal([]byte(two), data2)
if !data2.One.Three {
t.Fatal("three not found")
}
if !data2.One.Two {
t.Fatal("two not found")
}
}
func TestUserDocker(t *testing.T) {
config := &Config{
UserDocker: DockerConfig{
TLS: true,
},
}
bytes, err := yaml.Marshal(config)
if err != nil {
log.Fatal(err)
}
config = NewConfig()
err = yaml.Unmarshal(bytes, config)
if err != nil {
log.Fatal(err)
}
data := make(map[interface{}]interface{})
util.Convert(config, data)
fmt.Println(data)
val, ok := data["user_docker"]
if !ok {
t.Fatal("Failed to find user_docker")
}
if m, ok := val.(map[interface{}]interface{}); ok {
if v, ok := m["tls"]; ok {
if v != true {
t.Fatal("user_docker.tls is not true")
}
} else {
t.Fatal("user_docker.tls is not found")
}
} else {
t.Fatal("Bad data")
}
}

View File

@@ -62,26 +62,34 @@ func readSavedConfig(bytes []byte) (map[interface{}]interface{}, error) {
}
func readConfig(bytes []byte, files ...string) (map[interface{}]interface{}, error) {
data := make(map[interface{}]interface{})
// You can't just overlay yaml bytes on to maps, it won't merge, but instead
// just override the keys and not merge the map values.
left := make(map[interface{}]interface{})
for _, conf := range files {
content, err := readConfigFile(conf)
if err != nil {
return nil, err
}
err = yaml.Unmarshal(content, &data)
right := make(map[interface{}]interface{})
err = yaml.Unmarshal(content, &right)
if err != nil {
return nil, err
}
util.MergeMaps(left, right)
}
if bytes != nil && len(bytes) > 0 {
if err := yaml.Unmarshal(bytes, &data); err != nil {
right := make(map[interface{}]interface{})
if err := yaml.Unmarshal(bytes, &right); err != nil {
return nil, err
}
util.MergeMaps(left, right)
}
return data, nil
return left, nil
}
func readConfigFile(file string) ([]byte, error) {

View File

@@ -164,3 +164,21 @@ func Convert(from, to interface{}) error {
return yaml.Unmarshal(bytes, to)
}
func MergeMaps(left, right map[interface{}]interface{}) {
for k, v := range right {
merged := false
if existing, ok := left[k]; ok {
if rightMap, ok := v.(map[interface{}]interface{}); ok {
if leftMap, ok := existing.(map[interface{}]interface{}); ok {
merged = true
MergeMaps(leftMap, rightMap)
}
}
}
if !merged {
left[k] = v
}
}
}