Add generated file

This PR adds generated files under pkg/client and vendor folder.
This commit is contained in:
xing-yang
2018-07-12 10:55:15 -07:00
parent 36b1de0341
commit e213d1890d
17729 changed files with 5090889 additions and 0 deletions

View File

@@ -0,0 +1,160 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package jsonmergepatch
import (
"fmt"
"reflect"
"github.com/evanphx/json-patch"
"k8s.io/apimachinery/pkg/util/json"
"k8s.io/apimachinery/pkg/util/mergepatch"
)
// Create a 3-way merge patch based-on JSON merge patch.
// Calculate addition-and-change patch between current and modified.
// Calculate deletion patch between original and modified.
func CreateThreeWayJSONMergePatch(original, modified, current []byte, fns ...mergepatch.PreconditionFunc) ([]byte, error) {
if len(original) == 0 {
original = []byte(`{}`)
}
if len(modified) == 0 {
modified = []byte(`{}`)
}
if len(current) == 0 {
current = []byte(`{}`)
}
addAndChangePatch, err := jsonpatch.CreateMergePatch(current, modified)
if err != nil {
return nil, err
}
// Only keep addition and changes
addAndChangePatch, addAndChangePatchObj, err := keepOrDeleteNullInJsonPatch(addAndChangePatch, false)
if err != nil {
return nil, err
}
deletePatch, err := jsonpatch.CreateMergePatch(original, modified)
if err != nil {
return nil, err
}
// Only keep deletion
deletePatch, deletePatchObj, err := keepOrDeleteNullInJsonPatch(deletePatch, true)
if err != nil {
return nil, err
}
hasConflicts, err := mergepatch.HasConflicts(addAndChangePatchObj, deletePatchObj)
if err != nil {
return nil, err
}
if hasConflicts {
return nil, mergepatch.NewErrConflict(mergepatch.ToYAMLOrError(addAndChangePatchObj), mergepatch.ToYAMLOrError(deletePatchObj))
}
patch, err := jsonpatch.MergePatch(deletePatch, addAndChangePatch)
if err != nil {
return nil, err
}
var patchMap map[string]interface{}
err = json.Unmarshal(patch, &patchMap)
if err != nil {
return nil, fmt.Errorf("Failed to unmarshal patch for precondition check: %s", patch)
}
meetPreconditions, err := meetPreconditions(patchMap, fns...)
if err != nil {
return nil, err
}
if !meetPreconditions {
return nil, mergepatch.NewErrPreconditionFailed(patchMap)
}
return patch, nil
}
// keepOrDeleteNullInJsonPatch takes a json-encoded byte array and a boolean.
// It returns a filtered object and its corresponding json-encoded byte array.
// It is a wrapper of func keepOrDeleteNullInObj
func keepOrDeleteNullInJsonPatch(patch []byte, keepNull bool) ([]byte, map[string]interface{}, error) {
var patchMap map[string]interface{}
err := json.Unmarshal(patch, &patchMap)
if err != nil {
return nil, nil, err
}
filteredMap, err := keepOrDeleteNullInObj(patchMap, keepNull)
if err != nil {
return nil, nil, err
}
o, err := json.Marshal(filteredMap)
return o, filteredMap, err
}
// keepOrDeleteNullInObj will keep only the null value and delete all the others,
// if keepNull is true. Otherwise, it will delete all the null value and keep the others.
func keepOrDeleteNullInObj(m map[string]interface{}, keepNull bool) (map[string]interface{}, error) {
filteredMap := make(map[string]interface{})
var err error
for key, val := range m {
switch {
case keepNull && val == nil:
filteredMap[key] = nil
case val != nil:
switch typedVal := val.(type) {
case map[string]interface{}:
// Explicitly-set empty maps are treated as values instead of empty patches
if len(typedVal) == 0 {
if !keepNull {
filteredMap[key] = typedVal
}
continue
}
var filteredSubMap map[string]interface{}
filteredSubMap, err = keepOrDeleteNullInObj(typedVal, keepNull)
if err != nil {
return nil, err
}
// If the returned filtered submap was empty, this is an empty patch for the entire subdict, so the key
// should not be set
if len(filteredSubMap) != 0 {
filteredMap[key] = filteredSubMap
}
case []interface{}, string, float64, bool, int, int64, nil:
// Lists are always replaced in Json, no need to check each entry in the list.
if !keepNull {
filteredMap[key] = val
}
default:
return nil, fmt.Errorf("unknown type: %v", reflect.TypeOf(typedVal))
}
}
}
return filteredMap, nil
}
func meetPreconditions(patchObj map[string]interface{}, fns ...mergepatch.PreconditionFunc) (bool, error) {
// Apply the preconditions to the patch, and return an error if any of them fail.
for _, fn := range fns {
if !fn(patchObj) {
return false, fmt.Errorf("precondition failed for: %v", patchObj)
}
}
return true, nil
}

View File

@@ -0,0 +1,696 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package jsonmergepatch
import (
"fmt"
"reflect"
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/evanphx/json-patch"
"github.com/ghodss/yaml"
"k8s.io/apimachinery/pkg/util/json"
)
type FilterNullTestCases struct {
TestCases []FilterNullTestCase
}
type FilterNullTestCase struct {
Description string
OriginalObj map[string]interface{}
ExpectedWithNull map[string]interface{}
ExpectedWithoutNull map[string]interface{}
}
var filterNullTestCaseData = []byte(`
testCases:
- description: nil original
originalObj: {}
expectedWithNull: {}
expectedWithoutNull: {}
- description: simple map
originalObj:
nilKey: null
nonNilKey: foo
expectedWithNull:
nilKey: null
expectedWithoutNull:
nonNilKey: foo
- description: simple map with all nil values
originalObj:
nilKey1: null
nilKey2: null
expectedWithNull:
nilKey1: null
nilKey2: null
expectedWithoutNull: {}
- description: simple map with all non-nil values
originalObj:
nonNilKey1: foo
nonNilKey2: bar
expectedWithNull: {}
expectedWithoutNull:
nonNilKey1: foo
nonNilKey2: bar
- description: nested map
originalObj:
mapKey:
nilKey: null
nonNilKey: foo
expectedWithNull:
mapKey:
nilKey: null
expectedWithoutNull:
mapKey:
nonNilKey: foo
- description: nested map that all subkeys are nil
originalObj:
mapKey:
nilKey1: null
nilKey2: null
expectedWithNull:
mapKey:
nilKey1: null
nilKey2: null
expectedWithoutNull: {}
- description: nested map that all subkeys are non-nil
originalObj:
mapKey:
nonNilKey1: foo
nonNilKey2: bar
expectedWithNull: {}
expectedWithoutNull:
mapKey:
nonNilKey1: foo
nonNilKey2: bar
- description: explicitly empty map as value
originalObj:
mapKey: {}
expectedWithNull: {}
expectedWithoutNull:
mapKey: {}
- description: explicitly empty nested map
originalObj:
mapKey:
nonNilKey: {}
expectedWithNull: {}
expectedWithoutNull:
mapKey:
nonNilKey: {}
- description: multiple expliclty empty nested maps
originalObj:
mapKey:
nonNilKey1: {}
nonNilKey2: {}
expectedWithNull: {}
expectedWithoutNull:
mapKey:
nonNilKey1: {}
nonNilKey2: {}
- description: nested map with non-null value as empty map
originalObj:
mapKey:
nonNilKey: {}
nilKey: null
expectedWithNull:
mapKey:
nilKey: null
expectedWithoutNull:
mapKey:
nonNilKey: {}
- description: empty list
originalObj:
listKey: []
expectedWithNull: {}
expectedWithoutNull:
listKey: []
- description: list of primitives
originalObj:
listKey:
- 1
- 2
expectedWithNull: {}
expectedWithoutNull:
listKey:
- 1
- 2
- description: list of maps
originalObj:
listKey:
- k1: v1
- k2: null
- k3: v3
k4: null
expectedWithNull: {}
expectedWithoutNull:
listKey:
- k1: v1
- k2: null
- k3: v3
k4: null
- description: list of different types
originalObj:
listKey:
- k1: v1
- k2: null
- v3
expectedWithNull: {}
expectedWithoutNull:
listKey:
- k1: v1
- k2: null
- v3
`)
func TestKeepOrDeleteNullInObj(t *testing.T) {
tc := FilterNullTestCases{}
err := yaml.Unmarshal(filterNullTestCaseData, &tc)
if err != nil {
t.Fatalf("can't unmarshal test cases: %s\n", err)
}
for _, test := range tc.TestCases {
resultWithNull, err := keepOrDeleteNullInObj(test.OriginalObj, true)
if err != nil {
t.Errorf("Failed in test case %q when trying to keep null values: %s", test.Description, err)
}
if !reflect.DeepEqual(test.ExpectedWithNull, resultWithNull) {
t.Errorf("Failed in test case %q when trying to keep null values:\nexpected expectedWithNull:\n%+v\nbut got:\n%+v\n", test.Description, test.ExpectedWithNull, resultWithNull)
}
resultWithoutNull, err := keepOrDeleteNullInObj(test.OriginalObj, false)
if err != nil {
t.Errorf("Failed in test case %q when trying to keep non-null values: %s", test.Description, err)
}
if !reflect.DeepEqual(test.ExpectedWithoutNull, resultWithoutNull) {
t.Errorf("Failed in test case %q when trying to keep non-null values:\n expected expectedWithoutNull:\n%+v\nbut got:\n%+v\n", test.Description, test.ExpectedWithoutNull, resultWithoutNull)
}
}
}
type JSONMergePatchTestCases struct {
TestCases []JSONMergePatchTestCase
}
type JSONMergePatchTestCase struct {
Description string
JSONMergePatchTestCaseData
}
type JSONMergePatchTestCaseData struct {
// Original is the original object (last-applied config in annotation)
Original map[string]interface{}
// Modified is the modified object (new config we want)
Modified map[string]interface{}
// Current is the current object (live config in the server)
Current map[string]interface{}
// ThreeWay is the expected three-way merge patch
ThreeWay map[string]interface{}
// Result is the expected object after applying the three-way patch on current object.
Result map[string]interface{}
}
var createJSONMergePatchTestCaseData = []byte(`
testCases:
- description: nil original
modified:
name: 1
value: 1
current:
name: 1
other: a
threeWay:
value: 1
result:
name: 1
value: 1
other: a
- description: nil patch
original:
name: 1
modified:
name: 1
current:
name: 1
threeWay:
{}
result:
name: 1
- description: add field to map
original:
name: 1
modified:
name: 1
value: 1
current:
name: 1
other: a
threeWay:
value: 1
result:
name: 1
value: 1
other: a
- description: add field to map with conflict
original:
name: 1
modified:
name: 1
value: 1
current:
name: a
other: a
threeWay:
name: 1
value: 1
result:
name: 1
value: 1
other: a
- description: add field and delete field from map
original:
name: 1
modified:
value: 1
current:
name: 1
other: a
threeWay:
name: null
value: 1
result:
value: 1
other: a
- description: add field and delete field from map with conflict
original:
name: 1
modified:
value: 1
current:
name: a
other: a
threeWay:
name: null
value: 1
result:
value: 1
other: a
- description: delete field from nested map
original:
simpleMap:
key1: 1
key2: 1
modified:
simpleMap:
key1: 1
current:
simpleMap:
key1: 1
key2: 1
other: a
threeWay:
simpleMap:
key2: null
result:
simpleMap:
key1: 1
other: a
- description: delete field from nested map with conflict
original:
simpleMap:
key1: 1
key2: 1
modified:
simpleMap:
key1: 1
current:
simpleMap:
key1: a
key2: 1
other: a
threeWay:
simpleMap:
key1: 1
key2: null
result:
simpleMap:
key1: 1
other: a
- description: delete all fields from map
original:
name: 1
value: 1
modified: {}
current:
name: 1
value: 1
other: a
threeWay:
name: null
value: null
result:
other: a
- description: delete all fields from map with conflict
original:
name: 1
value: 1
modified: {}
current:
name: 1
value: a
other: a
threeWay:
name: null
value: null
result:
other: a
- description: add field and delete all fields from map
original:
name: 1
value: 1
modified:
other: a
current:
name: 1
value: 1
other: a
threeWay:
name: null
value: null
result:
other: a
- description: add field and delete all fields from map with conflict
original:
name: 1
value: 1
modified:
other: a
current:
name: 1
value: 1
other: b
threeWay:
name: null
value: null
other: a
result:
other: a
- description: replace list of scalars
original:
intList:
- 1
- 2
modified:
intList:
- 2
- 3
current:
intList:
- 1
- 2
threeWay:
intList:
- 2
- 3
result:
intList:
- 2
- 3
- description: replace list of scalars with conflict
original:
intList:
- 1
- 2
modified:
intList:
- 2
- 3
current:
intList:
- 1
- 4
threeWay:
intList:
- 2
- 3
result:
intList:
- 2
- 3
- description: patch with different scalar type
original:
foo: 1
modified:
foo: true
current:
foo: 1
bar: 2
threeWay:
foo: true
result:
foo: true
bar: 2
- description: patch from scalar to list
original:
foo: 0
modified:
foo:
- 1
- 2
current:
foo: 0
bar: 2
threeWay:
foo:
- 1
- 2
result:
foo:
- 1
- 2
bar: 2
- description: patch from list to scalar
original:
foo:
- 1
- 2
modified:
foo: 0
current:
foo:
- 1
- 2
bar: 2
threeWay:
foo: 0
result:
foo: 0
bar: 2
- description: patch from scalar to map
original:
foo: 0
modified:
foo:
baz: 1
current:
foo: 0
bar: 2
threeWay:
foo:
baz: 1
result:
foo:
baz: 1
bar: 2
- description: patch from map to scalar
original:
foo:
baz: 1
modified:
foo: 0
current:
foo:
baz: 1
bar: 2
threeWay:
foo: 0
result:
foo: 0
bar: 2
- description: patch from map to list
original:
foo:
baz: 1
modified:
foo:
- 1
- 2
current:
foo:
baz: 1
bar: 2
threeWay:
foo:
- 1
- 2
result:
foo:
- 1
- 2
bar: 2
- description: patch from list to map
original:
foo:
- 1
- 2
modified:
foo:
baz: 0
current:
foo:
- 1
- 2
bar: 2
threeWay:
foo:
baz: 0
result:
foo:
baz: 0
bar: 2
- description: patch with different nested types
original:
foo:
- a: true
- 2
- false
modified:
foo:
- 1
- false
- b: 1
current:
foo:
- a: true
- 2
- false
bar: 0
threeWay:
foo:
- 1
- false
- b: 1
result:
foo:
- 1
- false
- b: 1
bar: 0
`)
func TestCreateThreeWayJSONMergePatch(t *testing.T) {
tc := JSONMergePatchTestCases{}
err := yaml.Unmarshal(createJSONMergePatchTestCaseData, &tc)
if err != nil {
t.Errorf("can't unmarshal test cases: %s\n", err)
return
}
for _, c := range tc.TestCases {
testThreeWayPatch(t, c)
}
}
func testThreeWayPatch(t *testing.T, c JSONMergePatchTestCase) {
original, modified, current, expected, result := threeWayTestCaseToJSONOrFail(t, c)
actual, err := CreateThreeWayJSONMergePatch(original, modified, current)
if err != nil {
t.Fatalf("error: %s", err)
}
testPatchCreation(t, expected, actual, c.Description)
testPatchApplication(t, current, actual, result, c.Description)
}
func testPatchCreation(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 testPatchApplication(t *testing.T, original, patch, expected []byte, description string) {
result, err := jsonpatch.MergePatch(original, patch)
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
}
}
func threeWayTestCaseToJSONOrFail(t *testing.T, c JSONMergePatchTestCase) ([]byte, []byte, []byte, []byte, []byte) {
return testObjectToJSONOrFail(t, c.Original),
testObjectToJSONOrFail(t, c.Modified),
testObjectToJSONOrFail(t, c.Current),
testObjectToJSONOrFail(t, c.ThreeWay),
testObjectToJSONOrFail(t, c.Result)
}
func testObjectToJSONOrFail(t *testing.T, o map[string]interface{}) []byte {
if o == nil {
return nil
}
j, err := toJSON(o)
if err != nil {
t.Error(err)
}
return j
}
func jsonToYAMLOrError(j []byte) string {
y, err := jsonToYAML(j)
if err != nil {
return err.Error()
}
return string(y)
}
func toJSON(v interface{}) ([]byte, error) {
j, err := json.Marshal(v)
if err != nil {
return nil, fmt.Errorf("json marshal failed: %v\n%v\n", err, spew.Sdump(v))
}
return j, nil
}
func jsonToYAML(j []byte) ([]byte, error) {
y, err := yaml.JSONToYAML(j)
if err != nil {
return nil, fmt.Errorf("json to yaml failed: %v\n%v\n", err, j)
}
return y, nil
}