Merge pull request #127524 from mjudeikis/mjudeikis/extend.group.manager

Add GroupLister interface to discovery GroupManager
This commit is contained in:
Kubernetes Prow Robot 2024-09-23 09:06:06 +01:00 committed by GitHub
commit 19500e8551
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 38 additions and 4 deletions

View File

@ -17,6 +17,7 @@ limitations under the License.
package discovery
import (
"context"
"net/http"
"sync"
@ -33,12 +34,21 @@ import (
// GroupManager is an interface that allows dynamic mutation of the existing webservice to handle
// API groups being added or removed.
type GroupManager interface {
GroupLister
AddGroup(apiGroup metav1.APIGroup)
RemoveGroup(groupName string)
ServeHTTP(resp http.ResponseWriter, req *http.Request)
WebService() *restful.WebService
}
// GroupLister knows how to list APIGroups for discovery.
type GroupLister interface {
// Groups returns APIGroups for discovery, filling in ServerAddressByClientCIDRs
// based on data in req.
Groups(ctx context.Context, req *http.Request) ([]metav1.APIGroup, error)
}
// rootAPIsHandler creates a webservice serving api group discovery.
// The list of APIGroups may change while the server is running because additional resources
// are registered or removed. It is not safe to cache the values.
@ -94,24 +104,40 @@ func (s *rootAPIsHandler) RemoveGroup(groupName string) {
}
}
func (s *rootAPIsHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
func (s *rootAPIsHandler) Groups(ctx context.Context, req *http.Request) ([]metav1.APIGroup, error) {
s.lock.RLock()
defer s.lock.RUnlock()
return s.groupsLocked(ctx, req), nil
}
// groupsLocked returns the APIGroupList discovery information for this handler.
// The caller must hold the lock before invoking this method to avoid data races.
func (s *rootAPIsHandler) groupsLocked(ctx context.Context, req *http.Request) []metav1.APIGroup {
clientIP := utilnet.GetClientIP(req)
serverCIDR := s.addresses.ServerAddressByClientCIDRs(clientIP)
orderedGroups := []metav1.APIGroup{}
for _, groupName := range s.apiGroupNames {
orderedGroups = append(orderedGroups, s.apiGroups[groupName])
}
clientIP := utilnet.GetClientIP(req)
serverCIDR := s.addresses.ServerAddressByClientCIDRs(clientIP)
groups := make([]metav1.APIGroup, len(orderedGroups))
for i := range orderedGroups {
groups[i] = orderedGroups[i]
groups[i].ServerAddressByClientCIDRs = serverCIDR
}
responsewriters.WriteObjectNegotiated(s.serializer, negotiation.DefaultEndpointRestrictions, schema.GroupVersion{}, resp, req, http.StatusOK, &metav1.APIGroupList{Groups: groups}, false)
return groups
}
func (s *rootAPIsHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
s.lock.RLock()
defer s.lock.RUnlock()
groupList := metav1.APIGroupList{Groups: s.groupsLocked(req.Context(), req)}
responsewriters.WriteObjectNegotiated(s.serializer, negotiation.DefaultEndpointRestrictions, schema.GroupVersion{}, resp, req, http.StatusOK, &groupList, false)
}
func (s *rootAPIsHandler) restfulHandle(req *restful.Request, resp *restful.Response) {

View File

@ -17,6 +17,7 @@ limitations under the License.
package discovery
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
@ -173,6 +174,13 @@ func TestDiscoveryOrdering(t *testing.T) {
t.Fatalf("unexpected error: %v", err)
}
// Check if internal groups listers returns the same group.
groups, err := handler.Groups(context.TODO(), &http.Request{})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
assert.Len(t, groups, 6)
assert.Len(t, groupList.Groups, 6)
assert.Equal(t, "x", groupList.Groups[0].Name)
assert.Equal(t, "y", groupList.Groups[1].Name)