Skip to content

Commit 72bcdda

Browse files
authored
chore: avoid unnecessary json marshal (#626)
* chore: avoid unnecessary json marshal Signed-off-by: Michael Crenshaw <[email protected]> * more tests Signed-off-by: Michael Crenshaw <[email protected]> * refactor test to satisfy sonarcloud Signed-off-by: Michael Crenshaw <[email protected]> --------- Signed-off-by: Michael Crenshaw <[email protected]>
1 parent df9b446 commit 72bcdda

File tree

2 files changed

+39
-25
lines changed

2 files changed

+39
-25
lines changed

pkg/diff/diff.go

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -667,22 +667,6 @@ func ThreeWayDiff(orig, config, live *unstructured.Unstructured) (*DiffResult, e
667667
return buildDiffResult(predictedLiveBytes, liveBytes), nil
668668
}
669669

670-
// stripTypeInformation strips any type information (e.g. float64 vs. int) from the unstructured
671-
// object by remarshalling the object. This is important for diffing since it will cause godiff
672-
// to report a false difference.
673-
func stripTypeInformation(un *unstructured.Unstructured) *unstructured.Unstructured {
674-
unBytes, err := json.Marshal(un)
675-
if err != nil {
676-
panic(err)
677-
}
678-
var newUn unstructured.Unstructured
679-
err = json.Unmarshal(unBytes, &newUn)
680-
if err != nil {
681-
panic(err)
682-
}
683-
return &newUn
684-
}
685-
686670
// removeNamespaceAnnotation remove the namespace and an empty annotation map from the metadata.
687671
// The namespace field is present in live (namespaced) objects, but not necessarily present in
688672
// config or last-applied. This results in a diff which we don't care about. We delete the two so
@@ -1081,11 +1065,20 @@ func toString(val interface{}) string {
10811065
// Remarshalling also strips any type information (e.g. float64 vs. int) from the unstructured
10821066
// object. This is important for diffing since it will cause godiff to report a false difference.
10831067
func remarshal(obj *unstructured.Unstructured, o options) *unstructured.Unstructured {
1084-
obj = stripTypeInformation(obj)
10851068
data, err := json.Marshal(obj)
10861069
if err != nil {
10871070
panic(err)
10881071
}
1072+
1073+
// Unmarshal again to strip type information (e.g. float64 vs. int) from the unstructured
1074+
// object. This is important for diffing since it will cause godiff to report a false difference.
1075+
var newUn unstructured.Unstructured
1076+
err = json.Unmarshal(data, &newUn)
1077+
if err != nil {
1078+
panic(err)
1079+
}
1080+
obj = &newUn
1081+
10891082
gvk := obj.GroupVersionKind()
10901083
item, err := scheme.Scheme.New(obj.GroupVersionKind())
10911084
if err != nil {

pkg/diff/diff_test.go

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,14 @@ metadata:
11271127
}
11281128

11291129
func TestRemarshalResources(t *testing.T) {
1130+
getRequests := func(un *unstructured.Unstructured) map[string]interface{} {
1131+
return un.Object["spec"].(map[string]interface{})["containers"].([]interface{})[0].(map[string]interface{})["resources"].(map[string]interface{})["requests"].(map[string]interface{})
1132+
}
1133+
1134+
setRequests := func(un *unstructured.Unstructured, requests map[string]interface{}) {
1135+
un.Object["spec"].(map[string]interface{})["containers"].([]interface{})[0].(map[string]interface{})["resources"].(map[string]interface{})["requests"] = requests
1136+
}
1137+
11301138
manifest := []byte(`
11311139
apiVersion: v1
11321140
kind: Pod
@@ -1142,14 +1150,27 @@ spec:
11421150
`)
11431151
un := unstructured.Unstructured{}
11441152
err := yaml.Unmarshal(manifest, &un)
1145-
assert.NoError(t, err)
1146-
requestsBefore := un.Object["spec"].(map[string]interface{})["containers"].([]interface{})[0].(map[string]interface{})["resources"].(map[string]interface{})["requests"].(map[string]interface{})
1147-
t.Log(requestsBefore)
1148-
newUn := remarshal(&un, applyOptions(diffOptionsForTest()))
1149-
requestsAfter := newUn.Object["spec"].(map[string]interface{})["containers"].([]interface{})[0].(map[string]interface{})["resources"].(map[string]interface{})["requests"].(map[string]interface{})
1150-
t.Log(requestsAfter)
1151-
assert.Equal(t, float64(0.2), requestsBefore["cpu"])
1152-
assert.Equal(t, "200m", requestsAfter["cpu"])
1153+
require.NoError(t, err)
1154+
1155+
testCases := []struct {
1156+
name string
1157+
cpu any
1158+
expectedCPU any
1159+
}{
1160+
{"from float", 0.2, "200m"},
1161+
{"from float64", float64(0.2), "200m"},
1162+
{"from string", "0.2", "200m"},
1163+
{"from invalid", "invalid", "invalid"},
1164+
}
1165+
1166+
for _, tc := range testCases {
1167+
t.Run(tc.name, func(t *testing.T) {
1168+
setRequests(&un, map[string]interface{}{"cpu": tc.cpu})
1169+
newUn := remarshal(&un, applyOptions(diffOptionsForTest()))
1170+
requestsAfter := getRequests(newUn)
1171+
assert.Equal(t, tc.expectedCPU, requestsAfter["cpu"])
1172+
})
1173+
}
11531174
}
11541175

11551176
func ExampleDiff() {

0 commit comments

Comments
 (0)