@@ -26,7 +26,9 @@ import (
26
26
"net/http"
27
27
"os"
28
28
"path/filepath"
29
+ "reflect"
29
30
"regexp"
31
+ "sort"
30
32
"strconv"
31
33
"strings"
32
34
"testing"
@@ -46,6 +48,7 @@ import (
46
48
"k8s.io/apimachinery/pkg/util/wait"
47
49
auditinternal "k8s.io/apiserver/pkg/apis/audit"
48
50
auditv1 "k8s.io/apiserver/pkg/apis/audit/v1"
51
+ endpointsdiscovery "k8s.io/apiserver/pkg/endpoints/discovery"
49
52
"k8s.io/apiserver/pkg/storage/storagebackend"
50
53
"k8s.io/client-go/discovery"
51
54
cacheddiscovery "k8s.io/client-go/discovery/cached/memory"
@@ -245,6 +248,7 @@ type svmTest struct {
245
248
client clientset.Interface
246
249
clientConfig * rest.Config
247
250
dynamicClient * dynamic.DynamicClient
251
+ discoveryClient * discovery.DiscoveryClient
248
252
storageConfig * storagebackend.Config
249
253
server * kubeapiservertesting.TestServer
250
254
apiextensionsclient * apiextensionsclientset.Clientset
@@ -350,6 +354,7 @@ func svmSetup(ctx context.Context, t *testing.T) *svmTest {
350
354
client : clientSet ,
351
355
clientConfig : server .ClientConfig ,
352
356
dynamicClient : dynamicClient ,
357
+ discoveryClient : rvDiscoveryClient ,
353
358
policyFile : policyFile ,
354
359
logFile : logFile ,
355
360
filePathForEncryptionConfig : filePathForEncryptionConfig ,
@@ -484,29 +489,6 @@ func (svm *svmTest) updateFile(t *testing.T, configDir, filename string, newCont
484
489
}
485
490
}
486
491
487
- // func (svm *svmTest) createSVMResource(ctx context.Context, t *testing.T, name string) (
488
- // *svmv1alpha1.StorageVersionMigration,
489
- // error,
490
- // ) {
491
- // t.Helper()
492
- // svmResource := &svmv1alpha1.StorageVersionMigration{
493
- // ObjectMeta: metav1.ObjectMeta{
494
- // Name: name,
495
- // },
496
- // Spec: svmv1alpha1.StorageVersionMigrationSpec{
497
- // Resource: svmv1alpha1.GroupVersionResource{
498
- // Group: "",
499
- // Version: "v1",
500
- // Resource: "secrets",
501
- // },
502
- // },
503
- // }
504
- //
505
- // return svm.client.StoragemigrationV1alpha1().
506
- // StorageVersionMigrations().
507
- // Create(ctx, svmResource, metav1.CreateOptions{})
508
- // }
509
-
510
492
func (svm * svmTest ) createSVMResource (ctx context.Context , t * testing.T , name string , gvr svmv1alpha1.GroupVersionResource ) (
511
493
* svmv1alpha1.StorageVersionMigration ,
512
494
error ,
@@ -757,27 +739,74 @@ func (svm *svmTest) updateCRD(
757
739
t * testing.T ,
758
740
crdName string ,
759
741
updatesCRDVersions []apiextensionsv1.CustomResourceDefinitionVersion ,
760
- ) * apiextensionsv1.CustomResourceDefinition {
742
+ expectedServingVersions []string ,
743
+ expectedStorageVersion string ,
744
+ ) {
761
745
t .Helper ()
762
746
763
747
var err error
764
- _ , err = crdintegration .UpdateV1CustomResourceDefinitionWithRetry (svm .apiextensionsclient , crdName , func (c * apiextensionsv1.CustomResourceDefinition ) {
748
+ crd , err : = crdintegration .UpdateV1CustomResourceDefinitionWithRetry (svm .apiextensionsclient , crdName , func (c * apiextensionsv1.CustomResourceDefinition ) {
765
749
c .Spec .Versions = updatesCRDVersions
766
750
})
767
751
if err != nil {
768
752
t .Fatalf ("Failed to update CRD: %v" , err )
769
753
}
770
754
771
- crd , err := svm .apiextensionsclient .ApiextensionsV1 ().CustomResourceDefinitions ().Get (ctx , crdName , metav1.GetOptions {})
772
- if err != nil {
773
- t .Fatalf ("Failed to get CRD: %v" , err )
774
- }
755
+ svm .waitForCRDUpdate (ctx , t , crd .Spec .Names .Kind , expectedServingVersions , expectedStorageVersion )
756
+ }
775
757
776
- // TODO: wrap all actions after updateCRD with wait loops so we do not need this sleep
777
- // it is currently necessary because we update the CRD but do not otherwise guarantee that the updated config is active
778
- time .Sleep (10 * time .Second )
758
+ func (svm * svmTest ) waitForCRDUpdate (
759
+ ctx context.Context ,
760
+ t * testing.T ,
761
+ crdKind string ,
762
+ expectedServingVersions []string ,
763
+ expectedStorageVersion string ,
764
+ ) {
765
+ t .Helper ()
779
766
780
- return crd
767
+ err := wait .PollUntilContextTimeout (
768
+ ctx ,
769
+ 500 * time .Millisecond ,
770
+ wait .ForeverTestTimeout ,
771
+ true ,
772
+ func (ctx context.Context ) (bool , error ) {
773
+ apiGroups , _ , err := svm .discoveryClient .ServerGroupsAndResources ()
774
+ if err != nil {
775
+ return false , fmt .Errorf ("failed to get server groups and resources: %w" , err )
776
+ }
777
+ for _ , api := range apiGroups {
778
+ if api .Name == crdGroup {
779
+ var servingVersions []string
780
+ for _ , apiVersion := range api .Versions {
781
+ servingVersions = append (servingVersions , apiVersion .Version )
782
+ }
783
+ sort .Strings (servingVersions )
784
+
785
+ // Check if the serving versions are as expected
786
+ if reflect .DeepEqual (expectedServingVersions , servingVersions ) {
787
+ expectedHash := endpointsdiscovery .StorageVersionHash (crdGroup , expectedStorageVersion , crdKind )
788
+ resourceList , err := svm .discoveryClient .ServerResourcesForGroupVersion (crdGroup + "/" + api .PreferredVersion .Version )
789
+ if err != nil {
790
+ return false , fmt .Errorf ("failed to get server resources for group version: %w" , err )
791
+ }
792
+
793
+ // Check if the storage version is as expected
794
+ for _ , resource := range resourceList .APIResources {
795
+ if resource .Kind == crdKind {
796
+ if resource .StorageVersionHash == expectedHash {
797
+ return true , nil
798
+ }
799
+ }
800
+ }
801
+ }
802
+ }
803
+ }
804
+ return false , nil
805
+ },
806
+ )
807
+ if err != nil {
808
+ t .Fatalf ("Failed to update a CRD: Name: %s, Err: %v" , crdName , err )
809
+ }
781
810
}
782
811
783
812
func (svm * svmTest ) createCR (ctx context.Context , t * testing.T , crName , version string ) * unstructured.Unstructured {
0 commit comments