Skip to content

Commit 7a9cc98

Browse files
author
gentele
committed
fix issue #314 and improve config split, merge and save
1 parent 9b1061d commit 7a9cc98

5 files changed

Lines changed: 121 additions & 26 deletions

File tree

cmd/init.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ func (cmd *InitCmd) Run(cobraCmd *cobra.Command, args []string) {
152152
Auth: &v1.RegistryAuth{},
153153
},
154154
},
155-
})
155+
}, false)
156156

157157
imageMap := *config.Images
158158
cmd.defaultImage = imageMap["default"]

pkg/devspace/config/configutil/get.go

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package configutil
22

33
import (
4+
"fmt"
45
"os"
56
"sync"
67

@@ -89,8 +90,44 @@ func GetConfig() *v1.Config {
8990
//ignore error as overwrite.yaml is optional
9091
loadConfig(overwriteConfig, OverwriteConfigPath)
9192

92-
Merge(&config, configRaw)
93-
Merge(&config, overwriteConfig)
93+
configImages := *config.Images
94+
configImageDefault := configImages["default"]
95+
configRawImages := *configRaw.Images
96+
configRawImageDefault := configRawImages["default"]
97+
98+
fmt.Println(configRawImageDefault.Name)
99+
100+
fmt.Println("")
101+
fmt.Println("merge config")
102+
103+
Merge(&config, configRaw, false)
104+
105+
configImages = *config.Images
106+
configImageDefault = configImages["default"]
107+
configRawImages = *configRaw.Images
108+
configRawImageDefault = configRawImages["default"]
109+
110+
fmt.Println(configImageDefault.Name)
111+
fmt.Println(configRawImageDefault.Name)
112+
113+
fmt.Println("")
114+
fmt.Println("merge overwrite config")
115+
116+
Merge(&config, overwriteConfig, true)
117+
118+
configImages = *config.Images
119+
configImageDefault = configImages["default"]
120+
configRawImages = *configRaw.Images
121+
configRawImageDefault = configRawImages["default"]
122+
123+
fmt.Println(configImageDefault.Name)
124+
fmt.Println(configRawImageDefault.Name)
125+
126+
configOverwriteImages := *configRaw.Images
127+
configOverwriteImageDefault := configOverwriteImages["default"]
128+
129+
fmt.Println(configOverwriteImageDefault.Name)
130+
fmt.Println(*configOverwriteImageDefault.Name)
94131

95132
SetDefaultsOnce()
96133
})

pkg/devspace/config/configutil/merge.go

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package configutil
33
import (
44
"reflect"
55
"unsafe"
6+
7+
"gopkg.in/yaml.v2"
68
)
79

810
type pointerInterface struct {
@@ -12,7 +14,7 @@ type pointerInterface struct {
1214
// Merge deeply merges two objects
1315
// object MUST be a pointer of a pointer
1416
// overwriteObject MUST be a pointer
15-
func Merge(object interface{}, overwriteObject interface{}) {
17+
func Merge(object interface{}, overwriteObject interface{}, unifyPointers bool) {
1618
overwriteObjectRef := reflect.ValueOf(overwriteObject)
1719

1820
if !overwriteObjectRef.IsNil() {
@@ -21,6 +23,13 @@ func Merge(object interface{}, overwriteObject interface{}) {
2123
}
2224
objectPointerReal := reflect.ValueOf(object).Elem().Interface()
2325
overwriteObject := overwriteObjectRef.Interface()
26+
27+
if !unifyPointers {
28+
overwriteObject = deepCopy(overwriteObject)
29+
30+
// ensure deepCopy only runs once
31+
unifyPointers = true
32+
}
2433
overwriteObjectType := reflect.TypeOf(overwriteObject)
2534
overwriteObjectKind := overwriteObjectType.Kind()
2635
objectPointerRef := reflect.ValueOf(objectPointerReal)
@@ -53,10 +62,10 @@ func Merge(object interface{}, overwriteObject interface{}) {
5362
overwriteValue := getMapValue(overwriteObject, key, genericPointerType)
5463
valuePointerRef := objectRef.MapIndex(keyRef)
5564

56-
if isZero(valuePointerRef) == false {
65+
if isZero(valuePointerRef) == false && !isTrivialDataType(valuePointerRef) {
5766
valuePointer := valuePointerRef.Interface()
5867

59-
Merge(&valuePointer, overwriteValue)
68+
Merge(&valuePointer, overwriteValue, unifyPointers)
6069
} else {
6170
keyRef := reflect.ValueOf(key)
6271
overwriteValueRef := reflect.ValueOf(overwriteValue)
@@ -68,18 +77,17 @@ func Merge(object interface{}, overwriteObject interface{}) {
6877
case reflect.Struct:
6978
for i := 0; i < overwriteObjectRef.NumField(); i++ {
7079
overwriteValueRef := overwriteObjectRef.Field(i)
71-
overwriteValuePointerRef := reflect.ValueOf(overwriteValueRef.Interface())
7280

73-
if !overwriteValuePointerRef.IsNil() {
81+
if !overwriteValueRef.IsNil() {
7482
overwriteValue := overwriteValueRef.Interface()
7583
valuePointerRef := objectRef.Field(i)
7684

77-
if valuePointerRef.IsNil() {
78-
valuePointerRef.Set(reflect.ValueOf(overwriteValue))
85+
if valuePointerRef.IsNil() || isTrivialDataType(valuePointerRef) {
86+
valuePointerRef.Set(overwriteValueRef)
7987
} else {
8088
valuePointer := valuePointerRef.Interface()
8189

82-
Merge(&valuePointer, overwriteValue)
90+
Merge(&valuePointer, overwriteValue, unifyPointers)
8391
}
8492
}
8593
}
@@ -91,3 +99,32 @@ func Merge(object interface{}, overwriteObject interface{}) {
9199
}
92100
}
93101
}
102+
103+
func isTrivialDataType(value reflect.Value) bool {
104+
valueType := value.Type()
105+
106+
if valueType.Kind() == reflect.Ptr {
107+
valueType = valueType.Elem()
108+
}
109+
110+
switch valueType.Kind() {
111+
case reflect.Slice:
112+
return false
113+
case reflect.Map:
114+
return false
115+
case reflect.Struct:
116+
return false
117+
}
118+
return true
119+
}
120+
121+
func deepCopy(from interface{}) interface{} {
122+
yamlData, _ := yaml.Marshal(from)
123+
objectType := reflect.TypeOf(from)
124+
125+
copy := reflect.New(objectType).Interface()
126+
127+
yaml.Unmarshal(yamlData, copy)
128+
129+
return copy
130+
}

pkg/devspace/config/configutil/save.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ func SaveConfig() error {
1616
// default and overwrite values
1717
configToIgnore := makeConfig()
1818

19-
Merge(&configToIgnore, defaultConfig)
20-
Merge(&configToIgnore, overwriteConfig)
19+
Merge(&configToIgnore, defaultConfig, true)
20+
Merge(&configToIgnore, overwriteConfig, true)
2121

2222
// generates config without default and overwrite values
2323
configMapRaw, _, err := splitConfigs(config, configRaw, configToIgnore)

pkg/devspace/config/configutil/split.go

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ func splitConfigs(config interface{}, configRaw interface{}, overwriteConfig int
142142
fieldRaw := objectRawValueRef.Field(i).Elem()
143143
overwriteField := overwriteValueRef.Field(i).Elem()
144144

145-
fieldValue := field.Interface()
145+
fieldValue := reflect.New(fieldType).Interface()
146146
fieldRawValue := reflect.New(fieldType).Interface()
147147
overwriteFieldValue := reflect.New(fieldType).Interface()
148148

@@ -151,6 +151,7 @@ func splitConfigs(config interface{}, configRaw interface{}, overwriteConfig int
151151
isFieldRawNil := true
152152

153153
if !isZero(field) {
154+
fieldValue = field.Elem().Interface()
154155
isFieldNil = false
155156
}
156157

@@ -166,20 +167,14 @@ func splitConfigs(config interface{}, configRaw interface{}, overwriteConfig int
166167
var fieldValueClean, overwriteFieldValueClean interface{}
167168
var err error
168169

169-
fieldKind := fieldType.Kind()
170-
171-
if fieldKind == reflect.Map || fieldKind == reflect.Slice || fieldKind == reflect.Struct {
172-
fieldValueClean, overwriteFieldValueClean, err = splitConfigs(
173-
fieldValue,
174-
fieldRawValue,
175-
overwriteFieldValue,
176-
)
170+
if isTrivialDataType(field) {
171+
saveField := ((!isFieldNil && !saveOverwriteField) || !isFieldRawNil)
177172

178-
if err != nil {
179-
return nil, nil, err
173+
if saveField && saveOverwriteField {
174+
if isTrivialOverwrite(fieldValue, overwriteFieldValue, fieldRawValue) {
175+
fieldValue = fieldRawValue
176+
}
180177
}
181-
} else {
182-
saveField := ((!isFieldNil && !saveOverwriteField) || !isFieldRawNil)
183178

184179
if saveField {
185180
fieldValueClean = fieldValue
@@ -188,6 +183,16 @@ func splitConfigs(config interface{}, configRaw interface{}, overwriteConfig int
188183
if saveOverwriteField {
189184
overwriteFieldValueClean = overwriteFieldValue
190185
}
186+
} else {
187+
fieldValueClean, overwriteFieldValueClean, err = splitConfigs(
188+
fieldValue,
189+
fieldRawValue,
190+
overwriteFieldValue,
191+
)
192+
193+
if err != nil {
194+
return nil, nil, err
195+
}
191196
}
192197

193198
if fieldValueClean != nil {
@@ -212,6 +217,10 @@ func splitConfigs(config interface{}, configRaw interface{}, overwriteConfig int
212217
saveOverwriteValue := !isOverwriteObjectNil
213218
saveValue := ((!isObjectNil && !saveOverwriteValue) || !isObjectRawNil)
214219

220+
if saveValue && saveOverwriteValue {
221+
saveValue = !isTrivialOverwrite(objectValueRef, overwriteObject, objectRawValue)
222+
}
223+
215224
//TODO: Determine overwritten values and set objectValue accordingly
216225

217226
if saveValue && saveOverwriteValue {
@@ -225,6 +234,18 @@ func splitConfigs(config interface{}, configRaw interface{}, overwriteConfig int
225234
}
226235
}
227236

237+
func isTrivialOverwrite(objectValue, overwriteValue, objectRawValue interface{}) bool {
238+
objectValueRef := reflect.ValueOf(objectValue)
239+
240+
if isTrivialDataType(objectValueRef) {
241+
if reflect.DeepEqual(objectValue, overwriteValue) && !reflect.DeepEqual(objectValue, objectRawValue) {
242+
// do not save the value if it is equal to the overwriteValue and is different than rawValue
243+
return true
244+
}
245+
}
246+
return false
247+
}
248+
228249
func getMapValue(valueMap interface{}, key interface{}, refType reflect.Type) interface{} {
229250
valueMapValue, _ := getPointerValue(valueMap)
230251
mapRef := reflect.ValueOf(valueMapValue)

0 commit comments

Comments
 (0)