blob: 3ff84611ab553e85df26608139d0a9a49b691a8c [file] [log] [blame]
David Bainbridge86971522019-09-26 22:09:39 +00001/*
2Copyright 2019 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package runtime
18
19import (
20 "sync"
21
22 "k8s.io/apimachinery/pkg/runtime/schema"
23)
24
25type equivalentResourceRegistry struct {
26 // keyFunc computes a key for the specified resource (this allows honoring colocated resources across API groups).
27 // if null, or if "" is returned, resource.String() is used as the key
28 keyFunc func(resource schema.GroupResource) string
29 // resources maps key -> subresource -> equivalent resources (subresource is not included in the returned resources).
30 // main resources are stored with subresource="".
31 resources map[string]map[string][]schema.GroupVersionResource
32 // kinds maps resource -> subresource -> kind
33 kinds map[schema.GroupVersionResource]map[string]schema.GroupVersionKind
34 // keys caches the computed key for each GroupResource
35 keys map[schema.GroupResource]string
36
37 mutex sync.RWMutex
38}
39
40var _ EquivalentResourceMapper = (*equivalentResourceRegistry)(nil)
41var _ EquivalentResourceRegistry = (*equivalentResourceRegistry)(nil)
42
43// NewEquivalentResourceRegistry creates a resource registry that considers all versions of a GroupResource to be equivalent.
44func NewEquivalentResourceRegistry() EquivalentResourceRegistry {
45 return &equivalentResourceRegistry{}
46}
47
48// NewEquivalentResourceRegistryWithIdentity creates a resource mapper with a custom identity function.
49// If "" is returned by the function, GroupResource#String is used as the identity.
50// GroupResources with the same identity string are considered equivalent.
51func NewEquivalentResourceRegistryWithIdentity(keyFunc func(schema.GroupResource) string) EquivalentResourceRegistry {
52 return &equivalentResourceRegistry{keyFunc: keyFunc}
53}
54
55func (r *equivalentResourceRegistry) EquivalentResourcesFor(resource schema.GroupVersionResource, subresource string) []schema.GroupVersionResource {
56 r.mutex.RLock()
57 defer r.mutex.RUnlock()
58 return r.resources[r.keys[resource.GroupResource()]][subresource]
59}
60func (r *equivalentResourceRegistry) KindFor(resource schema.GroupVersionResource, subresource string) schema.GroupVersionKind {
61 r.mutex.RLock()
62 defer r.mutex.RUnlock()
63 return r.kinds[resource][subresource]
64}
65func (r *equivalentResourceRegistry) RegisterKindFor(resource schema.GroupVersionResource, subresource string, kind schema.GroupVersionKind) {
66 r.mutex.Lock()
67 defer r.mutex.Unlock()
68 if r.kinds == nil {
69 r.kinds = map[schema.GroupVersionResource]map[string]schema.GroupVersionKind{}
70 }
71 if r.kinds[resource] == nil {
72 r.kinds[resource] = map[string]schema.GroupVersionKind{}
73 }
74 r.kinds[resource][subresource] = kind
75
76 // get the shared key of the parent resource
77 key := ""
78 gr := resource.GroupResource()
79 if r.keyFunc != nil {
80 key = r.keyFunc(gr)
81 }
82 if key == "" {
83 key = gr.String()
84 }
85
86 if r.keys == nil {
87 r.keys = map[schema.GroupResource]string{}
88 }
89 r.keys[gr] = key
90
91 if r.resources == nil {
92 r.resources = map[string]map[string][]schema.GroupVersionResource{}
93 }
94 if r.resources[key] == nil {
95 r.resources[key] = map[string][]schema.GroupVersionResource{}
96 }
97 r.resources[key][subresource] = append(r.resources[key][subresource], resource)
98}