From 43f87eae5b43db0d637ced3d2a10001551e24ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Wed, 24 Apr 2024 14:07:26 +0200 Subject: [PATCH 1/6] feat: feature flag to clone secondary resource on access 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 | 10 ++++++++++ .../api/config/ConfigurationServiceOverrider.java | 12 ++++++++++++ .../event/source/informer/InformerManager.java | 4 +++- .../operator/sample/WebPageReconciler.java | 9 ++++----- .../operator/sample/WebPageOperatorE2E.java | 2 ++ 5 files changed, 31 insertions(+), 6 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 fa502e043b..172e9863d7 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 @@ -404,4 +404,14 @@ default boolean useSSAToPatchPrimaryResource() { return true; } + /** + * By default, secondary resources are cloned when returned from the cache. This might have a + * performance impact, and if reconciler relies on SSA it is not needed to do. Since the goal of + * the cloning is to prevent modification on the object in the cache, that would no longer reflect + * the state on the server in that case. + */ + default boolean cloneSecondaryResources() { + return true; + } + } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverrider.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverrider.java index d4aa430800..5150b12859 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverrider.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverrider.java @@ -40,6 +40,7 @@ public class ConfigurationServiceOverrider { private Boolean previousAnnotationForDependentResources; private Boolean parseResourceVersions; private Boolean useSSAToPatchPrimaryResource; + private Boolean cloneSecondaryResources; private DependentResourceFactory dependentResourceFactory; ConfigurationServiceOverrider(ConfigurationService original) { @@ -180,6 +181,11 @@ public ConfigurationServiceOverrider withUseSSAToPatchPrimaryResource(boolean va return this; } + public ConfigurationServiceOverrider withCloneSecondaryResources(boolean value) { + this.cloneSecondaryResources = value; + return this; + } + public ConfigurationService build() { return new BaseConfigurationService(original.getVersion(), cloner, client) { @Override @@ -323,6 +329,12 @@ public boolean useSSAToPatchPrimaryResource() { : super.useSSAToPatchPrimaryResource(); } + + @Override + public boolean cloneSecondaryResources() { + return cloneSecondaryResources != null ? cloneSecondaryResources + : super.cloneSecondaryResources(); + } }; } 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 e68cd3ab25..93e1182d34 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 @@ -170,7 +170,9 @@ public Stream list(String namespace, Predicate predicate) { public Optional get(ResourceID resourceID) { return getSource(resourceID.getNamespace().orElse(WATCH_ALL_NAMESPACES)) .flatMap(source -> source.get(resourceID)) - .map(r -> configurationService.getResourceCloner().clone(r)); + .map(r -> configurationService.cloneSecondaryResources() + ? configurationService.getResourceCloner().clone(r) + : r); } @Override diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageReconciler.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageReconciler.java index 46bc3dd392..8b4e38ce6d 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageReconciler.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageReconciler.java @@ -12,7 +12,6 @@ import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.networking.v1.Ingress; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.dsl.Replaceable; import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.*; @@ -90,7 +89,7 @@ public UpdateControl reconcile(WebPage webPage, Context contex desiredHtmlConfigMap.getMetadata().getName(), ns); kubernetesClient.configMaps().inNamespace(ns).resource(desiredHtmlConfigMap) - .createOr(Replaceable::update); + .serverSideApply(); } var existingDeployment = context.getSecondaryResource(Deployment.class).orElse(null); @@ -100,7 +99,7 @@ public UpdateControl reconcile(WebPage webPage, Context contex desiredDeployment.getMetadata().getName(), ns); kubernetesClient.apps().deployments().inNamespace(ns).resource(desiredDeployment) - .createOr(Replaceable::update); + .serverSideApply(); } var existingService = context.getSecondaryResource(Service.class).orElse(null); @@ -110,14 +109,14 @@ public UpdateControl reconcile(WebPage webPage, Context contex desiredDeployment.getMetadata().getName(), ns); kubernetesClient.services().inNamespace(ns).resource(desiredService) - .createOr(Replaceable::update); + .serverSideApply(); } var existingIngress = context.getSecondaryResource(Ingress.class); if (Boolean.TRUE.equals(webPage.getSpec().getExposed())) { var desiredIngress = makeDesiredIngress(webPage); if (existingIngress.isEmpty() || !match(desiredIngress, existingIngress.get())) { - kubernetesClient.resource(desiredIngress).inNamespace(ns).createOr(Replaceable::update); + kubernetesClient.resource(desiredIngress).inNamespace(ns).serverSideApply(); } } else existingIngress.ifPresent( diff --git a/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorE2E.java b/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorE2E.java index 03c3d2c2e0..e5f5cd404a 100644 --- a/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorE2E.java +++ b/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorE2E.java @@ -26,10 +26,12 @@ public WebPageOperatorE2E() throws FileNotFoundException {} AbstractOperatorExtension operator = isLocal() ? LocallyRunOperatorExtension.builder() + .withConfigurationService(o -> o.withCloneSecondaryResources(false)) .waitForNamespaceDeletion(false) .withReconciler(new WebPageReconciler(client)) .build() : ClusterDeployedOperatorExtension.builder() + .withConfigurationService(o -> o.withCloneSecondaryResources(false)) .waitForNamespaceDeletion(false) .withOperatorDeployment(client.load(new FileInputStream("k8s/operator.yaml")).items(), resources -> { From ada9f951964c8972d833d9f381769eaced72e436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Wed, 24 Apr 2024 14:15:55 +0200 Subject: [PATCH 2/6] naming and docs improvements 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 | 11 ++++++----- .../api/config/ConfigurationServiceOverrider.java | 14 ++++++++------ .../processing/event/ReconciliationDispatcher.java | 1 - .../event/source/informer/InformerManager.java | 2 +- .../operator/sample/WebPageOperatorE2E.java | 6 ++++-- 5 files changed, 19 insertions(+), 15 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 172e9863d7..289c803598 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 @@ -405,12 +405,13 @@ default boolean useSSAToPatchPrimaryResource() { } /** - * By default, secondary resources are cloned when returned from the cache. This might have a - * performance impact, and if reconciler relies on SSA it is not needed to do. Since the goal of - * the cloning is to prevent modification on the object in the cache, that would no longer reflect - * the state on the server in that case. + * By default, secondary resources are cloned when returned from the cache. + * ({@link io.javaoperatorsdk.operator.api.reconciler.Context#getSecondaryResource(Class)}) This + * might have a performance impact, and if reconciler relies on SSA it is not needed to do. Since + * the goal of the cloning is to prevent modification on the object in the cache, that would no + * longer reflect the state on the server in that case. */ - default boolean cloneSecondaryResources() { + default boolean cloneSecondaryResourcesWhenGettingFromCache() { return true; } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverrider.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverrider.java index 5150b12859..6cc0cc5469 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverrider.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverrider.java @@ -40,7 +40,7 @@ public class ConfigurationServiceOverrider { private Boolean previousAnnotationForDependentResources; private Boolean parseResourceVersions; private Boolean useSSAToPatchPrimaryResource; - private Boolean cloneSecondaryResources; + private Boolean cloneSecondaryResourcesWhenGettingFromCache; private DependentResourceFactory dependentResourceFactory; ConfigurationServiceOverrider(ConfigurationService original) { @@ -181,8 +181,9 @@ public ConfigurationServiceOverrider withUseSSAToPatchPrimaryResource(boolean va return this; } - public ConfigurationServiceOverrider withCloneSecondaryResources(boolean value) { - this.cloneSecondaryResources = value; + public ConfigurationServiceOverrider withCloneSecondaryResourcesWhenGettingFromCache( + boolean value) { + this.cloneSecondaryResourcesWhenGettingFromCache = value; return this; } @@ -331,9 +332,10 @@ public boolean useSSAToPatchPrimaryResource() { } @Override - public boolean cloneSecondaryResources() { - return cloneSecondaryResources != null ? cloneSecondaryResources - : super.cloneSecondaryResources(); + public boolean cloneSecondaryResourcesWhenGettingFromCache() { + return cloneSecondaryResourcesWhenGettingFromCache != null + ? cloneSecondaryResourcesWhenGettingFromCache + : super.cloneSecondaryResourcesWhenGettingFromCache(); } }; } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java index 752e3ed0c2..531917adac 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java @@ -361,7 +361,6 @@ private P patchResource(P resource, P originalResource) { getVersion(resource)); log.trace("Resource before update: {}", resource); - // todo unit test final var finalizerName = configuration().getFinalizerName(); if (useSSA && controller.useFinalizer()) { // addFinalizer already prevents adding an already present finalizer so no need to check 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 93e1182d34..a97897b1fa 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 @@ -170,7 +170,7 @@ public Stream list(String namespace, Predicate predicate) { public Optional get(ResourceID resourceID) { return getSource(resourceID.getNamespace().orElse(WATCH_ALL_NAMESPACES)) .flatMap(source -> source.get(resourceID)) - .map(r -> configurationService.cloneSecondaryResources() + .map(r -> configurationService.cloneSecondaryResourcesWhenGettingFromCache() ? configurationService.getResourceCloner().clone(r) : r); } diff --git a/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorE2E.java b/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorE2E.java index e5f5cd404a..b0a6a94706 100644 --- a/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorE2E.java +++ b/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorE2E.java @@ -26,12 +26,14 @@ public WebPageOperatorE2E() throws FileNotFoundException {} AbstractOperatorExtension operator = isLocal() ? LocallyRunOperatorExtension.builder() - .withConfigurationService(o -> o.withCloneSecondaryResources(false)) + .withConfigurationService( + o -> o.withCloneSecondaryResourcesWhenGettingFromCache(false)) .waitForNamespaceDeletion(false) .withReconciler(new WebPageReconciler(client)) .build() : ClusterDeployedOperatorExtension.builder() - .withConfigurationService(o -> o.withCloneSecondaryResources(false)) + .withConfigurationService( + o -> o.withCloneSecondaryResourcesWhenGettingFromCache(false)) .waitForNamespaceDeletion(false) .withOperatorDeployment(client.load(new FileInputStream("k8s/operator.yaml")).items(), resources -> { From 7eb8f50ad30040f1ecf9df8ddb81d9efa3da4618 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Thu, 25 Apr 2024 16:57:56 +0200 Subject: [PATCH 3/6] changing to not clone resources by default 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 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 289c803598..c2dc9cddd6 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 @@ -412,7 +412,7 @@ default boolean useSSAToPatchPrimaryResource() { * longer reflect the state on the server in that case. */ default boolean cloneSecondaryResourcesWhenGettingFromCache() { - return true; + return false; } } From a34cb4d63867c5985731382d1815074f1f13cb71 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Tue, 30 Apr 2024 17:56:05 +0200 Subject: [PATCH 4/6] docs: improve javadoc Signed-off-by: Chris Laprun --- .../api/config/ConfigurationService.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 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 c2dc9cddd6..93985bd556 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 @@ -20,6 +20,7 @@ import io.fabric8.kubernetes.client.KubernetesClientBuilder; import io.fabric8.kubernetes.client.utils.KubernetesSerialization; import io.javaoperatorsdk.operator.api.monitoring.Metrics; +import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResourceFactory; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; @@ -396,7 +397,8 @@ default boolean parseResourceVersionsForEventFilteringAndCaching() { * either use simple patches or SSA. Setting this to {@code true}, controllers will use SSA for * adding finalizers, managing observed generation, patching resources and status. * - * @return {@code true} by default + * @return {@code true} if Server-Side Apply (SSA) should be used when patching the primary + * resources, {@code false} otherwise * @since 5.0.0 * @see ConfigurationServiceOverrider#withUseSSAToPatchPrimaryResource(boolean) */ @@ -405,11 +407,23 @@ default boolean useSSAToPatchPrimaryResource() { } /** - * By default, secondary resources are cloned when returned from the cache. - * ({@link io.javaoperatorsdk.operator.api.reconciler.Context#getSecondaryResource(Class)}) This - * might have a performance impact, and if reconciler relies on SSA it is not needed to do. Since - * the goal of the cloning is to prevent modification on the object in the cache, that would no - * longer reflect the state on the server in that case. + *

+ * Determines whether resources retrieved from caches such as via calls to + * {@link Context#getSecondaryResource(Class)} should be defensively cloned first. + *

+ * + *

+ * Defensive cloning to prevent problematic cache modifications (modifying the resource would + * otherwise modify the stored copy in the cache) was transparently done in previous JOSDK + * versions. This might have performance consequences and, with the more prevalent use of + * Server-Side Apply, where you should create a new copy of your resource with only modified + * fields, such modifications of these resources are less likely to occur. + *

+ * + * @return {@code true} if resources should be defensively cloned before returning them from + * caches, {@code false} otherwise + * + * @since 5.0.0 */ default boolean cloneSecondaryResourcesWhenGettingFromCache() { return false; From 376e74ac79181748d8d174db2eb8d9132efa2427 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Tue, 30 Apr 2024 17:56:41 +0200 Subject: [PATCH 5/6] fix: no need to set the cloning flag since false is now the default Signed-off-by: Chris Laprun --- .../javaoperatorsdk/operator/sample/WebPageOperatorE2E.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorE2E.java b/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorE2E.java index b0a6a94706..03c3d2c2e0 100644 --- a/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorE2E.java +++ b/sample-operators/webpage/src/test/java/io/javaoperatorsdk/operator/sample/WebPageOperatorE2E.java @@ -26,14 +26,10 @@ public WebPageOperatorE2E() throws FileNotFoundException {} AbstractOperatorExtension operator = isLocal() ? LocallyRunOperatorExtension.builder() - .withConfigurationService( - o -> o.withCloneSecondaryResourcesWhenGettingFromCache(false)) .waitForNamespaceDeletion(false) .withReconciler(new WebPageReconciler(client)) .build() : ClusterDeployedOperatorExtension.builder() - .withConfigurationService( - o -> o.withCloneSecondaryResourcesWhenGettingFromCache(false)) .waitForNamespaceDeletion(false) .withOperatorDeployment(client.load(new FileInputStream("k8s/operator.yaml")).items(), resources -> { From bb660854a44009d2e0aba4c973dd59cb83a75afc Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Tue, 30 Apr 2024 18:23:30 +0200 Subject: [PATCH 6/6] fix: enforce returning value from original config if not overridden Signed-off-by: Chris Laprun --- .../config/ConfigurationServiceOverrider.java | 81 ++++++++++--------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverrider.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverrider.java index 6cc0cc5469..add050c6f0 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverrider.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverrider.java @@ -5,6 +5,7 @@ import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.function.Consumer; +import java.util.function.Function; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -194,22 +195,29 @@ public Set getKnownReconcilerNames() { return original.getKnownReconcilerNames(); } + private T overriddenValueOrDefault(T value, + Function defaultValue) { + return value != null ? value : defaultValue.apply(original); + } + @Override public boolean checkCRDAndValidateLocalModel() { - return checkCR != null ? checkCR : original.checkCRDAndValidateLocalModel(); + return overriddenValueOrDefault(checkCR, + ConfigurationService::checkCRDAndValidateLocalModel); } @Override + @SuppressWarnings("rawtypes") public DependentResourceFactory dependentResourceFactory() { - return dependentResourceFactory != null ? dependentResourceFactory - : DependentResourceFactory.DEFAULT; + return overriddenValueOrDefault(dependentResourceFactory, + ConfigurationService::dependentResourceFactory); } @Override public int concurrentReconciliationThreads() { return Utils.ensureValid( - concurrentReconciliationThreads != null ? concurrentReconciliationThreads - : original.concurrentReconciliationThreads(), + overriddenValueOrDefault(concurrentReconciliationThreads, + ConfigurationService::concurrentReconciliationThreads), "maximum reconciliation threads", minimumMaxValueFor(minConcurrentReconciliationThreads), original.concurrentReconciliationThreads()); @@ -218,8 +226,8 @@ public int concurrentReconciliationThreads() { @Override public int concurrentWorkflowExecutorThreads() { return Utils.ensureValid( - concurrentWorkflowExecutorThreads != null ? concurrentWorkflowExecutorThreads - : original.concurrentWorkflowExecutorThreads(), + overriddenValueOrDefault(concurrentWorkflowExecutorThreads, + ConfigurationService::concurrentWorkflowExecutorThreads), "maximum workflow execution threads", minimumMaxValueFor(minConcurrentWorkflowExecutorThreads), original.concurrentWorkflowExecutorThreads()); @@ -231,8 +239,8 @@ public int concurrentWorkflowExecutorThreads() { @Deprecated(forRemoval = true) @Override public int minConcurrentReconciliationThreads() { - return minConcurrentReconciliationThreads != null ? minConcurrentReconciliationThreads - : original.minConcurrentReconciliationThreads(); + return overriddenValueOrDefault(minConcurrentReconciliationThreads, + ConfigurationService::minConcurrentReconciliationThreads); } /** @@ -241,30 +249,29 @@ public int minConcurrentReconciliationThreads() { @Override @Deprecated(forRemoval = true) public int minConcurrentWorkflowExecutorThreads() { - return minConcurrentWorkflowExecutorThreads != null ? minConcurrentWorkflowExecutorThreads - : original.minConcurrentWorkflowExecutorThreads(); + return overriddenValueOrDefault(minConcurrentWorkflowExecutorThreads, + ConfigurationService::minConcurrentWorkflowExecutorThreads); } @Override public Metrics getMetrics() { - return metrics != null ? metrics : original.getMetrics(); + return overriddenValueOrDefault(metrics, ConfigurationService::getMetrics); } @Override public boolean closeClientOnStop() { - return closeClientOnStop != null ? closeClientOnStop : original.closeClientOnStop(); + return overriddenValueOrDefault(closeClientOnStop, ConfigurationService::closeClientOnStop); } @Override public ExecutorService getExecutorService() { - return executorService != null ? executorService - : super.getExecutorService(); + return overriddenValueOrDefault(executorService, ConfigurationService::getExecutorService); } @Override public ExecutorService getWorkflowExecutorService() { - return workflowExecutorService != null ? workflowExecutorService - : super.getWorkflowExecutorService(); + return overriddenValueOrDefault(workflowExecutorService, + ConfigurationService::getWorkflowExecutorService); } @Override @@ -281,61 +288,55 @@ public Optional getInformerStoppedHandler() { @Override public boolean stopOnInformerErrorDuringStartup() { - return stopOnInformerErrorDuringStartup != null ? stopOnInformerErrorDuringStartup - : super.stopOnInformerErrorDuringStartup(); + return overriddenValueOrDefault(stopOnInformerErrorDuringStartup, + ConfigurationService::stopOnInformerErrorDuringStartup); } @Override public Duration cacheSyncTimeout() { - return cacheSyncTimeout != null ? cacheSyncTimeout : super.cacheSyncTimeout(); + return overriddenValueOrDefault(cacheSyncTimeout, ConfigurationService::cacheSyncTimeout); } @Override public ResourceClassResolver getResourceClassResolver() { - return resourceClassResolver != null ? resourceClassResolver - : super.getResourceClassResolver(); + return overriddenValueOrDefault(resourceClassResolver, + ConfigurationService::getResourceClassResolver); } @Override public boolean ssaBasedCreateUpdateMatchForDependentResources() { - return ssaBasedCreateUpdateMatchForDependentResources != null - ? ssaBasedCreateUpdateMatchForDependentResources - : super.ssaBasedCreateUpdateMatchForDependentResources(); + return overriddenValueOrDefault(ssaBasedCreateUpdateMatchForDependentResources, + ConfigurationService::ssaBasedCreateUpdateMatchForDependentResources); } @Override public Set> defaultNonSSAResource() { - return defaultNonSSAResource != null ? defaultNonSSAResource - : super.defaultNonSSAResource(); + return overriddenValueOrDefault(defaultNonSSAResource, + ConfigurationService::defaultNonSSAResource); } @Override public boolean previousAnnotationForDependentResourcesEventFiltering() { - return previousAnnotationForDependentResources != null - ? previousAnnotationForDependentResources - : super.previousAnnotationForDependentResourcesEventFiltering(); + return overriddenValueOrDefault(previousAnnotationForDependentResources, + ConfigurationService::previousAnnotationForDependentResourcesEventFiltering); } @Override public boolean parseResourceVersionsForEventFilteringAndCaching() { - return parseResourceVersions != null - ? parseResourceVersions - : super.parseResourceVersionsForEventFilteringAndCaching(); + return overriddenValueOrDefault(parseResourceVersions, + ConfigurationService::parseResourceVersionsForEventFilteringAndCaching); } @Override public boolean useSSAToPatchPrimaryResource() { - return useSSAToPatchPrimaryResource != null - ? useSSAToPatchPrimaryResource - : super.useSSAToPatchPrimaryResource(); - + return overriddenValueOrDefault(useSSAToPatchPrimaryResource, + ConfigurationService::useSSAToPatchPrimaryResource); } @Override public boolean cloneSecondaryResourcesWhenGettingFromCache() { - return cloneSecondaryResourcesWhenGettingFromCache != null - ? cloneSecondaryResourcesWhenGettingFromCache - : super.cloneSecondaryResourcesWhenGettingFromCache(); + return overriddenValueOrDefault(cloneSecondaryResourcesWhenGettingFromCache, + ConfigurationService::cloneSecondaryResourcesWhenGettingFromCache); } }; }