...
1
16
17 package resource
18
19 import (
20 "context"
21 "fmt"
22 "reflect"
23
24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
26 "k8s.io/apimachinery/pkg/runtime/schema"
27 "k8s.io/client-go/dynamic"
28 )
29
30
31
32 type CRDGetter func() ([]schema.GroupKind, error)
33
34 func CRDFromDynamic(client dynamic.Interface) CRDGetter {
35 return func() ([]schema.GroupKind, error) {
36 list, err := client.Resource(schema.GroupVersionResource{
37 Group: "apiextensions.k8s.io",
38 Version: "v1",
39 Resource: "customresourcedefinitions",
40 }).List(context.TODO(), metav1.ListOptions{})
41 if err != nil {
42 return nil, fmt.Errorf("failed to list CRDs: %v", err)
43 }
44 if list == nil {
45 return nil, nil
46 }
47
48 gks := []schema.GroupKind{}
49
50
51 for _, crd := range (*list).Items {
52
53 group, _, _ := unstructured.NestedString(crd.Object, "spec", "group")
54 kind, _, _ := unstructured.NestedString(crd.Object, "spec", "names", "kind")
55
56 gks = append(gks, schema.GroupKind{
57 Group: group,
58 Kind: kind,
59 })
60 }
61
62 return gks, nil
63 }
64 }
65
66
67
68 type CRDFinder interface {
69 HasCRD(gvk schema.GroupKind) (bool, error)
70 }
71
72 func NewCRDFinder(getter CRDGetter) CRDFinder {
73 return &crdFinder{
74 getter: getter,
75 }
76 }
77
78 type crdFinder struct {
79 getter CRDGetter
80 cache *[]schema.GroupKind
81 }
82
83 func (f *crdFinder) cacheCRDs() error {
84 if f.cache != nil {
85 return nil
86 }
87
88 list, err := f.getter()
89 if err != nil {
90 return err
91 }
92 f.cache = &list
93 return nil
94 }
95
96 func (f *crdFinder) findCRD(gvk schema.GroupKind) bool {
97 for _, crd := range *f.cache {
98 if reflect.DeepEqual(gvk, crd) {
99 return true
100 }
101 }
102 return false
103 }
104
105 func (f *crdFinder) HasCRD(gvk schema.GroupKind) (bool, error) {
106 if err := f.cacheCRDs(); err != nil {
107 return false, err
108 }
109 return f.findCRD(gvk), nil
110 }
111
View as plain text