Alexander Belanger 5 лет назад
Родитель
Сommit
affa236c6f
2 измененных файлов с 96 добавлено и 0 удалено
  1. 68 0
      cli/cmd/test.go
  2. 28 0
      cli/cmd/test_test.go

+ 68 - 0
cli/cmd/test.go

@@ -315,3 +315,71 @@ func StreamDynamic(client dynamic.Interface, op *Operation) error {
 func init() {
 	rootCmd.AddCommand(testCmd)
 }
+
+// replace arrays and scalar values
+func CoalesceValues(base, override map[string]interface{}) map[string]interface{} {
+	for key, val := range base {
+		if oVal, ok := override[key]; ok {
+			if oVal == nil {
+				delete(override, key)
+			} else if oMapVal, ok := oVal.(map[string]interface{}); ok {
+				bMapVal, ok := val.(map[string]interface{})
+
+				if !ok {
+					continue
+				}
+
+				override[key] = mergeMaps(bMapVal, oMapVal)
+			}
+		} else {
+			override[key] = val
+		}
+	}
+
+	return override
+}
+
+func isYAMLTable(v interface{}) bool {
+	_, ok := v.(map[string]interface{})
+	return ok
+}
+
+// mergeMaps merges any number of maps together, with maps later in the slice taking
+// precedent
+func mergeMaps(maps ...map[string]interface{}) map[string]interface{} {
+	// merge bottom-up
+	if len(maps) > 2 {
+		mLen := len(maps)
+		newMaps := maps[0 : mLen-2]
+
+		// reduce length of maps by 1 and merge again
+		newMaps = append(newMaps, mergeMaps(maps[mLen-2], maps[mLen-1]))
+		return mergeMaps(newMaps...)
+	} else if len(maps) == 2 {
+		if maps[0] == nil {
+			return maps[1]
+		}
+
+		if maps[1] == nil {
+			return maps[0]
+		}
+
+		for key, map0Val := range maps[0] {
+			if map1Val, ok := maps[1][key]; ok && map1Val == nil {
+				delete(maps[1], key)
+			} else if !ok {
+				maps[1][key] = map0Val
+			} else if isYAMLTable(map0Val) {
+				if isYAMLTable(map1Val) {
+					mergeMaps(map0Val.(map[string]interface{}), map1Val.(map[string]interface{}))
+				}
+			}
+		}
+
+		return maps[1]
+	} else if len(maps) == 1 {
+		return maps[0]
+	}
+
+	return nil
+}

+ 28 - 0
cli/cmd/test_test.go

@@ -0,0 +1,28 @@
+package cmd_test
+
+import (
+	"testing"
+
+	"github.com/porter-dev/porter/cli/cmd"
+)
+
+func TestMergeMapValues(t *testing.T) {
+	map1 := map[string]interface{}{
+		"hello": "there",
+		"i":     "have",
+	}
+
+	map2 := map[string]interface{}{
+		"hello": "general",
+		"the":   "high",
+	}
+
+	map3 := map[string]interface{}{
+		"hello":  "kenobi",
+		"ground": "!",
+	}
+
+	res := cmd.MergeMapValues(map1, map2, map3)
+
+	t.Errorf("%v\n", res)
+}