Move REST* interfaces into pkg/api/rest

Dependency chain is now api -> api/rest -> apiserver.  Makes the
interfaces much cleaner to read, and cleans up some inconsistenties
that crept in along the way.
This commit is contained in:
Clayton Coleman 2015-03-21 12:24:16 -04:00
parent df672504c2
commit d46087db50
30 changed files with 216 additions and 187 deletions

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package apiserver package rest
import ( import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
@ -26,15 +26,15 @@ import (
// RESTStorage is a generic interface for RESTful storage services. // RESTStorage is a generic interface for RESTful storage services.
// Resources which are exported to the RESTful API of apiserver need to implement this interface. It is expected // Resources which are exported to the RESTful API of apiserver need to implement this interface. It is expected
// that objects may implement any of the REST* interfaces. // that objects may implement any of the below interfaces.
// TODO: implement dynamic introspection (so GenericREST objects can indicate what they implement) type Storage interface {
type RESTStorage interface {
// New returns an empty object that can be used with Create and Update after request data has been put into it. // New returns an empty object that can be used with Create and Update after request data has been put into it.
// This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object) // This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object)
New() runtime.Object New() runtime.Object
} }
type RESTLister interface { // Lister is an object that can retrieve resources that match the provided field and label criteria.
type Lister interface {
// NewList returns an empty object that can be used with the List call. // NewList returns an empty object that can be used with the List call.
// This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object) // This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object)
NewList() runtime.Object NewList() runtime.Object
@ -42,23 +42,27 @@ type RESTLister interface {
List(ctx api.Context, label labels.Selector, field fields.Selector) (runtime.Object, error) List(ctx api.Context, label labels.Selector, field fields.Selector) (runtime.Object, error)
} }
type RESTGetter interface { // Getter is an object that can retrieve a named RESTful resource.
// Get finds a resource in the storage by id and returns it. type Getter interface {
// Get finds a resource in the storage by name and returns it.
// Although it can return an arbitrary error value, IsNotFound(err) is true for the // Although it can return an arbitrary error value, IsNotFound(err) is true for the
// returned error value err when the specified resource is not found. // returned error value err when the specified resource is not found.
Get(ctx api.Context, id string) (runtime.Object, error) Get(ctx api.Context, name string) (runtime.Object, error)
} }
type RESTDeleter interface { // Deleter is an object that can delete a named RESTful resource.
type Deleter interface {
// Delete finds a resource in the storage and deletes it. // Delete finds a resource in the storage and deletes it.
// Although it can return an arbitrary error value, IsNotFound(err) is true for the // Although it can return an arbitrary error value, IsNotFound(err) is true for the
// returned error value err when the specified resource is not found. // returned error value err when the specified resource is not found.
// Delete *may* return the object that was deleted, or a status object indicating additional // Delete *may* return the object that was deleted, or a status object indicating additional
// information about deletion. // information about deletion.
Delete(ctx api.Context, id string) (runtime.Object, error) Delete(ctx api.Context, name string) (runtime.Object, error)
} }
type RESTGracefulDeleter interface { // GracefulDeleter knows how to pass deletion options to allow delayed deletion of a
// RESTful object.
type GracefulDeleter interface {
// Delete finds a resource in the storage and deletes it. // Delete finds a resource in the storage and deletes it.
// If options are provided, the resource will attempt to honor them or return an invalid // If options are provided, the resource will attempt to honor them or return an invalid
// request error. // request error.
@ -66,20 +70,21 @@ type RESTGracefulDeleter interface {
// returned error value err when the specified resource is not found. // returned error value err when the specified resource is not found.
// Delete *may* return the object that was deleted, or a status object indicating additional // Delete *may* return the object that was deleted, or a status object indicating additional
// information about deletion. // information about deletion.
Delete(ctx api.Context, id string, options *api.DeleteOptions) (runtime.Object, error) Delete(ctx api.Context, name string, options *api.DeleteOptions) (runtime.Object, error)
} }
// GracefulDeleteAdapter adapts the RESTDeleter interface to RESTGracefulDeleter // GracefulDeleteAdapter adapts the Deleter interface to GracefulDeleter
type GracefulDeleteAdapter struct { type GracefulDeleteAdapter struct {
RESTDeleter Deleter
} }
// Delete implements RESTGracefulDeleter in terms of RESTDeleter // Delete implements RESTGracefulDeleter in terms of Deleter
func (w GracefulDeleteAdapter) Delete(ctx api.Context, id string, options *api.DeleteOptions) (runtime.Object, error) { func (w GracefulDeleteAdapter) Delete(ctx api.Context, name string, options *api.DeleteOptions) (runtime.Object, error) {
return w.RESTDeleter.Delete(ctx, id) return w.Deleter.Delete(ctx, name)
} }
type RESTCreater interface { // Creater is an object that can create an instance of a RESTful object.
type Creater interface {
// New returns an empty object that can be used with Create after request data has been put into it. // New returns an empty object that can be used with Create after request data has been put into it.
// This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object) // This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object)
New() runtime.Object New() runtime.Object
@ -88,7 +93,8 @@ type RESTCreater interface {
Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error)
} }
type RESTUpdater interface { // Updater is an object that can update an instance of a RESTful object.
type Updater interface {
// New returns an empty object that can be used with Update after request data has been put into it. // New returns an empty object that can be used with Update after request data has been put into it.
// This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object) // This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object)
New() runtime.Object New() runtime.Object
@ -99,25 +105,24 @@ type RESTUpdater interface {
Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error)
} }
type RESTPatcher interface { // CreaterUpdater is a storage object that must support both create and update.
RESTGetter // Go prevents embedded interfaces that implement the same method.
RESTUpdater type CreaterUpdater interface {
Creater
Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error)
} }
// RESTResult indicates the result of a REST transformation. // CreaterUpdater must satisfy the Updater interface.
type RESTResult struct { var _ Updater = CreaterUpdater(nil)
// The result of this operation. May be nil if the operation has no meaningful
// result (like Delete)
runtime.Object
// May be set true to indicate that the Update operation resulted in the object type Patcher interface {
// being created. Getter
Created bool Updater
} }
// ResourceWatcher should be implemented by all RESTStorage objects that // Watcher should be implemented by all Storage objects that
// want to offer the ability to watch for changes through the watch api. // want to offer the ability to watch for changes through the watch api.
type ResourceWatcher interface { type Watcher interface {
// 'label' selects on labels; 'field' selects on the object's fields. Not all fields // 'label' selects on labels; 'field' selects on the object's fields. Not all fields
// are supported; an error should be returned if 'field' tries to select on a field that // are supported; an error should be returned if 'field' tries to select on a field that
// isn't supported. 'resourceVersion' allows for continuing/starting a watch at a // isn't supported. 'resourceVersion' allows for continuing/starting a watch at a
@ -125,8 +130,18 @@ type ResourceWatcher interface {
Watch(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) Watch(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error)
} }
// StandardStorage is an interface covering the common verbs. Provided for testing whether a
// resource satisfies the normal storage methods. Use Storage when passing opaque storage objects.
type StandardStorage interface {
Getter
Lister
CreaterUpdater
GracefulDeleter
Watcher
}
// Redirector know how to return a remote resource's location. // Redirector know how to return a remote resource's location.
type Redirector interface { type Redirector interface {
// ResourceLocation should return the remote location of the given resource, or an error. // ResourceLocation should return the remote location of the given resource, or an error.
ResourceLocation(ctx api.Context, id string) (remoteLocation string, err error) ResourceLocation(ctx api.Context, name string) (remoteLocation string, err error)
} }

View File

@ -22,21 +22,21 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
) )
type Tester struct { type Tester struct {
*testing.T *testing.T
storage apiserver.RESTStorage storage rest.Storage
storageError injectErrorFunc storageError injectErrorFunc
clusterScope bool clusterScope bool
} }
type injectErrorFunc func(err error) type injectErrorFunc func(err error)
func New(t *testing.T, storage apiserver.RESTStorage, storageError injectErrorFunc) *Tester { func New(t *testing.T, storage rest.Storage, storageError injectErrorFunc) *Tester {
return &Tester{ return &Tester{
T: t, T: t,
storage: storage, storage: storage,
@ -85,7 +85,7 @@ func (t *Tester) TestCreateResetsUserData(valid runtime.Object) {
objectMeta.UID = "bad-uid" objectMeta.UID = "bad-uid"
objectMeta.CreationTimestamp = now objectMeta.CreationTimestamp = now
obj, err := t.storage.(apiserver.RESTCreater).Create(api.NewDefaultContext(), valid) obj, err := t.storage.(rest.Creater).Create(api.NewDefaultContext(), valid)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
@ -111,7 +111,7 @@ func (t *Tester) TestCreateHasMetadata(valid runtime.Object) {
context = api.NewContext() context = api.NewContext()
} }
obj, err := t.storage.(apiserver.RESTCreater).Create(context, valid) obj, err := t.storage.(rest.Creater).Create(context, valid)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
@ -131,7 +131,7 @@ func (t *Tester) TestCreateGeneratesName(valid runtime.Object) {
objectMeta.GenerateName = "test-" objectMeta.GenerateName = "test-"
_, err = t.storage.(apiserver.RESTCreater).Create(api.NewDefaultContext(), valid) _, err = t.storage.(rest.Creater).Create(api.NewDefaultContext(), valid)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
@ -148,7 +148,7 @@ func (t *Tester) TestCreateGeneratesNameReturnsServerTimeout(valid runtime.Objec
objectMeta.GenerateName = "test-" objectMeta.GenerateName = "test-"
t.withStorageError(errors.NewAlreadyExists("kind", "thing"), func() { t.withStorageError(errors.NewAlreadyExists("kind", "thing"), func() {
_, err := t.storage.(apiserver.RESTCreater).Create(api.NewDefaultContext(), valid) _, err := t.storage.(rest.Creater).Create(api.NewDefaultContext(), valid)
if err == nil || !errors.IsServerTimeout(err) { if err == nil || !errors.IsServerTimeout(err) {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
@ -158,7 +158,7 @@ func (t *Tester) TestCreateGeneratesNameReturnsServerTimeout(valid runtime.Objec
func (t *Tester) TestCreateInvokesValidation(invalid ...runtime.Object) { func (t *Tester) TestCreateInvokesValidation(invalid ...runtime.Object) {
for i, obj := range invalid { for i, obj := range invalid {
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
_, err := t.storage.(apiserver.RESTCreater).Create(ctx, obj) _, err := t.storage.(rest.Creater).Create(ctx, obj)
if !errors.IsInvalid(err) { if !errors.IsInvalid(err) {
t.Errorf("%d: Expected to get an invalid resource error, got %v", i, err) t.Errorf("%d: Expected to get an invalid resource error, got %v", i, err)
} }
@ -173,7 +173,7 @@ func (t *Tester) TestCreateRejectsMismatchedNamespace(valid runtime.Object) {
objectMeta.Namespace = "not-default" objectMeta.Namespace = "not-default"
_, err = t.storage.(apiserver.RESTCreater).Create(api.NewDefaultContext(), valid) _, err = t.storage.(rest.Creater).Create(api.NewDefaultContext(), valid)
if err == nil { if err == nil {
t.Errorf("Expected an error, but we didn't get one") t.Errorf("Expected an error, but we didn't get one")
} else if strings.Contains(err.Error(), "Controller.Namespace does not match the provided context") { } else if strings.Contains(err.Error(), "Controller.Namespace does not match the provided context") {
@ -189,7 +189,7 @@ func (t *Tester) TestCreateRejectsNamespace(valid runtime.Object) {
objectMeta.Namespace = "not-default" objectMeta.Namespace = "not-default"
_, err = t.storage.(apiserver.RESTCreater).Create(api.NewDefaultContext(), valid) _, err = t.storage.(rest.Creater).Create(api.NewDefaultContext(), valid)
if err == nil { if err == nil {
t.Errorf("Expected an error, but we didn't get one") t.Errorf("Expected an error, but we didn't get one")
} else if strings.Contains(err.Error(), "Controller.Namespace does not match the provided context") { } else if strings.Contains(err.Error(), "Controller.Namespace does not match the provided context") {
@ -210,11 +210,11 @@ func (t *Tester) TestDeleteNoGraceful(createFn func() runtime.Object, wasGracefu
} }
ctx := api.WithNamespace(api.NewContext(), objectMeta.Namespace) ctx := api.WithNamespace(api.NewContext(), objectMeta.Namespace)
_, err = t.storage.(apiserver.RESTGracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(10)) _, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(10))
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
if _, err := t.storage.(apiserver.RESTGetter).Get(ctx, objectMeta.Name); !errors.IsNotFound(err) { if _, err := t.storage.(rest.Getter).Get(ctx, objectMeta.Name); !errors.IsNotFound(err) {
t.Errorf("unexpected error, object should not exist: %v", err) t.Errorf("unexpected error, object should not exist: %v", err)
} }
if wasGracefulFn() { if wasGracefulFn() {
@ -229,11 +229,11 @@ func (t *Tester) TestDeleteGracefulHasDefault(existing runtime.Object, expectedG
} }
ctx := api.WithNamespace(api.NewContext(), objectMeta.Namespace) ctx := api.WithNamespace(api.NewContext(), objectMeta.Namespace)
_, err = t.storage.(apiserver.RESTGracefulDeleter).Delete(ctx, objectMeta.Name, &api.DeleteOptions{}) _, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, &api.DeleteOptions{})
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
if _, err := t.storage.(apiserver.RESTGetter).Get(ctx, objectMeta.Name); err != nil { if _, err := t.storage.(rest.Getter).Get(ctx, objectMeta.Name); err != nil {
t.Errorf("unexpected error, object should exist: %v", err) t.Errorf("unexpected error, object should exist: %v", err)
} }
if !wasGracefulFn() { if !wasGracefulFn() {
@ -248,11 +248,11 @@ func (t *Tester) TestDeleteGracefulUsesZeroOnNil(existing runtime.Object, expect
} }
ctx := api.WithNamespace(api.NewContext(), objectMeta.Namespace) ctx := api.WithNamespace(api.NewContext(), objectMeta.Namespace)
_, err = t.storage.(apiserver.RESTGracefulDeleter).Delete(ctx, objectMeta.Name, nil) _, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, nil)
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
if _, err := t.storage.(apiserver.RESTGetter).Get(ctx, objectMeta.Name); !errors.IsNotFound(err) { if _, err := t.storage.(rest.Getter).Get(ctx, objectMeta.Name); !errors.IsNotFound(err) {
t.Errorf("unexpected error, object should exist: %v", err) t.Errorf("unexpected error, object should exist: %v", err)
} }
} }

View File

@ -28,6 +28,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/emicklei/go-restful" "github.com/emicklei/go-restful"
@ -94,7 +95,7 @@ func (a *APIInstaller) newWebService() *restful.WebService {
return ws return ws
} }
func (a *APIInstaller) registerResourceHandlers(path string, storage RESTStorage, ws *restful.WebService, watchHandler, redirectHandler, proxyHandler http.Handler) error { func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storage, ws *restful.WebService, watchHandler, redirectHandler, proxyHandler http.Handler) error {
admit := a.group.Admit admit := a.group.Admit
context := a.group.Context context := a.group.Context
@ -121,7 +122,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage RESTStorage
versionedObject := indirectArbitraryPointer(versionedPtr) versionedObject := indirectArbitraryPointer(versionedPtr)
var versionedList interface{} var versionedList interface{}
if lister, ok := storage.(RESTLister); ok { if lister, ok := storage.(rest.Lister); ok {
list := lister.NewList() list := lister.NewList()
_, listKind, err := a.group.Typer.ObjectVersionAndKind(list) _, listKind, err := a.group.Typer.ObjectVersionAndKind(list)
versionedListPtr, err := a.group.Creater.New(a.group.Version, listKind) versionedListPtr, err := a.group.Creater.New(a.group.Version, listKind)
@ -137,15 +138,15 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage RESTStorage
} }
// what verbs are supported by the storage, used to know what verbs we support per path // what verbs are supported by the storage, used to know what verbs we support per path
creater, isCreater := storage.(RESTCreater) creater, isCreater := storage.(rest.Creater)
lister, isLister := storage.(RESTLister) lister, isLister := storage.(rest.Lister)
getter, isGetter := storage.(RESTGetter) getter, isGetter := storage.(rest.Getter)
deleter, isDeleter := storage.(RESTDeleter) deleter, isDeleter := storage.(rest.Deleter)
gracefulDeleter, isGracefulDeleter := storage.(RESTGracefulDeleter) gracefulDeleter, isGracefulDeleter := storage.(rest.GracefulDeleter)
updater, isUpdater := storage.(RESTUpdater) updater, isUpdater := storage.(rest.Updater)
patcher, isPatcher := storage.(RESTPatcher) patcher, isPatcher := storage.(rest.Patcher)
_, isWatcher := storage.(ResourceWatcher) _, isWatcher := storage.(rest.Watcher)
_, isRedirector := storage.(Redirector) _, isRedirector := storage.(rest.Redirector)
var versionedDeleterObject runtime.Object var versionedDeleterObject runtime.Object
switch { switch {
@ -157,7 +158,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage RESTStorage
versionedDeleterObject = object versionedDeleterObject = object
isDeleter = true isDeleter = true
case isDeleter: case isDeleter:
gracefulDeleter = GracefulDeleteAdapter{deleter} gracefulDeleter = rest.GracefulDeleteAdapter{deleter}
} }
var ctxFn ContextFunc var ctxFn ContextFunc

View File

@ -30,6 +30,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/admission" "github.com/GoogleCloudPlatform/kubernetes/pkg/admission"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/healthz" "github.com/GoogleCloudPlatform/kubernetes/pkg/healthz"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
@ -90,12 +91,12 @@ type Mux interface {
HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))
} }
// APIGroupVersion is a helper for exposing RESTStorage objects as http.Handlers via go-restful // APIGroupVersion is a helper for exposing rest.Storage objects as http.Handlers via go-restful
// It handles URLs of the form: // It handles URLs of the form:
// /${storage_key}[/${object_name}] // /${storage_key}[/${object_name}]
// Where 'storage_key' points to a RESTStorage object stored in storage. // Where 'storage_key' points to a rest.Storage object stored in storage.
type APIGroupVersion struct { type APIGroupVersion struct {
Storage map[string]RESTStorage Storage map[string]rest.Storage
Root string Root string
Version string Version string

View File

@ -34,6 +34,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
apierrs "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" apierrs "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
@ -124,26 +125,26 @@ type defaultAPIServer struct {
} }
// uses the default settings // uses the default settings
func handle(storage map[string]RESTStorage) http.Handler { func handle(storage map[string]rest.Storage) http.Handler {
return handleInternal(storage, admissionControl, mapper, selfLinker) return handleInternal(storage, admissionControl, mapper, selfLinker)
} }
// tests with a deny admission controller // tests with a deny admission controller
func handleDeny(storage map[string]RESTStorage) http.Handler { func handleDeny(storage map[string]rest.Storage) http.Handler {
return handleInternal(storage, deny.NewAlwaysDeny(), mapper, selfLinker) return handleInternal(storage, deny.NewAlwaysDeny(), mapper, selfLinker)
} }
// tests using the new namespace scope mechanism // tests using the new namespace scope mechanism
func handleNamespaced(storage map[string]RESTStorage) http.Handler { func handleNamespaced(storage map[string]rest.Storage) http.Handler {
return handleInternal(storage, admissionControl, namespaceMapper, selfLinker) return handleInternal(storage, admissionControl, namespaceMapper, selfLinker)
} }
// tests using a custom self linker // tests using a custom self linker
func handleLinker(storage map[string]RESTStorage, selfLinker runtime.SelfLinker) http.Handler { func handleLinker(storage map[string]rest.Storage, selfLinker runtime.SelfLinker) http.Handler {
return handleInternal(storage, admissionControl, mapper, selfLinker) return handleInternal(storage, admissionControl, mapper, selfLinker)
} }
func handleInternal(storage map[string]RESTStorage, admissionControl admission.Interface, mapper meta.RESTMapper, selfLinker runtime.SelfLinker) http.Handler { func handleInternal(storage map[string]rest.Storage, admissionControl admission.Interface, mapper meta.RESTMapper, selfLinker runtime.SelfLinker) http.Handler {
group := &APIGroupVersion{ group := &APIGroupVersion{
Storage: storage, Storage: storage,
@ -365,7 +366,7 @@ func TestNotFound(t *testing.T) {
"watch missing storage": {"GET", "/api/version/watch/", http.StatusNotFound}, "watch missing storage": {"GET", "/api/version/watch/", http.StatusNotFound},
"watch with bad method": {"POST", "/api/version/watch/foo/bar", http.StatusMethodNotAllowed}, "watch with bad method": {"POST", "/api/version/watch/foo/bar", http.StatusMethodNotAllowed},
} }
handler := handle(map[string]RESTStorage{ handler := handle(map[string]rest.Storage{
"foo": &SimpleRESTStorage{}, "foo": &SimpleRESTStorage{},
}) })
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
@ -395,7 +396,7 @@ func (UnimplementedRESTStorage) New() runtime.Object {
return &Simple{} return &Simple{}
} }
// TestUnimplementedRESTStorage ensures that if a RESTStorage does not implement a given // TestUnimplementedRESTStorage ensures that if a rest.Storage does not implement a given
// method, that it is literally not registered with the server. In the past, // method, that it is literally not registered with the server. In the past,
// we registered everything, and returned method not supported if it didn't support // we registered everything, and returned method not supported if it didn't support
// a verb. Now we literally do not register a storage if it does not implement anything. // a verb. Now we literally do not register a storage if it does not implement anything.
@ -417,7 +418,7 @@ func TestUnimplementedRESTStorage(t *testing.T) {
"proxy object": {"GET", "/api/version/proxy/foo/bar", http.StatusNotFound}, "proxy object": {"GET", "/api/version/proxy/foo/bar", http.StatusNotFound},
"redirect object": {"GET", "/api/version/redirect/foo/bar", http.StatusNotFound}, "redirect object": {"GET", "/api/version/redirect/foo/bar", http.StatusNotFound},
} }
handler := handle(map[string]RESTStorage{ handler := handle(map[string]rest.Storage{
"foo": UnimplementedRESTStorage{}, "foo": UnimplementedRESTStorage{},
}) })
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
@ -444,7 +445,7 @@ func TestUnimplementedRESTStorage(t *testing.T) {
} }
func TestVersion(t *testing.T) { func TestVersion(t *testing.T) {
handler := handle(map[string]RESTStorage{}) handler := handle(map[string]rest.Storage{})
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
defer server.Close() defer server.Close()
client := http.Client{} client := http.Client{}
@ -487,7 +488,7 @@ func TestList(t *testing.T) {
{"/api/version/simple", "", "/api/version/simple", false}, {"/api/version/simple", "", "/api/version/simple", false},
} }
for i, testCase := range testCases { for i, testCase := range testCases {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{expectedResourceNamespace: testCase.namespace} simpleStorage := SimpleRESTStorage{expectedResourceNamespace: testCase.namespace}
storage["simple"] = &simpleStorage storage["simple"] = &simpleStorage
selfLinker := &setTestSelfLinker{ selfLinker := &setTestSelfLinker{
@ -525,7 +526,7 @@ func TestList(t *testing.T) {
} }
func TestErrorList(t *testing.T) { func TestErrorList(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{ simpleStorage := SimpleRESTStorage{
errors: map[string]error{"list": fmt.Errorf("test Error")}, errors: map[string]error{"list": fmt.Errorf("test Error")},
} }
@ -545,7 +546,7 @@ func TestErrorList(t *testing.T) {
} }
func TestNonEmptyList(t *testing.T) { func TestNonEmptyList(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{ simpleStorage := SimpleRESTStorage{
list: []Simple{ list: []Simple{
{ {
@ -593,7 +594,7 @@ func TestNonEmptyList(t *testing.T) {
} }
func TestSelfLinkSkipsEmptyName(t *testing.T) { func TestSelfLinkSkipsEmptyName(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{ simpleStorage := SimpleRESTStorage{
list: []Simple{ list: []Simple{
{ {
@ -640,7 +641,7 @@ func TestSelfLinkSkipsEmptyName(t *testing.T) {
} }
func TestGet(t *testing.T) { func TestGet(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{ simpleStorage := SimpleRESTStorage{
item: Simple{ item: Simple{
Other: "foo", Other: "foo",
@ -679,7 +680,7 @@ func TestGet(t *testing.T) {
} }
func TestGetAlternateSelfLink(t *testing.T) { func TestGetAlternateSelfLink(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{ simpleStorage := SimpleRESTStorage{
item: Simple{ item: Simple{
Other: "foo", Other: "foo",
@ -717,7 +718,7 @@ func TestGetAlternateSelfLink(t *testing.T) {
} }
func TestGetNamespaceSelfLink(t *testing.T) { func TestGetNamespaceSelfLink(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{ simpleStorage := SimpleRESTStorage{
item: Simple{ item: Simple{
Other: "foo", Other: "foo",
@ -754,7 +755,7 @@ func TestGetNamespaceSelfLink(t *testing.T) {
} }
} }
func TestGetMissing(t *testing.T) { func TestGetMissing(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{ simpleStorage := SimpleRESTStorage{
errors: map[string]error{"get": apierrs.NewNotFound("simple", "id")}, errors: map[string]error{"get": apierrs.NewNotFound("simple", "id")},
} }
@ -774,7 +775,7 @@ func TestGetMissing(t *testing.T) {
} }
func TestDelete(t *testing.T) { func TestDelete(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{} simpleStorage := SimpleRESTStorage{}
ID := "id" ID := "id"
storage["simple"] = &simpleStorage storage["simple"] = &simpleStorage
@ -797,7 +798,7 @@ func TestDelete(t *testing.T) {
} }
func TestDeleteWithOptions(t *testing.T) { func TestDeleteWithOptions(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{} simpleStorage := SimpleRESTStorage{}
ID := "id" ID := "id"
storage["simple"] = &simpleStorage storage["simple"] = &simpleStorage
@ -834,11 +835,11 @@ func TestDeleteWithOptions(t *testing.T) {
} }
func TestLegacyDelete(t *testing.T) { func TestLegacyDelete(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{} simpleStorage := SimpleRESTStorage{}
ID := "id" ID := "id"
storage["simple"] = LegacyRESTStorage{&simpleStorage} storage["simple"] = LegacyRESTStorage{&simpleStorage}
var _ RESTDeleter = storage["simple"].(LegacyRESTStorage) var _ rest.Deleter = storage["simple"].(LegacyRESTStorage)
handler := handle(storage) handler := handle(storage)
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
defer server.Close() defer server.Close()
@ -861,7 +862,7 @@ func TestLegacyDelete(t *testing.T) {
} }
func TestLegacyDeleteIgnoresOptions(t *testing.T) { func TestLegacyDeleteIgnoresOptions(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{} simpleStorage := SimpleRESTStorage{}
ID := "id" ID := "id"
storage["simple"] = LegacyRESTStorage{&simpleStorage} storage["simple"] = LegacyRESTStorage{&simpleStorage}
@ -893,7 +894,7 @@ func TestLegacyDeleteIgnoresOptions(t *testing.T) {
} }
func TestDeleteInvokesAdmissionControl(t *testing.T) { func TestDeleteInvokesAdmissionControl(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{} simpleStorage := SimpleRESTStorage{}
ID := "id" ID := "id"
storage["simple"] = &simpleStorage storage["simple"] = &simpleStorage
@ -913,7 +914,7 @@ func TestDeleteInvokesAdmissionControl(t *testing.T) {
} }
func TestDeleteMissing(t *testing.T) { func TestDeleteMissing(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
ID := "id" ID := "id"
simpleStorage := SimpleRESTStorage{ simpleStorage := SimpleRESTStorage{
errors: map[string]error{"delete": apierrs.NewNotFound("simple", ID)}, errors: map[string]error{"delete": apierrs.NewNotFound("simple", ID)},
@ -936,7 +937,7 @@ func TestDeleteMissing(t *testing.T) {
} }
func TestPatch(t *testing.T) { func TestPatch(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
ID := "id" ID := "id"
item := &Simple{ item := &Simple{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
@ -973,7 +974,7 @@ func TestPatch(t *testing.T) {
} }
func TestPatchRequiresMatchingName(t *testing.T) { func TestPatchRequiresMatchingName(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
ID := "id" ID := "id"
item := &Simple{ item := &Simple{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
@ -1000,7 +1001,7 @@ func TestPatchRequiresMatchingName(t *testing.T) {
} }
func TestUpdate(t *testing.T) { func TestUpdate(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{} simpleStorage := SimpleRESTStorage{}
ID := "id" ID := "id"
storage["simple"] = &simpleStorage storage["simple"] = &simpleStorage
@ -1043,7 +1044,7 @@ func TestUpdate(t *testing.T) {
} }
func TestUpdateInvokesAdmissionControl(t *testing.T) { func TestUpdateInvokesAdmissionControl(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{} simpleStorage := SimpleRESTStorage{}
ID := "id" ID := "id"
storage["simple"] = &simpleStorage storage["simple"] = &simpleStorage
@ -1076,7 +1077,7 @@ func TestUpdateInvokesAdmissionControl(t *testing.T) {
} }
func TestUpdateRequiresMatchingName(t *testing.T) { func TestUpdateRequiresMatchingName(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{} simpleStorage := SimpleRESTStorage{}
ID := "id" ID := "id"
storage["simple"] = &simpleStorage storage["simple"] = &simpleStorage
@ -1105,7 +1106,7 @@ func TestUpdateRequiresMatchingName(t *testing.T) {
} }
func TestUpdateAllowsMissingNamespace(t *testing.T) { func TestUpdateAllowsMissingNamespace(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{} simpleStorage := SimpleRESTStorage{}
ID := "id" ID := "id"
storage["simple"] = &simpleStorage storage["simple"] = &simpleStorage
@ -1138,7 +1139,7 @@ func TestUpdateAllowsMissingNamespace(t *testing.T) {
// when the object name and namespace can't be retrieved, skip name checking // when the object name and namespace can't be retrieved, skip name checking
func TestUpdateAllowsMismatchedNamespaceOnError(t *testing.T) { func TestUpdateAllowsMismatchedNamespaceOnError(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{} simpleStorage := SimpleRESTStorage{}
ID := "id" ID := "id"
storage["simple"] = &simpleStorage storage["simple"] = &simpleStorage
@ -1179,7 +1180,7 @@ func TestUpdateAllowsMismatchedNamespaceOnError(t *testing.T) {
} }
func TestUpdatePreventsMismatchedNamespace(t *testing.T) { func TestUpdatePreventsMismatchedNamespace(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
simpleStorage := SimpleRESTStorage{} simpleStorage := SimpleRESTStorage{}
ID := "id" ID := "id"
storage["simple"] = &simpleStorage storage["simple"] = &simpleStorage
@ -1212,7 +1213,7 @@ func TestUpdatePreventsMismatchedNamespace(t *testing.T) {
} }
func TestUpdateMissing(t *testing.T) { func TestUpdateMissing(t *testing.T) {
storage := map[string]RESTStorage{} storage := map[string]rest.Storage{}
ID := "id" ID := "id"
simpleStorage := SimpleRESTStorage{ simpleStorage := SimpleRESTStorage{
errors: map[string]error{"update": apierrs.NewNotFound("simple", ID)}, errors: map[string]error{"update": apierrs.NewNotFound("simple", ID)},
@ -1246,7 +1247,7 @@ func TestUpdateMissing(t *testing.T) {
} }
func TestCreateNotFound(t *testing.T) { func TestCreateNotFound(t *testing.T) {
handler := handle(map[string]RESTStorage{ handler := handle(map[string]rest.Storage{
"simple": &SimpleRESTStorage{ "simple": &SimpleRESTStorage{
// storage.Create can fail with not found error in theory. // storage.Create can fail with not found error in theory.
// See https://github.com/GoogleCloudPlatform/kubernetes/pull/486#discussion_r15037092. // See https://github.com/GoogleCloudPlatform/kubernetes/pull/486#discussion_r15037092.
@ -1275,7 +1276,7 @@ func TestCreateNotFound(t *testing.T) {
} }
func TestCreateChecksDecode(t *testing.T) { func TestCreateChecksDecode(t *testing.T) {
handler := handle(map[string]RESTStorage{"simple": &SimpleRESTStorage{}}) handler := handle(map[string]rest.Storage{"simple": &SimpleRESTStorage{}})
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
defer server.Close() defer server.Close()
client := http.Client{} client := http.Client{}
@ -1299,7 +1300,7 @@ func TestCreateChecksDecode(t *testing.T) {
} }
func TestUpdateChecksDecode(t *testing.T) { func TestUpdateChecksDecode(t *testing.T) {
handler := handle(map[string]RESTStorage{"simple": &SimpleRESTStorage{}}) handler := handle(map[string]rest.Storage{"simple": &SimpleRESTStorage{}})
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
defer server.Close() defer server.Close()
client := http.Client{} client := http.Client{}
@ -1367,7 +1368,7 @@ func TestCreate(t *testing.T) {
namespace: "default", namespace: "default",
expectedSet: "/api/version/foo/bar?namespace=default", expectedSet: "/api/version/foo/bar?namespace=default",
} }
handler := handleLinker(map[string]RESTStorage{"foo": &storage}, selfLinker) handler := handleLinker(map[string]rest.Storage{"foo": &storage}, selfLinker)
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
defer server.Close() defer server.Close()
client := http.Client{} client := http.Client{}
@ -1423,7 +1424,7 @@ func TestCreateInNamespace(t *testing.T) {
namespace: "other", namespace: "other",
expectedSet: "/api/version/foo/bar?namespace=other", expectedSet: "/api/version/foo/bar?namespace=other",
} }
handler := handleLinker(map[string]RESTStorage{"foo": &storage}, selfLinker) handler := handleLinker(map[string]rest.Storage{"foo": &storage}, selfLinker)
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
defer server.Close() defer server.Close()
client := http.Client{} client := http.Client{}
@ -1479,7 +1480,7 @@ func TestCreateInvokesAdmissionControl(t *testing.T) {
namespace: "other", namespace: "other",
expectedSet: "/api/version/foo/bar?namespace=other", expectedSet: "/api/version/foo/bar?namespace=other",
} }
handler := handleInternal(map[string]RESTStorage{"foo": &storage}, deny.NewAlwaysDeny(), mapper, selfLinker) handler := handleInternal(map[string]rest.Storage{"foo": &storage}, deny.NewAlwaysDeny(), mapper, selfLinker)
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
defer server.Close() defer server.Close()
client := http.Client{} client := http.Client{}
@ -1539,7 +1540,7 @@ func TestDelayReturnsError(t *testing.T) {
return nil, apierrs.NewAlreadyExists("foo", "bar") return nil, apierrs.NewAlreadyExists("foo", "bar")
}, },
} }
handler := handle(map[string]RESTStorage{"foo": &storage}) handler := handle(map[string]rest.Storage{"foo": &storage})
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
defer server.Close() defer server.Close()
@ -1603,7 +1604,7 @@ func TestCreateTimeout(t *testing.T) {
return obj, nil return obj, nil
}, },
} }
handler := handle(map[string]RESTStorage{ handler := handle(map[string]rest.Storage{
"foo": &storage, "foo": &storage,
}) })
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
@ -1637,7 +1638,7 @@ func TestCORSAllowedOrigins(t *testing.T) {
} }
handler := CORS( handler := CORS(
handle(map[string]RESTStorage{}), handle(map[string]rest.Storage{}),
allowedOriginRegexps, nil, nil, "true", allowedOriginRegexps, nil, nil, "true",
) )
server := httptest.NewServer(handler) server := httptest.NewServer(handler)

View File

@ -14,5 +14,5 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
// Package apiserver contains the code that provides a RESTful api service. // Package apiserver contains the code that provides a rest.ful api service.
package apiserver package apiserver

View File

@ -32,6 +32,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/httplog" "github.com/GoogleCloudPlatform/kubernetes/pkg/httplog"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
@ -79,7 +80,7 @@ var tagsToAttrs = map[string]util.StringSet{
// specified by items implementing Redirector. // specified by items implementing Redirector.
type ProxyHandler struct { type ProxyHandler struct {
prefix string prefix string
storage map[string]RESTStorage storage map[string]rest.Storage
codec runtime.Codec codec runtime.Codec
context api.RequestContextMapper context api.RequestContextMapper
apiRequestInfoResolver *APIRequestInfoResolver apiRequestInfoResolver *APIRequestInfoResolver
@ -112,15 +113,15 @@ func (r *ProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return return
} }
id := parts[1] id := parts[1]
rest := "" remainder := ""
if len(parts) > 2 { if len(parts) > 2 {
proxyParts := parts[2:] proxyParts := parts[2:]
rest = strings.Join(proxyParts, "/") remainder = strings.Join(proxyParts, "/")
if strings.HasSuffix(req.URL.Path, "/") { if strings.HasSuffix(req.URL.Path, "/") {
// The original path had a trailing slash, which has been stripped // The original path had a trailing slash, which has been stripped
// by KindAndNamespace(). We should add it back because some // by KindAndNamespace(). We should add it back because some
// servers (like etcd) require it. // servers (like etcd) require it.
rest = rest + "/" remainder = remainder + "/"
} }
} }
storage, ok := r.storage[resource] storage, ok := r.storage[resource]
@ -132,7 +133,7 @@ func (r *ProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
} }
apiResource = resource apiResource = resource
redirector, ok := storage.(Redirector) redirector, ok := storage.(rest.Redirector)
if !ok { if !ok {
httplog.LogOf(req, w).Addf("'%v' is not a redirector", resource) httplog.LogOf(req, w).Addf("'%v' is not a redirector", resource)
httpCode = errorJSON(errors.NewMethodNotSupported(resource, "proxy"), r.codec, w) httpCode = errorJSON(errors.NewMethodNotSupported(resource, "proxy"), r.codec, w)
@ -160,7 +161,7 @@ func (r *ProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// hosts for paths. // hosts for paths.
destURL.Host = location destURL.Host = location
} }
destURL.Path = rest destURL.Path = remainder
destURL.RawQuery = req.URL.RawQuery destURL.RawQuery = req.URL.RawQuery
newReq, err := http.NewRequest(req.Method, destURL.String(), req.Body) newReq, err := http.NewRequest(req.Method, destURL.String(), req.Body)
if err != nil { if err != nil {

View File

@ -28,6 +28,7 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"golang.org/x/net/html" "golang.org/x/net/html"
"golang.org/x/net/websocket" "golang.org/x/net/websocket"
) )
@ -280,10 +281,10 @@ func TestProxy(t *testing.T) {
expectedResourceNamespace: item.reqNamespace, expectedResourceNamespace: item.reqNamespace,
} }
namespaceHandler := handleNamespaced(map[string]RESTStorage{"foo": simpleStorage}) namespaceHandler := handleNamespaced(map[string]rest.Storage{"foo": simpleStorage})
namespaceServer := httptest.NewServer(namespaceHandler) namespaceServer := httptest.NewServer(namespaceHandler)
defer namespaceServer.Close() defer namespaceServer.Close()
legacyNamespaceHandler := handle(map[string]RESTStorage{"foo": simpleStorage}) legacyNamespaceHandler := handle(map[string]rest.Storage{"foo": simpleStorage})
legacyNamespaceServer := httptest.NewServer(legacyNamespaceHandler) legacyNamespaceServer := httptest.NewServer(legacyNamespaceHandler)
defer legacyNamespaceServer.Close() defer legacyNamespaceServer.Close()
@ -340,7 +341,7 @@ func TestProxyUpgrade(t *testing.T) {
expectedResourceNamespace: "myns", expectedResourceNamespace: "myns",
} }
namespaceHandler := handleNamespaced(map[string]RESTStorage{"foo": simpleStorage}) namespaceHandler := handleNamespaced(map[string]rest.Storage{"foo": simpleStorage})
server := httptest.NewServer(namespaceHandler) server := httptest.NewServer(namespaceHandler)
defer server.Close() defer server.Close()

View File

@ -23,12 +23,13 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/httplog" "github.com/GoogleCloudPlatform/kubernetes/pkg/httplog"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
) )
type RedirectHandler struct { type RedirectHandler struct {
storage map[string]RESTStorage storage map[string]rest.Storage
codec runtime.Codec codec runtime.Codec
context api.RequestContextMapper context api.RequestContextMapper
apiRequestInfoResolver *APIRequestInfoResolver apiRequestInfoResolver *APIRequestInfoResolver
@ -71,7 +72,7 @@ func (r *RedirectHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
} }
apiResource = resource apiResource = resource
redirector, ok := storage.(Redirector) redirector, ok := storage.(rest.Redirector)
if !ok { if !ok {
httplog.LogOf(req, w).Addf("'%v' is not a redirector", resource) httplog.LogOf(req, w).Addf("'%v' is not a redirector", resource)
httpCode = errorJSON(errors.NewMethodNotSupported(resource, "redirect"), r.codec, w) httpCode = errorJSON(errors.NewMethodNotSupported(resource, "redirect"), r.codec, w)

View File

@ -22,6 +22,8 @@ import (
"net/http/httptest" "net/http/httptest"
"net/url" "net/url"
"testing" "testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
) )
func TestRedirect(t *testing.T) { func TestRedirect(t *testing.T) {
@ -29,7 +31,7 @@ func TestRedirect(t *testing.T) {
errors: map[string]error{}, errors: map[string]error{},
expectedResourceNamespace: "default", expectedResourceNamespace: "default",
} }
handler := handle(map[string]RESTStorage{"foo": simpleStorage}) handler := handle(map[string]rest.Storage{"foo": simpleStorage})
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
defer server.Close() defer server.Close()
@ -80,7 +82,7 @@ func TestRedirectWithNamespaces(t *testing.T) {
errors: map[string]error{}, errors: map[string]error{},
expectedResourceNamespace: "other", expectedResourceNamespace: "other",
} }
handler := handleNamespaced(map[string]RESTStorage{"foo": simpleStorage}) handler := handleNamespaced(map[string]rest.Storage{"foo": simpleStorage})
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
defer server.Close() defer server.Close()

View File

@ -26,6 +26,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/admission" "github.com/GoogleCloudPlatform/kubernetes/pkg/admission"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
@ -58,8 +59,8 @@ type ScopeNamer interface {
GenerateListLink(req *restful.Request) (path, query string, err error) GenerateListLink(req *restful.Request) (path, query string, err error)
} }
// GetResource returns a function that handles retrieving a single resource from a RESTStorage object. // GetResource returns a function that handles retrieving a single resource from a rest.Storage object.
func GetResource(r RESTGetter, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec) restful.RouteFunction { func GetResource(r rest.Getter, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec) restful.RouteFunction {
return func(req *restful.Request, res *restful.Response) { return func(req *restful.Request, res *restful.Response) {
w := res.ResponseWriter w := res.ResponseWriter
namespace, name, err := namer.Name(req) namespace, name, err := namer.Name(req)
@ -101,8 +102,8 @@ func parseSelectorQueryParams(query url.Values, version, apiResource string) (la
return label, field, nil return label, field, nil
} }
// ListResource returns a function that handles retrieving a list of resources from a RESTStorage object. // ListResource returns a function that handles retrieving a list of resources from a rest.Storage object.
func ListResource(r RESTLister, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, version, apiResource string) restful.RouteFunction { func ListResource(r rest.Lister, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, version, apiResource string) restful.RouteFunction {
return func(req *restful.Request, res *restful.Response) { return func(req *restful.Request, res *restful.Response) {
w := res.ResponseWriter w := res.ResponseWriter
@ -134,7 +135,7 @@ func ListResource(r RESTLister, ctxFn ContextFunc, namer ScopeNamer, codec runti
} }
// CreateResource returns a function that will handle a resource creation. // CreateResource returns a function that will handle a resource creation.
func CreateResource(r RESTCreater, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, typer runtime.ObjectTyper, resource string, admit admission.Interface) restful.RouteFunction { func CreateResource(r rest.Creater, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, typer runtime.ObjectTyper, resource string, admit admission.Interface) restful.RouteFunction {
return func(req *restful.Request, res *restful.Response) { return func(req *restful.Request, res *restful.Response) {
w := res.ResponseWriter w := res.ResponseWriter
@ -191,7 +192,7 @@ func CreateResource(r RESTCreater, ctxFn ContextFunc, namer ScopeNamer, codec ru
// PatchResource returns a function that will handle a resource patch // PatchResource returns a function that will handle a resource patch
// TODO: Eventually PatchResource should just use AtomicUpdate and this routine should be a bit cleaner // TODO: Eventually PatchResource should just use AtomicUpdate and this routine should be a bit cleaner
func PatchResource(r RESTPatcher, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, typer runtime.ObjectTyper, resource string, admit admission.Interface) restful.RouteFunction { func PatchResource(r rest.Patcher, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, typer runtime.ObjectTyper, resource string, admit admission.Interface) restful.RouteFunction {
return func(req *restful.Request, res *restful.Response) { return func(req *restful.Request, res *restful.Response) {
w := res.ResponseWriter w := res.ResponseWriter
@ -266,7 +267,7 @@ func PatchResource(r RESTPatcher, ctxFn ContextFunc, namer ScopeNamer, codec run
} }
// UpdateResource returns a function that will handle a resource update // UpdateResource returns a function that will handle a resource update
func UpdateResource(r RESTUpdater, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, typer runtime.ObjectTyper, resource string, admit admission.Interface) restful.RouteFunction { func UpdateResource(r rest.Updater, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, typer runtime.ObjectTyper, resource string, admit admission.Interface) restful.RouteFunction {
return func(req *restful.Request, res *restful.Response) { return func(req *restful.Request, res *restful.Response) {
w := res.ResponseWriter w := res.ResponseWriter
@ -330,7 +331,7 @@ func UpdateResource(r RESTUpdater, ctxFn ContextFunc, namer ScopeNamer, codec ru
} }
// DeleteResource returns a function that will handle a resource deletion // DeleteResource returns a function that will handle a resource deletion
func DeleteResource(r RESTGracefulDeleter, checkBody bool, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, resource, kind string, admit admission.Interface) restful.RouteFunction { func DeleteResource(r rest.GracefulDeleter, checkBody bool, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, resource, kind string, admit admission.Interface) restful.RouteFunction {
return func(req *restful.Request, res *restful.Response) { return func(req *restful.Request, res *restful.Response) {
w := res.ResponseWriter w := res.ResponseWriter
@ -376,7 +377,7 @@ func DeleteResource(r RESTGracefulDeleter, checkBody bool, ctxFn ContextFunc, na
return return
} }
// if the RESTDeleter returns a nil object, fill out a status. Callers may return a valid // if the rest.Deleter returns a nil object, fill out a status. Callers may return a valid
// object with the response. // object with the response.
if result == nil { if result == nil {
result = &api.Status{ result = &api.Status{

View File

@ -26,6 +26,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/httplog" "github.com/GoogleCloudPlatform/kubernetes/pkg/httplog"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
@ -36,7 +37,7 @@ import (
) )
type WatchHandler struct { type WatchHandler struct {
storage map[string]RESTStorage storage map[string]rest.Storage
codec runtime.Codec codec runtime.Codec
linker runtime.SelfLinker linker runtime.SelfLinker
info *APIRequestInfoResolver info *APIRequestInfoResolver
@ -90,7 +91,7 @@ func (h *WatchHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return return
} }
apiResource = requestInfo.Resource apiResource = requestInfo.Resource
watcher, ok := storage.(ResourceWatcher) watcher, ok := storage.(rest.Watcher)
if !ok { if !ok {
httpCode = errorJSON(errors.NewMethodNotSupported(requestInfo.Resource, "watch"), h.codec, w) httpCode = errorJSON(errors.NewMethodNotSupported(requestInfo.Resource, "watch"), h.codec, w)
return return

View File

@ -25,6 +25,7 @@ import (
"testing" "testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
@ -49,8 +50,8 @@ var watchTestTable = []struct {
func TestWatchWebsocket(t *testing.T) { func TestWatchWebsocket(t *testing.T) {
simpleStorage := &SimpleRESTStorage{} simpleStorage := &SimpleRESTStorage{}
_ = ResourceWatcher(simpleStorage) // Give compile error if this doesn't work. _ = rest.Watcher(simpleStorage) // Give compile error if this doesn't work.
handler := handle(map[string]RESTStorage{"foo": simpleStorage}) handler := handle(map[string]rest.Storage{"foo": simpleStorage})
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
defer server.Close() defer server.Close()
@ -102,7 +103,7 @@ func TestWatchWebsocket(t *testing.T) {
func TestWatchHTTP(t *testing.T) { func TestWatchHTTP(t *testing.T) {
simpleStorage := &SimpleRESTStorage{} simpleStorage := &SimpleRESTStorage{}
handler := handle(map[string]RESTStorage{"foo": simpleStorage}) handler := handle(map[string]rest.Storage{"foo": simpleStorage})
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
defer server.Close() defer server.Close()
client := http.Client{} client := http.Client{}
@ -167,7 +168,7 @@ func TestWatchParamParsing(t *testing.T) {
return label, value, nil return label, value, nil
}) })
simpleStorage := &SimpleRESTStorage{} simpleStorage := &SimpleRESTStorage{}
handler := handle(map[string]RESTStorage{"foo": simpleStorage}) handler := handle(map[string]rest.Storage{"foo": simpleStorage})
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
defer server.Close() defer server.Close()
@ -237,7 +238,7 @@ func TestWatchParamParsing(t *testing.T) {
func TestWatchProtocolSelection(t *testing.T) { func TestWatchProtocolSelection(t *testing.T) {
simpleStorage := &SimpleRESTStorage{} simpleStorage := &SimpleRESTStorage{}
handler := handle(map[string]RESTStorage{"foo": simpleStorage}) handler := handle(map[string]rest.Storage{"foo": simpleStorage})
server := httptest.NewServer(handler) server := httptest.NewServer(handler)
defer server.Close() defer server.Close()
defer server.CloseClientConnections() defer server.CloseClientConnections()

View File

@ -17,10 +17,11 @@ limitations under the License.
package record package record
import ( import (
"sync"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/golang/groupcache/lru" "github.com/golang/groupcache/lru"
"sync"
) )
type history struct { type history struct {

View File

@ -17,9 +17,10 @@ limitations under the License.
package record package record
import ( import (
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"testing"
) )
func TestAddOrUpdateEventNoExisting(t *testing.T) { func TestAddOrUpdateEventNoExisting(t *testing.T) {

View File

@ -31,6 +31,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/admission" "github.com/GoogleCloudPlatform/kubernetes/pkg/admission"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta3" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta3"
@ -151,7 +152,7 @@ type Master struct {
masterServices *util.Runner masterServices *util.Runner
// storage contains the RESTful endpoints exposed by this master // storage contains the RESTful endpoints exposed by this master
storage map[string]apiserver.RESTStorage storage map[string]rest.Storage
// registries are internal client APIs for accessing the storage layer // registries are internal client APIs for accessing the storage layer
// TODO: define the internal typed interface in a way that clients can // TODO: define the internal typed interface in a way that clients can
@ -384,7 +385,7 @@ func (m *Master) init(c *Config) {
} }
// TODO: Factor out the core API registration // TODO: Factor out the core API registration
m.storage = map[string]apiserver.RESTStorage{ m.storage = map[string]rest.Storage{
"pods": podStorage, "pods": podStorage,
"pods/status": podStatusStorage, "pods/status": podStatusStorage,
"pods/binding": bindingStorage, "pods/binding": bindingStorage,
@ -576,7 +577,7 @@ func (m *Master) defaultAPIGroupVersion() *apiserver.APIGroupVersion {
// api_v1beta1 returns the resources and codec for API version v1beta1. // api_v1beta1 returns the resources and codec for API version v1beta1.
func (m *Master) api_v1beta1() *apiserver.APIGroupVersion { func (m *Master) api_v1beta1() *apiserver.APIGroupVersion {
storage := make(map[string]apiserver.RESTStorage) storage := make(map[string]rest.Storage)
for k, v := range m.storage { for k, v := range m.storage {
storage[k] = v storage[k] = v
} }
@ -589,7 +590,7 @@ func (m *Master) api_v1beta1() *apiserver.APIGroupVersion {
// api_v1beta2 returns the resources and codec for API version v1beta2. // api_v1beta2 returns the resources and codec for API version v1beta2.
func (m *Master) api_v1beta2() *apiserver.APIGroupVersion { func (m *Master) api_v1beta2() *apiserver.APIGroupVersion {
storage := make(map[string]apiserver.RESTStorage) storage := make(map[string]rest.Storage)
for k, v := range m.storage { for k, v := range m.storage {
storage[k] = v storage[k] = v
} }
@ -602,7 +603,7 @@ func (m *Master) api_v1beta2() *apiserver.APIGroupVersion {
// api_v1beta3 returns the resources and codec for API version v1beta3. // api_v1beta3 returns the resources and codec for API version v1beta3.
func (m *Master) api_v1beta3() *apiserver.APIGroupVersion { func (m *Master) api_v1beta3() *apiserver.APIGroupVersion {
storage := make(map[string]apiserver.RESTStorage) storage := make(map[string]rest.Storage)
for k, v := range m.storage { for k, v := range m.storage {
if k == "minions" { if k == "minions" {
continue continue

View File

@ -22,7 +22,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/golang/glog" "github.com/golang/glog"
) )
@ -91,7 +91,7 @@ func (m *Master) createMasterNamespaceIfNeeded(ns string) error {
Namespace: "", Namespace: "",
}, },
} }
_, err := m.storage["namespaces"].(apiserver.RESTCreater).Create(ctx, namespace) _, err := m.storage["namespaces"].(rest.Creater).Create(ctx, namespace)
if err != nil && errors.IsAlreadyExists(err) { if err != nil && errors.IsAlreadyExists(err) {
err = nil err = nil
} }
@ -121,7 +121,7 @@ func (m *Master) createMasterServiceIfNeeded(serviceName string, serviceIP net.I
SessionAffinity: api.AffinityTypeNone, SessionAffinity: api.AffinityTypeNone,
}, },
} }
_, err := m.storage["services"].(apiserver.RESTCreater).Create(ctx, svc) _, err := m.storage["services"].(rest.Creater).Create(ctx, svc)
if err != nil && errors.IsAlreadyExists(err) { if err != nil && errors.IsAlreadyExists(err) {
err = nil err = nil
} }

View File

@ -20,7 +20,7 @@ import (
"errors" "errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
@ -38,12 +38,12 @@ import (
// //
// TODO: this also means that pod and node API endpoints have to be colocated in the same // TODO: this also means that pod and node API endpoints have to be colocated in the same
// process // process
func RESTStorageToNodes(storage apiserver.RESTStorage) client.NodesInterface { func RESTStorageToNodes(storage rest.Storage) client.NodesInterface {
return &nodeAdaptor{storage} return &nodeAdaptor{storage}
} }
type nodeAdaptor struct { type nodeAdaptor struct {
storage apiserver.RESTStorage storage rest.Storage
} }
func (n *nodeAdaptor) Nodes() client.NodeInterface { func (n *nodeAdaptor) Nodes() client.NodeInterface {
@ -66,7 +66,7 @@ func (n *nodeAdaptor) Create(minion *api.Node) (*api.Node, error) {
// List lists all the nodes in the cluster. // List lists all the nodes in the cluster.
func (n *nodeAdaptor) List() (*api.NodeList, error) { func (n *nodeAdaptor) List() (*api.NodeList, error) {
ctx := api.NewContext() ctx := api.NewContext()
obj, err := n.storage.(apiserver.RESTLister).List(ctx, labels.Everything(), fields.Everything()) obj, err := n.storage.(rest.Lister).List(ctx, labels.Everything(), fields.Everything())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -76,7 +76,7 @@ func (n *nodeAdaptor) List() (*api.NodeList, error) {
// Get gets an existing node. // Get gets an existing node.
func (n *nodeAdaptor) Get(name string) (*api.Node, error) { func (n *nodeAdaptor) Get(name string) (*api.Node, error) {
ctx := api.NewContext() ctx := api.NewContext()
obj, err := n.storage.(apiserver.RESTGetter).Get(ctx, name) obj, err := n.storage.(rest.Getter).Get(ctx, name)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -71,14 +71,14 @@ type PodLister interface {
ListPods(ctx api.Context, labels labels.Selector) (*api.PodList, error) ListPods(ctx api.Context, labels labels.Selector) (*api.PodList, error)
} }
// REST implements apiserver.RESTStorage for the replication controller service. // REST implements rest.Storage for the replication controller service.
type REST struct { type REST struct {
registry Registry registry Registry
podLister PodLister podLister PodLister
strategy rcStrategy strategy rcStrategy
} }
// NewREST returns a new apiserver.RESTStorage for the given registry and PodLister. // NewREST returns a new rest.Storage for the given registry and PodLister.
func NewREST(registry Registry, podLister PodLister) *REST { func NewREST(registry Registry, podLister PodLister) *REST {
return &REST{ return &REST{
registry: registry, registry: registry,
@ -167,7 +167,7 @@ func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, boo
} }
// Watch returns ReplicationController events via a watch.Interface. // Watch returns ReplicationController events via a watch.Interface.
// It implements apiserver.ResourceWatcher. // It implements rest.Watcher.
func (rs *REST) Watch(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { func (rs *REST) Watch(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
return rs.registry.WatchControllers(ctx, label, field, resourceVersion) return rs.registry.WatchControllers(ctx, label, field, resourceVersion)
} }

View File

@ -32,7 +32,7 @@ type REST struct {
registry Registry registry Registry
} }
// NewREST returns a new apiserver.RESTStorage implementation for endpoints // NewREST returns a new rest.Storage implementation for endpoints
func NewREST(registry Registry) *REST { func NewREST(registry Registry) *REST {
return &REST{ return &REST{
registry: registry, registry: registry,
@ -53,7 +53,7 @@ func (rs *REST) List(ctx api.Context, label labels.Selector, field fields.Select
} }
// Watch returns Endpoint events via a watch.Interface. // Watch returns Endpoint events via a watch.Interface.
// It implements apiserver.ResourceWatcher. // It implements rest.Watcher.
func (rs *REST) Watch(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { func (rs *REST) Watch(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
return rs.registry.WatchEndpoints(ctx, label, field, resourceVersion) return rs.registry.WatchEndpoints(ctx, label, field, resourceVersion)
} }

View File

@ -135,7 +135,7 @@ func (rs *REST) List(ctx api.Context, label labels.Selector, field fields.Select
} }
// Watch returns Events events via a watch.Interface. // Watch returns Events events via a watch.Interface.
// It implements apiserver.ResourceWatcher. // It implements rest.Watcher.
func (rs *REST) Watch(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { func (rs *REST) Watch(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
return rs.registry.WatchPredicate(ctx, &generic.SelectionPredicate{label, field, rs.getAttrs}, resourceVersion) return rs.registry.WatchPredicate(ctx, &generic.SelectionPredicate{label, field, rs.getAttrs}, resourceVersion)
} }

View File

@ -21,8 +21,8 @@ import (
"testing" "testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
@ -74,8 +74,8 @@ func TestRESTCreate(t *testing.T) {
} }
for _, item := range table { for _, item := range table {
_, rest := NewTestREST() _, storage := NewTestREST()
c, err := rest.Create(item.ctx, item.event) c, err := storage.Create(item.ctx, item.event)
if !item.valid { if !item.valid {
if err == nil { if err == nil {
ctxNS := api.NamespaceValue(item.ctx) ctxNS := api.NamespaceValue(item.ctx)
@ -94,7 +94,7 @@ func TestRESTCreate(t *testing.T) {
t.Errorf("diff: %s", util.ObjectDiff(e, a)) t.Errorf("diff: %s", util.ObjectDiff(e, a))
} }
// Ensure we implement the interface // Ensure we implement the interface
_ = apiserver.ResourceWatcher(rest) _ = rest.Watcher(storage)
} }
} }

View File

@ -38,7 +38,7 @@ type REST struct {
registry Registry registry Registry
} }
// NewREST returns a new apiserver.RESTStorage implementation for minion. // NewREST returns a new rest.Storage implementation for minion.
func NewREST(m Registry) *REST { func NewREST(m Registry) *REST {
return &REST{ return &REST{
registry: m, registry: m,
@ -133,7 +133,7 @@ func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, boo
} }
// Watch returns Minions events via a watch.Interface. // Watch returns Minions events via a watch.Interface.
// It implements apiserver.ResourceWatcher. // It implements rest.Watcher.
func (rs *REST) Watch(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { func (rs *REST) Watch(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
return rs.registry.WatchMinions(ctx, label, field, resourceVersion) return rs.registry.WatchMinions(ctx, label, field, resourceVersion)
} }

View File

@ -18,7 +18,7 @@ package namespace
import ( import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
@ -44,10 +44,10 @@ type Registry interface {
// Storage is an interface for a standard REST Storage backend // Storage is an interface for a standard REST Storage backend
// TODO: move me somewhere common // TODO: move me somewhere common
type Storage interface { type Storage interface {
apiserver.RESTGracefulDeleter rest.GracefulDeleter
apiserver.RESTLister rest.Lister
apiserver.RESTGetter rest.Getter
apiserver.ResourceWatcher rest.Watcher
Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error)
Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error)

View File

@ -26,8 +26,8 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
etcderrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors/etcd" etcderrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors/etcd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest/resttest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest/resttest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
@ -682,7 +682,7 @@ func TestResourceLocation(t *testing.T) {
cache := &fakeCache{statusToReturn: &api.PodStatus{PodIP: expectedIP}} cache := &fakeCache{statusToReturn: &api.PodStatus{PodIP: expectedIP}}
storage = storage.WithPodStatus(cache) storage = storage.WithPodStatus(cache)
redirector := apiserver.Redirector(storage) redirector := rest.Redirector(storage)
location, err := redirector.ResourceLocation(api.NewDefaultContext(), tc.query) location, err := redirector.ResourceLocation(api.NewDefaultContext(), tc.query)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)

View File

@ -18,7 +18,7 @@ package pod
import ( import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
@ -44,10 +44,10 @@ type Registry interface {
// Storage is an interface for a standard REST Storage backend // Storage is an interface for a standard REST Storage backend
// TODO: move me somewhere common // TODO: move me somewhere common
type Storage interface { type Storage interface {
apiserver.RESTGracefulDeleter rest.GracefulDeleter
apiserver.RESTLister rest.Lister
apiserver.RESTGetter rest.Getter
apiserver.ResourceWatcher rest.Watcher
Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error)
Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error)

View File

@ -18,7 +18,7 @@ package resourcequota
import ( import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
@ -44,10 +44,10 @@ type Registry interface {
// Storage is an interface for a standard REST Storage backend // Storage is an interface for a standard REST Storage backend
// TODO: move me somewhere common // TODO: move me somewhere common
type Storage interface { type Storage interface {
apiserver.RESTGracefulDeleter rest.GracefulDeleter
apiserver.RESTLister rest.Lister
apiserver.RESTGetter rest.Getter
apiserver.ResourceWatcher rest.Watcher
Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error)
Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error)

View File

@ -21,7 +21,7 @@ import (
"testing" "testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
@ -73,8 +73,8 @@ func TestRESTCreate(t *testing.T) {
} }
for _, item := range table { for _, item := range table {
_, rest := NewTestREST() _, storage := NewTestREST()
c, err := rest.Create(item.ctx, item.secret) c, err := storage.Create(item.ctx, item.secret)
if !item.valid { if !item.valid {
if err == nil { if err == nil {
ctxNS := api.NamespaceValue(item.ctx) ctxNS := api.NamespaceValue(item.ctx)
@ -93,7 +93,7 @@ func TestRESTCreate(t *testing.T) {
t.Errorf("diff: %s", util.ObjectDiff(e, a)) t.Errorf("diff: %s", util.ObjectDiff(e, a))
} }
// Ensure we implement the interface // Ensure we implement the interface
_ = apiserver.ResourceWatcher(rest) _ = rest.Watcher(storage)
} }
} }

View File

@ -174,7 +174,7 @@ func (rs *REST) List(ctx api.Context, label labels.Selector, field fields.Select
} }
// Watch returns Services events via a watch.Interface. // Watch returns Services events via a watch.Interface.
// It implements apiserver.ResourceWatcher. // It implements rest.Watcher.
func (rs *REST) Watch(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { func (rs *REST) Watch(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
return rs.registry.WatchServices(ctx, label, field, resourceVersion) return rs.registry.WatchServices(ctx, label, field, resourceVersion)
} }

View File

@ -24,8 +24,8 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest/resttest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest/resttest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
cloud "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/fake" cloud "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/fake"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
@ -384,7 +384,7 @@ func TestServiceRegistryResourceLocation(t *testing.T) {
Selector: map[string]string{"bar": "baz"}, Selector: map[string]string{"bar": "baz"},
}, },
}) })
redirector := apiserver.Redirector(storage) redirector := rest.Redirector(storage)
location, err := redirector.ResourceLocation(ctx, "foo") location, err := redirector.ResourceLocation(ctx, "foo")
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)