mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 03:41:45 +00:00
Merge pull request #41043 from soltysh/issue20208
Automatic merge from submit-queue (batch tested with PRs 41043, 39058, 41021, 41603, 41414) Allow setting replace patchStrategy for structs **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #20208 @liggitt and @ymqytw ptal, you were in the original issue
This commit is contained in:
commit
4bae7f18a5
@ -158,11 +158,18 @@ func diffMaps(original, modified map[string]interface{}, t reflect.Type, ignoreC
|
|||||||
switch originalValueTyped := originalValue.(type) {
|
switch originalValueTyped := originalValue.(type) {
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
modifiedValueTyped := modifiedValue.(map[string]interface{})
|
modifiedValueTyped := modifiedValue.(map[string]interface{})
|
||||||
fieldType, _, _, err := forkedjson.LookupPatchMetadata(t, key)
|
fieldType, fieldPatchStrategy, _, err := forkedjson.LookupPatchMetadata(t, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if fieldPatchStrategy == replaceDirective {
|
||||||
|
if !ignoreChangesAndAdditions {
|
||||||
|
patch[key] = modifiedValue
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
patchValue, err := diffMaps(originalValueTyped, modifiedValueTyped, fieldType, ignoreChangesAndAdditions, ignoreDeletions)
|
patchValue, err := diffMaps(originalValueTyped, modifiedValueTyped, fieldType, ignoreChangesAndAdditions, ignoreDeletions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -1026,6 +1033,10 @@ func mergingMapFieldsHaveConflicts(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if fieldPatchStrategy == replaceDirective {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Check the individual keys.
|
// Check the individual keys.
|
||||||
return mapsHaveConflicts(leftType, rightType, fieldType)
|
return mapsHaveConflicts(leftType, rightType, fieldType)
|
||||||
default:
|
default:
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/mergepatch"
|
"k8s.io/apimachinery/pkg/util/mergepatch"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -92,6 +93,7 @@ type MergeItem struct {
|
|||||||
NonMergingIntList []int
|
NonMergingIntList []int
|
||||||
MergeItemPtr *MergeItem `patchStrategy:"merge" patchMergeKey:"name"`
|
MergeItemPtr *MergeItem `patchStrategy:"merge" patchMergeKey:"name"`
|
||||||
SimpleMap map[string]string
|
SimpleMap map[string]string
|
||||||
|
ReplacingItem runtime.RawExtension `patchStrategy:"replace"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var mergeItem MergeItem
|
var mergeItem MergeItem
|
||||||
@ -2366,3 +2368,260 @@ func TestNumberConversion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var replaceRawExtensionPatchTestCases = []StrategicMergePatchRawTestCase{
|
||||||
|
{
|
||||||
|
Description: "replace RawExtension field, rest unchanched",
|
||||||
|
StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
|
||||||
|
Original: []byte(`
|
||||||
|
name: my-object
|
||||||
|
value: some-value
|
||||||
|
other: current-other
|
||||||
|
replacingItem:
|
||||||
|
Some: Generic
|
||||||
|
Yaml: Inside
|
||||||
|
The: RawExtension
|
||||||
|
Field: Period
|
||||||
|
`),
|
||||||
|
Current: []byte(`
|
||||||
|
name: my-object
|
||||||
|
value: some-value
|
||||||
|
other: current-other
|
||||||
|
merginglist:
|
||||||
|
- name: 1
|
||||||
|
- name: 2
|
||||||
|
- name: 3
|
||||||
|
replacingItem:
|
||||||
|
Some: Generic
|
||||||
|
Yaml: Inside
|
||||||
|
The: RawExtension
|
||||||
|
Field: Period
|
||||||
|
`),
|
||||||
|
Modified: []byte(`
|
||||||
|
name: my-object
|
||||||
|
value: some-value
|
||||||
|
other: current-other
|
||||||
|
merginglist:
|
||||||
|
- name: 1
|
||||||
|
- name: 2
|
||||||
|
- name: 3
|
||||||
|
replacingItem:
|
||||||
|
Newly: Modified
|
||||||
|
Yaml: Inside
|
||||||
|
The: RawExtension
|
||||||
|
`),
|
||||||
|
TwoWay: []byte(`
|
||||||
|
merginglist:
|
||||||
|
- name: 1
|
||||||
|
- name: 2
|
||||||
|
- name: 3
|
||||||
|
replacingItem:
|
||||||
|
Newly: Modified
|
||||||
|
Yaml: Inside
|
||||||
|
The: RawExtension
|
||||||
|
`),
|
||||||
|
TwoWayResult: []byte(`
|
||||||
|
name: my-object
|
||||||
|
value: some-value
|
||||||
|
other: current-other
|
||||||
|
merginglist:
|
||||||
|
- name: 1
|
||||||
|
- name: 2
|
||||||
|
- name: 3
|
||||||
|
replacingItem:
|
||||||
|
Newly: Modified
|
||||||
|
Yaml: Inside
|
||||||
|
The: RawExtension
|
||||||
|
`),
|
||||||
|
ThreeWay: []byte(`
|
||||||
|
replacingItem:
|
||||||
|
Newly: Modified
|
||||||
|
Yaml: Inside
|
||||||
|
The: RawExtension
|
||||||
|
`),
|
||||||
|
Result: []byte(`
|
||||||
|
name: my-object
|
||||||
|
value: some-value
|
||||||
|
other: current-other
|
||||||
|
merginglist:
|
||||||
|
- name: 1
|
||||||
|
- name: 2
|
||||||
|
- name: 3
|
||||||
|
replacingItem:
|
||||||
|
Newly: Modified
|
||||||
|
Yaml: Inside
|
||||||
|
The: RawExtension
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Description: "replace RawExtension field and merge list",
|
||||||
|
StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
|
||||||
|
Original: []byte(`
|
||||||
|
name: my-object
|
||||||
|
value: some-value
|
||||||
|
other: current-other
|
||||||
|
merginglist:
|
||||||
|
- name: 1
|
||||||
|
replacingItem:
|
||||||
|
Some: Generic
|
||||||
|
Yaml: Inside
|
||||||
|
The: RawExtension
|
||||||
|
Field: Period
|
||||||
|
`),
|
||||||
|
Current: []byte(`
|
||||||
|
name: my-object
|
||||||
|
value: some-value
|
||||||
|
other: current-other
|
||||||
|
merginglist:
|
||||||
|
- name: 1
|
||||||
|
- name: 3
|
||||||
|
replacingItem:
|
||||||
|
Some: Generic
|
||||||
|
Yaml: Inside
|
||||||
|
The: RawExtension
|
||||||
|
Field: Period
|
||||||
|
`),
|
||||||
|
Modified: []byte(`
|
||||||
|
name: my-object
|
||||||
|
value: some-value
|
||||||
|
other: current-other
|
||||||
|
merginglist:
|
||||||
|
- name: 1
|
||||||
|
- name: 2
|
||||||
|
replacingItem:
|
||||||
|
Newly: Modified
|
||||||
|
Yaml: Inside
|
||||||
|
The: RawExtension
|
||||||
|
`),
|
||||||
|
TwoWay: []byte(`
|
||||||
|
merginglist:
|
||||||
|
- name: 2
|
||||||
|
replacingItem:
|
||||||
|
Newly: Modified
|
||||||
|
Yaml: Inside
|
||||||
|
The: RawExtension
|
||||||
|
`),
|
||||||
|
TwoWayResult: []byte(`
|
||||||
|
name: my-object
|
||||||
|
value: some-value
|
||||||
|
other: current-other
|
||||||
|
merginglist:
|
||||||
|
- name: 1
|
||||||
|
- name: 2
|
||||||
|
replacingItem:
|
||||||
|
Newly: Modified
|
||||||
|
Yaml: Inside
|
||||||
|
The: RawExtension
|
||||||
|
`),
|
||||||
|
ThreeWay: []byte(`
|
||||||
|
merginglist:
|
||||||
|
- name: 2
|
||||||
|
replacingItem:
|
||||||
|
Newly: Modified
|
||||||
|
Yaml: Inside
|
||||||
|
The: RawExtension
|
||||||
|
`),
|
||||||
|
Result: []byte(`
|
||||||
|
name: my-object
|
||||||
|
value: some-value
|
||||||
|
other: current-other
|
||||||
|
merginglist:
|
||||||
|
- name: 1
|
||||||
|
- name: 3
|
||||||
|
- name: 2
|
||||||
|
replacingItem:
|
||||||
|
Newly: Modified
|
||||||
|
Yaml: Inside
|
||||||
|
The: RawExtension
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReplaceWithRawExtension(t *testing.T) {
|
||||||
|
for _, c := range replaceRawExtensionPatchTestCases {
|
||||||
|
testTwoWayPatchWithoutSorting(t, c)
|
||||||
|
testThreeWayPatchWithoutSorting(t, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTwoWayPatchWithoutSorting(t *testing.T, c StrategicMergePatchRawTestCase) {
|
||||||
|
original, expectedPatch, modified, expectedResult := twoWayRawTestCaseToJSONOrFail(t, c)
|
||||||
|
|
||||||
|
actualPatch, err := CreateTwoWayMergePatch(original, modified, mergeItem)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error: %s\nin test case: %s\ncannot create two way patch:\noriginal:%s\ntwoWay:%s\nmodified:%s\ncurrent:%s\nthreeWay:%s\nresult:%s\n",
|
||||||
|
err, c.Description, c.Original, c.TwoWay, c.Modified, c.Current, c.ThreeWay, c.Result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testPatchCreationWithoutSorting(t, expectedPatch, actualPatch, c.Description)
|
||||||
|
testPatchApplicationWithoutSorting(t, original, actualPatch, expectedResult, c.Description)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testThreeWayPatchWithoutSorting(t *testing.T, c StrategicMergePatchRawTestCase) {
|
||||||
|
original, modified, current, expected, result := threeWayRawTestCaseToJSONOrFail(t, c)
|
||||||
|
actual, err := CreateThreeWayMergePatch(original, modified, current, mergeItem, false)
|
||||||
|
if err != nil {
|
||||||
|
if !mergepatch.IsConflict(err) {
|
||||||
|
t.Errorf("error: %s\nin test case: %s\ncannot create three way patch:\noriginal:%s\ntwoWay:%s\nmodified:%s\ncurrent:%s\nthreeWay:%s\nresult:%s\n",
|
||||||
|
err, c.Description, c.Original, c.TwoWay, c.Modified, c.Current, c.ThreeWay, c.Result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(c.Description, "conflict") {
|
||||||
|
t.Errorf("unexpected conflict: %s\nin test case: %s\ncannot create three way patch:\noriginal:%s\ntwoWay:%s\nmodified:%s\ncurrent:%s\nthreeWay:%s\nresult:%s\n",
|
||||||
|
err, c.Description, c.Original, c.TwoWay, c.Modified, c.Current, c.ThreeWay, c.Result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(c.Result) > 0 {
|
||||||
|
actual, err := CreateThreeWayMergePatch(original, modified, current, mergeItem, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error: %s\nin test case: %s\ncannot force three way patch application:\noriginal:%s\ntwoWay:%s\nmodified:%s\ncurrent:%s\nthreeWay:%s\nresult:%s\n",
|
||||||
|
err, c.Description, c.Original, c.TwoWay, c.Modified, c.Current, c.ThreeWay, c.Result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testPatchCreationWithoutSorting(t, expected, actual, c.Description)
|
||||||
|
testPatchApplicationWithoutSorting(t, current, actual, result, c.Description)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(c.Description, "conflict") || len(c.Result) < 1 {
|
||||||
|
t.Errorf("error: %s\nin test case: %s\nexpected conflict did not occur:\noriginal:%s\ntwoWay:%s\nmodified:%s\ncurrent:%s\nthreeWay:%s\nresult:%s\n",
|
||||||
|
err, c.Description, c.Original, c.TwoWay, c.Modified, c.Current, c.ThreeWay, c.Result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testPatchCreationWithoutSorting(t, expected, actual, c.Description)
|
||||||
|
testPatchApplicationWithoutSorting(t, current, actual, result, c.Description)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPatchCreationWithoutSorting(t *testing.T, expected, actual []byte, description string) {
|
||||||
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
|
t.Errorf("error in test case: %s\nexpected patch:\n%s\ngot:\n%s\n",
|
||||||
|
description, jsonToYAMLOrError(expected), jsonToYAMLOrError(actual))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPatchApplicationWithoutSorting(t *testing.T, original, patch, expected []byte, description string) {
|
||||||
|
result, err := StrategicMergePatch(original, patch, mergeItem)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error: %s\nin test case: %s\ncannot apply patch:\n%s\nto original:\n%s\n",
|
||||||
|
err, description, jsonToYAMLOrError(patch), jsonToYAMLOrError(original))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(result, expected) {
|
||||||
|
format := "error in test case: %s\npatch application failed:\noriginal:\n%s\npatch:\n%s\nexpected:\n%s\ngot:\n%s\n"
|
||||||
|
t.Errorf(format, description,
|
||||||
|
jsonToYAMLOrError(original), jsonToYAMLOrError(patch),
|
||||||
|
jsonToYAMLOrError(expected), jsonToYAMLOrError(result))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1
vendor/BUILD
vendored
1
vendor/BUILD
vendored
@ -13537,6 +13537,7 @@ go_test(
|
|||||||
deps = [
|
deps = [
|
||||||
"//vendor:github.com/davecgh/go-spew/spew",
|
"//vendor:github.com/davecgh/go-spew/spew",
|
||||||
"//vendor:github.com/ghodss/yaml",
|
"//vendor:github.com/ghodss/yaml",
|
||||||
|
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/mergepatch",
|
"//vendor:k8s.io/apimachinery/pkg/util/mergepatch",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user