// Ensure that when scheduler creates a binding for a pod that has already been deleted // by the API server, API server returns not-found error. func TestEtcdCreateBindingNoPod(t *testing.T) { storage, bindingStorage, _, server := newStorage(t) defer server.Terminate(t) defer storage.Store.DestroyFunc() ctx := api.NewDefaultContext() key, _ := storage.KeyFunc(ctx, "foo") key = etcdtest.AddPrefix(key) // Assume that a pod has undergone the following: // - Create (apiserver) // - Schedule (scheduler) // - Delete (apiserver) _, err := bindingStorage.Create(ctx, &api.Binding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "foo"}, Target: api.ObjectReference{Name: "machine"}, }) if err == nil { t.Fatalf("Expected not-found-error but got nothing") } if !errors.IsNotFound(storeerr.InterpretGetError(err, api.Resource("pods"), "foo")) { t.Fatalf("Unexpected error returned: %#v", err) } _, err = storage.Get(ctx, "foo") if err == nil { t.Fatalf("Expected not-found-error but got nothing") } if !errors.IsNotFound(storeerr.InterpretGetError(err, api.Resource("pods"), "foo")) { t.Fatalf("Unexpected error: %v", err) } }
// Ensure that when a deploymentRollback is created for a deployment that has already been deleted // by the API server, API server returns not-found error. func TestEtcdCreateDeploymentRollbackNoDeployment(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) rollbackStorage := storage.Rollback ctx := api.WithNamespace(api.NewContext(), namespace) key, _ := storage.Deployment.KeyFunc(ctx, name) key = etcdtest.AddPrefix(key) _, err := rollbackStorage.Create(ctx, &extensions.DeploymentRollback{ Name: name, UpdatedAnnotations: map[string]string{}, RollbackTo: extensions.RollbackConfig{Revision: 1}, }) if err == nil { t.Fatalf("Expected not-found-error but got nothing") } if !errors.IsNotFound(storeerr.InterpretGetError(err, extensions.Resource("deployments"), name)) { t.Fatalf("Unexpected error returned: %#v", err) } _, err = storage.Deployment.Get(ctx, name) if err == nil { t.Fatalf("Expected not-found-error but got nothing") } if !errors.IsNotFound(storeerr.InterpretGetError(err, extensions.Resource("deployments"), name)) { t.Fatalf("Unexpected error: %v", err) } }
// Get returns an api.RangeAllocation that represents the current state in // etcd. If the key does not exist, the object will have an empty ResourceVersion. func (e *Etcd) Get() (*api.RangeAllocation, error) { existing := &api.RangeAllocation{} if err := e.storage.Get(context.TODO(), e.baseKey, existing, true); err != nil { return nil, storeerr.InterpretGetError(err, e.resource, "") } return existing, nil }
// assignPod assigns the given pod to the given machine. func (r *BindingREST) assignPod(ctx api.Context, podID string, machine string, annotations map[string]string) (err error) { if _, err = r.setPodHostAndAnnotations(ctx, podID, "", machine, annotations); err != nil { err = storeerr.InterpretGetError(err, api.Resource("pods"), podID) err = storeerr.InterpretUpdateError(err, api.Resource("pods"), podID) if _, ok := err.(*errors.StatusError); !ok { err = errors.NewConflict(api.Resource("pods/binding"), podID, err) } } return }
func (r *RollbackREST) rollbackDeployment(ctx api.Context, deploymentID string, config *extensions.RollbackConfig, annotations map[string]string) (err error) { if _, err = r.setDeploymentRollback(ctx, deploymentID, config, annotations); err != nil { err = storeerr.InterpretGetError(err, extensions.Resource("deployments"), deploymentID) err = storeerr.InterpretUpdateError(err, extensions.Resource("deployments"), deploymentID) if _, ok := err.(*errors.StatusError); !ok { err = errors.NewConflict(extensions.Resource("deployments/rollback"), deploymentID, err) } } return }
func (r *RollbackREST) rollbackDeployment(ctx genericapirequest.Context, deploymentID string, config *extensions.RollbackConfig, annotations map[string]string) error { if _, err := r.setDeploymentRollback(ctx, deploymentID, config, annotations); err != nil { err = storeerr.InterpretGetError(err, extensions.Resource("deployments"), deploymentID) err = storeerr.InterpretUpdateError(err, extensions.Resource("deployments"), deploymentID) if _, ok := err.(*errors.StatusError); !ok { err = errors.NewInternalError(err) } return err } return nil }
// Refresh reloads the RangeAllocation from etcd. func (e *Etcd) Refresh() (*api.RangeAllocation, error) { e.lock.Lock() defer e.lock.Unlock() existing := &api.RangeAllocation{} if err := e.storage.Get(context.TODO(), e.baseKey, existing, false); err != nil { if storage.IsNotFound(err) { return nil, nil } return nil, storeerr.InterpretGetError(err, e.resource, "") } return existing, nil }
// Get retrieves the item from storage. func (e *Store) Get(ctx api.Context, name string) (runtime.Object, error) { obj := e.NewFunc() key, err := e.KeyFunc(ctx, name) if err != nil { return nil, err } if err := e.Storage.Get(ctx, key, obj, false); err != nil { return nil, storeerr.InterpretGetError(err, e.QualifiedResource, name) } if e.Decorator != nil { if err := e.Decorator(obj); err != nil { return nil, err } } return obj, nil }
// Get retrieves the item from storage. func (e *Store) Get(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { obj := e.NewFunc() key, err := e.KeyFunc(ctx, name) if err != nil { return nil, err } if err := e.Storage.Get(ctx, key, options.ResourceVersion, obj, false); err != nil { return nil, storeerr.InterpretGetError(err, e.QualifiedResource, name) } if e.Decorator != nil { if err := e.Decorator(obj); err != nil { return nil, err } } return obj, nil }
// Get retrieves the item from storage. func (e *Store) Get(ctx api.Context, name string) (runtime.Object, error) { obj := e.NewFunc() key, err := e.KeyFunc(ctx, name) if err != nil { return nil, err } // TODO: Once we pass GetOptions to this method, pass the ResourceVersion from it. if err := e.Storage.Get(ctx, key, "", obj, false); err != nil { return nil, storeerr.InterpretGetError(err, e.QualifiedResource, name) } if e.Decorator != nil { if err := e.Decorator(obj); err != nil { return nil, err } } return obj, nil }
// Delete enforces life-cycle rules for namespace termination func (r *REST) Delete(ctx api.Context, name string, options *api.DeleteOptions) (runtime.Object, error) { nsObj, err := r.Get(ctx, name) if err != nil { return nil, err } namespace := nsObj.(*api.Namespace) // Ensure we have a UID precondition if options == nil { options = api.NewDeleteOptions(0) } if options.Preconditions == nil { options.Preconditions = &api.Preconditions{} } if options.Preconditions.UID == nil { options.Preconditions.UID = &namespace.UID } else if *options.Preconditions.UID != namespace.UID { err = apierrors.NewConflict( api.Resource("namespaces"), name, fmt.Errorf("Precondition failed: UID in precondition: %v, UID in object meta: %v", *options.Preconditions.UID, namespace.UID), ) return nil, err } // upon first request to delete, we switch the phase to start namespace termination // TODO: enhance graceful deletion's calls to DeleteStrategy to allow phase change and finalizer patterns if namespace.DeletionTimestamp.IsZero() { key, err := r.Store.KeyFunc(ctx, name) if err != nil { return nil, err } preconditions := storage.Preconditions{UID: options.Preconditions.UID} out := r.Store.NewFunc() err = r.Store.Storage.GuaranteedUpdate( ctx, key, out, false, &preconditions, storage.SimpleUpdate(func(existing runtime.Object) (runtime.Object, error) { existingNamespace, ok := existing.(*api.Namespace) if !ok { // wrong type return nil, fmt.Errorf("expected *api.Namespace, got %v", existing) } // Set the deletion timestamp if needed if existingNamespace.DeletionTimestamp.IsZero() { now := unversioned.Now() existingNamespace.DeletionTimestamp = &now } // Set the namespace phase to terminating, if needed if existingNamespace.Status.Phase != api.NamespaceTerminating { existingNamespace.Status.Phase = api.NamespaceTerminating } return existingNamespace, nil }), ) if err != nil { err = storageerr.InterpretGetError(err, api.Resource("namespaces"), name) err = storageerr.InterpretUpdateError(err, api.Resource("namespaces"), name) if _, ok := err.(*apierrors.StatusError); !ok { err = apierrors.NewInternalError(err) } return nil, err } return out, nil } // prior to final deletion, we must ensure that finalizers is empty if len(namespace.Spec.Finalizers) != 0 { err = apierrors.NewConflict(api.Resource("namespaces"), namespace.Name, fmt.Errorf("The system is ensuring all content is removed from this namespace. Upon completion, this namespace will automatically be purged by the system.")) return nil, err } return r.Store.Delete(ctx, name, options) }