@@ -31,22 +31,32 @@ import (
31
31
certificatesapiv1beta1 "k8s.io/api/certificates/v1beta1"
32
32
apiv1 "k8s.io/api/core/v1"
33
33
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34
+ "k8s.io/apimachinery/pkg/runtime/schema"
34
35
utilnet "k8s.io/apimachinery/pkg/util/net"
35
36
"k8s.io/apimachinery/pkg/util/sets"
36
37
"k8s.io/apimachinery/pkg/version"
38
+ "k8s.io/apiserver/pkg/authorization/authorizerfactory"
39
+ "k8s.io/apiserver/pkg/features"
37
40
genericapiserver "k8s.io/apiserver/pkg/server"
38
41
"k8s.io/apiserver/pkg/server/options"
42
+ "k8s.io/apiserver/pkg/server/resourceconfig"
39
43
serverstorage "k8s.io/apiserver/pkg/server/storage"
40
44
etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing"
45
+ utilfeature "k8s.io/apiserver/pkg/util/feature"
46
+ utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
47
+ "k8s.io/client-go/discovery"
41
48
"k8s.io/client-go/informers"
42
49
"k8s.io/client-go/kubernetes"
43
50
"k8s.io/client-go/kubernetes/fake"
44
51
restclient "k8s.io/client-go/rest"
45
52
"k8s.io/kubernetes/pkg/api/legacyscheme"
46
53
"k8s.io/kubernetes/pkg/api/testapi"
54
+ "k8s.io/kubernetes/pkg/apis/batch"
47
55
api "k8s.io/kubernetes/pkg/apis/core"
56
+ apisstorage "k8s.io/kubernetes/pkg/apis/storage"
48
57
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
49
58
"k8s.io/kubernetes/pkg/master/reconcilers"
59
+ "k8s.io/kubernetes/pkg/master/storageversionhashdata"
50
60
certificatesrest "k8s.io/kubernetes/pkg/registry/certificates/rest"
51
61
corerest "k8s.io/kubernetes/pkg/registry/core/rest"
52
62
"k8s.io/kubernetes/pkg/registry/registrytest"
@@ -70,6 +80,14 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion
70
80
}
71
81
72
82
resourceEncoding := serverstorage .NewDefaultResourceEncodingConfig (legacyscheme .Scheme )
83
+ // This configures the testing master the same way the real master is
84
+ // configured. The storage versions of these resources are different
85
+ // from the storage versions of other resources in their group.
86
+ resourceEncodingOverrides := []schema.GroupVersionResource {
87
+ batch .Resource ("cronjobs" ).WithVersion ("v1beta1" ),
88
+ apisstorage .Resource ("volumeattachments" ).WithVersion ("v1beta1" ),
89
+ }
90
+ resourceEncoding = resourceconfig .MergeResourceEncodingConfigs (resourceEncoding , resourceEncodingOverrides )
73
91
storageFactory := serverstorage .NewDefaultStorageFactory (* storageConfig , testapi .StorageMediaType (), legacyscheme .Codecs , resourceEncoding , DefaultAPIResourceConfigSource (), nil )
74
92
75
93
etcdOptions := options .NewEtcdOptions (storageConfig )
@@ -81,12 +99,12 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion
81
99
}
82
100
83
101
kubeVersion := kubeversion .Get ()
102
+ config .GenericConfig .Authorization .Authorizer = authorizerfactory .NewAlwaysAllowAuthorizer ()
84
103
config .GenericConfig .Version = & kubeVersion
85
104
config .ExtraConfig .StorageFactory = storageFactory
86
105
config .GenericConfig .LoopbackClientConfig = & restclient.Config {APIPath : "/api" , ContentConfig : restclient.ContentConfig {NegotiatedSerializer : legacyscheme .Codecs }}
87
106
config .GenericConfig .PublicAddress = net .ParseIP ("192.168.10.4" )
88
107
config .GenericConfig .LegacyAPIGroupPrefixes = sets .NewString ("/api" )
89
- config .GenericConfig .LoopbackClientConfig = & restclient.Config {APIPath : "/api" , ContentConfig : restclient.ContentConfig {NegotiatedSerializer : legacyscheme .Codecs }}
90
108
config .ExtraConfig .KubeletClientConfig = kubeletclient.KubeletClientConfig {Port : 10250 }
91
109
config .ExtraConfig .ProxyTransport = utilnet .SetTransportDefaults (& http.Transport {
92
110
DialContext : func (ctx context.Context , network , addr string ) (net.Conn , error ) { return nil , nil },
@@ -363,6 +381,112 @@ func TestAPIVersionOfDiscoveryEndpoints(t *testing.T) {
363
381
364
382
}
365
383
384
+ // This test doesn't cover the apiregistration and apiextensions group, as they are installed by other apiservers.
385
+ func TestStorageVersionHashes (t * testing.T ) {
386
+ defer utilfeaturetesting .SetFeatureGateDuringTest (t , utilfeature .DefaultFeatureGate , features .StorageVersionHash , true )()
387
+ master , etcdserver , _ , _ := newMaster (t )
388
+ defer etcdserver .Terminate (t )
389
+
390
+ server := httptest .NewServer (master .GenericAPIServer .Handler .GoRestfulContainer .ServeMux )
391
+
392
+ c := & restclient.Config {
393
+ Host : server .URL ,
394
+ APIPath : "/api" ,
395
+ ContentConfig : restclient.ContentConfig {NegotiatedSerializer : legacyscheme .Codecs },
396
+ }
397
+ discover := discovery .NewDiscoveryClientForConfigOrDie (c )
398
+ all , err := discover .ServerResources ()
399
+ if err != nil {
400
+ t .Error (err )
401
+ }
402
+ var count int
403
+ for _ , g := range all {
404
+ for _ , r := range g .APIResources {
405
+ if strings .Contains (r .Name , "/" ) ||
406
+ storageversionhashdata .NoStorageVersionHash .Has (g .GroupVersion + "/" + r .Name ) {
407
+ if r .StorageVersionHash != "" {
408
+ t .Errorf ("expect resource %s/%s to have empty storageVersionHash, got hash %q" , g .GroupVersion , r .Name , r .StorageVersionHash )
409
+ }
410
+ continue
411
+ }
412
+ if r .StorageVersionHash == "" {
413
+ t .Errorf ("expect the storageVersionHash of %s/%s to exist" , g .GroupVersion , r .Name )
414
+ continue
415
+ }
416
+ // Uncomment the following line if you want to update storageversionhash/data.go
417
+ // fmt.Printf("\"%s/%s\": \"%s\",\n", g.GroupVersion, r.Name, r.StorageVersionHash)
418
+ expected := storageversionhashdata .GVRToStorageVersionHash [g .GroupVersion + "/" + r .Name ]
419
+ if r .StorageVersionHash != expected {
420
+ t .Errorf ("expect the storageVersionHash of %s/%s to be %q, got %q" , g .GroupVersion , r .Name , expected , r .StorageVersionHash )
421
+ }
422
+ count ++
423
+ }
424
+ }
425
+ if count != len (storageversionhashdata .GVRToStorageVersionHash ) {
426
+ t .Errorf ("please remove the redundant entries from GVRToStorageVersionHash" )
427
+ }
428
+ }
429
+
430
+ func TestStorageVersionHashEqualities (t * testing.T ) {
431
+ defer utilfeaturetesting .SetFeatureGateDuringTest (t , utilfeature .DefaultFeatureGate , features .StorageVersionHash , true )()
432
+ master , etcdserver , _ , assert := newMaster (t )
433
+ defer etcdserver .Terminate (t )
434
+
435
+ server := httptest .NewServer (master .GenericAPIServer .Handler .GoRestfulContainer .ServeMux )
436
+
437
+ // Test 1: extensions/v1beta1/replicasets and apps/v1/replicasets have
438
+ // the same storage version hash.
439
+ resp , err := http .Get (server .URL + "/apis/extensions/v1beta1" )
440
+ assert .Empty (err )
441
+ extList := metav1.APIResourceList {}
442
+ assert .NoError (decodeResponse (resp , & extList ))
443
+ var extReplicasetHash , appsReplicasetHash string
444
+ for _ , r := range extList .APIResources {
445
+ if r .Name == "replicasets" {
446
+ extReplicasetHash = r .StorageVersionHash
447
+ }
448
+ }
449
+ assert .NotEmpty (extReplicasetHash )
450
+
451
+ resp , err = http .Get (server .URL + "/apis/apps/v1" )
452
+ assert .Empty (err )
453
+ appsList := metav1.APIResourceList {}
454
+ assert .NoError (decodeResponse (resp , & appsList ))
455
+ for _ , r := range appsList .APIResources {
456
+ if r .Name == "replicasets" {
457
+ appsReplicasetHash = r .StorageVersionHash
458
+ }
459
+ }
460
+ assert .Equal (extReplicasetHash , appsReplicasetHash )
461
+
462
+ // Test 2: batch/v1/jobs and batch/v1beta1/cronjobs have different
463
+ // storage version hashes.
464
+ resp , err = http .Get (server .URL + "/apis/batch/v1" )
465
+ assert .Empty (err )
466
+ batchv1 := metav1.APIResourceList {}
467
+ assert .NoError (decodeResponse (resp , & batchv1 ))
468
+ var jobsHash string
469
+ for _ , r := range batchv1 .APIResources {
470
+ if r .Name == "jobs" {
471
+ jobsHash = r .StorageVersionHash
472
+ }
473
+ }
474
+ assert .NotEmpty (jobsHash )
475
+
476
+ resp , err = http .Get (server .URL + "/apis/batch/v1beta1" )
477
+ assert .Empty (err )
478
+ batchv1beta1 := metav1.APIResourceList {}
479
+ assert .NoError (decodeResponse (resp , & batchv1beta1 ))
480
+ var cronjobsHash string
481
+ for _ , r := range batchv1beta1 .APIResources {
482
+ if r .Name == "cronjobs" {
483
+ cronjobsHash = r .StorageVersionHash
484
+ }
485
+ }
486
+ assert .NotEmpty (cronjobsHash )
487
+ assert .NotEqual (jobsHash , cronjobsHash )
488
+ }
489
+
366
490
func TestNoAlphaVersionsEnabledByDefault (t * testing.T ) {
367
491
config := DefaultAPIResourceConfigSource ()
368
492
for gv , enable := range config .GroupVersionConfigs {
0 commit comments