diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java index 8cca524464..73927851e7 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java @@ -365,7 +365,7 @@ public void setConfigurationService(ConfigurationService configurationService) { super.setConfigurationService(configurationService); cache.addIndexers(indexerBuffer); - indexerBuffer = null; + indexerBuffer = new HashMap<>(); } public void addIndexers(Map>> indexers) { diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/DependentReInitializationIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/DependentReInitializationIT.java new file mode 100644 index 0000000000..19edc1af61 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/DependentReInitializationIT.java @@ -0,0 +1,39 @@ +package io.javaoperatorsdk.operator; + +import org.junit.jupiter.api.Test; + +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientBuilder; +import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension; +import io.javaoperatorsdk.operator.sample.dependentreinitialization.ConfigMapDependentResource; +import io.javaoperatorsdk.operator.sample.dependentreinitialization.DependentReInitializationCustomResource; +import io.javaoperatorsdk.operator.sample.dependentreinitialization.DependentReInitializationReconciler; + +class DependentReInitializationIT { + + /** + * In case dependent resource is managed by CDI (like in Quarkus) can be handy that the instance + * is reused in tests. + */ + @Test + void dependentCanDeReInitialized() { + var client = new KubernetesClientBuilder().build(); + LocallyRunOperatorExtension.applyCrd(DependentReInitializationCustomResource.class, client); + + var dependent = new ConfigMapDependentResource(); + + startEndStopOperator(client, dependent); + startEndStopOperator(client, dependent); + } + + private static void startEndStopOperator(KubernetesClient client, + ConfigMapDependentResource dependent) { + Operator o1 = new Operator(o -> o + .withCloseClientOnStop(false) + .withKubernetesClient(client)); + o1.register(new DependentReInitializationReconciler(dependent, client)); + o1.start(); + o1.stop(); + } + +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentreinitialization/ConfigMapDependentResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentreinitialization/ConfigMapDependentResource.java new file mode 100644 index 0000000000..a102060c10 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentreinitialization/ConfigMapDependentResource.java @@ -0,0 +1,29 @@ +package io.javaoperatorsdk.operator.sample.dependentreinitialization; + +import java.util.Map; + +import io.fabric8.kubernetes.api.model.ConfigMap; +import io.fabric8.kubernetes.api.model.ConfigMapBuilder; +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; + +public class ConfigMapDependentResource + extends CRUDKubernetesDependentResource { + + public ConfigMapDependentResource() { + super(ConfigMap.class); + } + + @Override + protected ConfigMap desired(DependentReInitializationCustomResource primary, + Context context) { + return new ConfigMapBuilder() + .withMetadata(new ObjectMetaBuilder() + .withName(primary.getMetadata().getName()) + .withNamespace(primary.getMetadata().getNamespace()) + .build()) + .withData(Map.of("key", "val")) + .build(); + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentreinitialization/DependentReInitializationCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentreinitialization/DependentReInitializationCustomResource.java new file mode 100644 index 0000000000..ce30463965 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentreinitialization/DependentReInitializationCustomResource.java @@ -0,0 +1,14 @@ +package io.javaoperatorsdk.operator.sample.dependentreinitialization; + +import io.fabric8.kubernetes.api.model.Namespaced; +import io.fabric8.kubernetes.client.CustomResource; +import io.fabric8.kubernetes.model.annotation.Group; +import io.fabric8.kubernetes.model.annotation.Version; + +@Group("sample.javaoperatorsdk") +@Version("v1") +public class DependentReInitializationCustomResource + extends CustomResource + implements Namespaced { + +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentreinitialization/DependentReInitializationReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentreinitialization/DependentReInitializationReconciler.java new file mode 100644 index 0000000000..e247ddb6df --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentreinitialization/DependentReInitializationReconciler.java @@ -0,0 +1,38 @@ +package io.javaoperatorsdk.operator.sample.dependentreinitialization; + +import java.util.Map; + +import io.fabric8.kubernetes.client.KubernetesClient; +import io.javaoperatorsdk.operator.api.reconciler.*; +import io.javaoperatorsdk.operator.processing.event.source.EventSource; + +@ControllerConfiguration +public class DependentReInitializationReconciler + implements Reconciler, + EventSourceInitializer { + + private final ConfigMapDependentResource configMapDependentResource; + + public DependentReInitializationReconciler(ConfigMapDependentResource dependentResource, + KubernetesClient client) { + this.configMapDependentResource = dependentResource; + this.configMapDependentResource.setKubernetesClient(client); + } + + @Override + public UpdateControl reconcile( + DependentReInitializationCustomResource resource, + Context context) throws Exception { + configMapDependentResource.reconcile(resource, context); + return UpdateControl.noUpdate(); + } + + @Override + public Map prepareEventSources( + EventSourceContext context) { + return EventSourceInitializer.nameEventSourcesFromDependentResource(context, + configMapDependentResource); + } + + +}