update StatusDetails to handle Groups

This commit is contained in:
deads2k
2015-12-10 13:32:29 -05:00
parent 5c4479f542
commit 9fda7f1812
75 changed files with 303 additions and 238 deletions

View File

@@ -68,7 +68,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
// Matches objects based on labels/fields for list and watch
PredicateFunc: configmap.MatchConfigMap,
EndpointName: "configmaps",
QualifiedResource: extensions.Resource("configmaps"),
CreateStrategy: configmap.Strategy,
UpdateStrategy: configmap.Strategy,

View File

@@ -62,7 +62,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return controller.MatchController(label, field)
},
EndpointName: "replicationControllers",
QualifiedResource: api.Resource("replicationcontrollers"),
// Used to validate controller creation
CreateStrategy: controller.Strategy,

View File

@@ -64,7 +64,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return daemonset.MatchDaemonSet(label, field)
},
EndpointName: "daemonsets",
QualifiedResource: extensions.Resource("daemonsets"),
// Used to validate daemon set creation
CreateStrategy: daemonset.Strategy,

View File

@@ -86,7 +86,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return deployment.MatchDeployment(label, field)
},
EndpointName: "deployments",
QualifiedResource: extensions.Resource("deployments"),
// Used to validate deployment creation.
CreateStrategy: deployment.Strategy,
@@ -130,7 +130,7 @@ func (r *ScaleREST) New() runtime.Object {
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 nil, errors.NewNotFound(extensions.Resource("deployments/scale"), name)
}
return extensions.ScaleFromDeployment(deployment), nil
}
@@ -145,17 +145,17 @@ func (r *ScaleREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object,
}
if errs := extvalidation.ValidateScale(scale); len(errs) > 0 {
return nil, false, errors.NewInvalid("scale", scale.Name, errs)
return nil, false, errors.NewInvalid(extensions.Kind("Scale"), scale.Name, errs)
}
deployment, err := (*r.registry).GetDeployment(ctx, scale.Name)
if err != nil {
return nil, false, errors.NewNotFound("scale", scale.Name)
return nil, false, errors.NewNotFound(extensions.Resource("deployments/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 nil, false, errors.NewConflict(extensions.Resource("deployments/scale"), scale.Name, err)
}
return extensions.ScaleFromDeployment(deployment), false, nil
}

View File

@@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return endpoint.MatchEndpoints(label, field)
},
EndpointName: "endpoints",
QualifiedResource: api.Resource("endpoints"),
CreateStrategy: endpoint.Strategy,
UpdateStrategy: endpoint.Strategy,

View File

@@ -57,7 +57,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator, ttl
TTLFunc: func(runtime.Object, uint64, bool) (uint64, error) {
return ttl, nil
},
EndpointName: "events",
QualifiedResource: api.Resource("events"),
CreateStrategy: event.Strategy,
UpdateStrategy: event.Strategy,

View File

@@ -66,7 +66,7 @@ func (r *ScaleREST) New() runtime.Object {
func (r *ScaleREST) Get(ctx api.Context, name string) (runtime.Object, error) {
rc, err := (*r.registry).GetController(ctx, name)
if err != nil {
return nil, errors.NewNotFound("scale", name)
return nil, errors.NewNotFound(extensions.Resource("replicationcontrollers/scale"), name)
}
return &extensions.Scale{
ObjectMeta: api.ObjectMeta{
@@ -94,17 +94,17 @@ func (r *ScaleREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object,
}
if errs := extvalidation.ValidateScale(scale); len(errs) > 0 {
return nil, false, errors.NewInvalid("scale", scale.Name, errs)
return nil, false, errors.NewInvalid(extensions.Kind("Scale"), scale.Name, errs)
}
rc, err := (*r.registry).GetController(ctx, scale.Name)
if err != nil {
return nil, false, errors.NewNotFound("scale", scale.Name)
return nil, false, errors.NewNotFound(extensions.Resource("replicationcontrollers/scale"), scale.Name)
}
rc.Spec.Replicas = scale.Spec.Replicas
rc, err = (*r.registry).UpdateController(ctx, rc)
if err != nil {
return nil, false, errors.NewConflict("scale", scale.Name, err)
return nil, false, errors.NewConflict(extensions.Resource("replicationcontrollers/scale"), scale.Name, err)
}
return &extensions.Scale{
ObjectMeta: api.ObjectMeta{

View File

@@ -63,7 +63,7 @@ type Etcd struct {
NewListFunc func() runtime.Object
// Used for error reporting
EndpointName string
QualifiedResource unversioned.GroupResource
// Used for listing/watching; should not include trailing "/"
KeyRootFunc func(ctx api.Context) string
@@ -181,7 +181,7 @@ func (e *Etcd) ListPredicate(ctx api.Context, m generic.Matcher, options *unvers
if name, ok := m.MatchesSingle(); ok {
if key, err := e.KeyFunc(ctx, name); err == nil {
err := e.Storage.GetToList(ctx, key, filterFunc, list)
return list, etcderr.InterpretListError(err, e.EndpointName)
return list, etcderr.InterpretListError(err, e.QualifiedResource)
}
// if we cannot extract a key based on the current context, the optimization is skipped
}
@@ -190,7 +190,7 @@ func (e *Etcd) ListPredicate(ctx api.Context, m generic.Matcher, options *unvers
options = &unversioned.ListOptions{ResourceVersion: "0"}
}
err := e.Storage.List(ctx, e.KeyRootFunc(ctx), options.ResourceVersion, filterFunc, list)
return list, etcderr.InterpretListError(err, e.EndpointName)
return list, etcderr.InterpretListError(err, e.QualifiedResource)
}
// Create inserts a new item according to the unique key from the object.
@@ -212,7 +212,7 @@ func (e *Etcd) Create(ctx api.Context, obj runtime.Object) (runtime.Object, erro
}
out := e.NewFunc()
if err := e.Storage.Create(ctx, key, obj, out, ttl); err != nil {
err = etcderr.InterpretCreateError(err, e.EndpointName, name)
err = etcderr.InterpretCreateError(err, e.QualifiedResource, name)
err = rest.CheckGeneratedNameError(e.CreateStrategy, err, obj)
return nil, err
}
@@ -259,7 +259,7 @@ func (e *Etcd) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool
}
if version == 0 {
if !e.UpdateStrategy.AllowCreateOnUpdate() {
return nil, nil, kubeerr.NewNotFound(e.EndpointName, name)
return nil, nil, kubeerr.NewNotFound(e.QualifiedResource, name)
}
creating = true
if err := rest.BeforeCreate(e.CreateStrategy, ctx, obj); err != nil {
@@ -286,7 +286,7 @@ func (e *Etcd) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool
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"))
return nil, nil, kubeerr.NewConflict(e.QualifiedResource, 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 {
@@ -304,10 +304,10 @@ func (e *Etcd) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool
if err != nil {
if creating {
err = etcderr.InterpretCreateError(err, e.EndpointName, name)
err = etcderr.InterpretCreateError(err, e.QualifiedResource, name)
err = rest.CheckGeneratedNameError(e.CreateStrategy, err, obj)
} else {
err = etcderr.InterpretUpdateError(err, e.EndpointName, name)
err = etcderr.InterpretUpdateError(err, e.QualifiedResource, name)
}
return nil, false, err
}
@@ -340,7 +340,7 @@ func (e *Etcd) Get(ctx api.Context, name string) (runtime.Object, error) {
return nil, err
}
if err := e.Storage.Get(ctx, key, obj, false); err != nil {
return nil, etcderr.InterpretGetError(err, e.EndpointName, name)
return nil, etcderr.InterpretGetError(err, e.QualifiedResource, name)
}
if e.Decorator != nil {
if err := e.Decorator(obj); err != nil {
@@ -364,7 +364,7 @@ func (e *Etcd) Delete(ctx api.Context, name string, options *api.DeleteOptions)
obj := e.NewFunc()
if err := e.Storage.Get(ctx, key, obj, false); err != nil {
return nil, etcderr.InterpretDeleteError(err, e.EndpointName, name)
return nil, etcderr.InterpretDeleteError(err, e.QualifiedResource, name)
}
// support older consumers of delete by treating "nil" as delete immediately
@@ -410,14 +410,14 @@ func (e *Etcd) Delete(ctx api.Context, name string, options *api.DeleteOptions)
case errAlreadyDeleting:
return e.finalizeDelete(obj, true)
default:
return nil, etcderr.InterpretUpdateError(err, e.EndpointName, name)
return nil, etcderr.InterpretUpdateError(err, e.QualifiedResource, name)
}
}
// delete immediately, or no graceful deletion supported
out := e.NewFunc()
if err := e.Storage.Delete(ctx, key, out); err != nil {
return nil, etcderr.InterpretDeleteError(err, e.EndpointName, name)
return nil, etcderr.InterpretDeleteError(err, e.QualifiedResource, name)
}
return e.finalizeDelete(out, true)
}

View File

@@ -92,11 +92,11 @@ func NewTestGenericEtcdRegistry(t *testing.T) (*etcdtesting.EtcdTestServer, *Etc
strategy := &testRESTStrategy{api.Scheme, api.SimpleNameGenerator, true, false, true}
return server, &Etcd{
NewFunc: func() runtime.Object { return &api.Pod{} },
NewListFunc: func() runtime.Object { return &api.PodList{} },
EndpointName: "pods",
CreateStrategy: strategy,
UpdateStrategy: strategy,
NewFunc: func() runtime.Object { return &api.Pod{} },
NewListFunc: func() runtime.Object { return &api.PodList{} },
QualifiedResource: api.Resource("pods"),
CreateStrategy: strategy,
UpdateStrategy: strategy,
KeyRootFunc: func(ctx api.Context) string {
return podPrefix
},

View File

@@ -23,6 +23,7 @@ import (
"net/http"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/unversioned"
)
// Check the http error status from a location URL.
@@ -39,8 +40,8 @@ const (
// A generic http response checker to transform the error.
type GenericHttpResponseChecker struct {
Kind string
Name string
QualifiedResource unversioned.GroupResource
Name string
}
func (checker GenericHttpResponseChecker) Check(resp *http.Response) error {
@@ -58,13 +59,13 @@ func (checker GenericHttpResponseChecker) Check(resp *http.Response) error {
case resp.StatusCode == http.StatusBadRequest:
return errors.NewBadRequest(bodyText)
case resp.StatusCode == http.StatusNotFound:
return errors.NewGenericServerResponse(resp.StatusCode, "", checker.Kind, checker.Name, bodyText, 0, false)
return errors.NewGenericServerResponse(resp.StatusCode, "", checker.QualifiedResource, checker.Name, bodyText, 0, false)
}
return errors.NewGenericServerResponse(resp.StatusCode, "", checker.Kind, checker.Name, bodyText, 0, false)
return errors.NewGenericServerResponse(resp.StatusCode, "", checker.QualifiedResource, checker.Name, bodyText, 0, false)
}
return nil
}
func NewGenericHttpResponseChecker(kind, name string) GenericHttpResponseChecker {
return GenericHttpResponseChecker{Kind: kind, Name: name}
func NewGenericHttpResponseChecker(qualifiedResource unversioned.GroupResource, name string) GenericHttpResponseChecker {
return GenericHttpResponseChecker{QualifiedResource: qualifiedResource, Name: name}
}

View File

@@ -25,11 +25,12 @@ import (
"strings"
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
)
func TestGenericHttpResponseChecker(t *testing.T) {
responseChecker := NewGenericHttpResponseChecker("Pod", "foo")
responseChecker := NewGenericHttpResponseChecker(api.Resource("pods"), "foo")
tests := []struct {
resp *http.Response
expectError bool
@@ -78,7 +79,7 @@ func TestGenericHttpResponseChecker(t *testing.T) {
}
func TestGenericHttpResponseCheckerLimitReader(t *testing.T) {
responseChecker := NewGenericHttpResponseChecker("Pod", "foo")
responseChecker := NewGenericHttpResponseChecker(api.Resource("pods"), "foo")
excessedString := strings.Repeat("a", (maxReadLength + 10000))
resp := &http.Response{
Body: ioutil.NopCloser(bytes.NewBufferString(excessedString)),

View File

@@ -27,6 +27,7 @@ import (
"reflect"
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
)
@@ -131,7 +132,7 @@ func TestInputStreamInternalServerErrorTransport(t *testing.T) {
streamer := &LocationStreamer{
Location: location,
Transport: fakeInternalServerErrorTransport("text/plain", message),
ResponseChecker: NewGenericHttpResponseChecker("", ""),
ResponseChecker: NewGenericHttpResponseChecker(api.Resource(""), ""),
}
expectedError := errors.NewInternalError(fmt.Errorf("%s", message))

View File

@@ -62,7 +62,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return horizontalpodautoscaler.MatchAutoscaler(label, field)
},
EndpointName: "horizontalPodAutoscalers",
QualifiedResource: extensions.Resource("horizontalpodautoscalers"),
// Used to validate autoscaler creation
CreateStrategy: horizontalpodautoscaler.Strategy,

View File

@@ -64,7 +64,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return ingress.MatchIngress(label, field)
},
EndpointName: "ingresses",
QualifiedResource: extensions.Resource("ingresses"),
// Used to validate controller creation
CreateStrategy: ingress.Strategy,

View File

@@ -64,7 +64,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return job.MatchJob(label, field)
},
EndpointName: "jobs",
QualifiedResource: extensions.Resource("jobs"),
// Used to validate job creation
CreateStrategy: job.Strategy,

View File

@@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return limitrange.MatchLimitRange(label, field)
},
EndpointName: "limitranges",
QualifiedResource: api.Resource("limitranges"),
CreateStrategy: limitrange.Strategy,
UpdateStrategy: limitrange.Strategy,

View File

@@ -70,7 +70,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return namespace.MatchNamespace(label, field)
},
EndpointName: "namespaces",
QualifiedResource: api.Resource("namespaces"),
CreateStrategy: namespace.Strategy,
UpdateStrategy: namespace.Strategy,
@@ -108,7 +108,7 @@ func (r *REST) Delete(ctx api.Context, name string, options *api.DeleteOptions)
// prior to final deletion, we must ensure that finalizers is empty
if len(namespace.Spec.Finalizers) != 0 {
err = apierrors.NewConflict("Namespace", 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."))
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.Etcd.Delete(ctx, name, nil)

View File

@@ -71,8 +71,8 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator, con
ObjectNameFunc: func(obj runtime.Object) (string, error) {
return obj.(*api.Node).Name, nil
},
PredicateFunc: node.MatchNode,
EndpointName: "node",
PredicateFunc: node.MatchNode,
QualifiedResource: api.Resource("nodes"),
CreateStrategy: node.Strategy,
UpdateStrategy: node.Strategy,

View File

@@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return persistentvolume.MatchPersistentVolumes(label, field)
},
EndpointName: "persistentvolume",
QualifiedResource: api.Resource("persistentvolumes"),
CreateStrategy: persistentvolume.Strategy,
UpdateStrategy: persistentvolume.Strategy,

View File

@@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return persistentvolumeclaim.MatchPersistentVolumeClaim(label, field)
},
EndpointName: "persistentvolumeclaims",
QualifiedResource: api.Resource("persistentvolumeclaims"),
CreateStrategy: persistentvolumeclaim.Strategy,
UpdateStrategy: persistentvolumeclaim.Strategy,

View File

@@ -84,7 +84,7 @@ func NewStorage(
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return pod.MatchPod(label, field)
},
EndpointName: "pods",
QualifiedResource: api.Resource("pods"),
CreateStrategy: pod.Strategy,
UpdateStrategy: pod.Strategy,
@@ -178,10 +178,10 @@ func (r *BindingREST) setPodHostAndAnnotations(ctx api.Context, podID, oldMachin
// 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 = etcderr.InterpretGetError(err, "pod", podID)
err = etcderr.InterpretUpdateError(err, "pod", podID)
err = etcderr.InterpretGetError(err, api.Resource("pods"), podID)
err = etcderr.InterpretUpdateError(err, api.Resource("pods"), podID)
if _, ok := err.(*errors.StatusError); !ok {
err = errors.NewConflict("binding", podID, err)
err = errors.NewConflict(api.Resource("pods/binding"), podID, err)
}
}
return

View File

@@ -354,7 +354,7 @@ func TestEtcdCreateBindingNoPod(t *testing.T) {
if err == nil {
t.Fatalf("Expected not-found-error but got nothing")
}
if !errors.IsNotFound(etcderrors.InterpretGetError(err, "Pod", "foo")) {
if !errors.IsNotFound(etcderrors.InterpretGetError(err, api.Resource("pods"), "foo")) {
t.Fatalf("Unexpected error returned: %#v", err)
}
@@ -362,7 +362,7 @@ func TestEtcdCreateBindingNoPod(t *testing.T) {
if err == nil {
t.Fatalf("Expected not-found-error but got nothing")
}
if !errors.IsNotFound(etcderrors.InterpretGetError(err, "Pod", "foo")) {
if !errors.IsNotFound(etcderrors.InterpretGetError(err, api.Resource("pods"), "foo")) {
t.Fatalf("Unexpected error: %v", err)
}
}

View File

@@ -52,7 +52,7 @@ func (r *LogREST) Get(ctx api.Context, name string, opts runtime.Object) (runtim
return nil, fmt.Errorf("invalid options object: %#v", opts)
}
if errs := validation.ValidatePodLogOptions(logOpts); len(errs) > 0 {
return nil, errors.NewInvalid("podlogs", name, errs)
return nil, errors.NewInvalid(api.Kind("PodLogOptions"), name, errs)
}
location, transport, err := pod.LogLocation(r.Store, r.KubeletConn, ctx, name, logOpts)
if err != nil {
@@ -63,7 +63,7 @@ func (r *LogREST) Get(ctx api.Context, name string, opts runtime.Object) (runtim
Transport: transport,
ContentType: "text/plain",
Flush: logOpts.Follow,
ResponseChecker: genericrest.NewGenericHttpResponseChecker("Pod", name),
ResponseChecker: genericrest.NewGenericHttpResponseChecker(api.Resource("pods/log"), name),
}, nil
}

View File

@@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return podtemplate.MatchPodTemplate(label, field)
},
EndpointName: "podtemplates",
QualifiedResource: api.Resource("podtemplates"),
CreateStrategy: podtemplate.Strategy,
UpdateStrategy: podtemplate.Strategy,

View File

@@ -57,7 +57,7 @@ func (e *EndpointRegistry) GetEndpoints(ctx api.Context, name string) (*api.Endp
}
}
}
return nil, errors.NewNotFound("Endpoints", name)
return nil, errors.NewNotFound(api.Resource("endpoints"), name)
}
func (e *EndpointRegistry) WatchEndpoints(ctx api.Context, options *unversioned.ListOptions) (watch.Interface, error) {

View File

@@ -95,7 +95,7 @@ func (r *NodeRegistry) GetNode(ctx api.Context, nodeID string) (*api.Node, error
return &node, nil
}
}
return nil, errors.NewNotFound("node", nodeID)
return nil, errors.NewNotFound(api.Resource("nodes"), nodeID)
}
func (r *NodeRegistry) DeleteNode(ctx api.Context, nodeID string) error {

View File

@@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) (*R
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return resourcequota.MatchResourceQuota(label, field)
},
EndpointName: "resourcequotas",
QualifiedResource: api.Resource("resourcequotas"),
CreateStrategy: resourcequota.Strategy,
UpdateStrategy: resourcequota.Strategy,

View File

@@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return secret.Matcher(label, field)
},
EndpointName: "secrets",
QualifiedResource: api.Resource("secrets"),
CreateStrategy: secret.Strategy,
UpdateStrategy: secret.Strategy,

View File

@@ -88,7 +88,7 @@ func (s strategy) Export(obj runtime.Object, exact bool) error {
errs := []*field.Error{
field.Invalid(field.NewPath("type"), t, "can not export service account secrets"),
}
return errors.NewInvalid("Secret", t.Name, errs)
return errors.NewInvalid(api.Kind("Secret"), t.Name, errs)
}
return nil
}

View File

@@ -24,6 +24,7 @@ import (
"k8s.io/kubernetes/pkg/api"
k8serr "k8s.io/kubernetes/pkg/api/errors"
etcderr "k8s.io/kubernetes/pkg/api/errors/etcd"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/registry/service"
"k8s.io/kubernetes/pkg/registry/service/allocator"
"k8s.io/kubernetes/pkg/runtime"
@@ -47,8 +48,8 @@ type Etcd struct {
storage storage.Interface
last string
baseKey string
kind string
baseKey string
resource unversioned.GroupResource
}
// Etcd implements allocator.Interface and service.RangeRegistry
@@ -57,12 +58,12 @@ var _ service.RangeRegistry = &Etcd{}
// NewEtcd returns an allocator that is backed by Etcd and can manage
// persisting the snapshot state of allocation after each allocation is made.
func NewEtcd(alloc allocator.Snapshottable, baseKey string, kind string, storage storage.Interface) *Etcd {
func NewEtcd(alloc allocator.Snapshottable, baseKey string, resource unversioned.GroupResource, storage storage.Interface) *Etcd {
return &Etcd{
alloc: alloc,
storage: storage,
baseKey: baseKey,
kind: kind,
alloc: alloc,
storage: storage,
baseKey: baseKey,
resource: resource,
}
}
@@ -146,7 +147,7 @@ func (e *Etcd) tryUpdate(fn func() error) error {
storage.SimpleUpdate(func(input runtime.Object) (output runtime.Object, err error) {
existing := input.(*api.RangeAllocation)
if len(existing.ResourceVersion) == 0 {
return nil, fmt.Errorf("cannot allocate resources of type %s at this time", e.kind)
return nil, fmt.Errorf("cannot allocate resources of type %s at this time", e.resource.String())
}
if existing.ResourceVersion != e.last {
if err := e.alloc.Restore(existing.Range, existing.Data); err != nil {
@@ -163,7 +164,7 @@ func (e *Etcd) tryUpdate(fn func() error) error {
return existing, nil
}),
)
return etcderr.InterpretUpdateError(err, e.kind, "")
return etcderr.InterpretUpdateError(err, e.resource, "")
}
// Refresh reloads the RangeAllocation from etcd.
@@ -176,7 +177,7 @@ func (e *Etcd) Refresh() (*api.RangeAllocation, error) {
if storage.IsNotFound(err) {
return nil, nil
}
return nil, etcderr.InterpretGetError(err, e.kind, "")
return nil, etcderr.InterpretGetError(err, e.resource, "")
}
return existing, nil
@@ -187,7 +188,7 @@ func (e *Etcd) Refresh() (*api.RangeAllocation, error) {
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, etcderr.InterpretGetError(err, e.kind, "")
return nil, etcderr.InterpretGetError(err, e.resource, "")
}
return existing, nil
}
@@ -205,17 +206,17 @@ func (e *Etcd) CreateOrUpdate(snapshot *api.RangeAllocation) error {
switch {
case len(snapshot.ResourceVersion) != 0 && len(existing.ResourceVersion) != 0:
if snapshot.ResourceVersion != existing.ResourceVersion {
return nil, k8serr.NewConflict(e.kind, "", fmt.Errorf("the provided resource version does not match"))
return nil, k8serr.NewConflict(e.resource, "", fmt.Errorf("the provided resource version does not match"))
}
case len(existing.ResourceVersion) != 0:
return nil, k8serr.NewConflict(e.kind, "", fmt.Errorf("another caller has already initialized the resource"))
return nil, k8serr.NewConflict(e.resource, "", fmt.Errorf("another caller has already initialized the resource"))
}
last = snapshot.ResourceVersion
return snapshot, nil
}),
)
if err != nil {
return etcderr.InterpretUpdateError(err, e.kind, "")
return etcderr.InterpretUpdateError(err, e.resource, "")
}
err = e.alloc.Restore(snapshot.Range, snapshot.Data)
if err == nil {

View File

@@ -32,7 +32,7 @@ import (
func newStorage(t *testing.T) (*Etcd, *etcdtesting.EtcdTestServer, allocator.Interface) {
etcdStorage, server := registrytest.NewEtcdStorage(t, "")
mem := allocator.NewAllocationMap(100, "rangeSpecValue")
etcd := NewEtcd(mem, "/ranges/serviceips", "serviceipallocation", etcdStorage)
etcd := NewEtcd(mem, "/ranges/serviceips", api.Resource("serviceipallocations"), etcdStorage)
return etcd, server, mem
}
@@ -50,7 +50,7 @@ func key() string {
func TestEmpty(t *testing.T) {
storage, server, _ := newStorage(t)
defer server.Terminate(t)
if _, err := storage.Allocate(1); !strings.Contains(err.Error(), "cannot allocate resources of type serviceipallocation at this time") {
if _, err := storage.Allocate(1); !strings.Contains(err.Error(), "cannot allocate resources of type serviceipallocations at this time") {
t.Fatal(err)
}
}
@@ -93,7 +93,7 @@ func TestStore(t *testing.T) {
}
other = allocator.NewAllocationMap(100, "rangeSpecValue")
otherStorage := NewEtcd(other, "/ranges/serviceips", "serviceipallocation", storage.storage)
otherStorage := NewEtcd(other, "/ranges/serviceips", api.Resource("serviceipallocations"), storage.storage)
if ok, err := otherStorage.Allocate(2); ok || err != nil {
t.Fatal(err)
}

View File

@@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return service.MatchServices(label, field)
},
EndpointName: "services",
QualifiedResource: api.Resource("services"),
CreateStrategy: service.Strategy,
UpdateStrategy: service.Strategy,

View File

@@ -44,7 +44,7 @@ func newStorage(t *testing.T) (*etcdtesting.EtcdTestServer, ipallocator.Interfac
storage := ipallocator.NewAllocatorCIDRRange(cidr, func(max int, rangeSpec string) allocator.Interface {
mem := allocator.NewAllocationMap(max, rangeSpec)
backing = mem
etcd := allocatoretcd.NewEtcd(mem, "/ranges/serviceips", "serviceipallocation", etcdStorage)
etcd := allocatoretcd.NewEtcd(mem, "/ranges/serviceips", api.Resource("serviceipallocations"), etcdStorage)
return etcd
})
@@ -66,7 +66,7 @@ func key() string {
func TestEmpty(t *testing.T) {
server, storage, _, _ := newStorage(t)
defer server.Terminate(t)
if err := storage.Allocate(net.ParseIP("192.168.1.2")); !strings.Contains(err.Error(), "cannot allocate resources of type serviceipallocation at this time") {
if err := storage.Allocate(net.ParseIP("192.168.1.2")); !strings.Contains(err.Error(), "cannot allocate resources of type serviceipallocations at this time") {
t.Fatal(err)
}
}

View File

@@ -96,7 +96,7 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, err
if err := rs.serviceIPs.Allocate(net.ParseIP(service.Spec.ClusterIP)); err != nil {
// TODO: when validation becomes versioned, this gets more complicated.
el := field.ErrorList{field.Invalid(field.NewPath("spec", "clusterIP"), service.Spec.ClusterIP, err.Error())}
return nil, errors.NewInvalid("Service", service.Name, el)
return nil, errors.NewInvalid(api.Kind("Service"), service.Name, el)
}
releaseServiceIP = true
}
@@ -109,7 +109,7 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, err
if err != nil {
// TODO: when validation becomes versioned, this gets more complicated.
el := field.ErrorList{field.Invalid(field.NewPath("spec", "ports").Index(i).Child("nodePort"), servicePort.NodePort, err.Error())}
return nil, errors.NewInvalid("Service", service.Name, el)
return nil, errors.NewInvalid(api.Kind("Service"), service.Name, el)
}
} else if assignNodePorts {
nodePort, err := nodePortOp.AllocateNext()
@@ -199,7 +199,7 @@ func (*REST) NewList() runtime.Object {
func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) {
service := obj.(*api.Service)
if !api.ValidNamespace(ctx, &service.ObjectMeta) {
return nil, false, errors.NewConflict("service", service.Namespace, fmt.Errorf("Service.Namespace does not match the provided context"))
return nil, false, errors.NewConflict(api.Resource("services"), service.Namespace, fmt.Errorf("Service.Namespace does not match the provided context"))
}
oldService, err := rs.registry.GetService(ctx, service.Name)
@@ -210,7 +210,7 @@ func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, boo
// Copy over non-user fields
// TODO: make this a merge function
if errs := validation.ValidateServiceUpdate(service, oldService); len(errs) > 0 {
return nil, false, errors.NewInvalid("service", service.Name, errs)
return nil, false, errors.NewInvalid(api.Kind("Service"), service.Name, errs)
}
nodePortOp := portallocator.StartOperation(rs.serviceNodePorts)
@@ -230,7 +230,7 @@ func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, boo
err := nodePortOp.Allocate(nodePort)
if err != nil {
el := field.ErrorList{field.Invalid(field.NewPath("spec", "ports").Index(i).Child("nodePort"), nodePort, err.Error())}
return nil, false, errors.NewInvalid("Service", service.Name, el)
return nil, false, errors.NewInvalid(api.Kind("Service"), service.Name, el)
}
}
} else {

View File

@@ -105,17 +105,17 @@ func TestExportService(t *testing.T) {
}
func TestCheckGeneratedNameError(t *testing.T) {
expect := errors.NewNotFound("foo", "bar")
expect := errors.NewNotFound(api.Resource("foos"), "bar")
if err := rest.CheckGeneratedNameError(Strategy, expect, &api.Pod{}); err != expect {
t.Errorf("NotFoundError should be ignored: %v", err)
}
expect = errors.NewAlreadyExists("foo", "bar")
expect = errors.NewAlreadyExists(api.Resource("foos"), "bar")
if err := rest.CheckGeneratedNameError(Strategy, expect, &api.Pod{}); err != expect {
t.Errorf("AlreadyExists should be returned when no GenerateName field: %v", err)
}
expect = errors.NewAlreadyExists("foo", "bar")
expect = errors.NewAlreadyExists(api.Resource("foos"), "bar")
if err := rest.CheckGeneratedNameError(Strategy, expect, &api.Pod{ObjectMeta: api.ObjectMeta{GenerateName: "foo"}}); err == nil || !errors.IsServerTimeout(err) {
t.Errorf("expected try again later error: %v", err)
}

View File

@@ -54,7 +54,7 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return serviceaccount.Matcher(label, field)
},
EndpointName: "serviceaccounts",
QualifiedResource: api.Resource("serviceaccounts"),
CreateStrategy: serviceaccount.Strategy,
UpdateStrategy: serviceaccount.Strategy,

View File

@@ -55,9 +55,9 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *RE
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return thirdpartyresource.Matcher(label, field)
},
EndpointName: "thirdPartyResources",
CreateStrategy: thirdpartyresource.Strategy,
UpdateStrategy: thirdpartyresource.Strategy,
QualifiedResource: extensions.Resource("thirdpartyresources"),
CreateStrategy: thirdpartyresource.Strategy,
UpdateStrategy: thirdpartyresource.Strategy,
Storage: storageInterface,
}

View File

@@ -57,9 +57,9 @@ func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator, gro
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return thirdpartyresourcedata.Matcher(label, field)
},
EndpointName: "thirdpartyresourcedata",
CreateStrategy: thirdpartyresourcedata.Strategy,
UpdateStrategy: thirdpartyresourcedata.Strategy,
QualifiedResource: extensions.Resource("thirdpartyresourcedatas"),
CreateStrategy: thirdpartyresourcedata.Strategy,
UpdateStrategy: thirdpartyresourcedata.Strategy,
Storage: storageInterface,
}