registry: move generic registry tester into k8s.io/apiserver
Kubernetes-commit: 0b100cb69b9f99445aa523cf9c4abae8f62c751a
This commit is contained in:
		
							parent
							
								
									bd9bc99807
								
							
						
					
					
						commit
						29de1cdd6d
					
				|  | @ -39,6 +39,7 @@ filegroup( | ||||||
|         ":package-srcs", |         ":package-srcs", | ||||||
|         "//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:all-srcs", |         "//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:all-srcs", | ||||||
|         "//staging/src/k8s.io/apiserver/pkg/registry/generic/rest:all-srcs", |         "//staging/src/k8s.io/apiserver/pkg/registry/generic/rest:all-srcs", | ||||||
|  |         "//staging/src/k8s.io/apiserver/pkg/registry/generic/testing:all-srcs", | ||||||
|     ], |     ], | ||||||
|     tags = ["automanaged"], |     tags = ["automanaged"], | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,35 @@ | ||||||
|  | load("@io_bazel_rules_go//go:def.bzl", "go_library") | ||||||
|  | 
 | ||||||
|  | go_library( | ||||||
|  |     name = "go_default_library", | ||||||
|  |     srcs = ["tester.go"], | ||||||
|  |     importpath = "k8s.io/apiserver/pkg/registry/generic/testing", | ||||||
|  |     visibility = ["//visibility:public"], | ||||||
|  |     deps = [ | ||||||
|  |         "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", | ||||||
|  |         "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", | ||||||
|  |         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", | ||||||
|  |         "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library", | ||||||
|  |         "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", | ||||||
|  |         "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", | ||||||
|  |         "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", | ||||||
|  |         "//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", | ||||||
|  |         "//vendor/k8s.io/apiserver/pkg/registry/rest/resttest:go_default_library", | ||||||
|  |         "//vendor/k8s.io/apiserver/pkg/storage/etcd:go_default_library", | ||||||
|  |         "//vendor/k8s.io/apiserver/pkg/storage/testing:go_default_library", | ||||||
|  |     ], | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | filegroup( | ||||||
|  |     name = "package-srcs", | ||||||
|  |     srcs = glob(["**"]), | ||||||
|  |     tags = ["automanaged"], | ||||||
|  |     visibility = ["//visibility:private"], | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | filegroup( | ||||||
|  |     name = "all-srcs", | ||||||
|  |     srcs = [":package-srcs"], | ||||||
|  |     tags = ["automanaged"], | ||||||
|  |     visibility = ["//visibility:public"], | ||||||
|  | ) | ||||||
|  | @ -0,0 +1,202 @@ | ||||||
|  | /* | ||||||
|  | Copyright 2015 The Kubernetes Authors. | ||||||
|  | 
 | ||||||
|  | Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | you may not use this file except in compliance with the License. | ||||||
|  | You may obtain a copy of the License at | ||||||
|  | 
 | ||||||
|  |     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | 
 | ||||||
|  | Unless required by applicable law or agreed to in writing, software | ||||||
|  | distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  | See the License for the specific language governing permissions and | ||||||
|  | limitations under the License. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | package tester | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"k8s.io/apimachinery/pkg/api/errors" | ||||||
|  | 	"k8s.io/apimachinery/pkg/api/meta" | ||||||
|  | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||
|  | 	"k8s.io/apimachinery/pkg/fields" | ||||||
|  | 	"k8s.io/apimachinery/pkg/labels" | ||||||
|  | 	"k8s.io/apimachinery/pkg/runtime" | ||||||
|  | 	genericapirequest "k8s.io/apiserver/pkg/endpoints/request" | ||||||
|  | 	genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" | ||||||
|  | 	"k8s.io/apiserver/pkg/registry/rest/resttest" | ||||||
|  | 	etcdstorage "k8s.io/apiserver/pkg/storage/etcd" | ||||||
|  | 	storagetesting "k8s.io/apiserver/pkg/storage/testing" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type Tester struct { | ||||||
|  | 	tester  *resttest.Tester | ||||||
|  | 	storage *genericregistry.Store | ||||||
|  | } | ||||||
|  | type UpdateFunc func(runtime.Object) runtime.Object | ||||||
|  | 
 | ||||||
|  | func New(t *testing.T, storage *genericregistry.Store, scheme *runtime.Scheme) *Tester { | ||||||
|  | 	return &Tester{ | ||||||
|  | 		tester:  resttest.New(t, storage, scheme), | ||||||
|  | 		storage: storage, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Tester) TestNamespace() string { | ||||||
|  | 	return t.tester.TestNamespace() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Tester) ClusterScope() *Tester { | ||||||
|  | 	t.tester = t.tester.ClusterScope() | ||||||
|  | 	return t | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Tester) Namer(namer func(int) string) *Tester { | ||||||
|  | 	t.tester = t.tester.Namer(namer) | ||||||
|  | 	return t | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Tester) AllowCreateOnUpdate() *Tester { | ||||||
|  | 	t.tester = t.tester.AllowCreateOnUpdate() | ||||||
|  | 	return t | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Tester) GeneratesName() *Tester { | ||||||
|  | 	t.tester = t.tester.GeneratesName() | ||||||
|  | 	return t | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Tester) ReturnDeletedObject() *Tester { | ||||||
|  | 	t.tester = t.tester.ReturnDeletedObject() | ||||||
|  | 	return t | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Tester) TestCreate(valid runtime.Object, invalid ...runtime.Object) { | ||||||
|  | 	t.tester.TestCreate( | ||||||
|  | 		valid, | ||||||
|  | 		t.createObject, | ||||||
|  | 		t.getObject, | ||||||
|  | 		invalid..., | ||||||
|  | 	) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Tester) TestUpdate(valid runtime.Object, validUpdateFunc UpdateFunc, invalidUpdateFunc ...UpdateFunc) { | ||||||
|  | 	var invalidFuncs []resttest.UpdateFunc | ||||||
|  | 	for _, f := range invalidUpdateFunc { | ||||||
|  | 		invalidFuncs = append(invalidFuncs, resttest.UpdateFunc(f)) | ||||||
|  | 	} | ||||||
|  | 	t.tester.TestUpdate( | ||||||
|  | 		valid, | ||||||
|  | 		t.createObject, | ||||||
|  | 		t.getObject, | ||||||
|  | 		resttest.UpdateFunc(validUpdateFunc), | ||||||
|  | 		invalidFuncs..., | ||||||
|  | 	) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Tester) TestDelete(valid runtime.Object) { | ||||||
|  | 	t.tester.TestDelete( | ||||||
|  | 		valid, | ||||||
|  | 		t.createObject, | ||||||
|  | 		t.getObject, | ||||||
|  | 		errors.IsNotFound, | ||||||
|  | 	) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Tester) TestDeleteGraceful(valid runtime.Object, expectedGrace int64) { | ||||||
|  | 	t.tester.TestDeleteGraceful( | ||||||
|  | 		valid, | ||||||
|  | 		t.createObject, | ||||||
|  | 		t.getObject, | ||||||
|  | 		expectedGrace, | ||||||
|  | 	) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Tester) TestGet(valid runtime.Object) { | ||||||
|  | 	t.tester.TestGet(valid) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Tester) TestList(valid runtime.Object) { | ||||||
|  | 	t.tester.TestList( | ||||||
|  | 		valid, | ||||||
|  | 		t.setObjectsForList, | ||||||
|  | 	) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Tester) TestWatch(valid runtime.Object, labelsPass, labelsFail []labels.Set, fieldsPass, fieldsFail []fields.Set) { | ||||||
|  | 	t.tester.TestWatch( | ||||||
|  | 		valid, | ||||||
|  | 		t.emitObject, | ||||||
|  | 		labelsPass, | ||||||
|  | 		labelsFail, | ||||||
|  | 		fieldsPass, | ||||||
|  | 		fieldsFail, | ||||||
|  | 		// TODO: This should be filtered, the registry should not be aware of this level of detail
 | ||||||
|  | 		[]string{etcdstorage.EtcdCreate, etcdstorage.EtcdDelete}, | ||||||
|  | 	) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Helper functions
 | ||||||
|  | 
 | ||||||
|  | func (t *Tester) getObject(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) { | ||||||
|  | 	accessor, err := meta.Accessor(obj) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	result, err := t.storage.Get(ctx, accessor.GetName(), &metav1.GetOptions{}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return result, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Tester) createObject(ctx genericapirequest.Context, obj runtime.Object) error { | ||||||
|  | 	accessor, err := meta.Accessor(obj) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	key, err := t.storage.KeyFunc(ctx, accessor.GetName()) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return t.storage.Storage.Create(ctx, key, obj, nil, 0) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Tester) setObjectsForList(objects []runtime.Object) []runtime.Object { | ||||||
|  | 	key := t.storage.KeyRootFunc(t.tester.TestContext()) | ||||||
|  | 	if _, err := t.storage.DeleteCollection(t.tester.TestContext(), nil, nil); err != nil { | ||||||
|  | 		t.tester.Errorf("unable to clear collection: %v", err) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	if err := storagetesting.CreateObjList(key, t.storage.Storage, objects); err != nil { | ||||||
|  | 		t.tester.Errorf("unexpected error: %v", err) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	return objects | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Tester) emitObject(obj runtime.Object, action string) error { | ||||||
|  | 	ctx := t.tester.TestContext() | ||||||
|  | 	var err error | ||||||
|  | 
 | ||||||
|  | 	switch action { | ||||||
|  | 	case etcdstorage.EtcdCreate: | ||||||
|  | 		err = t.createObject(ctx, obj) | ||||||
|  | 	case etcdstorage.EtcdDelete: | ||||||
|  | 		var accessor metav1.Object | ||||||
|  | 		accessor, err = meta.Accessor(obj) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		_, _, err = t.storage.Delete(ctx, accessor.GetName(), nil) | ||||||
|  | 	default: | ||||||
|  | 		err = fmt.Errorf("unexpected action: %v", action) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return err | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue