@@ -12,12 +12,15 @@ import (
12
12
13
13
"golang.org/x/net/context"
14
14
15
+ apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
16
+ apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
15
17
"k8s.io/apimachinery/pkg/api/meta"
16
18
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17
19
"k8s.io/apimachinery/pkg/runtime"
18
20
"k8s.io/apimachinery/pkg/runtime/schema"
19
21
"k8s.io/apimachinery/pkg/util/diff"
20
22
"k8s.io/apimachinery/pkg/util/sets"
23
+ "k8s.io/apimachinery/pkg/util/wait"
21
24
discocache "k8s.io/client-go/discovery/cached"
22
25
restclient "k8s.io/client-go/rest"
23
26
"k8s.io/client-go/restmapper"
@@ -475,6 +478,23 @@ var etcdStorageData = map[schema.GroupVersionResource]struct {
475
478
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"}}}` ,
476
479
expectedEtcdPath : "kubernetes.io/apiextensions.k8s.io/customresourcedefinitions/openshiftwebconsoleconfigs.webconsole.operator.openshift.io" ,
477
480
},
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
+ },
478
498
// --
479
499
480
500
// k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1
@@ -837,6 +857,71 @@ func TestEtcd3StoragePath(t *testing.T) {
837
857
kubeConfig .Burst = 9999
838
858
kubeClient := kclientset .NewForConfigOrDie (kubeConfig )
839
859
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
+
840
925
mapper := restmapper .NewDeferredDiscoveryRESTMapper (discocache .NewMemCacheClient (kubeClient .Discovery ()))
841
926
mapper .Reset ()
842
927
@@ -1129,6 +1214,10 @@ func jsonToMetaObject(stub string) (*metaObject, error) {
1129
1214
if err := json .Unmarshal ([]byte (stub ), & obj ); err != nil {
1130
1215
return nil , err
1131
1216
}
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 = ""
1132
1221
return obj , nil
1133
1222
}
1134
1223
@@ -1182,6 +1271,9 @@ func (c *allClient) create(stub, ns string, mapping *meta.RESTMapping, all *[]cl
1182
1271
namespaced := mapping .Scope .Name () == meta .RESTScopeNameNamespace
1183
1272
output , err := req .NamespaceIfScoped (ns , namespaced ).Resource (mapping .Resource .Resource ).Body (strings .NewReader (stub )).Do ().Get ()
1184
1273
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
+ }
1185
1277
return err
1186
1278
}
1187
1279
* all = append (* all , cleanupData {output , mapping })
@@ -1351,3 +1443,53 @@ func diffMapKeys(a, b interface{}, stringer func(interface{}) string) []string {
1351
1443
1352
1444
return ret
1353
1445
}
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