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:
@@ -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")
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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) {
|
||||
|
18
util/util.go
18
util/util.go
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user