diff --git a/test/e2e/apimachinery/aggregator.go b/test/e2e/apimachinery/aggregator.go index b7f12162dc6..529c3353228 100644 --- a/test/e2e/apimachinery/aggregator.go +++ b/test/e2e/apimachinery/aggregator.go @@ -52,7 +52,6 @@ import ( admissionapi "k8s.io/pod-security-admission/api" samplev1alpha1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1" "k8s.io/utils/pointer" - "k8s.io/utils/strings/slices" "github.com/onsi/ginkgo/v2" "github.com/onsi/gomega" @@ -737,24 +736,6 @@ func TestSampleAPIServer(ctx context.Context, f *framework.Framework, aggrclient framework.ExpectNoError(err, "failed to count the required APIServices") framework.Logf("APIService %s has been deleted.", apiServiceName) - ginkgo.By("Confirm that the group path of " + apiServiceName + " was removed from root paths") - groupPath := "/apis/" + apiServiceGroupName - err = wait.PollUntilContextTimeout(ctx, apiServiceRetryPeriod, apiServiceRetryTimeout, true, func(ctx context.Context) (done bool, err error) { - rootPaths := metav1.RootPaths{} - statusContent, err = restClient.Get(). - AbsPath("/"). - SetHeader("Accept", "application/json").DoRaw(ctx) - if err != nil { - return false, err - } - err = json.Unmarshal(statusContent, &rootPaths) - if err != nil { - return false, err - } - return !slices.Contains(rootPaths.Paths, groupPath), nil - }) - framework.ExpectNoError(err, "Expected to not find %s from root paths", groupPath) - cleanupSampleAPIServer(ctx, client, aggrclient, n, apiServiceName) } diff --git a/test/integration/apiserver/discovery/discovery_test.go b/test/integration/apiserver/discovery/discovery_test.go index 7ce49612430..71307c1378f 100644 --- a/test/integration/apiserver/discovery/discovery_test.go +++ b/test/integration/apiserver/discovery/discovery_test.go @@ -37,6 +37,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/sets" discoveryendpoint "k8s.io/apiserver/pkg/endpoints/discovery/aggregated" genericfeatures "k8s.io/apiserver/pkg/features" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -241,6 +242,7 @@ func TestAggregatedAPIServiceDiscovery(t *testing.T) { // For each groupversion served by our resourcemanager, create an APIService // object connected to our fake APIServer + var groupVersions []metav1.GroupVersion for _, versionInfo := range basicTestGroup.Versions { groupVersion := metav1.GroupVersion{ Group: basicTestGroup.Name, @@ -248,14 +250,19 @@ func TestAggregatedAPIServiceDiscovery(t *testing.T) { } require.NoError(t, registerAPIService(ctx, client, groupVersion, service)) - defer func() { - require.NoError(t, unregisterAPIService(ctx, client, groupVersion)) - }() + groupVersions = append(groupVersions, groupVersion) } // Keep repeatedly fetching document from aggregator. // Check to see if it contains our service within a reasonable amount of time require.NoError(t, WaitForGroups(ctx, client, basicTestGroupWithFixup)) + require.NoError(t, WaitForRootPaths(t, ctx, client, sets.New("/apis/"+basicTestGroup.Name), nil)) + + // Unregister and ensure the group gets dropped from root paths + for _, groupVersion := range groupVersions { + require.NoError(t, unregisterAPIService(ctx, client, groupVersion)) + } + require.NoError(t, WaitForRootPaths(t, ctx, client, nil, sets.New("/apis/"+basicTestGroup.Name))) } func runTestCases(t *testing.T, cases []testCase) { diff --git a/test/integration/apiserver/discovery/framework.go b/test/integration/apiserver/discovery/framework.go index 4593b27bb9e..f0642330db9 100644 --- a/test/integration/apiserver/discovery/framework.go +++ b/test/integration/apiserver/discovery/framework.go @@ -22,6 +22,7 @@ import ( "fmt" "reflect" "strings" + "testing" "time" apiextensions "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" @@ -29,6 +30,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" @@ -573,6 +575,29 @@ func WaitForGroupsAbsent(ctx context.Context, client testClient, groups ...strin } +func WaitForRootPaths(t *testing.T, ctx context.Context, client testClient, requirePaths, forbidPaths sets.Set[string]) error { + return wait.PollUntilContextTimeout(ctx, 250*time.Millisecond, maxTimeout, true, func(ctx context.Context) (done bool, err error) { + statusContent, err := client.Discovery().RESTClient().Get().AbsPath("/").SetHeader("Accept", "application/json").DoRaw(ctx) + if err != nil { + return false, err + } + rootPaths := metav1.RootPaths{} + if err := json.Unmarshal(statusContent, &rootPaths); err != nil { + return false, err + } + paths := sets.New(rootPaths.Paths...) + if missing := requirePaths.Difference(paths); len(missing) > 0 { + t.Logf("missing required root paths %v", sets.List(missing)) + return false, nil + } + if present := forbidPaths.Intersection(paths); len(present) > 0 { + t.Logf("present forbidden root paths %v", sets.List(present)) + return false, nil + } + return true, nil + }) +} + func WaitForGroups(ctx context.Context, client testClient, groups ...apidiscoveryv2beta1.APIGroupDiscovery) error { return WaitForResultWithCondition(ctx, client, func(groupList apidiscoveryv2beta1.APIGroupDiscoveryList) bool { for _, searchGroup := range groups {