func (t *Tester) TestDeleteGracefulImmediate(existing runtime.Object, expectedGrace int64, wasGracefulFn func() bool) { objectMeta, err := api.ObjectMetaFor(existing) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, existing) } ctx := api.WithNamespace(t.TestContext(), objectMeta.Namespace) _, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(expectedGrace)) if err != nil { t.Errorf("unexpected error: %v", err) } if !wasGracefulFn() { t.Errorf("did not gracefully delete resource") } // second delete is immediate, resource is deleted out, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(0)) if err != nil { t.Errorf("unexpected error: %v", err) } _, err = t.storage.(rest.Getter).Get(ctx, objectMeta.Name) if !errors.IsNotFound(err) { t.Errorf("unexpected error, object should be deleted immediately: %v", err) } objectMeta, err = api.ObjectMetaFor(out) if err != nil { t.Errorf("unexpected error: %v", err) return } if objectMeta.DeletionTimestamp == nil || objectMeta.DeletionGracePeriodSeconds == nil || *objectMeta.DeletionGracePeriodSeconds != 0 { t.Errorf("unexpected deleted meta: %#v", objectMeta) } }
// ObjectReaction returns a ReactionFunc that takes a generic action string of the form // <verb>-<resource> or <verb>-<subresource>-<resource> and attempts to return a runtime // Object or error that matches the requested action. For instance, list-replicationControllers // should attempt to return a list of replication controllers. This method delegates to the // ObjectRetriever interface to satisfy retrieval of lists or retrieval of single items. // TODO: add support for sub resources func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc { return func(action Action) (runtime.Object, error) { _, kind, err := mapper.VersionAndKindForResource(action.GetResource()) if err != nil { return nil, fmt.Errorf("unrecognized action %s: %v", action.GetResource(), err) } // TODO: have mapper return a Kind for a subresource? switch castAction := action.(type) { case ListAction: return o.Kind(kind+"List", "") case GetAction: return o.Kind(kind, castAction.GetName()) case DeleteAction: return o.Kind(kind, castAction.GetName()) case CreateAction: meta, err := api.ObjectMetaFor(castAction.GetObject()) if err != nil { return nil, err } return o.Kind(kind, meta.Name) case UpdateAction: meta, err := api.ObjectMetaFor(castAction.GetObject()) if err != nil { return nil, err } return o.Kind(kind, meta.Name) default: return nil, fmt.Errorf("no reaction implemented for %s", action) } } }
func annotateRuntimeObject(t *testing.T, originalObj, currentObj runtime.Object, kind string) (string, []byte) { originalMeta, err := api.ObjectMetaFor(originalObj) if err != nil { t.Fatal(err) } originalMeta.Labels["DELETE_ME"] = "DELETE_ME" original, err := json.Marshal(originalObj) if err != nil { t.Fatal(err) } currentMeta, err := api.ObjectMetaFor(currentObj) if err != nil { t.Fatal(err) } if currentMeta.Annotations == nil { currentMeta.Annotations = map[string]string{} } currentMeta.Annotations[kubectl.LastAppliedConfigAnnotation] = string(original) current, err := json.Marshal(currentObj) if err != nil { t.Fatal(err) } return currentMeta.Name, current }
func (t *Tester) TestDeleteGracefulWithValue(existing runtime.Object, expectedGrace int64, wasGracefulFn func() bool) { objectMeta, err := api.ObjectMetaFor(existing) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, existing) } ctx := api.WithNamespace(t.TestContext(), objectMeta.Namespace) _, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(expectedGrace+2)) if err != nil { t.Errorf("unexpected error: %v", err) } if !wasGracefulFn() { t.Errorf("did not gracefully delete resource") } object, err := t.storage.(rest.Getter).Get(ctx, objectMeta.Name) if err != nil { t.Errorf("unexpected error, object should exist: %v", err) } objectMeta, err = api.ObjectMetaFor(object) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, object) } if objectMeta.DeletionTimestamp == nil { t.Errorf("did not set deletion timestamp") } if objectMeta.DeletionGracePeriodSeconds == nil { t.Fatalf("did not set deletion grace period seconds") } if *objectMeta.DeletionGracePeriodSeconds != expectedGrace+2 { t.Errorf("actual grace period does not match expected: %d", *objectMeta.DeletionGracePeriodSeconds) } }
// TODO: add other common fields that require global validation. func validateCommonFields(obj, old runtime.Object) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} objectMeta, err := api.ObjectMetaFor(obj) if err != nil { return append(allErrs, errors.NewInternalError(err)) } oldObjectMeta, err := api.ObjectMetaFor(old) if err != nil { return append(allErrs, errors.NewInternalError(err)) } allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(objectMeta, oldObjectMeta)...) return allErrs }
// TODO: add other common fields that require global validation. func validateCommonFields(obj, old runtime.Object) utilvalidation.ErrorList { allErrs := utilvalidation.ErrorList{} objectMeta, err := api.ObjectMetaFor(obj) if err != nil { return append(allErrs, utilvalidation.NewInternalError(utilvalidation.NewFieldPath("metadata"), err)) } oldObjectMeta, err := api.ObjectMetaFor(old) if err != nil { return append(allErrs, utilvalidation.NewInternalError(utilvalidation.NewFieldPath("metadata"), err)) } allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(objectMeta, oldObjectMeta, utilvalidation.NewFieldPath("metadata"))...) return allErrs }
// TODO: add other common fields that require global validation. func validateCommonFields(obj, old runtime.Object) (field.ErrorList, error) { allErrs := field.ErrorList{} objectMeta, err := api.ObjectMetaFor(obj) if err != nil { return nil, fmt.Errorf("failed to get new object metadata: %v", err) } oldObjectMeta, err := api.ObjectMetaFor(old) if err != nil { return nil, fmt.Errorf("failed to get old object metadata: %v", err) } allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(objectMeta, oldObjectMeta, field.NewPath("metadata"))...) return allErrs, nil }
func AddMountedSecretEdges(g osgraph.Graph, podSpec *kubegraph.PodSpecNode) { //pod specs are always contained. We'll get the toplevel container so that we can pull a namespace from it containerNode := osgraph.GetTopLevelContainerNode(g, podSpec) containerObj := g.GraphDescriber.Object(containerNode) meta, err := kapi.ObjectMetaFor(containerObj.(runtime.Object)) if err != nil { // this should never happen. it means that a podSpec is owned by a top level container that is not a runtime.Object panic(err) } for _, volume := range podSpec.Volumes { source := volume.VolumeSource if source.Secret == nil { continue } // pod secrets must be in the same namespace syntheticSecret := &kapi.Secret{} syntheticSecret.Namespace = meta.Namespace syntheticSecret.Name = source.Secret.SecretName secretNode := kubegraph.FindOrCreateSyntheticSecretNode(g, syntheticSecret) g.AddEdge(podSpec, secretNode, MountedSecretEdgeKind) } }
// 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 api.Context, key string, obj, existing runtime.Object) bool { if !EnableGarbageCollector { return false } newMeta, err := api.ObjectMetaFor(obj) if err != nil { utilruntime.HandleError(err) return false } oldMeta, err := api.ObjectMetaFor(existing) if err != nil { utilruntime.HandleError(err) return false } return len(newMeta.Finalizers) == 0 && oldMeta.DeletionGracePeriodSeconds != nil && *oldMeta.DeletionGracePeriodSeconds == 0 }
func (t *Tester) getObject(ctx api.Context, obj runtime.Object) (runtime.Object, error) { meta, err := api.ObjectMetaFor(obj) if err != nil { return nil, err } key, err := t.storage.KeyFunc(ctx, meta.Name) if err != nil { return nil, err } key = etcdtest.AddPrefix(key) resp, err := t.fakeClient.Get(key, false, false) if err != nil { return nil, err } result := t.storage.NewFunc() codec, err := getCodec(obj) if err != nil { return nil, err } if err := codec.DecodeInto([]byte(resp.Node.Value), result); err != nil { return nil, err } return result, nil }
// annotationFor returns the annotation with key for obj. func annotationFor(obj runtime.Object, key string) string { meta, err := api.ObjectMetaFor(obj) if err != nil { return "" } return meta.Annotations[key] }
// getChangeCause returns the change-cause annotation of the input object func getChangeCause(obj runtime.Object) string { meta, err := api.ObjectMetaFor(obj) if err != nil { return "" } return meta.Annotations[ChangeCauseAnnotation] }
// updateAnnotations updates annotations of obj func (o AnnotateOptions) updateAnnotations(obj runtime.Object) error { meta, err := api.ObjectMetaFor(obj) if err != nil { return err } if !o.overwrite { if err := validateNoAnnotationOverwrites(meta, o.newAnnotations); err != nil { return err } } if meta.Annotations == nil { meta.Annotations = make(map[string]string) } for key, value := range o.newAnnotations { meta.Annotations[key] = value } for _, annotation := range o.removeAnnotations { delete(meta.Annotations, annotation) } if len(o.resourceVersion) != 0 { meta.ResourceVersion = o.resourceVersion } return nil }
func labelFunc(obj runtime.Object, overwrite bool, resourceVersion string, labels map[string]string, remove []string) error { meta, err := api.ObjectMetaFor(obj) if err != nil { return err } if !overwrite { if err := validateNoOverwrites(meta, labels); err != nil { return err } } if meta.Labels == nil { meta.Labels = make(map[string]string) } for key, value := range labels { meta.Labels[key] = value } for _, label := range remove { delete(meta.Labels, label) } if len(resourceVersion) != 0 { meta.ResourceVersion = resourceVersion } return nil }
func (t *Tester) getObjectMetaOrFail(obj runtime.Object) *api.ObjectMeta { meta, err := api.ObjectMetaFor(obj) if err != nil { t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, obj) } return meta }
func GetUniqueRuntimeObjectNodeName(nodeKind string, obj runtime.Object) UniqueName { meta, err := kapi.ObjectMetaFor(obj) if err != nil { panic(err) } return UniqueName(fmt.Sprintf("%s|%s/%s", nodeKind, meta.Namespace, meta.Name)) }
// ObjectReaction returns a ReactionFunc that takes a generic action string of the form // <verb>-<resource> or <verb>-<subresource>-<resource> and attempts to return a runtime // Object or error that matches the requested action. For instance, list-replicationControllers // should attempt to return a list of replication controllers. This method delegates to the // ObjectRetriever interface to satisfy retrieval of lists or retrieval of single items. // TODO: add support for sub resources func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc { return func(action Action) (bool, runtime.Object, error) { gvk, err := mapper.KindFor(action.GetResource()) if err != nil { return false, nil, fmt.Errorf("unrecognized action %s: %v", action.GetResource(), err) } // TODO: have mapper return a Kind for a subresource? switch castAction := action.(type) { case ListAction: gvk.Kind += "List" resource, err := o.Kind(gvk, "") return true, resource, err case GetAction: resource, err := o.Kind(gvk, castAction.GetName()) return true, resource, err case DeleteAction: resource, err := o.Kind(gvk, castAction.GetName()) return true, resource, err case CreateAction: meta, err := api.ObjectMetaFor(castAction.GetObject()) if err != nil { return true, nil, err } resource, err := o.Kind(gvk, meta.Name) return true, resource, err case UpdateAction: meta, err := api.ObjectMetaFor(castAction.GetObject()) if err != nil { return true, nil, err } resource, err := o.Kind(gvk, meta.Name) return true, resource, err default: return false, nil, fmt.Errorf("no reaction implemented for %s", action) } return true, nil, nil } }
// RecordChangeCause annotate change-cause to input runtime object. func RecordChangeCause(obj runtime.Object, changeCause string) error { meta, err := api.ObjectMetaFor(obj) if err != nil { return err } if meta.Annotations == nil { meta.Annotations = make(map[string]string) } meta.Annotations[kubectl.ChangeCauseAnnotation] = changeCause return nil }
func objectMetaData(raw interface{}) (runtime.Object, *kapi.ObjectMeta, error) { obj, ok := raw.(runtime.Object) if !ok { return nil, nil, fmt.Errorf("%#v is not a runtime.Object", raw) } meta, err := kapi.ObjectMetaFor(obj) if err != nil { return nil, nil, err } return obj, meta, nil }
func (t *Tester) setObject(ctx api.Context, obj runtime.Object) error { meta, err := api.ObjectMetaFor(obj) if err != nil { return err } key, err := t.storage.KeyFunc(ctx, meta.Name) if err != nil { return err } return t.storage.Storage.Set(ctx, key, obj, nil, 0) }
// ObjectResourceVersion implements Versioner func (a APIObjectVersioner) ObjectResourceVersion(obj runtime.Object) (uint64, error) { meta, err := api.ObjectMetaFor(obj) if err != nil { return 0, err } version := meta.ResourceVersion if len(version) == 0 { return 0, nil } return strconv.ParseUint(version, 10, 64) }
// objectMetaAndKind retrieves kind and ObjectMeta from a runtime object, or returns an error. func objectMetaAndKind(typer runtime.ObjectTyper, obj runtime.Object) (*api.ObjectMeta, unversioned.GroupVersionKind, error) { objectMeta, err := api.ObjectMetaFor(obj) if err != nil { return nil, unversioned.GroupVersionKind{}, errors.NewInternalError(err) } kinds, _, err := typer.ObjectKinds(obj) if err != nil { return nil, unversioned.GroupVersionKind{}, errors.NewInternalError(err) } return objectMeta, kinds[0], 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 := api.ObjectMetaFor(obj) if kerr != nil { return kerr } now := unversioned.NewTime(time.Now()) objectMeta.DeletionTimestamp = &now var zero int64 = 0 objectMeta.DeletionGracePeriodSeconds = &zero return nil }
// objectMetaAndKind retrieves kind and ObjectMeta from a runtime object, or returns an error. func objectMetaAndKind(typer runtime.ObjectTyper, obj runtime.Object) (*api.ObjectMeta, string, error) { objectMeta, err := api.ObjectMetaFor(obj) if err != nil { return nil, "", errors.NewInternalError(err) } _, kind, err := typer.ObjectVersionAndKind(obj) if err != nil { return nil, "", errors.NewInternalError(err) } return objectMeta, kind, nil }
func (t *Tester) delete(ctx api.Context, obj runtime.Object) error { objectMeta, err := api.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 (t *Tester) getObject(ctx api.Context, obj runtime.Object) (runtime.Object, error) { meta, err := api.ObjectMetaFor(obj) if err != nil { return nil, err } result, err := t.storage.Get(ctx, meta.Name) if err != nil { return nil, err } return result, nil }
func checkPreconditions(preconditions *storage.Preconditions, out runtime.Object) error { if preconditions == nil { return nil } objMeta, err := api.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 { return etcd.Error{Code: etcd.ErrorCodeTestFailed, Message: fmt.Sprintf("the UID in the precondition (%s) does not match the UID in record (%s). The object might have been deleted and then recreated", *preconditions.UID, objMeta.UID)} } return nil }
func (t *Tester) setObject(ctx api.Context, obj runtime.Object) error { meta, err := api.ObjectMetaFor(obj) if err != nil { return err } key, err := t.storage.KeyFunc(ctx, meta.Name) if err != nil { return err } key = etcdtest.AddPrefix(key) _, err = t.fakeClient.Set(key, runtime.EncodeOrDie(testapi.Codec(), obj), 0) return err }
func SetObject(fakeClient *tools.FakeEtcdClient, keyFn keyFunc, ctx api.Context, obj runtime.Object) error { meta, err := api.ObjectMetaFor(obj) if err != nil { return err } key, err := keyFn(ctx, meta.Name) if err != nil { return err } key = etcdtest.AddPrefix(key) _, err = fakeClient.Set(key, runtime.EncodeOrDie(testapi.Codec(), obj), 0) return err }
func namespaceFor(node graph.Node) (string, error) { obj := node.(objectifier).Object() switch t := obj.(type) { case runtime.Object: meta, err := kapi.ObjectMetaFor(t) if err != nil { return "", err } return meta.Namespace, nil default: return "", fmt.Errorf("unknown object: %#v", obj) } }