func (o objects) Kind(kind, name string) (runtime.Object, error) { empty, _ := o.scheme.New("", kind) nilValue := reflect.Zero(reflect.TypeOf(empty)).Interface().(runtime.Object) arr, ok := o.types[kind] if !ok { if strings.HasSuffix(kind, "List") { itemKind := kind[:len(kind)-4] arr, ok := o.types[itemKind] if !ok { return empty, nil } out, err := o.scheme.New("", kind) if err != nil { return nilValue, err } if err := runtime.SetList(out, arr); err != nil { return nilValue, err } if out, err = o.scheme.Copy(out); err != nil { return nilValue, err } return out, nil } return nilValue, errors.NewNotFound(kind, name) } index := o.last[kind] if index >= len(arr) { index = len(arr) - 1 } if index < 0 { return nilValue, errors.NewNotFound(kind, name) } out, err := o.scheme.Copy(arr[index]) if err != nil { return nilValue, err } o.last[kind] = index + 1 if status, ok := out.(*unversioned.Status); ok { if status.Details != nil { status.Details.Kind = kind } if status.Status != unversioned.StatusSuccess { return nilValue, &errors.StatusError{ErrStatus: *status} } } return out, nil }
func (r *ScaleREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { if obj == nil { return nil, false, errors.NewBadRequest(fmt.Sprintf("nil update passed to Scale")) } scale, ok := obj.(*extensions.Scale) if !ok { return nil, false, errors.NewBadRequest(fmt.Sprintf("wrong object passed to Scale update: %v", obj)) } deployment, err := (*r.registry).GetDeployment(ctx, scale.Name) if err != nil { return nil, false, errors.NewNotFound("scale", scale.Name) } deployment.Spec.Replicas = scale.Spec.Replicas deployment, err = (*r.registry).UpdateDeployment(ctx, deployment) if err != nil { return nil, false, errors.NewConflict("scale", scale.Name, err) } return &extensions.Scale{ ObjectMeta: api.ObjectMeta{ Name: deployment.Name, Namespace: deployment.Namespace, CreationTimestamp: deployment.CreationTimestamp, }, Spec: extensions.ScaleSpec{ Replicas: deployment.Spec.Replicas, }, Status: extensions.ScaleStatus{ Replicas: deployment.Status.Replicas, Selector: deployment.Spec.Selector, }, }, false, nil }
// NewNotFound is a utility function to return a well-formatted admission control error response func NewNotFound(a Attributes) error { name, kind, err := extractKindName(a) if err != nil { return apierrors.NewInternalError(err) } return apierrors.NewNotFound(kind, name) }
func (c *mockBinderClient) GetPersistentVolumeClaim(namespace, name string) (*api.PersistentVolumeClaim, error) { if c.claim != nil { return c.claim, nil } else { return nil, errors.NewNotFound("persistentVolume", name) } }
// existingController verifies if the controller already exists func (r *RollingUpdater) existingController(controller *api.ReplicationController) (*api.ReplicationController, error) { // without rc name but generate name, there's no existing rc if len(controller.Name) == 0 && len(controller.GenerateName) > 0 { return nil, errors.NewNotFound("ReplicationController", controller.Name) } // controller name is required to get rc back return r.c.ReplicationControllers(controller.Namespace).Get(controller.Name) }
// InterpretDeleteError converts a generic etcd error on a delete // operation into the appropriate API error. func InterpretDeleteError(err error, kind, name string) error { switch { case tools.IsEtcdNotFound(err): return errors.NewNotFound(kind, name) default: return err } }
// InterpretGetError converts a generic etcd error on a retrieval // operation into the appropriate API error. func InterpretGetError(err error, kind, name string) error { switch { case etcdstorage.IsEtcdNotFound(err): return errors.NewNotFound(kind, name) default: return err } }
func (r *NodeRegistry) GetNode(ctx api.Context, nodeID string) (*api.Node, error) { r.Lock() defer r.Unlock() if r.Err != nil { return nil, r.Err } for _, node := range r.Nodes.Items { if node.Name == nodeID { return &node, nil } } return nil, errors.NewNotFound("node", nodeID) }
func TestCheckGeneratedNameError(t *testing.T) { expect := errors.NewNotFound("foo", "bar") if err := CheckGeneratedNameError(Services, expect, &api.Pod{}); err != expect { t.Errorf("NotFoundError should be ignored: %v", err) } expect = errors.NewAlreadyExists("foo", "bar") if err := CheckGeneratedNameError(Services, expect, &api.Pod{}); err != expect { t.Errorf("AlreadyExists should be returned when no GenerateName field: %v", err) } expect = errors.NewAlreadyExists("foo", "bar") if err := CheckGeneratedNameError(Services, expect, &api.Pod{ObjectMeta: api.ObjectMeta{GenerateName: "foo"}}); err == nil || !errors.IsServerTimeout(err) { t.Errorf("expected try again later error: %v", err) } }
func (e *EndpointRegistry) GetEndpoints(ctx api.Context, name string) (*api.Endpoints, error) { // TODO: support namespaces in this mock e.lock.Lock() defer e.lock.Unlock() if e.Err != nil { return nil, e.Err } if e.Endpoints != nil { for _, endpoint := range e.Endpoints.Items { if endpoint.Name == name { return &endpoint, nil } } } return nil, errors.NewNotFound("Endpoints", name) }
func (r *ScaleREST) Get(ctx api.Context, name string) (runtime.Object, error) { deployment, err := (*r.registry).GetDeployment(ctx, name) if err != nil { return nil, errors.NewNotFound("scale", name) } return &extensions.Scale{ ObjectMeta: api.ObjectMeta{ Name: name, Namespace: deployment.Namespace, CreationTimestamp: deployment.CreationTimestamp, }, Spec: extensions.ScaleSpec{ Replicas: deployment.Spec.Replicas, }, Status: extensions.ScaleStatus{ Replicas: deployment.Status.Replicas, Selector: deployment.Spec.Selector, }, }, nil }
func TestDeleteAllNotFound(t *testing.T) { _, svc, _ := testData() f, tf, codec := NewAPIFactory() // Add an item to the list which will result in a 404 on delete svc.Items = append(svc.Items, api.Service{ObjectMeta: api.ObjectMeta{Name: "foo"}}) notFoundError := &errors.NewNotFound("Service", "foo").(*errors.StatusError).ErrStatus tf.Printer = &testPrinter{} tf.Client = &fake.RESTClient{ Codec: codec, Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/services" && m == "GET": return &http.Response{StatusCode: 200, Body: objBody(codec, svc)}, nil case p == "/namespaces/test/services/foo" && m == "DELETE": return &http.Response{StatusCode: 404, Body: objBody(codec, notFoundError)}, nil case p == "/namespaces/test/services/baz" && m == "DELETE": return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil default: t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) return nil, nil } }), } tf.Namespace = "test" buf := bytes.NewBuffer([]byte{}) cmd := NewCmdDelete(f, buf) cmd.Flags().Set("all", "true") cmd.Flags().Set("cascade", "false") // Make sure we can explicitly choose to fail on NotFound errors, even with --all cmd.Flags().Set("ignore-not-found", "false") cmd.Flags().Set("output", "name") err := RunDelete(f, buf, cmd, []string{"services"}, &DeleteOptions{}) if err == nil || !errors.IsNotFound(err) { t.Errorf("unexpected error: expected NotFound, got %v", err) } }
func TestErrorsToAPIStatus(t *testing.T) { cases := map[error]unversioned.Status{ errors.NewNotFound("foo", "bar"): { Status: unversioned.StatusFailure, Code: http.StatusNotFound, Reason: unversioned.StatusReasonNotFound, Message: "foo \"bar\" not found", Details: &unversioned.StatusDetails{ Kind: "foo", Name: "bar", }, }, errors.NewAlreadyExists("foo", "bar"): { Status: unversioned.StatusFailure, Code: http.StatusConflict, Reason: "AlreadyExists", Message: "foo \"bar\" already exists", Details: &unversioned.StatusDetails{ Kind: "foo", Name: "bar", }, }, errors.NewConflict("foo", "bar", stderrs.New("failure")): { Status: unversioned.StatusFailure, Code: http.StatusConflict, Reason: "Conflict", Message: "foo \"bar\" cannot be updated: failure", Details: &unversioned.StatusDetails{ Kind: "foo", Name: "bar", }, }, } for k, v := range cases { actual := errToAPIStatus(k) if !reflect.DeepEqual(actual, &v) { t.Errorf("%s: Expected %#v, Got %#v", k, v, actual) } } }
func TestErrors(t *testing.T) { o := NewObjects(api.Scheme, api.Scheme) o.Add(&api.List{ Items: []runtime.Object{ // This first call to List will return this error &(errors.NewNotFound("ServiceList", "").(*errors.StatusError).ErrStatus), // The second call to List will return this error &(errors.NewForbidden("ServiceList", "", nil).(*errors.StatusError).ErrStatus), }, }) client := &Fake{} client.AddReactor("*", "*", ObjectReaction(o, testapi.Default.RESTMapper())) _, err := client.Services("test").List(labels.Everything(), fields.Everything()) if !errors.IsNotFound(err) { t.Fatalf("unexpected error: %v", err) } t.Logf("error: %#v", err.(*errors.StatusError).Status()) _, err = client.Services("test").List(labels.Everything(), fields.Everything()) if !errors.IsForbidden(err) { t.Fatalf("unexpected error: %v", err) } }
// Update performs an atomic update and set of the object. Returns the result of the update // or an error. If the registry allows create-on-update, the create flow will be executed. // A bool is returned along with the object and any errors, to indicate object creation. func (e *Etcd) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { trace := util.NewTrace("Update " + reflect.TypeOf(obj).String()) defer trace.LogIfLong(time.Second) name, err := e.ObjectNameFunc(obj) if err != nil { return nil, false, err } key, err := e.KeyFunc(ctx, name) if err != nil { return nil, false, err } // If AllowUnconditionalUpdate() is true and the object specified by the user does not have a resource version, // then we populate it with the latest version. // Else, we check that the version specified by the user matches the version of latest etcd object. resourceVersion, err := e.Storage.Versioner().ObjectResourceVersion(obj) if err != nil { return nil, false, err } doUnconditionalUpdate := resourceVersion == 0 && e.UpdateStrategy.AllowUnconditionalUpdate() // TODO: expose TTL creating := false out := e.NewFunc() err = e.Storage.GuaranteedUpdate(key, out, true, func(existing runtime.Object, res storage.ResponseMeta) (runtime.Object, *uint64, error) { version, err := e.Storage.Versioner().ObjectResourceVersion(existing) if err != nil { return nil, nil, err } if version == 0 { if !e.UpdateStrategy.AllowCreateOnUpdate() { return nil, nil, kubeerr.NewNotFound(e.EndpointName, name) } creating = true if err := rest.BeforeCreate(e.CreateStrategy, ctx, obj); err != nil { return nil, nil, err } ttl, err := e.calculateTTL(obj, 0, false) if err != nil { return nil, nil, err } return obj, &ttl, nil } creating = false if doUnconditionalUpdate { // Update the object's resource version to match the latest etcd object's resource version. err = e.Storage.Versioner().UpdateObject(obj, res.Expiration, res.ResourceVersion) if err != nil { return nil, nil, err } } else { // Check if the object's resource version matches the latest resource version. newVersion, err := e.Storage.Versioner().ObjectResourceVersion(obj) if err != nil { return nil, nil, err } if newVersion != version { return nil, nil, kubeerr.NewConflict(e.EndpointName, name, fmt.Errorf("the object has been modified; please apply your changes to the latest version and try again")) } } if err := rest.BeforeUpdate(e.UpdateStrategy, ctx, obj, existing); err != nil { return nil, nil, err } ttl, err := e.calculateTTL(obj, res.TTL, true) if err != nil { return nil, nil, err } if int64(ttl) != res.TTL { return obj, &ttl, nil } return obj, nil, nil }) if err != nil { if creating { err = etcderr.InterpretCreateError(err, e.EndpointName, name) err = rest.CheckGeneratedNameError(e.CreateStrategy, err, obj) } else { err = etcderr.InterpretUpdateError(err, e.EndpointName, name) } return nil, false, err } if creating { if e.AfterCreate != nil { if err := e.AfterCreate(out); err != nil { return nil, false, err } } } else { if e.AfterUpdate != nil { if err := e.AfterUpdate(out); err != nil { return nil, false, err } } } if e.Decorator != nil { if err := e.Decorator(obj); err != nil { return nil, false, err } } return out, creating, nil }