Description
Bug Report
What did you do?
We have a primary resource, let's call it MyCustomResource
. The reconciler for this resource creates and maintains a ConfigMap
based on the MyCustomResource
. The ConfigMap
is created in a different namespace than MyCustomResource
, thus we cannot use the ownerReference
mechanism to ensure that the resource is deleted when the primary resource is deleted. To do so, we use JOSDK annotations (primary-name
and primary-namespace
).
The issue is that sometimes when the primary resource is deleted very quickly - right after it was created, the secondary resource is not created:
2024-03-04 10:12:17,918 ERROR [io.jav.ope.pro.eve.EventProcessor] (ReconcilerExecutor-mycustomresourcereconciler-117) Error during event processing ExecutionScope{ resource id: ResourceID{name='test', namespace='default'}, version: 7364248}: java.lang.NullPointerException: Cannot invoke "io.fabric8.kubernetes.api.model.HasMetadata.addFinalizer(String)" because "r" is null
at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.lambda$updateCustomResourceWithFinalizer$2(ReconciliationDispatcher.java:331)
at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.conflictRetryingUpdate(ReconciliationDispatcher.java:353)
at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.updateCustomResourceWithFinalizer(ReconciliationDispatcher.java:330)
at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.handleReconcile(ReconciliationDispatcher.java:116)
at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.handleDispatch(ReconciliationDispatcher.java:90)
at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.handleExecution(ReconciliationDispatcher.java:64)
at io.javaoperatorsdk.operator.processing.event.EventProcessor$ReconcilerExecutor.run(EventProcessor.java:450)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
So it seems that the secondary resource is created, even though the primary resource has no finalizer added.
This issue was reproduced with a sample repo. There is a repeated test that fails after several test loops - it is non deterministic.
What did you expect to see?
There are no Orphan secondary resources left, when the Primary is deleted.
What did you see instead? Under which circumstances?
There is an Orphan secondary resource left, that will be never deleted.
Environment
Kubernetes cluster type:
rancher desktop, version: 1.25
$ Mention java-operator-sdk version from pom.xml file
4.8.0
$ java -version
Java Temurin 17.0.6
$ kubectl version
kubectl version doesn't seem to be related, under the hood JOSDK is using fabric8 kubernetes client with version 6.10.0
Possible Solution
Make sure that the finalizer is applied first before creating secondary resources