mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-09 20:17:41 +00:00
Merge pull request #121283 from tnqn/cleanup-unregistered-group
Unregister group path from apiserver when the group no longer exists
This commit is contained in:
commit
dc8b57d8a7
@ -144,8 +144,9 @@ type APIAggregator struct {
|
|||||||
|
|
||||||
// proxyHandlers are the proxy handlers that are currently registered, keyed by apiservice.name
|
// proxyHandlers are the proxy handlers that are currently registered, keyed by apiservice.name
|
||||||
proxyHandlers map[string]*proxyHandler
|
proxyHandlers map[string]*proxyHandler
|
||||||
// handledGroups are the groups that already have routes
|
// handledGroupVersions contain the groups that already have routes. The key is the name of the group and the value
|
||||||
handledGroups sets.String
|
// is the versions for the group.
|
||||||
|
handledGroupVersions map[string]sets.Set[string]
|
||||||
|
|
||||||
// lister is used to add group handling for /apis/<group> aggregator lookups based on
|
// lister is used to add group handling for /apis/<group> aggregator lookups based on
|
||||||
// controller state
|
// controller state
|
||||||
@ -235,7 +236,7 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg
|
|||||||
delegateHandler: delegationTarget.UnprotectedHandler(),
|
delegateHandler: delegationTarget.UnprotectedHandler(),
|
||||||
proxyTransportDial: proxyTransportDial,
|
proxyTransportDial: proxyTransportDial,
|
||||||
proxyHandlers: map[string]*proxyHandler{},
|
proxyHandlers: map[string]*proxyHandler{},
|
||||||
handledGroups: sets.String{},
|
handledGroupVersions: map[string]sets.Set[string]{},
|
||||||
lister: informerFactory.Apiregistration().V1().APIServices().Lister(),
|
lister: informerFactory.Apiregistration().V1().APIServices().Lister(),
|
||||||
APIRegistrationInformers: informerFactory,
|
APIRegistrationInformers: informerFactory,
|
||||||
serviceResolver: c.ExtraConfig.ServiceResolver,
|
serviceResolver: c.ExtraConfig.ServiceResolver,
|
||||||
@ -524,7 +525,9 @@ func (s *APIAggregator) AddAPIService(apiService *v1.APIService) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if we've already registered the path with the handler, we don't want to do it again.
|
// if we've already registered the path with the handler, we don't want to do it again.
|
||||||
if s.handledGroups.Has(apiService.Spec.Group) {
|
versions, exist := s.handledGroupVersions[apiService.Spec.Group]
|
||||||
|
if exist {
|
||||||
|
versions.Insert(apiService.Spec.Version)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,7 +542,7 @@ func (s *APIAggregator) AddAPIService(apiService *v1.APIService) error {
|
|||||||
// aggregation is protected
|
// aggregation is protected
|
||||||
s.GenericAPIServer.Handler.NonGoRestfulMux.Handle(groupPath, groupDiscoveryHandler)
|
s.GenericAPIServer.Handler.NonGoRestfulMux.Handle(groupPath, groupDiscoveryHandler)
|
||||||
s.GenericAPIServer.Handler.NonGoRestfulMux.UnlistedHandle(groupPath+"/", groupDiscoveryHandler)
|
s.GenericAPIServer.Handler.NonGoRestfulMux.UnlistedHandle(groupPath+"/", groupDiscoveryHandler)
|
||||||
s.handledGroups.Insert(apiService.Spec.Group)
|
s.handledGroupVersions[apiService.Spec.Group] = sets.New[string](apiService.Spec.Version)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,8 +571,18 @@ func (s *APIAggregator) RemoveAPIService(apiServiceName string) {
|
|||||||
}
|
}
|
||||||
delete(s.proxyHandlers, apiServiceName)
|
delete(s.proxyHandlers, apiServiceName)
|
||||||
|
|
||||||
// TODO unregister group level discovery when there are no more versions for the group
|
versions, exist := s.handledGroupVersions[version.Group]
|
||||||
// We don't need this right away because the handler properly delegates when no versions are present
|
if !exist {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
versions.Delete(version.Version)
|
||||||
|
if versions.Len() > 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delete(s.handledGroupVersions, version.Group)
|
||||||
|
groupPath := "/apis/" + version.Group
|
||||||
|
s.GenericAPIServer.Handler.NonGoRestfulMux.Unregister(groupPath)
|
||||||
|
s.GenericAPIServer.Handler.NonGoRestfulMux.Unregister(groupPath + "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultAPIResourceConfigSource returns default configuration for an APIResource.
|
// DefaultAPIResourceConfigSource returns default configuration for an APIResource.
|
||||||
|
@ -52,6 +52,7 @@ import (
|
|||||||
admissionapi "k8s.io/pod-security-admission/api"
|
admissionapi "k8s.io/pod-security-admission/api"
|
||||||
samplev1alpha1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1"
|
samplev1alpha1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1"
|
||||||
"k8s.io/utils/pointer"
|
"k8s.io/utils/pointer"
|
||||||
|
"k8s.io/utils/strings/slices"
|
||||||
|
|
||||||
"github.com/onsi/ginkgo/v2"
|
"github.com/onsi/ginkgo/v2"
|
||||||
"github.com/onsi/gomega"
|
"github.com/onsi/gomega"
|
||||||
@ -560,7 +561,6 @@ func TestSampleAPIServer(ctx context.Context, f *framework.Framework, aggrclient
|
|||||||
ginkgo.By("Adding a label to the APIService")
|
ginkgo.By("Adding a label to the APIService")
|
||||||
apiServiceClient := aggrclient.ApiregistrationV1().APIServices()
|
apiServiceClient := aggrclient.ApiregistrationV1().APIServices()
|
||||||
apiServiceLabel := map[string]string{"e2e-apiservice": "patched"}
|
apiServiceLabel := map[string]string{"e2e-apiservice": "patched"}
|
||||||
apiServiceLabelSelector := labels.SelectorFromSet(apiServiceLabel).String()
|
|
||||||
apiServicePatch, err := json.Marshal(map[string]interface{}{
|
apiServicePatch, err := json.Marshal(map[string]interface{}{
|
||||||
"metadata": map[string]interface{}{
|
"metadata": map[string]interface{}{
|
||||||
"labels": apiServiceLabel,
|
"labels": apiServiceLabel,
|
||||||
@ -641,7 +641,7 @@ func TestSampleAPIServer(ctx context.Context, f *framework.Framework, aggrclient
|
|||||||
framework.Logf("Found updated apiService label for %q", apiServiceName)
|
framework.Logf("Found updated apiService label for %q", apiServiceName)
|
||||||
|
|
||||||
// kubectl delete flunder test-flunder
|
// kubectl delete flunder test-flunder
|
||||||
ginkgo.By(fmt.Sprintf("Delete APIService %q", flunderName))
|
ginkgo.By(fmt.Sprintf("Delete flunders resource %q", flunderName))
|
||||||
err = dynamicClient.Delete(ctx, flunderName, metav1.DeleteOptions{})
|
err = dynamicClient.Delete(ctx, flunderName, metav1.DeleteOptions{})
|
||||||
validateErrorWithDebugInfo(ctx, f, err, pods, "deleting flunders(%v) using dynamic client", unstructuredList.Items)
|
validateErrorWithDebugInfo(ctx, f, err, pods, "deleting flunders(%v) using dynamic client", unstructuredList.Items)
|
||||||
|
|
||||||
@ -724,6 +724,7 @@ func TestSampleAPIServer(ctx context.Context, f *framework.Framework, aggrclient
|
|||||||
}
|
}
|
||||||
framework.Logf("Found patched status condition for %s", wardle.ObjectMeta.Name)
|
framework.Logf("Found patched status condition for %s", wardle.ObjectMeta.Name)
|
||||||
|
|
||||||
|
apiServiceLabelSelector := labels.SelectorFromSet(updatedApiService.Labels).String()
|
||||||
ginkgo.By(fmt.Sprintf("APIService deleteCollection with labelSelector: %q", apiServiceLabelSelector))
|
ginkgo.By(fmt.Sprintf("APIService deleteCollection with labelSelector: %q", apiServiceLabelSelector))
|
||||||
|
|
||||||
err = aggrclient.ApiregistrationV1().APIServices().DeleteCollection(ctx,
|
err = aggrclient.ApiregistrationV1().APIServices().DeleteCollection(ctx,
|
||||||
@ -736,6 +737,24 @@ func TestSampleAPIServer(ctx context.Context, f *framework.Framework, aggrclient
|
|||||||
framework.ExpectNoError(err, "failed to count the required APIServices")
|
framework.ExpectNoError(err, "failed to count the required APIServices")
|
||||||
framework.Logf("APIService %s has been deleted.", apiServiceName)
|
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)
|
cleanupSampleAPIServer(ctx, client, aggrclient, n, apiServiceName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user