Merge pull request #5758 from smarterclayton/get_input_parameters

Cleanup REST interfaces across the codebase
This commit is contained in:
Derek Carr 2015-03-23 17:17:27 -04:00
commit 3864cad20e
41 changed files with 307 additions and 317 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
@ -348,16 +349,16 @@ func logStackOnRecover(panicReason interface{}, httpWriter http.ResponseWriter)
// init initializes master. // init initializes master.
func (m *Master) init(c *Config) { func (m *Master) init(c *Config) {
podStorage, bindingStorage, podStatusStorage := podetcd.NewREST(c.EtcdHelper) podStorage, bindingStorage, podStatusStorage := podetcd.NewStorage(c.EtcdHelper)
podRegistry := pod.NewRegistry(podStorage) podRegistry := pod.NewRegistry(podStorage)
eventRegistry := event.NewEtcdRegistry(c.EtcdHelper, uint64(c.EventTTL.Seconds())) eventRegistry := event.NewEtcdRegistry(c.EtcdHelper, uint64(c.EventTTL.Seconds()))
limitRangeRegistry := limitrange.NewEtcdRegistry(c.EtcdHelper) limitRangeRegistry := limitrange.NewEtcdRegistry(c.EtcdHelper)
resourceQuotaStorage, resourceQuotaStatusStorage := resourcequotaetcd.NewREST(c.EtcdHelper) resourceQuotaStorage, resourceQuotaStatusStorage := resourcequotaetcd.NewStorage(c.EtcdHelper)
secretRegistry := secret.NewEtcdRegistry(c.EtcdHelper) secretRegistry := secret.NewEtcdRegistry(c.EtcdHelper)
namespaceStorage := namespaceetcd.NewREST(c.EtcdHelper) namespaceStorage := namespaceetcd.NewStorage(c.EtcdHelper)
m.namespaceRegistry = namespace.NewRegistry(namespaceStorage) m.namespaceRegistry = namespace.NewRegistry(namespaceStorage)
// TODO: split me up into distinct storage registries // TODO: split me up into distinct storage registries
@ -367,7 +368,7 @@ func (m *Master) init(c *Config) {
m.endpointRegistry = registry m.endpointRegistry = registry
m.nodeRegistry = registry m.nodeRegistry = registry
nodeStorage := minion.NewREST(m.nodeRegistry) nodeStorage := minion.NewStorage(m.nodeRegistry)
// TODO: unify the storage -> registry and storage -> client patterns // TODO: unify the storage -> registry and storage -> client patterns
nodeStorageClient := RESTStorageToNodes(nodeStorage) nodeStorageClient := RESTStorageToNodes(nodeStorage)
podCache := NewPodCache( podCache := NewPodCache(
@ -384,24 +385,24 @@ 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,
"bindings": bindingStorage, "bindings": bindingStorage,
"replicationControllers": controller.NewREST(registry, podRegistry), "replicationControllers": controller.NewStorage(registry, podRegistry),
"services": service.NewREST(m.serviceRegistry, c.Cloud, m.nodeRegistry, m.portalNet, c.ClusterName), "services": service.NewStorage(m.serviceRegistry, c.Cloud, m.nodeRegistry, m.portalNet, c.ClusterName),
"endpoints": endpoint.NewREST(m.endpointRegistry), "endpoints": endpoint.NewStorage(m.endpointRegistry),
"minions": nodeStorage, "minions": nodeStorage,
"nodes": nodeStorage, "nodes": nodeStorage,
"events": event.NewREST(eventRegistry), "events": event.NewStorage(eventRegistry),
"limitRanges": limitrange.NewREST(limitRangeRegistry), "limitRanges": limitrange.NewStorage(limitRangeRegistry),
"resourceQuotas": resourceQuotaStorage, "resourceQuotas": resourceQuotaStorage,
"resourceQuotas/status": resourceQuotaStatusStorage, "resourceQuotas/status": resourceQuotaStatusStorage,
"namespaces": namespaceStorage, "namespaces": namespaceStorage,
"secrets": secret.NewREST(secretRegistry), "secrets": secret.NewStorage(secretRegistry),
} }
apiVersions := []string{"v1beta1", "v1beta2"} apiVersions := []string{"v1beta1", "v1beta2"}
@ -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,15 +71,15 @@ 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. // NewStorage returns a new rest.Storage for the given registry and PodLister.
func NewREST(registry Registry, podLister PodLister) *REST { func NewStorage(registry Registry, podLister PodLister) *REST {
return &REST{ return &REST{
registry: registry, registry: registry,
podLister: podLister, podLister: podLister,
@ -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

@ -397,7 +397,7 @@ func (f *fakePodLister) ListPods(ctx api.Context, s labels.Selector) (*api.PodLi
// TODO: remove, covered by TestCreate // TODO: remove, covered by TestCreate
func TestCreateControllerWithGeneratedName(t *testing.T) { func TestCreateControllerWithGeneratedName(t *testing.T) {
storage := NewREST(&registrytest.ControllerRegistry{}, nil) storage := NewStorage(&registrytest.ControllerRegistry{}, nil)
controller := &api.ReplicationController{ controller := &api.ReplicationController{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Namespace: api.NamespaceDefault, Namespace: api.NamespaceDefault,
@ -443,7 +443,7 @@ func TestCreateControllerWithConflictingNamespace(t *testing.T) {
func TestCreate(t *testing.T) { func TestCreate(t *testing.T) {
registry := &registrytest.ControllerRegistry{} registry := &registrytest.ControllerRegistry{}
test := resttest.New(t, NewREST(registry, nil), registry.SetError) test := resttest.New(t, NewStorage(registry, nil), registry.SetError)
test.TestCreate( test.TestCreate(
// valid // valid
&api.ReplicationController{ &api.ReplicationController{

View File

@ -32,8 +32,8 @@ type REST struct {
registry Registry registry Registry
} }
// NewREST returns a new apiserver.RESTStorage implementation for endpoints // NewStorage returns a new rest.Storage implementation for endpoints
func NewREST(registry Registry) *REST { func NewStorage(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

@ -34,7 +34,7 @@ func TestGetEndpoints(t *testing.T) {
Endpoints: []api.Endpoint{{IP: "127.0.0.1", Port: 9000}}, Endpoints: []api.Endpoint{{IP: "127.0.0.1", Port: 9000}},
}, },
} }
storage := NewREST(registry) storage := NewStorage(registry)
ctx := api.NewContext() ctx := api.NewContext()
obj, err := storage.Get(ctx, "foo") obj, err := storage.Get(ctx, "foo")
if err != nil { if err != nil {
@ -49,7 +49,7 @@ func TestGetEndpointsMissingService(t *testing.T) {
registry := &registrytest.ServiceRegistry{ registry := &registrytest.ServiceRegistry{
Err: errors.NewNotFound("service", "foo"), Err: errors.NewNotFound("service", "foo"),
} }
storage := NewREST(registry) storage := NewStorage(registry)
ctx := api.NewContext() ctx := api.NewContext()
// returns service not found // returns service not found
_, err := storage.Get(ctx, "foo") _, err := storage.Get(ctx, "foo")
@ -73,7 +73,7 @@ func TestGetEndpointsMissingService(t *testing.T) {
func TestEndpointsRegistryList(t *testing.T) { func TestEndpointsRegistryList(t *testing.T) {
registry := registrytest.NewServiceRegistry() registry := registrytest.NewServiceRegistry()
storage := NewREST(registry) storage := NewStorage(registry)
registry.EndpointsList = api.EndpointsList{ registry.EndpointsList = api.EndpointsList{
ListMeta: api.ListMeta{ResourceVersion: "1"}, ListMeta: api.ListMeta{ResourceVersion: "1"},
Items: []api.Endpoints{ Items: []api.Endpoints{

View File

@ -42,7 +42,7 @@ func NewTestEtcdRegistry(client tools.EtcdClient) *Registry {
func NewTestEtcdRegistryWithPods(client tools.EtcdClient) *Registry { func NewTestEtcdRegistryWithPods(client tools.EtcdClient) *Registry {
helper := tools.NewEtcdHelper(client, latest.Codec) helper := tools.NewEtcdHelper(client, latest.Codec)
podStorage, _, _ := podetcd.NewREST(helper) podStorage, _, _ := podetcd.NewStorage(helper)
registry := NewRegistry(helper, pod.NewRegistry(podStorage)) registry := NewRegistry(helper, pod.NewRegistry(podStorage))
return registry return registry
} }

View File

@ -34,9 +34,9 @@ type REST struct {
registry generic.Registry registry generic.Registry
} }
// NewREST returns a new REST. You must use a registry created by // NewStorage returns a new REST. You must use a registry created by
// NewEtcdRegistry unless you're testing. // NewEtcdRegistry unless you're testing.
func NewREST(registry generic.Registry) *REST { func NewStorage(registry generic.Registry) *REST {
return &REST{ return &REST{
registry: registry, registry: registry,
} }
@ -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"
@ -36,7 +36,7 @@ type testRegistry struct {
func NewTestREST() (testRegistry, *REST) { func NewTestREST() (testRegistry, *REST) {
reg := testRegistry{registrytest.NewGeneric(nil)} reg := testRegistry{registrytest.NewGeneric(nil)}
return reg, NewREST(reg) return reg, NewStorage(reg)
} }
func testEvent(name string) *api.Event { func testEvent(name string) *api.Event {
@ -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

@ -35,9 +35,9 @@ type REST struct {
registry generic.Registry registry generic.Registry
} }
// NewREST returns a new REST. You must use a registry created by // NewStorage returns a new REST. You must use a registry created by
// NewEtcdRegistry unless you're testing. // NewEtcdRegistry unless you're testing.
func NewREST(registry generic.Registry) *REST { func NewStorage(registry generic.Registry) *REST {
return &REST{ return &REST{
registry: registry, registry: registry,
} }

View File

@ -38,8 +38,8 @@ type REST struct {
registry Registry registry Registry
} }
// NewREST returns a new apiserver.RESTStorage implementation for minion. // NewStorage returns a new rest.Storage implementation for minion.
func NewREST(m Registry) *REST { func NewStorage(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

@ -28,7 +28,7 @@ import (
) )
func TestMinionRegistryREST(t *testing.T) { func TestMinionRegistryREST(t *testing.T) {
ms := NewREST(registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{})) ms := NewStorage(registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{}))
ctx := api.NewContext() ctx := api.NewContext()
if obj, err := ms.Get(ctx, "foo"); err != nil || obj.(*api.Node).Name != "foo" { if obj, err := ms.Get(ctx, "foo"); err != nil || obj.(*api.Node).Name != "foo" {
t.Errorf("missing expected object") t.Errorf("missing expected object")
@ -88,7 +88,7 @@ func TestMinionRegistryREST(t *testing.T) {
} }
func TestMinionRegistryValidUpdate(t *testing.T) { func TestMinionRegistryValidUpdate(t *testing.T) {
storage := NewREST(registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{})) storage := NewStorage(registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{}))
ctx := api.NewContext() ctx := api.NewContext()
obj, err := storage.Get(ctx, "foo") obj, err := storage.Get(ctx, "foo")
if err != nil { if err != nil {
@ -113,7 +113,7 @@ var (
) )
func TestMinionRegistryValidatesCreate(t *testing.T) { func TestMinionRegistryValidatesCreate(t *testing.T) {
storage := NewREST(registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{})) storage := NewStorage(registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{}))
ctx := api.NewContext() ctx := api.NewContext()
failureCases := map[string]api.Node{ failureCases := map[string]api.Node{
"zero-length Name": { "zero-length Name": {
@ -156,7 +156,7 @@ func contains(nodes *api.NodeList, nodeID string) bool {
func TestCreate(t *testing.T) { func TestCreate(t *testing.T) {
registry := registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{}) registry := registrytest.NewMinionRegistry([]string{"foo", "bar"}, api.NodeResources{})
test := resttest.New(t, NewREST(registry), registry.SetError).ClusterScope() test := resttest.New(t, NewStorage(registry), registry.SetError).ClusterScope()
test.TestCreate( test.TestCreate(
// valid // valid
&api.Node{ &api.Node{

View File

@ -32,8 +32,8 @@ type REST struct {
*etcdgeneric.Etcd *etcdgeneric.Etcd
} }
// NewREST returns a RESTStorage object that will work against namespaces // NewStorage returns a RESTStorage object that will work against namespaces
func NewREST(h tools.EtcdHelper) *REST { func NewStorage(h tools.EtcdHelper) *REST {
store := &etcdgeneric.Etcd{ store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.Namespace{} }, NewFunc: func() runtime.Object { return &api.Namespace{} },
NewListFunc: func() runtime.Object { return &api.NamespaceList{} }, NewListFunc: func() runtime.Object { return &api.NamespaceList{} },

View File

@ -41,7 +41,7 @@ func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) {
func newStorage(t *testing.T) (*REST, *tools.FakeEtcdClient, tools.EtcdHelper) { func newStorage(t *testing.T) (*REST, *tools.FakeEtcdClient, tools.EtcdHelper) {
fakeEtcdClient, h := newHelper(t) fakeEtcdClient, h := newHelper(t)
storage := NewREST(h) storage := NewStorage(h)
return storage, fakeEtcdClient, h return storage, fakeEtcdClient, h
} }
@ -69,7 +69,7 @@ func TestStorage(t *testing.T) {
func TestCreate(t *testing.T) { func TestCreate(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
storage := NewREST(helper) storage := NewStorage(helper)
test := resttest.New(t, storage, fakeEtcdClient.SetError) test := resttest.New(t, storage, fakeEtcdClient.SetError)
namespace := validNewNamespace() namespace := validNewNamespace()
namespace.ObjectMeta = api.ObjectMeta{} namespace.ObjectMeta = api.ObjectMeta{}
@ -94,7 +94,7 @@ func expectNamespace(t *testing.T, out runtime.Object) (*api.Namespace, bool) {
func TestCreateSetsFields(t *testing.T) { func TestCreateSetsFields(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
storage := NewREST(helper) storage := NewStorage(helper)
namespace := validNewNamespace() namespace := validNewNamespace()
_, err := storage.Create(api.NewDefaultContext(), namespace) _, err := storage.Create(api.NewDefaultContext(), namespace)
if err != fakeEtcdClient.Err { if err != fakeEtcdClient.Err {
@ -124,7 +124,7 @@ func TestListEmptyNamespaceList(t *testing.T) {
E: fakeEtcdClient.NewError(tools.EtcdErrorCodeNotFound), E: fakeEtcdClient.NewError(tools.EtcdErrorCodeNotFound),
} }
storage := NewREST(helper) storage := NewStorage(helper)
namespaces, err := storage.List(api.NewContext(), labels.Everything(), fields.Everything()) namespaces, err := storage.List(api.NewContext(), labels.Everything(), fields.Everything())
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
@ -157,7 +157,7 @@ func TestListNamespaceList(t *testing.T) {
}, },
}, },
} }
storage := NewREST(helper) storage := NewStorage(helper)
namespacesObj, err := storage.List(api.NewDefaultContext(), labels.Everything(), fields.Everything()) namespacesObj, err := storage.List(api.NewDefaultContext(), labels.Everything(), fields.Everything())
namespaces := namespacesObj.(*api.NamespaceList) namespaces := namespacesObj.(*api.NamespaceList)
if err != nil { if err != nil {
@ -204,7 +204,7 @@ func TestListNamespaceListSelection(t *testing.T) {
}, },
}, },
} }
storage := NewREST(helper) storage := NewStorage(helper)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
table := []struct { table := []struct {
label, field string label, field string
@ -252,7 +252,7 @@ func TestListNamespaceListSelection(t *testing.T) {
} }
func TestNamespaceDecode(t *testing.T) { func TestNamespaceDecode(t *testing.T) {
storage := NewREST(tools.EtcdHelper{}) storage := NewStorage(tools.EtcdHelper{})
expected := validNewNamespace() expected := validNewNamespace()
expected.Status.Phase = api.NamespaceActive expected.Status.Phase = api.NamespaceActive
body, err := latest.Codec.Encode(expected) body, err := latest.Codec.Encode(expected)
@ -281,7 +281,7 @@ func TestGet(t *testing.T) {
}, },
}, },
} }
storage := NewREST(helper) storage := NewStorage(helper)
obj, err := storage.Get(api.NewContext(), "foo") obj, err := storage.Get(api.NewContext(), "foo")
namespace := obj.(*api.Namespace) namespace := obj.(*api.Namespace)
if err != nil { if err != nil {
@ -311,7 +311,7 @@ func TestDeleteNamespace(t *testing.T) {
}, },
}, },
} }
storage := NewREST(helper) storage := NewStorage(helper)
_, err := storage.Delete(api.NewDefaultContext(), "foo", nil) _, err := storage.Delete(api.NewDefaultContext(), "foo", nil)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)

View File

@ -18,10 +18,9 @@ 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/watch" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
) )
@ -41,26 +40,14 @@ type Registry interface {
DeleteNamespace(ctx api.Context, namespaceID string) error DeleteNamespace(ctx api.Context, namespaceID string) error
} }
// Storage is an interface for a standard REST Storage backend
// TODO: move me somewhere common
type Storage interface {
apiserver.RESTGracefulDeleter
apiserver.RESTLister
apiserver.RESTGetter
apiserver.ResourceWatcher
Create(ctx api.Context, obj runtime.Object) (runtime.Object, error)
Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error)
}
// storage puts strong typing around storage calls // storage puts strong typing around storage calls
type storage struct { type storage struct {
Storage rest.StandardStorage
} }
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched // NewRegistry returns a new Registry interface for the given Storage. Any mismatched
// types will panic. // types will panic.
func NewRegistry(s Storage) Registry { func NewRegistry(s rest.StandardStorage) Registry {
return &storage{s} return &storage{s}
} }

View File

@ -38,8 +38,8 @@ type REST struct {
etcdgeneric.Etcd etcdgeneric.Etcd
} }
// NewREST returns a RESTStorage object that will work against pods. // NewStorage returns a RESTStorage object that will work against pods.
func NewREST(h tools.EtcdHelper) (*REST, *BindingREST, *StatusREST) { func NewStorage(h tools.EtcdHelper) (*REST, *BindingREST, *StatusREST) {
prefix := "/registry/pods" prefix := "/registry/pods"
store := &etcdgeneric.Etcd{ store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.Pod{} }, NewFunc: func() runtime.Object { return &api.Pod{} },

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"
@ -69,7 +69,7 @@ func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) {
func newStorage(t *testing.T) (*REST, *BindingREST, *StatusREST, *tools.FakeEtcdClient, tools.EtcdHelper) { func newStorage(t *testing.T) (*REST, *BindingREST, *StatusREST, *tools.FakeEtcdClient, tools.EtcdHelper) {
fakeEtcdClient, h := newHelper(t) fakeEtcdClient, h := newHelper(t)
storage, bindingStorage, statusStorage := NewREST(h) storage, bindingStorage, statusStorage := NewStorage(h)
storage = storage.WithPodStatus(&fakeCache{statusToReturn: &api.PodStatus{}}) storage = storage.WithPodStatus(&fakeCache{statusToReturn: &api.PodStatus{}})
return storage, bindingStorage, statusStorage, fakeEtcdClient, h return storage, bindingStorage, statusStorage, fakeEtcdClient, h
} }
@ -112,7 +112,7 @@ func TestStorage(t *testing.T) {
func TestCreate(t *testing.T) { func TestCreate(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
cache := &fakeCache{statusToReturn: &api.PodStatus{}} cache := &fakeCache{statusToReturn: &api.PodStatus{}}
storage = storage.WithPodStatus(cache) storage = storage.WithPodStatus(cache)
test := resttest.New(t, storage, fakeEtcdClient.SetError) test := resttest.New(t, storage, fakeEtcdClient.SetError)
@ -132,7 +132,7 @@ func TestCreate(t *testing.T) {
func TestDelete(t *testing.T) { func TestDelete(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
cache := &fakeCache{statusToReturn: &api.PodStatus{}} cache := &fakeCache{statusToReturn: &api.PodStatus{}}
storage = storage.WithPodStatus(cache) storage = storage.WithPodStatus(cache)
test := resttest.New(t, storage, fakeEtcdClient.SetError) test := resttest.New(t, storage, fakeEtcdClient.SetError)
@ -170,7 +170,7 @@ func expectPod(t *testing.T, out runtime.Object) (*api.Pod, bool) {
func TestCreateRegistryError(t *testing.T) { func TestCreateRegistryError(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.Err = fmt.Errorf("test error") fakeEtcdClient.Err = fmt.Errorf("test error")
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
pod := validNewPod() pod := validNewPod()
_, err := storage.Create(api.NewDefaultContext(), pod) _, err := storage.Create(api.NewDefaultContext(), pod)
@ -181,7 +181,7 @@ func TestCreateRegistryError(t *testing.T) {
func TestCreateSetsFields(t *testing.T) { func TestCreateSetsFields(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
cache := &fakeCache{statusToReturn: &api.PodStatus{}} cache := &fakeCache{statusToReturn: &api.PodStatus{}}
storage = storage.WithPodStatus(cache) storage = storage.WithPodStatus(cache)
pod := validNewPod() pod := validNewPod()
@ -205,7 +205,7 @@ func TestCreateSetsFields(t *testing.T) {
func TestListError(t *testing.T) { func TestListError(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.Err = fmt.Errorf("test error") fakeEtcdClient.Err = fmt.Errorf("test error")
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
cache := &fakeCache{} cache := &fakeCache{}
storage = storage.WithPodStatus(cache) storage = storage.WithPodStatus(cache)
pods, err := storage.List(api.NewDefaultContext(), labels.Everything(), fields.Everything()) pods, err := storage.List(api.NewDefaultContext(), labels.Everything(), fields.Everything())
@ -233,7 +233,7 @@ func TestListCacheError(t *testing.T) {
}, },
}, },
} }
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
cache := &fakeCache{errorToReturn: client.ErrPodInfoNotAvailable} cache := &fakeCache{errorToReturn: client.ErrPodInfoNotAvailable}
storage = storage.WithPodStatus(cache) storage = storage.WithPodStatus(cache)
@ -258,7 +258,7 @@ func TestListEmptyPodList(t *testing.T) {
E: fakeEtcdClient.NewError(tools.EtcdErrorCodeNotFound), E: fakeEtcdClient.NewError(tools.EtcdErrorCodeNotFound),
} }
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
cache := &fakeCache{} cache := &fakeCache{}
storage = storage.WithPodStatus(cache) storage = storage.WithPodStatus(cache)
pods, err := storage.List(api.NewContext(), labels.Everything(), fields.Everything()) pods, err := storage.List(api.NewContext(), labels.Everything(), fields.Everything())
@ -296,7 +296,7 @@ func TestListPodList(t *testing.T) {
}, },
}, },
} }
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
cache := &fakeCache{statusToReturn: &api.PodStatus{Phase: api.PodRunning}} cache := &fakeCache{statusToReturn: &api.PodStatus{Phase: api.PodRunning}}
storage = storage.WithPodStatus(cache) storage = storage.WithPodStatus(cache)
@ -347,7 +347,7 @@ func TestListPodListSelection(t *testing.T) {
}, },
}, },
} }
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
cache := &fakeCache{statusToReturn: &api.PodStatus{Phase: api.PodRunning}} cache := &fakeCache{statusToReturn: &api.PodStatus{Phase: api.PodRunning}}
storage = storage.WithPodStatus(cache) storage = storage.WithPodStatus(cache)
@ -414,7 +414,7 @@ func TestListPodListSelection(t *testing.T) {
} }
func TestPodDecode(t *testing.T) { func TestPodDecode(t *testing.T) {
storage, _, _ := NewREST(tools.EtcdHelper{}) storage, _, _ := NewStorage(tools.EtcdHelper{})
expected := validNewPod() expected := validNewPod()
body, err := latest.Codec.Encode(expected) body, err := latest.Codec.Encode(expected)
if err != nil { if err != nil {
@ -443,7 +443,7 @@ func TestGet(t *testing.T) {
}, },
}, },
} }
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
cache := &fakeCache{statusToReturn: &api.PodStatus{Phase: api.PodRunning}} cache := &fakeCache{statusToReturn: &api.PodStatus{Phase: api.PodRunning}}
storage = storage.WithPodStatus(cache) storage = storage.WithPodStatus(cache)
@ -471,7 +471,7 @@ func TestGetCacheError(t *testing.T) {
}, },
}, },
} }
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
cache := &fakeCache{errorToReturn: client.ErrPodInfoNotAvailable} cache := &fakeCache{errorToReturn: client.ErrPodInfoNotAvailable}
storage = storage.WithPodStatus(cache) storage = storage.WithPodStatus(cache)
@ -491,7 +491,7 @@ func TestGetCacheError(t *testing.T) {
func TestPodStorageValidatesCreate(t *testing.T) { func TestPodStorageValidatesCreate(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.Err = fmt.Errorf("test error") fakeEtcdClient.Err = fmt.Errorf("test error")
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
cache := &fakeCache{statusToReturn: &api.PodStatus{}} cache := &fakeCache{statusToReturn: &api.PodStatus{}}
storage = storage.WithPodStatus(cache) storage = storage.WithPodStatus(cache)
@ -511,7 +511,7 @@ func TestPodStorageValidatesCreate(t *testing.T) {
// TODO: remove, this is covered by RESTTest.TestCreate // TODO: remove, this is covered by RESTTest.TestCreate
func TestCreatePod(t *testing.T) { func TestCreatePod(t *testing.T) {
_, helper := newHelper(t) _, helper := newHelper(t)
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
cache := &fakeCache{statusToReturn: &api.PodStatus{}} cache := &fakeCache{statusToReturn: &api.PodStatus{}}
storage = storage.WithPodStatus(cache) storage = storage.WithPodStatus(cache)
@ -535,7 +535,7 @@ func TestCreatePod(t *testing.T) {
// TODO: remove, this is covered by RESTTest.TestCreate // TODO: remove, this is covered by RESTTest.TestCreate
func TestCreateWithConflictingNamespace(t *testing.T) { func TestCreateWithConflictingNamespace(t *testing.T) {
_, helper := newHelper(t) _, helper := newHelper(t)
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
cache := &fakeCache{} cache := &fakeCache{}
storage = storage.WithPodStatus(cache) storage = storage.WithPodStatus(cache)
@ -566,7 +566,7 @@ func TestUpdateWithConflictingNamespace(t *testing.T) {
}, },
}, },
} }
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
cache := &fakeCache{} cache := &fakeCache{}
storage = storage.WithPodStatus(cache) storage = storage.WithPodStatus(cache)
@ -678,11 +678,11 @@ func TestResourceLocation(t *testing.T) {
}, },
}, },
} }
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
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)
@ -712,7 +712,7 @@ func TestDeletePod(t *testing.T) {
}, },
}, },
} }
storage, _, _ := NewREST(helper) storage, _, _ := NewStorage(helper)
cache := &fakeCache{statusToReturn: &api.PodStatus{}} cache := &fakeCache{statusToReturn: &api.PodStatus{}}
storage = storage.WithPodStatus(cache) storage = storage.WithPodStatus(cache)

View File

@ -18,10 +18,9 @@ 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/watch" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
) )
@ -41,26 +40,14 @@ type Registry interface {
DeletePod(ctx api.Context, podID string) error DeletePod(ctx api.Context, podID string) error
} }
// Storage is an interface for a standard REST Storage backend
// TODO: move me somewhere common
type Storage interface {
apiserver.RESTGracefulDeleter
apiserver.RESTLister
apiserver.RESTGetter
apiserver.ResourceWatcher
Create(ctx api.Context, obj runtime.Object) (runtime.Object, error)
Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error)
}
// storage puts strong typing around storage calls // storage puts strong typing around storage calls
type storage struct { type storage struct {
Storage rest.StandardStorage
} }
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched // NewRegistry returns a new Registry interface for the given Storage. Any mismatched
// types will panic. // types will panic.
func NewRegistry(s Storage) Registry { func NewRegistry(s rest.StandardStorage) Registry {
return &storage{s} return &storage{s}
} }

View File

@ -32,8 +32,8 @@ type REST struct {
*etcdgeneric.Etcd *etcdgeneric.Etcd
} }
// NewREST returns a RESTStorage object that will work against ResourceQuota objects. // NewStorage returns a RESTStorage object that will work against ResourceQuota objects.
func NewREST(h tools.EtcdHelper) (*REST, *StatusREST) { func NewStorage(h tools.EtcdHelper) (*REST, *StatusREST) {
prefix := "/registry/resourcequotas" prefix := "/registry/resourcequotas"
store := &etcdgeneric.Etcd{ store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &api.ResourceQuota{} }, NewFunc: func() runtime.Object { return &api.ResourceQuota{} },

View File

@ -46,7 +46,7 @@ func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) {
func newStorage(t *testing.T) (*REST, *StatusREST, *tools.FakeEtcdClient, tools.EtcdHelper) { func newStorage(t *testing.T) (*REST, *StatusREST, *tools.FakeEtcdClient, tools.EtcdHelper) {
fakeEtcdClient, h := newHelper(t) fakeEtcdClient, h := newHelper(t)
storage, statusStorage := NewREST(h) storage, statusStorage := NewStorage(h)
return storage, statusStorage, fakeEtcdClient, h return storage, statusStorage, fakeEtcdClient, h
} }
@ -85,7 +85,7 @@ func TestStorage(t *testing.T) {
func TestCreate(t *testing.T) { func TestCreate(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
storage, _ := NewREST(helper) storage, _ := NewStorage(helper)
test := resttest.New(t, storage, fakeEtcdClient.SetError) test := resttest.New(t, storage, fakeEtcdClient.SetError)
resourcequota := validNewResourceQuota() resourcequota := validNewResourceQuota()
resourcequota.ObjectMeta = api.ObjectMeta{} resourcequota.ObjectMeta = api.ObjectMeta{}
@ -111,7 +111,7 @@ func expectResourceQuota(t *testing.T, out runtime.Object) (*api.ResourceQuota,
func TestCreateRegistryError(t *testing.T) { func TestCreateRegistryError(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.Err = fmt.Errorf("test error") fakeEtcdClient.Err = fmt.Errorf("test error")
storage, _ := NewREST(helper) storage, _ := NewStorage(helper)
resourcequota := validNewResourceQuota() resourcequota := validNewResourceQuota()
_, err := storage.Create(api.NewDefaultContext(), resourcequota) _, err := storage.Create(api.NewDefaultContext(), resourcequota)
@ -122,7 +122,7 @@ func TestCreateRegistryError(t *testing.T) {
func TestCreateSetsFields(t *testing.T) { func TestCreateSetsFields(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
storage, _ := NewREST(helper) storage, _ := NewStorage(helper)
resourcequota := validNewResourceQuota() resourcequota := validNewResourceQuota()
_, err := storage.Create(api.NewDefaultContext(), resourcequota) _, err := storage.Create(api.NewDefaultContext(), resourcequota)
if err != fakeEtcdClient.Err { if err != fakeEtcdClient.Err {
@ -144,7 +144,7 @@ func TestCreateSetsFields(t *testing.T) {
func TestListError(t *testing.T) { func TestListError(t *testing.T) {
fakeEtcdClient, helper := newHelper(t) fakeEtcdClient, helper := newHelper(t)
fakeEtcdClient.Err = fmt.Errorf("test error") fakeEtcdClient.Err = fmt.Errorf("test error")
storage, _ := NewREST(helper) storage, _ := NewStorage(helper)
resourcequotas, err := storage.List(api.NewDefaultContext(), labels.Everything(), fields.Everything()) resourcequotas, err := storage.List(api.NewDefaultContext(), labels.Everything(), fields.Everything())
if err != fakeEtcdClient.Err { if err != fakeEtcdClient.Err {
t.Fatalf("Expected %#v, Got %#v", fakeEtcdClient.Err, err) t.Fatalf("Expected %#v, Got %#v", fakeEtcdClient.Err, err)
@ -162,7 +162,7 @@ func TestListEmptyResourceQuotaList(t *testing.T) {
E: fakeEtcdClient.NewError(tools.EtcdErrorCodeNotFound), E: fakeEtcdClient.NewError(tools.EtcdErrorCodeNotFound),
} }
storage, _ := NewREST(helper) storage, _ := NewStorage(helper)
resourcequotas, err := storage.List(api.NewContext(), labels.Everything(), fields.Everything()) resourcequotas, err := storage.List(api.NewContext(), labels.Everything(), fields.Everything())
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
@ -196,7 +196,7 @@ func TestListResourceQuotaList(t *testing.T) {
}, },
}, },
} }
storage, _ := NewREST(helper) storage, _ := NewStorage(helper)
resourcequotasObj, err := storage.List(api.NewDefaultContext(), labels.Everything(), fields.Everything()) resourcequotasObj, err := storage.List(api.NewDefaultContext(), labels.Everything(), fields.Everything())
resourcequotas := resourcequotasObj.(*api.ResourceQuotaList) resourcequotas := resourcequotasObj.(*api.ResourceQuotaList)
if err != nil { if err != nil {
@ -236,7 +236,7 @@ func TestListResourceQuotaListSelection(t *testing.T) {
}, },
}, },
} }
storage, _ := NewREST(helper) storage, _ := NewStorage(helper)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
table := []struct { table := []struct {
@ -282,7 +282,7 @@ func TestListResourceQuotaListSelection(t *testing.T) {
} }
func TestResourceQuotaDecode(t *testing.T) { func TestResourceQuotaDecode(t *testing.T) {
storage, _ := NewREST(tools.EtcdHelper{}) storage, _ := NewStorage(tools.EtcdHelper{})
expected := validNewResourceQuota() expected := validNewResourceQuota()
body, err := latest.Codec.Encode(expected) body, err := latest.Codec.Encode(expected)
if err != nil { if err != nil {
@ -309,7 +309,7 @@ func TestGet(t *testing.T) {
}, },
}, },
} }
storage, _ := NewREST(helper) storage, _ := NewStorage(helper)
obj, err := storage.Get(api.WithNamespace(api.NewContext(), "test"), "foo") obj, err := storage.Get(api.WithNamespace(api.NewContext(), "test"), "foo")
resourcequota := obj.(*api.ResourceQuota) resourcequota := obj.(*api.ResourceQuota)
if err != nil { if err != nil {
@ -339,7 +339,7 @@ func TestDeleteResourceQuota(t *testing.T) {
}, },
}, },
} }
storage, _ := NewREST(helper) storage, _ := NewStorage(helper)
_, err := storage.Delete(api.NewDefaultContext(), "foo", nil) _, err := storage.Delete(api.NewDefaultContext(), "foo", nil)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)

View File

@ -18,10 +18,9 @@ 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/watch" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
) )
@ -41,26 +40,14 @@ type Registry interface {
DeleteResourceQuota(ctx api.Context, podID string) error DeleteResourceQuota(ctx api.Context, podID string) error
} }
// Storage is an interface for a standard REST Storage backend
// TODO: move me somewhere common
type Storage interface {
apiserver.RESTGracefulDeleter
apiserver.RESTLister
apiserver.RESTGetter
apiserver.ResourceWatcher
Create(ctx api.Context, obj runtime.Object) (runtime.Object, error)
Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error)
}
// storage puts strong typing around storage calls // storage puts strong typing around storage calls
type storage struct { type storage struct {
Storage rest.StandardStorage
} }
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched // NewRegistry returns a new Registry interface for the given Storage. Any mismatched
// types will panic. // types will panic.
func NewRegistry(s Storage) Registry { func NewRegistry(s rest.StandardStorage) Registry {
return &storage{s} return &storage{s}
} }

View File

@ -35,9 +35,9 @@ type REST struct {
registry generic.Registry registry generic.Registry
} }
// NewREST returns a new REST. You must use a registry created by // NewStorage returns a new REST. You must use a registry created by
// NewEtcdRegistry unless you're testing. // NewEtcdRegistry unless you're testing.
func NewREST(registry generic.Registry) *REST { func NewStorage(registry generic.Registry) *REST {
return &REST{ return &REST{
registry: registry, registry: registry,
} }

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"
@ -35,7 +35,7 @@ type testRegistry struct {
func NewTestREST() (testRegistry, *REST) { func NewTestREST() (testRegistry, *REST) {
reg := testRegistry{registrytest.NewGeneric(nil)} reg := testRegistry{registrytest.NewGeneric(nil)}
return reg, NewREST(reg) return reg, NewStorage(reg)
} }
func testSecret(name string) *api.Secret { func testSecret(name string) *api.Secret {
@ -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

@ -45,8 +45,8 @@ type REST struct {
clusterName string clusterName string
} }
// NewREST returns a new REST. // NewStorage returns a new REST.
func NewREST(registry Registry, cloud cloudprovider.Interface, machines minion.Registry, portalNet *net.IPNet, func NewStorage(registry Registry, cloud cloudprovider.Interface, machines minion.Registry, portalNet *net.IPNet,
clusterName string) *REST { clusterName string) *REST {
// TODO: Before we can replicate masters, this has to be synced (e.g. lives in etcd) // TODO: Before we can replicate masters, this has to be synced (e.g. lives in etcd)
ipa := newIPAllocator(portalNet) ipa := newIPAllocator(portalNet)
@ -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"
@ -44,7 +44,7 @@ func TestServiceRegistryCreate(t *testing.T) {
registry := registrytest.NewServiceRegistry() registry := registrytest.NewServiceRegistry()
fakeCloud := &cloud.FakeCloud{} fakeCloud := &cloud.FakeCloud{}
machines := []string{"foo", "bar", "baz"} machines := []string{"foo", "bar", "baz"}
storage := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") storage := NewStorage(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes")
storage.portalMgr.randomAttempts = 0 storage.portalMgr.randomAttempts = 0
svc := &api.Service{ svc := &api.Service{
@ -85,7 +85,7 @@ func TestServiceRegistryCreate(t *testing.T) {
func TestServiceStorageValidatesCreate(t *testing.T) { func TestServiceStorageValidatesCreate(t *testing.T) {
registry := registrytest.NewServiceRegistry() registry := registrytest.NewServiceRegistry()
storage := NewREST(registry, nil, nil, makeIPNet(t), "kubernetes") storage := NewStorage(registry, nil, nil, makeIPNet(t), "kubernetes")
failureCases := map[string]api.Service{ failureCases := map[string]api.Service{
"empty ID": { "empty ID": {
ObjectMeta: api.ObjectMeta{Name: ""}, ObjectMeta: api.ObjectMeta{Name: ""},
@ -128,7 +128,7 @@ func TestServiceRegistryUpdate(t *testing.T) {
Selector: map[string]string{"bar": "baz1"}, Selector: map[string]string{"bar": "baz1"},
}, },
}) })
storage := NewREST(registry, nil, nil, makeIPNet(t), "kubernetes") storage := NewStorage(registry, nil, nil, makeIPNet(t), "kubernetes")
updated_svc, created, err := storage.Update(ctx, &api.Service{ updated_svc, created, err := storage.Update(ctx, &api.Service{
ObjectMeta: api.ObjectMeta{Name: "foo"}, ObjectMeta: api.ObjectMeta{Name: "foo"},
Spec: api.ServiceSpec{ Spec: api.ServiceSpec{
@ -166,7 +166,7 @@ func TestServiceStorageValidatesUpdate(t *testing.T) {
Selector: map[string]string{"bar": "baz"}, Selector: map[string]string{"bar": "baz"},
}, },
}) })
storage := NewREST(registry, nil, nil, makeIPNet(t), "kubernetes") storage := NewStorage(registry, nil, nil, makeIPNet(t), "kubernetes")
failureCases := map[string]api.Service{ failureCases := map[string]api.Service{
"empty ID": { "empty ID": {
ObjectMeta: api.ObjectMeta{Name: ""}, ObjectMeta: api.ObjectMeta{Name: ""},
@ -203,7 +203,7 @@ func TestServiceRegistryExternalService(t *testing.T) {
registry := registrytest.NewServiceRegistry() registry := registrytest.NewServiceRegistry()
fakeCloud := &cloud.FakeCloud{} fakeCloud := &cloud.FakeCloud{}
machines := []string{"foo", "bar", "baz"} machines := []string{"foo", "bar", "baz"}
storage := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") storage := NewStorage(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes")
svc := &api.Service{ svc := &api.Service{
ObjectMeta: api.ObjectMeta{Name: "foo"}, ObjectMeta: api.ObjectMeta{Name: "foo"},
Spec: api.ServiceSpec{ Spec: api.ServiceSpec{
@ -236,7 +236,7 @@ func TestServiceRegistryExternalServiceError(t *testing.T) {
Err: fmt.Errorf("test error"), Err: fmt.Errorf("test error"),
} }
machines := []string{"foo", "bar", "baz"} machines := []string{"foo", "bar", "baz"}
storage := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") storage := NewStorage(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes")
svc := &api.Service{ svc := &api.Service{
ObjectMeta: api.ObjectMeta{Name: "foo"}, ObjectMeta: api.ObjectMeta{Name: "foo"},
Spec: api.ServiceSpec{ Spec: api.ServiceSpec{
@ -262,7 +262,7 @@ func TestServiceRegistryDelete(t *testing.T) {
registry := registrytest.NewServiceRegistry() registry := registrytest.NewServiceRegistry()
fakeCloud := &cloud.FakeCloud{} fakeCloud := &cloud.FakeCloud{}
machines := []string{"foo", "bar", "baz"} machines := []string{"foo", "bar", "baz"}
storage := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") storage := NewStorage(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes")
svc := &api.Service{ svc := &api.Service{
ObjectMeta: api.ObjectMeta{Name: "foo"}, ObjectMeta: api.ObjectMeta{Name: "foo"},
Spec: api.ServiceSpec{ Spec: api.ServiceSpec{
@ -286,7 +286,7 @@ func TestServiceRegistryDeleteExternal(t *testing.T) {
registry := registrytest.NewServiceRegistry() registry := registrytest.NewServiceRegistry()
fakeCloud := &cloud.FakeCloud{} fakeCloud := &cloud.FakeCloud{}
machines := []string{"foo", "bar", "baz"} machines := []string{"foo", "bar", "baz"}
storage := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") storage := NewStorage(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes")
svc := &api.Service{ svc := &api.Service{
ObjectMeta: api.ObjectMeta{Name: "foo"}, ObjectMeta: api.ObjectMeta{Name: "foo"},
Spec: api.ServiceSpec{ Spec: api.ServiceSpec{
@ -311,7 +311,7 @@ func TestServiceRegistryUpdateExternalService(t *testing.T) {
registry := registrytest.NewServiceRegistry() registry := registrytest.NewServiceRegistry()
fakeCloud := &cloud.FakeCloud{} fakeCloud := &cloud.FakeCloud{}
machines := []string{"foo", "bar", "baz"} machines := []string{"foo", "bar", "baz"}
storage := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") storage := NewStorage(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes")
// Create non-external load balancer. // Create non-external load balancer.
svc1 := &api.Service{ svc1 := &api.Service{
@ -355,7 +355,7 @@ func TestServiceRegistryGet(t *testing.T) {
registry := registrytest.NewServiceRegistry() registry := registrytest.NewServiceRegistry()
fakeCloud := &cloud.FakeCloud{} fakeCloud := &cloud.FakeCloud{}
machines := []string{"foo", "bar", "baz"} machines := []string{"foo", "bar", "baz"}
storage := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") storage := NewStorage(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes")
registry.CreateService(ctx, &api.Service{ registry.CreateService(ctx, &api.Service{
ObjectMeta: api.ObjectMeta{Name: "foo"}, ObjectMeta: api.ObjectMeta{Name: "foo"},
Spec: api.ServiceSpec{ Spec: api.ServiceSpec{
@ -377,14 +377,14 @@ func TestServiceRegistryResourceLocation(t *testing.T) {
registry.Endpoints = api.Endpoints{Endpoints: []api.Endpoint{{IP: "foo", Port: 80}}} registry.Endpoints = api.Endpoints{Endpoints: []api.Endpoint{{IP: "foo", Port: 80}}}
fakeCloud := &cloud.FakeCloud{} fakeCloud := &cloud.FakeCloud{}
machines := []string{"foo", "bar", "baz"} machines := []string{"foo", "bar", "baz"}
storage := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") storage := NewStorage(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes")
registry.CreateService(ctx, &api.Service{ registry.CreateService(ctx, &api.Service{
ObjectMeta: api.ObjectMeta{Name: "foo"}, ObjectMeta: api.ObjectMeta{Name: "foo"},
Spec: api.ServiceSpec{ Spec: api.ServiceSpec{
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)
@ -408,7 +408,7 @@ func TestServiceRegistryList(t *testing.T) {
registry := registrytest.NewServiceRegistry() registry := registrytest.NewServiceRegistry()
fakeCloud := &cloud.FakeCloud{} fakeCloud := &cloud.FakeCloud{}
machines := []string{"foo", "bar", "baz"} machines := []string{"foo", "bar", "baz"}
storage := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") storage := NewStorage(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes")
registry.CreateService(ctx, &api.Service{ registry.CreateService(ctx, &api.Service{
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: api.NamespaceDefault}, ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: api.NamespaceDefault},
Spec: api.ServiceSpec{ Spec: api.ServiceSpec{
@ -445,7 +445,7 @@ func TestServiceRegistryIPAllocation(t *testing.T) {
registry := registrytest.NewServiceRegistry() registry := registrytest.NewServiceRegistry()
fakeCloud := &cloud.FakeCloud{} fakeCloud := &cloud.FakeCloud{}
machines := []string{"foo", "bar", "baz"} machines := []string{"foo", "bar", "baz"}
rest := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") rest := NewStorage(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes")
rest.portalMgr.randomAttempts = 0 rest.portalMgr.randomAttempts = 0
svc1 := &api.Service{ svc1 := &api.Service{
@ -507,7 +507,7 @@ func TestServiceRegistryIPReallocation(t *testing.T) {
registry := registrytest.NewServiceRegistry() registry := registrytest.NewServiceRegistry()
fakeCloud := &cloud.FakeCloud{} fakeCloud := &cloud.FakeCloud{}
machines := []string{"foo", "bar", "baz"} machines := []string{"foo", "bar", "baz"}
rest := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") rest := NewStorage(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes")
rest.portalMgr.randomAttempts = 0 rest.portalMgr.randomAttempts = 0
svc1 := &api.Service{ svc1 := &api.Service{
@ -555,7 +555,7 @@ func TestServiceRegistryIPUpdate(t *testing.T) {
registry := registrytest.NewServiceRegistry() registry := registrytest.NewServiceRegistry()
fakeCloud := &cloud.FakeCloud{} fakeCloud := &cloud.FakeCloud{}
machines := []string{"foo", "bar", "baz"} machines := []string{"foo", "bar", "baz"}
rest := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") rest := NewStorage(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes")
rest.portalMgr.randomAttempts = 0 rest.portalMgr.randomAttempts = 0
svc := &api.Service{ svc := &api.Service{
@ -601,7 +601,7 @@ func TestServiceRegistryIPExternalLoadBalancer(t *testing.T) {
registry := registrytest.NewServiceRegistry() registry := registrytest.NewServiceRegistry()
fakeCloud := &cloud.FakeCloud{} fakeCloud := &cloud.FakeCloud{}
machines := []string{"foo", "bar", "baz"} machines := []string{"foo", "bar", "baz"}
rest := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") rest := NewStorage(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes")
rest.portalMgr.randomAttempts = 0 rest.portalMgr.randomAttempts = 0
svc := &api.Service{ svc := &api.Service{
@ -640,7 +640,7 @@ func TestServiceRegistryIPReloadFromStorage(t *testing.T) {
registry := registrytest.NewServiceRegistry() registry := registrytest.NewServiceRegistry()
fakeCloud := &cloud.FakeCloud{} fakeCloud := &cloud.FakeCloud{}
machines := []string{"foo", "bar", "baz"} machines := []string{"foo", "bar", "baz"}
rest1 := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") rest1 := NewStorage(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes")
rest1.portalMgr.randomAttempts = 0 rest1.portalMgr.randomAttempts = 0
svc := &api.Service{ svc := &api.Service{
@ -666,7 +666,7 @@ func TestServiceRegistryIPReloadFromStorage(t *testing.T) {
rest1.Create(ctx, svc) rest1.Create(ctx, svc)
// This will reload from storage, finding the previous 2 // This will reload from storage, finding the previous 2
rest2 := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") rest2 := NewStorage(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes")
rest2.portalMgr.randomAttempts = 0 rest2.portalMgr.randomAttempts = 0
svc = &api.Service{ svc = &api.Service{
@ -726,7 +726,7 @@ func TestCreate(t *testing.T) {
registry := registrytest.NewServiceRegistry() registry := registrytest.NewServiceRegistry()
fakeCloud := &cloud.FakeCloud{} fakeCloud := &cloud.FakeCloud{}
machines := []string{"foo", "bar", "baz"} machines := []string{"foo", "bar", "baz"}
rest := NewREST(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes") rest := NewStorage(registry, fakeCloud, registrytest.NewMinionRegistry(machines, api.NodeResources{}), makeIPNet(t), "kubernetes")
rest.portalMgr.randomAttempts = 0 rest.portalMgr.randomAttempts = 0
test := resttest.New(t, rest, registry.SetError) test := resttest.New(t, rest, registry.SetError)