forked from GoogleCloudPlatform/k8s-stackdriver
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mapper.go
135 lines (104 loc) · 4.18 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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package dynamicmapper
import (
"fmt"
"sync"
"time"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/discovery"
"k8s.io/client-go/restmapper"
)
// RegeneratingDiscoveryRESTMapper is a RESTMapper which Regenerates its cache of mappings periodically.
// It functions by recreating a normal discovery RESTMapper at the specified interval.
// We don't refresh automatically on cache misses, since we get called on every label, plenty of which will
// be unrelated to Kubernetes resources.
type RegeneratingDiscoveryRESTMapper struct {
discoveryClient discovery.DiscoveryInterface
refreshInterval time.Duration
mu sync.RWMutex
delegate meta.RESTMapper
}
// NewRESTMapper creates RegeneratingDiscoveryRESTMapper.
func NewRESTMapper(discoveryClient discovery.DiscoveryInterface, refreshInterval time.Duration) (*RegeneratingDiscoveryRESTMapper, error) {
mapper := &RegeneratingDiscoveryRESTMapper{
discoveryClient: discoveryClient,
refreshInterval: refreshInterval,
}
if err := mapper.RegenerateMappings(); err != nil {
return nil, fmt.Errorf("unable to populate initial set of REST mappings: %v", err)
}
return mapper, nil
}
// RunUntil runs the mapping refresher until the given stop channel is closed.
func (m *RegeneratingDiscoveryRESTMapper) RunUntil(stop <-chan struct{}) {
go wait.Until(func() {
if err := m.RegenerateMappings(); err != nil {
glog.Errorf("error regenerating REST mappings from discovery: %v", err)
}
}, m.refreshInterval, stop)
}
// RegenerateMappings regenerates cached mappings.
func (m *RegeneratingDiscoveryRESTMapper) RegenerateMappings() error {
resources, err := restmapper.GetAPIGroupResources(m.discoveryClient)
if err != nil {
return err
}
newDelegate := restmapper.NewDiscoveryRESTMapper(resources)
// don't lock until we're ready to replace
m.mu.Lock()
defer m.mu.Unlock()
m.delegate = newDelegate
return nil
}
// KindFor takes a partial resource and returns back the single match.
// It returns an error if there are multiple matches.
func (m *RegeneratingDiscoveryRESTMapper) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) {
m.mu.RLock()
defer m.mu.RUnlock()
return m.delegate.KindFor(resource)
}
// KindsFor takes a partial resource and returns back the list of
// potential kinds in priority order.
func (m *RegeneratingDiscoveryRESTMapper) KindsFor(resource schema.GroupVersionResource) ([]schema.GroupVersionKind, error) {
m.mu.RLock()
defer m.mu.RUnlock()
return m.delegate.KindsFor(resource)
}
// ResourceFor takes a partial resource and returns back the single
// match. It returns an error if there are multiple matches.
func (m *RegeneratingDiscoveryRESTMapper) ResourceFor(input schema.GroupVersionResource) (schema.GroupVersionResource, error) {
m.mu.RLock()
defer m.mu.RUnlock()
return m.delegate.ResourceFor(input)
}
// ResourcesFor takes a partial resource and returns back the list of
// potential resource in priority order.
func (m *RegeneratingDiscoveryRESTMapper) ResourcesFor(input schema.GroupVersionResource) ([]schema.GroupVersionResource, error) {
m.mu.RLock()
defer m.mu.RUnlock()
return m.delegate.ResourcesFor(input)
}
// RESTMapping identifies a preferred resource mapping for the
// provided group kind.
func (m *RegeneratingDiscoveryRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (*meta.RESTMapping, error) {
m.mu.RLock()
defer m.mu.RUnlock()
return m.delegate.RESTMapping(gk, versions...)
}
// RESTMappings returns the RESTMappings for the provided group kind
// in a rough internal preferred order. If no kind is found, it will
// return a NoResourceMatchError.
func (m *RegeneratingDiscoveryRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) ([]*meta.RESTMapping, error) {
m.mu.RLock()
defer m.mu.RUnlock()
return m.delegate.RESTMappings(gk, versions...)
}
// ResourceSingularizer converts a resource name from plural to
// singular (e.g., from pods to pod).
func (m *RegeneratingDiscoveryRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
m.mu.RLock()
defer m.mu.RUnlock()
return m.delegate.ResourceSingularizer(resource)
}