mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-10-21 06:39:53 +00:00
aa698bc3e1
Kubernetes v1.22 version has been released and this update ceph csi dependencies to use the same version. Signed-off-by: Humble Chirammal <hchiramm@redhat.com>
166 lines
4.8 KiB
Go
166 lines
4.8 KiB
Go
/*
|
|
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/v4/fieldpath"
|
|
"sigs.k8s.io/structured-merge-diff/v4/schema"
|
|
"sigs.k8s.io/structured-merge-diff/v4/value"
|
|
)
|
|
|
|
type removingWalker struct {
|
|
value value.Value
|
|
out interface{}
|
|
schema *schema.Schema
|
|
toRemove *fieldpath.Set
|
|
allocator value.Allocator
|
|
shouldExtract bool
|
|
}
|
|
|
|
// removeItemsWithSchema will walk the given value and look for items from the toRemove set.
|
|
// Depending on whether shouldExtract is set true or false, it will return a modified version
|
|
// of the input value with either:
|
|
// 1. only the items in the toRemove set (when shouldExtract is true) or
|
|
// 2. the items from the toRemove set removed from the value (when shouldExtract is false).
|
|
func removeItemsWithSchema(val value.Value, toRemove *fieldpath.Set, schema *schema.Schema, typeRef schema.TypeRef, shouldExtract bool) value.Value {
|
|
w := &removingWalker{
|
|
value: val,
|
|
schema: schema,
|
|
toRemove: toRemove,
|
|
allocator: value.NewFreelistAllocator(),
|
|
shouldExtract: shouldExtract,
|
|
}
|
|
resolveSchema(schema, typeRef, val, w)
|
|
return value.NewValueInterface(w.out)
|
|
}
|
|
|
|
func (w *removingWalker) doScalar(t *schema.Scalar) ValidationErrors {
|
|
w.out = w.value.Unstructured()
|
|
return nil
|
|
}
|
|
|
|
func (w *removingWalker) doList(t *schema.List) (errs ValidationErrors) {
|
|
if !w.value.IsList() {
|
|
return nil
|
|
}
|
|
l := w.value.AsListUsing(w.allocator)
|
|
defer w.allocator.Free(l)
|
|
// If list is null or empty just return
|
|
if l == nil || l.Length() == 0 {
|
|
return nil
|
|
}
|
|
|
|
// atomic lists should return everything in the case of extract
|
|
// and nothing in the case of remove (!w.shouldExtract)
|
|
if t.ElementRelationship == schema.Atomic {
|
|
if w.shouldExtract {
|
|
w.out = w.value.Unstructured()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var newItems []interface{}
|
|
iter := l.RangeUsing(w.allocator)
|
|
defer w.allocator.Free(iter)
|
|
for iter.Next() {
|
|
i, item := iter.Item()
|
|
// Ignore error because we have already validated this list
|
|
pe, _ := listItemToPathElement(w.allocator, w.schema, t, i, item)
|
|
path, _ := fieldpath.MakePath(pe)
|
|
// save items on the path when we shouldExtract
|
|
// but ignore them when we are removing (i.e. !w.shouldExtract)
|
|
if w.toRemove.Has(path) {
|
|
if w.shouldExtract {
|
|
newItems = append(newItems, removeItemsWithSchema(item, w.toRemove, w.schema, t.ElementType, w.shouldExtract).Unstructured())
|
|
} else {
|
|
continue
|
|
}
|
|
}
|
|
if subset := w.toRemove.WithPrefix(pe); !subset.Empty() {
|
|
item = removeItemsWithSchema(item, subset, w.schema, t.ElementType, w.shouldExtract)
|
|
} else {
|
|
// don't save items not on the path when we shouldExtract.
|
|
if w.shouldExtract {
|
|
continue
|
|
}
|
|
}
|
|
newItems = append(newItems, item.Unstructured())
|
|
}
|
|
if len(newItems) > 0 {
|
|
w.out = newItems
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (w *removingWalker) doMap(t *schema.Map) ValidationErrors {
|
|
if !w.value.IsMap() {
|
|
return nil
|
|
}
|
|
m := w.value.AsMapUsing(w.allocator)
|
|
if m != nil {
|
|
defer w.allocator.Free(m)
|
|
}
|
|
// If map is null or empty just return
|
|
if m == nil || m.Empty() {
|
|
return nil
|
|
}
|
|
|
|
// atomic maps should return everything in the case of extract
|
|
// and nothing in the case of remove (!w.shouldExtract)
|
|
if t.ElementRelationship == schema.Atomic {
|
|
if w.shouldExtract {
|
|
w.out = w.value.Unstructured()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
fieldTypes := map[string]schema.TypeRef{}
|
|
for _, structField := range t.Fields {
|
|
fieldTypes[structField.Name] = structField.Type
|
|
}
|
|
|
|
newMap := map[string]interface{}{}
|
|
m.Iterate(func(k string, val value.Value) bool {
|
|
pe := fieldpath.PathElement{FieldName: &k}
|
|
path, _ := fieldpath.MakePath(pe)
|
|
fieldType := t.ElementType
|
|
if ft, ok := fieldTypes[k]; ok {
|
|
fieldType = ft
|
|
}
|
|
// save values on the path when we shouldExtract
|
|
// but ignore them when we are removing (i.e. !w.shouldExtract)
|
|
if w.toRemove.Has(path) {
|
|
if w.shouldExtract {
|
|
newMap[k] = removeItemsWithSchema(val, w.toRemove, w.schema, fieldType, w.shouldExtract).Unstructured()
|
|
|
|
}
|
|
return true
|
|
}
|
|
if subset := w.toRemove.WithPrefix(pe); !subset.Empty() {
|
|
val = removeItemsWithSchema(val, subset, w.schema, fieldType, w.shouldExtract)
|
|
} else {
|
|
// don't save values not on the path when we shouldExtract.
|
|
if w.shouldExtract {
|
|
return true
|
|
}
|
|
}
|
|
newMap[k] = val.Unstructured()
|
|
return true
|
|
})
|
|
if len(newMap) > 0 {
|
|
w.out = newMap
|
|
}
|
|
return nil
|
|
}
|