Skip to content

Commit 08570c7

Browse files
authored
Merge pull request kubernetes#130276 from stlaz/svm_flakes
Fix SVM test flaking because of occasional slow resource storage update
2 parents 6b8e5a9 + a0a226d commit 08570c7

File tree

2 files changed

+55
-44
lines changed

2 files changed

+55
-44
lines changed

Diff for: test/integration/storageversionmigrator/storageversionmigrator_test.go

+24-14
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,17 @@ import (
2828

2929
svmv1alpha1 "k8s.io/api/storagemigration/v1alpha1"
3030
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
32+
"k8s.io/apimachinery/pkg/util/wait"
3133
encryptionconfigcontroller "k8s.io/apiserver/pkg/server/options/encryptionconfig/controller"
3234
etcd3watcher "k8s.io/apiserver/pkg/storage/etcd3"
3335
utilfeature "k8s.io/apiserver/pkg/util/feature"
3436
clientgofeaturegate "k8s.io/client-go/features"
3537
"k8s.io/component-base/featuregate"
3638
featuregatetesting "k8s.io/component-base/featuregate/testing"
37-
"k8s.io/klog/v2/ktesting"
3839
"k8s.io/kubernetes/pkg/features"
3940
"k8s.io/kubernetes/test/integration/framework"
41+
"k8s.io/kubernetes/test/utils/ktesting"
4042
)
4143

4244
// TestStorageVersionMigration is an integration test that verifies storage version migration works.
@@ -56,9 +58,7 @@ func TestStorageVersionMigration(t *testing.T) {
5658
// this makes the test super responsive. It's set to a default of 1 minute.
5759
encryptionconfigcontroller.EncryptionConfigFileChangePollDuration = time.Second
5860

59-
_, ctx := ktesting.NewTestContext(t)
60-
ctx, cancel := context.WithCancel(ctx)
61-
defer cancel()
61+
ctx := ktesting.Init(t)
6262

6363
svmTest := svmSetup(ctx, t)
6464

@@ -92,7 +92,7 @@ func TestStorageVersionMigration(t *testing.T) {
9292
}
9393

9494
wantPrefix := "k8s:enc:aescbc:v1:key2"
95-
etcdSecret, err := svmTest.getRawSecretFromETCD(t, secret.Name, secret.Namespace)
95+
etcdSecret, err := svmTest.getRawSecretFromETCD(t, secret.Namespace, secret.Name)
9696
if err != nil {
9797
t.Fatalf("Failed to get secret from etcd: %v", err)
9898
}
@@ -163,9 +163,7 @@ func TestStorageVersionMigrationWithCRD(t *testing.T) {
163163
goleak.IgnoreTopFunction("github.com/moby/spdystream.(*Connection).shutdown"),
164164
)
165165

166-
_, ctx := ktesting.NewTestContext(t)
167-
ctx, cancel := context.WithCancel(ctx)
168-
defer cancel()
166+
ctx := ktesting.Init(t)
169167

170168
crVersions := make(map[string]versions)
171169

@@ -210,10 +208,24 @@ func TestStorageVersionMigrationWithCRD(t *testing.T) {
210208
svmTest.updateCRD(ctx, t, crd.Name, v2StorageCRDVersion, []string{"v1", "v2"}, "v2")
211209

212210
// create CR with v1
213-
cr3 := svmTest.createCR(ctx, t, "cr3", "v1")
214-
if ok := svmTest.isCRStoredAtVersion(t, "v2", cr3.GetName()); !ok {
215-
t.Fatalf("CR not stored at version v2")
211+
var cr3 *unstructured.Unstructured
212+
// updateCRD checks discovery returns storageVersionHash matching storage version v2
213+
// to make sure the API server uses v2 but CRD controllers may race and the resource
214+
// might still get stored in v1.
215+
// Attempt to recreate the CR until it gets stored as v2.
216+
// https://github.com/kubernetes/kubernetes/issues/130235
217+
err := wait.PollUntilContextTimeout(ctx, 1*time.Second, 10*time.Second, true, func(waitCtx context.Context) (done bool, err error) {
218+
cr3 = svmTest.createCR(waitCtx, t, "cr3", "v1")
219+
if ok := svmTest.isCRStoredAtVersion(t, "v2", cr3.GetName()); !ok {
220+
svmTest.deleteCR(waitCtx, t, cr3.GetName(), "v1")
221+
return false, nil
222+
}
223+
return true, nil
224+
})
225+
if err != nil {
226+
t.Fatalf("timed out waiting for CR to be stored as v2: %v", err)
216227
}
228+
217229
crVersions[cr3.GetName()] = versions{
218230
generation: cr3.GetGeneration(),
219231
rv: cr3.GetResourceVersion(),
@@ -291,9 +303,7 @@ func TestStorageVersionMigrationDuringChaos(t *testing.T) {
291303
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.StorageVersionMigrator, true)
292304
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, featuregate.Feature(clientgofeaturegate.InformerResourceVersion), true)
293305

294-
_, ctx := ktesting.NewTestContext(t)
295-
ctx, cancel := context.WithCancel(ctx)
296-
t.Cleanup(cancel)
306+
ctx := ktesting.Init(t)
297307

298308
svmTest := svmSetup(ctx, t)
299309

Diff for: test/integration/storageversionmigrator/util.go

+31-30
Original file line numberDiff line numberDiff line change
@@ -388,17 +388,17 @@ func (svm *svmTest) createSecret(ctx context.Context, t *testing.T, name, namesp
388388
return svm.client.CoreV1().Secrets(secret.Namespace).Create(ctx, secret, metav1.CreateOptions{})
389389
}
390390

391-
func (svm *svmTest) getRawSecretFromETCD(t *testing.T, name, namespace string) ([]byte, error) {
391+
func (svm *svmTest) getRawSecretFromETCD(t *testing.T, namespace, name string) ([]byte, error) {
392392
t.Helper()
393-
secretETCDPath := svm.getETCDPathForResource(t, svm.storageConfig.Prefix, "", "secrets", name, namespace)
393+
secretETCDPath := getETCDPathForResource(t, svm.storageConfig.Prefix, "", "secrets", namespace, name)
394394
etcdResponse, err := svm.readRawRecordFromETCD(t, secretETCDPath)
395395
if err != nil {
396396
return nil, fmt.Errorf("failed to read %s from etcd: %w", secretETCDPath, err)
397397
}
398398
return etcdResponse.Kvs[0].Value, nil
399399
}
400400

401-
func (svm *svmTest) getETCDPathForResource(t *testing.T, storagePrefix, group, resource, name, namespaceName string) string {
401+
func getETCDPathForResource(t *testing.T, storagePrefix, group, resource, namespaceName, name string) string {
402402
t.Helper()
403403
groupResource := resource
404404
if group != "" {
@@ -432,9 +432,9 @@ func (svm *svmTest) readRawRecordFromETCD(t *testing.T, path string) (*clientv3.
432432
return response, nil
433433
}
434434

435-
func (svm *svmTest) getRawCRFromETCD(t *testing.T, name, namespace, crdGroup, crdName string) ([]byte, error) {
435+
func (svm *svmTest) getRawCRFromETCD(t *testing.T, crdGroup, crdName, namespace, name string) ([]byte, error) {
436436
t.Helper()
437-
crdETCDPath := svm.getETCDPathForResource(t, svm.storageConfig.Prefix, crdGroup, crdName, name, namespace)
437+
crdETCDPath := getETCDPathForResource(t, svm.storageConfig.Prefix, crdGroup, crdName, namespace, name)
438438
etcdResponse, err := svm.readRawRecordFromETCD(t, crdETCDPath)
439439
if err != nil {
440440
t.Fatalf("failed to read %s from etcd: %v", crdETCDPath, err)
@@ -808,29 +808,30 @@ func (svm *svmTest) waitForCRDUpdate(
808808
return false, fmt.Errorf("failed to get server groups and resources: %w", err)
809809
}
810810
for _, api := range apiGroups {
811-
if api.Name == crdGroup {
812-
var servingVersions []string
813-
for _, apiVersion := range api.Versions {
814-
servingVersions = append(servingVersions, apiVersion.Version)
815-
}
816-
sort.Strings(servingVersions)
817-
818-
// Check if the serving versions are as expected
819-
if reflect.DeepEqual(expectedServingVersions, servingVersions) {
820-
expectedHash := endpointsdiscovery.StorageVersionHash(crdGroup, expectedStorageVersion, crdKind)
821-
resourceList, err := svm.discoveryClient.ServerResourcesForGroupVersion(crdGroup + "/" + api.PreferredVersion.Version)
822-
if err != nil {
823-
return false, fmt.Errorf("failed to get server resources for group version: %w", err)
824-
}
825-
826-
// Check if the storage version is as expected
827-
for _, resource := range resourceList.APIResources {
828-
if resource.Kind == crdKind {
829-
if resource.StorageVersionHash == expectedHash {
830-
return true, nil
831-
}
832-
}
833-
}
811+
if api.Name != crdGroup {
812+
continue
813+
}
814+
var servingVersions []string
815+
for _, apiVersion := range api.Versions {
816+
servingVersions = append(servingVersions, apiVersion.Version)
817+
}
818+
sort.Strings(servingVersions)
819+
820+
// Check if the serving versions are as expected
821+
if !reflect.DeepEqual(expectedServingVersions, servingVersions) {
822+
continue
823+
}
824+
825+
expectedHash := endpointsdiscovery.StorageVersionHash(crdGroup, expectedStorageVersion, crdKind)
826+
resourceList, err := svm.discoveryClient.ServerResourcesForGroupVersion(crdGroup + "/" + api.PreferredVersion.Version)
827+
if err != nil {
828+
return false, fmt.Errorf("failed to get server resources for group version: %w", err)
829+
}
830+
831+
// Check if the storage version is as expected
832+
for _, resource := range resourceList.APIResources {
833+
if resource.Kind == crdKind && resource.StorageVersionHash == expectedHash {
834+
return true, nil
834835
}
835836
}
836837
}
@@ -1056,7 +1057,7 @@ func (svm *svmTest) setupServerCert(t *testing.T) *certContext {
10561057
func (svm *svmTest) isCRStoredAtVersion(t *testing.T, version, crName string) bool {
10571058
t.Helper()
10581059

1059-
data, err := svm.getRawCRFromETCD(t, crName, defaultNamespace, crdGroup, crdName+"s")
1060+
data, err := svm.getRawCRFromETCD(t, crdGroup, crdName+"s", defaultNamespace, crName)
10601061
if err != nil {
10611062
t.Fatalf("Failed to get CR from etcd: %v", err)
10621063
}
@@ -1135,7 +1136,7 @@ func (svm *svmTest) validateRVAndGeneration(ctx context.Context, t *testing.T, c
11351136

11361137
for crName, version := range crVersions {
11371138
// get CR from etcd
1138-
data, err := svm.getRawCRFromETCD(t, crName, defaultNamespace, crdGroup, crdName+"s")
1139+
data, err := svm.getRawCRFromETCD(t, crdGroup, crdName+"s", defaultNamespace, crName)
11391140
if err != nil {
11401141
t.Fatalf("Failed to get CR from etcd: %v", err)
11411142
}

0 commit comments

Comments
 (0)