Bump to latest SMD to pick up performance optimizations
This commit is contained in:
parent
9617322727
commit
d9faaca647
2
go.mod
2
go.mod
@ -574,7 +574,7 @@ replace (
|
|||||||
mvdan.cc/unparam => mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34
|
mvdan.cc/unparam => mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34
|
||||||
rsc.io/pdf => rsc.io/pdf v0.1.1
|
rsc.io/pdf => rsc.io/pdf v0.1.1
|
||||||
sigs.k8s.io/kustomize => sigs.k8s.io/kustomize v2.0.3+incompatible
|
sigs.k8s.io/kustomize => sigs.k8s.io/kustomize v2.0.3+incompatible
|
||||||
sigs.k8s.io/structured-merge-diff/v3 => sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200121225636-0fb62c1057dd
|
sigs.k8s.io/structured-merge-diff/v3 => sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c
|
||||||
sigs.k8s.io/yaml => sigs.k8s.io/yaml v1.2.0
|
sigs.k8s.io/yaml => sigs.k8s.io/yaml v1.2.0
|
||||||
sourcegraph.com/sqs/pbtypes => sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4
|
sourcegraph.com/sqs/pbtypes => sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4
|
||||||
vbom.ml/util => vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc
|
vbom.ml/util => vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc
|
||||||
|
4
go.sum
4
go.sum
@ -621,8 +621,8 @@ mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34/go.mod h1:H6SUd1XjIs+qQCyskX
|
|||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
|
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/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200121225636-0fb62c1057dd h1:RtLwJkS5lCLrbjdIqQdKiwZ6LrlGuLVdIcVhkUfsaIA=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200121225636-0fb62c1057dd/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
||||||
|
2
staging/src/k8s.io/api/go.sum
generated
2
staging/src/k8s.io/api/go.sum
generated
@ -100,6 +100,8 @@ k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
|||||||
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||||
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
@ -463,8 +463,8 @@ k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8E
|
|||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874 h1:0KsuGbLhWdIxv5DA1OnbFz5hI/Co9kuxMfMUa5YsAHY=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874 h1:0KsuGbLhWdIxv5DA1OnbFz5hI/Co9kuxMfMUa5YsAHY=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200121225636-0fb62c1057dd h1:RtLwJkS5lCLrbjdIqQdKiwZ6LrlGuLVdIcVhkUfsaIA=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200121225636-0fb62c1057dd/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
@ -33,6 +33,7 @@ require (
|
|||||||
gopkg.in/yaml.v2 v2.2.8
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
k8s.io/klog v1.0.0
|
k8s.io/klog v1.0.0
|
||||||
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c
|
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c
|
||||||
sigs.k8s.io/yaml v1.2.0
|
sigs.k8s.io/yaml v1.2.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
2
staging/src/k8s.io/apimachinery/go.sum
generated
2
staging/src/k8s.io/apimachinery/go.sum
generated
@ -118,6 +118,8 @@ k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
|||||||
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c h1:/KUFqjjqAcY4Us6luF5RDNZ16KJtb49HfR3ZHB9qYXM=
|
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c h1:/KUFqjjqAcY4Us6luF5RDNZ16KJtb49HfR3ZHB9qYXM=
|
||||||
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
@ -634,6 +634,11 @@ func (q Quantity) MarshalJSON() ([]byte, error) {
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToUnstructured implements the value.UnstructuredConverter interface.
|
||||||
|
func (q Quantity) ToUnstructured() interface{} {
|
||||||
|
return q.String()
|
||||||
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements the json.Unmarshaller interface.
|
// UnmarshalJSON implements the json.Unmarshaller interface.
|
||||||
// TODO: Remove support for leading/trailing whitespace
|
// TODO: Remove support for leading/trailing whitespace
|
||||||
func (q *Quantity) UnmarshalJSON(value []byte) error {
|
func (q *Quantity) UnmarshalJSON(value []byte) error {
|
||||||
|
@ -49,6 +49,11 @@ func (d Duration) MarshalJSON() ([]byte, error) {
|
|||||||
return json.Marshal(d.Duration.String())
|
return json.Marshal(d.Duration.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToUnstructured implements the value.UnstructuredConverter interface.
|
||||||
|
func (d Duration) ToUnstructured() interface{} {
|
||||||
|
return d.Duration.String()
|
||||||
|
}
|
||||||
|
|
||||||
// OpenAPISchemaType is used by the kube-openapi generator when constructing
|
// OpenAPISchemaType is used by the kube-openapi generator when constructing
|
||||||
// the OpenAPI spec of this type.
|
// the OpenAPI spec of this type.
|
||||||
//
|
//
|
||||||
|
@ -153,6 +153,16 @@ func (t Time) MarshalJSON() ([]byte, error) {
|
|||||||
return buf, nil
|
return buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToUnstructured implements the value.UnstructuredConverter interface.
|
||||||
|
func (t Time) ToUnstructured() interface{} {
|
||||||
|
if t.IsZero() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
buf := make([]byte, 0, len(time.RFC3339))
|
||||||
|
buf = t.UTC().AppendFormat(buf, time.RFC3339)
|
||||||
|
return string(buf)
|
||||||
|
}
|
||||||
|
|
||||||
// OpenAPISchemaType is used by the kube-openapi generator when constructing
|
// OpenAPISchemaType is used by the kube-openapi generator when constructing
|
||||||
// the OpenAPI spec of this type.
|
// the OpenAPI spec of this type.
|
||||||
//
|
//
|
||||||
|
@ -72,6 +72,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
|
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
|
"//vendor/sigs.k8s.io/structured-merge-diff/v3/value:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
encodingjson "encoding/json"
|
encodingjson "encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
@ -32,6 +31,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/conversion"
|
"k8s.io/apimachinery/pkg/conversion"
|
||||||
"k8s.io/apimachinery/pkg/util/json"
|
"k8s.io/apimachinery/pkg/util/json"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
|
"sigs.k8s.io/structured-merge-diff/v3/value"
|
||||||
|
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
)
|
)
|
||||||
@ -68,8 +68,6 @@ func newFieldsCache() *fieldsCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
marshalerType = reflect.TypeOf(new(encodingjson.Marshaler)).Elem()
|
|
||||||
unmarshalerType = reflect.TypeOf(new(encodingjson.Unmarshaler)).Elem()
|
|
||||||
mapStringInterfaceType = reflect.TypeOf(map[string]interface{}{})
|
mapStringInterfaceType = reflect.TypeOf(map[string]interface{}{})
|
||||||
stringType = reflect.TypeOf(string(""))
|
stringType = reflect.TypeOf(string(""))
|
||||||
fieldCache = newFieldsCache()
|
fieldCache = newFieldsCache()
|
||||||
@ -205,13 +203,9 @@ func fromUnstructured(sv, dv reflect.Value) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if the object has a custom JSON marshaller/unmarshaller.
|
// Check if the object has a custom JSON marshaller/unmarshaller.
|
||||||
if reflect.PtrTo(dt).Implements(unmarshalerType) {
|
entry := value.TypeReflectEntryOf(dv.Type())
|
||||||
data, err := json.Marshal(sv.Interface())
|
if entry.CanConvertFromUnstructured() {
|
||||||
if err != nil {
|
return entry.FromUnstructured(sv, dv)
|
||||||
return fmt.Errorf("error encoding %s to json: %v", st.String(), err)
|
|
||||||
}
|
|
||||||
unmarshaler := dv.Addr().Interface().(encodingjson.Unmarshaler)
|
|
||||||
return unmarshaler.UnmarshalJSON(data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch dt.Kind() {
|
switch dt.Kind() {
|
||||||
@ -481,94 +475,19 @@ func toUnstructuredViaJSON(obj interface{}, u *map[string]interface{}) error {
|
|||||||
return json.Unmarshal(data, u)
|
return json.Unmarshal(data, u)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
nullBytes = []byte("null")
|
|
||||||
trueBytes = []byte("true")
|
|
||||||
falseBytes = []byte("false")
|
|
||||||
)
|
|
||||||
|
|
||||||
func getMarshaler(v reflect.Value) (encodingjson.Marshaler, bool) {
|
|
||||||
// Check value receivers if v is not a pointer and pointer receivers if v is a pointer
|
|
||||||
if v.Type().Implements(marshalerType) {
|
|
||||||
return v.Interface().(encodingjson.Marshaler), true
|
|
||||||
}
|
|
||||||
// Check pointer receivers if v is not a pointer
|
|
||||||
if v.Kind() != reflect.Ptr && v.CanAddr() {
|
|
||||||
v = v.Addr()
|
|
||||||
if v.Type().Implements(marshalerType) {
|
|
||||||
return v.Interface().(encodingjson.Marshaler), true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func toUnstructured(sv, dv reflect.Value) error {
|
func toUnstructured(sv, dv reflect.Value) error {
|
||||||
// Check if the object has a custom JSON marshaller/unmarshaller.
|
// Check if the object has a custom string converter.
|
||||||
if marshaler, ok := getMarshaler(sv); ok {
|
entry := value.TypeReflectEntryOf(sv.Type())
|
||||||
if sv.Kind() == reflect.Ptr && sv.IsNil() {
|
if entry.CanConvertToUnstructured() {
|
||||||
// We're done - we don't need to store anything.
|
v, err := entry.ToUnstructured(sv)
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := marshaler.MarshalJSON()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
switch {
|
if v != nil {
|
||||||
case len(data) == 0:
|
dv.Set(reflect.ValueOf(v))
|
||||||
return fmt.Errorf("error decoding from json: empty value")
|
|
||||||
|
|
||||||
case bytes.Equal(data, nullBytes):
|
|
||||||
// We're done - we don't need to store anything.
|
|
||||||
|
|
||||||
case bytes.Equal(data, trueBytes):
|
|
||||||
dv.Set(reflect.ValueOf(true))
|
|
||||||
|
|
||||||
case bytes.Equal(data, falseBytes):
|
|
||||||
dv.Set(reflect.ValueOf(false))
|
|
||||||
|
|
||||||
case data[0] == '"':
|
|
||||||
var result string
|
|
||||||
err := json.Unmarshal(data, &result)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error decoding string from json: %v", err)
|
|
||||||
}
|
|
||||||
dv.Set(reflect.ValueOf(result))
|
|
||||||
|
|
||||||
case data[0] == '{':
|
|
||||||
result := make(map[string]interface{})
|
|
||||||
err := json.Unmarshal(data, &result)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error decoding object from json: %v", err)
|
|
||||||
}
|
|
||||||
dv.Set(reflect.ValueOf(result))
|
|
||||||
|
|
||||||
case data[0] == '[':
|
|
||||||
result := make([]interface{}, 0)
|
|
||||||
err := json.Unmarshal(data, &result)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error decoding array from json: %v", err)
|
|
||||||
}
|
|
||||||
dv.Set(reflect.ValueOf(result))
|
|
||||||
|
|
||||||
default:
|
|
||||||
var (
|
|
||||||
resultInt int64
|
|
||||||
resultFloat float64
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
if err = json.Unmarshal(data, &resultInt); err == nil {
|
|
||||||
dv.Set(reflect.ValueOf(resultInt))
|
|
||||||
} else if err = json.Unmarshal(data, &resultFloat); err == nil {
|
|
||||||
dv.Set(reflect.ValueOf(resultFloat))
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("error decoding number from json: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
st := sv.Type()
|
st := sv.Type()
|
||||||
switch st.Kind() {
|
switch st.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
|
@ -51,7 +51,7 @@ require (
|
|||||||
k8s.io/klog v1.0.0
|
k8s.io/klog v1.0.0
|
||||||
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c
|
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c
|
||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200121225636-0fb62c1057dd
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c
|
||||||
sigs.k8s.io/yaml v1.2.0
|
sigs.k8s.io/yaml v1.2.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
4
staging/src/k8s.io/apiserver/go.sum
generated
4
staging/src/k8s.io/apiserver/go.sum
generated
@ -372,8 +372,8 @@ k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8E
|
|||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874 h1:0KsuGbLhWdIxv5DA1OnbFz5hI/Co9kuxMfMUa5YsAHY=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874 h1:0KsuGbLhWdIxv5DA1OnbFz5hI/Co9kuxMfMUa5YsAHY=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200121225636-0fb62c1057dd h1:RtLwJkS5lCLrbjdIqQdKiwZ6LrlGuLVdIcVhkUfsaIA=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200121225636-0fb62c1057dd/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
@ -67,9 +67,13 @@ go_test(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal:go_default_library",
|
||||||
"//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library",
|
"//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library",
|
||||||
"//vendor/k8s.io/kube-openapi/pkg/util/proto/testing:go_default_library",
|
"//vendor/k8s.io/kube-openapi/pkg/util/proto/testing:go_default_library",
|
||||||
"//vendor/sigs.k8s.io/structured-merge-diff/v3/fieldpath:go_default_library",
|
"//vendor/sigs.k8s.io/structured-merge-diff/v3/fieldpath:go_default_library",
|
||||||
|
"//vendor/sigs.k8s.io/structured-merge-diff/v3/merge:go_default_library",
|
||||||
|
"//vendor/sigs.k8s.io/structured-merge-diff/v3/typed:go_default_library",
|
||||||
"//vendor/sigs.k8s.io/yaml:go_default_library",
|
"//vendor/sigs.k8s.io/yaml:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -33,9 +33,15 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
|
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
|
||||||
|
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal"
|
||||||
|
|
||||||
"k8s.io/kube-openapi/pkg/util/proto"
|
"k8s.io/kube-openapi/pkg/util/proto"
|
||||||
prototesting "k8s.io/kube-openapi/pkg/util/proto/testing"
|
prototesting "k8s.io/kube-openapi/pkg/util/proto/testing"
|
||||||
|
"sigs.k8s.io/structured-merge-diff/v3/fieldpath"
|
||||||
|
"sigs.k8s.io/structured-merge-diff/v3/merge"
|
||||||
|
"sigs.k8s.io/structured-merge-diff/v3/typed"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -45,9 +51,17 @@ var fakeSchema = prototesting.Fake{
|
|||||||
"api", "openapi-spec", "swagger.json"),
|
"api", "openapi-spec", "swagger.json"),
|
||||||
}
|
}
|
||||||
|
|
||||||
type fakeObjectConvertor struct{}
|
type fakeObjectConvertor struct {
|
||||||
|
converter merge.Converter
|
||||||
|
apiVersion fieldpath.APIVersion
|
||||||
|
}
|
||||||
|
|
||||||
func (c *fakeObjectConvertor) Convert(in, out, context interface{}) error {
|
func (c *fakeObjectConvertor) Convert(in, out, context interface{}) error {
|
||||||
|
if typedValue, ok := in.(*typed.TypedValue); ok {
|
||||||
|
var err error
|
||||||
|
out, err = c.converter.Convert(typedValue, c.apiVersion)
|
||||||
|
return err
|
||||||
|
}
|
||||||
out = in
|
out = in
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -71,18 +85,14 @@ type TestFieldManager struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewTestFieldManager(gvk schema.GroupVersionKind) TestFieldManager {
|
func NewTestFieldManager(gvk schema.GroupVersionKind) TestFieldManager {
|
||||||
d, err := fakeSchema.OpenAPISchema()
|
m := NewFakeOpenAPIModels()
|
||||||
if err != nil {
|
tc := NewFakeTypeConverter(m)
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
m, err := proto.NewOpenAPIData(d)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
converter := internal.NewVersionConverter(tc, &fakeObjectConvertor{}, gvk.GroupVersion())
|
||||||
|
apiVersion := fieldpath.APIVersion(gvk.GroupVersion().String())
|
||||||
f, err := fieldmanager.NewStructuredMergeManager(
|
f, err := fieldmanager.NewStructuredMergeManager(
|
||||||
m,
|
m,
|
||||||
&fakeObjectConvertor{},
|
&fakeObjectConvertor{converter, apiVersion},
|
||||||
&fakeObjectDefaulter{},
|
&fakeObjectDefaulter{},
|
||||||
gvk.GroupVersion(),
|
gvk.GroupVersion(),
|
||||||
gvk.GroupVersion(),
|
gvk.GroupVersion(),
|
||||||
@ -102,6 +112,26 @@ func NewTestFieldManager(gvk schema.GroupVersionKind) TestFieldManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewFakeTypeConverter(m proto.Models) internal.TypeConverter {
|
||||||
|
tc, err := internal.NewTypeConverter(m, false)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("Failed to build TypeConverter: %v", err))
|
||||||
|
}
|
||||||
|
return tc
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFakeOpenAPIModels() proto.Models {
|
||||||
|
d, err := fakeSchema.OpenAPISchema()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
m, err := proto.NewOpenAPIData(d)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
func (f *TestFieldManager) Reset() {
|
func (f *TestFieldManager) Reset() {
|
||||||
f.liveObj = f.emptyObj.DeepCopyObject()
|
f.liveObj = f.emptyObj.DeepCopyObject()
|
||||||
}
|
}
|
||||||
@ -393,16 +423,24 @@ func BenchmarkNewObject(b *testing.B) {
|
|||||||
obj: getObjectBytes("endpoints.yaml"),
|
obj: getObjectBytes("endpoints.yaml"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
scheme := runtime.NewScheme()
|
||||||
|
if err := corev1.AddToScheme(scheme); err != nil {
|
||||||
|
b.Fatalf("Failed to add to scheme: %v", err)
|
||||||
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
b.Run(test.gvk.Kind, func(b *testing.B) {
|
b.Run(test.gvk.Kind, func(b *testing.B) {
|
||||||
f := NewTestFieldManager(test.gvk)
|
f := NewTestFieldManager(test.gvk)
|
||||||
|
|
||||||
newObj := &unstructured.Unstructured{Object: map[string]interface{}{}}
|
decoder := serializer.NewCodecFactory(scheme).UniversalDecoder(test.gvk.GroupVersion())
|
||||||
if err := yaml.Unmarshal(test.obj, &newObj.Object); err != nil {
|
newObj, err := runtime.Decode(decoder, test.obj)
|
||||||
|
if err != nil {
|
||||||
b.Fatalf("Failed to parse yaml object: %v", err)
|
b.Fatalf("Failed to parse yaml object: %v", err)
|
||||||
}
|
}
|
||||||
newObj.SetManagedFields([]metav1.ManagedFieldsEntry{
|
objMeta, err := meta.Accessor(newObj)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("Failed to get object meta: %v", err)
|
||||||
|
}
|
||||||
|
objMeta.SetManagedFields([]metav1.ManagedFieldsEntry{
|
||||||
{
|
{
|
||||||
Manager: "default",
|
Manager: "default",
|
||||||
Operation: "Update",
|
Operation: "Update",
|
||||||
@ -463,6 +501,152 @@ func BenchmarkNewObject(b *testing.B) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toUnstructured(b *testing.B, o runtime.Object) *unstructured.Unstructured {
|
||||||
|
u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(o)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("Failed to unmarshal to json: %v", err)
|
||||||
|
}
|
||||||
|
return &unstructured.Unstructured{Object: u}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkConvertObjectToTyped(b *testing.B) {
|
||||||
|
tests := []struct {
|
||||||
|
gvk schema.GroupVersionKind
|
||||||
|
obj []byte
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
gvk: schema.FromAPIVersionAndKind("v1", "Pod"),
|
||||||
|
obj: getObjectBytes("pod.yaml"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gvk: schema.FromAPIVersionAndKind("v1", "Node"),
|
||||||
|
obj: getObjectBytes("node.yaml"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gvk: schema.FromAPIVersionAndKind("v1", "Endpoints"),
|
||||||
|
obj: getObjectBytes("endpoints.yaml"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
scheme := runtime.NewScheme()
|
||||||
|
if err := corev1.AddToScheme(scheme); err != nil {
|
||||||
|
b.Fatalf("Failed to add to scheme: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
b.Run(test.gvk.Kind, func(b *testing.B) {
|
||||||
|
decoder := serializer.NewCodecFactory(scheme).UniversalDecoder(test.gvk.GroupVersion())
|
||||||
|
m := NewFakeOpenAPIModels()
|
||||||
|
typeConverter := NewFakeTypeConverter(m)
|
||||||
|
|
||||||
|
structured, err := runtime.Decode(decoder, test.obj)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("Failed to parse yaml object: %v", err)
|
||||||
|
}
|
||||||
|
b.Run("structured", func(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
|
for pb.Next() {
|
||||||
|
_, err := typeConverter.ObjectToTyped(structured)
|
||||||
|
if err != nil {
|
||||||
|
b.Errorf("Error in ObjectToTyped: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
unstructured := toUnstructured(b, structured)
|
||||||
|
b.Run("unstructured", func(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
|
for pb.Next() {
|
||||||
|
_, err := typeConverter.ObjectToTyped(unstructured)
|
||||||
|
if err != nil {
|
||||||
|
b.Errorf("Error in ObjectToTyped: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkCompare(b *testing.B) {
|
||||||
|
tests := []struct {
|
||||||
|
gvk schema.GroupVersionKind
|
||||||
|
obj []byte
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
gvk: schema.FromAPIVersionAndKind("v1", "Pod"),
|
||||||
|
obj: getObjectBytes("pod.yaml"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gvk: schema.FromAPIVersionAndKind("v1", "Node"),
|
||||||
|
obj: getObjectBytes("node.yaml"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gvk: schema.FromAPIVersionAndKind("v1", "Endpoints"),
|
||||||
|
obj: getObjectBytes("endpoints.yaml"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
scheme := runtime.NewScheme()
|
||||||
|
if err := corev1.AddToScheme(scheme); err != nil {
|
||||||
|
b.Fatalf("Failed to add to scheme: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
b.Run(test.gvk.Kind, func(b *testing.B) {
|
||||||
|
decoder := serializer.NewCodecFactory(scheme).UniversalDecoder(test.gvk.GroupVersion())
|
||||||
|
m := NewFakeOpenAPIModels()
|
||||||
|
typeConverter := NewFakeTypeConverter(m)
|
||||||
|
|
||||||
|
structured, err := runtime.Decode(decoder, test.obj)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
tv1, err := typeConverter.ObjectToTyped(structured)
|
||||||
|
if err != nil {
|
||||||
|
b.Errorf("Error in ObjectToTyped: %v", err)
|
||||||
|
}
|
||||||
|
tv2, err := typeConverter.ObjectToTyped(structured)
|
||||||
|
if err != nil {
|
||||||
|
b.Errorf("Error in ObjectToTyped: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Run("structured", func(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
_, err = tv1.Compare(tv2)
|
||||||
|
if err != nil {
|
||||||
|
b.Errorf("Error in ObjectToTyped: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
unstructured := toUnstructured(b, structured)
|
||||||
|
utv1, err := typeConverter.ObjectToTyped(unstructured)
|
||||||
|
if err != nil {
|
||||||
|
b.Errorf("Error in ObjectToTyped: %v", err)
|
||||||
|
}
|
||||||
|
utv2, err := typeConverter.ObjectToTyped(unstructured)
|
||||||
|
if err != nil {
|
||||||
|
b.Errorf("Error in ObjectToTyped: %v", err)
|
||||||
|
}
|
||||||
|
b.Run("unstructured", func(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
|
for pb.Next() {
|
||||||
|
_, err = utv1.Compare(utv2)
|
||||||
|
if err != nil {
|
||||||
|
b.Errorf("Error in ObjectToTyped: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkRepeatedUpdate(b *testing.B) {
|
func BenchmarkRepeatedUpdate(b *testing.B) {
|
||||||
f := NewTestFieldManager(schema.FromAPIVersionAndKind("v1", "Pod"))
|
f := NewTestFieldManager(schema.FromAPIVersionAndKind("v1", "Pod"))
|
||||||
podBytes := getObjectBytes("pod.yaml")
|
podBytes := getObjectBytes("pod.yaml")
|
||||||
|
@ -49,11 +49,12 @@ var _ TypeConverter = DeducedTypeConverter{}
|
|||||||
|
|
||||||
// ObjectToTyped converts an object into a TypedValue with a "deduced type".
|
// ObjectToTyped converts an object into a TypedValue with a "deduced type".
|
||||||
func (DeducedTypeConverter) ObjectToTyped(obj runtime.Object) (*typed.TypedValue, error) {
|
func (DeducedTypeConverter) ObjectToTyped(obj runtime.Object) (*typed.TypedValue, error) {
|
||||||
u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
|
switch o := obj.(type) {
|
||||||
if err != nil {
|
case *unstructured.Unstructured:
|
||||||
return nil, err
|
return typed.DeducedParseableType.FromUnstructured(o.UnstructuredContent())
|
||||||
|
default:
|
||||||
|
return typed.DeducedParseableType.FromStructured(obj)
|
||||||
}
|
}
|
||||||
return typed.DeducedParseableType.FromUnstructured(u)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TypedToObject transforms the typed value into a runtime.Object. That
|
// TypedToObject transforms the typed value into a runtime.Object. That
|
||||||
@ -80,16 +81,17 @@ func NewTypeConverter(models proto.Models, preserveUnknownFields bool) (TypeConv
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *typeConverter) ObjectToTyped(obj runtime.Object) (*typed.TypedValue, error) {
|
func (c *typeConverter) ObjectToTyped(obj runtime.Object) (*typed.TypedValue, error) {
|
||||||
u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
gvk := obj.GetObjectKind().GroupVersionKind()
|
gvk := obj.GetObjectKind().GroupVersionKind()
|
||||||
t := c.parser.Type(gvk)
|
t := c.parser.Type(gvk)
|
||||||
if t == nil {
|
if t == nil {
|
||||||
return nil, newNoCorrespondingTypeError(gvk)
|
return nil, newNoCorrespondingTypeError(gvk)
|
||||||
}
|
}
|
||||||
return t.FromUnstructured(u)
|
switch o := obj.(type) {
|
||||||
|
case *unstructured.Unstructured:
|
||||||
|
return t.FromUnstructured(o.UnstructuredContent())
|
||||||
|
default:
|
||||||
|
return t.FromStructured(obj)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *typeConverter) TypedToObject(value *typed.TypedValue) (runtime.Object, error) {
|
func (c *typeConverter) TypedToObject(value *typed.TypedValue) (runtime.Object, error) {
|
||||||
|
2
staging/src/k8s.io/cli-runtime/go.sum
generated
2
staging/src/k8s.io/cli-runtime/go.sum
generated
@ -248,6 +248,8 @@ k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl
|
|||||||
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
|
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/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
2
staging/src/k8s.io/client-go/go.sum
generated
2
staging/src/k8s.io/client-go/go.sum
generated
@ -200,6 +200,8 @@ k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C
|
|||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
2
staging/src/k8s.io/cloud-provider/go.sum
generated
2
staging/src/k8s.io/cloud-provider/go.sum
generated
@ -183,6 +183,8 @@ k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C
|
|||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
2
staging/src/k8s.io/cluster-bootstrap/go.sum
generated
2
staging/src/k8s.io/cluster-bootstrap/go.sum
generated
@ -104,6 +104,8 @@ k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
|||||||
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||||
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
2
staging/src/k8s.io/component-base/go.sum
generated
2
staging/src/k8s.io/component-base/go.sum
generated
@ -222,6 +222,8 @@ k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C
|
|||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
2
staging/src/k8s.io/csi-translation-lib/go.sum
generated
2
staging/src/k8s.io/csi-translation-lib/go.sum
generated
@ -162,6 +162,8 @@ k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
|||||||
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
4
staging/src/k8s.io/kube-aggregator/go.sum
generated
4
staging/src/k8s.io/kube-aggregator/go.sum
generated
@ -393,8 +393,8 @@ k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8E
|
|||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874 h1:0KsuGbLhWdIxv5DA1OnbFz5hI/Co9kuxMfMUa5YsAHY=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874 h1:0KsuGbLhWdIxv5DA1OnbFz5hI/Co9kuxMfMUa5YsAHY=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200121225636-0fb62c1057dd h1:RtLwJkS5lCLrbjdIqQdKiwZ6LrlGuLVdIcVhkUfsaIA=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200121225636-0fb62c1057dd/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
@ -193,6 +193,8 @@ k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C
|
|||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
2
staging/src/k8s.io/kube-proxy/go.sum
generated
2
staging/src/k8s.io/kube-proxy/go.sum
generated
@ -193,6 +193,8 @@ k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C
|
|||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
2
staging/src/k8s.io/kube-scheduler/go.sum
generated
2
staging/src/k8s.io/kube-scheduler/go.sum
generated
@ -193,6 +193,8 @@ k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C
|
|||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
2
staging/src/k8s.io/kubectl/go.sum
generated
2
staging/src/k8s.io/kubectl/go.sum
generated
@ -325,6 +325,8 @@ k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl
|
|||||||
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
|
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/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
2
staging/src/k8s.io/kubelet/go.sum
generated
2
staging/src/k8s.io/kubelet/go.sum
generated
@ -130,6 +130,8 @@ k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
|||||||
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||||
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
3
staging/src/k8s.io/legacy-cloud-providers/go.sum
generated
3
staging/src/k8s.io/legacy-cloud-providers/go.sum
generated
@ -368,7 +368,8 @@ k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C
|
|||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200121225636-0fb62c1057dd/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
2
staging/src/k8s.io/metrics/go.sum
generated
2
staging/src/k8s.io/metrics/go.sum
generated
@ -212,6 +212,8 @@ k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C
|
|||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
4
staging/src/k8s.io/sample-apiserver/go.sum
generated
4
staging/src/k8s.io/sample-apiserver/go.sum
generated
@ -390,8 +390,8 @@ k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8E
|
|||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874 h1:0KsuGbLhWdIxv5DA1OnbFz5hI/Co9kuxMfMUa5YsAHY=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874 h1:0KsuGbLhWdIxv5DA1OnbFz5hI/Co9kuxMfMUa5YsAHY=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200121225636-0fb62c1057dd h1:RtLwJkS5lCLrbjdIqQdKiwZ6LrlGuLVdIcVhkUfsaIA=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200121225636-0fb62c1057dd/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
2
staging/src/k8s.io/sample-cli-plugin/go.sum
generated
2
staging/src/k8s.io/sample-cli-plugin/go.sum
generated
@ -247,6 +247,8 @@ k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl
|
|||||||
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
|
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/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
2
staging/src/k8s.io/sample-controller/go.sum
generated
2
staging/src/k8s.io/sample-controller/go.sum
generated
@ -217,6 +217,8 @@ k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C
|
|||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc h1:MUttqhwRgupMiA5ps5F3d2/NLkU8EZSECTGxrQxqM54=
|
||||||
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191217005138-9e5e9d854fcc/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c h1:xQP7F7Lntt2dtYmg12WPQHObOrAyPHlMWP1JVSa79GM=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -1967,7 +1967,7 @@ sigs.k8s.io/kustomize/pkg/transformers
|
|||||||
sigs.k8s.io/kustomize/pkg/transformers/config
|
sigs.k8s.io/kustomize/pkg/transformers/config
|
||||||
sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig
|
sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig
|
||||||
sigs.k8s.io/kustomize/pkg/types
|
sigs.k8s.io/kustomize/pkg/types
|
||||||
# sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200121225636-0fb62c1057dd => sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200121225636-0fb62c1057dd
|
# sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c => sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200207200219-5e70324e7c1c
|
||||||
sigs.k8s.io/structured-merge-diff/v3/fieldpath
|
sigs.k8s.io/structured-merge-diff/v3/fieldpath
|
||||||
sigs.k8s.io/structured-merge-diff/v3/merge
|
sigs.k8s.io/structured-merge-diff/v3/merge
|
||||||
sigs.k8s.io/structured-merge-diff/v3/schema
|
sigs.k8s.io/structured-merge-diff/v3/schema
|
||||||
|
34
vendor/sigs.k8s.io/structured-merge-diff/v3/fieldpath/fromvalue.go
generated
vendored
34
vendor/sigs.k8s.io/structured-merge-diff/v3/fieldpath/fromvalue.go
generated
vendored
@ -25,9 +25,10 @@ func SetFromValue(v value.Value) *Set {
|
|||||||
s := NewSet()
|
s := NewSet()
|
||||||
|
|
||||||
w := objectWalker{
|
w := objectWalker{
|
||||||
path: Path{},
|
path: Path{},
|
||||||
value: v,
|
value: v,
|
||||||
do: func(p Path) { s.Insert(p) },
|
allocator: value.NewFreelistAllocator(),
|
||||||
|
do: func(p Path) { s.Insert(p) },
|
||||||
}
|
}
|
||||||
|
|
||||||
w.walk()
|
w.walk()
|
||||||
@ -35,8 +36,9 @@ func SetFromValue(v value.Value) *Set {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type objectWalker struct {
|
type objectWalker struct {
|
||||||
path Path
|
path Path
|
||||||
value value.Value
|
value value.Value
|
||||||
|
allocator value.Allocator
|
||||||
|
|
||||||
do func(Path)
|
do func(Path)
|
||||||
}
|
}
|
||||||
@ -55,11 +57,15 @@ func (w *objectWalker) walk() {
|
|||||||
case w.value.IsList():
|
case w.value.IsList():
|
||||||
// If the list were atomic, we'd break here, but we don't have
|
// If the list were atomic, we'd break here, but we don't have
|
||||||
// a schema, so we can't tell.
|
// a schema, so we can't tell.
|
||||||
list := w.value.AsList()
|
l := w.value.AsListUsing(w.allocator)
|
||||||
for i := 0; i < list.Length(); i++ {
|
defer w.allocator.Free(l)
|
||||||
|
iter := l.RangeUsing(w.allocator)
|
||||||
|
defer w.allocator.Free(iter)
|
||||||
|
for iter.Next() {
|
||||||
|
i, value := iter.Item()
|
||||||
w2 := *w
|
w2 := *w
|
||||||
w2.path = append(w.path, GuessBestListPathElement(i, list.At(i)))
|
w2.path = append(w.path, w.GuessBestListPathElement(i, value))
|
||||||
w2.value = list.At(i)
|
w2.value = value
|
||||||
w2.walk()
|
w2.walk()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -67,7 +73,9 @@ func (w *objectWalker) walk() {
|
|||||||
// If the map/struct were atomic, we'd break here, but we don't
|
// If the map/struct were atomic, we'd break here, but we don't
|
||||||
// have a schema, so we can't tell.
|
// have a schema, so we can't tell.
|
||||||
|
|
||||||
w.value.AsMap().Iterate(func(k string, val value.Value) bool {
|
m := w.value.AsMapUsing(w.allocator)
|
||||||
|
defer w.allocator.Free(m)
|
||||||
|
m.IterateUsing(w.allocator, func(k string, val value.Value) bool {
|
||||||
w2 := *w
|
w2 := *w
|
||||||
w2.path = append(w.path, PathElement{FieldName: &k})
|
w2.path = append(w.path, PathElement{FieldName: &k})
|
||||||
w2.value = val
|
w2.value = val
|
||||||
@ -96,7 +104,7 @@ var AssociativeListCandidateFieldNames = []string{
|
|||||||
// referencing by index is acceptable. Currently this is done by checking
|
// referencing by index is acceptable. Currently this is done by checking
|
||||||
// whether item has any of the fields listed in
|
// whether item has any of the fields listed in
|
||||||
// AssociativeListCandidateFieldNames which have scalar values.
|
// AssociativeListCandidateFieldNames which have scalar values.
|
||||||
func GuessBestListPathElement(index int, item value.Value) PathElement {
|
func (w *objectWalker) GuessBestListPathElement(index int, item value.Value) PathElement {
|
||||||
if !item.IsMap() {
|
if !item.IsMap() {
|
||||||
// Non map items could be parts of sets or regular "atomic"
|
// Non map items could be parts of sets or regular "atomic"
|
||||||
// lists. We won't try to guess whether something should be a
|
// lists. We won't try to guess whether something should be a
|
||||||
@ -104,9 +112,11 @@ func GuessBestListPathElement(index int, item value.Value) PathElement {
|
|||||||
return PathElement{Index: &index}
|
return PathElement{Index: &index}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m := item.AsMapUsing(w.allocator)
|
||||||
|
defer w.allocator.Free(m)
|
||||||
var keys value.FieldList
|
var keys value.FieldList
|
||||||
for _, name := range AssociativeListCandidateFieldNames {
|
for _, name := range AssociativeListCandidateFieldNames {
|
||||||
f, ok := item.AsMap().Get(name)
|
f, ok := m.Get(name)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
20
vendor/sigs.k8s.io/structured-merge-diff/v3/fieldpath/serialize.go
generated
vendored
20
vendor/sigs.k8s.io/structured-merge-diff/v3/fieldpath/serialize.go
generated
vendored
@ -40,7 +40,7 @@ func (s *Set) ToJSONStream(w io.Writer) error {
|
|||||||
var r reusableBuilder
|
var r reusableBuilder
|
||||||
|
|
||||||
stream.WriteObjectStart()
|
stream.WriteObjectStart()
|
||||||
err := s.emitContents_v1(false, stream, &r)
|
err := s.emitContentsV1(false, stream, &r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ func (r *reusableBuilder) reset() *bytes.Buffer {
|
|||||||
return &r.Buffer
|
return &r.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Set) emitContents_v1(includeSelf bool, stream *jsoniter.Stream, r *reusableBuilder) error {
|
func (s *Set) emitContentsV1(includeSelf bool, stream *jsoniter.Stream, r *reusableBuilder) error {
|
||||||
mi, ci := 0, 0
|
mi, ci := 0, 0
|
||||||
first := true
|
first := true
|
||||||
preWrite := func() {
|
preWrite := func() {
|
||||||
@ -97,7 +97,7 @@ func (s *Set) emitContents_v1(includeSelf bool, stream *jsoniter.Stream, r *reus
|
|||||||
mpe := s.Members.members[mi]
|
mpe := s.Members.members[mi]
|
||||||
cpe := s.Children.members[ci].pathElement
|
cpe := s.Children.members[ci].pathElement
|
||||||
|
|
||||||
if mpe.Less(cpe) {
|
if c := mpe.Compare(cpe); c < 0 {
|
||||||
preWrite()
|
preWrite()
|
||||||
if err := serializePathElementToWriter(r.reset(), mpe); err != nil {
|
if err := serializePathElementToWriter(r.reset(), mpe); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -105,14 +105,14 @@ func (s *Set) emitContents_v1(includeSelf bool, stream *jsoniter.Stream, r *reus
|
|||||||
stream.WriteObjectField(r.unsafeString())
|
stream.WriteObjectField(r.unsafeString())
|
||||||
stream.WriteEmptyObject()
|
stream.WriteEmptyObject()
|
||||||
mi++
|
mi++
|
||||||
} else if cpe.Less(mpe) {
|
} else if c > 0 {
|
||||||
preWrite()
|
preWrite()
|
||||||
if err := serializePathElementToWriter(r.reset(), cpe); err != nil {
|
if err := serializePathElementToWriter(r.reset(), cpe); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
stream.WriteObjectField(r.unsafeString())
|
stream.WriteObjectField(r.unsafeString())
|
||||||
stream.WriteObjectStart()
|
stream.WriteObjectStart()
|
||||||
if err := s.Children.members[ci].set.emitContents_v1(false, stream, r); err != nil {
|
if err := s.Children.members[ci].set.emitContentsV1(false, stream, r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
stream.WriteObjectEnd()
|
stream.WriteObjectEnd()
|
||||||
@ -124,7 +124,7 @@ func (s *Set) emitContents_v1(includeSelf bool, stream *jsoniter.Stream, r *reus
|
|||||||
}
|
}
|
||||||
stream.WriteObjectField(r.unsafeString())
|
stream.WriteObjectField(r.unsafeString())
|
||||||
stream.WriteObjectStart()
|
stream.WriteObjectStart()
|
||||||
if err := s.Children.members[ci].set.emitContents_v1(true, stream, r); err != nil {
|
if err := s.Children.members[ci].set.emitContentsV1(true, stream, r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
stream.WriteObjectEnd()
|
stream.WriteObjectEnd()
|
||||||
@ -154,7 +154,7 @@ func (s *Set) emitContents_v1(includeSelf bool, stream *jsoniter.Stream, r *reus
|
|||||||
}
|
}
|
||||||
stream.WriteObjectField(r.unsafeString())
|
stream.WriteObjectField(r.unsafeString())
|
||||||
stream.WriteObjectStart()
|
stream.WriteObjectStart()
|
||||||
if err := s.Children.members[ci].set.emitContents_v1(false, stream, r); err != nil {
|
if err := s.Children.members[ci].set.emitContentsV1(false, stream, r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
stream.WriteObjectEnd()
|
stream.WriteObjectEnd()
|
||||||
@ -169,7 +169,7 @@ func (s *Set) FromJSON(r io.Reader) error {
|
|||||||
// The iterator pool is completely useless for memory management, grrr.
|
// The iterator pool is completely useless for memory management, grrr.
|
||||||
iter := jsoniter.Parse(jsoniter.ConfigCompatibleWithStandardLibrary, r, 4096)
|
iter := jsoniter.Parse(jsoniter.ConfigCompatibleWithStandardLibrary, r, 4096)
|
||||||
|
|
||||||
found, _ := readIter_v1(iter)
|
found, _ := readIterV1(iter)
|
||||||
if found == nil {
|
if found == nil {
|
||||||
*s = Set{}
|
*s = Set{}
|
||||||
} else {
|
} else {
|
||||||
@ -180,7 +180,7 @@ func (s *Set) FromJSON(r io.Reader) error {
|
|||||||
|
|
||||||
// returns true if this subtree is also (or only) a member of parent; s is nil
|
// returns true if this subtree is also (or only) a member of parent; s is nil
|
||||||
// if there are no further children.
|
// if there are no further children.
|
||||||
func readIter_v1(iter *jsoniter.Iterator) (children *Set, isMember bool) {
|
func readIterV1(iter *jsoniter.Iterator) (children *Set, isMember bool) {
|
||||||
iter.ReadMapCB(func(iter *jsoniter.Iterator, key string) bool {
|
iter.ReadMapCB(func(iter *jsoniter.Iterator, key string) bool {
|
||||||
if key == "." {
|
if key == "." {
|
||||||
isMember = true
|
isMember = true
|
||||||
@ -199,7 +199,7 @@ func readIter_v1(iter *jsoniter.Iterator) (children *Set, isMember bool) {
|
|||||||
iter.Skip()
|
iter.Skip()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
grandchildren, childIsMember := readIter_v1(iter)
|
grandchildren, childIsMember := readIterV1(iter)
|
||||||
if childIsMember {
|
if childIsMember {
|
||||||
if children == nil {
|
if children == nil {
|
||||||
children = &Set{}
|
children = &Set{}
|
||||||
|
18
vendor/sigs.k8s.io/structured-merge-diff/v3/typed/helpers.go
generated
vendored
18
vendor/sigs.k8s.io/structured-merge-diff/v3/typed/helpers.go
generated
vendored
@ -154,7 +154,7 @@ func handleAtom(a schema.Atom, tr schema.TypeRef, ah atomHandler) ValidationErro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns the list, or an error. Reminder: nil is a valid list and might be returned.
|
// Returns the list, or an error. Reminder: nil is a valid list and might be returned.
|
||||||
func listValue(val value.Value) (value.List, error) {
|
func listValue(a value.Allocator, val value.Value) (value.List, error) {
|
||||||
if val.IsNull() {
|
if val.IsNull() {
|
||||||
// Null is a valid list.
|
// Null is a valid list.
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -162,11 +162,11 @@ func listValue(val value.Value) (value.List, error) {
|
|||||||
if !val.IsList() {
|
if !val.IsList() {
|
||||||
return nil, fmt.Errorf("expected list, got %v", val)
|
return nil, fmt.Errorf("expected list, got %v", val)
|
||||||
}
|
}
|
||||||
return val.AsList(), nil
|
return val.AsListUsing(a), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the map, or an error. Reminder: nil is a valid map and might be returned.
|
// Returns the map, or an error. Reminder: nil is a valid map and might be returned.
|
||||||
func mapValue(val value.Value) (value.Map, error) {
|
func mapValue(a value.Allocator, val value.Value) (value.Map, error) {
|
||||||
if val == nil {
|
if val == nil {
|
||||||
return nil, fmt.Errorf("expected map, got nil")
|
return nil, fmt.Errorf("expected map, got nil")
|
||||||
}
|
}
|
||||||
@ -177,10 +177,10 @@ func mapValue(val value.Value) (value.Map, error) {
|
|||||||
if !val.IsMap() {
|
if !val.IsMap() {
|
||||||
return nil, fmt.Errorf("expected map, got %v", val)
|
return nil, fmt.Errorf("expected map, got %v", val)
|
||||||
}
|
}
|
||||||
return val.AsMap(), nil
|
return val.AsMapUsing(a), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func keyedAssociativeListItemToPathElement(list *schema.List, index int, child value.Value) (fieldpath.PathElement, error) {
|
func keyedAssociativeListItemToPathElement(a value.Allocator, list *schema.List, index int, child value.Value) (fieldpath.PathElement, error) {
|
||||||
pe := fieldpath.PathElement{}
|
pe := fieldpath.PathElement{}
|
||||||
if child.IsNull() {
|
if child.IsNull() {
|
||||||
// For now, the keys are required which means that null entries
|
// For now, the keys are required which means that null entries
|
||||||
@ -191,8 +191,10 @@ func keyedAssociativeListItemToPathElement(list *schema.List, index int, child v
|
|||||||
return pe, errors.New("associative list with keys may not have non-map elements")
|
return pe, errors.New("associative list with keys may not have non-map elements")
|
||||||
}
|
}
|
||||||
keyMap := value.FieldList{}
|
keyMap := value.FieldList{}
|
||||||
|
m := child.AsMapUsing(a)
|
||||||
|
defer a.Free(m)
|
||||||
for _, fieldName := range list.Keys {
|
for _, fieldName := range list.Keys {
|
||||||
if val, ok := child.AsMap().Get(fieldName); ok {
|
if val, ok := m.Get(fieldName); ok {
|
||||||
keyMap = append(keyMap, value.Field{Name: fieldName, Value: val})
|
keyMap = append(keyMap, value.Field{Name: fieldName, Value: val})
|
||||||
} else {
|
} else {
|
||||||
return pe, fmt.Errorf("associative list with keys has an element that omits key field %q", fieldName)
|
return pe, fmt.Errorf("associative list with keys has an element that omits key field %q", fieldName)
|
||||||
@ -223,10 +225,10 @@ func setItemToPathElement(list *schema.List, index int, child value.Value) (fiel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func listItemToPathElement(list *schema.List, index int, child value.Value) (fieldpath.PathElement, error) {
|
func listItemToPathElement(a value.Allocator, list *schema.List, index int, child value.Value) (fieldpath.PathElement, error) {
|
||||||
if list.ElementRelationship == schema.Associative {
|
if list.ElementRelationship == schema.Associative {
|
||||||
if len(list.Keys) > 0 {
|
if len(list.Keys) > 0 {
|
||||||
return keyedAssociativeListItemToPathElement(list, index, child)
|
return keyedAssociativeListItemToPathElement(a, list, index, child)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's no keys, then we must be a set of primitives.
|
// If there's no keys, then we must be a set of primitives.
|
||||||
|
86
vendor/sigs.k8s.io/structured-merge-diff/v3/typed/merge.go
generated
vendored
86
vendor/sigs.k8s.io/structured-merge-diff/v3/typed/merge.go
generated
vendored
@ -48,6 +48,8 @@ type mergingWalker struct {
|
|||||||
|
|
||||||
// Allocate only as many walkers as needed for the depth by storing them here.
|
// Allocate only as many walkers as needed for the depth by storing them here.
|
||||||
spareWalkers *[]*mergingWalker
|
spareWalkers *[]*mergingWalker
|
||||||
|
|
||||||
|
allocator value.Allocator
|
||||||
}
|
}
|
||||||
|
|
||||||
// merge rules examine w.lhs and w.rhs (up to one of which may be nil) and
|
// merge rules examine w.lhs and w.rhs (up to one of which may be nil) and
|
||||||
@ -148,18 +150,15 @@ func (w *mergingWalker) finishDescent(w2 *mergingWalker) {
|
|||||||
*w.spareWalkers = append(*w.spareWalkers, w2)
|
*w.spareWalkers = append(*w.spareWalkers, w2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *mergingWalker) derefMap(prefix string, v value.Value, dest *value.Map) (errs ValidationErrors) {
|
func (w *mergingWalker) derefMap(prefix string, v value.Value) (value.Map, ValidationErrors) {
|
||||||
// taking dest as input so that it can be called as a one-liner with
|
|
||||||
// append.
|
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
m, err := mapValue(v)
|
m, err := mapValue(w.allocator, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorf("%v: %v", prefix, err)
|
return nil, errorf("%v: %v", prefix, err)
|
||||||
}
|
}
|
||||||
*dest = m
|
return m, nil
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *mergingWalker) visitListItems(t *schema.List, lhs, rhs value.List) (errs ValidationErrors) {
|
func (w *mergingWalker) visitListItems(t *schema.List, lhs, rhs value.List) (errs ValidationErrors) {
|
||||||
@ -184,7 +183,7 @@ func (w *mergingWalker) visitListItems(t *schema.List, lhs, rhs value.List) (err
|
|||||||
if rhs != nil {
|
if rhs != nil {
|
||||||
for i := 0; i < rhs.Length(); i++ {
|
for i := 0; i < rhs.Length(); i++ {
|
||||||
child := rhs.At(i)
|
child := rhs.At(i)
|
||||||
pe, err := listItemToPathElement(t, i, child)
|
pe, err := listItemToPathElement(w.allocator, t, i, child)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, errorf("rhs: element %v: %v", i, err.Error())...)
|
errs = append(errs, errorf("rhs: element %v: %v", i, err.Error())...)
|
||||||
// If we can't construct the path element, we can't
|
// If we can't construct the path element, we can't
|
||||||
@ -205,7 +204,7 @@ func (w *mergingWalker) visitListItems(t *schema.List, lhs, rhs value.List) (err
|
|||||||
if lhs != nil {
|
if lhs != nil {
|
||||||
for i := 0; i < lhs.Length(); i++ {
|
for i := 0; i < lhs.Length(); i++ {
|
||||||
child := lhs.At(i)
|
child := lhs.At(i)
|
||||||
pe, err := listItemToPathElement(t, i, child)
|
pe, err := listItemToPathElement(w.allocator, t, i, child)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, errorf("lhs: element %v: %v", i, err.Error())...)
|
errs = append(errs, errorf("lhs: element %v: %v", i, err.Error())...)
|
||||||
// If we can't construct the path element, we can't
|
// If we can't construct the path element, we can't
|
||||||
@ -253,24 +252,26 @@ func (w *mergingWalker) visitListItems(t *schema.List, lhs, rhs value.List) (err
|
|||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *mergingWalker) derefList(prefix string, v value.Value, dest *value.List) (errs ValidationErrors) {
|
func (w *mergingWalker) derefList(prefix string, v value.Value) (value.List, ValidationErrors) {
|
||||||
// taking dest as input so that it can be called as a one-liner with
|
|
||||||
// append.
|
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
l, err := listValue(v)
|
l, err := listValue(w.allocator, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorf("%v: %v", prefix, err)
|
return nil, errorf("%v: %v", prefix, err)
|
||||||
}
|
}
|
||||||
*dest = l
|
return l, nil
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *mergingWalker) doList(t *schema.List) (errs ValidationErrors) {
|
func (w *mergingWalker) doList(t *schema.List) (errs ValidationErrors) {
|
||||||
var lhs, rhs value.List
|
lhs, _ := w.derefList("lhs: ", w.lhs)
|
||||||
w.derefList("lhs: ", w.lhs, &lhs)
|
if lhs != nil {
|
||||||
w.derefList("rhs: ", w.rhs, &rhs)
|
defer w.allocator.Free(lhs)
|
||||||
|
}
|
||||||
|
rhs, _ := w.derefList("rhs: ", w.rhs)
|
||||||
|
if rhs != nil {
|
||||||
|
defer w.allocator.Free(rhs)
|
||||||
|
}
|
||||||
|
|
||||||
// If both lhs and rhs are empty/null, treat it as a
|
// If both lhs and rhs are empty/null, treat it as a
|
||||||
// leaf: this helps preserve the empty/null
|
// leaf: this helps preserve the empty/null
|
||||||
@ -311,31 +312,10 @@ func (w *mergingWalker) visitMapItem(t *schema.Map, out map[string]interface{},
|
|||||||
func (w *mergingWalker) visitMapItems(t *schema.Map, lhs, rhs value.Map) (errs ValidationErrors) {
|
func (w *mergingWalker) visitMapItems(t *schema.Map, lhs, rhs value.Map) (errs ValidationErrors) {
|
||||||
out := map[string]interface{}{}
|
out := map[string]interface{}{}
|
||||||
|
|
||||||
if lhs != nil {
|
value.MapZipUsing(w.allocator, lhs, rhs, value.Unordered, func(key string, lhsValue, rhsValue value.Value) bool {
|
||||||
lhs.Iterate(func(key string, val value.Value) bool {
|
errs = append(errs, w.visitMapItem(t, out, key, lhsValue, rhsValue)...)
|
||||||
var rval value.Value
|
return true
|
||||||
if rhs != nil {
|
})
|
||||||
if item, ok := rhs.Get(key); ok {
|
|
||||||
rval = item
|
|
||||||
defer rval.Recycle()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
errs = append(errs, w.visitMapItem(t, out, key, val, rval)...)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if rhs != nil {
|
|
||||||
rhs.Iterate(func(key string, val value.Value) bool {
|
|
||||||
if lhs != nil {
|
|
||||||
if lhs.Has(key) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
errs = append(errs, w.visitMapItem(t, out, key, nil, val)...)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if len(out) > 0 {
|
if len(out) > 0 {
|
||||||
i := interface{}(out)
|
i := interface{}(out)
|
||||||
w.out = &i
|
w.out = &i
|
||||||
@ -345,14 +325,18 @@ func (w *mergingWalker) visitMapItems(t *schema.Map, lhs, rhs value.Map) (errs V
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *mergingWalker) doMap(t *schema.Map) (errs ValidationErrors) {
|
func (w *mergingWalker) doMap(t *schema.Map) (errs ValidationErrors) {
|
||||||
var lhs, rhs value.Map
|
lhs, _ := w.derefMap("lhs: ", w.lhs)
|
||||||
w.derefMap("lhs: ", w.lhs, &lhs)
|
if lhs != nil {
|
||||||
w.derefMap("rhs: ", w.rhs, &rhs)
|
defer w.allocator.Free(lhs)
|
||||||
|
}
|
||||||
|
rhs, _ := w.derefMap("rhs: ", w.rhs)
|
||||||
|
if rhs != nil {
|
||||||
|
defer w.allocator.Free(rhs)
|
||||||
|
}
|
||||||
// If both lhs and rhs are empty/null, treat it as a
|
// If both lhs and rhs are empty/null, treat it as a
|
||||||
// leaf: this helps preserve the empty/null
|
// leaf: this helps preserve the empty/null
|
||||||
// distinction.
|
// distinction.
|
||||||
emptyPromoteToLeaf := (lhs == nil || lhs.Length() == 0) && (rhs == nil || rhs.Length() == 0)
|
emptyPromoteToLeaf := (lhs == nil || lhs.Empty()) && (rhs == nil || rhs.Empty())
|
||||||
|
|
||||||
if t.ElementRelationship == schema.Atomic || emptyPromoteToLeaf {
|
if t.ElementRelationship == schema.Atomic || emptyPromoteToLeaf {
|
||||||
w.doLeaf()
|
w.doLeaf()
|
||||||
|
36
vendor/sigs.k8s.io/structured-merge-diff/v3/typed/remove.go
generated
vendored
36
vendor/sigs.k8s.io/structured-merge-diff/v3/typed/remove.go
generated
vendored
@ -20,17 +20,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type removingWalker struct {
|
type removingWalker struct {
|
||||||
value value.Value
|
value value.Value
|
||||||
out interface{}
|
out interface{}
|
||||||
schema *schema.Schema
|
schema *schema.Schema
|
||||||
toRemove *fieldpath.Set
|
toRemove *fieldpath.Set
|
||||||
|
allocator value.Allocator
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeItemsWithSchema(val value.Value, toRemove *fieldpath.Set, schema *schema.Schema, typeRef schema.TypeRef) value.Value {
|
func removeItemsWithSchema(val value.Value, toRemove *fieldpath.Set, schema *schema.Schema, typeRef schema.TypeRef) value.Value {
|
||||||
w := &removingWalker{
|
w := &removingWalker{
|
||||||
value: val,
|
value: val,
|
||||||
schema: schema,
|
schema: schema,
|
||||||
toRemove: toRemove,
|
toRemove: toRemove,
|
||||||
|
allocator: value.NewFreelistAllocator(),
|
||||||
}
|
}
|
||||||
resolveSchema(schema, typeRef, val, w)
|
resolveSchema(schema, typeRef, val, w)
|
||||||
return value.NewValueInterface(w.out)
|
return value.NewValueInterface(w.out)
|
||||||
@ -42,18 +44,20 @@ func (w *removingWalker) doScalar(t *schema.Scalar) ValidationErrors {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *removingWalker) doList(t *schema.List) (errs ValidationErrors) {
|
func (w *removingWalker) doList(t *schema.List) (errs ValidationErrors) {
|
||||||
l := w.value.AsList()
|
l := w.value.AsListUsing(w.allocator)
|
||||||
|
defer w.allocator.Free(l)
|
||||||
// If list is null, empty, or atomic just return
|
// If list is null, empty, or atomic just return
|
||||||
if l == nil || l.Length() == 0 || t.ElementRelationship == schema.Atomic {
|
if l == nil || l.Length() == 0 || t.ElementRelationship == schema.Atomic {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var newItems []interface{}
|
var newItems []interface{}
|
||||||
for i := 0; i < l.Length(); i++ {
|
iter := l.RangeUsing(w.allocator)
|
||||||
item := l.At(i)
|
defer w.allocator.Free(iter)
|
||||||
|
for iter.Next() {
|
||||||
|
i, item := iter.Item()
|
||||||
// Ignore error because we have already validated this list
|
// Ignore error because we have already validated this list
|
||||||
pe, _ := listItemToPathElement(t, i, item)
|
pe, _ := listItemToPathElement(w.allocator, t, i, item)
|
||||||
path, _ := fieldpath.MakePath(pe)
|
path, _ := fieldpath.MakePath(pe)
|
||||||
if w.toRemove.Has(path) {
|
if w.toRemove.Has(path) {
|
||||||
continue
|
continue
|
||||||
@ -70,10 +74,12 @@ func (w *removingWalker) doList(t *schema.List) (errs ValidationErrors) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *removingWalker) doMap(t *schema.Map) ValidationErrors {
|
func (w *removingWalker) doMap(t *schema.Map) ValidationErrors {
|
||||||
m := w.value.AsMap()
|
m := w.value.AsMapUsing(w.allocator)
|
||||||
|
if m != nil {
|
||||||
|
defer w.allocator.Free(m)
|
||||||
|
}
|
||||||
// If map is null, empty, or atomic just return
|
// If map is null, empty, or atomic just return
|
||||||
if m == nil || m.Length() == 0 || t.ElementRelationship == schema.Atomic {
|
if m == nil || m.Empty() || t.ElementRelationship == schema.Atomic {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
vendor/sigs.k8s.io/structured-merge-diff/v3/typed/tofieldset.go
generated
vendored
16
vendor/sigs.k8s.io/structured-merge-diff/v3/typed/tofieldset.go
generated
vendored
@ -34,6 +34,7 @@ func (tv TypedValue) toFieldSetWalker() *toFieldSetWalker {
|
|||||||
v.schema = tv.schema
|
v.schema = tv.schema
|
||||||
v.typeRef = tv.typeRef
|
v.typeRef = tv.typeRef
|
||||||
v.set = &fieldpath.Set{}
|
v.set = &fieldpath.Set{}
|
||||||
|
v.allocator = value.NewFreelistAllocator()
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,6 +56,7 @@ type toFieldSetWalker struct {
|
|||||||
|
|
||||||
// Allocate only as many walkers as needed for the depth by storing them here.
|
// Allocate only as many walkers as needed for the depth by storing them here.
|
||||||
spareWalkers *[]*toFieldSetWalker
|
spareWalkers *[]*toFieldSetWalker
|
||||||
|
allocator value.Allocator
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *toFieldSetWalker) prepareDescent(pe fieldpath.PathElement, tr schema.TypeRef) *toFieldSetWalker {
|
func (v *toFieldSetWalker) prepareDescent(pe fieldpath.PathElement, tr schema.TypeRef) *toFieldSetWalker {
|
||||||
@ -94,7 +96,7 @@ func (v *toFieldSetWalker) doScalar(t *schema.Scalar) ValidationErrors {
|
|||||||
func (v *toFieldSetWalker) visitListItems(t *schema.List, list value.List) (errs ValidationErrors) {
|
func (v *toFieldSetWalker) visitListItems(t *schema.List, list value.List) (errs ValidationErrors) {
|
||||||
for i := 0; i < list.Length(); i++ {
|
for i := 0; i < list.Length(); i++ {
|
||||||
child := list.At(i)
|
child := list.At(i)
|
||||||
pe, _ := listItemToPathElement(t, i, child)
|
pe, _ := listItemToPathElement(v.allocator, t, i, child)
|
||||||
v2 := v.prepareDescent(pe, t.ElementType)
|
v2 := v.prepareDescent(pe, t.ElementType)
|
||||||
v2.value = child
|
v2.value = child
|
||||||
errs = append(errs, v2.toFieldSet()...)
|
errs = append(errs, v2.toFieldSet()...)
|
||||||
@ -106,8 +108,10 @@ func (v *toFieldSetWalker) visitListItems(t *schema.List, list value.List) (errs
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *toFieldSetWalker) doList(t *schema.List) (errs ValidationErrors) {
|
func (v *toFieldSetWalker) doList(t *schema.List) (errs ValidationErrors) {
|
||||||
list, _ := listValue(v.value)
|
list, _ := listValue(v.allocator, v.value)
|
||||||
|
if list != nil {
|
||||||
|
defer v.allocator.Free(list)
|
||||||
|
}
|
||||||
if t.ElementRelationship == schema.Atomic {
|
if t.ElementRelationship == schema.Atomic {
|
||||||
v.set.Insert(v.path)
|
v.set.Insert(v.path)
|
||||||
return nil
|
return nil
|
||||||
@ -143,8 +147,10 @@ func (v *toFieldSetWalker) visitMapItems(t *schema.Map, m value.Map) (errs Valid
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *toFieldSetWalker) doMap(t *schema.Map) (errs ValidationErrors) {
|
func (v *toFieldSetWalker) doMap(t *schema.Map) (errs ValidationErrors) {
|
||||||
m, _ := mapValue(v.value)
|
m, _ := mapValue(v.allocator, v.value)
|
||||||
|
if m != nil {
|
||||||
|
defer v.allocator.Free(m)
|
||||||
|
}
|
||||||
if t.ElementRelationship == schema.Atomic {
|
if t.ElementRelationship == schema.Atomic {
|
||||||
v.set.Insert(v.path)
|
v.set.Insert(v.path)
|
||||||
return nil
|
return nil
|
||||||
|
3
vendor/sigs.k8s.io/structured-merge-diff/v3/typed/typed.go
generated
vendored
3
vendor/sigs.k8s.io/structured-merge-diff/v3/typed/typed.go
generated
vendored
@ -238,6 +238,9 @@ func merge(lhs, rhs *TypedValue, rule, postRule mergeRule) (*TypedValue, error)
|
|||||||
mw.typeRef = lhs.typeRef
|
mw.typeRef = lhs.typeRef
|
||||||
mw.rule = rule
|
mw.rule = rule
|
||||||
mw.postItemHook = postRule
|
mw.postItemHook = postRule
|
||||||
|
if mw.allocator == nil {
|
||||||
|
mw.allocator = value.NewFreelistAllocator()
|
||||||
|
}
|
||||||
|
|
||||||
errs := mw.merge(nil)
|
errs := mw.merge(nil)
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
|
19
vendor/sigs.k8s.io/structured-merge-diff/v3/typed/validate.go
generated
vendored
19
vendor/sigs.k8s.io/structured-merge-diff/v3/typed/validate.go
generated
vendored
@ -33,6 +33,9 @@ func (tv TypedValue) walker() *validatingObjectWalker {
|
|||||||
v.value = tv.value
|
v.value = tv.value
|
||||||
v.schema = tv.schema
|
v.schema = tv.schema
|
||||||
v.typeRef = tv.typeRef
|
v.typeRef = tv.typeRef
|
||||||
|
if v.allocator == nil {
|
||||||
|
v.allocator = value.NewFreelistAllocator()
|
||||||
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +52,7 @@ type validatingObjectWalker struct {
|
|||||||
|
|
||||||
// Allocate only as many walkers as needed for the depth by storing them here.
|
// Allocate only as many walkers as needed for the depth by storing them here.
|
||||||
spareWalkers *[]*validatingObjectWalker
|
spareWalkers *[]*validatingObjectWalker
|
||||||
|
allocator value.Allocator
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *validatingObjectWalker) prepareDescent(tr schema.TypeRef) *validatingObjectWalker {
|
func (v *validatingObjectWalker) prepareDescent(tr schema.TypeRef) *validatingObjectWalker {
|
||||||
@ -112,13 +116,14 @@ func (v *validatingObjectWalker) doScalar(t *schema.Scalar) ValidationErrors {
|
|||||||
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 := fieldpath.MakePathElementSet(list.Length())
|
observedKeys := fieldpath.MakePathElementSet(list.Length())
|
||||||
for i := 0; i < list.Length(); i++ {
|
for i := 0; i < list.Length(); i++ {
|
||||||
child := list.At(i)
|
child := list.AtUsing(v.allocator, i)
|
||||||
|
defer v.allocator.Free(child)
|
||||||
var pe fieldpath.PathElement
|
var pe fieldpath.PathElement
|
||||||
if t.ElementRelationship != schema.Associative {
|
if t.ElementRelationship != schema.Associative {
|
||||||
pe.Index = &i
|
pe.Index = &i
|
||||||
} else {
|
} else {
|
||||||
var err error
|
var err error
|
||||||
pe, err = listItemToPathElement(t, i, child)
|
pe, err = listItemToPathElement(v.allocator, t, i, child)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, errorf("element %v: %v", i, err.Error())...)
|
errs = append(errs, errorf("element %v: %v", i, err.Error())...)
|
||||||
// If we can't construct the path element, we can't
|
// If we can't construct the path element, we can't
|
||||||
@ -140,7 +145,7 @@ func (v *validatingObjectWalker) visitListItems(t *schema.List, list value.List)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *validatingObjectWalker) doList(t *schema.List) (errs ValidationErrors) {
|
func (v *validatingObjectWalker) doList(t *schema.List) (errs ValidationErrors) {
|
||||||
list, err := listValue(v.value)
|
list, err := listValue(v.allocator, v.value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorf(err.Error())
|
return errorf(err.Error())
|
||||||
}
|
}
|
||||||
@ -149,13 +154,14 @@ func (v *validatingObjectWalker) doList(t *schema.List) (errs ValidationErrors)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer v.allocator.Free(list)
|
||||||
errs = v.visitListItems(t, list)
|
errs = v.visitListItems(t, list)
|
||||||
|
|
||||||
return errs
|
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) {
|
||||||
m.Iterate(func(key string, val value.Value) bool {
|
m.IterateUsing(v.allocator, func(key string, val value.Value) bool {
|
||||||
pe := fieldpath.PathElement{FieldName: &key}
|
pe := fieldpath.PathElement{FieldName: &key}
|
||||||
tr := t.ElementType
|
tr := t.ElementType
|
||||||
if sf, ok := t.FindField(key); ok {
|
if sf, ok := t.FindField(key); ok {
|
||||||
@ -175,15 +181,14 @@ func (v *validatingObjectWalker) visitMapItems(t *schema.Map, m value.Map) (errs
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *validatingObjectWalker) doMap(t *schema.Map) (errs ValidationErrors) {
|
func (v *validatingObjectWalker) doMap(t *schema.Map) (errs ValidationErrors) {
|
||||||
m, err := mapValue(v.value)
|
m, err := mapValue(v.allocator, v.value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorf(err.Error())
|
return errorf(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
defer v.allocator.Free(m)
|
||||||
errs = v.visitMapItems(t, m)
|
errs = v.visitMapItems(t, m)
|
||||||
|
|
||||||
return errs
|
return errs
|
||||||
|
2
vendor/sigs.k8s.io/structured-merge-diff/v3/value/BUILD
generated
vendored
2
vendor/sigs.k8s.io/structured-merge-diff/v3/value/BUILD
generated
vendored
@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
"allocator.go",
|
||||||
"doc.go",
|
"doc.go",
|
||||||
"fields.go",
|
"fields.go",
|
||||||
"jsontagutil.go",
|
"jsontagutil.go",
|
||||||
@ -12,6 +13,7 @@ go_library(
|
|||||||
"map.go",
|
"map.go",
|
||||||
"mapreflect.go",
|
"mapreflect.go",
|
||||||
"mapunstructured.go",
|
"mapunstructured.go",
|
||||||
|
"reflectcache.go",
|
||||||
"scalar.go",
|
"scalar.go",
|
||||||
"structreflect.go",
|
"structreflect.go",
|
||||||
"value.go",
|
"value.go",
|
||||||
|
203
vendor/sigs.k8s.io/structured-merge-diff/v3/value/allocator.go
generated
vendored
Normal file
203
vendor/sigs.k8s.io/structured-merge-diff/v3/value/allocator.go
generated
vendored
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 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 value
|
||||||
|
|
||||||
|
// Allocator provides a value object allocation strategy.
|
||||||
|
// Value objects can be allocated by passing an allocator to the "Using"
|
||||||
|
// receiver functions on the value interfaces, e.g. Map.ZipUsing(allocator, ...).
|
||||||
|
// Value objects returned from "Using" functions should be given back to the allocator
|
||||||
|
// once longer needed by calling Allocator.Free(Value).
|
||||||
|
type Allocator interface {
|
||||||
|
// Free gives the allocator back any value objects returned by the "Using"
|
||||||
|
// receiver functions on the value interfaces.
|
||||||
|
// interface{} may be any of: Value, Map, List or Range.
|
||||||
|
Free(interface{})
|
||||||
|
|
||||||
|
// The unexported functions are for "Using" receiver functions of the value types
|
||||||
|
// to request what they need from the allocator.
|
||||||
|
allocValueUnstructured() *valueUnstructured
|
||||||
|
allocListUnstructuredRange() *listUnstructuredRange
|
||||||
|
allocValueReflect() *valueReflect
|
||||||
|
allocMapReflect() *mapReflect
|
||||||
|
allocStructReflect() *structReflect
|
||||||
|
allocListReflect() *listReflect
|
||||||
|
allocListReflectRange() *listReflectRange
|
||||||
|
}
|
||||||
|
|
||||||
|
// HeapAllocator simply allocates objects to the heap. It is the default
|
||||||
|
// allocator used receiver functions on the value interfaces that do not accept
|
||||||
|
// an allocator and should be used whenever allocating objects that will not
|
||||||
|
// be given back to an allocator by calling Allocator.Free(Value).
|
||||||
|
var HeapAllocator = &heapAllocator{}
|
||||||
|
|
||||||
|
type heapAllocator struct{}
|
||||||
|
|
||||||
|
func (p *heapAllocator) allocValueUnstructured() *valueUnstructured {
|
||||||
|
return &valueUnstructured{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *heapAllocator) allocListUnstructuredRange() *listUnstructuredRange {
|
||||||
|
return &listUnstructuredRange{vv: &valueUnstructured{}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *heapAllocator) allocValueReflect() *valueReflect {
|
||||||
|
return &valueReflect{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *heapAllocator) allocStructReflect() *structReflect {
|
||||||
|
return &structReflect{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *heapAllocator) allocMapReflect() *mapReflect {
|
||||||
|
return &mapReflect{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *heapAllocator) allocListReflect() *listReflect {
|
||||||
|
return &listReflect{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *heapAllocator) allocListReflectRange() *listReflectRange {
|
||||||
|
return &listReflectRange{vr: &valueReflect{}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *heapAllocator) Free(_ interface{}) {}
|
||||||
|
|
||||||
|
// NewFreelistAllocator creates freelist based allocator.
|
||||||
|
// This allocator provides fast allocation and freeing of short lived value objects.
|
||||||
|
//
|
||||||
|
// The freelists are bounded in size by freelistMaxSize. If more than this amount of value objects is
|
||||||
|
// allocated at once, the excess will be returned to the heap for garbage collection when freed.
|
||||||
|
//
|
||||||
|
// This allocator is unsafe and must not be accessed concurrently by goroutines.
|
||||||
|
//
|
||||||
|
// This allocator works well for traversal of value data trees. Typical usage is to acquire
|
||||||
|
// a freelist at the beginning of the traversal and use it through out
|
||||||
|
// for all temporary value access.
|
||||||
|
func NewFreelistAllocator() Allocator {
|
||||||
|
return &freelistAllocator{
|
||||||
|
valueUnstructured: &freelist{new: func() interface{} {
|
||||||
|
return &valueUnstructured{}
|
||||||
|
}},
|
||||||
|
listUnstructuredRange: &freelist{new: func() interface{} {
|
||||||
|
return &listUnstructuredRange{vv: &valueUnstructured{}}
|
||||||
|
}},
|
||||||
|
valueReflect: &freelist{new: func() interface{} {
|
||||||
|
return &valueReflect{}
|
||||||
|
}},
|
||||||
|
mapReflect: &freelist{new: func() interface{} {
|
||||||
|
return &mapReflect{}
|
||||||
|
}},
|
||||||
|
structReflect: &freelist{new: func() interface{} {
|
||||||
|
return &structReflect{}
|
||||||
|
}},
|
||||||
|
listReflect: &freelist{new: func() interface{} {
|
||||||
|
return &listReflect{}
|
||||||
|
}},
|
||||||
|
listReflectRange: &freelist{new: func() interface{} {
|
||||||
|
return &listReflectRange{vr: &valueReflect{}}
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bound memory usage of freelists. This prevents the processing of very large lists from leaking memory.
|
||||||
|
// This limit is large enough for endpoints objects containing 1000 IP address entries. Freed objects
|
||||||
|
// that don't fit into the freelist are orphaned on the heap to be garbage collected.
|
||||||
|
const freelistMaxSize = 1000
|
||||||
|
|
||||||
|
type freelistAllocator struct {
|
||||||
|
valueUnstructured *freelist
|
||||||
|
listUnstructuredRange *freelist
|
||||||
|
valueReflect *freelist
|
||||||
|
mapReflect *freelist
|
||||||
|
structReflect *freelist
|
||||||
|
listReflect *freelist
|
||||||
|
listReflectRange *freelist
|
||||||
|
}
|
||||||
|
|
||||||
|
type freelist struct {
|
||||||
|
list []interface{}
|
||||||
|
new func() interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *freelist) allocate() interface{} {
|
||||||
|
var w2 interface{}
|
||||||
|
if n := len(f.list); n > 0 {
|
||||||
|
w2, f.list = f.list[n-1], f.list[:n-1]
|
||||||
|
} else {
|
||||||
|
w2 = f.new()
|
||||||
|
}
|
||||||
|
return w2
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *freelist) free(v interface{}) {
|
||||||
|
if len(f.list) < freelistMaxSize {
|
||||||
|
f.list = append(f.list, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *freelistAllocator) Free(value interface{}) {
|
||||||
|
switch v := value.(type) {
|
||||||
|
case *valueUnstructured:
|
||||||
|
v.Value = nil // don't hold references to unstructured objects
|
||||||
|
w.valueUnstructured.free(v)
|
||||||
|
case *listUnstructuredRange:
|
||||||
|
v.vv.Value = nil // don't hold references to unstructured objects
|
||||||
|
w.listUnstructuredRange.free(v)
|
||||||
|
case *valueReflect:
|
||||||
|
v.ParentMapKey = nil
|
||||||
|
v.ParentMap = nil
|
||||||
|
w.valueReflect.free(v)
|
||||||
|
case *mapReflect:
|
||||||
|
w.mapReflect.free(v)
|
||||||
|
case *structReflect:
|
||||||
|
w.structReflect.free(v)
|
||||||
|
case *listReflect:
|
||||||
|
w.listReflect.free(v)
|
||||||
|
case *listReflectRange:
|
||||||
|
v.vr.ParentMapKey = nil
|
||||||
|
v.vr.ParentMap = nil
|
||||||
|
w.listReflectRange.free(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *freelistAllocator) allocValueUnstructured() *valueUnstructured {
|
||||||
|
return w.valueUnstructured.allocate().(*valueUnstructured)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *freelistAllocator) allocListUnstructuredRange() *listUnstructuredRange {
|
||||||
|
return w.listUnstructuredRange.allocate().(*listUnstructuredRange)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *freelistAllocator) allocValueReflect() *valueReflect {
|
||||||
|
return w.valueReflect.allocate().(*valueReflect)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *freelistAllocator) allocStructReflect() *structReflect {
|
||||||
|
return w.structReflect.allocate().(*structReflect)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *freelistAllocator) allocMapReflect() *mapReflect {
|
||||||
|
return w.mapReflect.allocate().(*mapReflect)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *freelistAllocator) allocListReflect() *listReflect {
|
||||||
|
return w.listReflect.allocate().(*listReflect)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *freelistAllocator) allocListReflectRange() *listReflectRange {
|
||||||
|
return w.listReflectRange.allocate().(*listReflectRange)
|
||||||
|
}
|
2
vendor/sigs.k8s.io/structured-merge-diff/v3/value/fields.go
generated
vendored
2
vendor/sigs.k8s.io/structured-merge-diff/v3/value/fields.go
generated
vendored
@ -27,7 +27,7 @@ type Field struct {
|
|||||||
Value Value
|
Value Value
|
||||||
}
|
}
|
||||||
|
|
||||||
// FieldList is a list of key-value pairs. Each field is expectUpdated to
|
// FieldList is a list of key-value pairs. Each field is expected to
|
||||||
// have a different name.
|
// have a different name.
|
||||||
type FieldList []Field
|
type FieldList []Field
|
||||||
|
|
||||||
|
95
vendor/sigs.k8s.io/structured-merge-diff/v3/value/list.go
generated
vendored
95
vendor/sigs.k8s.io/structured-merge-diff/v3/value/list.go
generated
vendored
@ -23,24 +23,74 @@ type List interface {
|
|||||||
// At returns the item at the given position in the map. It will
|
// At returns the item at the given position in the map. It will
|
||||||
// panic if the index is out of range.
|
// panic if the index is out of range.
|
||||||
At(int) Value
|
At(int) Value
|
||||||
|
// AtUsing uses the provided allocator and returns the item at the given
|
||||||
|
// position in the map. It will panic if the index is out of range.
|
||||||
|
// The returned Value should be given back to the Allocator when no longer needed
|
||||||
|
// by calling Allocator.Free(Value).
|
||||||
|
AtUsing(Allocator, int) Value
|
||||||
|
// Range returns a ListRange for iterating over the items in the list.
|
||||||
|
Range() ListRange
|
||||||
|
// RangeUsing uses the provided allocator and returns a ListRange for
|
||||||
|
// iterating over the items in the list.
|
||||||
|
// The returned Range should be given back to the Allocator when no longer needed
|
||||||
|
// by calling Allocator.Free(Value).
|
||||||
|
RangeUsing(Allocator) ListRange
|
||||||
|
// Equals compares the two lists, and return true if they are the same, false otherwise.
|
||||||
|
// Implementations can use ListEquals as a general implementation for this methods.
|
||||||
|
Equals(List) bool
|
||||||
|
// EqualsUsing uses the provided allocator and compares the two lists, and return true if
|
||||||
|
// they are the same, false otherwise. Implementations can use ListEqualsUsing as a general
|
||||||
|
// implementation for this methods.
|
||||||
|
EqualsUsing(Allocator, List) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRange represents a single iteration across the items of a list.
|
||||||
|
type ListRange interface {
|
||||||
|
// Next increments to the next item in the range, if there is one, and returns true, or returns false if there are no more items.
|
||||||
|
Next() bool
|
||||||
|
// Item returns the index and value of the current item in the range. or panics if there is no current item.
|
||||||
|
// For efficiency, Item may reuse the values returned by previous Item calls. Callers should be careful avoid holding
|
||||||
|
// pointers to the value returned by Item() that escape the iteration loop since they become invalid once either
|
||||||
|
// Item() or Allocator.Free() is called.
|
||||||
|
Item() (index int, value Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
var EmptyRange = &emptyRange{}
|
||||||
|
|
||||||
|
type emptyRange struct{}
|
||||||
|
|
||||||
|
func (_ *emptyRange) Next() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_ *emptyRange) Item() (index int, value Value) {
|
||||||
|
panic("Item called on empty ListRange")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListEquals compares two lists lexically.
|
// ListEquals compares two lists lexically.
|
||||||
|
// WARN: This is a naive implementation, calling lhs.Equals(rhs) is typically the most efficient.
|
||||||
func ListEquals(lhs, rhs List) bool {
|
func ListEquals(lhs, rhs List) bool {
|
||||||
|
return ListEqualsUsing(HeapAllocator, lhs, rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEqualsUsing uses the provided allocator and compares two lists lexically.
|
||||||
|
// WARN: This is a naive implementation, calling lhs.EqualsUsing(allocator, rhs) is typically the most efficient.
|
||||||
|
func ListEqualsUsing(a Allocator, lhs, rhs List) bool {
|
||||||
if lhs.Length() != rhs.Length() {
|
if lhs.Length() != rhs.Length() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < lhs.Length(); i++ {
|
lhsRange := lhs.RangeUsing(a)
|
||||||
lv := lhs.At(i)
|
defer a.Free(lhsRange)
|
||||||
rv := rhs.At(i)
|
rhsRange := rhs.RangeUsing(a)
|
||||||
if !Equals(lv, rv) {
|
defer a.Free(rhsRange)
|
||||||
lv.Recycle()
|
|
||||||
rv.Recycle()
|
for lhsRange.Next() && rhsRange.Next() {
|
||||||
|
_, lv := lhsRange.Item()
|
||||||
|
_, rv := rhsRange.Item()
|
||||||
|
if !EqualsUsing(a, lv, rv) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
lv.Recycle()
|
|
||||||
rv.Recycle()
|
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -53,28 +103,37 @@ func ListLess(lhs, rhs List) bool {
|
|||||||
// ListCompare compares two lists lexically. The result will be 0 if l==rhs, -1
|
// ListCompare compares two lists lexically. The result will be 0 if l==rhs, -1
|
||||||
// if l < rhs, and +1 if l > rhs.
|
// if l < rhs, and +1 if l > rhs.
|
||||||
func ListCompare(lhs, rhs List) int {
|
func ListCompare(lhs, rhs List) int {
|
||||||
i := 0
|
return ListCompareUsing(HeapAllocator, lhs, rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListCompareUsing uses the provided allocator and compares two lists lexically. The result will be 0 if l==rhs, -1
|
||||||
|
// if l < rhs, and +1 if l > rhs.
|
||||||
|
func ListCompareUsing(a Allocator, lhs, rhs List) int {
|
||||||
|
lhsRange := lhs.RangeUsing(a)
|
||||||
|
defer a.Free(lhsRange)
|
||||||
|
rhsRange := rhs.RangeUsing(a)
|
||||||
|
defer a.Free(rhsRange)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if i >= lhs.Length() && i >= rhs.Length() {
|
lhsOk := lhsRange.Next()
|
||||||
|
rhsOk := rhsRange.Next()
|
||||||
|
if !lhsOk && !rhsOk {
|
||||||
// Lists are the same length and all items are equal.
|
// Lists are the same length and all items are equal.
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
if i >= lhs.Length() {
|
if !lhsOk {
|
||||||
// LHS is shorter.
|
// LHS is shorter.
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
if i >= rhs.Length() {
|
if !rhsOk {
|
||||||
// RHS is shorter.
|
// RHS is shorter.
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
lv := lhs.At(i)
|
_, lv := lhsRange.Item()
|
||||||
rv := rhs.At(i)
|
_, rv := rhsRange.Item()
|
||||||
if c := Compare(lv, rv); c != 0 {
|
if c := CompareUsing(a, lv, rv); c != 0 {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
lv.Recycle()
|
|
||||||
rv.Recycle()
|
|
||||||
// The items are equal; continue.
|
// The items are equal; continue.
|
||||||
i++
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
60
vendor/sigs.k8s.io/structured-merge-diff/v3/value/listreflect.go
generated
vendored
60
vendor/sigs.k8s.io/structured-merge-diff/v3/value/listreflect.go
generated
vendored
@ -16,7 +16,9 @@ limitations under the License.
|
|||||||
|
|
||||||
package value
|
package value
|
||||||
|
|
||||||
import "reflect"
|
import (
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
type listReflect struct {
|
type listReflect struct {
|
||||||
Value reflect.Value
|
Value reflect.Value
|
||||||
@ -29,7 +31,12 @@ func (r listReflect) Length() int {
|
|||||||
|
|
||||||
func (r listReflect) At(i int) Value {
|
func (r listReflect) At(i int) Value {
|
||||||
val := r.Value
|
val := r.Value
|
||||||
return mustWrapValueReflect(val.Index(i))
|
return mustWrapValueReflect(val.Index(i), nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r listReflect) AtUsing(a Allocator, i int) Value {
|
||||||
|
val := r.Value
|
||||||
|
return a.allocValueReflect().mustReuse(val.Index(i), nil, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r listReflect) Unstructured() interface{} {
|
func (r listReflect) Unstructured() interface{} {
|
||||||
@ -40,3 +47,52 @@ func (r listReflect) Unstructured() interface{} {
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r listReflect) Range() ListRange {
|
||||||
|
return r.RangeUsing(HeapAllocator)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r listReflect) RangeUsing(a Allocator) ListRange {
|
||||||
|
length := r.Value.Len()
|
||||||
|
if length == 0 {
|
||||||
|
return EmptyRange
|
||||||
|
}
|
||||||
|
rr := a.allocListReflectRange()
|
||||||
|
rr.list = r.Value
|
||||||
|
rr.i = -1
|
||||||
|
rr.entry = TypeReflectEntryOf(r.Value.Type().Elem())
|
||||||
|
return rr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r listReflect) Equals(other List) bool {
|
||||||
|
return r.EqualsUsing(HeapAllocator, other)
|
||||||
|
}
|
||||||
|
func (r listReflect) EqualsUsing(a Allocator, other List) bool {
|
||||||
|
if otherReflectList, ok := other.(*listReflect); ok {
|
||||||
|
return reflect.DeepEqual(r.Value.Interface(), otherReflectList.Value.Interface())
|
||||||
|
}
|
||||||
|
return ListEqualsUsing(a, &r, other)
|
||||||
|
}
|
||||||
|
|
||||||
|
type listReflectRange struct {
|
||||||
|
list reflect.Value
|
||||||
|
vr *valueReflect
|
||||||
|
i int
|
||||||
|
entry *TypeReflectCacheEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *listReflectRange) Next() bool {
|
||||||
|
r.i += 1
|
||||||
|
return r.i < r.list.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *listReflectRange) Item() (index int, value Value) {
|
||||||
|
if r.i < 0 {
|
||||||
|
panic("Item() called before first calling Next()")
|
||||||
|
}
|
||||||
|
if r.i >= r.list.Len() {
|
||||||
|
panic("Item() called on ListRange with no more items")
|
||||||
|
}
|
||||||
|
v := r.list.Index(r.i)
|
||||||
|
return r.i, r.vr.mustReuse(v, r.entry, nil, nil)
|
||||||
|
}
|
||||||
|
47
vendor/sigs.k8s.io/structured-merge-diff/v3/value/listunstructured.go
generated
vendored
47
vendor/sigs.k8s.io/structured-merge-diff/v3/value/listunstructured.go
generated
vendored
@ -25,3 +25,50 @@ func (l listUnstructured) Length() int {
|
|||||||
func (l listUnstructured) At(i int) Value {
|
func (l listUnstructured) At(i int) Value {
|
||||||
return NewValueInterface(l[i])
|
return NewValueInterface(l[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l listUnstructured) AtUsing(a Allocator, i int) Value {
|
||||||
|
return a.allocValueUnstructured().reuse(l[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l listUnstructured) Equals(other List) bool {
|
||||||
|
return l.EqualsUsing(HeapAllocator, other)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l listUnstructured) EqualsUsing(a Allocator, other List) bool {
|
||||||
|
return ListEqualsUsing(a, &l, other)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l listUnstructured) Range() ListRange {
|
||||||
|
return l.RangeUsing(HeapAllocator)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l listUnstructured) RangeUsing(a Allocator) ListRange {
|
||||||
|
if len(l) == 0 {
|
||||||
|
return EmptyRange
|
||||||
|
}
|
||||||
|
r := a.allocListUnstructuredRange()
|
||||||
|
r.list = l
|
||||||
|
r.i = -1
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
type listUnstructuredRange struct {
|
||||||
|
list listUnstructured
|
||||||
|
vv *valueUnstructured
|
||||||
|
i int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *listUnstructuredRange) Next() bool {
|
||||||
|
r.i += 1
|
||||||
|
return r.i < len(r.list)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *listUnstructuredRange) Item() (index int, value Value) {
|
||||||
|
if r.i < 0 {
|
||||||
|
panic("Item() called before first calling Next()")
|
||||||
|
}
|
||||||
|
if r.i >= len(r.list) {
|
||||||
|
panic("Item() called on ListRange with no more items")
|
||||||
|
}
|
||||||
|
return r.i, r.vv.reuse(r.list[r.i])
|
||||||
|
}
|
||||||
|
253
vendor/sigs.k8s.io/structured-merge-diff/v3/value/map.go
generated
vendored
253
vendor/sigs.k8s.io/structured-merge-diff/v3/value/map.go
generated
vendored
@ -18,7 +18,6 @@ package value
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Map represents a Map or go structure.
|
// Map represents a Map or go structure.
|
||||||
@ -27,6 +26,11 @@ type Map interface {
|
|||||||
Set(key string, val Value)
|
Set(key string, val Value)
|
||||||
// Get returns the value for the given key, if present, or (nil, false) otherwise.
|
// Get returns the value for the given key, if present, or (nil, false) otherwise.
|
||||||
Get(key string) (Value, bool)
|
Get(key string) (Value, bool)
|
||||||
|
// GetUsing uses the provided allocator and returns the value for the given key,
|
||||||
|
// if present, or (nil, false) otherwise.
|
||||||
|
// The returned Value should be given back to the Allocator when no longer needed
|
||||||
|
// by calling Allocator.Free(Value).
|
||||||
|
GetUsing(a Allocator, key string) (Value, bool)
|
||||||
// Has returns true if the key is present, or false otherwise.
|
// Has returns true if the key is present, or false otherwise.
|
||||||
Has(key string) bool
|
Has(key string) bool
|
||||||
// Delete removes the key from the map.
|
// Delete removes the key from the map.
|
||||||
@ -34,12 +38,162 @@ type Map interface {
|
|||||||
// Equals compares the two maps, and return true if they are the same, false otherwise.
|
// Equals compares the two maps, and return true if they are the same, false otherwise.
|
||||||
// Implementations can use MapEquals as a general implementation for this methods.
|
// Implementations can use MapEquals as a general implementation for this methods.
|
||||||
Equals(other Map) bool
|
Equals(other Map) bool
|
||||||
|
// EqualsUsing uses the provided allocator and compares the two maps, and return true if
|
||||||
|
// they are the same, false otherwise. Implementations can use MapEqualsUsing as a general
|
||||||
|
// implementation for this methods.
|
||||||
|
EqualsUsing(a Allocator, other Map) bool
|
||||||
// Iterate runs the given function for each key/value in the
|
// Iterate runs the given function for each key/value in the
|
||||||
// map. Returning false in the closure prematurely stops the
|
// map. Returning false in the closure prematurely stops the
|
||||||
// iteration.
|
// iteration.
|
||||||
Iterate(func(key string, value Value) bool) bool
|
Iterate(func(key string, value Value) bool) bool
|
||||||
|
// IterateUsing uses the provided allocator and runs the given function for each key/value
|
||||||
|
// in the map. Returning false in the closure prematurely stops the iteration.
|
||||||
|
IterateUsing(Allocator, func(key string, value Value) bool) bool
|
||||||
// Length returns the number of items in the map.
|
// Length returns the number of items in the map.
|
||||||
Length() int
|
Length() int
|
||||||
|
// Empty returns true if the map is empty.
|
||||||
|
Empty() bool
|
||||||
|
// Zip iterates over the entries of two maps together. If both maps contain a value for a given key, fn is called
|
||||||
|
// with the values from both maps, otherwise it is called with the value of the map that contains the key and nil
|
||||||
|
// for the map that does not contain the key. Returning false in the closure prematurely stops the iteration.
|
||||||
|
Zip(other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool
|
||||||
|
// ZipUsing uses the provided allocator and iterates over the entries of two maps together. If both maps
|
||||||
|
// contain a value for a given key, fn is called with the values from both maps, otherwise it is called with
|
||||||
|
// the value of the map that contains the key and nil for the map that does not contain the key. Returning
|
||||||
|
// false in the closure prematurely stops the iteration.
|
||||||
|
ZipUsing(a Allocator, other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapTraverseOrder defines the map traversal ordering available.
|
||||||
|
type MapTraverseOrder int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Unordered indicates that the map traversal has no ordering requirement.
|
||||||
|
Unordered = iota
|
||||||
|
// LexicalKeyOrder indicates that the map traversal is ordered by key, lexically.
|
||||||
|
LexicalKeyOrder
|
||||||
|
)
|
||||||
|
|
||||||
|
// MapZip iterates over the entries of two maps together. If both maps contain a value for a given key, fn is called
|
||||||
|
// with the values from both maps, otherwise it is called with the value of the map that contains the key and nil
|
||||||
|
// for the other map. Returning false in the closure prematurely stops the iteration.
|
||||||
|
func MapZip(lhs, rhs Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
|
||||||
|
return MapZipUsing(HeapAllocator, lhs, rhs, order, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapZipUsing uses the provided allocator and iterates over the entries of two maps together. If both maps
|
||||||
|
// contain a value for a given key, fn is called with the values from both maps, otherwise it is called with
|
||||||
|
// the value of the map that contains the key and nil for the other map. Returning false in the closure
|
||||||
|
// prematurely stops the iteration.
|
||||||
|
func MapZipUsing(a Allocator, lhs, rhs Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
|
||||||
|
if lhs != nil {
|
||||||
|
return lhs.ZipUsing(a, rhs, order, fn)
|
||||||
|
}
|
||||||
|
if rhs != nil {
|
||||||
|
return rhs.ZipUsing(a, lhs, order, func(key string, rhs, lhs Value) bool { // arg positions of lhs and rhs deliberately swapped
|
||||||
|
return fn(key, lhs, rhs)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaultMapZip provides a default implementation of Zip for implementations that do not need to provide
|
||||||
|
// their own optimized implementation.
|
||||||
|
func defaultMapZip(a Allocator, lhs, rhs Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
|
||||||
|
switch order {
|
||||||
|
case Unordered:
|
||||||
|
return unorderedMapZip(a, lhs, rhs, fn)
|
||||||
|
case LexicalKeyOrder:
|
||||||
|
return lexicalKeyOrderedMapZip(a, lhs, rhs, fn)
|
||||||
|
default:
|
||||||
|
panic("Unsupported map order")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func unorderedMapZip(a Allocator, lhs, rhs Map, fn func(key string, lhs, rhs Value) bool) bool {
|
||||||
|
if (lhs == nil || lhs.Empty()) && (rhs == nil || rhs.Empty()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if lhs != nil {
|
||||||
|
ok := lhs.IterateUsing(a, func(key string, lhsValue Value) bool {
|
||||||
|
var rhsValue Value
|
||||||
|
if rhs != nil {
|
||||||
|
if item, ok := rhs.GetUsing(a, key); ok {
|
||||||
|
rhsValue = item
|
||||||
|
defer a.Free(rhsValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fn(key, lhsValue, rhsValue)
|
||||||
|
})
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rhs != nil {
|
||||||
|
return rhs.IterateUsing(a, func(key string, rhsValue Value) bool {
|
||||||
|
if lhs == nil || !lhs.Has(key) {
|
||||||
|
return fn(key, nil, rhsValue)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func lexicalKeyOrderedMapZip(a Allocator, lhs, rhs Map, fn func(key string, lhs, rhs Value) bool) bool {
|
||||||
|
var lhsLength, rhsLength int
|
||||||
|
var orderedLength int // rough estimate of length of union of map keys
|
||||||
|
if lhs != nil {
|
||||||
|
lhsLength = lhs.Length()
|
||||||
|
orderedLength = lhsLength
|
||||||
|
}
|
||||||
|
if rhs != nil {
|
||||||
|
rhsLength = rhs.Length()
|
||||||
|
if rhsLength > orderedLength {
|
||||||
|
orderedLength = rhsLength
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if lhsLength == 0 && rhsLength == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
ordered := make([]string, 0, orderedLength)
|
||||||
|
if lhs != nil {
|
||||||
|
lhs.IterateUsing(a, func(key string, _ Value) bool {
|
||||||
|
ordered = append(ordered, key)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if rhs != nil {
|
||||||
|
rhs.IterateUsing(a, func(key string, _ Value) bool {
|
||||||
|
if lhs == nil || !lhs.Has(key) {
|
||||||
|
ordered = append(ordered, key)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
sort.Strings(ordered)
|
||||||
|
for _, key := range ordered {
|
||||||
|
var litem, ritem Value
|
||||||
|
if lhs != nil {
|
||||||
|
litem, _ = lhs.GetUsing(a, key)
|
||||||
|
}
|
||||||
|
if rhs != nil {
|
||||||
|
ritem, _ = rhs.GetUsing(a, key)
|
||||||
|
}
|
||||||
|
ok := fn(key, litem, ritem)
|
||||||
|
if litem != nil {
|
||||||
|
a.Free(litem)
|
||||||
|
}
|
||||||
|
if ritem != nil {
|
||||||
|
a.Free(ritem)
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapLess compares two maps lexically.
|
// MapLess compares two maps lexically.
|
||||||
@ -49,65 +203,68 @@ func MapLess(lhs, rhs Map) bool {
|
|||||||
|
|
||||||
// MapCompare compares two maps lexically.
|
// MapCompare compares two maps lexically.
|
||||||
func MapCompare(lhs, rhs Map) int {
|
func MapCompare(lhs, rhs Map) int {
|
||||||
lorder := make([]string, 0, lhs.Length())
|
return MapCompareUsing(HeapAllocator, lhs, rhs)
|
||||||
lhs.Iterate(func(key string, _ Value) bool {
|
}
|
||||||
lorder = append(lorder, key)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
sort.Strings(lorder)
|
|
||||||
rorder := make([]string, 0, rhs.Length())
|
|
||||||
rhs.Iterate(func(key string, _ Value) bool {
|
|
||||||
rorder = append(rorder, key)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
sort.Strings(rorder)
|
|
||||||
|
|
||||||
i := 0
|
// MapCompareUsing uses the provided allocator and compares two maps lexically.
|
||||||
for {
|
func MapCompareUsing(a Allocator, lhs, rhs Map) int {
|
||||||
if i >= len(lorder) && i >= len(rorder) {
|
c := 0
|
||||||
// Maps are the same length and all items are equal.
|
var llength, rlength int
|
||||||
return 0
|
if lhs != nil {
|
||||||
}
|
llength = lhs.Length()
|
||||||
if i >= len(lorder) {
|
|
||||||
// LHS is shorter.
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
if i >= len(rorder) {
|
|
||||||
// RHS is shorter.
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
if c := strings.Compare(lorder[i], rorder[i]); c != 0 {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
litem, _ := lhs.Get(lorder[i])
|
|
||||||
ritem, _ := rhs.Get(rorder[i])
|
|
||||||
if c := Compare(litem, ritem); c != 0 {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
litem.Recycle()
|
|
||||||
ritem.Recycle()
|
|
||||||
// The items are equal; continue.
|
|
||||||
i++
|
|
||||||
}
|
}
|
||||||
|
if rhs != nil {
|
||||||
|
rlength = rhs.Length()
|
||||||
|
}
|
||||||
|
if llength == 0 && rlength == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
i := 0
|
||||||
|
MapZipUsing(a, lhs, rhs, LexicalKeyOrder, func(key string, lhs, rhs Value) bool {
|
||||||
|
switch {
|
||||||
|
case i == llength:
|
||||||
|
c = -1
|
||||||
|
case i == rlength:
|
||||||
|
c = 1
|
||||||
|
case lhs == nil:
|
||||||
|
c = 1
|
||||||
|
case rhs == nil:
|
||||||
|
c = -1
|
||||||
|
default:
|
||||||
|
c = CompareUsing(a, lhs, rhs)
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
return c == 0
|
||||||
|
})
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapEquals returns true if lhs == rhs, false otherwise. This function
|
// MapEquals returns true if lhs == rhs, false otherwise. This function
|
||||||
// acts on generic types and should not be used by callers, but can help
|
// acts on generic types and should not be used by callers, but can help
|
||||||
// implement Map.Equals.
|
// implement Map.Equals.
|
||||||
|
// WARN: This is a naive implementation, calling lhs.Equals(rhs) is typically the most efficient.
|
||||||
func MapEquals(lhs, rhs Map) bool {
|
func MapEquals(lhs, rhs Map) bool {
|
||||||
|
return MapEqualsUsing(HeapAllocator, lhs, rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapEqualsUsing uses the provided allocator and returns true if lhs == rhs,
|
||||||
|
// false otherwise. This function acts on generic types and should not be used
|
||||||
|
// by callers, but can help implement Map.Equals.
|
||||||
|
// WARN: This is a naive implementation, calling lhs.EqualsUsing(allocator, rhs) is typically the most efficient.
|
||||||
|
func MapEqualsUsing(a Allocator, lhs, rhs Map) bool {
|
||||||
|
if lhs == nil && rhs == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if lhs == nil || rhs == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.Length() != rhs.Length() {
|
if lhs.Length() != rhs.Length() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return lhs.Iterate(func(k string, v Value) bool {
|
return MapZipUsing(a, lhs, rhs, Unordered, func(key string, lhs, rhs Value) bool {
|
||||||
vo, ok := rhs.Get(k)
|
if lhs == nil || rhs == nil {
|
||||||
if !ok {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !Equals(v, vo) {
|
return EqualsUsing(a, lhs, rhs)
|
||||||
vo.Recycle()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
vo.Recycle()
|
|
||||||
return true
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
134
vendor/sigs.k8s.io/structured-merge-diff/v3/value/mapreflect.go
generated
vendored
134
vendor/sigs.k8s.io/structured-merge-diff/v3/value/mapreflect.go
generated
vendored
@ -16,7 +16,9 @@ limitations under the License.
|
|||||||
|
|
||||||
package value
|
package value
|
||||||
|
|
||||||
import "reflect"
|
import (
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
type mapReflect struct {
|
type mapReflect struct {
|
||||||
valueReflect
|
valueReflect
|
||||||
@ -27,13 +29,27 @@ func (r mapReflect) Length() int {
|
|||||||
return val.Len()
|
return val.Len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r mapReflect) Empty() bool {
|
||||||
|
val := r.Value
|
||||||
|
return val.Len() == 0
|
||||||
|
}
|
||||||
|
|
||||||
func (r mapReflect) Get(key string) (Value, bool) {
|
func (r mapReflect) Get(key string) (Value, bool) {
|
||||||
mapKey := r.toMapKey(key)
|
return r.GetUsing(HeapAllocator, key)
|
||||||
val := r.Value.MapIndex(mapKey)
|
}
|
||||||
if !val.IsValid() {
|
|
||||||
|
func (r mapReflect) GetUsing(a Allocator, key string) (Value, bool) {
|
||||||
|
k, v, ok := r.get(key)
|
||||||
|
if !ok {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
return mustWrapValueReflectMapItem(&r.Value, &mapKey, val), val != reflect.Value{}
|
return a.allocValueReflect().mustReuse(v, nil, &r.Value, &k), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r mapReflect) get(k string) (key, value reflect.Value, ok bool) {
|
||||||
|
mapKey := r.toMapKey(k)
|
||||||
|
val := r.Value.MapIndex(mapKey)
|
||||||
|
return mapKey, val, val.IsValid() && val != reflect.Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r mapReflect) Has(key string) bool {
|
func (r mapReflect) Has(key string) bool {
|
||||||
@ -61,21 +77,29 @@ func (r mapReflect) toMapKey(key string) reflect.Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r mapReflect) Iterate(fn func(string, Value) bool) bool {
|
func (r mapReflect) Iterate(fn func(string, Value) bool) bool {
|
||||||
return eachMapEntry(r.Value, func(s string, value reflect.Value) bool {
|
return r.IterateUsing(HeapAllocator, fn)
|
||||||
mapVal := mustWrapValueReflect(value)
|
}
|
||||||
defer mapVal.Recycle()
|
|
||||||
return fn(s, mapVal)
|
func (r mapReflect) IterateUsing(a Allocator, fn func(string, Value) bool) bool {
|
||||||
|
if r.Value.Len() == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
v := a.allocValueReflect()
|
||||||
|
defer a.Free(v)
|
||||||
|
return eachMapEntry(r.Value, func(e *TypeReflectCacheEntry, key reflect.Value, value reflect.Value) bool {
|
||||||
|
return fn(key.String(), v.mustReuse(value, e, &r.Value, &key))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func eachMapEntry(val reflect.Value, fn func(string, reflect.Value) bool) bool {
|
func eachMapEntry(val reflect.Value, fn func(*TypeReflectCacheEntry, reflect.Value, reflect.Value) bool) bool {
|
||||||
iter := val.MapRange()
|
iter := val.MapRange()
|
||||||
|
entry := TypeReflectEntryOf(val.Type().Elem())
|
||||||
for iter.Next() {
|
for iter.Next() {
|
||||||
next := iter.Value()
|
next := iter.Value()
|
||||||
if !next.IsValid() {
|
if !next.IsValid() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !fn(iter.Key().String(), next) {
|
if !fn(entry, iter.Key(), next) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,16 +116,94 @@ func (r mapReflect) Unstructured() interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r mapReflect) Equals(m Map) bool {
|
func (r mapReflect) Equals(m Map) bool {
|
||||||
if r.Length() != m.Length() {
|
return r.EqualsUsing(HeapAllocator, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r mapReflect) EqualsUsing(a Allocator, m Map) bool {
|
||||||
|
lhsLength := r.Length()
|
||||||
|
rhsLength := m.Length()
|
||||||
|
if lhsLength != rhsLength {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhsLength == 0 {
|
||||||
// TODO: Optimize to avoid Iterate looping here by using r.Value.MapRange or similar if it improves performance.
|
return true
|
||||||
|
}
|
||||||
|
vr := a.allocValueReflect()
|
||||||
|
defer a.Free(vr)
|
||||||
|
entry := TypeReflectEntryOf(r.Value.Type().Elem())
|
||||||
return m.Iterate(func(key string, value Value) bool {
|
return m.Iterate(func(key string, value Value) bool {
|
||||||
lhsVal, ok := r.Get(key)
|
_, lhsVal, ok := r.get(key)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return Equals(lhsVal, value)
|
return Equals(vr.mustReuse(lhsVal, entry, nil, nil), value)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r mapReflect) Zip(other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
|
||||||
|
return r.ZipUsing(HeapAllocator, other, order, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r mapReflect) ZipUsing(a Allocator, other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
|
||||||
|
if otherMapReflect, ok := other.(*mapReflect); ok && order == Unordered {
|
||||||
|
return r.unorderedReflectZip(a, otherMapReflect, fn)
|
||||||
|
}
|
||||||
|
return defaultMapZip(a, &r, other, order, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// unorderedReflectZip provides an optimized unordered zip for mapReflect types.
|
||||||
|
func (r mapReflect) unorderedReflectZip(a Allocator, other *mapReflect, fn func(key string, lhs, rhs Value) bool) bool {
|
||||||
|
if r.Empty() && (other == nil || other.Empty()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
lhs := r.Value
|
||||||
|
lhsEntry := TypeReflectEntryOf(lhs.Type().Elem())
|
||||||
|
|
||||||
|
// map lookup via reflection is expensive enough that it is better to keep track of visited keys
|
||||||
|
visited := map[string]struct{}{}
|
||||||
|
|
||||||
|
vlhs, vrhs := a.allocValueReflect(), a.allocValueReflect()
|
||||||
|
defer a.Free(vlhs)
|
||||||
|
defer a.Free(vrhs)
|
||||||
|
|
||||||
|
if other != nil {
|
||||||
|
rhs := other.Value
|
||||||
|
rhsEntry := TypeReflectEntryOf(rhs.Type().Elem())
|
||||||
|
iter := rhs.MapRange()
|
||||||
|
|
||||||
|
for iter.Next() {
|
||||||
|
key := iter.Key()
|
||||||
|
keyString := key.String()
|
||||||
|
next := iter.Value()
|
||||||
|
if !next.IsValid() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rhsVal := vrhs.mustReuse(next, rhsEntry, &rhs, &key)
|
||||||
|
visited[keyString] = struct{}{}
|
||||||
|
var lhsVal Value
|
||||||
|
if _, v, ok := r.get(keyString); ok {
|
||||||
|
lhsVal = vlhs.mustReuse(v, lhsEntry, &lhs, &key)
|
||||||
|
}
|
||||||
|
if !fn(keyString, lhsVal, rhsVal) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iter := lhs.MapRange()
|
||||||
|
for iter.Next() {
|
||||||
|
key := iter.Key()
|
||||||
|
if _, ok := visited[key.String()]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
next := iter.Value()
|
||||||
|
if !next.IsValid() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !fn(key.String(), vlhs.mustReuse(next, lhsEntry, &lhs, &key), nil) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
129
vendor/sigs.k8s.io/structured-merge-diff/v3/value/mapunstructured.go
generated
vendored
129
vendor/sigs.k8s.io/structured-merge-diff/v3/value/mapunstructured.go
generated
vendored
@ -23,10 +23,14 @@ func (m mapUnstructuredInterface) Set(key string, val Value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m mapUnstructuredInterface) Get(key string) (Value, bool) {
|
func (m mapUnstructuredInterface) Get(key string) (Value, bool) {
|
||||||
|
return m.GetUsing(HeapAllocator, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mapUnstructuredInterface) GetUsing(a Allocator, key string) (Value, bool) {
|
||||||
if v, ok := m[key]; !ok {
|
if v, ok := m[key]; !ok {
|
||||||
return nil, false
|
return nil, false
|
||||||
} else {
|
} else {
|
||||||
return NewValueInterface(v), true
|
return a.allocValueUnstructured().reuse(v), true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,16 +44,22 @@ func (m mapUnstructuredInterface) Delete(key string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m mapUnstructuredInterface) Iterate(fn func(key string, value Value) bool) bool {
|
func (m mapUnstructuredInterface) Iterate(fn func(key string, value Value) bool) bool {
|
||||||
|
return m.IterateUsing(HeapAllocator, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mapUnstructuredInterface) IterateUsing(a Allocator, fn func(key string, value Value) bool) bool {
|
||||||
|
if len(m) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
vv := a.allocValueUnstructured()
|
||||||
|
defer a.Free(vv)
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
if ks, ok := k.(string); !ok {
|
if ks, ok := k.(string); !ok {
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
vv := NewValueInterface(v)
|
if !fn(ks, vv.reuse(v)) {
|
||||||
if !fn(ks, vv) {
|
|
||||||
vv.Recycle()
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
vv.Recycle()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -59,29 +69,40 @@ func (m mapUnstructuredInterface) Length() int {
|
|||||||
return len(m)
|
return len(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m mapUnstructuredInterface) Empty() bool {
|
||||||
|
return len(m) == 0
|
||||||
|
}
|
||||||
|
|
||||||
func (m mapUnstructuredInterface) Equals(other Map) bool {
|
func (m mapUnstructuredInterface) Equals(other Map) bool {
|
||||||
if m.Length() != other.Length() {
|
return m.EqualsUsing(HeapAllocator, other)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mapUnstructuredInterface) EqualsUsing(a Allocator, other Map) bool {
|
||||||
|
lhsLength := m.Length()
|
||||||
|
rhsLength := other.Length()
|
||||||
|
if lhsLength != rhsLength {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for k, v := range m {
|
if lhsLength == 0 {
|
||||||
ks, ok := k.(string)
|
return true
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
vo, ok := other.Get(ks)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
vv := NewValueInterface(v)
|
|
||||||
if !Equals(vv, vo) {
|
|
||||||
vv.Recycle()
|
|
||||||
vo.Recycle()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
vo.Recycle()
|
|
||||||
vv.Recycle()
|
|
||||||
}
|
}
|
||||||
return true
|
vv := a.allocValueUnstructured()
|
||||||
|
defer a.Free(vv)
|
||||||
|
return other.Iterate(func(key string, value Value) bool {
|
||||||
|
lhsVal, ok := m[key]
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return Equals(vv.reuse(lhsVal), value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mapUnstructuredInterface) Zip(other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
|
||||||
|
return m.ZipUsing(HeapAllocator, other, order, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mapUnstructuredInterface) ZipUsing(a Allocator, other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
|
||||||
|
return defaultMapZip(a, m, other, order, fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
type mapUnstructuredString map[string]interface{}
|
type mapUnstructuredString map[string]interface{}
|
||||||
@ -91,10 +112,13 @@ func (m mapUnstructuredString) Set(key string, val Value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m mapUnstructuredString) Get(key string) (Value, bool) {
|
func (m mapUnstructuredString) Get(key string) (Value, bool) {
|
||||||
|
return m.GetUsing(HeapAllocator, key)
|
||||||
|
}
|
||||||
|
func (m mapUnstructuredString) GetUsing(a Allocator, key string) (Value, bool) {
|
||||||
if v, ok := m[key]; !ok {
|
if v, ok := m[key]; !ok {
|
||||||
return nil, false
|
return nil, false
|
||||||
} else {
|
} else {
|
||||||
return NewValueInterface(v), true
|
return a.allocValueUnstructured().reuse(v), true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,13 +132,19 @@ func (m mapUnstructuredString) Delete(key string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m mapUnstructuredString) Iterate(fn func(key string, value Value) bool) bool {
|
func (m mapUnstructuredString) Iterate(fn func(key string, value Value) bool) bool {
|
||||||
|
return m.IterateUsing(HeapAllocator, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mapUnstructuredString) IterateUsing(a Allocator, fn func(key string, value Value) bool) bool {
|
||||||
|
if len(m) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
vv := a.allocValueUnstructured()
|
||||||
|
defer a.Free(vv)
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
vv := NewValueInterface(v)
|
if !fn(k, vv.reuse(v)) {
|
||||||
if !fn(k, vv) {
|
|
||||||
vv.Recycle()
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
vv.Recycle()
|
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -124,22 +154,37 @@ func (m mapUnstructuredString) Length() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m mapUnstructuredString) Equals(other Map) bool {
|
func (m mapUnstructuredString) Equals(other Map) bool {
|
||||||
if m.Length() != other.Length() {
|
return m.EqualsUsing(HeapAllocator, other)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mapUnstructuredString) EqualsUsing(a Allocator, other Map) bool {
|
||||||
|
lhsLength := m.Length()
|
||||||
|
rhsLength := other.Length()
|
||||||
|
if lhsLength != rhsLength {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for k, v := range m {
|
if lhsLength == 0 {
|
||||||
vo, ok := other.Get(k)
|
return true
|
||||||
|
}
|
||||||
|
vv := a.allocValueUnstructured()
|
||||||
|
defer a.Free(vv)
|
||||||
|
return other.Iterate(func(key string, value Value) bool {
|
||||||
|
lhsVal, ok := m[key]
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
vv := NewValueInterface(v)
|
return Equals(vv.reuse(lhsVal), value)
|
||||||
if !Equals(vv, vo) {
|
})
|
||||||
vo.Recycle()
|
}
|
||||||
vv.Recycle()
|
|
||||||
return false
|
func (m mapUnstructuredString) Zip(other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
|
||||||
}
|
return m.ZipUsing(HeapAllocator, other, order, fn)
|
||||||
vo.Recycle()
|
}
|
||||||
vv.Recycle()
|
|
||||||
}
|
func (m mapUnstructuredString) ZipUsing(a Allocator, other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
|
||||||
return true
|
return defaultMapZip(a, m, other, order, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mapUnstructuredString) Empty() bool {
|
||||||
|
return len(m) == 0
|
||||||
}
|
}
|
||||||
|
463
vendor/sigs.k8s.io/structured-merge-diff/v3/value/reflectcache.go
generated
vendored
Normal file
463
vendor/sigs.k8s.io/structured-merge-diff/v3/value/reflectcache.go
generated
vendored
Normal file
@ -0,0 +1,463 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 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 value
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UnstructuredConverter defines how a type can be converted directly to unstructured.
|
||||||
|
// Types that implement json.Marshaler may also optionally implement this interface to provide a more
|
||||||
|
// direct and more efficient conversion. All types that choose to implement this interface must still
|
||||||
|
// implement this same conversion via json.Marshaler.
|
||||||
|
type UnstructuredConverter interface {
|
||||||
|
json.Marshaler // require that json.Marshaler is implemented
|
||||||
|
|
||||||
|
// ToUnstructured returns the unstructured representation.
|
||||||
|
ToUnstructured() interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypeReflectCacheEntry keeps data gathered using reflection about how a type is converted to/from unstructured.
|
||||||
|
type TypeReflectCacheEntry struct {
|
||||||
|
isJsonMarshaler bool
|
||||||
|
ptrIsJsonMarshaler bool
|
||||||
|
isJsonUnmarshaler bool
|
||||||
|
ptrIsJsonUnmarshaler bool
|
||||||
|
isStringConvertable bool
|
||||||
|
ptrIsStringConvertable bool
|
||||||
|
|
||||||
|
structFields map[string]*FieldCacheEntry
|
||||||
|
orderedStructFields []*FieldCacheEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
// FieldCacheEntry keeps data gathered using reflection about how the field of a struct is converted to/from
|
||||||
|
// unstructured.
|
||||||
|
type FieldCacheEntry struct {
|
||||||
|
// JsonName returns the name of the field according to the json tags on the struct field.
|
||||||
|
JsonName string
|
||||||
|
// isOmitEmpty is true if the field has the json 'omitempty' tag.
|
||||||
|
isOmitEmpty bool
|
||||||
|
// fieldPath is a list of field indices (see FieldByIndex) to lookup the value of
|
||||||
|
// a field in a reflect.Value struct. The field indices in the list form a path used
|
||||||
|
// to traverse through intermediary 'inline' fields.
|
||||||
|
fieldPath [][]int
|
||||||
|
|
||||||
|
fieldType reflect.Type
|
||||||
|
TypeEntry *TypeReflectCacheEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FieldCacheEntry) CanOmit(fieldVal reflect.Value) bool {
|
||||||
|
return f.isOmitEmpty && (safeIsNil(fieldVal) || isZero(fieldVal))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUsing returns the field identified by this FieldCacheEntry from the provided struct.
|
||||||
|
func (f *FieldCacheEntry) GetFrom(structVal reflect.Value) reflect.Value {
|
||||||
|
// field might be nested within 'inline' structs
|
||||||
|
for _, elem := range f.fieldPath {
|
||||||
|
structVal = structVal.FieldByIndex(elem)
|
||||||
|
}
|
||||||
|
return structVal
|
||||||
|
}
|
||||||
|
|
||||||
|
var marshalerType = reflect.TypeOf(new(json.Marshaler)).Elem()
|
||||||
|
var unmarshalerType = reflect.TypeOf(new(json.Unmarshaler)).Elem()
|
||||||
|
var unstructuredConvertableType = reflect.TypeOf(new(UnstructuredConverter)).Elem()
|
||||||
|
var defaultReflectCache = newReflectCache()
|
||||||
|
|
||||||
|
// TypeReflectEntryOf returns the TypeReflectCacheEntry of the provided reflect.Type.
|
||||||
|
func TypeReflectEntryOf(t reflect.Type) *TypeReflectCacheEntry {
|
||||||
|
cm := defaultReflectCache.get()
|
||||||
|
if record, ok := cm[t]; ok {
|
||||||
|
return record
|
||||||
|
}
|
||||||
|
updates := reflectCacheMap{}
|
||||||
|
result := typeReflectEntryOf(cm, t, updates)
|
||||||
|
if len(updates) > 0 {
|
||||||
|
defaultReflectCache.update(updates)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypeReflectEntryOf returns all updates needed to add provided reflect.Type, and the types its fields transitively
|
||||||
|
// depend on, to the cache.
|
||||||
|
func typeReflectEntryOf(cm reflectCacheMap, t reflect.Type, updates reflectCacheMap) *TypeReflectCacheEntry {
|
||||||
|
if record, ok := cm[t]; ok {
|
||||||
|
return record
|
||||||
|
}
|
||||||
|
if record, ok := updates[t]; ok {
|
||||||
|
return record
|
||||||
|
}
|
||||||
|
typeEntry := &TypeReflectCacheEntry{
|
||||||
|
isJsonMarshaler: t.Implements(marshalerType),
|
||||||
|
ptrIsJsonMarshaler: reflect.PtrTo(t).Implements(marshalerType),
|
||||||
|
isJsonUnmarshaler: reflect.PtrTo(t).Implements(unmarshalerType),
|
||||||
|
isStringConvertable: t.Implements(unstructuredConvertableType),
|
||||||
|
ptrIsStringConvertable: reflect.PtrTo(t).Implements(unstructuredConvertableType),
|
||||||
|
}
|
||||||
|
if t.Kind() == reflect.Struct {
|
||||||
|
fieldEntries := map[string]*FieldCacheEntry{}
|
||||||
|
buildStructCacheEntry(t, fieldEntries, nil)
|
||||||
|
typeEntry.structFields = fieldEntries
|
||||||
|
sortedByJsonName := make([]*FieldCacheEntry, len(fieldEntries))
|
||||||
|
i := 0
|
||||||
|
for _, entry := range fieldEntries {
|
||||||
|
sortedByJsonName[i] = entry
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
sort.Slice(sortedByJsonName, func(i, j int) bool {
|
||||||
|
return sortedByJsonName[i].JsonName < sortedByJsonName[j].JsonName
|
||||||
|
})
|
||||||
|
typeEntry.orderedStructFields = sortedByJsonName
|
||||||
|
}
|
||||||
|
|
||||||
|
// cyclic type references are allowed, so we must add the typeEntry to the updates map before resolving
|
||||||
|
// the field.typeEntry references, or creating them if they are not already in the cache
|
||||||
|
updates[t] = typeEntry
|
||||||
|
|
||||||
|
for _, field := range typeEntry.structFields {
|
||||||
|
if field.TypeEntry == nil {
|
||||||
|
field.TypeEntry = typeReflectEntryOf(cm, field.fieldType, updates)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return typeEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildStructCacheEntry(t reflect.Type, infos map[string]*FieldCacheEntry, fieldPath [][]int) {
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
field := t.Field(i)
|
||||||
|
jsonName, omit, isInline, isOmitempty := lookupJsonTags(field)
|
||||||
|
if omit {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if isInline {
|
||||||
|
buildStructCacheEntry(field.Type, infos, append(fieldPath, field.Index))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
info := &FieldCacheEntry{JsonName: jsonName, isOmitEmpty: isOmitempty, fieldPath: append(fieldPath, field.Index), fieldType: field.Type}
|
||||||
|
infos[jsonName] = info
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fields returns a map of JSON field name to FieldCacheEntry for structs, or nil for non-structs.
|
||||||
|
func (e TypeReflectCacheEntry) Fields() map[string]*FieldCacheEntry {
|
||||||
|
return e.structFields
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fields returns a map of JSON field name to FieldCacheEntry for structs, or nil for non-structs.
|
||||||
|
func (e TypeReflectCacheEntry) OrderedFields() []*FieldCacheEntry {
|
||||||
|
return e.orderedStructFields
|
||||||
|
}
|
||||||
|
|
||||||
|
// CanConvertToUnstructured returns true if this TypeReflectCacheEntry can convert values of its type to unstructured.
|
||||||
|
func (e TypeReflectCacheEntry) CanConvertToUnstructured() bool {
|
||||||
|
return e.isJsonMarshaler || e.ptrIsJsonMarshaler || e.isStringConvertable || e.ptrIsStringConvertable
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUnstructured converts the provided value to unstructured and returns it.
|
||||||
|
func (e TypeReflectCacheEntry) ToUnstructured(sv reflect.Value) (interface{}, error) {
|
||||||
|
// This is based on https://github.com/kubernetes/kubernetes/blob/82c9e5c814eb7acc6cc0a090c057294d0667ad66/staging/src/k8s.io/apimachinery/pkg/runtime/converter.go#L505
|
||||||
|
// and is intended to replace it.
|
||||||
|
|
||||||
|
// Check if the object has a custom string converter and use it if available, since it is much more efficient
|
||||||
|
// than round tripping through json.
|
||||||
|
if converter, ok := e.getUnstructuredConverter(sv); ok {
|
||||||
|
return converter.ToUnstructured(), nil
|
||||||
|
}
|
||||||
|
// Check if the object has a custom JSON marshaller/unmarshaller.
|
||||||
|
if marshaler, ok := e.getJsonMarshaler(sv); ok {
|
||||||
|
if sv.Kind() == reflect.Ptr && sv.IsNil() {
|
||||||
|
// We're done - we don't need to store anything.
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := marshaler.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case len(data) == 0:
|
||||||
|
return nil, fmt.Errorf("error decoding from json: empty value")
|
||||||
|
|
||||||
|
case bytes.Equal(data, nullBytes):
|
||||||
|
// We're done - we don't need to store anything.
|
||||||
|
return nil, nil
|
||||||
|
|
||||||
|
case bytes.Equal(data, trueBytes):
|
||||||
|
return true, nil
|
||||||
|
|
||||||
|
case bytes.Equal(data, falseBytes):
|
||||||
|
return false, nil
|
||||||
|
|
||||||
|
case data[0] == '"':
|
||||||
|
var result string
|
||||||
|
err := unmarshal(data, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error decoding string from json: %v", err)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
|
||||||
|
case data[0] == '{':
|
||||||
|
result := make(map[string]interface{})
|
||||||
|
err := unmarshal(data, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error decoding object from json: %v", err)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
|
||||||
|
case data[0] == '[':
|
||||||
|
result := make([]interface{}, 0)
|
||||||
|
err := unmarshal(data, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error decoding array from json: %v", err)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
var (
|
||||||
|
resultInt int64
|
||||||
|
resultFloat float64
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if err = unmarshal(data, &resultInt); err == nil {
|
||||||
|
return resultInt, nil
|
||||||
|
} else if err = unmarshal(data, &resultFloat); err == nil {
|
||||||
|
return resultFloat, nil
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("error decoding number from json: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("provided type cannot be converted: %v", sv.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
// CanConvertFromUnstructured returns true if this TypeReflectCacheEntry can convert objects of the type from unstructured.
|
||||||
|
func (e TypeReflectCacheEntry) CanConvertFromUnstructured() bool {
|
||||||
|
return e.isJsonUnmarshaler
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromUnstructured converts the provided source value from unstructured into the provided destination value.
|
||||||
|
func (e TypeReflectCacheEntry) FromUnstructured(sv, dv reflect.Value) error {
|
||||||
|
// TODO: this could be made much more efficient using direct conversions like
|
||||||
|
// UnstructuredConverter.ToUnstructured provides.
|
||||||
|
st := dv.Type()
|
||||||
|
data, err := json.Marshal(sv.Interface())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error encoding %s to json: %v", st.String(), err)
|
||||||
|
}
|
||||||
|
if unmarshaler, ok := e.getJsonUnmarshaler(dv); ok {
|
||||||
|
return unmarshaler.UnmarshalJSON(data)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("unable to unmarshal %v into %v", sv.Type(), dv.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
nullBytes = []byte("null")
|
||||||
|
trueBytes = []byte("true")
|
||||||
|
falseBytes = []byte("false")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (e TypeReflectCacheEntry) getJsonMarshaler(v reflect.Value) (json.Marshaler, bool) {
|
||||||
|
if e.isJsonMarshaler {
|
||||||
|
return v.Interface().(json.Marshaler), true
|
||||||
|
}
|
||||||
|
if e.ptrIsJsonMarshaler {
|
||||||
|
// Check pointer receivers if v is not a pointer
|
||||||
|
if v.Kind() != reflect.Ptr && v.CanAddr() {
|
||||||
|
v = v.Addr()
|
||||||
|
return v.Interface().(json.Marshaler), true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e TypeReflectCacheEntry) getJsonUnmarshaler(v reflect.Value) (json.Unmarshaler, bool) {
|
||||||
|
if !e.isJsonUnmarshaler {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return v.Addr().Interface().(json.Unmarshaler), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e TypeReflectCacheEntry) getUnstructuredConverter(v reflect.Value) (UnstructuredConverter, bool) {
|
||||||
|
if e.isStringConvertable {
|
||||||
|
return v.Interface().(UnstructuredConverter), true
|
||||||
|
}
|
||||||
|
if e.ptrIsStringConvertable {
|
||||||
|
// Check pointer receivers if v is not a pointer
|
||||||
|
if v.CanAddr() {
|
||||||
|
v = v.Addr()
|
||||||
|
return v.Interface().(UnstructuredConverter), true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
type typeReflectCache struct {
|
||||||
|
// use an atomic and copy-on-write since there are a fixed (typically very small) number of structs compiled into any
|
||||||
|
// go program using this cache
|
||||||
|
value atomic.Value
|
||||||
|
// mu is held by writers when performing load/modify/store operations on the cache, readers do not need to hold a
|
||||||
|
// read-lock since the atomic value is always read-only
|
||||||
|
mu sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func newReflectCache() *typeReflectCache {
|
||||||
|
cache := &typeReflectCache{}
|
||||||
|
cache.value.Store(make(reflectCacheMap))
|
||||||
|
return cache
|
||||||
|
}
|
||||||
|
|
||||||
|
type reflectCacheMap map[reflect.Type]*TypeReflectCacheEntry
|
||||||
|
|
||||||
|
// get returns the reflectCacheMap.
|
||||||
|
func (c *typeReflectCache) get() reflectCacheMap {
|
||||||
|
return c.value.Load().(reflectCacheMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
// update merges the provided updates into the cache.
|
||||||
|
func (c *typeReflectCache) update(updates reflectCacheMap) {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
|
currentCacheMap := c.value.Load().(reflectCacheMap)
|
||||||
|
|
||||||
|
hasNewEntries := false
|
||||||
|
for t := range updates {
|
||||||
|
if _, ok := currentCacheMap[t]; !ok {
|
||||||
|
hasNewEntries = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !hasNewEntries {
|
||||||
|
// Bail if the updates have been set while waiting for lock acquisition.
|
||||||
|
// This is safe since setting entries is idempotent.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
newCacheMap := make(reflectCacheMap, len(currentCacheMap)+len(updates))
|
||||||
|
for k, v := range currentCacheMap {
|
||||||
|
newCacheMap[k] = v
|
||||||
|
}
|
||||||
|
for t, update := range updates {
|
||||||
|
newCacheMap[t] = update
|
||||||
|
}
|
||||||
|
c.value.Store(newCacheMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Below json Unmarshal is fromk8s.io/apimachinery/pkg/util/json
|
||||||
|
// to handle number conversions as expected by Kubernetes
|
||||||
|
|
||||||
|
// limit recursive depth to prevent stack overflow errors
|
||||||
|
const maxDepth = 10000
|
||||||
|
|
||||||
|
// unmarshal unmarshals the given data
|
||||||
|
// If v is a *map[string]interface{}, numbers are converted to int64 or float64
|
||||||
|
func unmarshal(data []byte, v interface{}) error {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case *map[string]interface{}:
|
||||||
|
// Build a decoder from the given data
|
||||||
|
decoder := json.NewDecoder(bytes.NewBuffer(data))
|
||||||
|
// Preserve numbers, rather than casting to float64 automatically
|
||||||
|
decoder.UseNumber()
|
||||||
|
// Run the decode
|
||||||
|
if err := decoder.Decode(v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// If the decode succeeds, post-process the map to convert json.Number objects to int64 or float64
|
||||||
|
return convertMapNumbers(*v, 0)
|
||||||
|
|
||||||
|
case *[]interface{}:
|
||||||
|
// Build a decoder from the given data
|
||||||
|
decoder := json.NewDecoder(bytes.NewBuffer(data))
|
||||||
|
// Preserve numbers, rather than casting to float64 automatically
|
||||||
|
decoder.UseNumber()
|
||||||
|
// Run the decode
|
||||||
|
if err := decoder.Decode(v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// If the decode succeeds, post-process the map to convert json.Number objects to int64 or float64
|
||||||
|
return convertSliceNumbers(*v, 0)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return json.Unmarshal(data, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertMapNumbers traverses the map, converting any json.Number values to int64 or float64.
|
||||||
|
// values which are map[string]interface{} or []interface{} are recursively visited
|
||||||
|
func convertMapNumbers(m map[string]interface{}, depth int) error {
|
||||||
|
if depth > maxDepth {
|
||||||
|
return fmt.Errorf("exceeded max depth of %d", maxDepth)
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
for k, v := range m {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case json.Number:
|
||||||
|
m[k], err = convertNumber(v)
|
||||||
|
case map[string]interface{}:
|
||||||
|
err = convertMapNumbers(v, depth+1)
|
||||||
|
case []interface{}:
|
||||||
|
err = convertSliceNumbers(v, depth+1)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertSliceNumbers traverses the slice, converting any json.Number values to int64 or float64.
|
||||||
|
// values which are map[string]interface{} or []interface{} are recursively visited
|
||||||
|
func convertSliceNumbers(s []interface{}, depth int) error {
|
||||||
|
if depth > maxDepth {
|
||||||
|
return fmt.Errorf("exceeded max depth of %d", maxDepth)
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
for i, v := range s {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case json.Number:
|
||||||
|
s[i], err = convertNumber(v)
|
||||||
|
case map[string]interface{}:
|
||||||
|
err = convertMapNumbers(v, depth+1)
|
||||||
|
case []interface{}:
|
||||||
|
err = convertSliceNumbers(v, depth+1)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertNumber converts a json.Number to an int64 or float64, or returns an error
|
||||||
|
func convertNumber(n json.Number) (interface{}, error) {
|
||||||
|
// Attempt to convert to an int64 first
|
||||||
|
if i, err := n.Int64(); err == nil {
|
||||||
|
return i, nil
|
||||||
|
}
|
||||||
|
// Return a float64 (default json.Decode() behavior)
|
||||||
|
// An overflow will return an error
|
||||||
|
return n.Float64()
|
||||||
|
}
|
237
vendor/sigs.k8s.io/structured-merge-diff/v3/value/structreflect.go
generated
vendored
237
vendor/sigs.k8s.io/structured-merge-diff/v3/value/structreflect.go
generated
vendored
@ -19,162 +19,66 @@ package value
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// reflectStructCache keeps track of json tag related data for structs and fields to speed up reflection.
|
|
||||||
// TODO: This overlaps in functionality with the fieldCache in
|
|
||||||
// https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/runtime/converter.go#L57 but
|
|
||||||
// is more efficient at lookup by json field name. The logic should be consolidated. Only one copy of the cache needs
|
|
||||||
// to be kept for each running process.
|
|
||||||
var (
|
|
||||||
reflectStructCache = newStructCache()
|
|
||||||
)
|
|
||||||
|
|
||||||
type structCache struct {
|
|
||||||
// use an atomic and copy-on-write since there are a fixed (typically very small) number of structs compiled into any
|
|
||||||
// go program using this cache
|
|
||||||
value atomic.Value
|
|
||||||
// mu is held by writers when performing load/modify/store operations on the cache, readers do not need to hold a
|
|
||||||
// read-lock since the atomic value is always read-only
|
|
||||||
mu sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
type structCacheMap map[reflect.Type]structCacheEntry
|
|
||||||
|
|
||||||
// structCacheEntry contains information about each struct field, keyed by json field name, that is expensive to
|
|
||||||
// compute using reflection.
|
|
||||||
type structCacheEntry map[string]*fieldCacheEntry
|
|
||||||
|
|
||||||
// Get returns true and fieldCacheEntry for the given type if the type is in the cache. Otherwise Get returns false.
|
|
||||||
func (c *structCache) Get(t reflect.Type) (map[string]*fieldCacheEntry, bool) {
|
|
||||||
entry, ok := c.value.Load().(structCacheMap)[t]
|
|
||||||
return entry, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set sets the fieldCacheEntry for the given type via a copy-on-write update to the struct cache.
|
|
||||||
func (c *structCache) Set(t reflect.Type, m map[string]*fieldCacheEntry) {
|
|
||||||
c.mu.Lock()
|
|
||||||
defer c.mu.Unlock()
|
|
||||||
|
|
||||||
currentCacheMap := c.value.Load().(structCacheMap)
|
|
||||||
|
|
||||||
if _, ok := currentCacheMap[t]; ok {
|
|
||||||
// Bail if the entry has been set while waiting for lock acquisition.
|
|
||||||
// This is safe since setting entries is idempotent.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
newCacheMap := make(structCacheMap, len(currentCacheMap)+1)
|
|
||||||
for k, v := range currentCacheMap {
|
|
||||||
newCacheMap[k] = v
|
|
||||||
}
|
|
||||||
newCacheMap[t] = m
|
|
||||||
c.value.Store(newCacheMap)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newStructCache() *structCache {
|
|
||||||
cache := &structCache{}
|
|
||||||
cache.value.Store(make(structCacheMap))
|
|
||||||
return cache
|
|
||||||
}
|
|
||||||
|
|
||||||
type fieldCacheEntry struct {
|
|
||||||
// isOmitEmpty is true if the field has the json 'omitempty' tag.
|
|
||||||
isOmitEmpty bool
|
|
||||||
// fieldPath is the field indices (see FieldByIndex) to lookup the value of
|
|
||||||
// a field in a reflect.Value struct. A path of field indices is used
|
|
||||||
// to support traversing to a field field in struct fields that have the 'inline'
|
|
||||||
// json tag.
|
|
||||||
fieldPath [][]int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fieldCacheEntry) getFieldFromStruct(structVal reflect.Value) reflect.Value {
|
|
||||||
// field might be field within 'inline' structs
|
|
||||||
for _, elem := range f.fieldPath {
|
|
||||||
structVal = structVal.FieldByIndex(elem)
|
|
||||||
}
|
|
||||||
return structVal
|
|
||||||
}
|
|
||||||
|
|
||||||
func getStructCacheEntry(t reflect.Type) structCacheEntry {
|
|
||||||
if hints, ok := reflectStructCache.Get(t); ok {
|
|
||||||
return hints
|
|
||||||
}
|
|
||||||
|
|
||||||
hints := map[string]*fieldCacheEntry{}
|
|
||||||
buildStructCacheEntry(t, hints, nil)
|
|
||||||
|
|
||||||
reflectStructCache.Set(t, hints)
|
|
||||||
return hints
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildStructCacheEntry(t reflect.Type, infos map[string]*fieldCacheEntry, fieldPath [][]int) {
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
|
||||||
field := t.Field(i)
|
|
||||||
jsonName, omit, isInline, isOmitempty := lookupJsonTags(field)
|
|
||||||
if omit {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if isInline {
|
|
||||||
buildStructCacheEntry(field.Type, infos, append(fieldPath, field.Index))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
info := &fieldCacheEntry{isOmitEmpty: isOmitempty, fieldPath: append(fieldPath, field.Index)}
|
|
||||||
infos[jsonName] = info
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type structReflect struct {
|
type structReflect struct {
|
||||||
valueReflect
|
valueReflect
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r structReflect) Length() int {
|
func (r structReflect) Length() int {
|
||||||
i := 0
|
i := 0
|
||||||
eachStructField(r.Value, func(s string, value reflect.Value) bool {
|
eachStructField(r.Value, func(_ *TypeReflectCacheEntry, s string, value reflect.Value) bool {
|
||||||
i++
|
i++
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r structReflect) Empty() bool {
|
||||||
|
return eachStructField(r.Value, func(_ *TypeReflectCacheEntry, s string, value reflect.Value) bool {
|
||||||
|
return false // exit early if the struct is non-empty
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (r structReflect) Get(key string) (Value, bool) {
|
func (r structReflect) Get(key string) (Value, bool) {
|
||||||
if val, ok, _ := r.findJsonNameField(key); ok {
|
return r.GetUsing(HeapAllocator, key)
|
||||||
return mustWrapValueReflect(val), true
|
}
|
||||||
|
|
||||||
|
func (r structReflect) GetUsing(a Allocator, key string) (Value, bool) {
|
||||||
|
if val, ok := r.findJsonNameField(key); ok {
|
||||||
|
return a.allocValueReflect().mustReuse(val, nil, nil, nil), true
|
||||||
}
|
}
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r structReflect) Has(key string) bool {
|
func (r structReflect) Has(key string) bool {
|
||||||
_, ok, _ := r.findJsonNameField(key)
|
_, ok := r.findJsonNameField(key)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r structReflect) Set(key string, val Value) {
|
func (r structReflect) Set(key string, val Value) {
|
||||||
fieldEntry, ok := getStructCacheEntry(r.Value.Type())[key]
|
fieldEntry, ok := TypeReflectEntryOf(r.Value.Type()).Fields()[key]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("key %s may not be set on struct %T: field does not exist", key, r.Value.Interface()))
|
panic(fmt.Sprintf("key %s may not be set on struct %T: field does not exist", key, r.Value.Interface()))
|
||||||
}
|
}
|
||||||
oldVal := fieldEntry.getFieldFromStruct(r.Value)
|
oldVal := fieldEntry.GetFrom(r.Value)
|
||||||
newVal := reflect.ValueOf(val.Unstructured())
|
newVal := reflect.ValueOf(val.Unstructured())
|
||||||
r.update(fieldEntry, key, oldVal, newVal)
|
r.update(fieldEntry, key, oldVal, newVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r structReflect) Delete(key string) {
|
func (r structReflect) Delete(key string) {
|
||||||
fieldEntry, ok := getStructCacheEntry(r.Value.Type())[key]
|
fieldEntry, ok := TypeReflectEntryOf(r.Value.Type()).Fields()[key]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("key %s may not be deleted on struct %T: field does not exist", key, r.Value.Interface()))
|
panic(fmt.Sprintf("key %s may not be deleted on struct %T: field does not exist", key, r.Value.Interface()))
|
||||||
}
|
}
|
||||||
oldVal := fieldEntry.getFieldFromStruct(r.Value)
|
oldVal := fieldEntry.GetFrom(r.Value)
|
||||||
if oldVal.Kind() != reflect.Ptr && !fieldEntry.isOmitEmpty {
|
if oldVal.Kind() != reflect.Ptr && !fieldEntry.isOmitEmpty {
|
||||||
panic(fmt.Sprintf("key %s may not be deleted on struct: %T: value is neither a pointer nor an omitempty field", key, r.Value.Interface()))
|
panic(fmt.Sprintf("key %s may not be deleted on struct: %T: value is neither a pointer nor an omitempty field", key, r.Value.Interface()))
|
||||||
}
|
}
|
||||||
r.update(fieldEntry, key, oldVal, reflect.Zero(oldVal.Type()))
|
r.update(fieldEntry, key, oldVal, reflect.Zero(oldVal.Type()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r structReflect) update(fieldEntry *fieldCacheEntry, key string, oldVal, newVal reflect.Value) {
|
func (r structReflect) update(fieldEntry *FieldCacheEntry, key string, oldVal, newVal reflect.Value) {
|
||||||
if oldVal.CanSet() {
|
if oldVal.CanSet() {
|
||||||
oldVal.Set(newVal)
|
oldVal.Set(newVal)
|
||||||
return
|
return
|
||||||
@ -187,7 +91,7 @@ func (r structReflect) update(fieldEntry *fieldCacheEntry, key string, oldVal, n
|
|||||||
panic("ParentMapKey must not be nil if ParentMap is not nil")
|
panic("ParentMapKey must not be nil if ParentMap is not nil")
|
||||||
}
|
}
|
||||||
replacement := reflect.New(r.Value.Type()).Elem()
|
replacement := reflect.New(r.Value.Type()).Elem()
|
||||||
fieldEntry.getFieldFromStruct(replacement).Set(newVal)
|
fieldEntry.GetFrom(replacement).Set(newVal)
|
||||||
r.ParentMap.SetMapIndex(*r.ParentMapKey, replacement)
|
r.ParentMap.SetMapIndex(*r.ParentMapKey, replacement)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -198,21 +102,25 @@ func (r structReflect) update(fieldEntry *fieldCacheEntry, key string, oldVal, n
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r structReflect) Iterate(fn func(string, Value) bool) bool {
|
func (r structReflect) Iterate(fn func(string, Value) bool) bool {
|
||||||
return eachStructField(r.Value, func(s string, value reflect.Value) bool {
|
return r.IterateUsing(HeapAllocator, fn)
|
||||||
v := mustWrapValueReflect(value)
|
}
|
||||||
defer v.Recycle()
|
|
||||||
return fn(s, v)
|
func (r structReflect) IterateUsing(a Allocator, fn func(string, Value) bool) bool {
|
||||||
|
vr := a.allocValueReflect()
|
||||||
|
defer a.Free(vr)
|
||||||
|
return eachStructField(r.Value, func(e *TypeReflectCacheEntry, s string, value reflect.Value) bool {
|
||||||
|
return fn(s, vr.mustReuse(value, e, nil, nil))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func eachStructField(structVal reflect.Value, fn func(string, reflect.Value) bool) bool {
|
func eachStructField(structVal reflect.Value, fn func(*TypeReflectCacheEntry, string, reflect.Value) bool) bool {
|
||||||
for jsonName, fieldCacheEntry := range getStructCacheEntry(structVal.Type()) {
|
for _, fieldCacheEntry := range TypeReflectEntryOf(structVal.Type()).OrderedFields() {
|
||||||
fieldVal := fieldCacheEntry.getFieldFromStruct(structVal)
|
fieldVal := fieldCacheEntry.GetFrom(structVal)
|
||||||
if fieldCacheEntry.isOmitEmpty && (safeIsNil(fieldVal) || isZero(fieldVal)) {
|
if fieldCacheEntry.CanOmit(fieldVal) {
|
||||||
// omit it
|
// omit it
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ok := fn(jsonName, fieldVal)
|
ok := fn(fieldCacheEntry.TypeEntry, fieldCacheEntry.JsonName, fieldVal)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -231,39 +139,70 @@ func (r structReflect) Unstructured() interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r structReflect) Equals(m Map) bool {
|
func (r structReflect) Equals(m Map) bool {
|
||||||
if rhsStruct, ok := m.(structReflect); ok {
|
return r.EqualsUsing(HeapAllocator, m)
|
||||||
return reflect.DeepEqual(r.Value.Interface(), rhsStruct.Value.Interface())
|
}
|
||||||
}
|
|
||||||
if r.Length() != m.Length() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
structCacheEntry := getStructCacheEntry(r.Value.Type())
|
|
||||||
|
|
||||||
return m.Iterate(func(s string, value Value) bool {
|
func (r structReflect) EqualsUsing(a Allocator, m Map) bool {
|
||||||
fieldCacheEntry, ok := structCacheEntry[s]
|
// MapEquals uses zip and is fairly efficient for structReflect
|
||||||
if !ok {
|
return MapEqualsUsing(a, &r, m)
|
||||||
return false
|
|
||||||
}
|
|
||||||
lhsVal := fieldCacheEntry.getFieldFromStruct(r.Value)
|
|
||||||
return Equals(mustWrapValueReflect(lhsVal), value)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r structReflect) findJsonNameFieldAndNotEmpty(jsonName string) (reflect.Value, bool) {
|
func (r structReflect) findJsonNameFieldAndNotEmpty(jsonName string) (reflect.Value, bool) {
|
||||||
structCacheEntry, ok := getStructCacheEntry(r.Value.Type())[jsonName]
|
structCacheEntry, ok := TypeReflectEntryOf(r.Value.Type()).Fields()[jsonName]
|
||||||
if !ok {
|
if !ok {
|
||||||
return reflect.Value{}, false
|
return reflect.Value{}, false
|
||||||
}
|
}
|
||||||
fieldVal := structCacheEntry.getFieldFromStruct(r.Value)
|
fieldVal := structCacheEntry.GetFrom(r.Value)
|
||||||
omit := structCacheEntry.isOmitEmpty && (safeIsNil(fieldVal) || isZero(fieldVal))
|
return fieldVal, !structCacheEntry.CanOmit(fieldVal)
|
||||||
return fieldVal, !omit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r structReflect) findJsonNameField(jsonName string) (val reflect.Value, ok bool, omitEmpty bool) {
|
func (r structReflect) findJsonNameField(jsonName string) (val reflect.Value, ok bool) {
|
||||||
structCacheEntry, ok := getStructCacheEntry(r.Value.Type())[jsonName]
|
structCacheEntry, ok := TypeReflectEntryOf(r.Value.Type()).Fields()[jsonName]
|
||||||
if !ok {
|
if !ok {
|
||||||
return reflect.Value{}, false, false
|
return reflect.Value{}, false
|
||||||
}
|
}
|
||||||
fieldVal := structCacheEntry.getFieldFromStruct(r.Value)
|
fieldVal := structCacheEntry.GetFrom(r.Value)
|
||||||
return fieldVal, true, structCacheEntry.isOmitEmpty
|
return fieldVal, !structCacheEntry.CanOmit(fieldVal)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r structReflect) Zip(other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
|
||||||
|
return r.ZipUsing(HeapAllocator, other, order, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r structReflect) ZipUsing(a Allocator, other Map, order MapTraverseOrder, fn func(key string, lhs, rhs Value) bool) bool {
|
||||||
|
if otherStruct, ok := other.(*structReflect); ok && r.Value.Type() == otherStruct.Value.Type() {
|
||||||
|
lhsvr, rhsvr := a.allocValueReflect(), a.allocValueReflect()
|
||||||
|
defer a.Free(lhsvr)
|
||||||
|
defer a.Free(rhsvr)
|
||||||
|
return r.structZip(otherStruct, lhsvr, rhsvr, fn)
|
||||||
|
}
|
||||||
|
return defaultMapZip(a, &r, other, order, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// structZip provides an optimized zip for structReflect types. The zip is always lexical key ordered since there is
|
||||||
|
// no additional cost to ordering the zip for structured types.
|
||||||
|
func (r structReflect) structZip(other *structReflect, lhsvr, rhsvr *valueReflect, fn func(key string, lhs, rhs Value) bool) bool {
|
||||||
|
lhsVal := r.Value
|
||||||
|
rhsVal := other.Value
|
||||||
|
|
||||||
|
for _, fieldCacheEntry := range TypeReflectEntryOf(lhsVal.Type()).OrderedFields() {
|
||||||
|
lhsFieldVal := fieldCacheEntry.GetFrom(lhsVal)
|
||||||
|
rhsFieldVal := fieldCacheEntry.GetFrom(rhsVal)
|
||||||
|
lhsOmit := fieldCacheEntry.CanOmit(lhsFieldVal)
|
||||||
|
rhsOmit := fieldCacheEntry.CanOmit(rhsFieldVal)
|
||||||
|
if lhsOmit && rhsOmit {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var lhsVal, rhsVal Value
|
||||||
|
if !lhsOmit {
|
||||||
|
lhsVal = lhsvr.mustReuse(lhsFieldVal, fieldCacheEntry.TypeEntry, nil, nil)
|
||||||
|
}
|
||||||
|
if !rhsOmit {
|
||||||
|
rhsVal = rhsvr.mustReuse(rhsFieldVal, fieldCacheEntry.TypeEntry, nil, nil)
|
||||||
|
}
|
||||||
|
if !fn(fieldCacheEntry.JsonName, lhsVal, rhsVal) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
52
vendor/sigs.k8s.io/structured-merge-diff/v3/value/value.go
generated
vendored
52
vendor/sigs.k8s.io/structured-merge-diff/v3/value/value.go
generated
vendored
@ -55,9 +55,15 @@ type Value interface {
|
|||||||
// AsMap converts the Value into a Map (or panic if the type
|
// AsMap converts the Value into a Map (or panic if the type
|
||||||
// doesn't allow it).
|
// doesn't allow it).
|
||||||
AsMap() Map
|
AsMap() Map
|
||||||
|
// AsMapUsing uses the provided allocator and converts the Value
|
||||||
|
// into a Map (or panic if the type doesn't allow it).
|
||||||
|
AsMapUsing(Allocator) Map
|
||||||
// AsList converts the Value into a List (or panic if the type
|
// AsList converts the Value into a List (or panic if the type
|
||||||
// doesn't allow it).
|
// doesn't allow it).
|
||||||
AsList() List
|
AsList() List
|
||||||
|
// AsListUsing uses the provided allocator and converts the Value
|
||||||
|
// into a List (or panic if the type doesn't allow it).
|
||||||
|
AsListUsing(Allocator) List
|
||||||
// AsBool converts the Value into a bool (or panic if the type
|
// AsBool converts the Value into a bool (or panic if the type
|
||||||
// doesn't allow it).
|
// doesn't allow it).
|
||||||
AsBool() bool
|
AsBool() bool
|
||||||
@ -71,10 +77,6 @@ type Value interface {
|
|||||||
// doesn't allow it).
|
// doesn't allow it).
|
||||||
AsString() string
|
AsString() string
|
||||||
|
|
||||||
// Recycle returns a value of this type that is no longer needed. The
|
|
||||||
// value shouldn't be used after this call.
|
|
||||||
Recycle()
|
|
||||||
|
|
||||||
// Unstructured converts the Value into an Unstructured interface{}.
|
// Unstructured converts the Value into an Unstructured interface{}.
|
||||||
Unstructured() interface{}
|
Unstructured() interface{}
|
||||||
}
|
}
|
||||||
@ -128,6 +130,11 @@ func ToYAML(v Value) ([]byte, error) {
|
|||||||
|
|
||||||
// Equals returns true iff the two values are equal.
|
// Equals returns true iff the two values are equal.
|
||||||
func Equals(lhs, rhs Value) bool {
|
func Equals(lhs, rhs Value) bool {
|
||||||
|
return EqualsUsing(HeapAllocator, lhs, rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EqualsUsing uses the provided allocator and returns true iff the two values are equal.
|
||||||
|
func EqualsUsing(a Allocator, lhs, rhs Value) bool {
|
||||||
if lhs.IsFloat() || rhs.IsFloat() {
|
if lhs.IsFloat() || rhs.IsFloat() {
|
||||||
var lf float64
|
var lf float64
|
||||||
if lhs.IsFloat() {
|
if lhs.IsFloat() {
|
||||||
@ -173,7 +180,11 @@ func Equals(lhs, rhs Value) bool {
|
|||||||
}
|
}
|
||||||
if lhs.IsList() {
|
if lhs.IsList() {
|
||||||
if rhs.IsList() {
|
if rhs.IsList() {
|
||||||
return ListEquals(lhs.AsList(), rhs.AsList())
|
lhsList := lhs.AsListUsing(a)
|
||||||
|
defer a.Free(lhsList)
|
||||||
|
rhsList := rhs.AsListUsing(a)
|
||||||
|
defer a.Free(rhsList)
|
||||||
|
return lhsList.EqualsUsing(a, rhsList)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
} else if rhs.IsList() {
|
} else if rhs.IsList() {
|
||||||
@ -181,7 +192,11 @@ func Equals(lhs, rhs Value) bool {
|
|||||||
}
|
}
|
||||||
if lhs.IsMap() {
|
if lhs.IsMap() {
|
||||||
if rhs.IsMap() {
|
if rhs.IsMap() {
|
||||||
return lhs.AsMap().Equals(rhs.AsMap())
|
lhsList := lhs.AsMapUsing(a)
|
||||||
|
defer a.Free(lhsList)
|
||||||
|
rhsList := rhs.AsMapUsing(a)
|
||||||
|
defer a.Free(rhsList)
|
||||||
|
return lhsList.EqualsUsing(a, rhsList)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
} else if rhs.IsMap() {
|
} else if rhs.IsMap() {
|
||||||
@ -215,8 +230,9 @@ func ToString(v Value) string {
|
|||||||
return fmt.Sprintf("%v", v.AsBool())
|
return fmt.Sprintf("%v", v.AsBool())
|
||||||
case v.IsList():
|
case v.IsList():
|
||||||
strs := []string{}
|
strs := []string{}
|
||||||
for i := 0; i < v.AsList().Length(); i++ {
|
list := v.AsList()
|
||||||
strs = append(strs, ToString(v.AsList().At(i)))
|
for i := 0; i < list.Length(); i++ {
|
||||||
|
strs = append(strs, ToString(list.At(i)))
|
||||||
}
|
}
|
||||||
return "[" + strings.Join(strs, ",") + "]"
|
return "[" + strings.Join(strs, ",") + "]"
|
||||||
case v.IsMap():
|
case v.IsMap():
|
||||||
@ -241,6 +257,14 @@ func Less(lhs, rhs Value) bool {
|
|||||||
// sorted, even if they are of different types). The result will be 0 if
|
// sorted, even if they are of different types). The result will be 0 if
|
||||||
// v==rhs, -1 if v < rhs, and +1 if v > rhs.
|
// v==rhs, -1 if v < rhs, and +1 if v > rhs.
|
||||||
func Compare(lhs, rhs Value) int {
|
func Compare(lhs, rhs Value) int {
|
||||||
|
return CompareUsing(HeapAllocator, lhs, rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompareUsing uses the provided allocator and provides a total
|
||||||
|
// ordering for Value (so that they can be sorted, even if they
|
||||||
|
// are of different types). The result will be 0 if v==rhs, -1
|
||||||
|
// if v < rhs, and +1 if v > rhs.
|
||||||
|
func CompareUsing(a Allocator, lhs, rhs Value) int {
|
||||||
if lhs.IsFloat() {
|
if lhs.IsFloat() {
|
||||||
if !rhs.IsFloat() {
|
if !rhs.IsFloat() {
|
||||||
// Extra: compare floats and ints numerically.
|
// Extra: compare floats and ints numerically.
|
||||||
@ -289,7 +313,11 @@ func Compare(lhs, rhs Value) int {
|
|||||||
if !rhs.IsList() {
|
if !rhs.IsList() {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return ListCompare(lhs.AsList(), rhs.AsList())
|
lhsList := lhs.AsListUsing(a)
|
||||||
|
defer a.Free(lhsList)
|
||||||
|
rhsList := rhs.AsListUsing(a)
|
||||||
|
defer a.Free(rhsList)
|
||||||
|
return ListCompareUsing(a, lhsList, rhsList)
|
||||||
} else if rhs.IsList() {
|
} else if rhs.IsList() {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
@ -297,7 +325,11 @@ func Compare(lhs, rhs Value) int {
|
|||||||
if !rhs.IsMap() {
|
if !rhs.IsMap() {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return MapCompare(lhs.AsMap(), rhs.AsMap())
|
lhsMap := lhs.AsMapUsing(a)
|
||||||
|
defer a.Free(lhsMap)
|
||||||
|
rhsMap := rhs.AsMapUsing(a)
|
||||||
|
defer a.Free(rhsMap)
|
||||||
|
return MapCompareUsing(a, lhsMap, rhsMap)
|
||||||
} else if rhs.IsMap() {
|
} else if rhs.IsMap() {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
279
vendor/sigs.k8s.io/structured-merge-diff/v3/value/valuereflect.go
generated
vendored
279
vendor/sigs.k8s.io/structured-merge-diff/v3/value/valuereflect.go
generated
vendored
@ -17,20 +17,11 @@ limitations under the License.
|
|||||||
package value
|
package value
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var reflectPool = sync.Pool{
|
|
||||||
New: func() interface{} {
|
|
||||||
return &valueReflect{}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewValueReflect creates a Value backed by an "interface{}" type,
|
// NewValueReflect creates a Value backed by an "interface{}" type,
|
||||||
// typically an structured object in Kubernetes world that is uses reflection to expose.
|
// typically an structured object in Kubernetes world that is uses reflection to expose.
|
||||||
// The provided "interface{}" value must be a pointer so that the value can be modified via reflection.
|
// The provided "interface{}" value must be a pointer so that the value can be modified via reflection.
|
||||||
@ -45,33 +36,57 @@ func NewValueReflect(value interface{}) (Value, error) {
|
|||||||
// The root value to reflect on must be a pointer so that map.Set() and map.Delete() operations are possible.
|
// The root value to reflect on must be a pointer so that map.Set() and map.Delete() operations are possible.
|
||||||
return nil, fmt.Errorf("value provided to NewValueReflect must be a pointer")
|
return nil, fmt.Errorf("value provided to NewValueReflect must be a pointer")
|
||||||
}
|
}
|
||||||
return wrapValueReflect(nil, nil, v)
|
return wrapValueReflect(v, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func wrapValueReflect(parentMap, parentMapKey *reflect.Value, value reflect.Value) (Value, error) {
|
// wrapValueReflect wraps the provide reflect.Value as a value. If parent in the data tree is a map, parentMap
|
||||||
// TODO: conversion of json.Marshaller interface types is expensive. This can be mostly optimized away by
|
// and parentMapKey must be provided so that the returned value may be set and deleted.
|
||||||
// introducing conversion functions that do not require going through JSON and using those here.
|
func wrapValueReflect(value reflect.Value, parentMap, parentMapKey *reflect.Value) (Value, error) {
|
||||||
if marshaler, ok := getMarshaler(value); ok {
|
val := HeapAllocator.allocValueReflect()
|
||||||
return toUnstructured(marshaler, value)
|
return val.reuse(value, nil, parentMap, parentMapKey)
|
||||||
}
|
|
||||||
value = dereference(value)
|
|
||||||
val := reflectPool.Get().(*valueReflect)
|
|
||||||
val.Value = value
|
|
||||||
val.ParentMap = parentMap
|
|
||||||
val.ParentMapKey = parentMapKey
|
|
||||||
return Value(val), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustWrapValueReflect(value reflect.Value) Value {
|
// wrapValueReflect wraps the provide reflect.Value as a value, and panics if there is an error. If parent in the data
|
||||||
v, err := wrapValueReflect(nil, nil, value)
|
// tree is a map, parentMap and parentMapKey must be provided so that the returned value may be set and deleted.
|
||||||
|
func mustWrapValueReflect(value reflect.Value, parentMap, parentMapKey *reflect.Value) Value {
|
||||||
|
v, err := wrapValueReflect(value, parentMap, parentMapKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustWrapValueReflectMapItem(parentMap, parentMapKey *reflect.Value, value reflect.Value) Value {
|
// the value interface doesn't care about the type for value.IsNull, so we can use a constant
|
||||||
v, err := wrapValueReflect(parentMap, parentMapKey, value)
|
var nilType = reflect.TypeOf(&struct{}{})
|
||||||
|
|
||||||
|
// reuse replaces the value of the valueReflect. If parent in the data tree is a map, parentMap and parentMapKey
|
||||||
|
// must be provided so that the returned value may be set and deleted.
|
||||||
|
func (r *valueReflect) reuse(value reflect.Value, cacheEntry *TypeReflectCacheEntry, parentMap, parentMapKey *reflect.Value) (Value, error) {
|
||||||
|
if cacheEntry == nil {
|
||||||
|
cacheEntry = TypeReflectEntryOf(value.Type())
|
||||||
|
}
|
||||||
|
if cacheEntry.CanConvertToUnstructured() {
|
||||||
|
u, err := cacheEntry.ToUnstructured(value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if u == nil {
|
||||||
|
value = reflect.Zero(nilType)
|
||||||
|
} else {
|
||||||
|
value = reflect.ValueOf(u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.Value = dereference(value)
|
||||||
|
r.ParentMap = parentMap
|
||||||
|
r.ParentMapKey = parentMapKey
|
||||||
|
r.kind = kind(r.Value)
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustReuse replaces the value of the valueReflect and panics if there is an error. If parent in the data tree is a
|
||||||
|
// map, parentMap and parentMapKey must be provided so that the returned value may be set and deleted.
|
||||||
|
func (r *valueReflect) mustReuse(value reflect.Value, cacheEntry *TypeReflectCacheEntry, parentMap, parentMapKey *reflect.Value) Value {
|
||||||
|
v, err := r.reuse(value, cacheEntry, parentMap, parentMapKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -90,53 +105,91 @@ type valueReflect struct {
|
|||||||
ParentMap *reflect.Value
|
ParentMap *reflect.Value
|
||||||
ParentMapKey *reflect.Value
|
ParentMapKey *reflect.Value
|
||||||
Value reflect.Value
|
Value reflect.Value
|
||||||
|
kind reflectType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r valueReflect) IsMap() bool {
|
func (r valueReflect) IsMap() bool {
|
||||||
return r.isKind(reflect.Map, reflect.Struct)
|
return r.kind == mapType || r.kind == structMapType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r valueReflect) IsList() bool {
|
func (r valueReflect) IsList() bool {
|
||||||
typ := r.Value.Type()
|
return r.kind == listType
|
||||||
return typ.Kind() == reflect.Slice && !(typ.Elem().Kind() == reflect.Uint8)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r valueReflect) IsBool() bool {
|
func (r valueReflect) IsBool() bool {
|
||||||
return r.isKind(reflect.Bool)
|
return r.kind == boolType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r valueReflect) IsInt() bool {
|
func (r valueReflect) IsInt() bool {
|
||||||
// Uint64 deliberately excluded, see valueUnstructured.Int.
|
return r.kind == intType || r.kind == uintType
|
||||||
return r.isKind(reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Uint, reflect.Uint32, reflect.Uint16, reflect.Uint8)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r valueReflect) IsFloat() bool {
|
func (r valueReflect) IsFloat() bool {
|
||||||
return r.isKind(reflect.Float64, reflect.Float32)
|
return r.kind == floatType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r valueReflect) IsString() bool {
|
func (r valueReflect) IsString() bool {
|
||||||
kind := r.Value.Kind()
|
return r.kind == stringType || r.kind == byteStringType
|
||||||
if kind == reflect.String {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if kind == reflect.Slice && r.Value.Type().Elem().Kind() == reflect.Uint8 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r valueReflect) IsNull() bool {
|
func (r valueReflect) IsNull() bool {
|
||||||
return safeIsNil(r.Value)
|
return r.kind == nullType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r valueReflect) isKind(kinds ...reflect.Kind) bool {
|
type reflectType = int
|
||||||
kind := r.Value.Kind()
|
|
||||||
for _, k := range kinds {
|
const (
|
||||||
if kind == k {
|
mapType = iota
|
||||||
return true
|
structMapType
|
||||||
|
listType
|
||||||
|
intType
|
||||||
|
uintType
|
||||||
|
floatType
|
||||||
|
stringType
|
||||||
|
byteStringType
|
||||||
|
boolType
|
||||||
|
nullType
|
||||||
|
)
|
||||||
|
|
||||||
|
func kind(v reflect.Value) reflectType {
|
||||||
|
typ := v.Type()
|
||||||
|
rk := typ.Kind()
|
||||||
|
switch rk {
|
||||||
|
case reflect.Map:
|
||||||
|
if v.IsNil() {
|
||||||
|
return nullType
|
||||||
}
|
}
|
||||||
|
return mapType
|
||||||
|
case reflect.Struct:
|
||||||
|
return structMapType
|
||||||
|
case reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8:
|
||||||
|
return intType
|
||||||
|
case reflect.Uint, reflect.Uint32, reflect.Uint16, reflect.Uint8:
|
||||||
|
// Uint64 deliberately excluded, see valueUnstructured.Int.
|
||||||
|
return uintType
|
||||||
|
case reflect.Float64, reflect.Float32:
|
||||||
|
return floatType
|
||||||
|
case reflect.String:
|
||||||
|
return stringType
|
||||||
|
case reflect.Bool:
|
||||||
|
return boolType
|
||||||
|
case reflect.Slice:
|
||||||
|
if v.IsNil() {
|
||||||
|
return nullType
|
||||||
|
}
|
||||||
|
elemKind := typ.Elem().Kind()
|
||||||
|
if elemKind == reflect.Uint8 {
|
||||||
|
return byteStringType
|
||||||
|
}
|
||||||
|
return listType
|
||||||
|
case reflect.Chan, reflect.Func, reflect.Ptr, reflect.UnsafePointer, reflect.Interface:
|
||||||
|
if v.IsNil() {
|
||||||
|
return nullType
|
||||||
|
}
|
||||||
|
panic(fmt.Sprintf("unsupported type: %v", v.Type()))
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unsupported type: %v", v.Type()))
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO find a cleaner way to avoid panics from reflect.IsNil()
|
// TODO find a cleaner way to avoid panics from reflect.IsNil()
|
||||||
@ -150,24 +203,33 @@ func safeIsNil(v reflect.Value) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r valueReflect) AsMap() Map {
|
func (r valueReflect) AsMap() Map {
|
||||||
val := r.Value
|
return r.AsMapUsing(HeapAllocator)
|
||||||
switch val.Kind() {
|
}
|
||||||
case reflect.Struct:
|
|
||||||
return structReflect{r}
|
func (r valueReflect) AsMapUsing(a Allocator) Map {
|
||||||
case reflect.Map:
|
switch r.kind {
|
||||||
return mapReflect{r}
|
case structMapType:
|
||||||
|
v := a.allocStructReflect()
|
||||||
|
v.valueReflect = r
|
||||||
|
return v
|
||||||
|
case mapType:
|
||||||
|
v := a.allocMapReflect()
|
||||||
|
v.valueReflect = r
|
||||||
|
return v
|
||||||
default:
|
default:
|
||||||
panic("value is not a map or struct")
|
panic("value is not a map or struct")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *valueReflect) Recycle() {
|
func (r valueReflect) AsList() List {
|
||||||
reflectPool.Put(r)
|
return r.AsListUsing(HeapAllocator)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r valueReflect) AsList() List {
|
func (r valueReflect) AsListUsing(a Allocator) List {
|
||||||
if r.IsList() {
|
if r.IsList() {
|
||||||
return listReflect{r.Value}
|
v := a.allocListReflect()
|
||||||
|
v.Value = r.Value
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
panic("value is not a list")
|
panic("value is not a list")
|
||||||
}
|
}
|
||||||
@ -180,10 +242,10 @@ func (r valueReflect) AsBool() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r valueReflect) AsInt() int64 {
|
func (r valueReflect) AsInt() int64 {
|
||||||
if r.isKind(reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8) {
|
if r.kind == intType {
|
||||||
return r.Value.Int()
|
return r.Value.Int()
|
||||||
}
|
}
|
||||||
if r.isKind(reflect.Uint, reflect.Uint32, reflect.Uint16, reflect.Uint8) {
|
if r.kind == uintType {
|
||||||
return int64(r.Value.Uint())
|
return int64(r.Value.Uint())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,11 +260,10 @@ func (r valueReflect) AsFloat() float64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r valueReflect) AsString() string {
|
func (r valueReflect) AsString() string {
|
||||||
kind := r.Value.Kind()
|
switch r.kind {
|
||||||
if kind == reflect.String {
|
case stringType:
|
||||||
return r.Value.String()
|
return r.Value.String()
|
||||||
}
|
case byteStringType:
|
||||||
if kind == reflect.Slice && r.Value.Type().Elem().Kind() == reflect.Uint8 {
|
|
||||||
return base64.StdEncoding.EncodeToString(r.Value.Bytes())
|
return base64.StdEncoding.EncodeToString(r.Value.Bytes())
|
||||||
}
|
}
|
||||||
panic("value is not a string")
|
panic("value is not a string")
|
||||||
@ -216,9 +277,9 @@ func (r valueReflect) Unstructured() interface{} {
|
|||||||
case val.Kind() == reflect.Struct:
|
case val.Kind() == reflect.Struct:
|
||||||
return structReflect{r}.Unstructured()
|
return structReflect{r}.Unstructured()
|
||||||
case val.Kind() == reflect.Map:
|
case val.Kind() == reflect.Map:
|
||||||
return mapReflect{r}.Unstructured()
|
return mapReflect{valueReflect: r}.Unstructured()
|
||||||
case r.IsList():
|
case r.IsList():
|
||||||
return listReflect{Value: r.Value}.Unstructured()
|
return listReflect{r.Value}.Unstructured()
|
||||||
case r.IsString():
|
case r.IsString():
|
||||||
return r.AsString()
|
return r.AsString()
|
||||||
case r.IsInt():
|
case r.IsInt():
|
||||||
@ -231,89 +292,3 @@ func (r valueReflect) Unstructured() interface{} {
|
|||||||
panic(fmt.Sprintf("value of type %s is not a supported by value reflector", val.Type()))
|
panic(fmt.Sprintf("value of type %s is not a supported by value reflector", val.Type()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The below getMarshaler and toUnstructured functions are based on
|
|
||||||
// https://github.com/kubernetes/kubernetes/blob/40df9f82d0572a123f5ad13f48312978a2ff5877/staging/src/k8s.io/apimachinery/pkg/runtime/converter.go#L509
|
|
||||||
// and should somehow be consolidated with it
|
|
||||||
|
|
||||||
var marshalerType = reflect.TypeOf(new(json.Marshaler)).Elem()
|
|
||||||
|
|
||||||
func getMarshaler(v reflect.Value) (json.Marshaler, bool) {
|
|
||||||
// Check value receivers if v is not a pointer and pointer receivers if v is a pointer
|
|
||||||
if v.Type().Implements(marshalerType) {
|
|
||||||
return v.Interface().(json.Marshaler), true
|
|
||||||
}
|
|
||||||
// Check pointer receivers if v is not a pointer
|
|
||||||
if v.Kind() != reflect.Ptr && v.CanAddr() {
|
|
||||||
v = v.Addr()
|
|
||||||
if v.Type().Implements(marshalerType) {
|
|
||||||
return v.Interface().(json.Marshaler), true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
nullBytes = []byte("null")
|
|
||||||
trueBytes = []byte("true")
|
|
||||||
falseBytes = []byte("false")
|
|
||||||
)
|
|
||||||
|
|
||||||
func toUnstructured(marshaler json.Marshaler, sv reflect.Value) (Value, error) {
|
|
||||||
data, err := marshaler.MarshalJSON()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
switch {
|
|
||||||
case len(data) == 0:
|
|
||||||
return nil, fmt.Errorf("error decoding from json: empty value")
|
|
||||||
|
|
||||||
case bytes.Equal(data, nullBytes):
|
|
||||||
// We're done - we don't need to store anything.
|
|
||||||
return NewValueInterface(nil), nil
|
|
||||||
|
|
||||||
case bytes.Equal(data, trueBytes):
|
|
||||||
return NewValueInterface(true), nil
|
|
||||||
|
|
||||||
case bytes.Equal(data, falseBytes):
|
|
||||||
return NewValueInterface(false), nil
|
|
||||||
|
|
||||||
case data[0] == '"':
|
|
||||||
var result string
|
|
||||||
err := json.Unmarshal(data, &result)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error decoding string from json: %v", err)
|
|
||||||
}
|
|
||||||
return NewValueInterface(result), nil
|
|
||||||
|
|
||||||
case data[0] == '{':
|
|
||||||
result := make(map[string]interface{})
|
|
||||||
err := json.Unmarshal(data, &result)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error decoding object from json: %v", err)
|
|
||||||
}
|
|
||||||
return NewValueInterface(result), nil
|
|
||||||
|
|
||||||
case data[0] == '[':
|
|
||||||
result := make([]interface{}, 0)
|
|
||||||
err := json.Unmarshal(data, &result)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error decoding array from json: %v", err)
|
|
||||||
}
|
|
||||||
return NewValueInterface(result), nil
|
|
||||||
|
|
||||||
default:
|
|
||||||
var (
|
|
||||||
resultInt int64
|
|
||||||
resultFloat float64
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
if err = json.Unmarshal(data, &resultInt); err == nil {
|
|
||||||
return NewValueInterface(resultInt), nil
|
|
||||||
}
|
|
||||||
if err = json.Unmarshal(data, &resultFloat); err == nil {
|
|
||||||
return NewValueInterface(resultFloat), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("error decoding number from json: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
29
vendor/sigs.k8s.io/structured-merge-diff/v3/value/valueunstructured.go
generated
vendored
29
vendor/sigs.k8s.io/structured-merge-diff/v3/value/valueunstructured.go
generated
vendored
@ -18,29 +18,26 @@ package value
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var viPool = sync.Pool{
|
|
||||||
New: func() interface{} {
|
|
||||||
return &valueUnstructured{}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewValueInterface creates a Value backed by an "interface{}" type,
|
// NewValueInterface creates a Value backed by an "interface{}" type,
|
||||||
// typically an unstructured object in Kubernetes world.
|
// typically an unstructured object in Kubernetes world.
|
||||||
// interface{} must be one of: map[string]interface{}, map[interface{}]interface{}, []interface{}, int types, float types,
|
// interface{} must be one of: map[string]interface{}, map[interface{}]interface{}, []interface{}, int types, float types,
|
||||||
// string or boolean. Nested interface{} must also be one of these types.
|
// string or boolean. Nested interface{} must also be one of these types.
|
||||||
func NewValueInterface(v interface{}) Value {
|
func NewValueInterface(v interface{}) Value {
|
||||||
vi := viPool.Get().(*valueUnstructured)
|
return Value(HeapAllocator.allocValueUnstructured().reuse(v))
|
||||||
vi.Value = v
|
|
||||||
return Value(vi)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type valueUnstructured struct {
|
type valueUnstructured struct {
|
||||||
Value interface{}
|
Value interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reuse replaces the value of the valueUnstructured.
|
||||||
|
func (vi *valueUnstructured) reuse(value interface{}) Value {
|
||||||
|
vi.Value = value
|
||||||
|
return vi
|
||||||
|
}
|
||||||
|
|
||||||
func (v valueUnstructured) IsMap() bool {
|
func (v valueUnstructured) IsMap() bool {
|
||||||
if _, ok := v.Value.(map[string]interface{}); ok {
|
if _, ok := v.Value.(map[string]interface{}); ok {
|
||||||
return true
|
return true
|
||||||
@ -52,6 +49,10 @@ func (v valueUnstructured) IsMap() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v valueUnstructured) AsMap() Map {
|
func (v valueUnstructured) AsMap() Map {
|
||||||
|
return v.AsMapUsing(HeapAllocator)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v valueUnstructured) AsMapUsing(_ Allocator) Map {
|
||||||
if v.Value == nil {
|
if v.Value == nil {
|
||||||
panic("invalid nil")
|
panic("invalid nil")
|
||||||
}
|
}
|
||||||
@ -73,6 +74,10 @@ func (v valueUnstructured) IsList() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v valueUnstructured) AsList() List {
|
func (v valueUnstructured) AsList() List {
|
||||||
|
return v.AsListUsing(HeapAllocator)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v valueUnstructured) AsListUsing(_ Allocator) List {
|
||||||
return listUnstructured(v.Value.([]interface{}))
|
return listUnstructured(v.Value.([]interface{}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,10 +173,6 @@ func (v valueUnstructured) IsNull() bool {
|
|||||||
return v.Value == nil
|
return v.Value == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *valueUnstructured) Recycle() {
|
|
||||||
viPool.Put(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v valueUnstructured) Unstructured() interface{} {
|
func (v valueUnstructured) Unstructured() interface{} {
|
||||||
return v.Value
|
return v.Value
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user