diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java
index 1421109eee..e9790b63e0 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java
@@ -358,10 +358,13 @@ private void validateCRDWithLocalModelIfRequired(Class
resClass, String contr
}
public void changeNamespaces(Set namespaces) {
- if (namespaces.contains(Constants.WATCH_ALL_NAMESPACES)
- || namespaces.contains(WATCH_CURRENT_NAMESPACE)) {
+ if (namespaces.contains(WATCH_CURRENT_NAMESPACE)) {
throw new OperatorException("Unexpected value in target namespaces: " + namespaces);
}
+ if (namespaces.contains(Constants.WATCH_ALL_NAMESPACES) && namespaces.size() > 1) {
+ throw new OperatorException(
+ "Watching all namespaces, but additional specific namespace is present");
+ }
eventProcessor.stop();
eventSourceManager.changeNamespaces(namespaces);
eventProcessor.start();
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerManager.java
index 4d7d547356..d51301c385 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerManager.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerManager.java
@@ -58,17 +58,12 @@ void initSources(MixedOperation, Resource> clien
final var labelSelector = configuration.getLabelSelector();
if (ResourceConfiguration.allNamespacesWatched(targetNamespaces)) {
- final var filteredBySelectorClient =
- client.inAnyNamespace().withLabelSelector(labelSelector);
- final var source =
- createEventSource(filteredBySelectorClient, eventHandler, WATCH_ALL_NAMESPACES);
+ var source = createEventSourceForNamespace(WATCH_ALL_NAMESPACES);
log.debug("Registered {} -> {} for any namespace", this, source);
} else {
targetNamespaces.forEach(
ns -> {
- final var source =
- createEventSource(client.inNamespace(ns).withLabelSelector(labelSelector),
- eventHandler, ns);
+ final var source = createEventSourceForNamespace(ns);
log.debug("Registered {} -> {} for namespace: {}", this, source,
ns);
});
@@ -87,10 +82,7 @@ public void changeNamespaces(Set namespaces) {
namespaces.forEach(ns -> {
if (!sources.containsKey(ns)) {
- final var source =
- createEventSource(
- client.inNamespace(ns).withLabelSelector(configuration.getLabelSelector()),
- eventHandler, ns);
+ final InformerWrapper source = createEventSourceForNamespace(ns);
source.addIndexers(this.indexers);
source.start();
log.debug("Registered new {} -> {} for namespace: {}", this, source,
@@ -100,6 +92,19 @@ public void changeNamespaces(Set namespaces) {
}
+ private InformerWrapper createEventSourceForNamespace(String namespace) {
+ final InformerWrapper source;
+ if (namespace.equals(WATCH_ALL_NAMESPACES)) {
+ final var filteredBySelectorClient =
+ client.inAnyNamespace().withLabelSelector(configuration.getLabelSelector());
+ source = createEventSource(filteredBySelectorClient, eventHandler, WATCH_ALL_NAMESPACES);
+ } else {
+ source = createEventSource(
+ client.inNamespace(namespace).withLabelSelector(configuration.getLabelSelector()),
+ eventHandler, namespace);
+ }
+ return source;
+ }
private InformerWrapper createEventSource(
FilterWatchListDeletable, Resource> filteredBySelectorClient,
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/ChangeNamespaceIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/ChangeNamespaceIT.java
index 56eda890a1..c7d3b04c4a 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/ChangeNamespaceIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/ChangeNamespaceIT.java
@@ -4,6 +4,8 @@
import java.util.Map;
import java.util.Set;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -12,6 +14,7 @@
import io.fabric8.kubernetes.api.model.NamespaceBuilder;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.client.KubernetesClient;
+import io.javaoperatorsdk.operator.api.reconciler.Constants;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import io.javaoperatorsdk.operator.sample.changenamespace.ChangeNamespaceTestCustomResource;
import io.javaoperatorsdk.operator.sample.changenamespace.ChangeNamespaceTestReconciler;
@@ -25,63 +28,98 @@ class ChangeNamespaceIT {
public static final String TEST_RESOURCE_NAME_2 = "test2";
public static final String TEST_RESOURCE_NAME_3 = "test3";
public static final String ADDITIONAL_TEST_NAMESPACE = "additional-test-namespace";
+
@RegisterExtension
LocallyRunOperatorExtension operator =
LocallyRunOperatorExtension.builder().withReconciler(new ChangeNamespaceTestReconciler())
.build();
+ @BeforeEach
+ void setup() {
+ client().namespaces().resource(additionalTestNamespace()).create();
+ }
+
+ @AfterEach
+ void cleanup() {
+ client().namespaces().resource(additionalTestNamespace()).delete();
+ }
+
@SuppressWarnings("rawtypes")
@Test
void addNewAndRemoveOldNamespaceTest() {
- try {
- var reconciler = operator.getReconcilerOfType(ChangeNamespaceTestReconciler.class);
- var defaultNamespaceResource = operator.create(customResource(TEST_RESOURCE_NAME_1));
+ var reconciler = operator.getReconcilerOfType(ChangeNamespaceTestReconciler.class);
+ var defaultNamespaceResource = operator.create(customResource(TEST_RESOURCE_NAME_1));
+
+ assertReconciled(reconciler, defaultNamespaceResource);
+ var resourceInAdditionalTestNamespace = createResourceInAdditionalNamespace();
+
+ assertNotReconciled(reconciler, resourceInAdditionalTestNamespace);
+ // adding additional namespace
+ RegisteredController registeredController =
+ operator.getRegisteredControllerForReconcile(ChangeNamespaceTestReconciler.class);
+ registeredController
+ .changeNamespaces(Set.of(operator.getNamespace(), ADDITIONAL_TEST_NAMESPACE));
+
+ assertReconciled(reconciler, resourceInAdditionalTestNamespace);
- await().pollDelay(Duration.ofMillis(100)).untilAsserted(() -> assertThat(
- reconciler.numberOfResourceReconciliations(defaultNamespaceResource)).isEqualTo(2));
+ // removing a namespace
+ registeredController.changeNamespaces(Set.of(ADDITIONAL_TEST_NAMESPACE));
- client().namespaces().create(additionalTestNamespace());
- var resourceInAdditionalTestNamespace = createResourceInTestNamespace();
- await().pollDelay(Duration.ofMillis(200)).untilAsserted(
- () -> assertThat(
- reconciler.numberOfResourceReconciliations(resourceInAdditionalTestNamespace))
- .isZero());
+ var newResourceInDefaultNamespace = operator.create(customResource(TEST_RESOURCE_NAME_3));
+ assertNotReconciled(reconciler, newResourceInDefaultNamespace);
- // adding additional namespace
- RegisteredController registeredController =
- operator.getRegisteredControllerForReconcile(ChangeNamespaceTestReconciler.class);
- registeredController
- .changeNamespaces(Set.of(operator.getNamespace(), ADDITIONAL_TEST_NAMESPACE));
+ ConfigMap firstMap = operator.get(ConfigMap.class, TEST_RESOURCE_NAME_1);
+ firstMap.setData(Map.of("data", "newdata"));
+ operator.replace(firstMap);
+ assertReconciled(reconciler, defaultNamespaceResource);
+ }
+
+ @Test
+ void changeToWatchAllNamespaces() {
+ var reconciler = operator.getReconcilerOfType(ChangeNamespaceTestReconciler.class);
+ var resourceInAdditionalTestNamespace = createResourceInAdditionalNamespace();
+
+ assertNotReconciled(reconciler, resourceInAdditionalTestNamespace);
- await().untilAsserted(
- () -> assertThat(
- reconciler.numberOfResourceReconciliations(resourceInAdditionalTestNamespace))
- .isEqualTo(2));
+ var registeredController =
+ operator.getRegisteredControllerForReconcile(ChangeNamespaceTestReconciler.class);
- // removing a namespace
- registeredController.changeNamespaces(Set.of(ADDITIONAL_TEST_NAMESPACE));
+ registeredController
+ .changeNamespaces(Set.of(Constants.WATCH_ALL_NAMESPACES));
- var newResourceInDefaultNamespace = operator.create(customResource(TEST_RESOURCE_NAME_3));
- await().pollDelay(Duration.ofMillis(200))
- .untilAsserted(() -> assertThat(
- reconciler.numberOfResourceReconciliations(newResourceInDefaultNamespace)).isZero());
+ assertReconciled(reconciler, resourceInAdditionalTestNamespace);
+ registeredController.changeNamespaces(Set.of(operator.getNamespace()));
- ConfigMap firstMap = operator.get(ConfigMap.class, TEST_RESOURCE_NAME_1);
- firstMap.setData(Map.of("data", "newdata"));
- operator.replace(firstMap);
+ var defaultNamespaceResource = operator.create(customResource(TEST_RESOURCE_NAME_1));
+ var resource2InAdditionalResource = createResourceInAdditionalNamespace(TEST_RESOURCE_NAME_3);
+ assertReconciled(reconciler, defaultNamespaceResource);
+ assertNotReconciled(reconciler, resource2InAdditionalResource);
+ }
+
+ private static void assertReconciled(ChangeNamespaceTestReconciler reconciler,
+ ChangeNamespaceTestCustomResource resourceInAdditionalTestNamespace) {
+ await().untilAsserted(
+ () -> assertThat(
+ reconciler.numberOfResourceReconciliations(resourceInAdditionalTestNamespace))
+ .isEqualTo(2));
+ }
- await().untilAsserted(() -> assertThat(
- reconciler.numberOfResourceReconciliations(defaultNamespaceResource)).isEqualTo(2));
+ private static void assertNotReconciled(ChangeNamespaceTestReconciler reconciler,
+ ChangeNamespaceTestCustomResource resourceInAdditionalTestNamespace) {
+ await().pollDelay(Duration.ofMillis(200)).untilAsserted(
+ () -> assertThat(
+ reconciler.numberOfResourceReconciliations(resourceInAdditionalTestNamespace))
+ .isZero());
+ }
- } finally {
- client().namespaces().delete(additionalTestNamespace());
- }
+ private ChangeNamespaceTestCustomResource createResourceInAdditionalNamespace() {
+ return createResourceInAdditionalNamespace(TEST_RESOURCE_NAME_2);
}
- private ChangeNamespaceTestCustomResource createResourceInTestNamespace() {
- var res = customResource(TEST_RESOURCE_NAME_2);
+ private ChangeNamespaceTestCustomResource createResourceInAdditionalNamespace(String name) {
+ var res = customResource(name);
return client().resources(ChangeNamespaceTestCustomResource.class)
.inNamespace(ADDITIONAL_TEST_NAMESPACE)
.create(res);