1
16
17 package discovery
18
19 import (
20 "fmt"
21
22 apidiscovery "k8s.io/api/apidiscovery/v2"
23 apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25 "k8s.io/apimachinery/pkg/runtime/schema"
26 )
27
28
29
30 type StaleGroupVersionError struct {
31 gv schema.GroupVersion
32 }
33
34 func (s StaleGroupVersionError) Error() string {
35 return fmt.Sprintf("stale GroupVersion discovery: %v", s.gv)
36 }
37
38
39
40 func SplitGroupsAndResources(aggregatedGroups apidiscovery.APIGroupDiscoveryList) (
41 *metav1.APIGroupList,
42 map[schema.GroupVersion]*metav1.APIResourceList,
43 map[schema.GroupVersion]error) {
44
45
46 groups := []*metav1.APIGroup{}
47 failedGVs := map[schema.GroupVersion]error{}
48 resourcesByGV := map[schema.GroupVersion]*metav1.APIResourceList{}
49 for _, aggGroup := range aggregatedGroups.Items {
50 group, resources, failed := convertAPIGroup(aggGroup)
51 groups = append(groups, group)
52 for gv, resourceList := range resources {
53 resourcesByGV[gv] = resourceList
54 }
55 for gv, err := range failed {
56 failedGVs[gv] = err
57 }
58 }
59
60 groupList := &metav1.APIGroupList{}
61 groupList.Groups = make([]metav1.APIGroup, 0, len(groups))
62 for _, group := range groups {
63 groupList.Groups = append(groupList.Groups, *group)
64 }
65 return groupList, resourcesByGV, failedGVs
66 }
67
68
69
70 func convertAPIGroup(g apidiscovery.APIGroupDiscovery) (
71 *metav1.APIGroup,
72 map[schema.GroupVersion]*metav1.APIResourceList,
73 map[schema.GroupVersion]error) {
74
75 group := &metav1.APIGroup{}
76 gvResources := map[schema.GroupVersion]*metav1.APIResourceList{}
77 failedGVs := map[schema.GroupVersion]error{}
78 group.Name = g.ObjectMeta.Name
79 for _, v := range g.Versions {
80 gv := schema.GroupVersion{Group: g.Name, Version: v.Version}
81 if v.Freshness == apidiscovery.DiscoveryFreshnessStale {
82 failedGVs[gv] = StaleGroupVersionError{gv: gv}
83 continue
84 }
85 version := metav1.GroupVersionForDiscovery{}
86 version.GroupVersion = gv.String()
87 version.Version = v.Version
88 group.Versions = append(group.Versions, version)
89
90 if group.PreferredVersion == (metav1.GroupVersionForDiscovery{}) {
91 group.PreferredVersion = version
92 }
93 resourceList := &metav1.APIResourceList{}
94 resourceList.GroupVersion = gv.String()
95 for _, r := range v.Resources {
96 resource, err := convertAPIResource(r)
97 if err == nil {
98 resourceList.APIResources = append(resourceList.APIResources, resource)
99 }
100
101
102
103 for _, subresource := range r.Subresources {
104 sr, err := convertAPISubresource(resource, subresource)
105 if err == nil {
106 resourceList.APIResources = append(resourceList.APIResources, sr)
107 }
108 }
109 }
110 gvResources[gv] = resourceList
111 }
112 return group, gvResources, failedGVs
113 }
114
115 var emptyKind = metav1.GroupVersionKind{}
116
117
118
119
120
121 func convertAPIResource(in apidiscovery.APIResourceDiscovery) (metav1.APIResource, error) {
122 result := metav1.APIResource{
123 Name: in.Resource,
124 SingularName: in.SingularResource,
125 Namespaced: in.Scope == apidiscovery.ScopeNamespace,
126 Verbs: in.Verbs,
127 ShortNames: in.ShortNames,
128 Categories: in.Categories,
129 }
130 var err error
131 if in.ResponseKind != nil && (*in.ResponseKind) != emptyKind {
132 result.Group = in.ResponseKind.Group
133 result.Version = in.ResponseKind.Version
134 result.Kind = in.ResponseKind.Kind
135 } else {
136 err = fmt.Errorf("discovery resource %s missing GVK", in.Resource)
137 }
138
139
140 return result, err
141 }
142
143
144 func convertAPISubresource(parent metav1.APIResource, in apidiscovery.APISubresourceDiscovery) (metav1.APIResource, error) {
145 result := metav1.APIResource{}
146 if in.ResponseKind == nil || (*in.ResponseKind) == emptyKind {
147 return result, fmt.Errorf("subresource %s/%s missing GVK", parent.Name, in.Subresource)
148 }
149 result.Name = fmt.Sprintf("%s/%s", parent.Name, in.Subresource)
150 result.SingularName = parent.SingularName
151 result.Namespaced = parent.Namespaced
152 result.Group = in.ResponseKind.Group
153 result.Version = in.ResponseKind.Version
154 result.Kind = in.ResponseKind.Kind
155 result.Verbs = in.Verbs
156 return result, nil
157 }
158
159
160
161
162
163
164
165 func SplitGroupsAndResourcesV2Beta1(aggregatedGroups apidiscoveryv2beta1.APIGroupDiscoveryList) (
166 *metav1.APIGroupList,
167 map[schema.GroupVersion]*metav1.APIResourceList,
168 map[schema.GroupVersion]error) {
169
170
171 groups := []*metav1.APIGroup{}
172 failedGVs := map[schema.GroupVersion]error{}
173 resourcesByGV := map[schema.GroupVersion]*metav1.APIResourceList{}
174 for _, aggGroup := range aggregatedGroups.Items {
175 group, resources, failed := convertAPIGroupv2beta1(aggGroup)
176 groups = append(groups, group)
177 for gv, resourceList := range resources {
178 resourcesByGV[gv] = resourceList
179 }
180 for gv, err := range failed {
181 failedGVs[gv] = err
182 }
183 }
184
185 groupList := &metav1.APIGroupList{}
186 groupList.Groups = make([]metav1.APIGroup, 0, len(groups))
187 for _, group := range groups {
188 groupList.Groups = append(groupList.Groups, *group)
189 }
190 return groupList, resourcesByGV, failedGVs
191 }
192
193
194
195 func convertAPIGroupv2beta1(g apidiscoveryv2beta1.APIGroupDiscovery) (
196 *metav1.APIGroup,
197 map[schema.GroupVersion]*metav1.APIResourceList,
198 map[schema.GroupVersion]error) {
199
200 group := &metav1.APIGroup{}
201 gvResources := map[schema.GroupVersion]*metav1.APIResourceList{}
202 failedGVs := map[schema.GroupVersion]error{}
203 group.Name = g.ObjectMeta.Name
204 for _, v := range g.Versions {
205 gv := schema.GroupVersion{Group: g.Name, Version: v.Version}
206 if v.Freshness == apidiscoveryv2beta1.DiscoveryFreshnessStale {
207 failedGVs[gv] = StaleGroupVersionError{gv: gv}
208 continue
209 }
210 version := metav1.GroupVersionForDiscovery{}
211 version.GroupVersion = gv.String()
212 version.Version = v.Version
213 group.Versions = append(group.Versions, version)
214
215 if group.PreferredVersion == (metav1.GroupVersionForDiscovery{}) {
216 group.PreferredVersion = version
217 }
218 resourceList := &metav1.APIResourceList{}
219 resourceList.GroupVersion = gv.String()
220 for _, r := range v.Resources {
221 resource, err := convertAPIResourcev2beta1(r)
222 if err == nil {
223 resourceList.APIResources = append(resourceList.APIResources, resource)
224 }
225
226
227
228 for _, subresource := range r.Subresources {
229 sr, err := convertAPISubresourcev2beta1(resource, subresource)
230 if err == nil {
231 resourceList.APIResources = append(resourceList.APIResources, sr)
232 }
233 }
234 }
235 gvResources[gv] = resourceList
236 }
237 return group, gvResources, failedGVs
238 }
239
240
241
242
243
244 func convertAPIResourcev2beta1(in apidiscoveryv2beta1.APIResourceDiscovery) (metav1.APIResource, error) {
245 result := metav1.APIResource{
246 Name: in.Resource,
247 SingularName: in.SingularResource,
248 Namespaced: in.Scope == apidiscoveryv2beta1.ScopeNamespace,
249 Verbs: in.Verbs,
250 ShortNames: in.ShortNames,
251 Categories: in.Categories,
252 }
253
254
255 if in.ResponseKind == nil || (*in.ResponseKind) == emptyKind {
256 return result, fmt.Errorf("discovery resource %s missing GVK", in.Resource)
257 }
258 result.Group = in.ResponseKind.Group
259 result.Version = in.ResponseKind.Version
260 result.Kind = in.ResponseKind.Kind
261 return result, nil
262 }
263
264
265 func convertAPISubresourcev2beta1(parent metav1.APIResource, in apidiscoveryv2beta1.APISubresourceDiscovery) (metav1.APIResource, error) {
266 result := metav1.APIResource{}
267 if in.ResponseKind == nil || (*in.ResponseKind) == emptyKind {
268 return result, fmt.Errorf("subresource %s/%s missing GVK", parent.Name, in.Subresource)
269 }
270 result.Name = fmt.Sprintf("%s/%s", parent.Name, in.Subresource)
271 result.SingularName = parent.SingularName
272 result.Namespaced = parent.Namespaced
273 result.Group = in.ResponseKind.Group
274 result.Version = in.ResponseKind.Version
275 result.Kind = in.ResponseKind.Kind
276 result.Verbs = in.Verbs
277 return result, nil
278 }
279
View as plain text