Skip to content

Commit 5ff0c86

Browse files
authored
Merge pull request #1235 from yue9944882/model-mapper-cache
Enhancing model-mapper: adding bi-directional caches
2 parents abfcc52 + 8107d51 commit 5ff0c86

File tree

3 files changed

+82
-23
lines changed

3 files changed

+82
-23
lines changed

e2e/src/test/groovy/io/kubernetes/client/e2e/util/ModelMapperTest.groovy

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,15 @@ class ModelMapperTest extends Specification {
3333
expect:
3434
new GroupVersionKind("", "v1", "Pod") == ModelMapper.getGroupVersionKindByClass(V1Pod.class)
3535
new GroupVersionResource("", "v1", "pods") == ModelMapper.getGroupVersionResourceByClass(V1Pod.class)
36+
ModelMapper.isNamespaced(V1Pod.class)
3637

3738
new GroupVersionKind("apps", "v1", "Deployment") == ModelMapper.getGroupVersionKindByClass(V1Deployment.class)
3839
new GroupVersionResource("apps", "v1", "deployments") == ModelMapper.getGroupVersionResourceByClass(V1Deployment.class)
40+
ModelMapper.isNamespaced(V1Deployment.class)
3941

4042
new GroupVersionKind("apiextensions.k8s.io", "v1beta1", "CustomResourceDefinition") == ModelMapper.getGroupVersionKindByClass(V1beta1CustomResourceDefinition.class)
4143
new GroupVersionResource("apiextensions.k8s.io", "v1beta1", "customresourcedefinitions") == ModelMapper.getGroupVersionResourceByClass(V1beta1CustomResourceDefinition.class)
44+
!ModelMapper.isNamespaced(V1beta1CustomResourceDefinition.class)
4245

4346
}
4447
}

util/src/main/java/io/kubernetes/client/util/ModelMapper.java

Lines changed: 72 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,13 @@ public class ModelMapper {
5353
// Model's api-version midfix to kubernetes api-version
5454
private static List<String> preBuiltApiVersions = new ArrayList<>();
5555

56-
// TODO(yue9944882): make the map bi-directional
57-
private static Map<GroupVersionKind, Class<?>> classesByGVK = new ConcurrentHashMap<>();
56+
private static BiDirectionalMap<GroupVersionKind, Class<?>> classesByGVK =
57+
new BiDirectionalMap<>();
5858

59-
// TODO(yue9944882): make the map bi-directional
60-
private static Map<GroupVersionResource, Class<?>> classesByGVR = new ConcurrentHashMap<>();
59+
private static BiDirectionalMap<GroupVersionResource, Class<?>> classesByGVR =
60+
new BiDirectionalMap<>();
61+
62+
private static Map<Class<?>, Boolean> isNamespacedByClasses = new ConcurrentHashMap<>();
6163

6264
private static Set<Discovery.APIResource> lastAPIDiscovery = new HashSet<>();
6365

@@ -114,8 +116,31 @@ public static void addModelMap(String group, String version, String kind, Class<
114116
*/
115117
public static void addModelMap(
116118
String group, String version, String kind, String resourceNamePlural, Class<?> clazz) {
117-
classesByGVK.put(new GroupVersionKind(group, version, kind), clazz);
118-
classesByGVR.put(new GroupVersionResource(group, version, resourceNamePlural), clazz);
119+
// TODO(yue9944882): consistency between bi-directional maps
120+
classesByGVK.add(new GroupVersionKind(group, version, kind), clazz);
121+
classesByGVR.add(new GroupVersionResource(group, version, resourceNamePlural), clazz);
122+
}
123+
124+
/**
125+
* Registering concrete model classes by its group, version, kind and isNamespaced (e.g. "apps",
126+
* "v1", "Deployment", true).
127+
*
128+
* @param group the group
129+
* @param version the version
130+
* @param kind the kind
131+
* @param resourceNamePlural the resource name plural
132+
* @param isNamespacedResource the is namespaced resource
133+
* @param clazz the clazz
134+
*/
135+
public static void addModelMap(
136+
String group,
137+
String version,
138+
String kind,
139+
String resourceNamePlural,
140+
Boolean isNamespacedResource,
141+
Class<?> clazz) {
142+
addModelMap(group, version, kind, resourceNamePlural, clazz);
143+
isNamespacedByClasses.put(clazz, isNamespacedResource);
119144
}
120145

121146
/**
@@ -149,7 +174,7 @@ public static Class<?> getApiTypeClass(String apiGroupVersion, String kind) {
149174
* @return the api type class
150175
*/
151176
public static Class<?> getApiTypeClass(String group, String version, String kind) {
152-
Class<?> clazz = classesByGVK.get(new GroupVersionKind(group, version, kind));
177+
Class<?> clazz = classesByGVK.getByK(new GroupVersionKind(group, version, kind));
153178
if (clazz != null) {
154179
return clazz;
155180
}
@@ -163,11 +188,7 @@ public static Class<?> getApiTypeClass(String group, String version, String kind
163188
* @return the group version kind by class
164189
*/
165190
public static GroupVersionKind getGroupVersionKindByClass(Class<?> clazz) {
166-
return classesByGVK.entrySet().stream()
167-
.filter(e -> clazz.equals(e.getValue()))
168-
.map(e -> e.getKey())
169-
.findFirst()
170-
.orElse(preBuiltGetGroupVersionKindByClass(clazz));
191+
return classesByGVK.getByV(clazz);
171192
}
172193

173194
/**
@@ -177,13 +198,18 @@ public static GroupVersionKind getGroupVersionKindByClass(Class<?> clazz) {
177198
* @return the group version kind by class
178199
*/
179200
public static GroupVersionResource getGroupVersionResourceByClass(Class<?> clazz) {
180-
return classesByGVR.entrySet().stream()
181-
.filter(e -> clazz.equals(e.getValue()))
182-
.map(e -> e.getKey())
183-
.findFirst()
184-
.get();
201+
return classesByGVR.getByV(clazz);
185202
}
186203

204+
/**
205+
* Refreshes the model mapping by syncing up w/the api discovery info from the kubernetes
206+
* apiserver. These mapping will be cached for {@link
207+
* ModelMapper#DEFAULT_DISCOVERY_REFRESH_INTERVAL}.
208+
*
209+
* @param discovery the discovery
210+
* @return the set
211+
* @throws ApiException the api exception
212+
*/
187213
public static Set<Discovery.APIResource> refresh(Discovery discovery) throws ApiException {
188214
return refresh(discovery, DEFAULT_DISCOVERY_REFRESH_INTERVAL);
189215
}
@@ -220,6 +246,7 @@ public static Set<Discovery.APIResource> refresh(Discovery discovery, Duration r
220246
version,
221247
apiResource.getKind(),
222248
apiResource.getResourcePlural(),
249+
apiResource.getNamespaced(),
223250
clazz);
224251
}
225252
}
@@ -253,6 +280,16 @@ public static GroupVersionKind preBuiltGetGroupVersionKindByClass(Class<?> clazz
253280
.get();
254281
}
255282

283+
/**
284+
* Checks whether the class is connected with a namespaced kubernetes resource.
285+
*
286+
* @param clazz the clazz
287+
* @return the boolean
288+
*/
289+
public static Boolean isNamespaced(Class<?> clazz) {
290+
return isNamespacedByClasses.get(clazz);
291+
}
292+
256293
private static void initApiGroupMap() {
257294
preBuiltApiGroups.put("Admissionregistration", "admissionregistration.k8s.io");
258295
preBuiltApiGroups.put("Apiextensions", "apiextensions.k8s.io");
@@ -325,4 +362,22 @@ private static Pair<String, String> getApiVersion(String name) {
325362
.findFirst()
326363
.orElse(new MutablePair(null, name));
327364
}
365+
366+
static class BiDirectionalMap<K, V> {
367+
private Map<K, V> kvMap = new HashMap<>();
368+
private Map<V, K> vkMap = new HashMap<>();
369+
370+
synchronized void add(K k, V v) {
371+
kvMap.put(k, v);
372+
vkMap.put(v, k);
373+
}
374+
375+
synchronized V getByK(K k) {
376+
return kvMap.get(k);
377+
}
378+
379+
synchronized K getByV(V v) {
380+
return vkMap.get(v);
381+
}
382+
}
328383
}

util/src/test/java/io/kubernetes/client/util/ModelMapperTest.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,18 @@ public void testAddingModel() {
5454
}
5555

5656
@Test
57-
public void testGetClassByKind() {
57+
public void testPreBuiltGetClassByKind() {
5858
assertEquals(
59-
new GroupVersionKind("", "v1", "Pod"), ModelMapper.getGroupVersionKindByClass(V1Pod.class));
60-
59+
new GroupVersionKind("", "v1", "Pod"),
60+
ModelMapper.preBuiltGetGroupVersionKindByClass(V1Pod.class));
6161
assertEquals(
62-
new GroupVersionKind("", "v1", "Pod"), ModelMapper.getGroupVersionKindByClass(V1Pod.class));
62+
new GroupVersionKind("", "v1", "Pod"),
63+
ModelMapper.preBuiltGetGroupVersionKindByClass(V1Pod.class));
6364
assertEquals(
6465
new GroupVersionKind("", "v1", "Deployment"),
65-
ModelMapper.getGroupVersionKindByClass(V1Deployment.class));
66+
ModelMapper.preBuiltGetGroupVersionKindByClass(V1Deployment.class));
6667
assertEquals(
6768
new GroupVersionKind("", "v1beta1", "CustomResourceDefinition"),
68-
ModelMapper.getGroupVersionKindByClass(V1beta1CustomResourceDefinition.class));
69+
ModelMapper.preBuiltGetGroupVersionKindByClass(V1beta1CustomResourceDefinition.class));
6970
}
7071
}

0 commit comments

Comments
 (0)