From fdb86b07bb76ff89be0548d6b0dcefb8476e3f25 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Fri, 28 Oct 2022 16:35:07 +0200 Subject: [PATCH 1/2] refactor: move configuration processing to BaseConfigurationService Replaced all the different controller configuration implementations by only one: ResolvedControllerConfiguration. --- .../AnnotationControllerConfiguration.java | 259 ------------------ .../api/config/BaseConfigurationService.java | 222 ++++++++++++++- .../api/config/ControllerConfiguration.java | 32 ++- .../ControllerConfigurationOverrider.java | 25 +- .../DefaultControllerConfiguration.java | 156 ----------- .../config/DefaultResourceConfiguration.java | 35 +-- .../ResolvedControllerConfiguration.java | 157 +++++++++++ .../api/config/ResourceConfiguration.java | 14 + .../operator/api/config/Utils.java | 9 +- .../informer/InformerConfiguration.java | 10 +- .../operator/ControllerManagerTest.java | 23 +- .../ControllerConfigurationOverriderTest.java | 3 +- .../event/source/ResourceEventFilterTest.java | 20 +- .../ControllerResourceEventSourceTest.java | 27 +- .../AnnotationControllerConfiguration.java | 17 -- .../runtime/DefaultConfigurationService.java | 5 +- ...java => BaseConfigurationServiceTest.java} | 51 ++-- 17 files changed, 526 insertions(+), 539 deletions(-) delete mode 100644 operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AnnotationControllerConfiguration.java delete mode 100644 operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultControllerConfiguration.java create mode 100644 operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResolvedControllerConfiguration.java delete mode 100644 operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/AnnotationControllerConfiguration.java rename operator-framework/src/test/java/io/javaoperatorsdk/operator/config/{runtime/AnnotationControllerConfigurationTest.java => BaseConfigurationServiceTest.java} (90%) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AnnotationControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AnnotationControllerConfiguration.java deleted file mode 100644 index 4e4f945515..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AnnotationControllerConfiguration.java +++ /dev/null @@ -1,259 +0,0 @@ -package io.javaoperatorsdk.operator.api.config; - -import java.lang.annotation.Annotation; -import java.time.Duration; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.function.Function; -import java.util.function.UnaryOperator; -import java.util.stream.Collectors; - -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.OperatorException; -import io.javaoperatorsdk.operator.ReconcilerUtils; -import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; -import io.javaoperatorsdk.operator.api.reconciler.Constants; -import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; -import io.javaoperatorsdk.operator.api.reconciler.Reconciler; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent; -import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; -import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition; -import io.javaoperatorsdk.operator.processing.event.rate.RateLimiter; -import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter; -import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilters; -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 io.javaoperatorsdk.operator.processing.retry.Retry; - -import static io.javaoperatorsdk.operator.api.reconciler.Constants.DEFAULT_NAMESPACES_SET; - -@SuppressWarnings("rawtypes") -public class AnnotationControllerConfiguration

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

{ - - protected final Reconciler

reconciler; - private final ControllerConfiguration annotation; - private List specs; - private Class

resourceClass; - - public AnnotationControllerConfiguration(Reconciler

reconciler) { - this.reconciler = reconciler; - this.annotation = reconciler.getClass().getAnnotation(ControllerConfiguration.class); - if (annotation == null) { - throw new OperatorException( - "Missing mandatory @" + ControllerConfiguration.class.getSimpleName() + - " annotation for reconciler: " + reconciler); - } - } - - @Override - public String getName() { - return ReconcilerUtils.getNameFor(reconciler); - } - - @Override - public String getFinalizerName() { - if (annotation == null || annotation.finalizerName().isBlank()) { - return ReconcilerUtils.getDefaultFinalizerName(getResourceClass()); - } else { - final var finalizer = annotation.finalizerName(); - if (ReconcilerUtils.isFinalizerValid(finalizer)) { - return finalizer; - } else { - throw new IllegalArgumentException( - finalizer - + " is not a valid finalizer. See https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#finalizers for details"); - } - } - } - - @Override - public boolean isGenerationAware() { - return valueOrDefault( - annotation, ControllerConfiguration::generationAwareEventProcessing, true); - } - - @Override - public Set getNamespaces() { - return Set.of(valueOrDefault(annotation, ControllerConfiguration::namespaces, - DEFAULT_NAMESPACES_SET.toArray(String[]::new))); - } - - @Override - @SuppressWarnings("unchecked") - public Optional> cachePruneFunction() { - return Optional.ofNullable( - Utils.instantiate(annotation.cachePruneFunction(), UnaryOperator.class, - Utils.contextFor(this, null, null))); - } - - @Override - @SuppressWarnings("unchecked") - public Class

getResourceClass() { - if (resourceClass == null) { - resourceClass = - (Class

) Utils.getFirstTypeArgumentFromSuperClassOrInterface(reconciler.getClass(), - Reconciler.class); - } - return resourceClass; - } - - @Override - public String getLabelSelector() { - return valueOrDefault(annotation, ControllerConfiguration::labelSelector, ""); - } - - @Override - public String getAssociatedReconcilerClassName() { - return reconciler.getClass().getCanonicalName(); - } - - @SuppressWarnings("unchecked") - @Override - public ResourceEventFilter

getEventFilter() { - ResourceEventFilter

answer = null; - - Class>[] filterTypes = - (Class>[]) valueOrDefault(annotation, - ControllerConfiguration::eventFilters, new Object[] {}); - for (var filterType : filterTypes) { - try { - ResourceEventFilter

filter = filterType.getConstructor().newInstance(); - - if (answer == null) { - answer = filter; - } else { - answer = answer.and(filter); - } - } catch (Exception e) { - throw new IllegalArgumentException(e); - } - } - return answer != null ? answer : ResourceEventFilters.passthrough(); - } - - @Override - public Optional maxReconciliationInterval() { - final var newConfig = annotation.maxReconciliationInterval(); - if (newConfig != null && newConfig.interval() > 0) { - return Optional.of(Duration.of(newConfig.interval(), newConfig.timeUnit().toChronoUnit())); - } - return Optional.empty(); - } - - @Override - public RateLimiter getRateLimiter() { - final Class rateLimiterClass = annotation.rateLimiter(); - return Utils.instantiateAndConfigureIfNeeded(rateLimiterClass, RateLimiter.class, - Utils.contextFor(this, null, null), this::configureFromAnnotatedReconciler); - } - - @Override - public Retry getRetry() { - final Class retryClass = annotation.retry(); - return Utils.instantiateAndConfigureIfNeeded(retryClass, Retry.class, - Utils.contextFor(this, null, null), this::configureFromAnnotatedReconciler); - } - - - @SuppressWarnings("unchecked") - private void configureFromAnnotatedReconciler(Object instance) { - if (instance instanceof AnnotationConfigurable) { - AnnotationConfigurable configurable = (AnnotationConfigurable) instance; - final Class configurationClass = - (Class) Utils.getFirstTypeArgumentFromSuperClassOrInterface( - instance.getClass(), AnnotationConfigurable.class); - final var configAnnotation = reconciler.getClass().getAnnotation(configurationClass); - if (configAnnotation != null) { - configurable.initFrom(configAnnotation); - } - } - } - - @Override - @SuppressWarnings("unchecked") - public Optional> onAddFilter() { - return Optional.ofNullable( - Utils.instantiate(annotation.onAddFilter(), OnAddFilter.class, - Utils.contextFor(this, null, null))); - } - - @SuppressWarnings("unchecked") - @Override - public Optional> onUpdateFilter() { - return Optional.ofNullable( - Utils.instantiate(annotation.onUpdateFilter(), OnUpdateFilter.class, - Utils.contextFor(this, null, null))); - } - - @SuppressWarnings("unchecked") - @Override - public Optional> genericFilter() { - return Optional.ofNullable( - Utils.instantiate(annotation.genericFilter(), GenericFilter.class, - Utils.contextFor(this, null, null))); - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - @Override - public List getDependentResources() { - if (specs == null) { - final var dependents = - valueOrDefault(annotation, ControllerConfiguration::dependents, new Dependent[] {}); - if (dependents.length == 0) { - specs = Collections.emptyList(); - return specs; - } - - final var specsMap = new LinkedHashMap(dependents.length); - for (Dependent dependent : dependents) { - final Class dependentType = dependent.type(); - - final var name = getName(dependent, dependentType); - var spec = specsMap.get(name); - if (spec != null) { - throw new IllegalArgumentException( - "A DependentResource named '" + name + "' already exists: " + spec); - } - - var eventSourceName = dependent.useEventSourceWithName(); - eventSourceName = Constants.NO_VALUE_SET.equals(eventSourceName) ? null : eventSourceName; - final var context = Utils.contextFor(this, dependentType, null); - spec = new DependentResourceSpec(dependentType, name, - Set.of(dependent.dependsOn()), - Utils.instantiate(dependent.readyPostcondition(), Condition.class, context), - Utils.instantiate(dependent.reconcilePrecondition(), Condition.class, context), - Utils.instantiate(dependent.deletePostcondition(), Condition.class, context), - eventSourceName); - specsMap.put(name, spec); - } - - specs = specsMap.values().stream().collect(Collectors.toUnmodifiableList()); - } - return specs; - } - - private String getName(Dependent dependent, Class dependentType) { - var name = dependent.name(); - if (name.isBlank()) { - name = DependentResource.defaultNameFor(dependentType); - } - return name; - } - - public static T valueOrDefault( - ControllerConfiguration controllerConfiguration, - Function mapper, - T defaultValue) { - if (controllerConfiguration == null) { - return defaultValue; - } else { - return mapper.apply(controllerConfiguration); - } - } - -} 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 1e4b535202..4e585ed3f7 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 @@ -1,13 +1,41 @@ package io.javaoperatorsdk.operator.api.config; +import java.lang.annotation.Annotation; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.function.UnaryOperator; +import java.util.stream.Collectors; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import io.fabric8.kubernetes.api.model.HasMetadata; +import io.javaoperatorsdk.operator.OperatorException; +import io.javaoperatorsdk.operator.ReconcilerUtils; +import io.javaoperatorsdk.operator.api.config.Utils.Configurator; +import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; +import io.javaoperatorsdk.operator.api.reconciler.Constants; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; +import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent; +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.AnnotationDependentResourceConfigurator; +import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition; +import io.javaoperatorsdk.operator.processing.event.rate.RateLimiter; +import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter; +import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilters; +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 io.javaoperatorsdk.operator.processing.retry.Retry; import com.fasterxml.jackson.databind.ObjectMapper; +import static io.javaoperatorsdk.operator.api.reconciler.Constants.DEFAULT_NAMESPACES_SET; + public class BaseConfigurationService extends AbstractConfigurationService { private static final String LOGGER_NAME = "Default ConfigurationService implementation"; @@ -67,8 +95,143 @@ public ControllerConfiguration getConfigurationFor( return config; } - protected ControllerConfiguration configFor(Reconciler reconciler) { - return new AnnotationControllerConfiguration<>(reconciler); + @SuppressWarnings({"unchecked", "rawtypes"}) + protected

ControllerConfiguration

configFor(Reconciler

reconciler) { + final var annotation = reconciler.getClass().getAnnotation( + io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration.class); + if (annotation == null) { + throw new OperatorException( + "Missing mandatory @" + + io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration.class + .getSimpleName() + + + " annotation for reconciler: " + reconciler); + } + + final var resourceClass = (Class

) Utils.getFirstTypeArgumentFromSuperClassOrInterface( + reconciler.getClass(), Reconciler.class); + final var name = ReconcilerUtils.getNameFor(reconciler); + final var generationAware = valueOrDefault( + annotation, + io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration::generationAwareEventProcessing, + true); + final var associatedReconcilerClass = + ResolvedControllerConfiguration.getAssociatedReconcilerClassName(reconciler.getClass()); + + final Class retryClass = annotation.retry(); + final var retry = Utils.instantiateAndConfigureIfNeeded(retryClass, Retry.class, + Utils.contextFor(name, null, null), configuratorFor(Retry.class, reconciler)); + + final Class rateLimiterClass = annotation.rateLimiter(); + final var rateLimiter = Utils.instantiateAndConfigureIfNeeded(rateLimiterClass, + RateLimiter.class, + Utils.contextFor(name, null, null), configuratorFor(RateLimiter.class, reconciler)); + + final var reconciliationInterval = annotation.maxReconciliationInterval(); + long interval = -1; + TimeUnit timeUnit = null; + if (reconciliationInterval != null && reconciliationInterval.interval() > 0) { + interval = reconciliationInterval.interval(); + timeUnit = reconciliationInterval.timeUnit(); + } + + final var config = new ResolvedControllerConfiguration

( + resourceClass, name, generationAware, + associatedReconcilerClass, retry, rateLimiter, + ResolvedControllerConfiguration.getMaxReconciliationInterval(interval, timeUnit), + Utils.instantiate(annotation.onAddFilter(), OnAddFilter.class, + Utils.contextFor(name, null, null)), + Utils.instantiate(annotation.onUpdateFilter(), OnUpdateFilter.class, + Utils.contextFor(name, null, null)), + Utils.instantiate(annotation.genericFilter(), GenericFilter.class, + Utils.contextFor(name, null, null)), + Utils.instantiate(annotation.cachePruneFunction(), UnaryOperator.class, + Utils.contextFor(name, null, null)), + Set.of(valueOrDefault(annotation, + io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration::namespaces, + DEFAULT_NAMESPACES_SET.toArray(String[]::new))), + valueOrDefault(annotation, + io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration::finalizerName, + Constants.NO_VALUE_SET), + valueOrDefault(annotation, + io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration::labelSelector, + Constants.NO_VALUE_SET)); + + ResourceEventFilter

answer = deprecatedEventFilter(annotation); + config.setEventFilter(answer != null ? answer : ResourceEventFilters.passthrough()); + + List specs = dependentResources(annotation, config); + config.setDependentResources(specs); + + return config; + } + + @SuppressWarnings("unchecked") + private static

ResourceEventFilter

deprecatedEventFilter( + io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration annotation) { + ResourceEventFilter

answer = null; + + Class>[] filterTypes = + (Class>[]) valueOrDefault(annotation, + io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration::eventFilters, + new Object[] {}); + for (var filterType : filterTypes) { + try { + ResourceEventFilter

filter = filterType.getConstructor().newInstance(); + + if (answer == null) { + answer = filter; + } else { + answer = answer.and(filter); + } + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + return answer; + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private static List dependentResources( + io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration annotation, + ControllerConfiguration parent) { + final var dependents = + valueOrDefault(annotation, + io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration::dependents, + new Dependent[] {}); + if (dependents.length == 0) { + return Collections.emptyList(); + } + + final var specsMap = new LinkedHashMap(dependents.length); + for (Dependent dependent : dependents) { + final Class dependentType = dependent.type(); + + final var dependentName = getName(dependent.name(), dependentType); + var spec = specsMap.get(dependentName); + if (spec != null) { + throw new IllegalArgumentException( + "A DependentResource named '" + dependentName + "' already exists: " + spec); + } + + final var name = parent.getName(); + final var dependentResource = Utils.instantiateAndConfigureIfNeeded(dependentType, + DependentResource.class, + Utils.contextFor(name, dependentType, Dependent.class), + instance -> configureFromCustomAnnotation(instance, parent)); + + var eventSourceName = dependent.useEventSourceWithName(); + eventSourceName = Constants.NO_VALUE_SET.equals(eventSourceName) ? null : eventSourceName; + final var context = Utils.contextFor(name, dependentType, null); + spec = new DependentResourceSpec(dependentResource, dependentName, + Set.of(dependent.dependsOn()), + Utils.instantiate(dependent.readyPostcondition(), Condition.class, context), + Utils.instantiate(dependent.reconcilePrecondition(), Condition.class, context), + Utils.instantiate(dependent.deletePostcondition(), Condition.class, context), + eventSourceName); + specsMap.put(dependentName, spec); + } + return specsMap.values().stream().collect(Collectors.toUnmodifiableList()); } protected boolean createIfNeeded() { @@ -79,4 +242,59 @@ protected boolean createIfNeeded() { public boolean checkCRDAndValidateLocalModel() { return Utils.shouldCheckCRDAndValidateLocalModel(); } + + private static T valueOrDefault( + io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration controllerConfiguration, + Function mapper, + T defaultValue) { + if (controllerConfiguration == null) { + return defaultValue; + } else { + return mapper.apply(controllerConfiguration); + } + } + @SuppressWarnings("rawtypes") + private static String getName(String name, Class dependentType) { + if (name.isBlank()) { + name = DependentResource.defaultNameFor(dependentType); + } + return name; + } + + @SuppressWarnings("unused") + private static Configurator configuratorFor(Class instanceType, + Reconciler reconciler) { + return instance -> configureFromAnnotatedReconciler(instance, reconciler); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private static void configureFromAnnotatedReconciler(Object instance, Reconciler reconciler) { + if (instance instanceof AnnotationConfigurable) { + AnnotationConfigurable configurable = (AnnotationConfigurable) instance; + final Class configurationClass = + (Class) Utils.getFirstTypeArgumentFromSuperClassOrInterface( + instance.getClass(), AnnotationConfigurable.class); + final var configAnnotation = reconciler.getClass().getAnnotation(configurationClass); + if (configAnnotation != null) { + configurable.initFrom(configAnnotation); + } + } + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private static

void configureFromCustomAnnotation(Object instance, + ControllerConfiguration

parent) { + if (instance instanceof AnnotationDependentResourceConfigurator) { + AnnotationDependentResourceConfigurator configurator = + (AnnotationDependentResourceConfigurator) instance; + final Class configurationClass = + (Class) Utils.getFirstTypeArgumentFromInterface( + instance.getClass(), AnnotationDependentResourceConfigurator.class); + final var configAnnotation = instance.getClass().getAnnotation(configurationClass); + // always called even if the annotation is null so that implementations can provide default + // values + final var config = configurator.configFrom(configAnnotation, parent); + configurator.configureWith(config); + } + } } 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 74c40ed9a8..b2640777a7 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 @@ -17,19 +17,37 @@ import io.javaoperatorsdk.operator.processing.retry.GradualRetry; import io.javaoperatorsdk.operator.processing.retry.Retry; -public interface ControllerConfiguration extends ResourceConfiguration { +public interface ControllerConfiguration

extends ResourceConfiguration

{ @SuppressWarnings("rawtypes") RateLimiter DEFAULT_RATE_LIMITER = LinearRateLimiter.deactivatedRateLimiter(); default String getName() { - return ReconcilerUtils.getDefaultReconcilerName(getAssociatedReconcilerClassName()); + return ensureValidName(null, getAssociatedReconcilerClassName()); } default String getFinalizerName() { return ReconcilerUtils.getDefaultFinalizerName(getResourceClass()); } + static String ensureValidName(String name, String reconcilerClassName) { + return name != null ? name : ReconcilerUtils.getDefaultReconcilerName(reconcilerClassName); + } + + static String ensureValidFinalizerName(String finalizer, String resourceTypeName) { + if (finalizer != null && !finalizer.isBlank()) { + if (ReconcilerUtils.isFinalizerValid(finalizer)) { + return finalizer; + } else { + throw new IllegalArgumentException( + finalizer + + " is not a valid finalizer. See https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#finalizers for details"); + } + } else { + return ReconcilerUtils.getDefaultFinalizerName(resourceTypeName); + } + } + default boolean isGenerationAware() { return true; } @@ -70,8 +88,12 @@ default RateLimiter getRateLimiter() { *

* * @return filter + * @deprecated use {@link ResourceConfiguration#onAddFilter()}, + * {@link ResourceConfiguration#onUpdateFilter()} or + * {@link ResourceConfiguration#genericFilter()} instead */ - default ResourceEventFilter getEventFilter() { + @Deprecated(forRemoval = true) + default ResourceEventFilter

getEventFilter() { return ResourceEventFilters.passthrough(); } @@ -91,8 +113,8 @@ default ConfigurationService getConfigurationService() { @SuppressWarnings("unchecked") @Override - default Class getResourceClass() { - return (Class) Utils.getFirstTypeArgumentFromSuperClassOrInterface(getClass(), + default Class

getResourceClass() { + return (Class

) Utils.getFirstTypeArgumentFromSuperClassOrInterface(getClass(), ControllerConfiguration.class); } } 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 31de28631d..5d7712f927 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 @@ -179,25 +179,14 @@ public ControllerConfigurationOverrider replacingNamedDependentResourceConfig } public ControllerConfiguration build() { - return new DefaultControllerConfiguration<>( - original.getAssociatedReconcilerClassName(), - original.getName(), - original.getResourceTypeName(), - finalizer, - generationAware, - namespaces, - retry, - labelSelector, - customResourcePredicate, - original.getResourceClass(), - reconciliationMaxInterval, - onAddFilter, - onUpdateFilter, - genericFilter, - rateLimiter, + final var overridden = new ResolvedControllerConfiguration<>( + original.getResourceClass(), original.getName(), + generationAware, original.getAssociatedReconcilerClassName(), retry, rateLimiter, + reconciliationMaxInterval, onAddFilter, onUpdateFilter, genericFilter, cachePruneFunction, original.getDependentResources(), - cachePruneFunction, - configurations); + namespaces, finalizer, labelSelector); + overridden.setEventFilter(customResourcePredicate); + return overridden; } public static ControllerConfigurationOverrider override( diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultControllerConfiguration.java deleted file mode 100644 index 6dd99ecbe2..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultControllerConfiguration.java +++ /dev/null @@ -1,156 +0,0 @@ -package io.javaoperatorsdk.operator.api.config; - -import java.time.Duration; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.function.UnaryOperator; - -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfigurationProvider; -import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; -import io.javaoperatorsdk.operator.processing.event.rate.LinearRateLimiter; -import io.javaoperatorsdk.operator.processing.event.rate.RateLimiter; -import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter; -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 io.javaoperatorsdk.operator.processing.retry.Retry; - -@SuppressWarnings("rawtypes") -public class DefaultControllerConfiguration - extends DefaultResourceConfiguration - implements ControllerConfiguration, DependentResourceConfigurationProvider { - - private final String associatedControllerClassName; - private final String name; - private final String crdName; - private final String finalizer; - private final boolean generationAware; - private final Retry retry; - private final ResourceEventFilter resourceEventFilter; - private final List dependents; - private final Duration reconciliationMaxInterval; - private final RateLimiter rateLimiter; - private final Map configurations; - - // NOSONAR constructor is meant to provide all information - public DefaultControllerConfiguration( - String associatedControllerClassName, - String name, - String crdName, - String finalizer, - boolean generationAware, - Set namespaces, - Retry retry, - String labelSelector, - ResourceEventFilter resourceEventFilter, - Class resourceClass, - Duration reconciliationMaxInterval, - OnAddFilter onAddFilter, - OnUpdateFilter onUpdateFilter, - GenericFilter genericFilter, - RateLimiter rateLimiter, - List dependents, - UnaryOperator cachePruneFunction) { - this(associatedControllerClassName, name, crdName, finalizer, generationAware, namespaces, - retry, labelSelector, resourceEventFilter, resourceClass, reconciliationMaxInterval, - onAddFilter, onUpdateFilter, genericFilter, rateLimiter, dependents, cachePruneFunction, - null); - } - - DefaultControllerConfiguration( - String associatedControllerClassName, - String name, - String crdName, - String finalizer, - boolean generationAware, - Set namespaces, - Retry retry, - String labelSelector, - ResourceEventFilter resourceEventFilter, - Class resourceClass, - Duration reconciliationMaxInterval, - OnAddFilter onAddFilter, - OnUpdateFilter onUpdateFilter, - GenericFilter genericFilter, - RateLimiter rateLimiter, - List dependents, - UnaryOperator cachePruneFunction, - Map configurations) { - super(labelSelector, resourceClass, onAddFilter, onUpdateFilter, genericFilter, namespaces, - cachePruneFunction); - this.associatedControllerClassName = associatedControllerClassName; - this.name = name; - this.crdName = crdName; - this.finalizer = finalizer; - this.generationAware = generationAware; - this.reconciliationMaxInterval = reconciliationMaxInterval; - this.retry = - retry == null - ? ControllerConfiguration.super.getRetry() - : retry; - this.resourceEventFilter = resourceEventFilter; - this.rateLimiter = - rateLimiter != null ? rateLimiter : LinearRateLimiter.deactivatedRateLimiter(); - this.dependents = dependents != null ? dependents : Collections.emptyList(); - this.configurations = configurations != null ? configurations : Collections.emptyMap(); - } - - @Override - public String getName() { - return name; - } - - @Override - public String getResourceTypeName() { - return crdName; - } - - @Override - public String getFinalizerName() { - return finalizer; - } - - @Override - public boolean isGenerationAware() { - return generationAware; - } - - @Override - public String getAssociatedReconcilerClassName() { - return associatedControllerClassName; - } - - @Override - public Retry getRetry() { - return retry; - } - - @Override - public ResourceEventFilter getEventFilter() { - return resourceEventFilter; - } - - @Override - public List getDependentResources() { - return dependents; - } - - @Override - public Optional maxReconciliationInterval() { - return Optional.ofNullable(reconciliationMaxInterval); - } - - @Override - public RateLimiter getRateLimiter() { - return rateLimiter; - } - - @Override - public Object getConfigurationFor(DependentResourceSpec spec) { - return configurations.get(spec); - } -} 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/DefaultResourceConfiguration.java index 8e42284a25..bb9f365d58 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/DefaultResourceConfiguration.java @@ -5,52 +5,41 @@ import java.util.function.UnaryOperator; import io.fabric8.kubernetes.api.model.HasMetadata; +import io.javaoperatorsdk.operator.ReconcilerUtils; 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; - public class DefaultResourceConfiguration implements ResourceConfiguration { - private final String labelSelector; - private final Set namespaces; private final Class resourceClass; + private final String resourceTypeName; private final OnAddFilter onAddFilter; private final OnUpdateFilter onUpdateFilter; private final GenericFilter genericFilter; + private final String labelSelector; + private final Set namespaces; private final UnaryOperator cachePruneFunction; - public DefaultResourceConfiguration(String labelSelector, Class resourceClass, - OnAddFilter onAddFilter, - OnUpdateFilter onUpdateFilter, GenericFilter genericFilter, String... namespaces) { - this(labelSelector, resourceClass, onAddFilter, onUpdateFilter, genericFilter, - namespaces == null || namespaces.length == 0 ? DEFAULT_NAMESPACES_SET - : Set.of(namespaces), - null); - } - - public DefaultResourceConfiguration(String labelSelector, Class resourceClass, - OnAddFilter onAddFilter, - OnUpdateFilter onUpdateFilter, - GenericFilter genericFilter, - Set namespaces, + protected DefaultResourceConfiguration(Class resourceClass, + Set namespaces, String labelSelector, OnAddFilter onAddFilter, + OnUpdateFilter onUpdateFilter, GenericFilter genericFilter, UnaryOperator cachePruneFunction) { - this.labelSelector = labelSelector; this.resourceClass = resourceClass; + this.resourceTypeName = ReconcilerUtils.getResourceTypeName(resourceClass); this.onAddFilter = onAddFilter; this.onUpdateFilter = onUpdateFilter; this.genericFilter = genericFilter; - this.namespaces = - namespaces == null || namespaces.isEmpty() ? DEFAULT_NAMESPACES_SET - : namespaces; + + this.namespaces = ResourceConfiguration.ensureValidNamespaces(namespaces); + this.labelSelector = ResourceConfiguration.ensureValidLabelSelector(labelSelector); this.cachePruneFunction = cachePruneFunction; } @Override public String getResourceTypeName() { - return ResourceConfiguration.super.getResourceTypeName(); + return resourceTypeName; } @Override 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 new file mode 100644 index 0000000000..a587ce50f5 --- /dev/null +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResolvedControllerConfiguration.java @@ -0,0 +1,157 @@ +package io.javaoperatorsdk.operator.api.config; + +import java.time.Duration; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.function.UnaryOperator; + +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; +import io.javaoperatorsdk.operator.api.reconciler.Reconciler; +import io.javaoperatorsdk.operator.processing.event.rate.RateLimiter; +import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter; +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 io.javaoperatorsdk.operator.processing.retry.Retry; + +@SuppressWarnings("rawtypes") +public class ResolvedControllerConfiguration

+ extends DefaultResourceConfiguration

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

{ + + private final String name; + private final boolean generationAware; + private final String associatedReconcilerClassName; + private final Retry retry; + private final RateLimiter rateLimiter; + private final Optional maxReconciliationInterval; + private final String finalizer; + + private ResourceEventFilter

eventFilter; + private List dependentResources; + + public ResolvedControllerConfiguration(Class

resourceClass, ControllerConfiguration

other) { + this(resourceClass, other.getName(), other.isGenerationAware(), + other.getAssociatedReconcilerClassName(), other.getRetry(), other.getRateLimiter(), + other.maxReconciliationInterval().orElse(null), + other.onAddFilter().orElse(null), other.onUpdateFilter().orElse(null), + other.genericFilter().orElse(null), other.cachePruneFunction().orElse(null), + other.getDependentResources(), other.getNamespaces(), + other.getFinalizerName(), other.getLabelSelector()); + } + + public static Duration getMaxReconciliationInterval(long interval, TimeUnit timeUnit) { + return interval > 0 ? Duration.of(interval, timeUnit.toChronoUnit()) : null; + } + + public static String getAssociatedReconcilerClassName( + Class reconcilerClass) { + return reconcilerClass.getCanonicalName(); + } + + protected Retry ensureRetry(Retry given) { + return given == null ? ControllerConfiguration.super.getRetry() : given; + } + + protected RateLimiter ensureRateLimiter(RateLimiter given) { + return given == null ? ControllerConfiguration.super.getRateLimiter() : given; + } + + public ResolvedControllerConfiguration(Class

resourceClass, String name, + boolean generationAware, String associatedReconcilerClassName, Retry retry, + RateLimiter rateLimiter, Duration maxReconciliationInterval, + OnAddFilter

onAddFilter, OnUpdateFilter

onUpdateFilter, + GenericFilter

genericFilter, UnaryOperator

cachePruneFunction, + List dependentResources, + Set namespaces, String finalizer, String labelSelector) { + this(resourceClass, name, generationAware, associatedReconcilerClassName, retry, rateLimiter, + maxReconciliationInterval, onAddFilter, onUpdateFilter, genericFilter, cachePruneFunction, + namespaces, finalizer, labelSelector); + setDependentResources(dependentResources); + } + + protected ResolvedControllerConfiguration(Class

resourceClass, String name, + boolean generationAware, String associatedReconcilerClassName, Retry retry, + RateLimiter rateLimiter, Duration maxReconciliationInterval, + OnAddFilter

onAddFilter, OnUpdateFilter

onUpdateFilter, GenericFilter

genericFilter, + UnaryOperator

cachePruneFunction, + Set namespaces, String finalizer, String labelSelector) { + super(resourceClass, namespaces, labelSelector, onAddFilter, onUpdateFilter, genericFilter, + cachePruneFunction); + this.name = ControllerConfiguration.ensureValidName(name, associatedReconcilerClassName); + this.generationAware = generationAware; + this.associatedReconcilerClassName = associatedReconcilerClassName; + this.retry = ensureRetry(retry); + this.rateLimiter = ensureRateLimiter(rateLimiter); + this.maxReconciliationInterval = Optional.ofNullable(maxReconciliationInterval); + + this.finalizer = + ControllerConfiguration.ensureValidFinalizerName(finalizer, getResourceTypeName()); + } + + protected ResolvedControllerConfiguration(Class

resourceClass, String name, + Class reconcilerClas) { + this(resourceClass, name, false, getAssociatedReconcilerClassName(reconcilerClas), null, null, + null, null, null, null, null, + null, null, null); + } + + @Override + public String getName() { + return name; + } + + @Override + public String getFinalizerName() { + return finalizer; + } + + @Override + public boolean isGenerationAware() { + return generationAware; + } + + @Override + public String getAssociatedReconcilerClassName() { + return associatedReconcilerClassName; + } + + @Override + public Retry getRetry() { + return retry; + } + + @Override + public RateLimiter getRateLimiter() { + return rateLimiter; + } + + @Override + public List getDependentResources() { + return dependentResources; + } + + protected void setDependentResources(List dependentResources) { + this.dependentResources = dependentResources == null ? Collections.emptyList() + : Collections.unmodifiableList(dependentResources); + } + + @Override + public Optional maxReconciliationInterval() { + return maxReconciliationInterval; + } + + @Override + public ResourceEventFilter

getEventFilter() { + return eventFilter; + } + + @Deprecated(forRemoval = true) + protected void setEventFilter(ResourceEventFilter

eventFilter) { + this.eventFilter = eventFilter; + } +} 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 6a6574182a..85f3bc3b36 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,5 +1,6 @@ package io.javaoperatorsdk.operator.api.config; +import java.util.Collection; import java.util.Collections; import java.util.Optional; import java.util.Set; @@ -47,6 +48,11 @@ default String getLabelSelector() { return null; } + static String ensureValidLabelSelector(String labelSelector) { + // might want to implement validation here? + return labelSelector; + } + @SuppressWarnings("unchecked") default Class getResourceClass() { return (Class) Utils.getFirstTypeArgumentFromSuperClassOrInterface(getClass(), @@ -90,6 +96,14 @@ static void failIfNotValid(Set namespaces) { + Constants.WATCH_CURRENT_NAMESPACE + "'"); } + static Set ensureValidNamespaces(Collection namespaces) { + if (namespaces != null && !namespaces.isEmpty()) { + return Set.copyOf(namespaces); + } 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 diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Utils.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Utils.java index 00927b7f14..5838eb9b97 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Utils.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Utils.java @@ -227,6 +227,13 @@ public interface Configurator { public static String contextFor(ControllerConfiguration controllerConfiguration, Class dependentType, Class configurationAnnotation) { + return contextFor(controllerConfiguration.getName(), dependentType, configurationAnnotation); + } + + @SuppressWarnings("rawtypes") + public static String contextFor(String reconcilerName, + Class dependentType, + Class configurationAnnotation) { final var annotationName = configurationAnnotation != null ? configurationAnnotation.getSimpleName() : io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration.class @@ -235,7 +242,7 @@ public static String contextFor(ControllerConfiguration controllerConfigurati if (dependentType != null) { context += "DependentResource: " + dependentType.getName() + ", "; } - context += "reconciler: " + controllerConfiguration.getName(); + context += "reconciler: " + reconcilerName; return context; } 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 03e37863df..e26597dde5 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 @@ -30,7 +30,6 @@ class DefaultInformerConfiguration extends private final SecondaryToPrimaryMapper secondaryToPrimaryMapper; private final boolean followControllerNamespaceChanges; private final OnDeleteFilter onDeleteFilter; - private final UnaryOperator cachePruneFunction; protected DefaultInformerConfiguration(String labelSelector, Class resourceClass, @@ -42,7 +41,7 @@ protected DefaultInformerConfiguration(String labelSelector, OnDeleteFilter onDeleteFilter, GenericFilter genericFilter, UnaryOperator cachePruneFunction) { - super(labelSelector, resourceClass, onAddFilter, onUpdateFilter, genericFilter, namespaces, + super(resourceClass, namespaces, labelSelector, onAddFilter, onUpdateFilter, genericFilter, cachePruneFunction); this.followControllerNamespaceChanges = followControllerNamespaceChanges; @@ -51,7 +50,6 @@ protected DefaultInformerConfiguration(String labelSelector, Objects.requireNonNullElse(secondaryToPrimaryMapper, Mappers.fromOwnerReference()); this.onDeleteFilter = onDeleteFilter; - this.cachePruneFunction = cachePruneFunction; } @Override @@ -69,14 +67,10 @@ public Optional> onDeleteFilter() { } @Override + @SuppressWarnings("unchecked") public

PrimaryToSecondaryMapper

getPrimaryToSecondaryMapper() { return (PrimaryToSecondaryMapper

) primaryToSecondaryMapper; } - - @Override - public Optional> cachePruneFunction() { - return Optional.ofNullable(this.cachePruneFunction); - } } /** diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/ControllerManagerTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/ControllerManagerTest.java index 94af637b38..1cc98403f8 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/ControllerManagerTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/ControllerManagerTest.java @@ -3,11 +3,14 @@ import org.junit.jupiter.api.Test; import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.client.CustomResource; -import io.javaoperatorsdk.operator.api.config.DefaultControllerConfiguration; +import io.javaoperatorsdk.operator.api.config.ResolvedControllerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.processing.Controller; -import io.javaoperatorsdk.operator.sample.simple.*; +import io.javaoperatorsdk.operator.sample.simple.DuplicateCRController; +import io.javaoperatorsdk.operator.sample.simple.TestCustomReconciler; +import io.javaoperatorsdk.operator.sample.simple.TestCustomReconcilerOtherV1; +import io.javaoperatorsdk.operator.sample.simple.TestCustomResource; +import io.javaoperatorsdk.operator.sample.simple.TestCustomResourceOtherV1; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -46,19 +49,17 @@ private void checkException( }); final var msg = exception.getMessage(); assertTrue( - msg.contains("Cannot register controller '" + duplicated.getControllerName() + "'") - && msg.contains(registered.getControllerName()) + msg.contains("Cannot register controller '" + duplicated.getName() + "'") + && msg.contains(registered.getName()) && msg.contains(registered.getResourceTypeName())); } private static class TestControllerConfiguration - extends DefaultControllerConfiguration { + extends ResolvedControllerConfiguration { private final Reconciler controller; public TestControllerConfiguration(Reconciler controller, Class crClass) { - super(null, getControllerName(controller), - CustomResource.getCRDName(crClass), null, false, null, null, null, null, crClass, - null, null, null, null, null, null, null); + super(crClass, getControllerName(controller), controller.getClass()); this.controller = controller; } @@ -66,9 +67,5 @@ static String getControllerName( Reconciler controller) { return controller.getClass().getSimpleName() + "Controller"; } - - private String getControllerName() { - return getControllerName(controller); - } } } 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 766ef6d824..98c071e942 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 @@ -28,6 +28,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class ControllerConfigurationOverriderTest { + private final BaseConfigurationService configurationService = new BaseConfigurationService(); @Test void overridingNSShouldPreserveUntouchedDependents() { @@ -118,7 +119,7 @@ private Object extractDependentKubernetesResourceConfig( private io.javaoperatorsdk.operator.api.config.ControllerConfiguration createConfiguration( Reconciler reconciler) { - return new AnnotationControllerConfiguration<>(reconciler); + return configurationService.configFor(reconciler); } @ControllerConfiguration(namespaces = "foo") diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/ResourceEventFilterTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/ResourceEventFilterTest.java index df73d79164..d74075e746 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/ResourceEventFilterTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/ResourceEventFilterTest.java @@ -8,9 +8,10 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.MockKubernetesClient; +import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.TestUtils; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; -import io.javaoperatorsdk.operator.api.config.DefaultControllerConfiguration; +import io.javaoperatorsdk.operator.api.config.ResolvedControllerConfiguration; import io.javaoperatorsdk.operator.processing.Controller; import io.javaoperatorsdk.operator.processing.event.EventHandler; import io.javaoperatorsdk.operator.processing.event.EventSourceManager; @@ -25,7 +26,8 @@ import static org.mockito.Mockito.verify; class ResourceEventFilterTest { - public static final String FINALIZER = "finalizer"; + public static final String FINALIZER = + ReconcilerUtils.getDefaultFinalizerName(TestCustomResource.class); private EventHandler eventHandler; @@ -129,23 +131,21 @@ public TestControllerConfig(String finalizer, boolean generationAware, } private static class ControllerConfig extends - DefaultControllerConfiguration { + ResolvedControllerConfiguration { public ControllerConfig(String finalizer, boolean generationAware, ResourceEventFilter eventFilter, Class customResourceClass) { - super( + super(customResourceClass, + "test", + generationAware, null, - "testController", null, - finalizer, - generationAware, null, null, null, - eventFilter, - customResourceClass, null, - null, null, null, null, null, null); + null, null, null, finalizer, null); + setEventFilter(eventFilter); } } diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSourceTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSourceTest.java index 27b43656be..2e4a4d0e58 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSourceTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSourceTest.java @@ -7,8 +7,9 @@ import org.junit.jupiter.api.Test; import io.javaoperatorsdk.operator.MockKubernetesClient; +import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.TestUtils; -import io.javaoperatorsdk.operator.api.config.DefaultControllerConfiguration; +import io.javaoperatorsdk.operator.api.config.ResolvedControllerConfiguration; import io.javaoperatorsdk.operator.processing.Controller; import io.javaoperatorsdk.operator.processing.event.EventHandler; import io.javaoperatorsdk.operator.processing.event.EventSourceManager; @@ -19,12 +20,17 @@ import io.javaoperatorsdk.operator.sample.simple.TestCustomResource; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; class ControllerResourceEventSourceTest extends AbstractEventSourceTestBase, EventHandler> { - public static final String FINALIZER = "finalizer"; + public static final String FINALIZER = + ReconcilerUtils.getDefaultFinalizerName(TestCustomResource.class); private final TestController testController = new TestController(true); @@ -171,24 +177,27 @@ public boolean useFinalizer() { } private static class TestConfiguration extends - DefaultControllerConfiguration { + ResolvedControllerConfiguration { public TestConfiguration(boolean generationAware, OnAddFilter onAddFilter, OnUpdateFilter onUpdateFilter, GenericFilter genericFilter) { super( + TestCustomResource.class, + "test", + generationAware, null, - "testController", null, - FINALIZER, - generationAware, null, null, + onAddFilter, + onUpdateFilter, + genericFilter, null, null, - TestCustomResource.class, null, - onAddFilter, onUpdateFilter, genericFilter, null, null, null); + FINALIZER, + null); } } } diff --git a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/AnnotationControllerConfiguration.java b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/AnnotationControllerConfiguration.java deleted file mode 100644 index 47eee2a249..0000000000 --- a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/AnnotationControllerConfiguration.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.javaoperatorsdk.operator.config.runtime; - -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.api.reconciler.Reconciler; - -public class AnnotationControllerConfiguration - extends io.javaoperatorsdk.operator.api.config.AnnotationControllerConfiguration { - - public AnnotationControllerConfiguration(Reconciler reconciler) { - super(reconciler); - } - - @Override - public Class getResourceClass() { - return RuntimeControllerMetadata.getResourceClass(reconciler); - } -} 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 34e0b3f1d7..49f0ed2b67 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 @@ -4,6 +4,7 @@ import io.javaoperatorsdk.operator.api.config.BaseConfigurationService; import io.javaoperatorsdk.operator.api.config.ConfigurationServiceProvider; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; +import io.javaoperatorsdk.operator.api.config.ResolvedControllerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; public class DefaultConfigurationService extends BaseConfigurationService { @@ -46,6 +47,8 @@ public void setCreateIfNeeded(boolean createIfNeeded) { @Override protected ControllerConfiguration configFor(Reconciler reconciler) { - return new AnnotationControllerConfiguration<>(reconciler); + final var other = super.configFor(reconciler); + return new ResolvedControllerConfiguration<>( + RuntimeControllerMetadata.getResourceClass(reconciler), other); } } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/runtime/AnnotationControllerConfigurationTest.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/BaseConfigurationServiceTest.java similarity index 90% rename from operator-framework/src/test/java/io/javaoperatorsdk/operator/config/runtime/AnnotationControllerConfigurationTest.java rename to operator-framework/src/test/java/io/javaoperatorsdk/operator/config/BaseConfigurationServiceTest.java index bbc49ebf33..22af954661 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/runtime/AnnotationControllerConfigurationTest.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/BaseConfigurationServiceTest.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.operator.config.runtime; +package io.javaoperatorsdk.operator.config; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -14,8 +14,10 @@ import org.junit.jupiter.api.Test; import io.fabric8.kubernetes.api.model.ConfigMap; +import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.OperatorException; import io.javaoperatorsdk.operator.api.config.AnnotationConfigurable; +import io.javaoperatorsdk.operator.api.config.BaseConfigurationService; import io.javaoperatorsdk.operator.api.config.dependent.ConfigurationConverter; import io.javaoperatorsdk.operator.api.config.dependent.Configured; import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfigurationResolver; @@ -48,11 +50,29 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -class AnnotationControllerConfigurationTest { +class BaseConfigurationServiceTest { + + // subclass to expose configFor method to this test class + private final static class TestConfigurationService extends BaseConfigurationService { + + @Override + protected

io.javaoperatorsdk.operator.api.config.ControllerConfiguration

configFor( + Reconciler

reconciler) { + return super.configFor(reconciler); + } + } + + private final TestConfigurationService configurationService = new TestConfigurationService(); + + private

io.javaoperatorsdk.operator.api.config.ControllerConfiguration

configFor( + Reconciler

reconciler) { + // ensure that a new configuration is created each time + return configurationService.configFor(reconciler); + } @Test void defaultValuesShouldBeConsistent() { - final var configuration = new AnnotationControllerConfiguration<>(new SelectorReconciler()); + final var configuration = configFor(new SelectorReconciler()); final var annotated = extractDependentKubernetesResourceConfig(configuration, 1); final var unannotated = extractDependentKubernetesResourceConfig(configuration, 0); @@ -71,11 +91,11 @@ private KubernetesDependentResourceConfig extractDependentKubernetesResourceConf @Test @SuppressWarnings("rawtypes") void getDependentResources() { - var configuration = new AnnotationControllerConfiguration<>(new NoDepReconciler()); + var configuration = configFor(new NoDepReconciler()); var dependents = configuration.getDependentResources(); assertTrue(dependents.isEmpty()); - configuration = new AnnotationControllerConfiguration<>(new OneDepReconciler()); + configuration = configFor(new OneDepReconciler()); dependents = configuration.getDependentResources(); assertFalse(dependents.isEmpty()); assertEquals(1, dependents.size()); @@ -92,7 +112,7 @@ void getDependentResources() { assertEquals(1, config.namespaces().size()); assertEquals(Set.of(OneDepReconciler.CONFIGURED_NS), config.namespaces()); - configuration = new AnnotationControllerConfiguration<>(new NamedDepReconciler()); + configuration = configFor(new NamedDepReconciler()); dependents = configuration.getDependentResources(); assertFalse(dependents.isEmpty()); assertEquals(1, dependents.size()); @@ -107,7 +127,7 @@ void getDependentResources() { @Test void missingAnnotationThrowsException() { Assertions.assertThrows(OperatorException.class, - () -> new AnnotationControllerConfiguration<>(new MissingAnnotationReconciler())); + () -> configFor(new MissingAnnotationReconciler())); } @SuppressWarnings("rawtypes") @@ -125,13 +145,12 @@ private Optional findByNameOptional( @Test void tryingToAddDuplicatedDependentsWithoutNameShouldFail() { - var configuration = new AnnotationControllerConfiguration<>(new DuplicatedDepReconciler()); - assertThrows(IllegalArgumentException.class, configuration::getDependentResources); + assertThrows(IllegalArgumentException.class, () -> configFor(new DuplicatedDepReconciler())); } @Test void addingDuplicatedDependentsWithNameShouldWork() { - var config = new AnnotationControllerConfiguration<>(new NamedDuplicatedDepReconciler()); + var config = configFor(new NamedDuplicatedDepReconciler()); var dependents = config.getDependentResources(); assertEquals(2, dependents.size()); assertTrue(findByNameOptional(dependents, NamedDuplicatedDepReconciler.NAME).isPresent() @@ -141,13 +160,13 @@ && findByNameOptional(dependents, DependentResource.defaultNameFor(ReadOnlyDepen @Test void maxIntervalCanBeConfigured() { - var config = new AnnotationControllerConfiguration<>(new MaxIntervalReconciler()); + var config = configFor(new MaxIntervalReconciler()); assertEquals(50, config.maxReconciliationInterval().map(Duration::getSeconds).orElseThrow()); } @Test void checkDefaultRateAndRetryConfigurations() { - var config = new AnnotationControllerConfiguration<>(new NoDepReconciler()); + var config = configFor(new NoDepReconciler()); final var retry = assertInstanceOf(GenericRetry.class, config.getRetry()); assertEquals(GradualRetry.DEFAULT_MAX_ATTEMPTS, retry.getMaxAttempts()); assertEquals(GradualRetry.DEFAULT_MULTIPLIER, retry.getIntervalMultiplier()); @@ -161,7 +180,7 @@ void checkDefaultRateAndRetryConfigurations() { @Test void configuringRateAndRetryViaAnnotationsShouldWork() { var config = - new AnnotationControllerConfiguration<>(new ConfigurableRateLimitAndRetryReconciler()); + configFor(new ConfigurableRateLimitAndRetryReconciler()); final var retry = config.getRetry(); final var testRetry = assertInstanceOf(TestRetry.class, retry); assertEquals(12, testRetry.getValue()); @@ -173,7 +192,7 @@ void configuringRateAndRetryViaAnnotationsShouldWork() { @Test void checkingRetryingGraduallyWorks() { - var config = new AnnotationControllerConfiguration<>(new CheckRetryingGraduallyConfiguration()); + var config = configFor(new CheckRetryingGraduallyConfiguration()); final var retry = config.getRetry(); final var genericRetry = assertInstanceOf(GenericRetry.class, retry); assertEquals(CheckRetryingGraduallyConfiguration.INITIAL_INTERVAL, @@ -186,13 +205,13 @@ void checkingRetryingGraduallyWorks() { @Test void controllerConfigurationOnSuperClassShouldWork() { - var config = new AnnotationControllerConfiguration<>(new ControllerConfigurationOnSuperClass()); + var config = configFor(new ControllerConfigurationOnSuperClass()); assertNotNull(config.getName()); } @Test void configuringFromCustomAnnotationsShouldWork() { - var config = new AnnotationControllerConfiguration<>(new CustomAnnotationReconciler()); + var config = configFor(new CustomAnnotationReconciler()); assertEquals(CustomAnnotatedDep.PROVIDED_VALUE, getValue(config, 0)); assertEquals(CustomConfigConverter.CONVERTER_PROVIDED_DEFAULT, getValue(config, 1)); } From bda268ea994947e5a8791ad103a0b3117b09840e Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Fri, 9 Dec 2022 16:17:50 +0100 Subject: [PATCH 2/2] fix: update after rebase --- .../api/config/BaseConfigurationService.java | 28 +++---------------- .../ControllerConfigurationOverrider.java | 2 +- .../ResolvedControllerConfiguration.java | 24 ++++++++++++---- ...dentResourceConfigurationResolverTest.java | 27 +++++++++++++++--- .../event/source/ResourceEventFilterTest.java | 2 +- .../ControllerResourceEventSourceTest.java | 2 +- 6 files changed, 48 insertions(+), 37 deletions(-) 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 4e585ed3f7..db91ee22af 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 @@ -22,7 +22,6 @@ import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; -import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.AnnotationDependentResourceConfigurator; import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition; import io.javaoperatorsdk.operator.processing.event.rate.RateLimiter; import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter; @@ -155,7 +154,8 @@ protected

ControllerConfiguration

configFor(Reconcile Constants.NO_VALUE_SET), valueOrDefault(annotation, io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration::labelSelector, - Constants.NO_VALUE_SET)); + Constants.NO_VALUE_SET), + null); ResourceEventFilter

answer = deprecatedEventFilter(annotation); config.setEventFilter(answer != null ? answer : ResourceEventFilters.passthrough()); @@ -215,15 +215,11 @@ private static List dependentResources( } final var name = parent.getName(); - final var dependentResource = Utils.instantiateAndConfigureIfNeeded(dependentType, - DependentResource.class, - Utils.contextFor(name, dependentType, Dependent.class), - instance -> configureFromCustomAnnotation(instance, parent)); var eventSourceName = dependent.useEventSourceWithName(); eventSourceName = Constants.NO_VALUE_SET.equals(eventSourceName) ? null : eventSourceName; final var context = Utils.contextFor(name, dependentType, null); - spec = new DependentResourceSpec(dependentResource, dependentName, + spec = new DependentResourceSpec(dependentType, dependentName, Set.of(dependent.dependsOn()), Utils.instantiate(dependent.readyPostcondition(), Condition.class, context), Utils.instantiate(dependent.reconcilePrecondition(), Condition.class, context), @@ -253,6 +249,7 @@ private static T valueOrDefault( return mapper.apply(controllerConfiguration); } } + @SuppressWarnings("rawtypes") private static String getName(String name, Class dependentType) { if (name.isBlank()) { @@ -280,21 +277,4 @@ private static void configureFromAnnotatedReconciler(Object instance, Reconciler } } } - - @SuppressWarnings({"unchecked", "rawtypes"}) - private static

void configureFromCustomAnnotation(Object instance, - ControllerConfiguration

parent) { - if (instance instanceof AnnotationDependentResourceConfigurator) { - AnnotationDependentResourceConfigurator configurator = - (AnnotationDependentResourceConfigurator) instance; - final Class configurationClass = - (Class) Utils.getFirstTypeArgumentFromInterface( - instance.getClass(), AnnotationDependentResourceConfigurator.class); - final var configAnnotation = instance.getClass().getAnnotation(configurationClass); - // always called even if the annotation is null so that implementations can provide default - // values - final var config = configurator.configFrom(configAnnotation, parent); - configurator.configureWith(config); - } - } } 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 5d7712f927..789de127f5 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 @@ -184,7 +184,7 @@ public ControllerConfiguration build() { generationAware, original.getAssociatedReconcilerClassName(), retry, rateLimiter, reconciliationMaxInterval, onAddFilter, onUpdateFilter, genericFilter, cachePruneFunction, original.getDependentResources(), - namespaces, finalizer, labelSelector); + namespaces, finalizer, labelSelector, configurations); overridden.setEventFilter(customResourcePredicate); return overridden; } 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 a587ce50f5..b1f653cb75 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 @@ -3,12 +3,14 @@ import java.time.Duration; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.UnaryOperator; import io.fabric8.kubernetes.api.model.HasMetadata; +import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfigurationProvider; import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.processing.event.rate.RateLimiter; @@ -21,7 +23,8 @@ @SuppressWarnings("rawtypes") public class ResolvedControllerConfiguration

extends DefaultResourceConfiguration

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

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

, + DependentResourceConfigurationProvider { private final String name; private final boolean generationAware; @@ -30,6 +33,7 @@ public class ResolvedControllerConfiguration

private final RateLimiter rateLimiter; private final Optional maxReconciliationInterval; private final String finalizer; + private final Map configurations; private ResourceEventFilter

eventFilter; private List dependentResources; @@ -41,7 +45,7 @@ public ResolvedControllerConfiguration(Class

resourceClass, ControllerConfigu other.onAddFilter().orElse(null), other.onUpdateFilter().orElse(null), other.genericFilter().orElse(null), other.cachePruneFunction().orElse(null), other.getDependentResources(), other.getNamespaces(), - other.getFinalizerName(), other.getLabelSelector()); + other.getFinalizerName(), other.getLabelSelector(), Collections.emptyMap()); } public static Duration getMaxReconciliationInterval(long interval, TimeUnit timeUnit) { @@ -67,10 +71,11 @@ public ResolvedControllerConfiguration(Class

resourceClass, String name, OnAddFilter

onAddFilter, OnUpdateFilter

onUpdateFilter, GenericFilter

genericFilter, UnaryOperator

cachePruneFunction, List dependentResources, - Set namespaces, String finalizer, String labelSelector) { + Set namespaces, String finalizer, String labelSelector, + Map configurations) { this(resourceClass, name, generationAware, associatedReconcilerClassName, retry, rateLimiter, maxReconciliationInterval, onAddFilter, onUpdateFilter, genericFilter, cachePruneFunction, - namespaces, finalizer, labelSelector); + namespaces, finalizer, labelSelector, configurations); setDependentResources(dependentResources); } @@ -79,7 +84,8 @@ protected ResolvedControllerConfiguration(Class

resourceClass, String name, RateLimiter rateLimiter, Duration maxReconciliationInterval, OnAddFilter

onAddFilter, OnUpdateFilter

onUpdateFilter, GenericFilter

genericFilter, UnaryOperator

cachePruneFunction, - Set namespaces, String finalizer, String labelSelector) { + Set namespaces, String finalizer, String labelSelector, + Map configurations) { super(resourceClass, namespaces, labelSelector, onAddFilter, onUpdateFilter, genericFilter, cachePruneFunction); this.name = ControllerConfiguration.ensureValidName(name, associatedReconcilerClassName); @@ -88,6 +94,7 @@ protected ResolvedControllerConfiguration(Class

resourceClass, String name, this.retry = ensureRetry(retry); this.rateLimiter = ensureRateLimiter(rateLimiter); this.maxReconciliationInterval = Optional.ofNullable(maxReconciliationInterval); + this.configurations = configurations != null ? configurations : Collections.emptyMap(); this.finalizer = ControllerConfiguration.ensureValidFinalizerName(finalizer, getResourceTypeName()); @@ -97,7 +104,7 @@ protected ResolvedControllerConfiguration(Class

resourceClass, String name, Class reconcilerClas) { this(resourceClass, name, false, getAssociatedReconcilerClassName(reconcilerClas), null, null, null, null, null, null, null, - null, null, null); + null, null, null, null); } @Override @@ -154,4 +161,9 @@ public ResourceEventFilter

getEventFilter() { protected void setEventFilter(ResourceEventFilter

eventFilter) { this.eventFilter = eventFilter; } + + @Override + public Object getConfigurationFor(DependentResourceSpec spec) { + return configurations.get(spec); + } } diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceConfigurationResolverTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceConfigurationResolverTest.java index 983215bcb9..3187b32645 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceConfigurationResolverTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceConfigurationResolverTest.java @@ -8,8 +8,9 @@ import org.junit.jupiter.api.Test; import io.fabric8.kubernetes.api.model.ConfigMap; +import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.Service; -import io.javaoperatorsdk.operator.api.config.AnnotationControllerConfiguration; +import io.javaoperatorsdk.operator.api.config.BaseConfigurationService; import io.javaoperatorsdk.operator.api.config.ControllerConfigurationOverrider; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; @@ -30,9 +31,27 @@ class DependentResourceConfigurationResolverTest { + // subclass to expose configFor method to this test class + private final static class TestConfigurationService extends BaseConfigurationService { + + @Override + protected

io.javaoperatorsdk.operator.api.config.ControllerConfiguration

configFor( + Reconciler

reconciler) { + return super.configFor(reconciler); + } + } + + private final TestConfigurationService configurationService = new TestConfigurationService(); + + private

io.javaoperatorsdk.operator.api.config.ControllerConfiguration

configFor( + Reconciler

reconciler) { + // ensure that a new configuration is created each time + return configurationService.configFor(reconciler); + } + @Test void controllerConfigurationProvidedShouldBeReturnedIfAvailable() { - final var cfg = new AnnotationControllerConfiguration<>(new CustomAnnotationReconciler()); + final var cfg = configFor(new CustomAnnotationReconciler()); final var customConfig = DependentResourceConfigurationResolver .extractConfigurationFromConfigured(CustomAnnotatedDep.class, cfg); assertTrue(customConfig instanceof CustomConfig); @@ -51,7 +70,7 @@ void controllerConfigurationProvidedShouldBeReturnedIfAvailable() { @Test void getConverterShouldWork() { - final var cfg = new AnnotationControllerConfiguration<>(new CustomAnnotationReconciler()); + final var cfg = configFor(new CustomAnnotationReconciler()); var converter = DependentResourceConfigurationResolver.getConverter(CustomAnnotatedDep.class); assertNull(converter); assertNull(DependentResourceConfigurationResolver.getConverter(ChildCustomAnnotatedDep.class)); @@ -77,7 +96,7 @@ void getConverterShouldWork() { @SuppressWarnings("rawtypes") @Test void registerConverterShouldWork() { - final var cfg = new AnnotationControllerConfiguration<>(new CustomAnnotationReconciler()); + final var cfg = configFor(new CustomAnnotationReconciler()); var converter = DependentResourceConfigurationResolver.getConverter(ConfigMapDep.class); assertNull(converter); DependentResourceConfigurationResolver.extractConfigurationFromConfigured(ConfigMapDep.class, diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/ResourceEventFilterTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/ResourceEventFilterTest.java index d74075e746..26994cee1a 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/ResourceEventFilterTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/ResourceEventFilterTest.java @@ -144,7 +144,7 @@ public ControllerConfig(String finalizer, boolean generationAware, null, null, null, - null, null, null, finalizer, null); + null, null, null, finalizer, null, null); setEventFilter(eventFilter); } } diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSourceTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSourceTest.java index 2e4a4d0e58..5a171195e1 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSourceTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSourceTest.java @@ -197,7 +197,7 @@ public TestConfiguration(boolean generationAware, OnAddFilter