mirror of
https://github.com/rancher/os.git
synced 2025-09-03 07:44:21 +00:00
Reliably merge the yaml maps data
This commit is contained in:
@@ -1,6 +1,12 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rancherio/os/util"
|
||||||
|
)
|
||||||
import "reflect"
|
import "reflect"
|
||||||
|
|
||||||
func TestParseCmdline(t *testing.T) {
|
func TestParseCmdline(t *testing.T) {
|
||||||
@@ -93,3 +99,92 @@ func TestSet(t *testing.T) {
|
|||||||
t.Fatalf("Expected %v, got %v", expected, data)
|
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) {
|
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 {
|
for _, conf := range files {
|
||||||
content, err := readConfigFile(conf)
|
content, err := readConfigFile(conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = yaml.Unmarshal(content, &data)
|
right := make(map[interface{}]interface{})
|
||||||
|
err = yaml.Unmarshal(content, &right)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
util.MergeMaps(left, right)
|
||||||
}
|
}
|
||||||
|
|
||||||
if bytes != nil && len(bytes) > 0 {
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
util.MergeMaps(left, right)
|
||||||
}
|
}
|
||||||
|
|
||||||
return data, nil
|
return left, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readConfigFile(file string) ([]byte, error) {
|
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)
|
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