Skip to content

Commit 0af6fe5

Browse files
committed
Add custom resource coverage to ETCD path test
This change adds ETCD path tests that cover both namespace and cluster scoped custom resources. It also adds tests for custom resources with multiple versions and confirms that the correct version is persisted to disk. Signed-off-by: Monis Khan <[email protected]>
1 parent 8ccc7e1 commit 0af6fe5

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed

test/integration/etcd_storage_path_test.go

+142
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@ import (
1212

1313
"golang.org/x/net/context"
1414

15+
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
16+
apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
1517
"k8s.io/apimachinery/pkg/api/meta"
1618
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1719
"k8s.io/apimachinery/pkg/runtime"
1820
"k8s.io/apimachinery/pkg/runtime/schema"
1921
"k8s.io/apimachinery/pkg/util/diff"
2022
"k8s.io/apimachinery/pkg/util/sets"
23+
"k8s.io/apimachinery/pkg/util/wait"
2124
discocache "k8s.io/client-go/discovery/cached"
2225
restclient "k8s.io/client-go/rest"
2326
"k8s.io/client-go/restmapper"
@@ -475,6 +478,23 @@ var etcdStorageData = map[schema.GroupVersionResource]struct {
475478
stub: `{"metadata": {"name": "openshiftwebconsoleconfigs.webconsole.operator.openshift.io"},"spec": {"scope": "Cluster","group": "webconsole.operator.openshift.io","version": "v1alpha1","names": {"kind": "OpenShiftWebConsoleConfig","plural": "openshiftwebconsoleconfigs","singular": "openshiftwebconsoleconfig"}}}`,
476479
expectedEtcdPath: "kubernetes.io/apiextensions.k8s.io/customresourcedefinitions/openshiftwebconsoleconfigs.webconsole.operator.openshift.io",
477480
},
481+
gvr("cr.bar.com", "v1", "foos"): {
482+
stub: `{"kind": "Foo", "apiVersion": "cr.bar.com/v1", "metadata": {"name": "cr1foo"}, "color": "blue"}`, // requires TypeMeta due to CRD scheme's UnstructuredObjectTyper
483+
expectedEtcdPath: "kubernetes.io/cr.bar.com/foos/etcdstoragepathtestnamespace/cr1foo",
484+
},
485+
gvr("custom.fancy.com", "v2", "pants"): {
486+
stub: `{"kind": "Pant", "apiVersion": "custom.fancy.com/v2", "metadata": {"name": "cr2pant"}, "isFancy": true}`, // requires TypeMeta due to CRD scheme's UnstructuredObjectTyper
487+
expectedEtcdPath: "kubernetes.io/custom.fancy.com/pants/cr2pant",
488+
},
489+
gvr("awesome.bears.com", "v1", "pandas"): {
490+
stub: `{"kind": "Panda", "apiVersion": "awesome.bears.com/v1", "metadata": {"name": "cr3panda"}, "weight": 100}`, // requires TypeMeta due to CRD scheme's UnstructuredObjectTyper
491+
expectedEtcdPath: "kubernetes.io/awesome.bears.com/pandas/cr3panda",
492+
},
493+
gvr("awesome.bears.com", "v3", "pandas"): {
494+
stub: `{"kind": "Panda", "apiVersion": "awesome.bears.com/v3", "metadata": {"name": "cr4panda"}, "weight": 300}`, // requires TypeMeta due to CRD scheme's UnstructuredObjectTyper
495+
expectedEtcdPath: "kubernetes.io/awesome.bears.com/pandas/cr4panda",
496+
expectedGVK: gvkP("awesome.bears.com", "v1", "Panda"),
497+
},
478498
// --
479499

480500
// k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1
@@ -837,6 +857,71 @@ func TestEtcd3StoragePath(t *testing.T) {
837857
kubeConfig.Burst = 9999
838858
kubeClient := kclientset.NewForConfigOrDie(kubeConfig)
839859

860+
// create CRDs so we can make sure that custom resources do not get lost
861+
createTestCRDs(t, apiextensionsclientset.NewForConfigOrDie(kubeConfig),
862+
// namespaced with legacy version field
863+
&apiextensionsv1beta1.CustomResourceDefinition{
864+
ObjectMeta: metav1.ObjectMeta{
865+
Name: "foos.cr.bar.com",
866+
},
867+
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
868+
Group: "cr.bar.com",
869+
Version: "v1",
870+
Scope: apiextensionsv1beta1.NamespaceScoped,
871+
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
872+
Plural: "foos",
873+
Kind: "Foo",
874+
},
875+
},
876+
},
877+
// cluster scoped with legacy version field
878+
&apiextensionsv1beta1.CustomResourceDefinition{
879+
ObjectMeta: metav1.ObjectMeta{
880+
Name: "pants.custom.fancy.com",
881+
},
882+
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
883+
Group: "custom.fancy.com",
884+
Version: "v2",
885+
Scope: apiextensionsv1beta1.ClusterScoped,
886+
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
887+
Plural: "pants",
888+
Kind: "Pant",
889+
},
890+
},
891+
},
892+
// cluster scoped with versions field
893+
&apiextensionsv1beta1.CustomResourceDefinition{
894+
ObjectMeta: metav1.ObjectMeta{
895+
Name: "pandas.awesome.bears.com",
896+
},
897+
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
898+
Group: "awesome.bears.com",
899+
Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
900+
{
901+
Name: "v1",
902+
Served: true,
903+
Storage: true,
904+
},
905+
{
906+
Name: "v2",
907+
Served: false,
908+
Storage: false,
909+
},
910+
{
911+
Name: "v3",
912+
Served: true,
913+
Storage: false,
914+
},
915+
},
916+
Scope: apiextensionsv1beta1.ClusterScoped,
917+
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
918+
Plural: "pandas",
919+
Kind: "Panda",
920+
},
921+
},
922+
},
923+
)
924+
840925
mapper := restmapper.NewDeferredDiscoveryRESTMapper(discocache.NewMemCacheClient(kubeClient.Discovery()))
841926
mapper.Reset()
842927

@@ -1129,6 +1214,10 @@ func jsonToMetaObject(stub string) (*metaObject, error) {
11291214
if err := json.Unmarshal([]byte(stub), &obj); err != nil {
11301215
return nil, err
11311216
}
1217+
// unset type meta fields - we only set these in the CRD test data and it makes
1218+
// any CRD test with an expectedGVK override fail the DeepDerivative test
1219+
obj.Kind = ""
1220+
obj.APIVersion = ""
11321221
return obj, nil
11331222
}
11341223

@@ -1182,6 +1271,9 @@ func (c *allClient) create(stub, ns string, mapping *meta.RESTMapping, all *[]cl
11821271
namespaced := mapping.Scope.Name() == meta.RESTScopeNameNamespace
11831272
output, err := req.NamespaceIfScoped(ns, namespaced).Resource(mapping.Resource.Resource).Body(strings.NewReader(stub)).Do().Get()
11841273
if err != nil {
1274+
if runtime.IsNotRegisteredError(err) {
1275+
return nil // just ignore cleanup of CRDs for now, this is better fixed by moving to the dynamic client
1276+
}
11851277
return err
11861278
}
11871279
*all = append(*all, cleanupData{output, mapping})
@@ -1351,3 +1443,53 @@ func diffMapKeys(a, b interface{}, stringer func(interface{}) string) []string {
13511443

13521444
return ret
13531445
}
1446+
1447+
// copied and modified from k8s.io/kubernetes/test/integration/master/crd_test.go#TestCRD
1448+
1449+
func createTestCRDs(t *testing.T, client apiextensionsclientset.Interface, crds ...*apiextensionsv1beta1.CustomResourceDefinition) {
1450+
for _, crd := range crds {
1451+
createTestCRD(t, client, crd)
1452+
}
1453+
}
1454+
1455+
func createTestCRD(t *testing.T, client apiextensionsclientset.Interface, crd *apiextensionsv1beta1.CustomResourceDefinition) {
1456+
if _, err := client.ApiextensionsV1beta1().CustomResourceDefinitions().Create(crd); err != nil {
1457+
t.Fatalf("Failed to create %s CRD; %v", crd.Name, err)
1458+
}
1459+
if err := wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) {
1460+
return crdExistsInDiscovery(client, crd), nil
1461+
}); err != nil {
1462+
t.Fatalf("Failed to see %s in discovery: %v", crd.Name, err)
1463+
}
1464+
}
1465+
1466+
func crdExistsInDiscovery(client apiextensionsclientset.Interface, crd *apiextensionsv1beta1.CustomResourceDefinition) bool {
1467+
var versions []string
1468+
if len(crd.Spec.Version) != 0 {
1469+
versions = append(versions, crd.Spec.Version)
1470+
}
1471+
for _, v := range crd.Spec.Versions {
1472+
if v.Served {
1473+
versions = append(versions, v.Name)
1474+
}
1475+
}
1476+
for _, v := range versions {
1477+
if !crdVersionExistsInDiscovery(client, crd, v) {
1478+
return false
1479+
}
1480+
}
1481+
return true
1482+
}
1483+
1484+
func crdVersionExistsInDiscovery(client apiextensionsclientset.Interface, crd *apiextensionsv1beta1.CustomResourceDefinition, version string) bool {
1485+
resourceList, err := client.Discovery().ServerResourcesForGroupVersion(crd.Spec.Group + "/" + version)
1486+
if err != nil {
1487+
return false
1488+
}
1489+
for _, resource := range resourceList.APIResources {
1490+
if resource.Name == crd.Spec.Names.Plural {
1491+
return true
1492+
}
1493+
}
1494+
return false
1495+
}

0 commit comments

Comments
 (0)