11package io .javaoperatorsdk .operator .processing ;
22
3+ import com .fasterxml .jackson .core .JsonProcessingException ;
4+ import com .fasterxml .jackson .databind .ObjectMapper ;
35import io .fabric8 .kubernetes .client .CustomResource ;
46import java .util .Map ;
57import java .util .Optional ;
@@ -14,6 +16,7 @@ public class CustomResourceCache {
1416
1517 private static final Logger log = LoggerFactory .getLogger (CustomResourceCache .class );
1618
19+ private ObjectMapper objectMapper = new ObjectMapper ();
1720 private final Map <String , CustomResource > resources = new ConcurrentHashMap <>();
1821 private final Lock lock = new ReentrantLock ();
1922
@@ -38,8 +41,29 @@ public void cacheResource(CustomResource resource, Predicate<CustomResource> pre
3841 }
3942 }
4043
44+ /**
45+ * We clone the object so the one in the cache is not changed by the controller or dispatcher.
46+ * Therefore the cached object always represents the object coming from the API server.
47+ *
48+ * @param uuid
49+ * @return
50+ */
4151 public Optional <CustomResource > getLatestResource (String uuid ) {
42- return Optional .ofNullable (resources .get (uuid ));
52+ return Optional .ofNullable (clone (resources .get (uuid )));
53+ }
54+
55+ private CustomResource clone (CustomResource customResource ) {
56+ try {
57+ if (customResource == null ) {
58+ return null ;
59+ }
60+ CustomResource clonedObject =
61+ objectMapper .readValue (
62+ objectMapper .writeValueAsString (customResource ), customResource .getClass ());
63+ return clonedObject ;
64+ } catch (JsonProcessingException e ) {
65+ throw new IllegalStateException (e );
66+ }
4367 }
4468
4569 public CustomResource cleanup (String customResourceUid ) {
0 commit comments