-
Notifications
You must be signed in to change notification settings - Fork 0
/
mapper.go
91 lines (82 loc) · 2.78 KB
/
mapper.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package discoverymapper
import (
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/discovery"
"k8s.io/client-go/rest"
"k8s.io/client-go/restmapper"
)
// DiscoveryMapper is a interface for refresh and discovery resources from GVK.
type DiscoveryMapper interface {
GetMapper() (meta.RESTMapper, error)
Refresh() (meta.RESTMapper, error)
RESTMapping(gk schema.GroupKind, version ...string) (*meta.RESTMapping, error)
KindsFor(input schema.GroupVersionResource) ([]schema.GroupVersionKind, error)
}
var _ DiscoveryMapper = &DefaultDiscoveryMapper{}
// DefaultDiscoveryMapper is a K8s resource mapper for discovery, it will cache the result
type DefaultDiscoveryMapper struct {
dc *discovery.DiscoveryClient
mapper meta.RESTMapper
}
// New will create a new DefaultDiscoveryMapper by giving a K8s rest config
func New(c *rest.Config) (DiscoveryMapper, error) {
dc, err := discovery.NewDiscoveryClientForConfig(c)
if err != nil {
return nil, err
}
return &DefaultDiscoveryMapper{
dc: dc,
}, nil
}
// GetMapper will get the cached restmapper, if nil, it will create one by refresh
// Prefer lazy discovery, because resources created after refresh can not be found
func (d *DefaultDiscoveryMapper) GetMapper() (meta.RESTMapper, error) {
if d.mapper == nil {
return d.Refresh()
}
return d.mapper, nil
}
// Refresh will re-create the mapper by getting the new resource from K8s API by using discovery client
func (d *DefaultDiscoveryMapper) Refresh() (meta.RESTMapper, error) {
gr, err := restmapper.GetAPIGroupResources(d.dc)
if err != nil {
return nil, err
}
d.mapper = restmapper.NewDiscoveryRESTMapper(gr)
return d.mapper, nil
}
// RESTMapping will mapping resources from GVK, if not found, it will refresh from APIServer and try once again
func (d *DefaultDiscoveryMapper) RESTMapping(gk schema.GroupKind, version ...string) (*meta.RESTMapping, error) {
mapper, err := d.GetMapper()
if err != nil {
return nil, err
}
mapping, err := mapper.RESTMapping(gk, version...)
if meta.IsNoMatchError(err) {
// if no kind match err, refresh and try once more.
mapper, err = d.Refresh()
if err != nil {
return nil, err
}
mapping, err = mapper.RESTMapping(gk, version...)
}
return mapping, err
}
// KindsFor will get kinds from GroupVersionResource, if version not set, all resources matched will be returned.
func (d *DefaultDiscoveryMapper) KindsFor(input schema.GroupVersionResource) ([]schema.GroupVersionKind, error) {
mapper, err := d.GetMapper()
if err != nil {
return nil, err
}
mapping, err := mapper.KindsFor(input)
if meta.IsNoMatchError(err) {
// if no kind match err, refresh and try once more.
mapper, err = d.Refresh()
if err != nil {
return nil, err
}
mapping, err = mapper.KindsFor(input)
}
return mapping, err
}