Make Service storage a wrapper around other storages
The registry abstraction is unnecessary and adds direct coupling to the core types. By using a wrapper, we carry through the default implementations of the non-mutating operations. The DeleteCollection method is explicitly patched out since it cannot be correctly implemented on the storage currently. As a result, TableConvertor is now exposed. A few other minor refactorings * Corrected the case of some variables * Used functions instead of methods for several helper methods * Removed the legacy Deleter - service was the only remaining consumer Kubernetes-commit: 110b064d630ca39220696225dd597e7d33b95f4f
This commit is contained in:
parent
9c562ef4be
commit
7b21554cfc
|
|
@ -2839,65 +2839,6 @@ func TestDeleteWithOptionsQueryAndBody(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLegacyDelete(t *testing.T) {
|
|
||||||
storage := map[string]rest.Storage{}
|
|
||||||
simpleStorage := SimpleRESTStorage{}
|
|
||||||
ID := "id"
|
|
||||||
storage["simple"] = LegacyRESTStorage{&simpleStorage}
|
|
||||||
var _ rest.Deleter = storage["simple"].(LegacyRESTStorage)
|
|
||||||
handler := handle(storage)
|
|
||||||
server := httptest.NewServer(handler)
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
client := http.Client{}
|
|
||||||
request, err := http.NewRequest("DELETE", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, nil)
|
|
||||||
res, err := client.Do(request)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
if res.StatusCode != http.StatusOK {
|
|
||||||
t.Errorf("unexpected response: %#v", res)
|
|
||||||
}
|
|
||||||
if simpleStorage.deleted != ID {
|
|
||||||
t.Errorf("Unexpected delete: %s, expected %s", simpleStorage.deleted, ID)
|
|
||||||
}
|
|
||||||
if simpleStorage.deleteOptions != nil {
|
|
||||||
t.Errorf("unexpected delete options: %#v", simpleStorage.deleteOptions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLegacyDeleteIgnoresOptions(t *testing.T) {
|
|
||||||
storage := map[string]rest.Storage{}
|
|
||||||
simpleStorage := SimpleRESTStorage{}
|
|
||||||
ID := "id"
|
|
||||||
storage["simple"] = LegacyRESTStorage{&simpleStorage}
|
|
||||||
handler := handle(storage)
|
|
||||||
server := httptest.NewServer(handler)
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
item := metav1.NewDeleteOptions(300)
|
|
||||||
body, err := runtime.Encode(codec, item)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
client := http.Client{}
|
|
||||||
request, err := http.NewRequest("DELETE", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
|
|
||||||
res, err := client.Do(request)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
if res.StatusCode != http.StatusOK {
|
|
||||||
t.Errorf("unexpected response: %#v", res)
|
|
||||||
}
|
|
||||||
if simpleStorage.deleted != ID {
|
|
||||||
t.Errorf("Unexpected delete: %s, expected %s", simpleStorage.deleted, ID)
|
|
||||||
}
|
|
||||||
if simpleStorage.deleteOptions != nil {
|
|
||||||
t.Errorf("unexpected delete options: %#v", simpleStorage.deleteOptions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDeleteInvokesAdmissionControl(t *testing.T) {
|
func TestDeleteInvokesAdmissionControl(t *testing.T) {
|
||||||
// TODO: remove mutating deny when we removed it from the endpoint implementation and ported all plugins
|
// TODO: remove mutating deny when we removed it from the endpoint implementation and ported all plugins
|
||||||
for _, admit := range []admission.Interface{alwaysMutatingDeny{}, alwaysValidatingDeny{}} {
|
for _, admit := range []admission.Interface{alwaysMutatingDeny{}, alwaysValidatingDeny{}} {
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,6 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
lister, isLister := storage.(rest.Lister)
|
lister, isLister := storage.(rest.Lister)
|
||||||
getter, isGetter := storage.(rest.Getter)
|
getter, isGetter := storage.(rest.Getter)
|
||||||
getterWithOptions, isGetterWithOptions := storage.(rest.GetterWithOptions)
|
getterWithOptions, isGetterWithOptions := storage.(rest.GetterWithOptions)
|
||||||
deleter, isDeleter := storage.(rest.Deleter)
|
|
||||||
gracefulDeleter, isGracefulDeleter := storage.(rest.GracefulDeleter)
|
gracefulDeleter, isGracefulDeleter := storage.(rest.GracefulDeleter)
|
||||||
collectionDeleter, isCollectionDeleter := storage.(rest.CollectionDeleter)
|
collectionDeleter, isCollectionDeleter := storage.(rest.CollectionDeleter)
|
||||||
updater, isUpdater := storage.(rest.Updater)
|
updater, isUpdater := storage.(rest.Updater)
|
||||||
|
|
@ -273,16 +272,12 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
|
|
||||||
var versionedDeleteOptions runtime.Object
|
var versionedDeleteOptions runtime.Object
|
||||||
var versionedDeleterObject interface{}
|
var versionedDeleterObject interface{}
|
||||||
switch {
|
if isGracefulDeleter {
|
||||||
case isGracefulDeleter:
|
|
||||||
versionedDeleteOptions, err = a.group.Creater.New(optionsExternalVersion.WithKind("DeleteOptions"))
|
versionedDeleteOptions, err = a.group.Creater.New(optionsExternalVersion.WithKind("DeleteOptions"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
versionedDeleterObject = indirectArbitraryPointer(versionedDeleteOptions)
|
versionedDeleterObject = indirectArbitraryPointer(versionedDeleteOptions)
|
||||||
isDeleter = true
|
|
||||||
case isDeleter:
|
|
||||||
gracefulDeleter = rest.GracefulDeleteAdapter{Deleter: deleter}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
versionedStatusPtr, err := a.group.Creater.New(optionsExternalVersion.WithKind("Status"))
|
versionedStatusPtr, err := a.group.Creater.New(optionsExternalVersion.WithKind("Status"))
|
||||||
|
|
@ -416,7 +411,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
}
|
}
|
||||||
actions = appendIf(actions, action{"PUT", itemPath, nameParams, namer, false}, isUpdater)
|
actions = appendIf(actions, action{"PUT", itemPath, nameParams, namer, false}, isUpdater)
|
||||||
actions = appendIf(actions, action{"PATCH", itemPath, nameParams, namer, false}, isPatcher)
|
actions = appendIf(actions, action{"PATCH", itemPath, nameParams, namer, false}, isPatcher)
|
||||||
actions = appendIf(actions, action{"DELETE", itemPath, nameParams, namer, false}, isDeleter)
|
actions = appendIf(actions, action{"DELETE", itemPath, nameParams, namer, false}, isGracefulDeleter)
|
||||||
actions = appendIf(actions, action{"WATCH", "watch/" + itemPath, nameParams, namer, false}, isWatcher)
|
actions = appendIf(actions, action{"WATCH", "watch/" + itemPath, nameParams, namer, false}, isWatcher)
|
||||||
actions = appendIf(actions, action{"CONNECT", itemPath, nameParams, namer, false}, isConnecter)
|
actions = appendIf(actions, action{"CONNECT", itemPath, nameParams, namer, false}, isConnecter)
|
||||||
actions = appendIf(actions, action{"CONNECT", itemPath + "/{path:*}", proxyParams, namer, false}, isConnecter && connectSubpath)
|
actions = appendIf(actions, action{"CONNECT", itemPath + "/{path:*}", proxyParams, namer, false}, isConnecter && connectSubpath)
|
||||||
|
|
@ -462,7 +457,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
}
|
}
|
||||||
actions = appendIf(actions, action{"PUT", itemPath, nameParams, namer, false}, isUpdater)
|
actions = appendIf(actions, action{"PUT", itemPath, nameParams, namer, false}, isUpdater)
|
||||||
actions = appendIf(actions, action{"PATCH", itemPath, nameParams, namer, false}, isPatcher)
|
actions = appendIf(actions, action{"PATCH", itemPath, nameParams, namer, false}, isPatcher)
|
||||||
actions = appendIf(actions, action{"DELETE", itemPath, nameParams, namer, false}, isDeleter)
|
actions = appendIf(actions, action{"DELETE", itemPath, nameParams, namer, false}, isGracefulDeleter)
|
||||||
actions = appendIf(actions, action{"WATCH", "watch/" + itemPath, nameParams, namer, false}, isWatcher)
|
actions = appendIf(actions, action{"WATCH", "watch/" + itemPath, nameParams, namer, false}, isWatcher)
|
||||||
actions = appendIf(actions, action{"CONNECT", itemPath, nameParams, namer, false}, isConnecter)
|
actions = appendIf(actions, action{"CONNECT", itemPath, nameParams, namer, false}, isConnecter)
|
||||||
actions = appendIf(actions, action{"CONNECT", itemPath + "/{path:*}", proxyParams, namer, false}, isConnecter && connectSubpath)
|
actions = appendIf(actions, action{"CONNECT", itemPath + "/{path:*}", proxyParams, namer, false}, isConnecter && connectSubpath)
|
||||||
|
|
|
||||||
|
|
@ -137,16 +137,6 @@ type TableConvertor interface {
|
||||||
ConvertToTable(ctx genericapirequest.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error)
|
ConvertToTable(ctx genericapirequest.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deleter is an object that can delete a named RESTful resource.
|
|
||||||
type Deleter interface {
|
|
||||||
// Delete finds a resource in the storage and deletes it.
|
|
||||||
// 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.
|
|
||||||
// Delete *may* return the object that was deleted, or a status object indicating additional
|
|
||||||
// information about deletion.
|
|
||||||
Delete(ctx genericapirequest.Context, name string) (runtime.Object, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GracefulDeleter knows how to pass deletion options to allow delayed deletion of a
|
// GracefulDeleter knows how to pass deletion options to allow delayed deletion of a
|
||||||
// RESTful object.
|
// RESTful object.
|
||||||
type GracefulDeleter interface {
|
type GracefulDeleter interface {
|
||||||
|
|
@ -162,17 +152,6 @@ type GracefulDeleter interface {
|
||||||
Delete(ctx genericapirequest.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error)
|
Delete(ctx genericapirequest.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GracefulDeleteAdapter adapts the Deleter interface to GracefulDeleter
|
|
||||||
type GracefulDeleteAdapter struct {
|
|
||||||
Deleter
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete implements RESTGracefulDeleter in terms of Deleter
|
|
||||||
func (w GracefulDeleteAdapter) Delete(ctx genericapirequest.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
|
|
||||||
obj, err := w.Deleter.Delete(ctx, name)
|
|
||||||
return obj, true, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// CollectionDeleter is an object that can delete a collection
|
// CollectionDeleter is an object that can delete a collection
|
||||||
// of RESTful resources.
|
// of RESTful resources.
|
||||||
type CollectionDeleter interface {
|
type CollectionDeleter interface {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue