mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-28 13:03:43 +00:00
Merge pull request #45732 from sdminonne/apiextension-test
Automatic merge from submit-queue (batch tested with PRs 45070, 45821, 45732, 45494, 45789) apiextesions-server integration tests: test multiple registration **What this PR does / why we need it**: Add integration test for Multiple registrations XREF: #45511 **Special notes for your reviewer**: @deads2k my first plan was to submit one single PR for both tests but I'm facing one issue with resources deregistration. Get in touch via slack
This commit is contained in:
commit
958bbaaa44
@ -9,7 +9,10 @@ load(
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["basic_test.go"],
|
||||
srcs = [
|
||||
"basic_test.go",
|
||||
"registration_test.go",
|
||||
],
|
||||
tags = [
|
||||
"automanaged",
|
||||
"integration",
|
||||
@ -19,6 +22,8 @@ go_test(
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
||||
"//vendor/k8s.io/client-go/dynamic:go_default_library",
|
||||
"//vendor/k8s.io/kube-apiextensions-server/pkg/apis/apiextensions/v1alpha1:go_default_library",
|
||||
"//vendor/k8s.io/kube-apiextensions-server/test/integration/testserver:go_default_library",
|
||||
],
|
||||
)
|
||||
|
@ -50,10 +50,7 @@ func TestSimpleCRUD(t *testing.T) {
|
||||
}
|
||||
|
||||
ns := "not-the-default"
|
||||
noxuNamespacedResourceClient := noxuVersionClient.Resource(&metav1.APIResource{
|
||||
Name: noxuDefinition.Spec.Names.Plural,
|
||||
Namespaced: true,
|
||||
}, ns)
|
||||
noxuNamespacedResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition)
|
||||
initialList, err := noxuNamespacedResourceClient.List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -82,29 +79,9 @@ func TestSimpleCRUD(t *testing.T) {
|
||||
}
|
||||
defer noxuNamespacedWatch.Stop()
|
||||
|
||||
noxuInstanceToCreate := testserver.NewNoxuInstance(ns, "foo")
|
||||
createdNoxuInstance, err := noxuNamespacedResourceClient.Create(noxuInstanceToCreate)
|
||||
createdNoxuInstance, err := instantiateCustomResource(t, testserver.NewNoxuInstance(ns, "foo"), noxuNamespacedResourceClient, noxuDefinition)
|
||||
if err != nil {
|
||||
t.Logf("%#v", createdNoxuInstance)
|
||||
t.Fatal(err)
|
||||
}
|
||||
createdObjectMeta, err := meta.Accessor(createdNoxuInstance)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// it should have a UUID
|
||||
if len(createdObjectMeta.GetUID()) == 0 {
|
||||
t.Errorf("missing uuid: %#v", createdNoxuInstance)
|
||||
}
|
||||
createdTypeMeta, err := meta.TypeAccessor(createdNoxuInstance)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Version, createdTypeMeta.GetAPIVersion(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := noxuDefinition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
t.Fatalf("unable to create noxu Instance:%v", err)
|
||||
}
|
||||
|
||||
select {
|
||||
@ -178,6 +155,10 @@ func TestSimpleCRUD(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// it should have a UUID
|
||||
createdObjectMeta, err := meta.Accessor(createdNoxuInstance)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if e, a := createdObjectMeta.GetUID(), deletedObjectMeta.GetUID(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
@ -0,0 +1,246 @@
|
||||
/*
|
||||
Copyright 2017 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 integration
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/dynamic"
|
||||
apiextensionsv1alpha1 "k8s.io/kube-apiextensions-server/pkg/apis/apiextensions/v1alpha1"
|
||||
"k8s.io/kube-apiextensions-server/test/integration/testserver"
|
||||
)
|
||||
|
||||
func instantiateCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client *dynamic.ResourceClient, definition *apiextensionsv1alpha1.CustomResource) (*unstructured.Unstructured, error) {
|
||||
createdInstance, err := client.Create(instanceToCreate)
|
||||
if err != nil {
|
||||
t.Logf("%#v", createdInstance)
|
||||
return nil, err
|
||||
}
|
||||
createdObjectMeta, err := meta.Accessor(createdInstance)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// it should have a UUID
|
||||
if len(createdObjectMeta.GetUID()) == 0 {
|
||||
t.Errorf("missing uuid: %#v", createdInstance)
|
||||
}
|
||||
createdTypeMeta, err := meta.TypeAccessor(createdInstance)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if e, a := definition.Spec.Group+"/"+definition.Spec.Version, createdTypeMeta.GetAPIVersion(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := definition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
return createdInstance, nil
|
||||
}
|
||||
|
||||
func NewNamespacedCustomResourceClient(ns string, client *dynamic.Client, definition *apiextensionsv1alpha1.CustomResource) *dynamic.ResourceClient {
|
||||
return client.Resource(&metav1.APIResource{
|
||||
Name: definition.Spec.Names.Plural,
|
||||
Namespaced: definition.Spec.Scope == apiextensionsv1alpha1.NamespaceScoped,
|
||||
}, ns)
|
||||
}
|
||||
|
||||
func TestMultipleResourceInstances(t *testing.T) {
|
||||
stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServer()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer close(stopCh)
|
||||
|
||||
ns := "not-the-default"
|
||||
noxuDefinition := testserver.NewNoxuCustomResourceDefinition()
|
||||
noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
noxuNamespacedResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition)
|
||||
noxuList, err := noxuNamespacedResourceClient.List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
noxuListListMeta, err := meta.ListAccessor(noxuList)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
noxuNamespacedWatch, err := noxuNamespacedResourceClient.Watch(metav1.ListOptions{ResourceVersion: noxuListListMeta.GetResourceVersion()})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer noxuNamespacedWatch.Stop()
|
||||
|
||||
instances := map[string]*struct {
|
||||
Added bool
|
||||
Deleted bool
|
||||
Instance *unstructured.Unstructured
|
||||
}{
|
||||
"foo": {},
|
||||
"bar": {},
|
||||
}
|
||||
|
||||
for key, val := range instances {
|
||||
val.Instance, err = instantiateCustomResource(t, testserver.NewNoxuInstance(ns, key), noxuNamespacedResourceClient, noxuDefinition)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create Noxu Instance %q:%v", key, err)
|
||||
}
|
||||
}
|
||||
|
||||
addEvents := 0
|
||||
for addEvents < len(instances) {
|
||||
select {
|
||||
case watchEvent := <-noxuNamespacedWatch.ResultChan():
|
||||
if e, a := watch.Added, watchEvent.Type; e != a {
|
||||
t.Fatalf("expected %v, got %v", e, a)
|
||||
}
|
||||
name, err := meta.NewAccessor().Name(watchEvent.Object)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to retrieve object name:%v", err)
|
||||
}
|
||||
if instances[name].Added {
|
||||
t.Fatalf("Add event already registered for %q", name)
|
||||
}
|
||||
instances[name].Added = true
|
||||
addEvents++
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatalf("missing watch event")
|
||||
}
|
||||
}
|
||||
|
||||
for key, val := range instances {
|
||||
gottenNoxuInstace, err := noxuNamespacedResourceClient.Get(key)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if e, a := val.Instance, gottenNoxuInstace; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
}
|
||||
listWithItem, err := noxuNamespacedResourceClient.List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if e, a := len(instances), len(listWithItem.(*unstructured.UnstructuredList).Items); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
for _, a := range listWithItem.(*unstructured.UnstructuredList).Items {
|
||||
if e := instances[a.GetName()].Instance; !reflect.DeepEqual(e, &a) {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
}
|
||||
for key := range instances {
|
||||
if err := noxuNamespacedResourceClient.Delete(key, nil); err != nil {
|
||||
t.Fatalf("unable to delete %s:%v", key, err)
|
||||
}
|
||||
}
|
||||
listWithoutItem, err := noxuNamespacedResourceClient.List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if e, a := 0, len(listWithoutItem.(*unstructured.UnstructuredList).Items); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
deleteEvents := 0
|
||||
for deleteEvents < len(instances) {
|
||||
select {
|
||||
case watchEvent := <-noxuNamespacedWatch.ResultChan():
|
||||
if e, a := watch.Deleted, watchEvent.Type; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
break
|
||||
}
|
||||
name, err := meta.NewAccessor().Name(watchEvent.Object)
|
||||
if err != nil {
|
||||
t.Errorf("unable to retrieve object name:%v", err)
|
||||
}
|
||||
if instances[name].Deleted {
|
||||
t.Errorf("Delete event already registered for %q", name)
|
||||
}
|
||||
instances[name].Deleted = true
|
||||
deleteEvents++
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Errorf("missing watch event")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultipleRegistration(t *testing.T) {
|
||||
stopCh, apiExtensionClient, clientPool, err := testserver.StartDefaultServer()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer close(stopCh)
|
||||
|
||||
ns := "not-the-default"
|
||||
sameInstanceName := "foo"
|
||||
noxuDefinition := testserver.NewNoxuCustomResourceDefinition()
|
||||
noxuVersionClient, err := testserver.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, clientPool)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
noxuNamespacedResourceClient := NewNamespacedCustomResourceClient(ns, noxuVersionClient, noxuDefinition)
|
||||
createdNoxuInstance, err := instantiateCustomResource(t, testserver.NewNoxuInstance(ns, sameInstanceName), noxuNamespacedResourceClient, noxuDefinition)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create noxu Instance:%v", err)
|
||||
}
|
||||
|
||||
gottenNoxuInstance, err := noxuNamespacedResourceClient.Get(sameInstanceName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if e, a := createdNoxuInstance, gottenNoxuInstance; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
curletDefinition := testserver.NewCurletCustomResourceDefinition()
|
||||
curletVersionClient, err := testserver.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, clientPool)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
curletNamespacedResourceClient := NewNamespacedCustomResourceClient(ns, curletVersionClient, curletDefinition)
|
||||
createdCurletInstance, err := instantiateCustomResource(t, testserver.NewCurletInstance(ns, sameInstanceName), curletNamespacedResourceClient, curletDefinition)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create noxu Instance:%v", err)
|
||||
}
|
||||
gottenCurletInstance, err := curletNamespacedResourceClient.Get(sameInstanceName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if e, a := createdCurletInstance, gottenCurletInstance; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
// now re-GET noxu
|
||||
gottenNoxuInstance2, err := noxuNamespacedResourceClient.Get(sameInstanceName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if e, a := createdNoxuInstance, gottenNoxuInstance2; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
}
|
@ -61,6 +61,39 @@ func NewNoxuInstance(namespace, name string) *unstructured.Unstructured {
|
||||
}
|
||||
}
|
||||
|
||||
func NewCurletCustomResourceDefinition() *apiextensionsv1alpha1.CustomResource {
|
||||
return &apiextensionsv1alpha1.CustomResource{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "curlets.mygroup.example.com"},
|
||||
Spec: apiextensionsv1alpha1.CustomResourceSpec{
|
||||
Group: "mygroup.example.com",
|
||||
Version: "v1alpha1",
|
||||
Names: apiextensionsv1alpha1.CustomResourceNames{
|
||||
Plural: "curlets",
|
||||
Singular: "curlet",
|
||||
Kind: "Curlet",
|
||||
ListKind: "CurletList",
|
||||
},
|
||||
Scope: apiextensionsv1alpha1.NamespaceScoped,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewCurletInstance(namespace, name string) *unstructured.Unstructured {
|
||||
return &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "mygroup.example.com/v1alpha1",
|
||||
"kind": "Curlet",
|
||||
"metadata": map[string]interface{}{
|
||||
"namespace": namespace,
|
||||
"name": name,
|
||||
},
|
||||
"content": map[string]interface{}{
|
||||
"key": "value",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func CreateNewCustomResourceDefinition(customResource *apiextensionsv1alpha1.CustomResource, apiExtensionsClient clientset.Interface, clientPool dynamic.ClientPool) (*dynamic.Client, error) {
|
||||
_, err := apiExtensionsClient.Apiextensions().CustomResources().Create(customResource)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user