vendor: bump k8s dependencies to v0.29.2

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax
2024-02-24 16:41:41 +01:00
parent ae0a5e495a
commit 303e509bbf
761 changed files with 66147 additions and 29461 deletions

View File

@ -0,0 +1,49 @@
/*
Copyright 2014 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 equality
import (
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
)
// Semantic can do semantic deep equality checks for api objects.
// Example: apiequality.Semantic.DeepEqual(aPod, aPodWithNonNilButEmptyMaps) == true
var Semantic = conversion.EqualitiesOrDie(
func(a, b resource.Quantity) bool {
// Ignore formatting, only care that numeric value stayed the same.
// TODO: if we decide it's important, it should be safe to start comparing the format.
//
// Uninitialized quantities are equivalent to 0 quantities.
return a.Cmp(b) == 0
},
func(a, b metav1.MicroTime) bool {
return a.UTC() == b.UTC()
},
func(a, b metav1.Time) bool {
return a.UTC() == b.UTC()
},
func(a, b labels.Selector) bool {
return a.String() == b.String()
},
func(a, b fields.Selector) bool {
return a.String() == b.String()
},
)

View File

@ -2,7 +2,6 @@
reviewers:
- thockin
- lavalamp
- smarterclayton
- wojtek-t
- deads2k

View File

@ -22,14 +22,15 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// SetStatusCondition sets the corresponding condition in conditions to newCondition.
// SetStatusCondition sets the corresponding condition in conditions to newCondition and returns true
// if the conditions are changed by this call.
// conditions must be non-nil.
// 1. if the condition of the specified type already exists (all fields of the existing condition are updated to
// newCondition, LastTransitionTime is set to now if the new status differs from the old status)
// 2. if a condition of the specified type does not exist (LastTransitionTime is set to now() if unset, and newCondition is appended)
func SetStatusCondition(conditions *[]metav1.Condition, newCondition metav1.Condition) {
func SetStatusCondition(conditions *[]metav1.Condition, newCondition metav1.Condition) (changed bool) {
if conditions == nil {
return
return false
}
existingCondition := FindStatusCondition(*conditions, newCondition.Type)
if existingCondition == nil {
@ -37,7 +38,7 @@ func SetStatusCondition(conditions *[]metav1.Condition, newCondition metav1.Cond
newCondition.LastTransitionTime = metav1.NewTime(time.Now())
}
*conditions = append(*conditions, newCondition)
return
return true
}
if existingCondition.Status != newCondition.Status {
@ -47,18 +48,31 @@ func SetStatusCondition(conditions *[]metav1.Condition, newCondition metav1.Cond
} else {
existingCondition.LastTransitionTime = metav1.NewTime(time.Now())
}
changed = true
}
existingCondition.Reason = newCondition.Reason
existingCondition.Message = newCondition.Message
existingCondition.ObservedGeneration = newCondition.ObservedGeneration
if existingCondition.Reason != newCondition.Reason {
existingCondition.Reason = newCondition.Reason
changed = true
}
if existingCondition.Message != newCondition.Message {
existingCondition.Message = newCondition.Message
changed = true
}
if existingCondition.ObservedGeneration != newCondition.ObservedGeneration {
existingCondition.ObservedGeneration = newCondition.ObservedGeneration
changed = true
}
return changed
}
// RemoveStatusCondition removes the corresponding conditionType from conditions.
// RemoveStatusCondition removes the corresponding conditionType from conditions if present. Returns
// true if it was present and got removed.
// conditions must be non-nil.
func RemoveStatusCondition(conditions *[]metav1.Condition, conditionType string) {
func RemoveStatusCondition(conditions *[]metav1.Condition, conditionType string) (removed bool) {
if conditions == nil || len(*conditions) == 0 {
return
return false
}
newConditions := make([]metav1.Condition, 0, len(*conditions)-1)
for _, condition := range *conditions {
@ -67,7 +81,10 @@ func RemoveStatusCondition(conditions *[]metav1.Condition, conditionType string)
}
}
removed = len(*conditions) != len(newConditions)
*conditions = newConditions
return removed
}
// FindStatusCondition finds the conditionType in conditions.

View File

@ -40,8 +40,7 @@ var (
// IsListType returns true if the provided Object has a slice called Items.
// TODO: Replace the code in this check with an interface comparison by
//
// creating and enforcing that lists implement a list accessor.
// creating and enforcing that lists implement a list accessor.
func IsListType(obj runtime.Object) bool {
switch t := obj.(type) {
case runtime.Unstructured:
@ -113,8 +112,27 @@ func getItemsPtr(list runtime.Object) (interface{}, error) {
// EachListItem invokes fn on each runtime.Object in the list. Any error immediately terminates
// the loop.
//
// If items passed to fn are retained for different durations, and you want to avoid
// retaining all items in obj as long as any item is referenced, use EachListItemWithAlloc instead.
func EachListItem(obj runtime.Object, fn func(runtime.Object) error) error {
return eachListItem(obj, fn, false)
}
// EachListItemWithAlloc works like EachListItem, but avoids retaining references to the items slice in obj.
// It does this by making a shallow copy of non-pointer items in obj.
//
// If the items passed to fn are not retained, or are retained for the same duration, use EachListItem instead for memory efficiency.
func EachListItemWithAlloc(obj runtime.Object, fn func(runtime.Object) error) error {
return eachListItem(obj, fn, true)
}
// allocNew: Whether shallow copy is required when the elements in Object.Items are struct
func eachListItem(obj runtime.Object, fn func(runtime.Object) error, allocNew bool) error {
if unstructured, ok := obj.(runtime.Unstructured); ok {
if allocNew {
return unstructured.EachListItemWithAlloc(fn)
}
return unstructured.EachListItem(fn)
}
// TODO: Change to an interface call?
@ -141,8 +159,19 @@ func EachListItem(obj runtime.Object, fn func(runtime.Object) error) error {
for i := 0; i < len; i++ {
raw := items.Index(i)
if takeAddr {
raw = raw.Addr()
if allocNew {
// shallow copy to avoid retaining a reference to the original list item
itemCopy := reflect.New(raw.Type())
// assign to itemCopy and type-assert
itemCopy.Elem().Set(raw)
// reflect.New will guarantee that itemCopy must be a pointer.
raw = itemCopy
} else {
raw = raw.Addr()
}
}
// raw must be a pointer or an interface
// allocate a pointer is cheap
switch item := raw.Interface().(type) {
case *runtime.RawExtension:
if err := fn(item.Object); err != nil {
@ -167,7 +196,23 @@ func EachListItem(obj runtime.Object, fn func(runtime.Object) error) error {
// ExtractList returns obj's Items element as an array of runtime.Objects.
// Returns an error if obj is not a List type (does not have an Items member).
//
// If items in the returned list are retained for different durations, and you want to avoid
// retaining all items in obj as long as any item is referenced, use ExtractListWithAlloc instead.
func ExtractList(obj runtime.Object) ([]runtime.Object, error) {
return extractList(obj, false)
}
// ExtractListWithAlloc works like ExtractList, but avoids retaining references to the items slice in obj.
// It does this by making a shallow copy of non-pointer items in obj.
//
// If the items in the returned list are not retained, or are retained for the same duration, use ExtractList instead for memory efficiency.
func ExtractListWithAlloc(obj runtime.Object) ([]runtime.Object, error) {
return extractList(obj, true)
}
// allocNew: Whether shallow copy is required when the elements in Object.Items are struct
func extractList(obj runtime.Object, allocNew bool) ([]runtime.Object, error) {
itemsPtr, err := GetItemsPtr(obj)
if err != nil {
return nil, err
@ -177,10 +222,17 @@ func ExtractList(obj runtime.Object) ([]runtime.Object, error) {
return nil, err
}
list := make([]runtime.Object, items.Len())
if len(list) == 0 {
return list, nil
}
elemType := items.Type().Elem()
isRawExtension := elemType == rawExtensionObjectType
implementsObject := elemType.Implements(objectType)
for i := range list {
raw := items.Index(i)
switch item := raw.Interface().(type) {
case runtime.RawExtension:
switch {
case isRawExtension:
item := raw.Interface().(runtime.RawExtension)
switch {
case item.Object != nil:
list[i] = item.Object
@ -190,8 +242,18 @@ func ExtractList(obj runtime.Object) ([]runtime.Object, error) {
default:
list[i] = nil
}
case runtime.Object:
list[i] = item
case implementsObject:
list[i] = raw.Interface().(runtime.Object)
case allocNew:
// shallow copy to avoid retaining a reference to the original list item
itemCopy := reflect.New(raw.Type())
// assign to itemCopy and type-assert
itemCopy.Elem().Set(raw)
var ok bool
// reflect.New will guarantee that itemCopy must be a pointer.
if list[i], ok = itemCopy.Interface().(runtime.Object); !ok {
return nil, fmt.Errorf("%v: item[%v]: Expected object, got %#v(%s)", obj, i, raw.Interface(), raw.Kind())
}
default:
var found bool
if list[i], found = raw.Addr().Interface().(runtime.Object); !found {
@ -202,8 +264,12 @@ func ExtractList(obj runtime.Object) ([]runtime.Object, error) {
return list, nil
}
// objectSliceType is the type of a slice of Objects
var objectSliceType = reflect.TypeOf([]runtime.Object{})
var (
// objectSliceType is the type of a slice of Objects
objectSliceType = reflect.TypeOf([]runtime.Object{})
objectType = reflect.TypeOf((*runtime.Object)(nil)).Elem()
rawExtensionObjectType = reflect.TypeOf(runtime.RawExtension{})
)
// LenList returns the length of this list or 0 if it is not a list.
func LenList(list runtime.Object) int {
@ -238,7 +304,7 @@ func SetList(list runtime.Object, objects []runtime.Object) error {
slice := reflect.MakeSlice(items.Type(), len(objects), len(objects))
for i := range objects {
dest := slice.Index(i)
if dest.Type() == reflect.TypeOf(runtime.RawExtension{}) {
if dest.Type() == rawExtensionObjectType {
dest = dest.FieldByName("Object")
}

View File

@ -2,7 +2,6 @@
reviewers:
- thockin
- lavalamp
- smarterclayton
- wojtek-t
- derekwaynecarr

View File

@ -203,6 +203,44 @@ func (a *int64Amount) Sub(b int64Amount) bool {
return a.Add(int64Amount{value: -b.value, scale: b.scale})
}
// Mul multiplies the provided b to the current amount, or
// returns false if overflow or underflow would result.
func (a *int64Amount) Mul(b int64) bool {
switch {
case a.value == 0:
return true
case b == 0:
a.value = 0
a.scale = 0
return true
case a.scale == 0:
c, ok := int64Multiply(a.value, b)
if !ok {
return false
}
a.value = c
case a.scale > 0:
c, ok := int64Multiply(a.value, b)
if !ok {
return false
}
if _, ok = positiveScaleInt64(c, a.scale); !ok {
return false
}
a.value = c
default:
c, ok := int64Multiply(a.value, b)
if !ok {
return false
}
if _, ok = negativeScaleInt64(c, -a.scale); !ok {
return false
}
a.value = c
}
return true
}
// AsScale adjusts this amount to set a minimum scale, rounding up, and returns true iff no precision
// was lost. (1.1e5).AsScale(5) would return 1.1e5, but (1.1e5).AsScale(6) would return 1e6.
func (a int64Amount) AsScale(scale Scale) (int64Amount, bool) {

View File

@ -592,6 +592,16 @@ func (q *Quantity) Sub(y Quantity) {
q.ToDec().d.Dec.Sub(q.d.Dec, y.AsDec())
}
// Mul multiplies the provided y to the current value.
// It will return false if the result is inexact. Otherwise, it will return true.
func (q *Quantity) Mul(y int64) bool {
q.s = ""
if q.d.Dec == nil && q.i.Mul(y) {
return true
}
return q.ToDec().d.Dec.Mul(q.d.Dec, inf.NewDec(y, inf.Scale(0))).UnscaledBig().IsInt64()
}
// Cmp returns 0 if the quantity is equal to y, -1 if the quantity is less than y, or 1 if the
// quantity is greater than y.
func (q *Quantity) Cmp(y Quantity) int {

18
vendor/k8s.io/apimachinery/pkg/api/validation/doc.go generated vendored Normal file
View File

@ -0,0 +1,18 @@
/*
Copyright 2017 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 validation contains generic api type validation functions.
package validation // import "k8s.io/apimachinery/pkg/api/validation"

View File

@ -0,0 +1,88 @@
/*
Copyright 2014 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 validation
import (
"strings"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
)
// IsNegativeErrorMsg is a error message for value must be greater than or equal to 0.
const IsNegativeErrorMsg string = `must be greater than or equal to 0`
// ValidateNameFunc validates that the provided name is valid for a given resource type.
// Not all resources have the same validation rules for names. Prefix is true
// if the name will have a value appended to it. If the name is not valid,
// this returns a list of descriptions of individual characteristics of the
// value that were not valid. Otherwise this returns an empty list or nil.
type ValidateNameFunc func(name string, prefix bool) []string
// NameIsDNSSubdomain is a ValidateNameFunc for names that must be a DNS subdomain.
func NameIsDNSSubdomain(name string, prefix bool) []string {
if prefix {
name = maskTrailingDash(name)
}
return validation.IsDNS1123Subdomain(name)
}
// NameIsDNSLabel is a ValidateNameFunc for names that must be a DNS 1123 label.
func NameIsDNSLabel(name string, prefix bool) []string {
if prefix {
name = maskTrailingDash(name)
}
return validation.IsDNS1123Label(name)
}
// NameIsDNS1035Label is a ValidateNameFunc for names that must be a DNS 952 label.
func NameIsDNS1035Label(name string, prefix bool) []string {
if prefix {
name = maskTrailingDash(name)
}
return validation.IsDNS1035Label(name)
}
// ValidateNamespaceName can be used to check whether the given namespace name is valid.
// Prefix indicates this name will be used as part of generation, in which case
// trailing dashes are allowed.
var ValidateNamespaceName = NameIsDNSLabel
// ValidateServiceAccountName can be used to check whether the given service account name is valid.
// Prefix indicates this name will be used as part of generation, in which case
// trailing dashes are allowed.
var ValidateServiceAccountName = NameIsDNSSubdomain
// maskTrailingDash replaces the final character of a string with a subdomain safe
// value if it is a dash and if the length of this string is greater than 1. Note that
// this is used when a value could be appended to the string, see ValidateNameFunc
// for more info.
func maskTrailingDash(name string) string {
if len(name) > 1 && strings.HasSuffix(name, "-") {
return name[:len(name)-2] + "a"
}
return name
}
// ValidateNonnegativeField validates that given value is not negative.
func ValidateNonnegativeField(value int64, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if value < 0 {
allErrs = append(allErrs, field.Invalid(fldPath, value, IsNegativeErrorMsg))
}
return allErrs
}

View File

@ -0,0 +1,265 @@
/*
Copyright 2014 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 validation
import (
"fmt"
"strings"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
)
// FieldImmutableErrorMsg is a error message for field is immutable.
const FieldImmutableErrorMsg string = `field is immutable`
const TotalAnnotationSizeLimitB int = 256 * (1 << 10) // 256 kB
// BannedOwners is a black list of object that are not allowed to be owners.
var BannedOwners = map[schema.GroupVersionKind]struct{}{
{Group: "", Version: "v1", Kind: "Event"}: {},
}
// ValidateAnnotations validates that a set of annotations are correctly defined.
func ValidateAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
for k := range annotations {
// The rule is QualifiedName except that case doesn't matter, so convert to lowercase before checking.
for _, msg := range validation.IsQualifiedName(strings.ToLower(k)) {
allErrs = append(allErrs, field.Invalid(fldPath, k, msg))
}
}
if err := ValidateAnnotationsSize(annotations); err != nil {
allErrs = append(allErrs, field.TooLong(fldPath, "", TotalAnnotationSizeLimitB))
}
return allErrs
}
func ValidateAnnotationsSize(annotations map[string]string) error {
var totalSize int64
for k, v := range annotations {
totalSize += (int64)(len(k)) + (int64)(len(v))
}
if totalSize > (int64)(TotalAnnotationSizeLimitB) {
return fmt.Errorf("annotations size %d is larger than limit %d", totalSize, TotalAnnotationSizeLimitB)
}
return nil
}
func validateOwnerReference(ownerReference metav1.OwnerReference, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
gvk := schema.FromAPIVersionAndKind(ownerReference.APIVersion, ownerReference.Kind)
// gvk.Group is empty for the legacy group.
if len(gvk.Version) == 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("apiVersion"), ownerReference.APIVersion, "version must not be empty"))
}
if len(gvk.Kind) == 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("kind"), ownerReference.Kind, "kind must not be empty"))
}
if len(ownerReference.Name) == 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), ownerReference.Name, "name must not be empty"))
}
if len(ownerReference.UID) == 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("uid"), ownerReference.UID, "uid must not be empty"))
}
if _, ok := BannedOwners[gvk]; ok {
allErrs = append(allErrs, field.Invalid(fldPath, ownerReference, fmt.Sprintf("%s is disallowed from being an owner", gvk)))
}
return allErrs
}
// ValidateOwnerReferences validates that a set of owner references are correctly defined.
func ValidateOwnerReferences(ownerReferences []metav1.OwnerReference, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
firstControllerName := ""
for _, ref := range ownerReferences {
allErrs = append(allErrs, validateOwnerReference(ref, fldPath)...)
if ref.Controller != nil && *ref.Controller {
curControllerName := ref.Kind + "/" + ref.Name
if firstControllerName != "" {
allErrs = append(allErrs, field.Invalid(fldPath, ownerReferences,
fmt.Sprintf("Only one reference can have Controller set to true. Found \"true\" in references for %v and %v", firstControllerName, curControllerName)))
} else {
firstControllerName = curControllerName
}
}
}
return allErrs
}
// ValidateFinalizerName validates finalizer names.
func ValidateFinalizerName(stringValue string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
for _, msg := range validation.IsQualifiedName(stringValue) {
allErrs = append(allErrs, field.Invalid(fldPath, stringValue, msg))
}
return allErrs
}
// ValidateNoNewFinalizers validates the new finalizers has no new finalizers compare to old finalizers.
func ValidateNoNewFinalizers(newFinalizers []string, oldFinalizers []string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
extra := sets.NewString(newFinalizers...).Difference(sets.NewString(oldFinalizers...))
if len(extra) != 0 {
allErrs = append(allErrs, field.Forbidden(fldPath, fmt.Sprintf("no new finalizers can be added if the object is being deleted, found new finalizers %#v", extra.List())))
}
return allErrs
}
// ValidateImmutableField validates the new value and the old value are deeply equal.
func ValidateImmutableField(newVal, oldVal interface{}, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if !apiequality.Semantic.DeepEqual(oldVal, newVal) {
allErrs = append(allErrs, field.Invalid(fldPath, newVal, FieldImmutableErrorMsg))
}
return allErrs
}
// ValidateObjectMeta validates an object's metadata on creation. It expects that name generation has already
// been performed.
// It doesn't return an error for rootscoped resources with namespace, because namespace should already be cleared before.
func ValidateObjectMeta(objMeta *metav1.ObjectMeta, requiresNamespace bool, nameFn ValidateNameFunc, fldPath *field.Path) field.ErrorList {
metadata, err := meta.Accessor(objMeta)
if err != nil {
var allErrs field.ErrorList
allErrs = append(allErrs, field.Invalid(fldPath, objMeta, err.Error()))
return allErrs
}
return ValidateObjectMetaAccessor(metadata, requiresNamespace, nameFn, fldPath)
}
// ValidateObjectMetaAccessor validates an object's metadata on creation. It expects that name generation has already
// been performed.
// It doesn't return an error for rootscoped resources with namespace, because namespace should already be cleared before.
func ValidateObjectMetaAccessor(meta metav1.Object, requiresNamespace bool, nameFn ValidateNameFunc, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
if len(meta.GetGenerateName()) != 0 {
for _, msg := range nameFn(meta.GetGenerateName(), true) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("generateName"), meta.GetGenerateName(), msg))
}
}
// If the generated name validates, but the calculated value does not, it's a problem with generation, and we
// report it here. This may confuse users, but indicates a programming bug and still must be validated.
// If there are multiple fields out of which one is required then add an or as a separator
if len(meta.GetName()) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("name"), "name or generateName is required"))
} else {
for _, msg := range nameFn(meta.GetName(), false) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), meta.GetName(), msg))
}
}
if requiresNamespace {
if len(meta.GetNamespace()) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("namespace"), ""))
} else {
for _, msg := range ValidateNamespaceName(meta.GetNamespace(), false) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("namespace"), meta.GetNamespace(), msg))
}
}
} else {
if len(meta.GetNamespace()) != 0 {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("namespace"), "not allowed on this type"))
}
}
allErrs = append(allErrs, ValidateNonnegativeField(meta.GetGeneration(), fldPath.Child("generation"))...)
allErrs = append(allErrs, v1validation.ValidateLabels(meta.GetLabels(), fldPath.Child("labels"))...)
allErrs = append(allErrs, ValidateAnnotations(meta.GetAnnotations(), fldPath.Child("annotations"))...)
allErrs = append(allErrs, ValidateOwnerReferences(meta.GetOwnerReferences(), fldPath.Child("ownerReferences"))...)
allErrs = append(allErrs, ValidateFinalizers(meta.GetFinalizers(), fldPath.Child("finalizers"))...)
allErrs = append(allErrs, v1validation.ValidateManagedFields(meta.GetManagedFields(), fldPath.Child("managedFields"))...)
return allErrs
}
// ValidateFinalizers tests if the finalizers name are valid, and if there are conflicting finalizers.
func ValidateFinalizers(finalizers []string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
hasFinalizerOrphanDependents := false
hasFinalizerDeleteDependents := false
for _, finalizer := range finalizers {
allErrs = append(allErrs, ValidateFinalizerName(finalizer, fldPath)...)
if finalizer == metav1.FinalizerOrphanDependents {
hasFinalizerOrphanDependents = true
}
if finalizer == metav1.FinalizerDeleteDependents {
hasFinalizerDeleteDependents = true
}
}
if hasFinalizerDeleteDependents && hasFinalizerOrphanDependents {
allErrs = append(allErrs, field.Invalid(fldPath, finalizers, fmt.Sprintf("finalizer %s and %s cannot be both set", metav1.FinalizerOrphanDependents, metav1.FinalizerDeleteDependents)))
}
return allErrs
}
// ValidateObjectMetaUpdate validates an object's metadata when updated.
func ValidateObjectMetaUpdate(newMeta, oldMeta *metav1.ObjectMeta, fldPath *field.Path) field.ErrorList {
newMetadata, err := meta.Accessor(newMeta)
if err != nil {
allErrs := field.ErrorList{}
allErrs = append(allErrs, field.Invalid(fldPath, newMeta, err.Error()))
return allErrs
}
oldMetadata, err := meta.Accessor(oldMeta)
if err != nil {
allErrs := field.ErrorList{}
allErrs = append(allErrs, field.Invalid(fldPath, oldMeta, err.Error()))
return allErrs
}
return ValidateObjectMetaAccessorUpdate(newMetadata, oldMetadata, fldPath)
}
// ValidateObjectMetaAccessorUpdate validates an object's metadata when updated.
func ValidateObjectMetaAccessorUpdate(newMeta, oldMeta metav1.Object, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
// Finalizers cannot be added if the object is already being deleted.
if oldMeta.GetDeletionTimestamp() != nil {
allErrs = append(allErrs, ValidateNoNewFinalizers(newMeta.GetFinalizers(), oldMeta.GetFinalizers(), fldPath.Child("finalizers"))...)
}
// Reject updates that don't specify a resource version
if len(newMeta.GetResourceVersion()) == 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("resourceVersion"), newMeta.GetResourceVersion(), "must be specified for an update"))
}
// Generation shouldn't be decremented
if newMeta.GetGeneration() < oldMeta.GetGeneration() {
allErrs = append(allErrs, field.Invalid(fldPath.Child("generation"), newMeta.GetGeneration(), "must not be decremented"))
}
allErrs = append(allErrs, ValidateImmutableField(newMeta.GetName(), oldMeta.GetName(), fldPath.Child("name"))...)
allErrs = append(allErrs, ValidateImmutableField(newMeta.GetNamespace(), oldMeta.GetNamespace(), fldPath.Child("namespace"))...)
allErrs = append(allErrs, ValidateImmutableField(newMeta.GetUID(), oldMeta.GetUID(), fldPath.Child("uid"))...)
allErrs = append(allErrs, ValidateImmutableField(newMeta.GetCreationTimestamp(), oldMeta.GetCreationTimestamp(), fldPath.Child("creationTimestamp"))...)
allErrs = append(allErrs, ValidateImmutableField(newMeta.GetDeletionTimestamp(), oldMeta.GetDeletionTimestamp(), fldPath.Child("deletionTimestamp"))...)
allErrs = append(allErrs, ValidateImmutableField(newMeta.GetDeletionGracePeriodSeconds(), oldMeta.GetDeletionGracePeriodSeconds(), fldPath.Child("deletionGracePeriodSeconds"))...)
allErrs = append(allErrs, v1validation.ValidateLabels(newMeta.GetLabels(), fldPath.Child("labels"))...)
allErrs = append(allErrs, ValidateAnnotations(newMeta.GetAnnotations(), fldPath.Child("annotations"))...)
allErrs = append(allErrs, ValidateOwnerReferences(newMeta.GetOwnerReferences(), fldPath.Child("ownerReferences"))...)
allErrs = append(allErrs, v1validation.ValidateManagedFields(newMeta.GetManagedFields(), fldPath.Child("managedFields"))...)
return allErrs
}