@@ -5,17 +5,20 @@ package dao
5
5
6
6
import (
7
7
"fmt"
8
+ "slices"
8
9
"sort"
9
10
"strings"
10
11
"sync"
11
12
12
- "github.com/derailed/k9s/internal/client"
13
13
"github.com/rs/zerolog/log"
14
+ apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
14
15
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15
16
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
16
17
"k8s.io/apimachinery/pkg/labels"
17
18
"k8s.io/apimachinery/pkg/runtime"
18
19
"k8s.io/apimachinery/pkg/runtime/schema"
20
+
21
+ "github.com/derailed/k9s/internal/client"
19
22
)
20
23
21
24
const (
@@ -95,10 +98,7 @@ func AccessorFor(f Factory, gvr client.GVR) (Accessor, error) {
95
98
96
99
r , ok := m [gvr ]
97
100
if ! ok {
98
- r = new (Generic )
99
- if MetaAccess .IsScalable (gvr ) {
100
- r = new (Scaler )
101
- }
101
+ r = new (Scaler )
102
102
log .Debug ().Msgf ("No DAO registry entry for %q. Using generics!" , gvr )
103
103
}
104
104
r .Init (f , gvr )
@@ -144,12 +144,7 @@ func (m *Meta) GVK2GVR(gv schema.GroupVersion, kind string) (client.GVR, bool, b
144
144
145
145
// IsCRD checks if resource represents a CRD
146
146
func IsCRD (r metav1.APIResource ) bool {
147
- for _ , c := range r .Categories {
148
- if c == crdCat {
149
- return true
150
- }
151
- }
152
- return false
147
+ return slices .Contains (r .Categories , crdCat )
153
148
}
154
149
155
150
// MetaFor returns a resource metadata for a given gvr.
@@ -166,24 +161,19 @@ func (m *Meta) MetaFor(gvr client.GVR) (metav1.APIResource, error) {
166
161
167
162
// IsK8sMeta checks for non resource meta.
168
163
func IsK8sMeta (m metav1.APIResource ) bool {
169
- for _ , c := range m .Categories {
170
- if c == k9sCat || c == helmCat {
171
- return false
172
- }
173
- }
174
-
175
- return true
164
+ return ! slices .ContainsFunc (m .Categories , func (category string ) bool {
165
+ return category == k9sCat || category == helmCat
166
+ })
176
167
}
177
168
178
169
// IsK9sMeta checks for non resource meta.
179
170
func IsK9sMeta (m metav1.APIResource ) bool {
180
- for _ , c := range m .Categories {
181
- if c == k9sCat {
182
- return true
183
- }
184
- }
171
+ return slices .Contains (m .Categories , k9sCat )
172
+ }
185
173
186
- return false
174
+ // IsScalable check if the resource can be scaled
175
+ func IsScalable (m metav1.APIResource ) bool {
176
+ return slices .Contains (m .Categories , scaleCat )
187
177
}
188
178
189
179
// LoadResources hydrates server preferred+CRDs resource metadata.
@@ -196,22 +186,12 @@ func (m *Meta) LoadResources(f Factory) error {
196
186
return err
197
187
}
198
188
loadNonResource (m .resMetas )
199
- loadCRDs (f , m .resMetas )
200
189
201
- return nil
202
- }
203
-
204
- // IsScalable check if the resource can be scaled
205
- func (m * Meta ) IsScalable (gvr client.GVR ) bool {
206
- if meta , ok := m .resMetas [gvr ]; ok {
207
- for _ , c := range meta .Categories {
208
- if c == scaleCat {
209
- return true
210
- }
211
- }
212
- }
190
+ // We've actually loaded all the CRDs in loadPreferred, and we're now adding
191
+ // some additional CRD properties on top of that.
192
+ go m .loadCRDs (f )
213
193
214
- return false
194
+ return nil
215
195
}
216
196
217
197
// BOZO!! Need countermeasures for direct commands!
@@ -419,11 +399,16 @@ func isDeprecated(gvr client.GVR) bool {
419
399
return ok
420
400
}
421
401
422
- func loadCRDs (f Factory , m ResourceMetas ) {
402
+ // loadCRDs Wait for the cache to synced and then add some additional properties to CRD.
403
+ func (m * Meta ) loadCRDs (f Factory ) {
423
404
if f .Client () == nil || ! f .Client ().ConnectionOK () {
424
405
return
425
406
}
426
- oo , err := f .List (crdGVR , client .ClusterScope , false , labels .Everything ())
407
+
408
+ // we must block until all CRDs caches were synced
409
+ f .WaitForCacheSync ()
410
+
411
+ oo , err := f .List (crdGVR , client .ClusterScope , true , labels .Everything ())
427
412
if err != nil {
428
413
log .Warn ().Err (err ).Msgf ("Fail CRDs load" )
429
414
return
@@ -440,25 +425,28 @@ func loadCRDs(f Factory, m ResourceMetas) {
440
425
var meta metav1.APIResource
441
426
meta .Kind = crd .Spec .Names .Kind
442
427
meta .Group = crd .Spec .Group
443
- meta .Name = crd .Name
428
+ meta .Name = crd .Spec . Names . Plural
444
429
meta .SingularName = crd .Spec .Names .Singular
445
430
meta .ShortNames = crd .Spec .Names .ShortNames
446
431
meta .Namespaced = crd .Spec .Scope == apiext .NamespaceScoped
447
432
for _ , v := range crd .Spec .Versions {
448
433
if v .Served && ! v .Deprecated {
434
+ if v .Subresources != nil && v .Subresources .Scale != nil && ! slices .Contains (meta .Categories , scaleCat ) {
435
+ meta .Categories = append (meta .Categories , scaleCat )
436
+ }
437
+
449
438
meta .Version = v .Name
450
439
break
451
440
}
452
441
}
453
442
454
- // meta, errs := extractMeta(o)
455
- // if len(errs) > 0 {
456
- // log.Error().Err(errs[0]).Msgf("Fail to extract CRD meta (%d) errors", len(errs))
457
- // continue
458
- // }
459
- meta .Categories = append (meta .Categories , crdCat )
460
- gvr := client .NewGVRFromMeta (meta )
461
- m [gvr ] = meta
443
+ if ! slices .Contains (meta .Categories , crdCat ) {
444
+ meta .Categories = append (meta .Categories , crdCat )
445
+ }
446
+
447
+ m .mx .Lock ()
448
+ m .resMetas [client .NewGVRFromMeta (meta )] = meta
449
+ m .mx .Unlock ()
462
450
}
463
451
}
464
452
0 commit comments