@@ -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}
0 commit comments