Skip to content

Commit 7db417e

Browse files
committed
wait for Kube resource instead of APIBinding to make e2e tests more reliable
On-behalf-of: @SAP christoph.mewes@sap.com
1 parent 6d8fd96 commit 7db417e

File tree

4 files changed

+72
-89
lines changed

4 files changed

+72
-89
lines changed

test/e2e/sync/apiexportendpointslice_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,10 @@ func TestAPIExportEndpointSliceSameCluster(t *testing.T) {
116116
teamClusterPath := logicalcluster.NewPath("root").Join(orgWorkspace).Join("team-1")
117117
teamClient := kcpClusterClient.Cluster(teamClusterPath)
118118

119-
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionResource{
120-
Group: kcpGroupName,
121-
Version: "v1",
122-
Resource: "crontabs",
119+
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionKind{
120+
Group: kcpGroupName,
121+
Version: "v1",
122+
Kind: "CronTab",
123123
})
124124

125125
// In kcp 0.27, the binding' status is not perfectly in-sync with the actual APIs available in
@@ -260,10 +260,10 @@ func TestAPIExportEndpointSliceDifferentCluster(t *testing.T) {
260260
teamClusterPath := logicalcluster.NewPath("root").Join(orgWorkspace).Join("team-1")
261261
teamClient := kcpClusterClient.Cluster(teamClusterPath)
262262

263-
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionResource{
264-
Group: kcpGroupName,
265-
Version: "v1",
266-
Resource: "crontabs",
263+
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionKind{
264+
Group: kcpGroupName,
265+
Version: "v1",
266+
Kind: "CronTab",
267267
})
268268

269269
// TODO: Remove this once we do not support kcp 0.27 anymore.

test/e2e/sync/primary_test.go

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,10 @@ func TestSyncSimpleObject(t *testing.T) {
9797
teamClusterPath := logicalcluster.NewPath("root").Join(orgWorkspace).Join("team-1")
9898
teamClient := kcpClusterClient.Cluster(teamClusterPath)
9999

100-
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionResource{
101-
Group: kcpGroupName,
102-
Version: "v1",
103-
Resource: "crontabs",
100+
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionKind{
101+
Group: kcpGroupName,
102+
Version: "v1",
103+
Kind: "CronTab",
104104
})
105105

106106
// create a Crontab object in a team workspace
@@ -190,10 +190,10 @@ func TestSyncSimpleObjectOldNaming(t *testing.T) {
190190
teamClusterPath := logicalcluster.NewPath("root").Join(orgWorkspace).Join("team-1")
191191
teamClient := kcpClusterClient.Cluster(teamClusterPath)
192192

193-
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionResource{
194-
Group: kcpGroupName,
195-
Version: "v1",
196-
Resource: "crontabs",
193+
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionKind{
194+
Group: kcpGroupName,
195+
Version: "v1",
196+
Kind: "CronTab",
197197
})
198198

199199
// create a Crontab object in a team workspace
@@ -274,10 +274,10 @@ func TestSyncWithDefaultNamingRules(t *testing.T) {
274274
// wait until the API is available
275275
kcpClusterClient := utils.GetKcpAdminClusterClient(t)
276276

277-
crontabsGVR := schema.GroupVersionResource{
278-
Group: "kcp.example.com",
279-
Version: "v1",
280-
Resource: "crontabs",
277+
crontabsGVK := schema.GroupVersionKind{
278+
Group: "kcp.example.com",
279+
Version: "v1",
280+
Kind: "CronTab",
281281
}
282282

283283
// create a Crontab object in each team workspace, importantly using the same name and
@@ -298,7 +298,7 @@ spec:
298298
teamClusterPath := logicalcluster.NewPath("root").Join(orgWorkspace).Join(team)
299299
teamClient := kcpClusterClient.Cluster(teamClusterPath)
300300

301-
utils.WaitForBoundAPI(t, ctx, teamClient, crontabsGVR)
301+
utils.WaitForBoundAPI(t, ctx, teamClient, crontabsGVK)
302302

303303
if err := teamClient.Create(ctx, utils.YAMLToUnstructured(t, crontabYAML)); err != nil {
304304
t.Fatalf("Failed to create %s's CronTab in kcp: %v", team, err)
@@ -380,10 +380,10 @@ func TestLocalChangesAreKept(t *testing.T) {
380380
teamClusterPath := logicalcluster.NewPath("root").Join(orgWorkspace).Join("team-1")
381381
teamClient := kcpClusterClient.Cluster(teamClusterPath)
382382

383-
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionResource{
384-
Group: kcpGroupName,
385-
Version: "v1",
386-
Resource: "crontabs",
383+
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionKind{
384+
Group: kcpGroupName,
385+
Version: "v1",
386+
Kind: "CronTab",
387387
})
388388

389389
// create a Crontab object in a team workspace
@@ -577,10 +577,10 @@ func TestResourceFilter(t *testing.T) {
577577
teamClusterPath := logicalcluster.NewPath("root").Join(orgWorkspace).Join("team-1")
578578
teamClient := kcpClusterClient.Cluster(teamClusterPath)
579579

580-
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionResource{
581-
Group: kcpGroupName,
582-
Version: "v1",
583-
Resource: "crontabs",
580+
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionKind{
581+
Group: kcpGroupName,
582+
Version: "v1",
583+
Kind: "CronTab",
584584
})
585585

586586
// create two Crontab objects in a team workspace
@@ -694,10 +694,10 @@ func TestSyncingOverlyLongNames(t *testing.T) {
694694
teamClusterPath := logicalcluster.NewPath("root").Join(orgWorkspace).Join("team-1")
695695
teamClient := kcpClusterClient.Cluster(teamClusterPath)
696696

697-
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionResource{
698-
Group: kcpGroupName,
699-
Version: "v1",
700-
Resource: "crontabs",
697+
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionKind{
698+
Group: kcpGroupName,
699+
Version: "v1",
700+
Kind: "CronTab",
701701
})
702702

703703
// create a namespace and CronTab with extremely long names
@@ -796,10 +796,10 @@ func TestSyncWithWorkspacePath(t *testing.T) {
796796
teamClusterPath := logicalcluster.NewPath("root").Join(orgWorkspace).Join("team-1")
797797
teamClient := kcpClusterClient.Cluster(teamClusterPath)
798798

799-
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionResource{
800-
Group: kcpGroupName,
801-
Version: "v1",
802-
Resource: "crontabs",
799+
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionKind{
800+
Group: kcpGroupName,
801+
Version: "v1",
802+
Kind: "CronTab",
803803
})
804804

805805
// create a Crontab object in a team workspace
@@ -921,10 +921,10 @@ func TestSyncMultiResources(t *testing.T) {
921921
teamClusterPath := logicalcluster.NewPath("root").Join(orgWorkspace).Join("team-1")
922922
teamClient := kcpClusterClient.Cluster(teamClusterPath)
923923

924-
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionResource{
925-
Group: kcpGroupName,
926-
Version: "v1",
927-
Resource: "crontabs",
924+
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionKind{
925+
Group: kcpGroupName,
926+
Version: "v1",
927+
Kind: "CronTab",
928928
})
929929

930930
// create a Crontab object in a team workspace

test/e2e/sync/related_test.go

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -593,10 +593,10 @@ func TestSyncRelatedObjects(t *testing.T) {
593593
teamClusterPath := logicalcluster.NewPath("root").Join(testcase.workspace).Join("team-1")
594594
teamClient := kcpClusterClient.Cluster(teamClusterPath)
595595

596-
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionResource{
597-
Group: apiExportName,
598-
Version: "v1",
599-
Resource: "crontabs",
596+
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionKind{
597+
Group: apiExportName,
598+
Version: "v1",
599+
Kind: "CronTab",
600600
})
601601

602602
// create a Crontab object in a team workspace
@@ -951,10 +951,10 @@ func TestSyncRelatedMultiObjects(t *testing.T) {
951951
utils.RunAgent(ctx, t, "bob", orgKubconfig, envtestKubeconfig, apiExportName, "")
952952

953953
// wait until the API is available
954-
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionResource{
955-
Group: apiExportName,
956-
Version: "v1",
957-
Resource: "backups",
954+
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionKind{
955+
Group: apiExportName,
956+
Version: "v1",
957+
Kind: "Backup",
958958
})
959959

960960
// create a Backup object in a team workspace
@@ -1226,10 +1226,10 @@ func TestSyncNonStandardRelatedResources(t *testing.T) {
12261226
teamClusterPath := logicalcluster.NewPath("root").Join(testcase.workspace).Join("team-1")
12271227
teamClient := kcpClusterClient.Cluster(teamClusterPath)
12281228

1229-
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionResource{
1230-
Group: apiExportName,
1231-
Version: "v1",
1232-
Resource: "crontabs",
1229+
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionKind{
1230+
Group: apiExportName,
1231+
Version: "v1",
1232+
Kind: "CronTab",
12331233
})
12341234

12351235
// create a Crontab object in a team workspace
@@ -1470,14 +1470,14 @@ func TestSyncNonStandardRelatedResourcesMultipleAPIExports(t *testing.T) {
14701470
utils.RunAgent(ctx, t, "initroid", initroidOrgKubconfig, envtestKubeconfig, initroidAPIExportName, "agent=initroid")
14711471

14721472
// wait until the APIs are available
1473-
for orgWs, gvr := range map[string]schema.GroupVersionResource{
1474-
initechOrgWorkspace: {Group: initechAPIExportName, Version: "v1", Resource: "crontabs"},
1475-
initroidOrgWorkspace: {Group: initroidAPIExportName, Version: "v1", Resource: "backups"},
1473+
for orgWs, gvk := range map[string]schema.GroupVersionKind{
1474+
initechOrgWorkspace: {Group: initechAPIExportName, Version: "v1", Kind: "CronTab"},
1475+
initroidOrgWorkspace: {Group: initroidAPIExportName, Version: "v1", Kind: "Backup"},
14761476
} {
14771477
teamClusterPath := logicalcluster.NewPath("root").Join(orgWs).Join("team-1")
14781478
teamClient := kcpClusterClient.Cluster(teamClusterPath)
14791479

1480-
utils.WaitForBoundAPI(t, ctx, teamClient, gvr)
1480+
utils.WaitForBoundAPI(t, ctx, teamClient, gvk)
14811481
}
14821482

14831483
// Since we are claiming resources from other APIExports, the default accepted claims
@@ -1620,10 +1620,10 @@ func TestDeletePrimaryWithRelatedKcpResource(t *testing.T) {
16201620
teamClusterPath := logicalcluster.NewPath("root").Join("delete-primary-related-kcp").Join("team-1")
16211621
teamClient := kcpClusterClient.Cluster(teamClusterPath)
16221622

1623-
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionResource{
1624-
Group: apiExportName,
1625-
Version: "v1",
1626-
Resource: "crontabs",
1623+
utils.WaitForBoundAPI(t, ctx, teamClient, schema.GroupVersionKind{
1624+
Group: apiExportName,
1625+
Version: "v1",
1626+
Kind: "CronTab",
16271627
})
16281628

16291629
// Step 1: Create a CronTab in kcp

test/utils/wait.go

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,10 @@ package utils
1818

1919
import (
2020
"context"
21-
"slices"
2221
"testing"
2322
"time"
2423

25-
kcpapisv1alpha1 "github.com/kcp-dev/sdk/apis/apis/v1alpha1"
26-
24+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2725
"k8s.io/apimachinery/pkg/runtime/schema"
2826
"k8s.io/apimachinery/pkg/types"
2927
"k8s.io/apimachinery/pkg/util/wait"
@@ -45,36 +43,21 @@ func WaitForObject(t *testing.T, ctx context.Context, client ctrlruntimeclient.C
4543
t.Logf("%T is ready.", obj)
4644
}
4745

48-
func WaitForBoundAPI(t *testing.T, ctx context.Context, client ctrlruntimeclient.Client, gvr schema.GroupVersionResource) {
46+
func WaitForBoundAPI(t *testing.T, ctx context.Context, client ctrlruntimeclient.Client, gvk schema.GroupVersionKind) {
4947
t.Helper()
5048

51-
t.Logf("Waiting for API %s/%s to be bound in kcp…", gvr.Group, gvr.Resource)
52-
err := wait.PollUntilContextTimeout(ctx, 500*time.Millisecond, 1*time.Minute, false, func(ctx context.Context) (bool, error) {
53-
apiBindings := &kcpapisv1alpha1.APIBindingList{}
54-
err := client.List(ctx, apiBindings)
55-
if err != nil {
56-
return false, err
57-
}
49+
t.Logf("Waiting for API %s/%s to be bound in kcp…", gvk.Group, gvk.Kind)
5850

59-
for _, binding := range apiBindings.Items {
60-
if bindingHasGVR(binding, gvr) {
61-
return true, nil
62-
}
63-
}
51+
// Wait for actual resource availability instead of checking the APIBinding, because this is more
52+
// reliable, especially on slower CI environments.
53+
err := wait.PollUntilContextTimeout(ctx, 500*time.Millisecond, 1*time.Minute, false, func(ctx context.Context) (bool, error) {
54+
// Try to list resources of this type - if the resource isn't ready, this will fail
55+
list := &unstructured.UnstructuredList{}
56+
list.SetGroupVersionKind(gvk)
6457

65-
return false, nil
58+
return client.List(ctx, list) == nil, nil
6659
})
6760
if err != nil {
68-
t.Fatalf("Failed to wait for API %v to become available: %v", gvr, err)
61+
t.Fatalf("Failed to wait for API %v to become available: %v", gvk, err)
6962
}
7063
}
71-
72-
func bindingHasGVR(binding kcpapisv1alpha1.APIBinding, gvr schema.GroupVersionResource) bool {
73-
for _, bound := range binding.Status.BoundResources {
74-
if bound.Group == gvr.Group && bound.Resource == gvr.Resource && slices.Contains(bound.StorageVersions, gvr.Version) {
75-
return true
76-
}
77-
}
78-
79-
return false
80-
}

0 commit comments

Comments
 (0)