From dd2deb6214616383c82c13be20d5f8ad43c02ea9 Mon Sep 17 00:00:00 2001 From: csviri Date: Wed, 30 Nov 2022 16:25:16 +0100 Subject: [PATCH 1/4] feat: change namespace to "watch all namespace" --- .../operator/processing/Controller.java | 7 +++-- .../source/informer/InformerManager.java | 27 +++++++++++-------- .../operator/ChangeNamespaceIT.java | 1 + 3 files changed, 22 insertions(+), 13 deletions(-) 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..05f79b04a3 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/ChangeNamespaceIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/ChangeNamespaceIT.java @@ -25,6 +25,7 @@ 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()) From 6cef377edfcc68aa91e2575e5e4f759c653ebb43 Mon Sep 17 00:00:00 2001 From: csviri Date: Wed, 30 Nov 2022 16:31:45 +0100 Subject: [PATCH 2/4] empty tests --- .../javaoperatorsdk/operator/ChangeNamespaceIT.java | 11 +++++++++++ 1 file changed, 11 insertions(+) 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 05f79b04a3..a4366a04ed 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/ChangeNamespaceIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/ChangeNamespaceIT.java @@ -81,6 +81,17 @@ void addNewAndRemoveOldNamespaceTest() { } } + // todo + @Test + void changeToWatchAllNamespaces() { + + } + + @Test + void changeFromWatchAllNamespaces() { + + } + private ChangeNamespaceTestCustomResource createResourceInTestNamespace() { var res = customResource(TEST_RESOURCE_NAME_2); return client().resources(ChangeNamespaceTestCustomResource.class) From 5e7575b4cc76913de770c4b27de62a161352dce3 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 1 Dec 2022 10:36:49 +0100 Subject: [PATCH 3/4] IT --- .../operator/ChangeNamespaceIT.java | 109 +++++++++++------- 1 file changed, 67 insertions(+), 42 deletions(-) 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 a4366a04ed..0ce80b67f8 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; @@ -31,69 +34,91 @@ class ChangeNamespaceIT { 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)); - await().pollDelay(Duration.ofMillis(100)).untilAsserted(() -> assertThat( - reconciler.numberOfResourceReconciliations(defaultNamespaceResource)).isEqualTo(2)); + assertReconciled(reconciler,defaultNamespaceResource); + var resourceInAdditionalTestNamespace = createResourceInAdditionalNamespace(); - client().namespaces().create(additionalTestNamespace()); - var resourceInAdditionalTestNamespace = createResourceInTestNamespace(); + assertNotReconciled(reconciler,resourceInAdditionalTestNamespace); + // adding additional namespace + RegisteredController registeredController = + operator.getRegisteredControllerForReconcile(ChangeNamespaceTestReconciler.class); + registeredController + .changeNamespaces(Set.of(operator.getNamespace(), ADDITIONAL_TEST_NAMESPACE)); - await().pollDelay(Duration.ofMillis(200)).untilAsserted( - () -> assertThat( - reconciler.numberOfResourceReconciliations(resourceInAdditionalTestNamespace)) - .isZero()); + assertReconciled(reconciler,resourceInAdditionalTestNamespace); - // adding additional namespace - RegisteredController registeredController = - operator.getRegisteredControllerForReconcile(ChangeNamespaceTestReconciler.class); - registeredController - .changeNamespaces(Set.of(operator.getNamespace(), ADDITIONAL_TEST_NAMESPACE)); + // removing a namespace + registeredController.changeNamespaces(Set.of(ADDITIONAL_TEST_NAMESPACE)); - await().untilAsserted( - () -> assertThat( - reconciler.numberOfResourceReconciliations(resourceInAdditionalTestNamespace)) - .isEqualTo(2)); - // removing a namespace - registeredController.changeNamespaces(Set.of(ADDITIONAL_TEST_NAMESPACE)); + var newResourceInDefaultNamespace = operator.create(customResource(TEST_RESOURCE_NAME_3)); + assertNotReconciled(reconciler,newResourceInDefaultNamespace); - var newResourceInDefaultNamespace = operator.create(customResource(TEST_RESOURCE_NAME_3)); - await().pollDelay(Duration.ofMillis(200)) - .untilAsserted(() -> assertThat( - reconciler.numberOfResourceReconciliations(newResourceInDefaultNamespace)).isZero()); + 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(); - ConfigMap firstMap = operator.get(ConfigMap.class, TEST_RESOURCE_NAME_1); - firstMap.setData(Map.of("data", "newdata")); - operator.replace(firstMap); + assertNotReconciled(reconciler, resourceInAdditionalTestNamespace); - await().untilAsserted(() -> assertThat( - reconciler.numberOfResourceReconciliations(defaultNamespaceResource)).isEqualTo(2)); + var registeredController = + operator.getRegisteredControllerForReconcile(ChangeNamespaceTestReconciler.class); - } finally { - client().namespaces().delete(additionalTestNamespace()); - } - } + registeredController + .changeNamespaces(Set.of(Constants.WATCH_ALL_NAMESPACES)); - // todo - @Test - void changeToWatchAllNamespaces() { + assertReconciled(reconciler,resourceInAdditionalTestNamespace); + + registeredController.changeNamespaces(Set.of(operator.getNamespace())); + + var defaultNamespaceResource = operator.create(customResource(TEST_RESOURCE_NAME_1)); + var resource2InAdditionalResource = createResourceInAdditionalNamespace(TEST_RESOURCE_NAME_3); + assertReconciled(reconciler,defaultNamespaceResource); + assertNotReconciled(reconciler, resource2InAdditionalResource); } - @Test - void changeFromWatchAllNamespaces() { + private static void assertReconciled(ChangeNamespaceTestReconciler reconciler, ChangeNamespaceTestCustomResource resourceInAdditionalTestNamespace) { + await().untilAsserted( + () -> assertThat( + reconciler.numberOfResourceReconciliations(resourceInAdditionalTestNamespace)) + .isEqualTo(2)); + } + + private static void assertNotReconciled(ChangeNamespaceTestReconciler reconciler, ChangeNamespaceTestCustomResource resourceInAdditionalTestNamespace) { + await().pollDelay(Duration.ofMillis(200)).untilAsserted( + () -> assertThat( + reconciler.numberOfResourceReconciliations(resourceInAdditionalTestNamespace)) + .isZero()); + } + 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); From 611c1d6ec694534332d3173e60ef7ae5e83455c5 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 1 Dec 2022 10:52:08 +0100 Subject: [PATCH 4/4] format --- .../operator/ChangeNamespaceIT.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) 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 0ce80b67f8..c7d3b04c4a 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/ChangeNamespaceIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/ChangeNamespaceIT.java @@ -50,29 +50,29 @@ void addNewAndRemoveOldNamespaceTest() { var reconciler = operator.getReconcilerOfType(ChangeNamespaceTestReconciler.class); var defaultNamespaceResource = operator.create(customResource(TEST_RESOURCE_NAME_1)); - assertReconciled(reconciler,defaultNamespaceResource); + assertReconciled(reconciler, defaultNamespaceResource); var resourceInAdditionalTestNamespace = createResourceInAdditionalNamespace(); - assertNotReconciled(reconciler,resourceInAdditionalTestNamespace); + assertNotReconciled(reconciler, resourceInAdditionalTestNamespace); // adding additional namespace RegisteredController registeredController = operator.getRegisteredControllerForReconcile(ChangeNamespaceTestReconciler.class); registeredController .changeNamespaces(Set.of(operator.getNamespace(), ADDITIONAL_TEST_NAMESPACE)); - assertReconciled(reconciler,resourceInAdditionalTestNamespace); + assertReconciled(reconciler, resourceInAdditionalTestNamespace); // removing a namespace registeredController.changeNamespaces(Set.of(ADDITIONAL_TEST_NAMESPACE)); var newResourceInDefaultNamespace = operator.create(customResource(TEST_RESOURCE_NAME_3)); - assertNotReconciled(reconciler,newResourceInDefaultNamespace); + assertNotReconciled(reconciler, newResourceInDefaultNamespace); ConfigMap firstMap = operator.get(ConfigMap.class, TEST_RESOURCE_NAME_1); firstMap.setData(Map.of("data", "newdata")); operator.replace(firstMap); - assertReconciled(reconciler,defaultNamespaceResource); + assertReconciled(reconciler, defaultNamespaceResource); } @Test @@ -88,25 +88,26 @@ void changeToWatchAllNamespaces() { registeredController .changeNamespaces(Set.of(Constants.WATCH_ALL_NAMESPACES)); - assertReconciled(reconciler,resourceInAdditionalTestNamespace); + assertReconciled(reconciler, resourceInAdditionalTestNamespace); registeredController.changeNamespaces(Set.of(operator.getNamespace())); var defaultNamespaceResource = operator.create(customResource(TEST_RESOURCE_NAME_1)); var resource2InAdditionalResource = createResourceInAdditionalNamespace(TEST_RESOURCE_NAME_3); - assertReconciled(reconciler,defaultNamespaceResource); + assertReconciled(reconciler, defaultNamespaceResource); assertNotReconciled(reconciler, resource2InAdditionalResource); - } - private static void assertReconciled(ChangeNamespaceTestReconciler reconciler, ChangeNamespaceTestCustomResource resourceInAdditionalTestNamespace) { + private static void assertReconciled(ChangeNamespaceTestReconciler reconciler, + ChangeNamespaceTestCustomResource resourceInAdditionalTestNamespace) { await().untilAsserted( - () -> assertThat( - reconciler.numberOfResourceReconciliations(resourceInAdditionalTestNamespace)) - .isEqualTo(2)); + () -> assertThat( + reconciler.numberOfResourceReconciliations(resourceInAdditionalTestNamespace)) + .isEqualTo(2)); } - private static void assertNotReconciled(ChangeNamespaceTestReconciler reconciler, ChangeNamespaceTestCustomResource resourceInAdditionalTestNamespace) { + private static void assertNotReconciled(ChangeNamespaceTestReconciler reconciler, + ChangeNamespaceTestCustomResource resourceInAdditionalTestNamespace) { await().pollDelay(Duration.ofMillis(200)).untilAsserted( () -> assertThat( reconciler.numberOfResourceReconciliations(resourceInAdditionalTestNamespace))