Description
Bug Report
What did you do?
I am using the JOSDK through quarkus-operator-sdk. I have a specific use case that I explained in #1437. The code is available at https://github.com/derlin/josdk-operator-dependent-crs/blob/main/src/main/java/ch/derlin/configreconciler/DbReconciler.java .
Now, I am trying to migrate to quarkus-operator-sdk 5.X, which updates JOSDK from 3.X to 4.X. The difficulty comes from the fact that I have two different event sources for the same class Secret
.
My event sources are prepared like this. The createInformer
method creates its own event source, while the dbSecret
is an instance of CRUDKubernetesDependentResource<Secret, Db>
:
@Override
public Map<String, EventSource> prepareEventSources(EventSourceContext<Db> context) {
Map<String, EventSource> eventSources = Map.of(
CONFIG_INFORMER, createInformer(context, Config.class, CONFIG_INFORMER),
CREDENTIALS_SECRET_INFORMER, createInformer(context, Secret.class, CREDENTIALS_SECRET_INFORMER, CREDENTIALS_SECRET_LABEL),
DB_SECRET_INFORMER, dbSecret.initEventSource(context)
);
dbSecret.useEventSourceWithName(DB_SECRET_INFORMER); // <- added for 4.X migration
return eventSources;
}
In my reconciliation, I have the following:
@Override
public UpdateControl<Db> reconcile(Db resource, Context<Db> context) {
// ...
// ⮕ .getSecondaryResource deprecated, how to do the same in 4.X ?
var config = context.getSecondaryResource(Config.class).orElseThrow(() ->
new ValidationException("Missing config"));
var credentialsSecret = context.getSecondaryResource(Secret.class, CREDENTIALS_SECRET_INFORMER).orElseThrow(() ->
new ValidationException("Missing credentials secret"));
dbSecret.reconcile(resource, context); // ⮕ THROWING EXCEPTION
var secret = context.getSecondaryResource(Secret.class, DB_SECRET_INFORMER).orElseThrow();
// ...
}
This was working fine with the old version but with 4.X I get the following exception when calling dbSecret.reconcile(resource, context)
:
Error during event processing ExecutionScope{ resource id: ResourceID{name='example-db', namespace='upgrade'}, version: 340777} failed.: io.javaoperatorsdk.operator.OperatorException: java.lang.IllegalArgumentException: There are multiple EventSources registered for type io.fabric8.kubernetes.api.model.Secret, you need to provide a name to specify which EventSource you want to query. Known names: dependent_db_secret,dependent_credentials_secret
at io.javaoperatorsdk.operator.monitoring.micrometer.MicrometerMetrics.lambda$timeControllerExecution$0(MicrometerMetrics.java:58)
at io.micrometer.core.instrument.composite.CompositeTimer.record(CompositeTimer.java:65)
at io.javaoperatorsdk.operator.monitoring.micrometer.MicrometerMetrics.timeControllerExecution(MicrometerMetrics.java:54)
at io.javaoperatorsdk.operator.processing.Controller.reconcile(Controller.java:93)
at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.reconcileExecution(ReconciliationDispatcher.java:130)
at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.handleReconcile(ReconciliationDispatcher.java:110)
at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.handleDispatch(ReconciliationDispatcher.java:81)
at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.handleExecution(ReconciliationDispatcher.java:54)
at io.javaoperatorsdk.operator.processing.event.EventProcessor$ReconcilerExecutor.run(EventProcessor.java:406)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.lang.IllegalArgumentException: There are multiple EventSources registered for type io.fabric8.kubernetes.api.model.Secret, you need to provide a name to specify which EventSource you want to query. Known names: dependent_db_secret,dependent_credentials_secret
at io.javaoperatorsdk.operator.processing.event.EventSources.get(EventSources.java:118)
at io.javaoperatorsdk.operator.processing.event.EventSourceManager.getResourceEventSourceFor(EventSourceManager.java:199)
at io.javaoperatorsdk.operator.api.reconciler.DefaultContext.getSecondaryResource(DefaultContext.java:47)
at io.javaoperatorsdk.operator.api.reconciler.Context.getSecondaryResource(Context.java:16)
at io.javaoperatorsdk.operator.processing.dependent.AbstractDependentResource.getSecondaryResource(AbstractDependentResource.java:92)
at io.javaoperatorsdk.operator.processing.dependent.SingleDependentResourceReconciler.reconcile(SingleDependentResourceReconciler.java:18)
at io.javaoperatorsdk.operator.processing.dependent.AbstractDependentResource.reconcile(AbstractDependentResource.java:50)
at ch.derlin.configreconciler.DbReconciler.reconcile(DbReconciler.java:77)
at ch.derlin.configreconciler.DbReconciler.reconcile(DbReconciler.java:34)
at ch.derlin.configreconciler.DbReconciler_ClientProxy.reconcile(Unknown Source)
at io.javaoperatorsdk.operator.processing.Controller$1.execute(Controller.java:136)
at io.javaoperatorsdk.operator.processing.Controller$1.execute(Controller.java:94)
at io.javaoperatorsdk.operator.monitoring.micrometer.MicrometerMetrics.lambda$timeControllerExecution$0(MicrometerMetrics.java:56)
... 11 more
I added the line dbSecret.useEventSourceWithName()
(see first code snippet) to try to avoid this error, to no avail.
SIDE NOTE: I also have no idea how to do the getSecondaryResource
with the new implementation, any hint ?
What did you expect to see?
I would expect the code to keep working, meaning I am able to reconcile my dbSecret
(and also fetch my secondary resources) as before.
What did you see instead? Under which circumstances?
I see the exception (see above):
java.lang.IllegalArgumentException: There are multiple EventSources registered for type io.fabric8.kubernetes.api.model.Secret, you need to provide a name to specify which EventSource you want to query. Known names: custom_secret,dependent_secret
Environment
I am using K3D for testing (vanilla kubernetes).
$ Mention java-operator-sdk version from pom.xml file
<dependency>
<groupId>io.quarkiverse.operatorsdk</groupId>
<artifactId>quarkus-operator-sdk</artifactId>
<version>5.0.0.Beta2</version>
</dependency>
<dependency>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework-core</artifactId>
<version>4.1.1</version>
</dependency>
$ java -version
java -version
openjdk version "11.0.16.1" 2022-08-12
OpenJDK Runtime Environment Homebrew (build 11.0.16.1+0)
OpenJDK 64-Bit Server VM Homebrew (build 11.0.16.1+0, mixed mode)
$ kubectl version
kubectl version --short
Flag --short has been deprecated, and will be removed in the future. The --short output will become the default.
Client Version: v1.25.4
Kustomize Version: v4.5.7
Server Version: v1.24.4+k3s1
Possible Solution
I think the problem comes from https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/SingleDependentResourceReconciler.java#L18 where the .getSecondaryResource()
doesn't use any discriminator / doesn't look for the event source name.
Additional context
I already shared my use case in this issue #1437. A minimal reproducible example is available at https://github.com/derlin/josdk-operator-dependent-crs/tree/quarkus-operator-5.X :
- branch
main
⮕ working version with 3.X - branch
quarkus-operator-5.X
⮕ failing version with 4.X