// TODO: add other common fields that require global validation. func validateCommonFields(obj, old runtime.Object) (field.ErrorList, error) { allErrs := field.ErrorList{} objectMeta, err := metav1.ObjectMetaFor(obj) if err != nil { return nil, fmt.Errorf("failed to get new object metadata: %v", err) } oldObjectMeta, err := metav1.ObjectMetaFor(old) if err != nil { return nil, fmt.Errorf("failed to get old object metadata: %v", err) } allErrs = append(allErrs, genericvalidation.ValidateObjectMetaUpdate(objectMeta, oldObjectMeta, field.NewPath("metadata"))...) return allErrs, nil }
// shouldDelete checks if a Update is removing all the object's finalizers. If so, // it further checks if the object's DeletionGracePeriodSeconds is 0. If so, it // returns true. func (e *Store) shouldDelete(ctx genericapirequest.Context, key string, obj, existing runtime.Object) bool { if !e.EnableGarbageCollection { return false } newMeta, err := metav1.ObjectMetaFor(obj) if err != nil { utilruntime.HandleError(err) return false } oldMeta, err := metav1.ObjectMetaFor(existing) if err != nil { utilruntime.HandleError(err) return false } return len(newMeta.Finalizers) == 0 && oldMeta.DeletionGracePeriodSeconds != nil && *oldMeta.DeletionGracePeriodSeconds == 0 }
func (t *Tester) getObjectMetaOrFail(obj runtime.Object) *metav1.ObjectMeta { meta, err := metav1.ObjectMetaFor(obj) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, obj) } return meta }
// objectMetaAndKind retrieves kind and ObjectMeta from a runtime object, or returns an error. func objectMetaAndKind(typer runtime.ObjectTyper, obj runtime.Object) (*metav1.ObjectMeta, schema.GroupVersionKind, error) { objectMeta, err := metav1.ObjectMetaFor(obj) if err != nil { return nil, schema.GroupVersionKind{}, errors.NewInternalError(err) } kinds, _, err := typer.ObjectKinds(obj) if err != nil { return nil, schema.GroupVersionKind{}, errors.NewInternalError(err) } return objectMeta, kinds[0], nil }
func (t *Tester) delete(ctx genericapirequest.Context, obj runtime.Object) error { objectMeta, err := metav1.ObjectMetaFor(obj) if err != nil { return err } deleter, ok := t.storage.(rest.GracefulDeleter) if !ok { return fmt.Errorf("Expected deleting storage, got %v", t.storage) } _, err = deleter.Delete(ctx, objectMeta.Name, nil) return err }
func checkPreconditions(key string, preconditions *storage.Preconditions, out runtime.Object) error { if preconditions == nil { return nil } objMeta, err := metav1.ObjectMetaFor(out) if err != nil { return storage.NewInternalErrorf("can't enforce preconditions %v on un-introspectable object %v, got error: %v", *preconditions, out, err) } if preconditions.UID != nil && *preconditions.UID != objMeta.UID { errMsg := fmt.Sprintf("Precondition failed: UID in precondition: %v, UID in object meta: %v", *preconditions.UID, objMeta.UID) return storage.NewInvalidObjError(key, errMsg) } return nil }
// markAsDeleting sets the obj's DeletionGracePeriodSeconds to 0, and sets the // DeletionTimestamp to "now". Finalizers are watching for such updates and will // finalize the object if their IDs are present in the object's Finalizers list. func markAsDeleting(obj runtime.Object) (err error) { objectMeta, kerr := metav1.ObjectMetaFor(obj) if kerr != nil { return kerr } now := metav1.NewTime(time.Now()) // This handles Generation bump for resources that don't support graceful deletion. For resources that support graceful deletion is handle in pkg/api/rest/delete.go if objectMeta.DeletionTimestamp == nil && objectMeta.Generation > 0 { objectMeta.Generation++ } objectMeta.DeletionTimestamp = &now var zero int64 = 0 objectMeta.DeletionGracePeriodSeconds = &zero return nil }
// BeforeUpdate ensures that common operations for all resources are performed on update. It only returns // errors that can be converted to api.Status. It will invoke update validation with the provided existing // and updated objects. func BeforeUpdate(strategy RESTUpdateStrategy, ctx genericapirequest.Context, obj, old runtime.Object) error { objectMeta, kind, kerr := objectMetaAndKind(strategy, obj) if kerr != nil { return kerr } if strategy.NamespaceScoped() { if !ValidNamespace(ctx, objectMeta) { return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request") } } else { objectMeta.Namespace = api.NamespaceNone } // Ensure requests cannot update generation oldMeta, err := metav1.ObjectMetaFor(old) if err != nil { return err } objectMeta.Generation = oldMeta.Generation strategy.PrepareForUpdate(ctx, obj, old) // ClusterName is ignored and should not be saved objectMeta.ClusterName = "" // Ensure some common fields, like UID, are validated for all resources. errs, err := validateCommonFields(obj, old) if err != nil { return errors.NewInternalError(err) } errs = append(errs, strategy.ValidateUpdate(ctx, obj, old)...) if len(errs) > 0 { return errors.NewInvalid(kind.GroupKind(), objectMeta.Name, errs) } strategy.Canonicalize(obj) return nil }