1
16
17 package apiserver
18
19 import (
20 "net/http"
21
22 apierrors "k8s.io/apimachinery/pkg/api/errors"
23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24 "k8s.io/apimachinery/pkg/labels"
25 "k8s.io/apimachinery/pkg/runtime/schema"
26 "k8s.io/apimachinery/pkg/runtime/serializer"
27 "k8s.io/apimachinery/pkg/util/sets"
28 "k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
29 "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
30
31 apiregistrationv1api "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
32 apiregistrationv1apihelper "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/helper"
33 apiregistrationv1beta1api "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1"
34 listers "k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1"
35 )
36
37
38
39 type apisHandler struct {
40 codecs serializer.CodecFactory
41 lister listers.APIServiceLister
42 discoveryGroup metav1.APIGroup
43 }
44
45 func discoveryGroup(enabledVersions sets.String) metav1.APIGroup {
46 retval := metav1.APIGroup{
47 Name: apiregistrationv1api.GroupName,
48 Versions: []metav1.GroupVersionForDiscovery{
49 {
50 GroupVersion: apiregistrationv1api.SchemeGroupVersion.String(),
51 Version: apiregistrationv1api.SchemeGroupVersion.Version,
52 },
53 },
54 PreferredVersion: metav1.GroupVersionForDiscovery{
55 GroupVersion: apiregistrationv1api.SchemeGroupVersion.String(),
56 Version: apiregistrationv1api.SchemeGroupVersion.Version,
57 },
58 }
59
60 if enabledVersions.Has(apiregistrationv1beta1api.SchemeGroupVersion.Version) {
61 retval.Versions = append(retval.Versions, metav1.GroupVersionForDiscovery{
62 GroupVersion: apiregistrationv1beta1api.SchemeGroupVersion.String(),
63 Version: apiregistrationv1beta1api.SchemeGroupVersion.Version,
64 })
65 }
66
67 return retval
68 }
69
70 func (r *apisHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
71 discoveryGroupList := &metav1.APIGroupList{
72
73
74 Groups: []metav1.APIGroup{r.discoveryGroup},
75 }
76
77 apiServices, err := r.lister.List(labels.Everything())
78 if err != nil {
79 http.Error(w, err.Error(), http.StatusInternalServerError)
80 return
81 }
82 apiServicesByGroup := apiregistrationv1apihelper.SortedByGroupAndVersion(apiServices)
83 for _, apiGroupServers := range apiServicesByGroup {
84
85 if len(apiGroupServers[0].Spec.Group) == 0 {
86 continue
87 }
88 discoveryGroup := convertToDiscoveryAPIGroup(apiGroupServers)
89 if discoveryGroup != nil {
90 discoveryGroupList.Groups = append(discoveryGroupList.Groups, *discoveryGroup)
91 }
92 }
93
94 responsewriters.WriteObjectNegotiated(r.codecs, negotiation.DefaultEndpointRestrictions, schema.GroupVersion{}, w, req, http.StatusOK, discoveryGroupList, false)
95 }
96
97
98
99 func convertToDiscoveryAPIGroup(apiServices []*apiregistrationv1api.APIService) *metav1.APIGroup {
100 apiServicesByGroup := apiregistrationv1apihelper.SortedByGroupAndVersion(apiServices)[0]
101
102 var discoveryGroup *metav1.APIGroup
103
104 for _, apiService := range apiServicesByGroup {
105
106 if discoveryGroup == nil {
107 discoveryGroup = &metav1.APIGroup{
108 Name: apiService.Spec.Group,
109 PreferredVersion: metav1.GroupVersionForDiscovery{
110 GroupVersion: apiService.Spec.Group + "/" + apiService.Spec.Version,
111 Version: apiService.Spec.Version,
112 },
113 }
114 }
115
116 discoveryGroup.Versions = append(discoveryGroup.Versions,
117 metav1.GroupVersionForDiscovery{
118 GroupVersion: apiService.Spec.Group + "/" + apiService.Spec.Version,
119 Version: apiService.Spec.Version,
120 },
121 )
122 }
123
124 return discoveryGroup
125 }
126
127
128 type apiGroupHandler struct {
129 codecs serializer.CodecFactory
130 groupName string
131
132 lister listers.APIServiceLister
133
134 delegate http.Handler
135 }
136
137 func (r *apiGroupHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
138 apiServices, err := r.lister.List(labels.Everything())
139 if statusErr, ok := err.(*apierrors.StatusError); ok {
140 responsewriters.WriteRawJSON(int(statusErr.Status().Code), statusErr.Status(), w)
141 return
142 }
143 if err != nil {
144 http.Error(w, err.Error(), http.StatusInternalServerError)
145 return
146 }
147
148 apiServicesForGroup := []*apiregistrationv1api.APIService{}
149 for _, apiService := range apiServices {
150 if apiService.Spec.Group == r.groupName {
151 apiServicesForGroup = append(apiServicesForGroup, apiService)
152 }
153 }
154
155 if len(apiServicesForGroup) == 0 {
156 r.delegate.ServeHTTP(w, req)
157 return
158 }
159
160 discoveryGroup := convertToDiscoveryAPIGroup(apiServicesForGroup)
161 if discoveryGroup == nil {
162 http.Error(w, "", http.StatusNotFound)
163 return
164 }
165 responsewriters.WriteObjectNegotiated(r.codecs, negotiation.DefaultEndpointRestrictions, schema.GroupVersion{}, w, req, http.StatusOK, discoveryGroup, false)
166 }
167
View as plain text