From c85a39cfc9e7fdedba8b56dafe3d5431155633b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Tue, 6 Feb 2024 10:43:25 +0100 Subject: [PATCH 01/12] feat: JDK client is now the default (#2235) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index eea74bbd49..9c0cee75fc 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,7 @@ ${java.version} java-operator-sdk https://sonarcloud.io - jdk + jdk 5.10.1 6.13.3 From e2b01b71eedbb9c33edf90816e67740bb8777b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Thu, 21 Mar 2024 09:38:00 +0100 Subject: [PATCH 02/12] improve: replace current formatting plugins with spotless plugin (#2302) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- pom.xml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index 9c0cee75fc..2cd1f4e242 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,7 @@ ${java.version} java-operator-sdk https://sonarcloud.io - jdk + jdk 5.10.1 6.13.3 @@ -77,21 +77,21 @@ 0.9.11 2.16.1 - 2.11 - 3.12.1 - 3.3.1 - 3.8.0 - 3.3.1 - 3.3.1 - 3.4.2 - 3.4.0 + 2.11 + 3.12.1 + 3.3.1 + 3.8.0 + 3.3.1 + 3.3.1 + 3.4.2 + 3.4.0 3.2.5 - 1.7.0 - 3.0.0 - 3.1.2 + 1.7.0 + 3.0.0 + 3.1.2 9.0.1 - 3.4.1 - 2.43.0 + 3.4.1 + 2.43.0 From 0df613c1c0e0f73d536c59f5043c694d37ec536c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Mon, 8 Apr 2024 18:47:48 +0200 Subject: [PATCH 03/12] fix: error with java docs validation (#2336) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- .../operator/api/config/ConfigurationService.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java index 0bd1607213..ab689c23a3 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java @@ -366,6 +366,8 @@ default ExecutorServiceManager getExecutorServiceManager() { * * @return if SSA should be used for dependent resources * @since 4.4.0 + * + * @return if SSA should be used for dependent resources */ default boolean ssaBasedCreateUpdateMatchForDependentResources() { return true; @@ -395,6 +397,8 @@ default Set> defaultNonSSAResource() { * * @return if special annotation should be used for dependent resource to filter events * @since 4.5.0 + * + * @return if special annotation should be used for dependent resource to filter events */ default boolean previousAnnotationForDependentResourcesEventFiltering() { return true; @@ -411,6 +415,8 @@ default boolean previousAnnotationForDependentResourcesEventFiltering() { * * @return if resource version should be parsed (as integer) * @since 4.5.0 + * + * @return if resource version should be parsed (as integer) */ default boolean parseResourceVersionsForEventFilteringAndCaching() { return false; From c32aa4eb3a27080c6e84bae685999fa5abe36d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Wed, 10 Apr 2024 16:03:03 +0200 Subject: [PATCH 04/12] fix: format after rebase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- pom.xml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index 2cd1f4e242..11a563903c 100644 --- a/pom.xml +++ b/pom.xml @@ -68,7 +68,7 @@ 3.16.0 0.21.0 1.13.0 - 3.26.3 + 3.26.3 4.2.0 2.7.3 1.13.3 @@ -77,21 +77,21 @@ 0.9.11 2.16.1 - 2.11 - 3.12.1 + 2.11 + 3.12.1 3.3.1 - 3.8.0 - 3.3.1 - 3.3.1 - 3.4.2 - 3.4.0 + 3.8.0 + 3.3.1 + 3.3.1 + 3.4.2 + 3.4.0 3.2.5 - 1.7.0 - 3.0.0 - 3.1.2 + 1.7.0 + 3.0.0 + 3.1.2 9.0.1 - 3.4.1 - 2.43.0 + 3.4.1 + 2.43.0 From 573ef797a045e0b57a08fbe1d7edf2239299879d Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Mon, 8 Jul 2024 17:50:05 +0200 Subject: [PATCH 05/12] feat: allow returning additional information from conditions (#2426) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #2424. --------- Signed-off-by: Attila Mészáros Signed-off-by: Chris Laprun Co-authored-by: Attila Mészáros Signed-off-by: Chris Laprun --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 11a563903c..eea74bbd49 100644 --- a/pom.xml +++ b/pom.xml @@ -68,7 +68,7 @@ 3.16.0 0.21.0 1.13.0 - 3.26.3 + 3.26.3 4.2.0 2.7.3 1.13.3 @@ -79,12 +79,12 @@ 2.11 3.12.1 - 3.3.1 + 3.3.1 3.8.0 3.3.1 3.3.1 - 3.4.2 - 3.4.0 + 3.4.2 + 3.4.0 3.2.5 1.7.0 3.0.0 From fe1caa54be53b783450e394b7f03f8b96bf6ede6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Thu, 8 Aug 2024 21:18:57 +0200 Subject: [PATCH 06/12] refactor: move integration tests to feature packages and sub packages based on type (#2483) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: integration tests moved to feature packages and sub packages pased on type Signed-off-by: Attila Mészáros * fix resource paths Signed-off-by: Attila Mészáros * fixes Signed-off-by: Attila Mészáros * link and test fixes Signed-off-by: Attila Mészáros * format Signed-off-by: Attila Mészáros * wip Signed-off-by: Attila Mészáros * old service Signed-off-by: Attila Mészáros * test fix Signed-off-by: Attila Mészáros * refactor: remove unneeded classes Signed-off-by: Chris Laprun * fix: typo in package name Signed-off-by: Chris Laprun --------- Signed-off-by: Attila Mészáros Signed-off-by: Chris Laprun Co-authored-by: Chris Laprun --- .../informerrelatedbehavior/InformerRelatedBehaviorITS.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/informerrelatedbehavior/InformerRelatedBehaviorITS.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/informerrelatedbehavior/InformerRelatedBehaviorITS.java index 21079c0504..6b8ed9517d 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/informerrelatedbehavior/InformerRelatedBehaviorITS.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/informerrelatedbehavior/InformerRelatedBehaviorITS.java @@ -20,6 +20,9 @@ import io.javaoperatorsdk.operator.Operator; import io.javaoperatorsdk.operator.OperatorException; import io.javaoperatorsdk.operator.ReconcilerUtils; +import io.javaoperatorsdk.operator.Operator; +import io.javaoperatorsdk.operator.OperatorException; +import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.health.InformerHealthIndicator; import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension; import io.javaoperatorsdk.operator.processing.event.source.controller.ControllerEventSource; From 205bb5af000fc7a4b845e00cc367cad9dabf490f Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Fri, 9 Aug 2024 16:01:02 +0200 Subject: [PATCH 07/12] refactor: move functionality out of ResourceConfiguration Signed-off-by: Chris Laprun --- .../io/javaoperatorsdk/operator/Operator.java | 5 +- .../api/config/ControllerConfiguration.java | 2 +- .../ControllerConfigurationOverrider.java | 11 +- .../api/config/ResourceConfiguration.java | 140 ------------------ .../api/config/informer/Informer.java | 2 +- .../informer/InformerConfiguration.java | 132 ++++++++++++++++- .../InformerEventSourceConfiguration.java | 33 ----- .../operator/api/reconciler/Constants.java | 1 + .../controller/ControllerEventSource.java | 7 +- .../source/informer/InformerEventSource.java | 9 +- .../source/informer/InformerManager.java | 22 ++- .../ControllerConfigurationOverriderTest.java | 71 +++++---- .../config/MockControllerConfiguration.java | 7 +- .../api/config/ResourceConfigurationTest.java | 44 +++--- .../informer/InformerEventSourceTest.java | 18 ++- ...ultipleSecondaryEventSourceReconciler.java | 5 +- .../config/BaseConfigurationServiceTest.java | 16 +- 17 files changed, 247 insertions(+), 278 deletions(-) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/Operator.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/Operator.java index 1283896a42..9680bc7e8d 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/Operator.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/Operator.java @@ -213,8 +213,9 @@ public

RegisteredController

register(Reconciler

re controllerManager.add(controller); - final var watchedNS = configuration.watchAllNamespaces() ? "[all namespaces]" - : configuration.getEffectiveNamespaces(); + final var informerConfig = configuration.getInformerConfig(); + final var watchedNS = informerConfig.watchAllNamespaces() ? "[all namespaces]" + : informerConfig.getEffectiveNamespaces(configuration); log.info( "Registered reconciler: '{}' for resource: '{}' for namespace(s): {}", diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java index aa74d7ea1a..7547ee3e64 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java @@ -86,7 +86,7 @@ default Class

getResourceClass() { @SuppressWarnings("unused") default Set getEffectiveNamespaces() { - return ResourceConfiguration.super.getEffectiveNamespaces(this); + return getInformerConfig().getEffectiveNamespaces(this); } /** diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverrider.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverrider.java index 423867107a..6740e86022 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverrider.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverrider.java @@ -35,15 +35,8 @@ public class ControllerConfigurationOverrider { private ControllerConfigurationOverrider(ControllerConfiguration original) { this.finalizer = original.getFinalizerName(); this.generationAware = original.isGenerationAware(); - this.config = InformerConfiguration.builder(original.getResourceClass()) - .withName(name) - .withNamespaces(original.getNamespaces()) - .withLabelSelector(original.getLabelSelector()) - .withOnAddFilter(original.onAddFilter().orElse(null)) - .withOnUpdateFilter(original.onUpdateFilter().orElse(null)) - .withGenericFilter(original.genericFilter().orElse(null)) - .withInformerListLimit(original.getInformerListLimit().orElse(null)) - .withItemStore(original.getItemStore().orElse(null)); + final var informerConfig = original.getInformerConfig(); + this.config = InformerConfiguration.builder(informerConfig); this.retry = original.getRetry(); this.reconciliationMaxInterval = original.maxReconciliationInterval().orElse(null); this.original = original; diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResourceConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResourceConfiguration.java index cac44c93db..f6039ce81e 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResourceConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResourceConfiguration.java @@ -1,24 +1,9 @@ package io.javaoperatorsdk.operator.api.config; -import java.util.Collection; -import java.util.Collections; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.client.informers.cache.ItemStore; -import io.javaoperatorsdk.operator.OperatorException; import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; -import io.javaoperatorsdk.operator.api.reconciler.Constants; -import io.javaoperatorsdk.operator.processing.event.source.cache.BoundedItemStore; -import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnUpdateFilter; - -import static io.javaoperatorsdk.operator.api.reconciler.Constants.DEFAULT_NAMESPACES_SET; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.WATCH_CURRENT_NAMESPACE_SET; public interface ResourceConfiguration { @@ -28,134 +13,9 @@ default String getResourceTypeName() { InformerConfiguration getInformerConfig(); - default Optional> onAddFilter() { - return Optional.ofNullable(getInformerConfig().getOnAddFilter()); - } - - default Optional> onUpdateFilter() { - return Optional.ofNullable(getInformerConfig().getOnUpdateFilter()); - } - - default Optional> genericFilter() { - return Optional.ofNullable(getInformerConfig().getGenericFilter()); - } - - /** - * Retrieves the label selector that is used to filter which resources are actually watched by the - * associated event source. See the official documentation on the - * topic - * for more details on syntax. - * - * @return the label selector filtering watched resources - */ - default String getLabelSelector() { - return getInformerConfig().getLabelSelector(); - } - - static String ensureValidLabelSelector(String labelSelector) { - // might want to implement validation here? - return labelSelector; - } - @SuppressWarnings("unchecked") default Class getResourceClass() { return (Class) Utils.getFirstTypeArgumentFromSuperClassOrInterface(getClass(), ResourceConfiguration.class); } - - default Set getNamespaces() { - return getInformerConfig().getNamespaces(); - } - - default boolean watchAllNamespaces() { - return allNamespacesWatched(getNamespaces()); - } - - static boolean allNamespacesWatched(Set namespaces) { - failIfNotValid(namespaces); - return DEFAULT_NAMESPACES_SET.equals(namespaces); - } - - default boolean watchCurrentNamespace() { - return currentNamespaceWatched(getNamespaces()); - } - - static boolean currentNamespaceWatched(Set namespaces) { - failIfNotValid(namespaces); - return WATCH_CURRENT_NAMESPACE_SET.equals(namespaces); - } - - static void failIfNotValid(Set namespaces) { - if (namespaces != null && !namespaces.isEmpty()) { - final var present = namespaces.contains(Constants.WATCH_CURRENT_NAMESPACE) - || namespaces.contains(Constants.WATCH_ALL_NAMESPACES); - if (!present || namespaces.size() == 1) { - return; - } - } - throw new IllegalArgumentException( - "Must specify namespaces. To watch all namespaces, use only '" - + Constants.WATCH_ALL_NAMESPACES - + "'. To watch only the namespace in which the operator is deployed, use only '" - + Constants.WATCH_CURRENT_NAMESPACE + "'"); - } - - static Set ensureValidNamespaces(Collection namespaces) { - if (namespaces != null && !namespaces.isEmpty()) { - return namespaces.stream().map(String::trim).collect(Collectors.toSet()); - } else { - return Constants.DEFAULT_NAMESPACES_SET; - } - } - - /** - * Computes the effective namespaces based on the set specified by the user, in particular - * retrieves the current namespace from the client when the user specified that they wanted to - * watch the current namespace only. - * - * @return a Set of namespace names the associated controller will watch - */ - default Set getEffectiveNamespaces(ControllerConfiguration controllerConfiguration) { - var targetNamespaces = getNamespaces(); - if (watchCurrentNamespace()) { - final String namespace = - controllerConfiguration.getConfigurationService().getKubernetesClient().getConfiguration() - .getNamespace(); - if (namespace == null) { - throw new OperatorException( - "Couldn't retrieve the currently connected namespace. Make sure it's correctly set in your ~/.kube/config file, using, e.g. 'kubectl config set-context --namespace='"); - } - targetNamespaces = Collections.singleton(namespace); - } - return targetNamespaces; - } - - /** - * Replaces the item store in informer. See underlying method - * in fabric8 client informer implementation. - * - *

- * The main goal, is to be able to use limited caches or provide any custom implementation. - *

- * - *

- * See {@link BoundedItemStore} and CaffeineBoundedCache - *

- * - * @return Optional {@link ItemStore} implementation. If present this item store will be used by - * the informers. - */ - default Optional> getItemStore() { - return Optional.ofNullable(getInformerConfig().getItemStore()); - } - - /** - * The maximum amount of items to return for a single list call when starting an informer. If this - * is a not null it will result in paginating for the initial load of the informer cache. - */ - default Optional getInformerListLimit() { - return Optional.ofNullable(getInformerConfig().getInformerListLimit()); - } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/Informer.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/Informer.java index 363200bea5..57da4f41a6 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/Informer.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/Informer.java @@ -13,7 +13,7 @@ import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter; import io.javaoperatorsdk.operator.processing.event.source.filter.OnUpdateFilter; -import static io.javaoperatorsdk.operator.api.config.informer.InformerEventSourceConfiguration.DEFAULT_FOLLOW_CONTROLLER_NAMESPACES_ON_CHANGE; +import static io.javaoperatorsdk.operator.api.reconciler.Constants.DEFAULT_FOLLOW_CONTROLLER_NAMESPACES_ON_CHANGE; import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_LONG_VALUE_SET; import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_VALUE_SET; diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java index 0cb6892ebe..35d1ae0367 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java @@ -1,12 +1,17 @@ package io.javaoperatorsdk.operator.api.config.informer; +import java.util.Collection; +import java.util.Collections; import java.util.Set; +import java.util.stream.Collectors; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.client.informers.cache.ItemStore; -import io.javaoperatorsdk.operator.api.config.ResourceConfiguration; +import io.javaoperatorsdk.operator.OperatorException; +import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.Utils; import io.javaoperatorsdk.operator.api.reconciler.Constants; +import io.javaoperatorsdk.operator.processing.event.source.cache.BoundedItemStore; import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter; import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter; import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter; @@ -68,6 +73,48 @@ public static InformerConfiguration.Builder builder( original.itemStore, original.informerListLimit).builder; } + public static String ensureValidLabelSelector(String labelSelector) { + // might want to implement validation here? + return labelSelector; + } + + public static boolean allNamespacesWatched(Set namespaces) { + failIfNotValid(namespaces); + return DEFAULT_NAMESPACES_SET.equals(namespaces); + } + + public static boolean currentNamespaceWatched(Set namespaces) { + failIfNotValid(namespaces); + return WATCH_CURRENT_NAMESPACE_SET.equals(namespaces); + } + + public static void failIfNotValid(Set namespaces) { + if (namespaces != null && !namespaces.isEmpty()) { + final var present = namespaces.contains(WATCH_CURRENT_NAMESPACE) + || namespaces.contains(WATCH_ALL_NAMESPACES); + if (!present || namespaces.size() == 1) { + return; + } + } + throw new IllegalArgumentException( + "Must specify namespaces. To watch all namespaces, use only '" + + WATCH_ALL_NAMESPACES + + "'. To watch only the namespace in which the operator is deployed, use only '" + + WATCH_CURRENT_NAMESPACE + "'"); + } + + public static Set ensureValidNamespaces(Collection namespaces) { + if (namespaces != null && !namespaces.isEmpty()) { + return namespaces.stream().map(String::trim).collect(Collectors.toSet()); + } else { + return Constants.DEFAULT_NAMESPACES_SET; + } + } + + public static boolean inheritsNamespacesFromController(Set namespaces) { + return SAME_AS_CONTROLLER_NAMESPACES_SET.equals(namespaces); + } + public String getName() { return name; } @@ -76,10 +123,64 @@ public Set getNamespaces() { return namespaces; } + public boolean watchAllNamespaces() { + return InformerConfiguration.allNamespacesWatched(getNamespaces()); + } + + public boolean watchCurrentNamespace() { + return InformerConfiguration.currentNamespaceWatched(getNamespaces()); + } + + public boolean inheritsNamespacesFromController() { + return inheritsNamespacesFromController(getNamespaces()); + } + + /** + * Computes the effective namespaces based on the set specified by the user, in particular + * retrieves the current namespace from the client when the user specified that they wanted to + * watch the current namespace only. + * + * @return a Set of namespace names the associated controller will watch + */ + public Set getEffectiveNamespaces(ControllerConfiguration controllerConfiguration) { + if (inheritsNamespacesFromController()) { + return controllerConfiguration.getEffectiveNamespaces(); + } + + var targetNamespaces = getNamespaces(); + if (watchCurrentNamespace()) { + final String namespace = + controllerConfiguration.getConfigurationService().getKubernetesClient().getConfiguration() + .getNamespace(); + if (namespace == null) { + throw new OperatorException( + "Couldn't retrieve the currently connected namespace. Make sure it's correctly set in your ~/.kube/config file, using, e.g. 'kubectl config set-context --namespace='"); + } + targetNamespaces = Collections.singleton(namespace); + } + return targetNamespaces; + } + + /** + * Used in case the watched namespaces are changed dynamically, thus when operator is running (See + * {@link io.javaoperatorsdk.operator.RegisteredController}). If true, changing the target + * namespaces of a controller would result to change target namespaces for the + * InformerEventSource. + * + * @return if namespace changes should be followed + */ public boolean isFollowControllerNamespacesOnChange() { return followControllerNamespacesOnChange; } + /** + * Retrieves the label selector that is used to filter which resources are actually watched by the + * associated informer. See the official documentation on the + * topic + * for more details on syntax. + * + * @return the label selector filtering watched resources + */ public String getLabelSelector() { return labelSelector; } @@ -100,10 +201,31 @@ public GenericFilter getGenericFilter() { return genericFilter; } + /** + * Replaces the item store in informer. See underlying method + * in fabric8 client informer implementation. + * + *

+ * The main goal, is to be able to use limited caches or provide any custom implementation. + *

+ * + *

+ * See {@link BoundedItemStore} and CaffeineBoundedCache + *

+ * + * @return Optional {@link ItemStore} implementation. If present this item store will be used by + * the informers. + */ public ItemStore getItemStore() { return itemStore; } + /** + * The maximum amount of items to return for a single list call when starting an informer. If this + * is a not null it will result in paginating for the initial load of the informer cache. + */ public Long getInformerListLimit() { return informerListLimit; } @@ -116,7 +238,7 @@ public InformerConfiguration buildForController() { // if the informer config uses the default "same as controller" value, reset the namespaces to // the default set for controllers if (namespaces == null || namespaces.isEmpty() - || InformerEventSourceConfiguration.inheritsNamespacesFromController(namespaces)) { + || inheritsNamespacesFromController(namespaces)) { namespaces = Constants.DEFAULT_NAMESPACES_SET; } return InformerConfiguration.this; @@ -128,7 +250,7 @@ public InformerConfiguration buildForInformerEventSource() { } if (followControllerNamespacesOnChange == null) { followControllerNamespacesOnChange = - InformerEventSourceConfiguration.DEFAULT_FOLLOW_CONTROLLER_NAMESPACES_ON_CHANGE; + DEFAULT_FOLLOW_CONTROLLER_NAMESPACES_ON_CHANGE; } return InformerConfiguration.this; } @@ -184,7 +306,7 @@ public Builder withName(String name) { public Builder withNamespaces(Set namespaces) { InformerConfiguration.this.namespaces = - ResourceConfiguration.ensureValidNamespaces(namespaces); + ensureValidNamespaces(namespaces); return this; } @@ -239,7 +361,7 @@ public Builder withFollowControllerNamespacesOnChange(boolean followChanges) { public Builder withLabelSelector(String labelSelector) { InformerConfiguration.this.labelSelector = - ResourceConfiguration.ensureValidLabelSelector(labelSelector); + ensureValidLabelSelector(labelSelector); return this; } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java index 1e5e1ce666..0be16ad0f2 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java @@ -2,32 +2,21 @@ import java.util.Objects; import java.util.Optional; -import java.util.Set; import java.util.function.Consumer; import io.fabric8.kubernetes.api.model.GenericKubernetesResource; import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.DefaultResourceConfiguration; import io.javaoperatorsdk.operator.api.config.ResourceConfiguration; import io.javaoperatorsdk.operator.api.config.Utils; import io.javaoperatorsdk.operator.processing.GroupVersionKind; import io.javaoperatorsdk.operator.processing.event.source.PrimaryToSecondaryMapper; import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter; import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.SAME_AS_CONTROLLER_NAMESPACES_SET; - public interface InformerEventSourceConfiguration extends ResourceConfiguration { - boolean DEFAULT_FOLLOW_CONTROLLER_NAMESPACES_ON_CHANGE = true; - - static boolean inheritsNamespacesFromController(Set namespaces) { - return SAME_AS_CONTROLLER_NAMESPACES_SET.equals(namespaces); - } - static Builder from( Class resourceClass, Class primaryResourceClass) { return new Builder<>(resourceClass, primaryResourceClass); @@ -62,10 +51,6 @@ default boolean followControllerNamespaceChanges() { */ SecondaryToPrimaryMapper getSecondaryToPrimaryMapper(); - default Optional> onDeleteFilter() { - return Optional.ofNullable(getInformerConfig().getOnDeleteFilter()); - } -

PrimaryToSecondaryMapper

getPrimaryToSecondaryMapper(); Optional getGroupVersionKind(); @@ -104,11 +89,6 @@ public SecondaryToPrimaryMapper getSecondaryToPrimaryMapper() { return secondaryToPrimaryMapper; } - @Override - public Optional> onDeleteFilter() { - return Optional.ofNullable(getInformerConfig().getOnDeleteFilter()); - } - @Override @SuppressWarnings("unchecked") public

PrimaryToSecondaryMapper

getPrimaryToSecondaryMapper() { @@ -119,19 +99,6 @@ public

PrimaryToSecondaryMapper

getPrimaryToSecondary public Optional getGroupVersionKind() { return Optional.ofNullable(groupVersionKind); } - - public boolean inheritsNamespacesFromController() { - return InformerEventSourceConfiguration.inheritsNamespacesFromController(getNamespaces()); - } - - @Override - public Set getEffectiveNamespaces(ControllerConfiguration controllerConfiguration) { - if (inheritsNamespacesFromController()) { - return controllerConfiguration.getEffectiveNamespaces(); - } else { - return super.getEffectiveNamespaces(controllerConfiguration); - } - } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Constants.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Constants.java index 594fcddd09..8003d8f836 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Constants.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Constants.java @@ -25,6 +25,7 @@ public final class Constants { public static final String RESOURCE_GVK_KEY = "josdk.resource.gvk"; public static final String CONTROLLER_NAME = "controller.name"; + public static final boolean DEFAULT_FOLLOW_CONTROLLER_NAMESPACES_ON_CHANGE = true; private Constants() {} } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSource.java index db457a4e41..07e5bd3fa2 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSource.java @@ -43,11 +43,12 @@ public ControllerEventSource(Controller controller) { .or(onUpdateMarkedForDeletion()); // by default the on add should be processed in all cases regarding internal filters - config.onAddFilter().ifPresent(this::setOnAddFilter); - config.onUpdateFilter() + final var informerConfig = config.getInformerConfig(); + Optional.ofNullable(informerConfig.getOnAddFilter()).ifPresent(this::setOnAddFilter); + Optional.ofNullable(informerConfig.getOnUpdateFilter()) .ifPresentOrElse(filter -> setOnUpdateFilter(filter.and(internalOnUpdateFilter)), () -> setOnUpdateFilter(internalOnUpdateFilter)); - config.genericFilter().ifPresent(this::setGenericFilter); + Optional.ofNullable(informerConfig.getGenericFilter()).ifPresent(this::setGenericFilter); setControllerConfiguration(config); } 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 db3b9d6601..2568683600 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 @@ -106,10 +106,11 @@ private InformerEventSource(InformerEventSourceConfiguration configuration, primaryToSecondaryIndex = NOOPPrimaryToSecondaryIndex.getInstance(); } - onAddFilter = configuration.onAddFilter().orElse(null); - onUpdateFilter = configuration.onUpdateFilter().orElse(null); - onDeleteFilter = configuration.onDeleteFilter().orElse(null); - genericFilter = configuration.genericFilter().orElse(null); + final var informerConfig = configuration.getInformerConfig(); + onAddFilter = informerConfig.getOnAddFilter(); + onUpdateFilter = informerConfig.getOnUpdateFilter(); + onDeleteFilter = informerConfig.getOnDeleteFilter(); + genericFilter = informerConfig.getGenericFilter(); } @Override 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 9fc4a7db19..8951ea4c9d 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 @@ -20,6 +20,7 @@ import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.ResourceConfiguration; +import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.health.InformerHealthIndicator; import io.javaoperatorsdk.operator.processing.LifecycleAware; import io.javaoperatorsdk.operator.processing.event.ResourceID; @@ -71,8 +72,9 @@ private void initSources() { if (!sources.isEmpty()) { throw new IllegalStateException("Some sources already initialized."); } - final var targetNamespaces = configuration.getEffectiveNamespaces(controllerConfiguration); - if (ResourceConfiguration.allNamespacesWatched(targetNamespaces)) { + final var targetNamespaces = + configuration.getInformerConfig().getEffectiveNamespaces(controllerConfiguration); + if (InformerConfiguration.allNamespacesWatched(targetNamespaces)) { var source = createEventSourceForNamespace(WATCH_ALL_NAMESPACES); log.debug("Registered {} -> {} for any namespace", this, source); } else { @@ -108,13 +110,14 @@ public void changeNamespaces(Set namespaces) { private InformerWrapper createEventSourceForNamespace(String namespace) { final InformerWrapper source; + final var labelSelector = configuration.getInformerConfig().getLabelSelector(); if (namespace.equals(WATCH_ALL_NAMESPACES)) { final var filteredBySelectorClient = - client.inAnyNamespace().withLabelSelector(configuration.getLabelSelector()); + client.inAnyNamespace().withLabelSelector(labelSelector); source = createEventSource(filteredBySelectorClient, eventHandler, WATCH_ALL_NAMESPACES); } else { source = createEventSource( - client.inNamespace(namespace).withLabelSelector(configuration.getLabelSelector()), + client.inNamespace(namespace).withLabelSelector(labelSelector), eventHandler, namespace); } source.addIndexers(indexers); @@ -124,9 +127,11 @@ private InformerWrapper createEventSourceForNamespace(String namespace) { private InformerWrapper createEventSource( FilterWatchListDeletable, Resource> filteredBySelectorClient, ResourceEventHandler eventHandler, String namespaceIdentifier) { - var informer = configuration.getInformerListLimit().map(filteredBySelectorClient::withLimit) + final var informerConfig = configuration.getInformerConfig(); + var informer = Optional.ofNullable(informerConfig.getInformerListLimit()) + .map(filteredBySelectorClient::withLimit) .orElse(filteredBySelectorClient).runnableInformer(0); - configuration.getItemStore().ifPresent(informer::itemStore); + Optional.ofNullable(informerConfig.getItemStore()).ifPresent(informer::itemStore); var source = new InformerWrapper<>(informer, controllerConfiguration.getConfigurationService(), namespaceIdentifier); source.addEventHandler(eventHandler); @@ -205,11 +210,12 @@ public List byIndex(String indexName, String indexKey) { @Override public String toString() { - final var selector = configuration.getLabelSelector(); + final var informerConfig = configuration.getInformerConfig(); + final var selector = informerConfig.getLabelSelector(); return "InformerManager [" + ReconcilerUtils.getResourceTypeNameWithVersion(configuration.getResourceClass()) + "] watching: " - + configuration.getEffectiveNamespaces(controllerConfiguration) + + informerConfig.getEffectiveNamespaces(controllerConfiguration) + (selector != null ? " selector: " + selector : ""); } diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverriderTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverriderTest.java index 00733b496b..f549696426 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverriderTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverriderTest.java @@ -30,7 +30,7 @@ import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResourceConfigBuilder; import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition; -import static io.javaoperatorsdk.operator.api.config.informer.InformerEventSourceConfiguration.inheritsNamespacesFromController; +import static io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration.inheritsNamespacesFromController; import static org.junit.jupiter.api.Assertions.*; class ControllerConfigurationOverriderTest { @@ -67,7 +67,7 @@ void overridingNSShouldPreserveUntouchedDependents() { .settingNamespace(namespace) .replacingNamedDependentResourceConfig(externalDRName, stringConfig) .build(); - assertEquals(Set.of(namespace), configuration.getNamespaces()); + assertEquals(Set.of(namespace), configuration.getInformerConfig().getNamespaces()); // check that we still have the proper number of dependent configs dependentResources = configuration.getWorkflowSpec().orElseThrow().getDependentResourceSpecs(); @@ -93,48 +93,55 @@ private io.javaoperatorsdk.operator.api.config.ControllerConfiguration create @Test void overridingNamespacesShouldWork() { var configuration = createConfiguration(new WatchCurrentReconciler()); - assertEquals(Set.of("foo"), configuration.getNamespaces()); - assertFalse(configuration.watchAllNamespaces()); - assertFalse(configuration.watchCurrentNamespace()); + var informerConfig = configuration.getInformerConfig(); + assertEquals(Set.of("foo"), informerConfig.getNamespaces()); + assertFalse(informerConfig.watchAllNamespaces()); + assertFalse(informerConfig.watchCurrentNamespace()); configuration = ControllerConfigurationOverrider.override(configuration) .addingNamespaces("foo", "bar") .build(); - assertEquals(Set.of("foo", "bar"), configuration.getNamespaces()); - assertFalse(configuration.watchAllNamespaces()); - assertFalse(configuration.watchCurrentNamespace()); + informerConfig = configuration.getInformerConfig(); + assertEquals(Set.of("foo", "bar"), informerConfig.getNamespaces()); + assertFalse(informerConfig.watchAllNamespaces()); + assertFalse(informerConfig.watchCurrentNamespace()); configuration = ControllerConfigurationOverrider.override(configuration) .removingNamespaces("bar") .build(); - assertEquals(Set.of("foo"), configuration.getNamespaces()); - assertFalse(configuration.watchAllNamespaces()); - assertFalse(configuration.watchCurrentNamespace()); + informerConfig = configuration.getInformerConfig(); + assertEquals(Set.of("foo"), informerConfig.getNamespaces()); + assertFalse(informerConfig.watchAllNamespaces()); + assertFalse(informerConfig.watchCurrentNamespace()); configuration = ControllerConfigurationOverrider.override(configuration) .removingNamespaces("foo") .build(); - assertTrue(configuration.watchAllNamespaces()); - assertFalse(configuration.watchCurrentNamespace()); + informerConfig = configuration.getInformerConfig(); + assertTrue(informerConfig.watchAllNamespaces()); + assertFalse(informerConfig.watchCurrentNamespace()); configuration = ControllerConfigurationOverrider.override(configuration) .settingNamespace("foo") .build(); - assertFalse(configuration.watchAllNamespaces()); - assertFalse(configuration.watchCurrentNamespace()); - assertEquals(Set.of("foo"), configuration.getNamespaces()); + informerConfig = configuration.getInformerConfig(); + assertFalse(informerConfig.watchAllNamespaces()); + assertFalse(informerConfig.watchCurrentNamespace()); + assertEquals(Set.of("foo"), informerConfig.getNamespaces()); configuration = ControllerConfigurationOverrider.override(configuration) .watchingOnlyCurrentNamespace() .build(); - assertFalse(configuration.watchAllNamespaces()); - assertTrue(configuration.watchCurrentNamespace()); + informerConfig = configuration.getInformerConfig(); + assertFalse(informerConfig.watchAllNamespaces()); + assertTrue(informerConfig.watchCurrentNamespace()); configuration = ControllerConfigurationOverrider.override(configuration) .watchingAllNamespaces() .build(); - assertTrue(configuration.watchAllNamespaces()); - assertFalse(configuration.watchCurrentNamespace()); + informerConfig = configuration.getInformerConfig(); + assertTrue(informerConfig.watchAllNamespaces()); + assertFalse(informerConfig.watchCurrentNamespace()); } @Test @@ -144,23 +151,24 @@ void itemStorePreserved() { configuration = ControllerConfigurationOverrider.override(configuration) .build(); - assertNotNull(configuration.getItemStore().orElse(null)); + assertNotNull(configuration.getInformerConfig().getItemStore()); } @Test void configuredDependentShouldNotChangeOnParentOverrideEvenWhenInitialConfigIsSame() { var configuration = createConfiguration(new OverriddenNSOnDepReconciler()); // retrieve the config for the first (and unique) dependent - var config = extractFirstDependentKubernetesResourceConfig(configuration); + var kubeDependentConfig = extractFirstDependentKubernetesResourceConfig(configuration); // override the parent NS to match the dependent's configuration = ControllerConfigurationOverrider.override(configuration) .settingNamespace(OverriddenNSDependent.DEP_NS).build(); - assertEquals(Set.of(OverriddenNSDependent.DEP_NS), configuration.getNamespaces()); + assertEquals(Set.of(OverriddenNSDependent.DEP_NS), + configuration.getInformerConfig().getNamespaces()); // check that the DependentResource inherits has its own configured NS - var informerConfig = config.informerConfig(); - assertEquals(Set.of(OverriddenNSDependent.DEP_NS), informerConfig.getNamespaces()); + assertEquals(Set.of(OverriddenNSDependent.DEP_NS), + kubeDependentConfig.informerConfig().getNamespaces()); // override the parent's NS final var newNS = "bar"; @@ -168,9 +176,9 @@ void configuredDependentShouldNotChangeOnParentOverrideEvenWhenInitialConfigIsSa ControllerConfigurationOverrider.override(configuration).settingNamespace(newNS).build(); // check that dependent config is still using its own NS - config = extractFirstDependentKubernetesResourceConfig(configuration); - informerConfig = config.informerConfig(); - assertEquals(Set.of(OverriddenNSDependent.DEP_NS), informerConfig.getNamespaces()); + kubeDependentConfig = extractFirstDependentKubernetesResourceConfig(configuration); + assertEquals(Set.of(OverriddenNSDependent.DEP_NS), + kubeDependentConfig.informerConfig().getNamespaces()); } @SuppressWarnings("unchecked") @@ -182,8 +190,7 @@ void dependentShouldWatchAllNamespacesIfParentDoesAsWell() { // check that the DependentResource inherits the controller's configuration if applicable var informerConfig = config.informerConfig(); - assertTrue( - inheritsNamespacesFromController(informerConfig.getNamespaces())); + assertTrue(inheritsNamespacesFromController(informerConfig.getNamespaces())); } @@ -196,7 +203,7 @@ void shouldBePossibleToForceDependentToWatchAllNamespaces() { // check that the DependentResource inherits the controller's configuration if applicable assertTrue( - ResourceConfiguration + InformerConfiguration .allNamespacesWatched(config.informerConfig().getNamespaces())); // override the NS @@ -207,7 +214,7 @@ void shouldBePossibleToForceDependentToWatchAllNamespaces() { // check that dependent config is still configured to watch all NS config = extractFirstDependentKubernetesResourceConfig(configuration); assertTrue( - ResourceConfiguration + InformerConfiguration .allNamespacesWatched(config.informerConfig().getNamespaces())); } diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/MockControllerConfiguration.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/MockControllerConfiguration.java index 6ae83294bb..afd01d0f90 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/MockControllerConfiguration.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/MockControllerConfiguration.java @@ -1,6 +1,7 @@ package io.javaoperatorsdk.operator.api.config; import io.fabric8.kubernetes.api.model.HasMetadata; +import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import static io.javaoperatorsdk.operator.api.reconciler.Constants.DEFAULT_NAMESPACES_SET; import static org.mockito.ArgumentMatchers.any; @@ -18,9 +19,11 @@ public static ControllerConfiguration forResource( public static ControllerConfiguration forResource( Class resourceType, ConfigurationService configurationService) { final ControllerConfiguration configuration = mock(ControllerConfiguration.class); + final InformerConfiguration informerConfiguration = mock(InformerConfiguration.class); + when(configuration.getInformerConfig()).thenReturn(informerConfiguration); when(configuration.getResourceClass()).thenReturn(resourceType); - when(configuration.getNamespaces()).thenReturn(DEFAULT_NAMESPACES_SET); - when(configuration.getEffectiveNamespaces(any())).thenCallRealMethod(); + when(informerConfiguration.getNamespaces()).thenReturn(DEFAULT_NAMESPACES_SET); + when(informerConfiguration.getEffectiveNamespaces(any())).thenCallRealMethod(); when(configuration.getName()).thenReturn(resourceType.getSimpleName()); when(configuration.getConfigurationService()).thenReturn(configurationService); return configuration; diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ResourceConfigurationTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ResourceConfigurationTest.java index 5cf8376ea2..c48fb58e75 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ResourceConfigurationTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ResourceConfigurationTest.java @@ -20,60 +20,60 @@ class ResourceConfigurationTest { @Test void allNamespacesWatched() { assertThrows(IllegalArgumentException.class, - () -> ResourceConfiguration.allNamespacesWatched(null)); - assertThrows(IllegalArgumentException.class, () -> ResourceConfiguration.allNamespacesWatched( + () -> InformerConfiguration.allNamespacesWatched(null)); + assertThrows(IllegalArgumentException.class, () -> InformerConfiguration.allNamespacesWatched( Set.of(Constants.WATCH_CURRENT_NAMESPACE, Constants.WATCH_ALL_NAMESPACES, "foo"))); - assertThrows(IllegalArgumentException.class, () -> ResourceConfiguration.allNamespacesWatched( + assertThrows(IllegalArgumentException.class, () -> InformerConfiguration.allNamespacesWatched( Collections.emptySet())); - assertFalse(ResourceConfiguration.allNamespacesWatched(Set.of("foo", "bar"))); - assertTrue(ResourceConfiguration.allNamespacesWatched(Set.of(Constants.WATCH_ALL_NAMESPACES))); - assertFalse(ResourceConfiguration.allNamespacesWatched(Set.of("foo"))); + assertFalse(InformerConfiguration.allNamespacesWatched(Set.of("foo", "bar"))); + assertTrue(InformerConfiguration.allNamespacesWatched(Set.of(Constants.WATCH_ALL_NAMESPACES))); + assertFalse(InformerConfiguration.allNamespacesWatched(Set.of("foo"))); assertFalse( - ResourceConfiguration.allNamespacesWatched(Set.of(Constants.WATCH_CURRENT_NAMESPACE))); + InformerConfiguration.allNamespacesWatched(Set.of(Constants.WATCH_CURRENT_NAMESPACE))); } @Test void currentNamespaceWatched() { assertThrows(IllegalArgumentException.class, - () -> ResourceConfiguration.currentNamespaceWatched(null)); + () -> InformerConfiguration.currentNamespaceWatched(null)); assertThrows(IllegalArgumentException.class, - () -> ResourceConfiguration.currentNamespaceWatched( + () -> InformerConfiguration.currentNamespaceWatched( Set.of(Constants.WATCH_CURRENT_NAMESPACE, Constants.WATCH_ALL_NAMESPACES, "foo"))); assertThrows(IllegalArgumentException.class, - () -> ResourceConfiguration.currentNamespaceWatched(Collections.emptySet())); - assertFalse(ResourceConfiguration.currentNamespaceWatched(Set.of("foo", "bar"))); + () -> InformerConfiguration.currentNamespaceWatched(Collections.emptySet())); + assertFalse(InformerConfiguration.currentNamespaceWatched(Set.of("foo", "bar"))); assertFalse( - ResourceConfiguration.currentNamespaceWatched(Set.of(Constants.WATCH_ALL_NAMESPACES))); - assertFalse(ResourceConfiguration.currentNamespaceWatched(Set.of("foo"))); + InformerConfiguration.currentNamespaceWatched(Set.of(Constants.WATCH_ALL_NAMESPACES))); + assertFalse(InformerConfiguration.currentNamespaceWatched(Set.of("foo"))); assertTrue( - ResourceConfiguration.currentNamespaceWatched(Set.of(Constants.WATCH_CURRENT_NAMESPACE))); + InformerConfiguration.currentNamespaceWatched(Set.of(Constants.WATCH_CURRENT_NAMESPACE))); } @Test void nullLabelSelectorByDefault() { - assertNull(DEFAULT.getLabelSelector()); + assertNull(DEFAULT.getInformerConfig().getLabelSelector()); } // todo: fix me @Disabled @Test void shouldWatchAllNamespacesByDefault() { - assertTrue(DEFAULT.watchAllNamespaces()); + assertTrue(DEFAULT.getInformerConfig().watchAllNamespaces()); } @Test void failIfNotValid() { - assertThrows(IllegalArgumentException.class, () -> ResourceConfiguration.failIfNotValid(null)); + assertThrows(IllegalArgumentException.class, () -> InformerConfiguration.failIfNotValid(null)); assertThrows(IllegalArgumentException.class, - () -> ResourceConfiguration.failIfNotValid(Collections.emptySet())); - assertThrows(IllegalArgumentException.class, () -> ResourceConfiguration.failIfNotValid( + () -> InformerConfiguration.failIfNotValid(Collections.emptySet())); + assertThrows(IllegalArgumentException.class, () -> InformerConfiguration.failIfNotValid( Set.of(Constants.WATCH_CURRENT_NAMESPACE, Constants.WATCH_ALL_NAMESPACES, "foo"))); - assertThrows(IllegalArgumentException.class, () -> ResourceConfiguration.failIfNotValid( + assertThrows(IllegalArgumentException.class, () -> InformerConfiguration.failIfNotValid( Set.of(Constants.WATCH_CURRENT_NAMESPACE, "foo"))); - assertThrows(IllegalArgumentException.class, () -> ResourceConfiguration.failIfNotValid( + assertThrows(IllegalArgumentException.class, () -> InformerConfiguration.failIfNotValid( Set.of(Constants.WATCH_ALL_NAMESPACES, "foo"))); // should work - ResourceConfiguration.failIfNotValid(Set.of("foo", "bar")); + InformerConfiguration.failIfNotValid(Set.of("foo", "bar")); } } diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSourceTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSourceTest.java index 442f53bc98..ce027846f0 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSourceTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSourceTest.java @@ -16,6 +16,7 @@ import io.javaoperatorsdk.operator.api.config.ConfigurationService; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.InformerStoppedHandler; +import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.api.config.informer.InformerEventSourceConfiguration; import io.javaoperatorsdk.operator.processing.event.EventHandler; import io.javaoperatorsdk.operator.processing.event.ResourceID; @@ -44,18 +45,19 @@ class InformerEventSourceTest { private final TemporaryResourceCache temporaryResourceCacheMock = mock(TemporaryResourceCache.class); private final EventHandler eventHandlerMock = mock(EventHandler.class); - private final InformerEventSourceConfiguration informerConfiguration = + private final InformerEventSourceConfiguration informerEventSourceConfiguration = mock(InformerEventSourceConfiguration.class); @BeforeEach void setup() { - when(informerConfiguration.getEffectiveNamespaces(any())) - .thenReturn(DEFAULT_NAMESPACES_SET); - when(informerConfiguration.getSecondaryToPrimaryMapper()) + final var informerConfig = mock(InformerConfiguration.class); + when(informerEventSourceConfiguration.getInformerConfig()).thenReturn(informerConfig); + when(informerConfig.getEffectiveNamespaces(any())).thenReturn(DEFAULT_NAMESPACES_SET); + when(informerEventSourceConfiguration.getSecondaryToPrimaryMapper()) .thenReturn(mock(SecondaryToPrimaryMapper.class)); - when(informerConfiguration.getResourceClass()).thenReturn(Deployment.class); + when(informerEventSourceConfiguration.getResourceClass()).thenReturn(Deployment.class); - informerEventSource = new InformerEventSource<>(informerConfiguration, clientMock); + informerEventSource = new InformerEventSource<>(informerEventSourceConfiguration, clientMock); var mockControllerConfig = mock(ControllerConfiguration.class); when(mockControllerConfig.getConfigurationService()).thenReturn(new BaseConfigurationService()); @@ -63,7 +65,7 @@ void setup() { informerEventSource.setEventHandler(eventHandlerMock); informerEventSource.setControllerConfiguration(mockControllerConfig); SecondaryToPrimaryMapper secondaryToPrimaryMapper = mock(SecondaryToPrimaryMapper.class); - when(informerConfiguration.getSecondaryToPrimaryMapper()) + when(informerEventSourceConfiguration.getSecondaryToPrimaryMapper()) .thenReturn(secondaryToPrimaryMapper); when(secondaryToPrimaryMapper.toPrimaryResourceIDs(any())) .thenReturn(Set.of(ResourceID.fromResource(testDeployment()))); @@ -184,7 +186,7 @@ void informerStoppedHandlerShouldBeCalledWhenInformerStops() { var mockControllerConfig = mock(ControllerConfiguration.class); when(mockControllerConfig.getConfigurationService()).thenReturn(configuration); - informerEventSource = new InformerEventSource<>(informerConfiguration, + informerEventSource = new InformerEventSource<>(informerEventSourceConfiguration, MockKubernetesClient.client(Deployment.class, unused -> { throw exception; })); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiplesecondaryeventsource/MultipleSecondaryEventSourceReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiplesecondaryeventsource/MultipleSecondaryEventSourceReconciler.java index bde573171d..77a3b245b0 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiplesecondaryeventsource/MultipleSecondaryEventSourceReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiplesecondaryeventsource/MultipleSecondaryEventSourceReconciler.java @@ -71,7 +71,10 @@ public List> prepareE var config = InformerEventSourceConfiguration .from(ConfigMap.class, MultipleSecondaryEventSourceCustomResource.class) .withInformerConfiguration(c -> c - .withNamespaces(context.getControllerConfiguration().getNamespaces()) + // TODO: this shouldn't be needed since this should be the default behavior (tracking + // the controller's namespaces) + .withNamespaces( + context.getControllerConfiguration().getInformerConfig().getNamespaces()) .withLabelSelector("multisecondary")) .withSecondaryToPrimaryMapper(s -> { var name = diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/BaseConfigurationServiceTest.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/BaseConfigurationServiceTest.java index 43309446fb..c83505e597 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/BaseConfigurationServiceTest.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/BaseConfigurationServiceTest.java @@ -112,19 +112,21 @@ void missingAnnotationCreatesDefaultConfig() { var config = configFor(reconciler); assertThat(config.getName()).isEqualTo(ReconcilerUtils.getNameFor(reconciler)); - assertThat(config.getLabelSelector()).isNull(); assertThat(config.getRetry()).isInstanceOf(GenericRetry.class); assertThat(config.getRateLimiter()).isInstanceOf(LinearRateLimiter.class); assertThat(config.maxReconciliationInterval()).hasValue(Duration.ofHours(DEFAULT_INTERVAL)); assertThat(config.fieldManager()).isEqualTo(config.getName()); - assertThat(config.getInformerListLimit()).isEmpty(); - assertThat(config.onAddFilter()).isEmpty(); - assertThat(config.onUpdateFilter()).isEmpty(); - assertThat(config.genericFilter()).isEmpty(); - assertThat(config.getNamespaces()).isEqualTo(Constants.DEFAULT_NAMESPACES_SET); assertThat(config.getFinalizerName()) .isEqualTo(ReconcilerUtils.getDefaultFinalizerName(config.getResourceClass())); - assertThat(config.getItemStore()).isEmpty(); + + final var informerConfig = config.getInformerConfig(); + assertThat(informerConfig.getLabelSelector()).isNull(); + assertNull(informerConfig.getInformerListLimit()); + assertNull(informerConfig.getOnAddFilter()); + assertNull(informerConfig.getOnUpdateFilter()); + assertNull(informerConfig.getGenericFilter()); + assertNull(informerConfig.getItemStore()); + assertThat(informerConfig.getNamespaces()).isEqualTo(Constants.DEFAULT_NAMESPACES_SET); } @SuppressWarnings("rawtypes") From f70f5e84bfd7fa7f6a880c409cdf142d7478f386 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Fri, 9 Aug 2024 16:33:36 +0200 Subject: [PATCH 08/12] refactor: rename ResourceConfigurationTest -> InformerConfigurationTest Signed-off-by: Chris Laprun --- .../informer/InformerConfiguration.java | 2 ++ .../ControllerConfigurationOverriderTest.java | 6 ++--- ...st.java => InformerConfigurationTest.java} | 23 ++++++++++--------- 3 files changed, 16 insertions(+), 15 deletions(-) rename operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/{ResourceConfigurationTest.java => InformerConfigurationTest.java} (82%) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java index 35d1ae0367..dea968fec3 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java @@ -241,6 +241,8 @@ public InformerConfiguration buildForController() { || inheritsNamespacesFromController(namespaces)) { namespaces = Constants.DEFAULT_NAMESPACES_SET; } + // to avoid potential NPE + followControllerNamespacesOnChange = false; return InformerConfiguration.this; } diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverriderTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverriderTest.java index f549696426..46ef56e1d4 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverriderTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverriderTest.java @@ -77,12 +77,11 @@ void overridingNSShouldPreserveUntouchedDependents() { assertEquals(stringConfig, resourceConfig); } - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings({"rawtypes"}) private KubernetesDependentResourceConfig extractFirstDependentKubernetesResourceConfig( io.javaoperatorsdk.operator.api.config.ControllerConfiguration configuration) { - var conf = (KubernetesDependentResourceConfig) extractDependentKubernetesResourceConfig( + return (KubernetesDependentResourceConfig) extractDependentKubernetesResourceConfig( configuration, 0); - return conf; } private io.javaoperatorsdk.operator.api.config.ControllerConfiguration createConfiguration( @@ -219,7 +218,6 @@ void shouldBePossibleToForceDependentToWatchAllNamespaces() { } @Test - @SuppressWarnings("unchecked") void overridingNamespacesShouldBePropagatedToDependentsWithDefaultConfig() { var configuration = createConfiguration(new OneDepReconciler()); // retrieve the config for the first (and unique) dependent diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ResourceConfigurationTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/InformerConfigurationTest.java similarity index 82% rename from operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ResourceConfigurationTest.java rename to operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/InformerConfigurationTest.java index c48fb58e75..988ae33352 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ResourceConfigurationTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/InformerConfigurationTest.java @@ -3,19 +3,14 @@ import java.util.Collections; import java.util.Set; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Constants; import static org.junit.jupiter.api.Assertions.*; -class ResourceConfigurationTest { - - public static final ResourceConfiguration DEFAULT = - () -> InformerConfiguration.builder().buildForInformerEventSource(); +class InformerConfigurationTest { @Test void allNamespacesWatched() { @@ -51,14 +46,20 @@ void currentNamespaceWatched() { @Test void nullLabelSelectorByDefault() { - assertNull(DEFAULT.getInformerConfig().getLabelSelector()); + final var informerConfig = InformerConfiguration.builder().buildForInformerEventSource(); + assertNull(informerConfig.getLabelSelector()); + } + + @Test + void shouldWatchAllNamespacesByDefaultForControllers() { + final var informerConfig = InformerConfiguration.builder().buildForController(); + assertTrue(informerConfig.watchAllNamespaces()); } - // todo: fix me - @Disabled @Test - void shouldWatchAllNamespacesByDefault() { - assertTrue(DEFAULT.getInformerConfig().watchAllNamespaces()); + void shouldFollowControllerNamespacesByDefaultForInformerEventSource() { + final var informerConfig = InformerConfiguration.builder().buildForInformerEventSource(); + assertTrue(informerConfig.isFollowControllerNamespacesOnChange()); } @Test From 2ce5fe748acdd800e5a8090e4dfdd53aa7beb086 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Fri, 16 Aug 2024 10:07:10 +0200 Subject: [PATCH 09/12] feat: record resource class in InformerConfiguration Signed-off-by: Chris Laprun --- .../api/config/ResourceConfiguration.java | 6 ++-- .../informer/InformerConfiguration.java | 31 ++++++++++++++----- .../dependent/DependentResourceFactory.java | 15 ++++++--- .../KubernetesDependentConverter.java | 5 ++- .../processing/event/EventSourceManager.java | 14 ++++----- .../api/config/InformerConfigurationTest.java | 9 ++++-- .../event/EventSourceManagerTest.java | 7 ++--- .../WebPageDependentsWorkflowReconciler.java | 2 +- ...WebPageStandaloneDependentsReconciler.java | 2 +- 9 files changed, 58 insertions(+), 33 deletions(-) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResourceConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResourceConfiguration.java index f6039ce81e..55401aef9e 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResourceConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResourceConfiguration.java @@ -2,20 +2,18 @@ import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; public interface ResourceConfiguration { default String getResourceTypeName() { - return ReconcilerUtils.getResourceTypeName(getResourceClass()); + return getInformerConfig().getResourceTypeName(); } InformerConfiguration getInformerConfig(); @SuppressWarnings("unchecked") default Class getResourceClass() { - return (Class) Utils.getFirstTypeArgumentFromSuperClassOrInterface(getClass(), - ResourceConfiguration.class); + return getInformerConfig().getResourceClass(); } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java index dea968fec3..8d7b232889 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java @@ -5,9 +5,11 @@ import java.util.Set; import java.util.stream.Collectors; +import io.fabric8.kubernetes.api.model.GenericKubernetesResource; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.client.informers.cache.ItemStore; import io.javaoperatorsdk.operator.OperatorException; +import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.Utils; import io.javaoperatorsdk.operator.api.reconciler.Constants; @@ -23,6 +25,8 @@ @SuppressWarnings("unused") public class InformerConfiguration { private final Builder builder = new Builder(); + private final Class resourceClass; + private final String resourceTypeName; private String name; private Set namespaces; private Boolean followControllerNamespacesOnChange; @@ -34,11 +38,12 @@ public class InformerConfiguration { private ItemStore itemStore; private Long informerListLimit; - public InformerConfiguration(String name, Set namespaces, + protected InformerConfiguration(Class resourceClass, String name, Set namespaces, boolean followControllerNamespacesOnChange, String labelSelector, OnAddFilter onAddFilter, OnUpdateFilter onUpdateFilter, OnDeleteFilter onDeleteFilter, GenericFilter genericFilter, ItemStore itemStore, Long informerListLimit) { + this(resourceClass); this.name = name; this.namespaces = namespaces; this.followControllerNamespacesOnChange = followControllerNamespacesOnChange; @@ -51,23 +56,25 @@ public InformerConfiguration(String name, Set namespaces, this.informerListLimit = informerListLimit; } - private InformerConfiguration() {} - - @SuppressWarnings({"rawtypes", "unchecked"}) - public static InformerConfiguration.Builder builder() { - return new InformerConfiguration().builder; + private InformerConfiguration(Class resourceClass) { + this.resourceClass = resourceClass; + this.resourceTypeName = resourceClass.isAssignableFrom(GenericKubernetesResource.class) + // in general this is irrelevant now for secondary resources it is used just by controller + // where GenericKubernetesResource now does not apply + ? GenericKubernetesResource.class.getSimpleName() + : ReconcilerUtils.getResourceTypeName(resourceClass); } @SuppressWarnings({"rawtypes", "unchecked"}) public static InformerConfiguration.Builder builder( Class resourceClass) { - return new InformerConfiguration().builder; + return new InformerConfiguration(resourceClass).builder; } @SuppressWarnings({"rawtypes", "unchecked"}) public static InformerConfiguration.Builder builder( InformerConfiguration original) { - return new InformerConfiguration(original.name, original.namespaces, + return new InformerConfiguration(original.resourceClass, original.name, original.namespaces, original.followControllerNamespacesOnChange, original.labelSelector, original.onAddFilter, original.onUpdateFilter, original.onDeleteFilter, original.genericFilter, original.itemStore, original.informerListLimit).builder; @@ -115,6 +122,14 @@ public static boolean inheritsNamespacesFromController(Set namespaces) { return SAME_AS_CONTROLLER_NAMESPACES_SET.equals(namespaces); } + public Class getResourceClass() { + return resourceClass; + } + + public String getResourceTypeName() { + return resourceTypeName; + } + public String getName() { return name; } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceFactory.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceFactory.java index 105d2b6c75..cc9a1dd6c3 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceFactory.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceFactory.java @@ -6,11 +6,11 @@ import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.ConfiguredDependentResource; @SuppressWarnings({"rawtypes", "unchecked"}) -public interface DependentResourceFactory> { +public interface DependentResourceFactory, D extends DependentResourceSpec> { DependentResourceFactory DEFAULT = new DependentResourceFactory() {}; - default DependentResource createFrom(DependentResourceSpec spec, C controllerConfiguration) { + default DependentResource createFrom(D spec, C controllerConfiguration) { final var dependentResourceClass = spec.getDependentResourceClass(); return Utils.instantiateAndConfigureIfNeeded(dependentResourceClass, DependentResource.class, @@ -18,8 +18,7 @@ default DependentResource createFrom(DependentResourceSpec spec, C controllerCon (instance) -> configure(instance, spec, controllerConfiguration)); } - default void configure(DependentResource instance, DependentResourceSpec spec, - C controllerConfiguration) { + default void configure(DependentResource instance, D spec, C controllerConfiguration) { if (instance instanceof ConfiguredDependentResource configurable) { final var config = controllerConfiguration.getConfigurationFor(spec); if (config != null) { @@ -27,4 +26,12 @@ default void configure(DependentResource instance, DependentResourceSpec spec, } } } + + default Class associatedResourceType(D spec) { + final var dependentResourceClass = spec.getDependentResourceClass(); + final var dr = Utils.instantiateAndConfigureIfNeeded(dependentResourceClass, + DependentResource.class, + null, null); + return dr != null ? dr.resourceType() : null; + } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentConverter.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentConverter.java index 36625b0689..3bfa8351d3 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentConverter.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentConverter.java @@ -43,7 +43,10 @@ private InformerConfiguration createInformerConfig( Class> dependentResourceClass = (Class>) spec.getDependentResourceClass(); - InformerConfiguration.Builder config = InformerConfiguration.builder(); + final var resourceType = controllerConfig.getConfigurationService().dependentResourceFactory() + .associatedResourceType(spec); + + InformerConfiguration.Builder config = InformerConfiguration.builder(resourceType); if (configAnnotation != null) { final var informerConfig = configAnnotation.informer(); final var context = Utils.contextFor(controllerConfig, dependentResourceClass, diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java index 2bb8c7a39a..174ffa0978 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java @@ -173,16 +173,16 @@ public void broadcastOnResourceEvent(ResourceAction action, P resource, P oldRes } public void changeNamespaces(Set namespaces) { - eventSources.controllerEventSource() - .changeNamespaces(namespaces); - executorServiceManager.boundedExecuteAndWaitForAllToComplete(eventSources + eventSources.controllerEventSource().changeNamespaces(namespaces); + final var namespaceChangeables = eventSources .additionalEventSources() .filter(NamespaceChangeable.class::isInstance) .map(NamespaceChangeable.class::cast) - .filter(NamespaceChangeable::allowsNamespaceChanges), e -> { - e.changeNamespaces(namespaces); - return null; - }, + .filter(NamespaceChangeable::allowsNamespaceChanges); + executorServiceManager.boundedExecuteAndWaitForAllToComplete(namespaceChangeables, e -> { + e.changeNamespaces(namespaces); + return null; + }, getEventSourceThreadNamer("changeNamespace")); } diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/InformerConfigurationTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/InformerConfigurationTest.java index 988ae33352..468c67e0d7 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/InformerConfigurationTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/InformerConfigurationTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.api.Test; +import io.fabric8.kubernetes.api.model.ConfigMap; import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Constants; @@ -46,19 +47,21 @@ void currentNamespaceWatched() { @Test void nullLabelSelectorByDefault() { - final var informerConfig = InformerConfiguration.builder().buildForInformerEventSource(); + final var informerConfig = + InformerConfiguration.builder(ConfigMap.class).buildForInformerEventSource(); assertNull(informerConfig.getLabelSelector()); } @Test void shouldWatchAllNamespacesByDefaultForControllers() { - final var informerConfig = InformerConfiguration.builder().buildForController(); + final var informerConfig = InformerConfiguration.builder(ConfigMap.class).buildForController(); assertTrue(informerConfig.watchAllNamespaces()); } @Test void shouldFollowControllerNamespacesByDefaultForInformerEventSource() { - final var informerConfig = InformerConfiguration.builder().buildForInformerEventSource(); + final var informerConfig = + InformerConfiguration.builder(ConfigMap.class).buildForInformerEventSource(); assertTrue(informerConfig.isFollowControllerNamespacesOnChange()); } diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/EventSourceManagerTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/EventSourceManagerTest.java index e24de96dbb..a7f0dade3b 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/EventSourceManagerTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/EventSourceManagerTest.java @@ -168,14 +168,13 @@ void changesNamespacesOnControllerAndInformerEventSources() { when(controllerResourceEventSourceMock.allowsNamespaceChanges()).thenCallRealMethod(); var manager = new EventSourceManager(controller, eventSources); - InformerEventSourceConfiguration informerConfigurationMock = + InformerEventSourceConfiguration eventSourceConfigurationMock = mock(InformerEventSourceConfiguration.class); - when(informerConfigurationMock.followControllerNamespaceChanges()).thenReturn(true); InformerEventSource informerEventSource = mock(InformerEventSource.class); when(informerEventSource.name()).thenReturn("ies"); when(informerEventSource.resourceType()).thenReturn(TestCustomResource.class); - when(informerEventSource.configuration()).thenReturn(informerConfigurationMock); - when(informerEventSource.allowsNamespaceChanges()).thenCallRealMethod(); + when(informerEventSource.configuration()).thenReturn(eventSourceConfigurationMock); + when(informerEventSource.allowsNamespaceChanges()).thenReturn(true); manager.registerEventSource(informerEventSource); manager.changeNamespaces(Set.of(newNamespaces)); diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageDependentsWorkflowReconciler.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageDependentsWorkflowReconciler.java index b38f48b912..15343793fd 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageDependentsWorkflowReconciler.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageDependentsWorkflowReconciler.java @@ -85,7 +85,7 @@ private void initDependentResources(KubernetesClient client) { Arrays.asList(configMapDR, deploymentDR, serviceDR, ingressDR) .forEach(dr -> dr.configureWith(new KubernetesDependentResourceConfigBuilder() - .withKubernetesDependentInformerConfig(InformerConfiguration.builder() + .withKubernetesDependentInformerConfig(InformerConfiguration.builder(dr.resourceType()) .withLabelSelector(DEPENDENT_RESOURCE_LABEL_SELECTOR) .buildForInformerEventSource()) .build())); diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStandaloneDependentsReconciler.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStandaloneDependentsReconciler.java index e7930a3658..580d529a72 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStandaloneDependentsReconciler.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStandaloneDependentsReconciler.java @@ -96,7 +96,7 @@ private Workflow createDependentResourcesAndWorkflow() { // configure them with our label selector Arrays.asList(configMapDR, deploymentDR, serviceDR, ingressDR) .forEach(dr -> dr.configureWith(new KubernetesDependentResourceConfigBuilder() - .withKubernetesDependentInformerConfig(InformerConfiguration.builder() + .withKubernetesDependentInformerConfig(InformerConfiguration.builder(dr.resourceType()) .withLabelSelector(SELECTOR + "=true") .buildForInformerEventSource()) .build())); From 724008a56bc3160fbea1ce5f8cdd865ade4323e1 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Fri, 16 Aug 2024 14:22:43 +0200 Subject: [PATCH 10/12] refactor: rename ResourceConfiguration to Informable Signed-off-by: Chris Laprun --- .../operator/api/config/ControllerConfiguration.java | 2 +- ...tResourceConfiguration.java => DefaultInformable.java} | 6 +++--- .../{ResourceConfiguration.java => Informable.java} | 3 +-- .../api/config/ResolvedControllerConfiguration.java | 2 +- .../config/informer/InformerEventSourceConfiguration.java | 8 ++++---- .../processing/event/source/informer/InformerManager.java | 4 ++-- .../event/source/informer/ManagedInformerEventSource.java | 4 ++-- .../InformerRelatedBehaviorITS.java | 3 --- 8 files changed, 14 insertions(+), 18 deletions(-) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/{DefaultResourceConfiguration.java => DefaultInformable.java} (87%) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/{ResourceConfiguration.java => Informable.java} (81%) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java index 7547ee3e64..da3d27f18f 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java @@ -14,7 +14,7 @@ import io.javaoperatorsdk.operator.processing.retry.GenericRetry; import io.javaoperatorsdk.operator.processing.retry.Retry; -public interface ControllerConfiguration

extends ResourceConfiguration

{ +public interface ControllerConfiguration

extends Informable

{ @SuppressWarnings("rawtypes") RateLimiter DEFAULT_RATE_LIMITER = LinearRateLimiter.deactivatedRateLimiter(); diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultResourceConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultInformable.java similarity index 87% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultResourceConfiguration.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultInformable.java index c0d725f746..5ab1a57bd0 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultResourceConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultInformable.java @@ -6,14 +6,14 @@ import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; -public class DefaultResourceConfiguration - implements ResourceConfiguration { +public class DefaultInformable + implements Informable { private final Class resourceClass; private final String resourceTypeName; private final InformerConfiguration informerConfig; - protected DefaultResourceConfiguration(Class resourceClass, + protected DefaultInformable(Class resourceClass, InformerConfiguration informerConfig) { this.resourceClass = resourceClass; this.resourceTypeName = resourceClass.isAssignableFrom(GenericKubernetesResource.class) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResourceConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Informable.java similarity index 81% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResourceConfiguration.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Informable.java index 55401aef9e..5b58836483 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResourceConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Informable.java @@ -4,7 +4,7 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; -public interface ResourceConfiguration { +public interface Informable { default String getResourceTypeName() { return getInformerConfig().getResourceTypeName(); @@ -12,7 +12,6 @@ default String getResourceTypeName() { InformerConfiguration getInformerConfig(); - @SuppressWarnings("unchecked") default Class getResourceClass() { return getInformerConfig().getResourceClass(); } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResolvedControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResolvedControllerConfiguration.java index 9bb7efb5cf..e60ea1b87c 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResolvedControllerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResolvedControllerConfiguration.java @@ -16,7 +16,7 @@ @SuppressWarnings("rawtypes") public class ResolvedControllerConfiguration

- extends DefaultResourceConfiguration

+ extends DefaultInformable

implements io.javaoperatorsdk.operator.api.config.ControllerConfiguration

{ private final String name; diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java index 0be16ad0f2..827bd6c57b 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java @@ -6,8 +6,8 @@ import io.fabric8.kubernetes.api.model.GenericKubernetesResource; import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.api.config.DefaultResourceConfiguration; -import io.javaoperatorsdk.operator.api.config.ResourceConfiguration; +import io.javaoperatorsdk.operator.api.config.DefaultInformable; +import io.javaoperatorsdk.operator.api.config.Informable; import io.javaoperatorsdk.operator.api.config.Utils; import io.javaoperatorsdk.operator.processing.GroupVersionKind; import io.javaoperatorsdk.operator.processing.event.source.PrimaryToSecondaryMapper; @@ -15,7 +15,7 @@ import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers; public interface InformerEventSourceConfiguration - extends ResourceConfiguration { + extends Informable { static Builder from( Class resourceClass, Class primaryResourceClass) { @@ -67,7 +67,7 @@ default Class getResourceClass() { } class DefaultInformerEventSourceConfiguration extends - DefaultResourceConfiguration implements InformerEventSourceConfiguration { + DefaultInformable implements InformerEventSourceConfiguration { private final PrimaryToSecondaryMapper primaryToSecondaryMapper; private final SecondaryToPrimaryMapper secondaryToPrimaryMapper; private final GroupVersionKind groupVersionKind; 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 8951ea4c9d..57bbf2a8ce 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 @@ -19,7 +19,7 @@ import io.javaoperatorsdk.operator.OperatorException; import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; -import io.javaoperatorsdk.operator.api.config.ResourceConfiguration; +import io.javaoperatorsdk.operator.api.config.Informable; import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.health.InformerHealthIndicator; import io.javaoperatorsdk.operator.processing.LifecycleAware; @@ -29,7 +29,7 @@ import static io.javaoperatorsdk.operator.api.reconciler.Constants.WATCH_ALL_NAMESPACES; -class InformerManager> +class InformerManager> implements LifecycleAware, IndexerResourceCache { private static final Logger log = LoggerFactory.getLogger(InformerManager.class); diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSource.java index 54d60e2cdf..f5e899826d 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSource.java @@ -17,8 +17,8 @@ import io.fabric8.kubernetes.client.informers.ResourceEventHandler; import io.javaoperatorsdk.operator.OperatorException; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; +import io.javaoperatorsdk.operator.api.config.Informable; import io.javaoperatorsdk.operator.api.config.NamespaceChangeable; -import io.javaoperatorsdk.operator.api.config.ResourceConfiguration; import io.javaoperatorsdk.operator.api.reconciler.dependent.RecentOperationCacheFiller; import io.javaoperatorsdk.operator.health.InformerHealthIndicator; import io.javaoperatorsdk.operator.health.InformerWrappingEventSourceHealthIndicator; @@ -27,7 +27,7 @@ import io.javaoperatorsdk.operator.processing.event.source.*; @SuppressWarnings("rawtypes") -public abstract class ManagedInformerEventSource> +public abstract class ManagedInformerEventSource> extends AbstractEventSource implements ResourceEventHandler, Cache, IndexerResourceCache, RecentOperationCacheFiller, NamespaceChangeable, diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/informerrelatedbehavior/InformerRelatedBehaviorITS.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/informerrelatedbehavior/InformerRelatedBehaviorITS.java index 6b8ed9517d..21079c0504 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/informerrelatedbehavior/InformerRelatedBehaviorITS.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/informerrelatedbehavior/InformerRelatedBehaviorITS.java @@ -20,9 +20,6 @@ import io.javaoperatorsdk.operator.Operator; import io.javaoperatorsdk.operator.OperatorException; import io.javaoperatorsdk.operator.ReconcilerUtils; -import io.javaoperatorsdk.operator.Operator; -import io.javaoperatorsdk.operator.OperatorException; -import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.health.InformerHealthIndicator; import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension; import io.javaoperatorsdk.operator.processing.event.source.controller.ControllerEventSource; From 62be83e71b45e77ddcf38f6345639be0fda92303 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Mon, 19 Aug 2024 12:09:52 +0200 Subject: [PATCH 11/12] fix: javadoc Signed-off-by: Chris Laprun --- .../operator/api/config/ConfigurationService.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java index ab689c23a3..ff06ad338f 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java @@ -364,10 +364,8 @@ default ExecutorServiceManager getExecutorServiceManager() { * SSA based create/update can be still used with the legacy matching, just overriding the match * method of Kubernetes Dependent Resource. * - * @return if SSA should be used for dependent resources + * @return {@code true} if SSA should be used for dependent resources, {@code false} otherwise * @since 4.4.0 - * - * @return if SSA should be used for dependent resources */ default boolean ssaBasedCreateUpdateMatchForDependentResources() { return true; From f268aa9e3a1ac5427f1813da6982c303c804c723 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Mon, 19 Aug 2024 12:49:40 +0200 Subject: [PATCH 12/12] refactor: remove now useless DefaultInformable Signed-off-by: Chris Laprun --- .../api/config/BaseConfigurationService.java | 2 +- .../api/config/ControllerConfiguration.java | 10 ----- .../ControllerConfigurationOverrider.java | 2 +- .../api/config/DefaultInformable.java | 41 ------------------- .../ResolvedControllerConfiguration.java | 21 ++++++---- .../InformerEventSourceConfiguration.java | 24 +++++------ .../controller/ControllerEventSourceTest.java | 1 - .../runtime/DefaultConfigurationService.java | 3 +- 8 files changed, 26 insertions(+), 78 deletions(-) delete mode 100644 operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultInformable.java diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/BaseConfigurationService.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/BaseConfigurationService.java index 20beef7f90..4204cb6faf 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/BaseConfigurationService.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/BaseConfigurationService.java @@ -280,7 +280,7 @@ private

ResolvedControllerConfiguration

controllerCon .buildForController(); return new ResolvedControllerConfiguration

( - resourceClass, name, generationAware, + name, generationAware, associatedReconcilerClass, retry, rateLimiter, ResolvedControllerConfiguration.getMaxReconciliationInterval(interval, timeUnit), valueOrDefaultFromAnnotation(annotation, diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java index da3d27f18f..e03cf5626e 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java @@ -74,16 +74,6 @@ default Optional maxReconciliationInterval() { ConfigurationService getConfigurationService(); - @SuppressWarnings("unchecked") - @Override - default Class

getResourceClass() { - // note that this implementation at the end not used within the boundaries of the core - // framework, should be removed in the future, (and marked as an API changed, or behavior - // change) - return (Class

) Utils.getFirstTypeArgumentFromSuperClassOrInterface(getClass(), - ControllerConfiguration.class); - } - @SuppressWarnings("unused") default Set getEffectiveNamespaces() { return getInformerConfig().getEffectiveNamespaces(this); diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverrider.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverrider.java index 6740e86022..3d3eef5990 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverrider.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverrider.java @@ -187,7 +187,7 @@ public ControllerConfigurationOverrider replacingNamedDependentResourceConfig } public ControllerConfiguration build() { - return new ResolvedControllerConfiguration<>(original.getResourceClass(), + return new ResolvedControllerConfiguration<>( name, generationAware, original.getAssociatedReconcilerClassName(), retry, rateLimiter, reconciliationMaxInterval, diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultInformable.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultInformable.java deleted file mode 100644 index 5ab1a57bd0..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultInformable.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.javaoperatorsdk.operator.api.config; - - -import io.fabric8.kubernetes.api.model.GenericKubernetesResource; -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.ReconcilerUtils; -import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; - -public class DefaultInformable - implements Informable { - - private final Class resourceClass; - private final String resourceTypeName; - private final InformerConfiguration informerConfig; - - protected DefaultInformable(Class resourceClass, - InformerConfiguration informerConfig) { - this.resourceClass = resourceClass; - this.resourceTypeName = resourceClass.isAssignableFrom(GenericKubernetesResource.class) - // in general this is irrelevant now for secondary resources it is used just by controller - // where GenericKubernetesResource now does not apply - ? GenericKubernetesResource.class.getSimpleName() - : ReconcilerUtils.getResourceTypeName(resourceClass); - this.informerConfig = informerConfig; - } - - @Override - public String getResourceTypeName() { - return resourceTypeName; - } - - @Override - public Class getResourceClass() { - return resourceClass; - } - - @Override - public InformerConfiguration getInformerConfig() { - return informerConfig; - } -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResolvedControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResolvedControllerConfiguration.java index e60ea1b87c..7e8415f584 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResolvedControllerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResolvedControllerConfiguration.java @@ -16,9 +16,9 @@ @SuppressWarnings("rawtypes") public class ResolvedControllerConfiguration

- extends DefaultInformable

implements io.javaoperatorsdk.operator.api.config.ControllerConfiguration

{ + private final InformerConfiguration

informerConfig; private final String name; private final boolean generationAware; private final String associatedReconcilerClassName; @@ -31,8 +31,8 @@ public class ResolvedControllerConfiguration

private final String fieldManager; private WorkflowSpec workflowSpec; - public ResolvedControllerConfiguration(Class

resourceClass, ControllerConfiguration

other) { - this(resourceClass, other.getName(), other.isGenerationAware(), + public ResolvedControllerConfiguration(ControllerConfiguration

other) { + this(other.getName(), other.isGenerationAware(), other.getAssociatedReconcilerClassName(), other.getRetry(), other.getRateLimiter(), other.maxReconciliationInterval().orElse(null), other.getFinalizerName(), Collections.emptyMap(), @@ -42,7 +42,7 @@ public ResolvedControllerConfiguration(Class

resourceClass, ControllerConfigu other.getWorkflowSpec().orElse(null)); } - public ResolvedControllerConfiguration(Class

resourceClass, String name, + public ResolvedControllerConfiguration(String name, boolean generationAware, String associatedReconcilerClassName, Retry retry, RateLimiter rateLimiter, Duration maxReconciliationInterval, String finalizer, @@ -51,19 +51,19 @@ public ResolvedControllerConfiguration(Class

resourceClass, String name, ConfigurationService configurationService, InformerConfiguration

informerConfig, WorkflowSpec workflowSpec) { - this(resourceClass, name, generationAware, associatedReconcilerClassName, retry, rateLimiter, + this(name, generationAware, associatedReconcilerClassName, retry, rateLimiter, maxReconciliationInterval, finalizer, configurations, fieldManager, configurationService, informerConfig); setWorkflowSpec(workflowSpec); } - protected ResolvedControllerConfiguration(Class

resourceClass, String name, + protected ResolvedControllerConfiguration(String name, boolean generationAware, String associatedReconcilerClassName, Retry retry, RateLimiter rateLimiter, Duration maxReconciliationInterval, String finalizer, Map configurations, String fieldManager, ConfigurationService configurationService, InformerConfiguration

informerConfig) { - super(resourceClass, informerConfig); + this.informerConfig = informerConfig; this.configurationService = configurationService; this.name = ControllerConfiguration.ensureValidName(name, associatedReconcilerClassName); this.generationAware = generationAware; @@ -79,11 +79,16 @@ protected ResolvedControllerConfiguration(Class

resourceClass, String name, protected ResolvedControllerConfiguration(Class

resourceClass, String name, Class reconcilerClas, ConfigurationService configurationService) { - this(resourceClass, name, false, getAssociatedReconcilerClassName(reconcilerClas), null, null, + this(name, false, getAssociatedReconcilerClassName(reconcilerClas), null, null, null, null, null, null, configurationService, InformerConfiguration.builder(resourceClass).buildForController()); } + @Override + public InformerConfiguration

getInformerConfig() { + return informerConfig; + } + public static Duration getMaxReconciliationInterval(long interval, TimeUnit timeUnit) { return interval > 0 ? Duration.of(interval, timeUnit.toChronoUnit()) : null; } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java index 827bd6c57b..20e6c7f131 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java @@ -6,9 +6,7 @@ import io.fabric8.kubernetes.api.model.GenericKubernetesResource; import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.api.config.DefaultInformable; import io.javaoperatorsdk.operator.api.config.Informable; -import io.javaoperatorsdk.operator.api.config.Utils; import io.javaoperatorsdk.operator.processing.GroupVersionKind; import io.javaoperatorsdk.operator.processing.event.source.PrimaryToSecondaryMapper; import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper; @@ -59,31 +57,29 @@ default String name() { return getInformerConfig().getName(); } - @SuppressWarnings("unchecked") - @Override - default Class getResourceClass() { - return (Class) Utils.getFirstTypeArgumentFromSuperClassOrInterface(getClass(), - InformerEventSourceConfiguration.class); - } - - class DefaultInformerEventSourceConfiguration extends - DefaultInformable implements InformerEventSourceConfiguration { + class DefaultInformerEventSourceConfiguration + implements InformerEventSourceConfiguration { private final PrimaryToSecondaryMapper primaryToSecondaryMapper; private final SecondaryToPrimaryMapper secondaryToPrimaryMapper; private final GroupVersionKind groupVersionKind; + private final InformerConfiguration informerConfig; protected DefaultInformerEventSourceConfiguration( - Class resourceClass, GroupVersionKind groupVersionKind, PrimaryToSecondaryMapper primaryToSecondaryMapper, SecondaryToPrimaryMapper secondaryToPrimaryMapper, InformerConfiguration informerConfig) { - super(resourceClass, informerConfig); + this.informerConfig = Objects.requireNonNull(informerConfig); this.groupVersionKind = groupVersionKind; this.primaryToSecondaryMapper = primaryToSecondaryMapper; this.secondaryToPrimaryMapper = secondaryToPrimaryMapper; } + @Override + public InformerConfiguration getInformerConfig() { + return informerConfig; + } + @Override public SecondaryToPrimaryMapper getSecondaryToPrimaryMapper() { return secondaryToPrimaryMapper; @@ -190,7 +186,7 @@ public InformerEventSourceConfiguration build() { "If GroupVersionKind is set the resource type must be GenericKubernetesDependentResource"); } - return new DefaultInformerEventSourceConfiguration<>(resourceClass, + return new DefaultInformerEventSourceConfiguration<>( groupVersionKind, primaryToSecondaryMapper, Objects.requireNonNullElse(secondaryToPrimaryMapper, diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSourceTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSourceTest.java index 5282fd2138..4ba2a5184c 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSourceTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSourceTest.java @@ -191,7 +191,6 @@ public TestConfiguration(boolean generationAware, OnAddFilter onUpdateFilter, GenericFilter genericFilter) { super( - TestCustomResource.class, "test", generationAware, null, diff --git a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/DefaultConfigurationService.java b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/DefaultConfigurationService.java index 12573b50f7..1a1214aa78 100644 --- a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/DefaultConfigurationService.java +++ b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/DefaultConfigurationService.java @@ -11,7 +11,6 @@ public class DefaultConfigurationService extends BaseConfigurationService { @Override protected ControllerConfiguration configFor(Reconciler reconciler) { final var other = super.configFor(reconciler); - return new ResolvedControllerConfiguration<>( - RuntimeControllerMetadata.getResourceClass(reconciler), other); + return new ResolvedControllerConfiguration<>(other); } }