diff --git a/go.mod b/go.mod index 5b4b7888450..05da154e593 100644 --- a/go.mod +++ b/go.mod @@ -473,7 +473,7 @@ replace ( modernc.org/strutil => modernc.org/strutil v1.0.0 modernc.org/xc => modernc.org/xc v1.0.0 sigs.k8s.io/kustomize => sigs.k8s.io/kustomize v2.0.3+incompatible - sigs.k8s.io/structured-merge-diff => sigs.k8s.io/structured-merge-diff v0.0.0-20190724202554-0c1d754dd648 + sigs.k8s.io/structured-merge-diff => sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca sigs.k8s.io/yaml => sigs.k8s.io/yaml v1.1.0 vbom.ml/util => vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc ) diff --git a/go.sum b/go.sum index 60d6543dd1f..8d1cbf13c66 100644 --- a/go.sum +++ b/go.sum @@ -505,8 +505,8 @@ modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= -sigs.k8s.io/structured-merge-diff v0.0.0-20190724202554-0c1d754dd648 h1:qukMPS/1fDG5pToYLYSEx5IpwHVJMtTyOMaIIsR2Fas= -sigs.k8s.io/structured-merge-diff v0.0.0-20190724202554-0c1d754dd648/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= +sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca h1:6dsH6AYQWbyZmtttJNe8Gq1cXOeS1BdV3eW37zHilAQ= +sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc h1:MksmcCZQWAQJCTA5T0jgI/0sJ51AVm4Z41MrmfczEoc= diff --git a/staging/src/k8s.io/apiextensions-apiserver/go.sum b/staging/src/k8s.io/apiextensions-apiserver/go.sum index f3cf424fb27..40e2b700faa 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/go.sum +++ b/staging/src/k8s.io/apiextensions-apiserver/go.sum @@ -335,7 +335,7 @@ modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= -sigs.k8s.io/structured-merge-diff v0.0.0-20190724202554-0c1d754dd648 h1:qukMPS/1fDG5pToYLYSEx5IpwHVJMtTyOMaIIsR2Fas= -sigs.k8s.io/structured-merge-diff v0.0.0-20190724202554-0c1d754dd648/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= +sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca h1:6dsH6AYQWbyZmtttJNe8Gq1cXOeS1BdV3eW37zHilAQ= +sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/staging/src/k8s.io/apiserver/go.mod b/staging/src/k8s.io/apiserver/go.mod index 53926040f05..7c80627f2c1 100644 --- a/staging/src/k8s.io/apiserver/go.mod +++ b/staging/src/k8s.io/apiserver/go.mod @@ -59,7 +59,7 @@ require ( k8s.io/klog v0.4.0 k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058 k8s.io/utils v0.0.0-20190801114015-581e00157fb1 - sigs.k8s.io/structured-merge-diff v0.0.0-20190724202554-0c1d754dd648 + sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca sigs.k8s.io/yaml v1.1.0 ) diff --git a/staging/src/k8s.io/apiserver/go.sum b/staging/src/k8s.io/apiserver/go.sum index 860499197c1..5454db59665 100644 --- a/staging/src/k8s.io/apiserver/go.sum +++ b/staging/src/k8s.io/apiserver/go.sum @@ -250,7 +250,7 @@ k8s.io/utils v0.0.0-20190801114015-581e00157fb1 h1:+ySTxfHnfzZb9ys375PXNlLhkJPLK k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= -sigs.k8s.io/structured-merge-diff v0.0.0-20190724202554-0c1d754dd648 h1:qukMPS/1fDG5pToYLYSEx5IpwHVJMtTyOMaIIsR2Fas= -sigs.k8s.io/structured-merge-diff v0.0.0-20190724202554-0c1d754dd648/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= +sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca h1:6dsH6AYQWbyZmtttJNe8Gq1cXOeS1BdV3eW37zHilAQ= +sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/staging/src/k8s.io/kube-aggregator/go.sum b/staging/src/k8s.io/kube-aggregator/go.sum index 06996e1c485..9afb012d5df 100644 --- a/staging/src/k8s.io/kube-aggregator/go.sum +++ b/staging/src/k8s.io/kube-aggregator/go.sum @@ -289,7 +289,7 @@ modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= -sigs.k8s.io/structured-merge-diff v0.0.0-20190724202554-0c1d754dd648 h1:qukMPS/1fDG5pToYLYSEx5IpwHVJMtTyOMaIIsR2Fas= -sigs.k8s.io/structured-merge-diff v0.0.0-20190724202554-0c1d754dd648/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= +sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca h1:6dsH6AYQWbyZmtttJNe8Gq1cXOeS1BdV3eW37zHilAQ= +sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/staging/src/k8s.io/legacy-cloud-providers/go.sum b/staging/src/k8s.io/legacy-cloud-providers/go.sum index 7fcc6f562cd..185866c791c 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/go.sum +++ b/staging/src/k8s.io/legacy-cloud-providers/go.sum @@ -235,6 +235,6 @@ k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058/go.mod h1:nfDlWeOsu3pUf4y k8s.io/utils v0.0.0-20190801114015-581e00157fb1 h1:+ySTxfHnfzZb9ys375PXNlLhkJPLKgHajBU0N62BDvE= k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= -sigs.k8s.io/structured-merge-diff v0.0.0-20190724202554-0c1d754dd648/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= +sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/staging/src/k8s.io/sample-apiserver/go.sum b/staging/src/k8s.io/sample-apiserver/go.sum index 1405fb5c0ce..1f8dd814ce0 100644 --- a/staging/src/k8s.io/sample-apiserver/go.sum +++ b/staging/src/k8s.io/sample-apiserver/go.sum @@ -286,7 +286,7 @@ modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= -sigs.k8s.io/structured-merge-diff v0.0.0-20190724202554-0c1d754dd648 h1:qukMPS/1fDG5pToYLYSEx5IpwHVJMtTyOMaIIsR2Fas= -sigs.k8s.io/structured-merge-diff v0.0.0-20190724202554-0c1d754dd648/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= +sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca h1:6dsH6AYQWbyZmtttJNe8Gq1cXOeS1BdV3eW37zHilAQ= +sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/vendor/modules.txt b/vendor/modules.txt index 9267be946d6..4cf846d2ff1 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1834,7 +1834,7 @@ sigs.k8s.io/kustomize/pkg/transformers sigs.k8s.io/kustomize/pkg/transformers/config sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig sigs.k8s.io/kustomize/pkg/types -# sigs.k8s.io/structured-merge-diff v0.0.0-20190724202554-0c1d754dd648 => sigs.k8s.io/structured-merge-diff v0.0.0-20190724202554-0c1d754dd648 +# sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca => sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca sigs.k8s.io/structured-merge-diff/fieldpath sigs.k8s.io/structured-merge-diff/merge sigs.k8s.io/structured-merge-diff/schema diff --git a/vendor/sigs.k8s.io/structured-merge-diff/merge/update.go b/vendor/sigs.k8s.io/structured-merge-diff/merge/update.go index 731ec4d7090..96c9751ac78 100644 --- a/vendor/sigs.k8s.io/structured-merge-diff/merge/update.go +++ b/vendor/sigs.k8s.io/structured-merge-diff/merge/update.go @@ -31,6 +31,14 @@ type Converter interface { // merge the object on Apply. type Updater struct { Converter Converter + + enableUnions bool +} + +// EnableUnionFeature turns on union handling. It is disabled by default until the +// feature is complete. +func (s *Updater) EnableUnionFeature() { + s.enableUnions = true } func (s *Updater) update(oldObject, newObject *typed.TypedValue, version fieldpath.APIVersion, managers fieldpath.ManagedFields, workflow string, force bool) (fieldpath.ManagedFields, error) { @@ -112,9 +120,12 @@ func (s *Updater) update(oldObject, newObject *typed.TypedValue, version fieldpa // PATCH call), and liveObject must be the original object (empty if // this is a CREATE call). func (s *Updater) Update(liveObject, newObject *typed.TypedValue, version fieldpath.APIVersion, managers fieldpath.ManagedFields, manager string) (*typed.TypedValue, fieldpath.ManagedFields, error) { - newObject, err := liveObject.NormalizeUnions(newObject) - if err != nil { - return nil, fieldpath.ManagedFields{}, err + var err error + if s.enableUnions { + newObject, err = liveObject.NormalizeUnions(newObject) + if err != nil { + return nil, fieldpath.ManagedFields{}, err + } } managers = shallowCopyManagers(managers) managers, err = s.update(liveObject, newObject, version, managers, manager, true) @@ -144,17 +155,22 @@ func (s *Updater) Update(liveObject, newObject *typed.TypedValue, version fieldp // and return it. func (s *Updater) Apply(liveObject, configObject *typed.TypedValue, version fieldpath.APIVersion, managers fieldpath.ManagedFields, manager string, force bool) (*typed.TypedValue, fieldpath.ManagedFields, error) { managers = shallowCopyManagers(managers) - configObject, err := configObject.NormalizeUnionsApply(configObject) - if err != nil { - return nil, fieldpath.ManagedFields{}, err + var err error + if s.enableUnions { + configObject, err = configObject.NormalizeUnionsApply(configObject) + if err != nil { + return nil, fieldpath.ManagedFields{}, err + } } newObject, err := liveObject.Merge(configObject) if err != nil { return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to merge config: %v", err) } - newObject, err = configObject.NormalizeUnionsApply(newObject) - if err != nil { - return nil, fieldpath.ManagedFields{}, err + if s.enableUnions { + newObject, err = configObject.NormalizeUnionsApply(newObject) + if err != nil { + return nil, fieldpath.ManagedFields{}, err + } } lastSet := managers[manager] set, err := configObject.ToFieldSet() diff --git a/vendor/sigs.k8s.io/structured-merge-diff/schema/BUILD b/vendor/sigs.k8s.io/structured-merge-diff/schema/BUILD index 65f9085e16b..7761df53789 100644 --- a/vendor/sigs.k8s.io/structured-merge-diff/schema/BUILD +++ b/vendor/sigs.k8s.io/structured-merge-diff/schema/BUILD @@ -5,6 +5,7 @@ go_library( srcs = [ "doc.go", "elements.go", + "equals.go", "schemaschema.go", ], importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/structured-merge-diff/schema", diff --git a/vendor/sigs.k8s.io/structured-merge-diff/schema/equals.go b/vendor/sigs.k8s.io/structured-merge-diff/schema/equals.go new file mode 100644 index 00000000000..271aed3c36a --- /dev/null +++ b/vendor/sigs.k8s.io/structured-merge-diff/schema/equals.go @@ -0,0 +1,166 @@ +/* +Copyright 2019 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 schema + +// Equals returns true iff the two Schemas are equal. +func (a Schema) Equals(b Schema) bool { + if len(a.Types) != len(b.Types) { + return false + } + for i := range a.Types { + if !a.Types[i].Equals(b.Types[i]) { + return false + } + } + return true +} + +// Equals returns true iff the two TypeRefs are equal. +// +// Note that two typerefs that have an equivalent type but where one is +// inlined and the other is named, are not considered equal. +func (a TypeRef) Equals(b TypeRef) bool { + if (a.NamedType == nil) != (b.NamedType == nil) { + return false + } + if a.NamedType != nil { + if *a.NamedType != *b.NamedType { + return false + } + //return true + } + return a.Inlined.Equals(b.Inlined) +} + +// Equals returns true iff the two TypeDefs are equal. +func (a TypeDef) Equals(b TypeDef) bool { + if a.Name != b.Name { + return false + } + return a.Atom.Equals(b.Atom) +} + +// Equals returns true iff the two Atoms are equal. +func (a Atom) Equals(b Atom) bool { + if (a.Scalar == nil) != (b.Scalar == nil) { + return false + } + if (a.List == nil) != (b.List == nil) { + return false + } + if (a.Map == nil) != (b.Map == nil) { + return false + } + switch { + case a.Scalar != nil: + return *a.Scalar == *b.Scalar + case a.List != nil: + return a.List.Equals(*b.List) + case a.Map != nil: + return a.Map.Equals(*b.Map) + } + return true +} + +// Equals returns true iff the two Maps are equal. +func (a Map) Equals(b Map) bool { + if !a.ElementType.Equals(b.ElementType) { + return false + } + if a.ElementRelationship != b.ElementRelationship { + return false + } + if len(a.Fields) != len(b.Fields) { + return false + } + for i := range a.Fields { + if !a.Fields[i].Equals(b.Fields[i]) { + return false + } + } + if len(a.Unions) != len(b.Unions) { + return false + } + for i := range a.Unions { + if !a.Unions[i].Equals(b.Unions[i]) { + return false + } + } + return true +} + +// Equals returns true iff the two Unions are equal. +func (a Union) Equals(b Union) bool { + if (a.Discriminator == nil) != (b.Discriminator == nil) { + return false + } + if a.Discriminator != nil { + if *a.Discriminator != *b.Discriminator { + return false + } + } + if a.DeduceInvalidDiscriminator != b.DeduceInvalidDiscriminator { + return false + } + if len(a.Fields) != len(b.Fields) { + return false + } + for i := range a.Fields { + if !a.Fields[i].Equals(b.Fields[i]) { + return false + } + } + return true +} + +// Equals returns true iff the two UnionFields are equal. +func (a UnionField) Equals(b UnionField) bool { + if a.FieldName != b.FieldName { + return false + } + if a.DiscriminatorValue != b.DiscriminatorValue { + return false + } + return true +} + +// Equals returns true iff the two StructFields are equal. +func (a StructField) Equals(b StructField) bool { + if a.Name != b.Name { + return false + } + return a.Type.Equals(b.Type) +} + +// Equals returns true iff the two Lists are equal. +func (a List) Equals(b List) bool { + if !a.ElementType.Equals(b.ElementType) { + return false + } + if a.ElementRelationship != b.ElementRelationship { + return false + } + if len(a.Keys) != len(b.Keys) { + return false + } + for i := range a.Keys { + if a.Keys[i] != b.Keys[i] { + return false + } + } + return true +} diff --git a/vendor/sigs.k8s.io/structured-merge-diff/typed/helpers.go b/vendor/sigs.k8s.io/structured-merge-diff/typed/helpers.go index ef856144f85..a7c12ccb001 100644 --- a/vendor/sigs.k8s.io/structured-merge-diff/typed/helpers.go +++ b/vendor/sigs.k8s.io/structured-merge-diff/typed/helpers.go @@ -67,6 +67,14 @@ func (ef *errorFormatter) descend(pe fieldpath.PathElement) { ef.path = append(ef.path, pe) } +// parent returns the parent, for the purpose of buffer reuse. It's an error to +// call this if there is no parent. +func (ef *errorFormatter) parent() errorFormatter { + return errorFormatter{ + path: ef.path[:len(ef.path)-1], + } +} + func (ef errorFormatter) errorf(format string, args ...interface{}) ValidationErrors { return ValidationErrors{{ Path: append(fieldpath.Path{}, ef.path...), diff --git a/vendor/sigs.k8s.io/structured-merge-diff/typed/merge.go b/vendor/sigs.k8s.io/structured-merge-diff/typed/merge.go index 8fee7dec1ce..27bc8b24e37 100644 --- a/vendor/sigs.k8s.io/structured-merge-diff/typed/merge.go +++ b/vendor/sigs.k8s.io/structured-merge-diff/typed/merge.go @@ -17,8 +17,6 @@ limitations under the License. package typed import ( - "reflect" - "sigs.k8s.io/structured-merge-diff/fieldpath" "sigs.k8s.io/structured-merge-diff/schema" "sigs.k8s.io/structured-merge-diff/value" @@ -43,6 +41,9 @@ type mergingWalker struct { // internal housekeeping--don't set when constructing. inLeaf bool // Set to true if we're in a "big leaf"--atomic map/list + + // Allocate only as many walkers as needed for the depth by storing them here. + spareWalkers *[]*mergingWalker } // merge rules examine w.lhs and w.rhs (up to one of which may be nil) and @@ -75,7 +76,7 @@ func (w *mergingWalker) merge() (errs ValidationErrors) { alhs := deduceAtom(a, w.lhs) arhs := deduceAtom(a, w.rhs) - if reflect.DeepEqual(alhs, arhs) { + if alhs.Equals(arhs) { errs = append(errs, handleAtom(arhs, w.typeRef, w)...) } else { w2 := *w @@ -117,13 +118,30 @@ func (w *mergingWalker) doScalar(t schema.Scalar) (errs ValidationErrors) { } func (w *mergingWalker) prepareDescent(pe fieldpath.PathElement, tr schema.TypeRef) *mergingWalker { - w2 := *w + if w.spareWalkers == nil { + // first descent. + w.spareWalkers = &[]*mergingWalker{} + } + var w2 *mergingWalker + if n := len(*w.spareWalkers); n > 0 { + w2, *w.spareWalkers = (*w.spareWalkers)[n-1], (*w.spareWalkers)[:n-1] + } else { + w2 = &mergingWalker{} + } + *w2 = *w w2.typeRef = tr w2.errorFormatter.descend(pe) w2.lhs = nil w2.rhs = nil w2.out = nil - return &w2 + return w2 +} + +func (w *mergingWalker) finishDescent(w2 *mergingWalker) { + // if the descent caused a realloc, ensure that we reuse the buffer + // for the next sibling. + w.errorFormatter = w2.errorFormatter.parent() + *w.spareWalkers = append(*w.spareWalkers, w2) } func (w *mergingWalker) derefMap(prefix string, v *value.Value, dest **value.Map) (errs ValidationErrors) { @@ -198,6 +216,7 @@ func (w *mergingWalker) visitListItems(t schema.List, lhs, rhs *value.List) (err } else if w2.out != nil { out.Items = append(out.Items, *w2.out) } + w.finishDescent(w2) // Keep track of children that have been handled delete(observedRHS, keyStr) } @@ -212,6 +231,7 @@ func (w *mergingWalker) visitListItems(t schema.List, lhs, rhs *value.List) (err } else if w2.out != nil { out.Items = append(out.Items, *w2.out) } + w.finishDescent(w2) } } @@ -272,13 +292,13 @@ func (w *mergingWalker) visitMapItems(t schema.Map, lhs, rhs *value.Map) (errs V } if lhs != nil { - for _, litem := range lhs.Items { - name := litem.Name + for i := range lhs.Items { + litem := &lhs.Items[i] fieldType := t.ElementType - if ft, ok := fieldTypes[name]; ok { + if ft, ok := fieldTypes[litem.Name]; ok { fieldType = ft } - w2 := w.prepareDescent(fieldpath.PathElement{FieldName: &name}, fieldType) + w2 := w.prepareDescent(fieldpath.PathElement{FieldName: &litem.Name}, fieldType) w2.lhs = &litem.Value if rhs != nil { if ritem, ok := rhs.Get(litem.Name); ok { @@ -288,31 +308,33 @@ func (w *mergingWalker) visitMapItems(t schema.Map, lhs, rhs *value.Map) (errs V if newErrs := w2.merge(); len(newErrs) > 0 { errs = append(errs, newErrs...) } else if w2.out != nil { - out.Set(name, *w2.out) + out.Items = append(out.Items, value.Field{litem.Name, *w2.out}) } + w.finishDescent(w2) } } if rhs != nil { - for _, ritem := range rhs.Items { + for j := range rhs.Items { + ritem := &rhs.Items[j] if lhs != nil { if _, ok := lhs.Get(ritem.Name); ok { continue } } - name := ritem.Name fieldType := t.ElementType - if ft, ok := fieldTypes[name]; ok { + if ft, ok := fieldTypes[ritem.Name]; ok { fieldType = ft } - w2 := w.prepareDescent(fieldpath.PathElement{FieldName: &name}, fieldType) + w2 := w.prepareDescent(fieldpath.PathElement{FieldName: &ritem.Name}, fieldType) w2.rhs = &ritem.Value if newErrs := w2.merge(); len(newErrs) > 0 { errs = append(errs, newErrs...) } else if w2.out != nil { - out.Set(name, *w2.out) + out.Items = append(out.Items, value.Field{ritem.Name, *w2.out}) } + w.finishDescent(w2) } } diff --git a/vendor/sigs.k8s.io/structured-merge-diff/typed/typed.go b/vendor/sigs.k8s.io/structured-merge-diff/typed/typed.go index 2f8323a9def..5db5018e5a1 100644 --- a/vendor/sigs.k8s.io/structured-merge-diff/typed/typed.go +++ b/vendor/sigs.k8s.io/structured-merge-diff/typed/typed.go @@ -18,7 +18,7 @@ package typed import ( "fmt" - "reflect" + "sync" "sigs.k8s.io/structured-merge-diff/fieldpath" "sigs.k8s.io/structured-merge-diff/schema" @@ -67,7 +67,9 @@ func (tv TypedValue) AsValue() *value.Value { // Validate returns an error with a list of every spec violation. func (tv TypedValue) Validate() error { - if errs := tv.walker().validate(); len(errs) != 0 { + w := tv.walker() + defer w.finished() + if errs := w.validate(); len(errs) != 0 { return errs } return nil @@ -78,6 +80,7 @@ func (tv TypedValue) Validate() error { func (tv TypedValue) ToFieldSet() (*fieldpath.Set, error) { s := fieldpath.NewSet() w := tv.walker() + defer w.finished() w.leafFieldCallback = func(p fieldpath.Path) { s.Insert(p) } w.nodeFieldCallback = func(p fieldpath.Path) { s.Insert(p) } if errs := w.validate(); len(errs) != 0 { @@ -118,8 +121,8 @@ func (tv TypedValue) Compare(rhs *TypedValue) (c *Comparison, err error) { c.Added.Insert(w.path) } else if w.rhs == nil { c.Removed.Insert(w.path) - } else if !reflect.DeepEqual(w.rhs, w.lhs) { - // TODO: reflect.DeepEqual is not sufficient for this. + } else if !w.rhs.Equals(*w.lhs) { + // TODO: Equality is not sufficient for this. // Need to implement equality check on the value type. c.Modified.Insert(w.path) } @@ -154,6 +157,8 @@ func (tv TypedValue) RemoveItems(items *fieldpath.Set) *TypedValue { // - If discriminator changed to non-nil, all other fields but the // discriminated one will be cleared, // - Otherwise, If only one field is left, update discriminator to that value. +// +// Please note: union behavior isn't finalized yet and this is still experimental. func (tv TypedValue) NormalizeUnions(new *TypedValue) (*TypedValue, error) { var errs ValidationErrors var normalizeFn = func(w *mergingWalker) { @@ -178,6 +183,8 @@ func (tv TypedValue) NormalizeUnions(new *TypedValue) (*TypedValue, error) { // NormalizeUnionsApply specifically normalize unions on apply. It // validates that the applied union is correct (there should be no // ambiguity there), and clear the fields according to the sent intent. +// +// Please note: union behavior isn't finalized yet and this is still experimental. func (tv TypedValue) NormalizeUnionsApply(new *TypedValue) (*TypedValue, error) { var errs ValidationErrors var normalizeFn = func(w *mergingWalker) { @@ -204,24 +211,41 @@ func (tv TypedValue) Empty() *TypedValue { return &tv } +var mwPool = sync.Pool{ + New: func() interface{} { return &mergingWalker{} }, +} + func merge(lhs, rhs *TypedValue, rule, postRule mergeRule) (*TypedValue, error) { if lhs.schema != rhs.schema { return nil, errorFormatter{}. errorf("expected objects with types from the same schema") } - if !reflect.DeepEqual(lhs.typeRef, rhs.typeRef) { + if !lhs.typeRef.Equals(rhs.typeRef) { return nil, errorFormatter{}. errorf("expected objects of the same type, but got %v and %v", lhs.typeRef, rhs.typeRef) } - mw := mergingWalker{ - lhs: &lhs.value, - rhs: &rhs.value, - schema: lhs.schema, - typeRef: lhs.typeRef, - rule: rule, - postItemHook: postRule, - } + mw := mwPool.Get().(*mergingWalker) + defer func() { + mw.lhs = nil + mw.rhs = nil + mw.schema = nil + mw.typeRef = schema.TypeRef{} + mw.rule = nil + mw.postItemHook = nil + mw.out = nil + mw.inLeaf = false + + mwPool.Put(mw) + }() + + mw.lhs = &lhs.value + mw.rhs = &rhs.value + mw.schema = lhs.schema + mw.typeRef = lhs.typeRef + mw.rule = rule + mw.postItemHook = postRule + errs := mw.merge() if len(errs) > 0 { return nil, errs diff --git a/vendor/sigs.k8s.io/structured-merge-diff/typed/validate.go b/vendor/sigs.k8s.io/structured-merge-diff/typed/validate.go index 1ed454c1593..0a763247308 100644 --- a/vendor/sigs.k8s.io/structured-merge-diff/typed/validate.go +++ b/vendor/sigs.k8s.io/structured-merge-diff/typed/validate.go @@ -17,17 +17,33 @@ limitations under the License. package typed import ( + "sync" + "sigs.k8s.io/structured-merge-diff/fieldpath" "sigs.k8s.io/structured-merge-diff/schema" "sigs.k8s.io/structured-merge-diff/value" ) +var vPool = sync.Pool{ + New: func() interface{} { return &validatingObjectWalker{} }, +} + func (tv TypedValue) walker() *validatingObjectWalker { - return &validatingObjectWalker{ - value: tv.value, - schema: tv.schema, - typeRef: tv.typeRef, - } + v := vPool.Get().(*validatingObjectWalker) + v.value = tv.value + v.schema = tv.schema + v.typeRef = tv.typeRef + return v +} + +func (v *validatingObjectWalker) finished() { + v.value = value.Value{} + v.schema = nil + v.typeRef = schema.TypeRef{} + v.leafFieldCallback = nil + v.nodeFieldCallback = nil + v.inLeaf = false + vPool.Put(v) } type validatingObjectWalker struct { @@ -49,9 +65,36 @@ type validatingObjectWalker struct { // internal housekeeping--don't set when constructing. inLeaf bool // Set to true if we're in a "big leaf"--atomic map/list + + // Allocate only as many walkers as needed for the depth by storing them here. + spareWalkers *[]*validatingObjectWalker } -func (v validatingObjectWalker) validate() ValidationErrors { +func (v *validatingObjectWalker) prepareDescent(pe fieldpath.PathElement, tr schema.TypeRef) *validatingObjectWalker { + if v.spareWalkers == nil { + // first descent. + v.spareWalkers = &[]*validatingObjectWalker{} + } + var v2 *validatingObjectWalker + if n := len(*v.spareWalkers); n > 0 { + v2, *v.spareWalkers = (*v.spareWalkers)[n-1], (*v.spareWalkers)[:n-1] + } else { + v2 = &validatingObjectWalker{} + } + *v2 = *v + v2.typeRef = tr + v2.errorFormatter.descend(pe) + return v2 +} + +func (v *validatingObjectWalker) finishDescent(v2 *validatingObjectWalker) { + // if the descent caused a realloc, ensure that we reuse the buffer + // for the next sibling. + v.errorFormatter = v2.errorFormatter.parent() + *v.spareWalkers = append(*v.spareWalkers, v2) +} + +func (v *validatingObjectWalker) validate() ValidationErrors { return resolveSchema(v.schema, v.typeRef, &v.value, v) } @@ -87,7 +130,7 @@ func (v *validatingObjectWalker) doNode() { } } -func (v validatingObjectWalker) doScalar(t schema.Scalar) ValidationErrors { +func (v *validatingObjectWalker) doScalar(t schema.Scalar) ValidationErrors { if errs := v.validateScalar(t, &v.value, ""); len(errs) > 0 { return errs } @@ -98,7 +141,7 @@ func (v validatingObjectWalker) doScalar(t schema.Scalar) ValidationErrors { return nil } -func (v validatingObjectWalker) visitListItems(t schema.List, list *value.List) (errs ValidationErrors) { +func (v *validatingObjectWalker) visitListItems(t schema.List, list *value.List) (errs ValidationErrors) { observedKeys := map[string]struct{}{} for i, child := range list.Items { pe, err := listItemToPathElement(t, i, child) @@ -114,18 +157,17 @@ func (v validatingObjectWalker) visitListItems(t schema.List, list *value.List) errs = append(errs, v.errorf("duplicate entries for key %v", keyStr)...) } observedKeys[keyStr] = struct{}{} - v2 := v - v2.errorFormatter.descend(pe) + v2 := v.prepareDescent(pe, t.ElementType) v2.value = child - v2.typeRef = t.ElementType errs = append(errs, v2.validate()...) v2.doNode() + v.finishDescent(v2) } return errs } -func (v validatingObjectWalker) doList(t schema.List) (errs ValidationErrors) { +func (v *validatingObjectWalker) doList(t schema.List) (errs ValidationErrors) { list, err := listValue(v.value) if err != nil { return v.error(err) @@ -144,7 +186,7 @@ func (v validatingObjectWalker) doList(t schema.List) (errs ValidationErrors) { return errs } -func (v validatingObjectWalker) visitMapItems(t schema.Map, m *value.Map) (errs ValidationErrors) { +func (v *validatingObjectWalker) visitMapItems(t schema.Map, m *value.Map) (errs ValidationErrors) { fieldTypes := map[string]schema.TypeRef{} for i := range t.Fields { // I don't want to use the loop variable since a reference @@ -153,25 +195,27 @@ func (v validatingObjectWalker) visitMapItems(t schema.Map, m *value.Map) (errs fieldTypes[f.Name] = f.Type } - for _, item := range m.Items { - v2 := v - name := item.Name - v2.errorFormatter.descend(fieldpath.PathElement{FieldName: &name}) - v2.value = item.Value + for i := range m.Items { + item := &m.Items[i] + pe := fieldpath.PathElement{FieldName: &item.Name} - var ok bool - if v2.typeRef, ok = fieldTypes[name]; ok { + if tr, ok := fieldTypes[item.Name]; ok { + v2 := v.prepareDescent(pe, tr) + v2.value = item.Value errs = append(errs, v2.validate()...) + v.finishDescent(v2) } else { - v2.typeRef = t.ElementType + v2 := v.prepareDescent(pe, t.ElementType) + v2.value = item.Value errs = append(errs, v2.validate()...) v2.doNode() + v.finishDescent(v2) } } return errs } -func (v validatingObjectWalker) doMap(t schema.Map) (errs ValidationErrors) { +func (v *validatingObjectWalker) doMap(t schema.Map) (errs ValidationErrors) { m, err := mapValue(v.value) if err != nil { return v.error(err) diff --git a/vendor/sigs.k8s.io/structured-merge-diff/value/value.go b/vendor/sigs.k8s.io/structured-merge-diff/value/value.go index 176f1c6794b..1ce63e1c970 100644 --- a/vendor/sigs.k8s.io/structured-merge-diff/value/value.go +++ b/vendor/sigs.k8s.io/structured-merge-diff/value/value.go @@ -34,6 +34,11 @@ type Value struct { Null bool // represents an explicit `"foo" = null` } +// Equals returns true iff the two values are equal. +func (v Value) Equals(rhs Value) bool { + return !v.Less(rhs) && !rhs.Less(v) +} + // Less provides a total ordering for Value (so that they can be sorted, even // if they are of different types). func (v Value) Less(rhs Value) bool { @@ -167,7 +172,7 @@ type Map struct { // may be nil; lazily constructed. // TODO: Direct modifications to Items above will cause serious problems. - index map[string]*Field + index map[string]int // may be empty; lazily constructed. // TODO: Direct modifications to Items above will cause serious problems. order []int @@ -264,14 +269,16 @@ func (m *Map) Less(rhs *Map) bool { // Get returns the (Field, true) or (nil, false) if it is not present func (m *Map) Get(key string) (*Field, bool) { if m.index == nil { - m.index = map[string]*Field{} + m.index = map[string]int{} for i := range m.Items { - f := &m.Items[i] - m.index[f.Name] = f + m.index[m.Items[i].Name] = i } } f, ok := m.index[key] - return f, ok + if !ok { + return nil, false + } + return &m.Items[f], true } // Set inserts or updates the given item. @@ -281,7 +288,8 @@ func (m *Map) Set(key string, value Value) { return } m.Items = append(m.Items, Field{Name: key, Value: value}) - m.index = nil // Since the append might have reallocated + i := len(m.Items) - 1 + m.index[key] = i m.order = nil }