mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-26 05:03:09 +00:00
Update smd repo to handle CRDs
This commit is contained in:
parent
7e4cc38401
commit
1751fc013f
6
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/path.go
generated
vendored
6
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/path.go
generated
vendored
@ -35,6 +35,12 @@ func (fp Path) String() string {
|
|||||||
return strings.Join(strs, "")
|
return strings.Join(strs, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fp Path) Copy() Path {
|
||||||
|
new := make(Path, len(fp))
|
||||||
|
copy(new, fp)
|
||||||
|
return new
|
||||||
|
}
|
||||||
|
|
||||||
// MakePath constructs a Path. The parts may be PathElements, ints, strings.
|
// MakePath constructs a Path. The parts may be PathElements, ints, strings.
|
||||||
func MakePath(parts ...interface{}) (Path, error) {
|
func MakePath(parts ...interface{}) (Path, error) {
|
||||||
var fp Path
|
var fp Path
|
||||||
|
10
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/set.go
generated
vendored
10
vendor/sigs.k8s.io/structured-merge-diff/fieldpath/set.go
generated
vendored
@ -154,6 +154,16 @@ func (s *Set) iteratePrefix(prefix Path, f func(Path)) {
|
|||||||
s.Children.iteratePrefix(prefix, f)
|
s.Children.iteratePrefix(prefix, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithPrefix returns the subset of paths which begin with the given prefix,
|
||||||
|
// with the prefix not included.
|
||||||
|
func (s *Set) WithPrefix(pe PathElement) *Set {
|
||||||
|
subset, ok := s.Children.Get(pe)
|
||||||
|
if !ok {
|
||||||
|
return NewSet()
|
||||||
|
}
|
||||||
|
return subset
|
||||||
|
}
|
||||||
|
|
||||||
// setNode is a pair of PathElement / Set, for the purpose of expressing
|
// setNode is a pair of PathElement / Set, for the purpose of expressing
|
||||||
// nested set membership.
|
// nested set membership.
|
||||||
type setNode struct {
|
type setNode struct {
|
||||||
|
48
vendor/sigs.k8s.io/structured-merge-diff/merge/update.go
generated
vendored
48
vendor/sigs.k8s.io/structured-merge-diff/merge/update.go
generated
vendored
@ -85,6 +85,15 @@ func (s *Updater) update(oldObject, newObject typed.TypedValue, version fieldpat
|
|||||||
|
|
||||||
for manager, conflictSet := range conflicts {
|
for manager, conflictSet := range conflicts {
|
||||||
managers[manager].Set = managers[manager].Set.Difference(conflictSet.Set)
|
managers[manager].Set = managers[manager].Set.Difference(conflictSet.Set)
|
||||||
|
if managers[manager].Set.Empty() {
|
||||||
|
delete(managers, manager)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := managers[workflow]; !ok {
|
||||||
|
managers[workflow] = &fieldpath.VersionedSet{
|
||||||
|
Set: fieldpath.NewSet(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return managers, nil
|
return managers, nil
|
||||||
@ -105,13 +114,11 @@ func (s *Updater) Update(liveObject, newObject typed.TypedValue, version fieldpa
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fieldpath.ManagedFields{}, fmt.Errorf("failed to compare live and new objects: %v", err)
|
return fieldpath.ManagedFields{}, fmt.Errorf("failed to compare live and new objects: %v", err)
|
||||||
}
|
}
|
||||||
if _, ok := managers[manager]; !ok {
|
|
||||||
managers[manager] = &fieldpath.VersionedSet{
|
|
||||||
Set: fieldpath.NewSet(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
managers[manager].Set = managers[manager].Set.Union(compare.Modified).Union(compare.Added).Difference(compare.Removed)
|
managers[manager].Set = managers[manager].Set.Union(compare.Modified).Union(compare.Added).Difference(compare.Removed)
|
||||||
managers[manager].APIVersion = version
|
managers[manager].APIVersion = version
|
||||||
|
if managers[manager].Set.Empty() {
|
||||||
|
delete(managers, manager)
|
||||||
|
}
|
||||||
return managers, nil
|
return managers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,22 +128,41 @@ func (s *Updater) Update(liveObject, newObject typed.TypedValue, version fieldpa
|
|||||||
func (s *Updater) Apply(liveObject, configObject typed.TypedValue, version fieldpath.APIVersion, managers fieldpath.ManagedFields, manager string, force bool) (typed.TypedValue, fieldpath.ManagedFields, error) {
|
func (s *Updater) Apply(liveObject, configObject typed.TypedValue, version fieldpath.APIVersion, managers fieldpath.ManagedFields, manager string, force bool) (typed.TypedValue, fieldpath.ManagedFields, error) {
|
||||||
newObject, err := liveObject.Merge(configObject)
|
newObject, err := liveObject.Merge(configObject)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return typed.TypedValue{}, fieldpath.ManagedFields{}, fmt.Errorf("failed to merge config: %v", err)
|
return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to merge config: %v", err)
|
||||||
}
|
}
|
||||||
managers, err = s.update(liveObject, newObject, version, managers, manager, force)
|
managers, err = s.update(liveObject, newObject, version, managers, manager, force)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return typed.TypedValue{}, fieldpath.ManagedFields{}, err
|
return nil, fieldpath.ManagedFields{}, err
|
||||||
|
}
|
||||||
|
newObject, err = s.removeDisownedItems(newObject, configObject, managers[manager])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to remove fields: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove unconflicting removed fields
|
|
||||||
|
|
||||||
set, err := configObject.ToFieldSet()
|
set, err := configObject.ToFieldSet()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return typed.TypedValue{}, fieldpath.ManagedFields{}, fmt.Errorf("failed to get field set: %v", err)
|
return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to get field set: %v", err)
|
||||||
}
|
}
|
||||||
managers[manager] = &fieldpath.VersionedSet{
|
managers[manager] = &fieldpath.VersionedSet{
|
||||||
Set: set,
|
Set: set,
|
||||||
APIVersion: version,
|
APIVersion: version,
|
||||||
}
|
}
|
||||||
|
if managers[manager].Set.Empty() {
|
||||||
|
delete(managers, manager)
|
||||||
|
}
|
||||||
return newObject, managers, nil
|
return newObject, managers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Updater) removeDisownedItems(merged, applied typed.TypedValue, lastSet *fieldpath.VersionedSet) (typed.TypedValue, error) {
|
||||||
|
if lastSet.Set.Empty() {
|
||||||
|
return merged, nil
|
||||||
|
}
|
||||||
|
convertedApplied, err := s.Converter.Convert(applied, lastSet.APIVersion)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to convert applied config to last applied version: %v", err)
|
||||||
|
}
|
||||||
|
appliedSet, err := convertedApplied.ToFieldSet()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create field set from applied config in last applied version: %v", err)
|
||||||
|
}
|
||||||
|
return merged.RemoveItems(lastSet.Set.Difference(appliedSet)), nil
|
||||||
|
}
|
||||||
|
2
vendor/sigs.k8s.io/structured-merge-diff/schema/BUILD
generated
vendored
2
vendor/sigs.k8s.io/structured-merge-diff/schema/BUILD
generated
vendored
@ -5,11 +5,13 @@ go_library(
|
|||||||
srcs = [
|
srcs = [
|
||||||
"doc.go",
|
"doc.go",
|
||||||
"elements.go",
|
"elements.go",
|
||||||
|
"fromvalue.go",
|
||||||
"schemaschema.go",
|
"schemaschema.go",
|
||||||
],
|
],
|
||||||
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/structured-merge-diff/schema",
|
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/structured-merge-diff/schema",
|
||||||
importpath = "sigs.k8s.io/structured-merge-diff/schema",
|
importpath = "sigs.k8s.io/structured-merge-diff/schema",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
|
deps = ["//vendor/sigs.k8s.io/structured-merge-diff/value:go_default_library"],
|
||||||
)
|
)
|
||||||
|
|
||||||
filegroup(
|
filegroup(
|
||||||
|
2
vendor/sigs.k8s.io/structured-merge-diff/schema/elements.go
generated
vendored
2
vendor/sigs.k8s.io/structured-merge-diff/schema/elements.go
generated
vendored
@ -207,7 +207,7 @@ func (s Schema) FindNamedType(name string) (TypeDef, bool) {
|
|||||||
//
|
//
|
||||||
// This allows callers to not care about the difference between a (possibly
|
// This allows callers to not care about the difference between a (possibly
|
||||||
// inlined) reference and a definition.
|
// inlined) reference and a definition.
|
||||||
func (s Schema) Resolve(tr TypeRef) (Atom, bool) {
|
func (s *Schema) Resolve(tr TypeRef) (Atom, bool) {
|
||||||
if tr.NamedType != nil {
|
if tr.NamedType != nil {
|
||||||
t, ok := s.FindNamedType(*tr.NamedType)
|
t, ok := s.FindNamedType(*tr.NamedType)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
57
vendor/sigs.k8s.io/structured-merge-diff/schema/fromvalue.go
generated
vendored
Normal file
57
vendor/sigs.k8s.io/structured-merge-diff/schema/fromvalue.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package schema
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sigs.k8s.io/structured-merge-diff/value"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TypeRefFromValue creates an inlined type from a value v
|
||||||
|
func TypeRefFromValue(v value.Value) TypeRef {
|
||||||
|
atom := atomFor(v)
|
||||||
|
return TypeRef{
|
||||||
|
Inlined: atom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func atomFor(v value.Value) Atom {
|
||||||
|
switch {
|
||||||
|
// Untyped cases (handled at the bottom of this function)
|
||||||
|
case v.Null:
|
||||||
|
case v.ListValue != nil:
|
||||||
|
case v.FloatValue != nil:
|
||||||
|
case v.IntValue != nil:
|
||||||
|
case v.StringValue != nil:
|
||||||
|
case v.BooleanValue != nil:
|
||||||
|
// Recursive case
|
||||||
|
case v.MapValue != nil:
|
||||||
|
s := Struct{}
|
||||||
|
for i := range v.MapValue.Items {
|
||||||
|
child := v.MapValue.Items[i]
|
||||||
|
field := StructField{
|
||||||
|
Name: child.Name,
|
||||||
|
Type: TypeRef{
|
||||||
|
Inlined: atomFor(child.Value),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
s.Fields = append(s.Fields, field)
|
||||||
|
}
|
||||||
|
return Atom{Struct: &s}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Atom{Untyped: &Untyped{}}
|
||||||
|
}
|
2
vendor/sigs.k8s.io/structured-merge-diff/typed/BUILD
generated
vendored
2
vendor/sigs.k8s.io/structured-merge-diff/typed/BUILD
generated
vendored
@ -3,10 +3,12 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
"deduced.go",
|
||||||
"doc.go",
|
"doc.go",
|
||||||
"helpers.go",
|
"helpers.go",
|
||||||
"merge.go",
|
"merge.go",
|
||||||
"parser.go",
|
"parser.go",
|
||||||
|
"remove.go",
|
||||||
"typed.go",
|
"typed.go",
|
||||||
"validate.go",
|
"validate.go",
|
||||||
],
|
],
|
||||||
|
178
vendor/sigs.k8s.io/structured-merge-diff/typed/deduced.go
generated
vendored
Normal file
178
vendor/sigs.k8s.io/structured-merge-diff/typed/deduced.go
generated
vendored
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 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 typed
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"sigs.k8s.io/structured-merge-diff/fieldpath"
|
||||||
|
"sigs.k8s.io/structured-merge-diff/value"
|
||||||
|
)
|
||||||
|
|
||||||
|
// deducedTypedValue holds a value and guesses what it is and what to
|
||||||
|
// do with it.
|
||||||
|
type deducedTypedValue struct {
|
||||||
|
value value.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsTypedDeduced is going to generate it's own type definition based on
|
||||||
|
// the content of the object. This is useful for CRDs that don't have a
|
||||||
|
// validation field.
|
||||||
|
func AsTypedDeduced(v value.Value) TypedValue {
|
||||||
|
return deducedTypedValue{value: v}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dv deducedTypedValue) AsValue() *value.Value {
|
||||||
|
return &dv.value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (deducedTypedValue) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dv deducedTypedValue) ToFieldSet() (*fieldpath.Set, error) {
|
||||||
|
set := fieldpath.NewSet()
|
||||||
|
fieldsetDeduced(dv.value, fieldpath.Path{}, set)
|
||||||
|
return set, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func fieldsetDeduced(v value.Value, path fieldpath.Path, set *fieldpath.Set) {
|
||||||
|
if v.MapValue == nil {
|
||||||
|
set.Insert(path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have a map.
|
||||||
|
// copy the existing path, append each item, and recursively call.
|
||||||
|
for i := range v.MapValue.Items {
|
||||||
|
child := v.MapValue.Items[i]
|
||||||
|
np := path.Copy()
|
||||||
|
np = append(np, fieldpath.PathElement{FieldName: &child.Name})
|
||||||
|
fieldsetDeduced(child.Value, np, set)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dv deducedTypedValue) Merge(pso TypedValue) (TypedValue, error) {
|
||||||
|
tpso, ok := pso.(deducedTypedValue)
|
||||||
|
if !ok {
|
||||||
|
return nil, errorFormatter{}.
|
||||||
|
errorf("can't merge deducedTypedValue with %T", tpso)
|
||||||
|
}
|
||||||
|
return AsTypedDeduced(mergeDeduced(dv.value, tpso.value)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeDeduced(lhs, rhs value.Value) value.Value {
|
||||||
|
// If both sides are maps, merge them, otherwise return right
|
||||||
|
// side.
|
||||||
|
if rhs.MapValue == nil || lhs.MapValue == nil {
|
||||||
|
return rhs
|
||||||
|
}
|
||||||
|
|
||||||
|
v := value.Value{MapValue: &value.Map{}}
|
||||||
|
for i := range lhs.MapValue.Items {
|
||||||
|
child := lhs.MapValue.Items[i]
|
||||||
|
v.MapValue.Set(child.Name, child.Value)
|
||||||
|
}
|
||||||
|
for i := range rhs.MapValue.Items {
|
||||||
|
child := rhs.MapValue.Items[i]
|
||||||
|
if sub, ok := v.MapValue.Get(child.Name); ok {
|
||||||
|
new := mergeDeduced(sub.Value, child.Value)
|
||||||
|
v.MapValue.Set(child.Name, new)
|
||||||
|
} else {
|
||||||
|
v.MapValue.Set(child.Name, child.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dv deducedTypedValue) Compare(rhs TypedValue) (c *Comparison, err error) {
|
||||||
|
trhs, ok := rhs.(deducedTypedValue)
|
||||||
|
if !ok {
|
||||||
|
return nil, errorFormatter{}.
|
||||||
|
errorf("can't merge deducedTypedValue with %T", rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
c = &Comparison{
|
||||||
|
Removed: fieldpath.NewSet(),
|
||||||
|
Modified: fieldpath.NewSet(),
|
||||||
|
Added: fieldpath.NewSet(),
|
||||||
|
}
|
||||||
|
|
||||||
|
added(dv.value, trhs.value, fieldpath.Path{}, c.Added)
|
||||||
|
added(trhs.value, dv.value, fieldpath.Path{}, c.Removed)
|
||||||
|
modified(dv.value, trhs.value, fieldpath.Path{}, c.Modified)
|
||||||
|
|
||||||
|
merge, err := dv.Merge(rhs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.Merged = merge
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func added(lhs, rhs value.Value, path fieldpath.Path, set *fieldpath.Set) {
|
||||||
|
if lhs.MapValue == nil && rhs.MapValue == nil {
|
||||||
|
// Both non-maps, nothing added, do nothing.
|
||||||
|
} else if lhs.MapValue == nil && rhs.MapValue != nil {
|
||||||
|
// From leaf to map, add leaf fields of map.
|
||||||
|
fieldsetDeduced(rhs, path, set)
|
||||||
|
} else if lhs.MapValue != nil && rhs.MapValue == nil {
|
||||||
|
// Went from map to field, add field.
|
||||||
|
set.Insert(path)
|
||||||
|
} else {
|
||||||
|
// Both are maps.
|
||||||
|
for i := range rhs.MapValue.Items {
|
||||||
|
child := rhs.MapValue.Items[i]
|
||||||
|
np := path.Copy()
|
||||||
|
np = append(np, fieldpath.PathElement{FieldName: &child.Name})
|
||||||
|
|
||||||
|
if v, ok := lhs.MapValue.Get(child.Name); ok {
|
||||||
|
added(v.Value, child.Value, np, set)
|
||||||
|
} else {
|
||||||
|
fieldsetDeduced(child.Value, np, set)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func modified(lhs, rhs value.Value, path fieldpath.Path, set *fieldpath.Set) {
|
||||||
|
if lhs.MapValue == nil && rhs.MapValue == nil {
|
||||||
|
if !reflect.DeepEqual(lhs, rhs) {
|
||||||
|
set.Insert(path)
|
||||||
|
}
|
||||||
|
} else if lhs.MapValue != nil && rhs.MapValue != nil {
|
||||||
|
// Both are maps.
|
||||||
|
for i := range rhs.MapValue.Items {
|
||||||
|
child := rhs.MapValue.Items[i]
|
||||||
|
|
||||||
|
v, ok := lhs.MapValue.Get(child.Name)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
np := path.Copy()
|
||||||
|
np = append(np, fieldpath.PathElement{FieldName: &child.Name})
|
||||||
|
modified(v.Value, child.Value, np, set)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveItems does nothing because all lists in a deducedTypedValue are considered atomic,
|
||||||
|
// and there are no maps because it is indistinguishable from a struct.
|
||||||
|
func (dv deducedTypedValue) RemoveItems(_ *fieldpath.Set) TypedValue {
|
||||||
|
return dv
|
||||||
|
}
|
3
vendor/sigs.k8s.io/structured-merge-diff/typed/helpers.go
generated
vendored
3
vendor/sigs.k8s.io/structured-merge-diff/typed/helpers.go
generated
vendored
@ -129,6 +129,9 @@ func (ef errorFormatter) validateScalar(t schema.Scalar, v *value.Value, prefix
|
|||||||
if v == nil {
|
if v == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if v.Null {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
switch t {
|
switch t {
|
||||||
case schema.Numeric:
|
case schema.Numeric:
|
||||||
if v.FloatValue == nil && v.IntValue == nil {
|
if v.FloatValue == nil && v.IntValue == nil {
|
||||||
|
61
vendor/sigs.k8s.io/structured-merge-diff/typed/parser.go
generated
vendored
61
vendor/sigs.k8s.io/structured-merge-diff/typed/parser.go
generated
vendored
@ -68,47 +68,80 @@ func (p *Parser) TypeNames() (names []string) {
|
|||||||
|
|
||||||
// Type returns a helper which can produce objects of the given type. Any
|
// Type returns a helper which can produce objects of the given type. Any
|
||||||
// errors are deferred until a further function is called.
|
// errors are deferred until a further function is called.
|
||||||
func (p *Parser) Type(name string) *ParseableType {
|
func (p *Parser) Type(name string) ParseableType {
|
||||||
return &ParseableType{
|
return &parseableType{
|
||||||
parser: p,
|
parser: p,
|
||||||
typename: name,
|
typename: name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseableType allows for easy production of typed objects.
|
// ParseableType allows for easy production of typed objects.
|
||||||
type ParseableType struct {
|
type ParseableType interface {
|
||||||
|
IsValid() bool
|
||||||
|
FromYAML(YAMLObject) (TypedValue, error)
|
||||||
|
FromUnstructured(interface{}) (TypedValue, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type parseableType struct {
|
||||||
parser *Parser
|
parser *Parser
|
||||||
typename string
|
typename string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ ParseableType = &parseableType{}
|
||||||
|
|
||||||
// IsValid return true if p's schema and typename are valid.
|
// IsValid return true if p's schema and typename are valid.
|
||||||
func (p *ParseableType) IsValid() bool {
|
func (p *parseableType) IsValid() bool {
|
||||||
_, ok := p.parser.Schema.Resolve(schema.TypeRef{NamedType: &p.typename})
|
_, ok := p.parser.Schema.Resolve(schema.TypeRef{NamedType: &p.typename})
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new empty object with the current schema and the
|
|
||||||
// type "typename".
|
|
||||||
func (p *ParseableType) New() (TypedValue, error) {
|
|
||||||
return p.FromYAML(YAMLObject("{}"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromYAML parses a yaml string into an object with the current schema
|
// FromYAML parses a yaml string into an object with the current schema
|
||||||
// and the type "typename" or an error if validation fails.
|
// and the type "typename" or an error if validation fails.
|
||||||
func (p *ParseableType) FromYAML(object YAMLObject) (TypedValue, error) {
|
func (p *parseableType) FromYAML(object YAMLObject) (TypedValue, error) {
|
||||||
v, err := value.FromYAML([]byte(object))
|
v, err := value.FromYAML([]byte(object))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return TypedValue{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return AsTyped(v, &p.parser.Schema, p.typename)
|
return AsTyped(v, &p.parser.Schema, p.typename)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromUnstructured converts a go interface to a TypedValue. It will return an
|
// FromUnstructured converts a go interface to a TypedValue. It will return an
|
||||||
// error if the resulting object fails schema validation.
|
// error if the resulting object fails schema validation.
|
||||||
func (p *ParseableType) FromUnstructured(in interface{}) (TypedValue, error) {
|
func (p *parseableType) FromUnstructured(in interface{}) (TypedValue, error) {
|
||||||
v, err := value.FromUnstructured(in)
|
v, err := value.FromUnstructured(in)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return TypedValue{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return AsTyped(v, &p.parser.Schema, p.typename)
|
return AsTyped(v, &p.parser.Schema, p.typename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeducedParseableType is a ParseableType that deduces the type from
|
||||||
|
// the content of the object.
|
||||||
|
type DeducedParseableType struct{}
|
||||||
|
|
||||||
|
var _ ParseableType = DeducedParseableType{}
|
||||||
|
|
||||||
|
// IsValid always returns true for a DeducedParseableType.
|
||||||
|
func (p DeducedParseableType) IsValid() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromYAML parses a yaml string into an object and deduces the type for
|
||||||
|
// that object.
|
||||||
|
func (p DeducedParseableType) FromYAML(object YAMLObject) (TypedValue, error) {
|
||||||
|
v, err := value.FromYAML([]byte(object))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return AsTypedDeduced(v), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromUnstructured converts a go interface to a TypedValue. It will return an
|
||||||
|
// error if the input object uses un-handled types.
|
||||||
|
func (p DeducedParseableType) FromUnstructured(in interface{}) (TypedValue, error) {
|
||||||
|
v, err := value.FromUnstructured(in)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return AsTypedDeduced(v), nil
|
||||||
|
}
|
||||||
|
119
vendor/sigs.k8s.io/structured-merge-diff/typed/remove.go
generated
vendored
Normal file
119
vendor/sigs.k8s.io/structured-merge-diff/typed/remove.go
generated
vendored
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 The Kubernetes Authors.
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package typed
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sigs.k8s.io/structured-merge-diff/fieldpath"
|
||||||
|
"sigs.k8s.io/structured-merge-diff/schema"
|
||||||
|
"sigs.k8s.io/structured-merge-diff/value"
|
||||||
|
)
|
||||||
|
|
||||||
|
type removingWalker struct {
|
||||||
|
value *value.Value
|
||||||
|
schema *schema.Schema
|
||||||
|
toRemove *fieldpath.Set
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeItemsWithSchema(value *value.Value, toRemove *fieldpath.Set, schema *schema.Schema, typeRef schema.TypeRef) {
|
||||||
|
w := &removingWalker{
|
||||||
|
value: value,
|
||||||
|
schema: schema,
|
||||||
|
toRemove: toRemove,
|
||||||
|
}
|
||||||
|
resolveSchema(schema, typeRef, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
// doLeaf should be called on leaves before descending into children, if there
|
||||||
|
// will be a descent. It modifies w.inLeaf.
|
||||||
|
func (w *removingWalker) doLeaf() ValidationErrors { return nil }
|
||||||
|
|
||||||
|
func (w *removingWalker) doScalar(t schema.Scalar) ValidationErrors { return nil }
|
||||||
|
|
||||||
|
func (w *removingWalker) doStruct(t schema.Struct) ValidationErrors {
|
||||||
|
s := w.value.MapValue
|
||||||
|
|
||||||
|
// If struct is null, empty, or atomic just return
|
||||||
|
if s == nil || len(s.Items) == 0 || t.ElementRelationship == schema.Atomic {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldTypes := map[string]schema.TypeRef{}
|
||||||
|
for _, structField := range t.Fields {
|
||||||
|
fieldTypes[structField.Name] = structField.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, _ := range s.Items {
|
||||||
|
item := s.Items[i]
|
||||||
|
pe := fieldpath.PathElement{FieldName: &item.Name}
|
||||||
|
if subset := w.toRemove.WithPrefix(pe); !subset.Empty() {
|
||||||
|
removeItemsWithSchema(&s.Items[i].Value, subset, w.schema, fieldTypes[item.Name])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *removingWalker) doList(t schema.List) (errs ValidationErrors) {
|
||||||
|
l := w.value.ListValue
|
||||||
|
|
||||||
|
// If list is null, empty, or atomic just return
|
||||||
|
if l == nil || len(l.Items) == 0 || t.ElementRelationship == schema.Atomic {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
newItems := []value.Value{}
|
||||||
|
for i, _ := range l.Items {
|
||||||
|
item := l.Items[i]
|
||||||
|
// Ignore error because we have already validated this list
|
||||||
|
pe, _ := listItemToPathElement(t, i, item)
|
||||||
|
path, _ := fieldpath.MakePath(pe)
|
||||||
|
if w.toRemove.Has(path) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if subset := w.toRemove.WithPrefix(pe); !subset.Empty() {
|
||||||
|
removeItemsWithSchema(&l.Items[i], subset, w.schema, t.ElementType)
|
||||||
|
}
|
||||||
|
newItems = append(newItems, l.Items[i])
|
||||||
|
}
|
||||||
|
l.Items = newItems
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *removingWalker) doMap(t schema.Map) ValidationErrors {
|
||||||
|
m := w.value.MapValue
|
||||||
|
|
||||||
|
// If map is null, empty, or atomic just return
|
||||||
|
if m == nil || len(m.Items) == 0 || t.ElementRelationship == schema.Atomic {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
newMap := &value.Map{}
|
||||||
|
for i, _ := range m.Items {
|
||||||
|
item := m.Items[i]
|
||||||
|
pe := fieldpath.PathElement{FieldName: &item.Name}
|
||||||
|
path, _ := fieldpath.MakePath(pe)
|
||||||
|
if w.toRemove.Has(path) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if subset := w.toRemove.WithPrefix(pe); !subset.Empty() {
|
||||||
|
removeItemsWithSchema(&m.Items[i].Value, subset, w.schema, t.ElementType)
|
||||||
|
}
|
||||||
|
newMap.Set(item.Name, m.Items[i].Value)
|
||||||
|
}
|
||||||
|
w.value.MapValue = newMap
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*removingWalker) doUntyped(_ schema.Untyped) ValidationErrors { return nil }
|
||||||
|
|
||||||
|
func (*removingWalker) errorf(_ string, _ ...interface{}) ValidationErrors { return nil }
|
255
vendor/sigs.k8s.io/structured-merge-diff/typed/typed.go
generated
vendored
255
vendor/sigs.k8s.io/structured-merge-diff/typed/typed.go
generated
vendored
@ -25,44 +25,87 @@ import (
|
|||||||
"sigs.k8s.io/structured-merge-diff/value"
|
"sigs.k8s.io/structured-merge-diff/value"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TypedValue is a value of some specific type.
|
// TypedValue is a value with an associated type.
|
||||||
type TypedValue struct {
|
type TypedValue interface {
|
||||||
value value.Value
|
// AsValue removes the type from the TypedValue and only keeps the value.
|
||||||
typeRef schema.TypeRef
|
AsValue() *value.Value
|
||||||
schema *schema.Schema
|
// Validate returns an error with a list of every spec violation.
|
||||||
|
Validate() error
|
||||||
|
// ToFieldSet creates a set containing every leaf field mentioned, or
|
||||||
|
// validation errors, if any were encountered.
|
||||||
|
ToFieldSet() (*fieldpath.Set, error)
|
||||||
|
// Merge returns the result of merging tv and pso ("partially specified
|
||||||
|
// object") together. Of note:
|
||||||
|
// * No fields can be removed by this operation.
|
||||||
|
// * If both tv and pso specify a given leaf field, the result will keep pso's
|
||||||
|
// value.
|
||||||
|
// * Container typed elements will have their items ordered:
|
||||||
|
// * like tv, if pso doesn't change anything in the container
|
||||||
|
// * like pso, if pso does change something in the container.
|
||||||
|
// tv and pso must both be of the same type (their Schema and TypeRef must
|
||||||
|
// match), or an error will be returned. Validation errors will be returned if
|
||||||
|
// the objects don't conform to the schema.
|
||||||
|
Merge(pso TypedValue) (TypedValue, error)
|
||||||
|
// Compare compares the two objects. See the comments on the `Comparison`
|
||||||
|
// struct for details on the return value.
|
||||||
|
//
|
||||||
|
// tv and rhs must both be of the same type (their Schema and TypeRef must
|
||||||
|
// match), or an error will be returned. Validation errors will be returned if
|
||||||
|
// the objects don't conform to the schema.
|
||||||
|
Compare(rhs TypedValue) (c *Comparison, err error)
|
||||||
|
// RemoveItems removes each provided list or map item from the value.
|
||||||
|
RemoveItems(items *fieldpath.Set) TypedValue
|
||||||
}
|
}
|
||||||
|
|
||||||
// AsTyped accepts a value and a type and returns a TypedValue. 'v' must have
|
// AsTyped accepts a value and a type and returns a TypedValue. 'v' must have
|
||||||
// type 'typeName' in the schema. An error is returned if the v doesn't conform
|
// type 'typeName' in the schema. An error is returned if the v doesn't conform
|
||||||
// to the schema.
|
// to the schema.
|
||||||
func AsTyped(v value.Value, s *schema.Schema, typeName string) (TypedValue, error) {
|
func AsTyped(v value.Value, s *schema.Schema, typeName string) (TypedValue, error) {
|
||||||
tv := TypedValue{
|
tv := typedValue{
|
||||||
value: v,
|
value: v,
|
||||||
typeRef: schema.TypeRef{NamedType: &typeName},
|
typeRef: schema.TypeRef{NamedType: &typeName},
|
||||||
schema: s,
|
schema: s,
|
||||||
}
|
}
|
||||||
if err := tv.Validate(); err != nil {
|
if err := tv.Validate(); err != nil {
|
||||||
return TypedValue{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return tv, nil
|
return tv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AsValue removes the type from the TypedValue and only keeps the value.
|
// AsTypeUnvalidated is just like AsTyped, but doesn't validate that the type
|
||||||
func (tv TypedValue) AsValue() *value.Value {
|
// conforms to the schema, for cases where that has already been checked or
|
||||||
|
// where you're going to call a method that validates as a side-effect (like
|
||||||
|
// ToFieldSet).
|
||||||
|
func AsTypedUnvalidated(v value.Value, s *schema.Schema, typeName string) TypedValue {
|
||||||
|
tv := typedValue{
|
||||||
|
value: v,
|
||||||
|
typeRef: schema.TypeRef{NamedType: &typeName},
|
||||||
|
schema: s,
|
||||||
|
}
|
||||||
|
return tv
|
||||||
|
}
|
||||||
|
|
||||||
|
// typedValue is a value of some specific type.
|
||||||
|
type typedValue struct {
|
||||||
|
value value.Value
|
||||||
|
typeRef schema.TypeRef
|
||||||
|
schema *schema.Schema
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ TypedValue = typedValue{}
|
||||||
|
|
||||||
|
func (tv typedValue) AsValue() *value.Value {
|
||||||
return &tv.value
|
return &tv.value
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate returns an error with a list of every spec violation.
|
func (tv typedValue) Validate() error {
|
||||||
func (tv TypedValue) Validate() error {
|
|
||||||
if errs := tv.walker().validate(); len(errs) != 0 {
|
if errs := tv.walker().validate(); len(errs) != 0 {
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToFieldSet creates a set containing every leaf field mentioned in tv, or
|
func (tv typedValue) ToFieldSet() (*fieldpath.Set, error) {
|
||||||
// validation errors, if any were encountered.
|
|
||||||
func (tv TypedValue) ToFieldSet() (*fieldpath.Set, error) {
|
|
||||||
s := fieldpath.NewSet()
|
s := fieldpath.NewSet()
|
||||||
w := tv.walker()
|
w := tv.walker()
|
||||||
w.leafFieldCallback = func(p fieldpath.Path) { s.Insert(p) }
|
w.leafFieldCallback = func(p fieldpath.Path) { s.Insert(p) }
|
||||||
@ -72,19 +115,91 @@ func (tv TypedValue) ToFieldSet() (*fieldpath.Set, error) {
|
|||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge returns the result of merging tv and pso ("partially specified
|
func (tv typedValue) Merge(pso TypedValue) (TypedValue, error) {
|
||||||
// object") together. Of note:
|
tpso, ok := pso.(typedValue)
|
||||||
// * No fields can be removed by this operation.
|
if !ok {
|
||||||
// * If both tv and pso specify a given leaf field, the result will keep pso's
|
return nil, errorFormatter{}.
|
||||||
// value.
|
errorf("can't merge typedValue with %T", pso)
|
||||||
// * Container typed elements will have their items ordered:
|
}
|
||||||
// * like tv, if pso doesn't change anything in the container
|
return merge(tv, tpso, ruleKeepRHS, nil)
|
||||||
// * like pso, if pso does change something in the container.
|
}
|
||||||
// tv and pso must both be of the same type (their Schema and TypeRef must
|
|
||||||
// match), or an error will be returned. Validation errors will be returned if
|
func (tv typedValue) Compare(rhs TypedValue) (c *Comparison, err error) {
|
||||||
// the objects don't conform to the schema.
|
trhs, ok := rhs.(typedValue)
|
||||||
func (tv TypedValue) Merge(pso TypedValue) (TypedValue, error) {
|
if !ok {
|
||||||
return merge(tv, pso, ruleKeepRHS, nil)
|
return nil, errorFormatter{}.
|
||||||
|
errorf("can't compare typedValue with %T", rhs)
|
||||||
|
}
|
||||||
|
c = &Comparison{
|
||||||
|
Removed: fieldpath.NewSet(),
|
||||||
|
Modified: fieldpath.NewSet(),
|
||||||
|
Added: fieldpath.NewSet(),
|
||||||
|
}
|
||||||
|
c.Merged, err = merge(tv, trhs, func(w *mergingWalker) {
|
||||||
|
if w.lhs == nil {
|
||||||
|
c.Added.Insert(w.path)
|
||||||
|
} else if w.rhs == nil {
|
||||||
|
c.Removed.Insert(w.path)
|
||||||
|
} else if !reflect.DeepEqual(w.rhs, w.lhs) {
|
||||||
|
// TODO: reflect.DeepEqual is not sufficient for this.
|
||||||
|
// Need to implement equality check on the value type.
|
||||||
|
c.Modified.Insert(w.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
ruleKeepRHS(w)
|
||||||
|
}, func(w *mergingWalker) {
|
||||||
|
if w.lhs == nil {
|
||||||
|
c.Added.Insert(w.path)
|
||||||
|
} else if w.rhs == nil {
|
||||||
|
c.Removed.Insert(w.path)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveItems removes each provided list or map item from the value.
|
||||||
|
func (tv typedValue) RemoveItems(items *fieldpath.Set) TypedValue {
|
||||||
|
removeItemsWithSchema(&tv.value, items, tv.schema, tv.typeRef)
|
||||||
|
return tv
|
||||||
|
}
|
||||||
|
|
||||||
|
func merge(lhs, rhs typedValue, rule, postRule mergeRule) (TypedValue, error) {
|
||||||
|
if lhs.schema != rhs.schema {
|
||||||
|
return nil, errorFormatter{}.
|
||||||
|
errorf("expected objects with types from the same schema")
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(lhs.typeRef, rhs.typeRef) {
|
||||||
|
return nil, errorFormatter{}.
|
||||||
|
errorf("expected objects of the same type, but got %v and %v", lhs.typeRef, rhs.typeRef)
|
||||||
|
}
|
||||||
|
|
||||||
|
mw := mergingWalker{
|
||||||
|
lhs: &lhs.value,
|
||||||
|
rhs: &rhs.value,
|
||||||
|
schema: lhs.schema,
|
||||||
|
typeRef: lhs.typeRef,
|
||||||
|
rule: rule,
|
||||||
|
postItemHook: postRule,
|
||||||
|
}
|
||||||
|
errs := mw.merge()
|
||||||
|
if len(errs) > 0 {
|
||||||
|
return nil, errs
|
||||||
|
}
|
||||||
|
|
||||||
|
out := typedValue{
|
||||||
|
schema: lhs.schema,
|
||||||
|
typeRef: lhs.typeRef,
|
||||||
|
}
|
||||||
|
if mw.out == nil {
|
||||||
|
out.value = value.Value{Null: true}
|
||||||
|
} else {
|
||||||
|
out.value = *mw.out
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comparison is the return value of a TypedValue.Compare() operation.
|
// Comparison is the return value of a TypedValue.Compare() operation.
|
||||||
@ -125,89 +240,3 @@ func (c *Comparison) String() string {
|
|||||||
}
|
}
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare compares the two objects. See the comments on the `Comparison`
|
|
||||||
// struct for details on the return value.
|
|
||||||
//
|
|
||||||
// tv and rhs must both be of the same type (their Schema and TypeRef must
|
|
||||||
// match), or an error will be returned. Validation errors will be returned if
|
|
||||||
// the objects don't conform to the schema.
|
|
||||||
func (tv TypedValue) Compare(rhs TypedValue) (c *Comparison, err error) {
|
|
||||||
c = &Comparison{
|
|
||||||
Removed: fieldpath.NewSet(),
|
|
||||||
Modified: fieldpath.NewSet(),
|
|
||||||
Added: fieldpath.NewSet(),
|
|
||||||
}
|
|
||||||
c.Merged, err = merge(tv, rhs, func(w *mergingWalker) {
|
|
||||||
if w.lhs == nil {
|
|
||||||
c.Added.Insert(w.path)
|
|
||||||
} else if w.rhs == nil {
|
|
||||||
c.Removed.Insert(w.path)
|
|
||||||
} else if !reflect.DeepEqual(w.rhs, w.lhs) {
|
|
||||||
// TODO: reflect.DeepEqual is not sufficient for this.
|
|
||||||
// Need to implement equality check on the value type.
|
|
||||||
c.Modified.Insert(w.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
ruleKeepRHS(w)
|
|
||||||
}, func(w *mergingWalker) {
|
|
||||||
if w.lhs == nil {
|
|
||||||
c.Added.Insert(w.path)
|
|
||||||
} else if w.rhs == nil {
|
|
||||||
c.Removed.Insert(w.path)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func merge(lhs, rhs TypedValue, rule, postRule mergeRule) (TypedValue, error) {
|
|
||||||
if lhs.schema != rhs.schema {
|
|
||||||
return TypedValue{}, errorFormatter{}.
|
|
||||||
errorf("expected objects with types from the same schema")
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(lhs.typeRef, rhs.typeRef) {
|
|
||||||
return TypedValue{}, errorFormatter{}.
|
|
||||||
errorf("expected objects of the same type, but got %v and %v", lhs.typeRef, rhs.typeRef)
|
|
||||||
}
|
|
||||||
|
|
||||||
mw := mergingWalker{
|
|
||||||
lhs: &lhs.value,
|
|
||||||
rhs: &rhs.value,
|
|
||||||
schema: lhs.schema,
|
|
||||||
typeRef: lhs.typeRef,
|
|
||||||
rule: rule,
|
|
||||||
postItemHook: postRule,
|
|
||||||
}
|
|
||||||
errs := mw.merge()
|
|
||||||
if len(errs) > 0 {
|
|
||||||
return TypedValue{}, errs
|
|
||||||
}
|
|
||||||
|
|
||||||
out := TypedValue{
|
|
||||||
schema: lhs.schema,
|
|
||||||
typeRef: lhs.typeRef,
|
|
||||||
}
|
|
||||||
if mw.out == nil {
|
|
||||||
out.value = value.Value{Null: true}
|
|
||||||
} else {
|
|
||||||
out.value = *mw.out
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AsTypeUnvalidated is just like WithType, but doesn't validate that the type
|
|
||||||
// conforms to the schema, for cases where that has already been checked or
|
|
||||||
// where you're going to call a method that validates as a side-effect (like
|
|
||||||
// ToFieldSet).
|
|
||||||
func AsTypedUnvalidated(v value.Value, s *schema.Schema, typeName string) TypedValue {
|
|
||||||
tv := TypedValue{
|
|
||||||
value: v,
|
|
||||||
typeRef: schema.TypeRef{NamedType: &typeName},
|
|
||||||
schema: s,
|
|
||||||
}
|
|
||||||
return tv
|
|
||||||
}
|
|
||||||
|
2
vendor/sigs.k8s.io/structured-merge-diff/typed/validate.go
generated
vendored
2
vendor/sigs.k8s.io/structured-merge-diff/typed/validate.go
generated
vendored
@ -22,7 +22,7 @@ import (
|
|||||||
"sigs.k8s.io/structured-merge-diff/value"
|
"sigs.k8s.io/structured-merge-diff/value"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (tv TypedValue) walker() *validatingObjectWalker {
|
func (tv typedValue) walker() *validatingObjectWalker {
|
||||||
return &validatingObjectWalker{
|
return &validatingObjectWalker{
|
||||||
value: tv.value,
|
value: tv.value,
|
||||||
schema: tv.schema,
|
schema: tv.schema,
|
||||||
|
2
vendor/sigs.k8s.io/structured-merge-diff/value/unstructured.go
generated
vendored
2
vendor/sigs.k8s.io/structured-merge-diff/value/unstructured.go
generated
vendored
@ -31,7 +31,7 @@ import (
|
|||||||
func FromYAML(input []byte) (Value, error) {
|
func FromYAML(input []byte) (Value, error) {
|
||||||
var decoded interface{}
|
var decoded interface{}
|
||||||
|
|
||||||
if len(input) == 0 || (len(input) == 4 && string(input) == "null") {
|
if len(input) == 4 && string(input) == "null" {
|
||||||
// Special case since the yaml package doesn't accurately
|
// Special case since the yaml package doesn't accurately
|
||||||
// preserve this.
|
// preserve this.
|
||||||
return Value{Null: true}, nil
|
return Value{Null: true}, nil
|
||||||
|
Loading…
Reference in New Issue
Block a user