diff --git a/pkg/util/strategicpatch/patch.go b/pkg/util/strategicpatch/patch.go index d8f59c4757f..d5123472aa4 100644 --- a/pkg/util/strategicpatch/patch.go +++ b/pkg/util/strategicpatch/patch.go @@ -17,11 +17,12 @@ limitations under the License. package strategicpatch import ( - "bytes" "encoding/json" "fmt" "reflect" "sort" + + forkedjson "github.com/GoogleCloudPlatform/kubernetes/third_party/forked/json" ) // An alternate implementation of JSON Merge Patch @@ -101,7 +102,7 @@ func mergeMap(original, patch map[string]interface{}, t reflect.Type) (map[strin } // If they're both maps or lists, recurse into the value. // First find the fieldPatchStrategy and fieldPatchMergeKey. - fieldType, fieldPatchStrategy, fieldPatchMergeKey, err := lookupPatchMetadata(t, k) + fieldType, fieldPatchStrategy, fieldPatchMergeKey, err := forkedjson.LookupPatchMetadata(t, k) if err != nil { return nil, err } @@ -268,7 +269,7 @@ func sortMergeListsByName(mapJSON []byte, dataStruct interface{}) ([]byte, error func sortMergeListsByNameMap(s map[string]interface{}, t reflect.Type) (map[string]interface{}, error) { newS := map[string]interface{}{} for k, v := range s { - fieldType, fieldPatchStrategy, fieldPatchMergeKey, err := lookupPatchMetadata(t, k) + fieldType, fieldPatchStrategy, fieldPatchMergeKey, err := forkedjson.LookupPatchMetadata(t, k) if err != nil { return nil, err } @@ -431,39 +432,3 @@ func sliceElementType(slices ...[]interface{}) (reflect.Type, error) { } return prevType, nil } - -// Finds the patchStrategy and patchMergeKey struct tag fields on a given -// struct field given the struct type and the JSON name of the field. -func lookupPatchMetadata(t reflect.Type, jsonField string) (reflect.Type, string, string, error) { - if t.Kind() == reflect.Map { - return t.Elem(), "", "", nil - } - if t.Kind() != reflect.Struct { - return nil, "", "", fmt.Errorf("merging an object in json but data type is not map or struct, instead is: %s", - t.Kind().String()) - } - jf := []byte(jsonField) - // Find the field that the JSON library would use. - var f *field - fields := cachedTypeFields(t) - for i := range fields { - ff := &fields[i] - if bytes.Equal(ff.nameBytes, jf) { - f = ff - break - } - // Do case-insensitive comparison. - if f == nil && ff.equalFold(ff.nameBytes, jf) { - f = ff - } - } - if f != nil { - // Find the reflect.Value of the most preferential - // struct field. - tjf := t.Field(f.index[0]) - patchStrategy := tjf.Tag.Get("patchStrategy") - patchMergeKey := tjf.Tag.Get("patchMergeKey") - return tjf.Type, patchStrategy, patchMergeKey, nil - } - return nil, "", "", fmt.Errorf("unable to find api field in struct %s for the json field %q", t.Name(), jsonField) -} diff --git a/third_party/forked/json/LICENSE b/third_party/forked/json/LICENSE new file mode 100644 index 00000000000..74487567632 --- /dev/null +++ b/third_party/forked/json/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkg/util/strategicpatch/fields.go b/third_party/forked/json/fields.go similarity index 88% rename from pkg/util/strategicpatch/fields.go rename to third_party/forked/json/fields.go index c92e73f17fc..6384f91104a 100644 --- a/pkg/util/strategicpatch/fields.go +++ b/third_party/forked/json/fields.go @@ -1,29 +1,14 @@ -/* -Copyright 2014 Google Inc. All rights reserved. - -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. -*/ - -// NOTE: The below is taken from the Go standard library to enable us to find -// the field of a struct that a given JSON key maps to. -// // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package strategicpatch + +// Package json is forked from the Go standard library to enable us to find the +// field of a struct that a given JSON key maps to. +package json import ( "bytes" + "fmt" "reflect" "sort" "strings" @@ -32,6 +17,43 @@ import ( "unicode/utf8" ) +// Finds the patchStrategy and patchMergeKey struct tag fields on a given +// struct field given the struct type and the JSON name of the field. +// TODO: fix the returned errors to be introspectable. +func LookupPatchMetadata(t reflect.Type, jsonField string) (reflect.Type, string, string, error) { + if t.Kind() == reflect.Map { + return t.Elem(), "", "", nil + } + if t.Kind() != reflect.Struct { + return nil, "", "", fmt.Errorf("merging an object in json but data type is not map or struct, instead is: %s", + t.Kind().String()) + } + jf := []byte(jsonField) + // Find the field that the JSON library would use. + var f *field + fields := cachedTypeFields(t) + for i := range fields { + ff := &fields[i] + if bytes.Equal(ff.nameBytes, jf) { + f = ff + break + } + // Do case-insensitive comparison. + if f == nil && ff.equalFold(ff.nameBytes, jf) { + f = ff + } + } + if f != nil { + // Find the reflect.Value of the most preferential + // struct field. + tjf := t.Field(f.index[0]) + patchStrategy := tjf.Tag.Get("patchStrategy") + patchMergeKey := tjf.Tag.Get("patchMergeKey") + return tjf.Type, patchStrategy, patchMergeKey, nil + } + return nil, "", "", fmt.Errorf("unable to find api field in struct %s for the json field %q", t.Name(), jsonField) +} + // A field represents a single field found in a struct. type field struct { name string