diff --git a/caffeine-bounded-cache-support/src/test/java/io/javaoperatorsdk/operator/processing/event/source/cache/sample/AbstractTestReconciler.java b/caffeine-bounded-cache-support/src/test/java/io/javaoperatorsdk/operator/processing/event/source/cache/sample/AbstractTestReconciler.java index 18cd486fb2..98101d1243 100644 --- a/caffeine-bounded-cache-support/src/test/java/io/javaoperatorsdk/operator/processing/event/source/cache/sample/AbstractTestReconciler.java +++ b/caffeine-bounded-cache-support/src/test/java/io/javaoperatorsdk/operator/processing/event/source/cache/sample/AbstractTestReconciler.java @@ -77,7 +77,7 @@ public List prepareEventSources( boundedItemStore(new KubernetesClientBuilder().build(), ConfigMap.class, Duration.ofMinutes(1), 1); // setting max size for testing purposes - var es = new InformerEventSource<>(InformerConfiguration.from(ConfigMap.class, context) + var es = new InformerEventSource<>(InformerConfiguration.from(ConfigMap.class, primaryClass()) .withItemStore(boundedItemStore) .withSecondaryToPrimaryMapper( Mappers.fromOwnerReferences(context.getPrimaryResourceClass(), @@ -104,4 +104,7 @@ public static BoundedItemStore boundedItemStore( .build(); return CaffeineBoundedItemStores.boundedItemStore(client, rClass, cache); } + + protected abstract Class

primaryClass(); + } diff --git a/caffeine-bounded-cache-support/src/test/java/io/javaoperatorsdk/operator/processing/event/source/cache/sample/clusterscope/BoundedCacheClusterScopeTestReconciler.java b/caffeine-bounded-cache-support/src/test/java/io/javaoperatorsdk/operator/processing/event/source/cache/sample/clusterscope/BoundedCacheClusterScopeTestReconciler.java index a154659164..84448fc9d8 100644 --- a/caffeine-bounded-cache-support/src/test/java/io/javaoperatorsdk/operator/processing/event/source/cache/sample/clusterscope/BoundedCacheClusterScopeTestReconciler.java +++ b/caffeine-bounded-cache-support/src/test/java/io/javaoperatorsdk/operator/processing/event/source/cache/sample/clusterscope/BoundedCacheClusterScopeTestReconciler.java @@ -7,4 +7,8 @@ public class BoundedCacheClusterScopeTestReconciler extends AbstractTestReconciler { + @Override + protected Class primaryClass() { + return BoundedCacheClusterScopeTestCustomResource.class; + } } diff --git a/caffeine-bounded-cache-support/src/test/java/io/javaoperatorsdk/operator/processing/event/source/cache/sample/namespacescope/BoundedCacheTestReconciler.java b/caffeine-bounded-cache-support/src/test/java/io/javaoperatorsdk/operator/processing/event/source/cache/sample/namespacescope/BoundedCacheTestReconciler.java index 211877b361..6b95665585 100644 --- a/caffeine-bounded-cache-support/src/test/java/io/javaoperatorsdk/operator/processing/event/source/cache/sample/namespacescope/BoundedCacheTestReconciler.java +++ b/caffeine-bounded-cache-support/src/test/java/io/javaoperatorsdk/operator/processing/event/source/cache/sample/namespacescope/BoundedCacheTestReconciler.java @@ -7,4 +7,8 @@ public class BoundedCacheTestReconciler extends AbstractTestReconciler { + @Override + protected Class primaryClass() { + return BoundedCacheTestCustomResource.class; + } } diff --git a/docs/documentation/v5-0-migration.md b/docs/documentation/v5-0-migration.md deleted file mode 100644 index a1c1b66120..0000000000 --- a/docs/documentation/v5-0-migration.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Migrating from v4.7 to v5.0 -description: Migrating from v4.7 to v5.0 -layout: docs -permalink: /docs/v5-0-migration ---- - -# Migrating from v4.7 to v5.0 - -## API Tweaks - -1. [Result of managed dependent resources](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/ManagedDependentResourceContext.java#L55-L57) - is not `Optional` anymore. In case you use this result, simply use the result - objects directly. -2. `EventSourceInitializer` is not a separate interface anymore. It is part of the `Reconciler` interface with a - default implementation. You can simply remove this interface from your reconciler. The - [`EventSourceUtils`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/EventSourceUtils.java#L11-L11) - now contains all the utility methods used for event sources naming that were previously defined in - the `EventSourceInitializer` interface. -3. Similarly, the `EventSourceProvider` interface has been remove, replaced by explicit initialization of the associated - event source on `DependentResource` via the ` - Optional> eventSource(EventSourceContext

eventSourceContext)` method. -4. Event sources are now explicitly named (via the `name` method of the `EventSource` interface). Built-in event sources - implementation have been updated to allow you to specify a name when instantiating them. If you don't provide a name - for your `EventSource` implementation (for example, by using its default, no-arg constructor), one will be - automatically generated. This simplifies the API to define event source to - `List prepareEventSources(EventSourceContext

context)`. - !!! IMPORTANT !!! - If you use dynamic registration of event sources, be sure to name your event sources explicitly as letting JOSDK name - them automatically might result in duplicated event sources being registered as JOSDK relies on the name to identify - event sources and concurrent, dynamic registration might lead to identical event sources having different generated - names, thus leading JOSDK to consider them as different and hence, register them multiple times. -5. Updates through `UpdateControl` now - use [Server Side Apply (SSA)](https://kubernetes.io/docs/reference/using-api/server-side-apply/) by default to add - the finalizer and for all - the patch operations in `UpdateControl`. The update operations were removed. If you do not wish to use SSA, you can - deactivate the feature using `ConfigurationService.useSSAToPatchPrimaryResource` and - related `ConfigurationServiceOverrider.withUseSSAToPatchPrimaryResource`. - - !!! IMPORTANT !!! - - See known issues with migration from non-SSA to SSA based status updates here: - [integration test](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/StatusPatchSSAMigrationIT.java#L71-L82) - where it is demonstrated. Also, the related part of - a [workaround](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/StatusPatchSSAMigrationIT.java#L110-L116). - -6. `ManagedDependentResourceContext` has been renamed to `ManagedWorkflowAndDependentResourceContext` and is accessed - via the accordingly renamed `managedWorkflowAndDependentResourceContext` method. -7. `ResourceDiscriminator` was removed. In most of the cases you can just delete the discriminator, everything should - work without it by default. To optimize and handle special cases see the relevant section - in [Dependent Resource documentation](/docs/dependent-resources#multiple-dependent-resources-of-same-type). -8. `ConfigurationService.getTerminationTimeoutSeconds` and associated overriding mechanism have been removed, - use `Operator.stop(Duration)` instead. -9. `Operator.installShutdownHook()` has been removed, use `Operator.installShutdownHook(Duration)` instead -10. Automated observed generation handling feature was removed (`ObservedGenerationAware` interface - and `ObservedGenerationAwareStatus` class were deleted). Manually handling observed generation is fairly easy to do - in your reconciler, however, it cannot be done automatically when using SSA. We therefore removed the feature since - it would have been confusing to have a different behavior for SSA and non-SSA cases. For an example of how to do - observed generation handling manually in your reconciler, see - [this sample](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationReconciler.java). -11. `BulkDependentResource` now supports [read-only mode](https://github.com/operator-framework/java-operator-sdk/issues/2233). - This also means, that `BulkDependentResource` now does not automatically implement `Creator` and `Deleter` as before. - Make sure to implement those interfaces in your bulk dependent resources. You can use also the new helper interface, the - [`CRUDBulkDependentResource`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/CRUDBulkDependentResource.java) - what also implement `BulkUpdater` interface. \ No newline at end of file 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 b496a9b1b7..70c86a2a94 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 @@ -17,6 +17,7 @@ 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.DependentResourceConfigurationResolver; import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; import io.javaoperatorsdk.operator.api.config.workflow.WorkflowSpec; import io.javaoperatorsdk.operator.api.reconciler.Constants; @@ -194,7 +195,7 @@ public boolean handleExceptionsInReconciler() { @SuppressWarnings({"unchecked", "rawtypes"}) private static List dependentResources( Workflow annotation, - ControllerConfiguration parent) { + ControllerConfiguration controllerConfiguration) { final var dependents = annotation.dependents(); @@ -213,7 +214,7 @@ private static List dependentResources( "A DependentResource named '" + dependentName + "' already exists: " + spec); } - final var name = parent.getName(); + final var name = controllerConfiguration.getName(); var eventSourceName = dependent.useEventSourceWithName(); eventSourceName = Constants.NO_VALUE_SET.equals(eventSourceName) ? null : eventSourceName; @@ -225,6 +226,12 @@ private static List dependentResources( Utils.instantiate(dependent.deletePostcondition(), Condition.class, context), Utils.instantiate(dependent.activationCondition(), Condition.class, context), eventSourceName); + + // extract potential configuration + DependentResourceConfigurationResolver.configureSpecFromConfigured(spec, + controllerConfiguration, + dependentType); + specsMap.put(dependentName, spec); } return specsMap.values().stream().toList(); 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 2031283f37..aa74d7ea1a 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 @@ -6,6 +6,7 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.ReconcilerUtils; +import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; import io.javaoperatorsdk.operator.api.config.workflow.WorkflowSpec; import io.javaoperatorsdk.operator.api.reconciler.MaxReconciliationInterval; import io.javaoperatorsdk.operator.processing.event.rate.LinearRateLimiter; @@ -71,7 +72,6 @@ default Optional maxReconciliationInterval() { return Optional.of(Duration.ofHours(MaxReconciliationInterval.DEFAULT_INTERVAL)); } - @SuppressWarnings("unused") ConfigurationService getConfigurationService(); @SuppressWarnings("unchecked") @@ -86,7 +86,7 @@ default Class

getResourceClass() { @SuppressWarnings("unused") default Set getEffectiveNamespaces() { - return ResourceConfiguration.super.getEffectiveNamespaces(getConfigurationService()); + return ResourceConfiguration.super.getEffectiveNamespaces(this); } /** @@ -100,4 +100,5 @@ default String fieldManager() { return getName(); } + C getConfigurationFor(DependentResourceSpec spec); } 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 ad66b8b563..315ed29c7b 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 @@ -19,7 +19,7 @@ import static io.javaoperatorsdk.operator.api.reconciler.Constants.DEFAULT_NAMESPACES_SET; import static io.javaoperatorsdk.operator.api.reconciler.Constants.WATCH_CURRENT_NAMESPACE_SET; -@SuppressWarnings({"rawtypes", "unused"}) +@SuppressWarnings({"rawtypes", "unused", "UnusedReturnValue"}) public class ControllerConfigurationOverrider { private String finalizer; 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 af96604591..9ecf24adc7 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 @@ -9,7 +9,6 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.client.informers.cache.ItemStore; -import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfigurationProvider; import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; import io.javaoperatorsdk.operator.api.config.workflow.WorkflowSpec; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; @@ -22,8 +21,7 @@ @SuppressWarnings("rawtypes") public class ResolvedControllerConfiguration

extends DefaultResourceConfiguration

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

, - DependentResourceConfigurationProvider { + implements io.javaoperatorsdk.operator.api.config.ControllerConfiguration

{ private final String name; private final boolean generationAware; @@ -168,8 +166,15 @@ public ConfigurationService getConfigurationService() { } @Override - public Object getConfigurationFor(DependentResourceSpec spec) { - return configurations.get(spec); + @SuppressWarnings("unchecked") + public C getConfigurationFor(DependentResourceSpec spec) { + // first check if there's an overridden configuration at the controller level + var config = configurations.get(spec); + if (config == null) { + // if not, check the spec for configuration + config = spec.getConfiguration().orElse(null); + } + return (C) config; } @Override 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 d94504f50f..b4677a8de6 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 @@ -111,11 +111,12 @@ static Set ensureValidNamespaces(Collection namespaces) { * * @return a Set of namespace names the associated controller will watch */ - default Set getEffectiveNamespaces(ConfigurationService configurationService) { + default Set getEffectiveNamespaces(ControllerConfiguration controllerConfiguration) { var targetNamespaces = getNamespaces(); if (watchCurrentNamespace()) { final String namespace = - configurationService.getKubernetesClient().getConfiguration().getNamespace(); + controllerConfiguration.getConfigurationService().getKubernetesClient().getConfiguration() + .getNamespace(); if (namespace == null) { throw new OperatorException( "Couldn't retrieve the currently connected namespace. Make sure it's correctly set in your ~/.kube/config file, using, e.g. 'kubectl config set-context --namespace='"); diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/ConfigurationConverter.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/ConfigurationConverter.java index 68e0f521de..f0327514ae 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/ConfigurationConverter.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/ConfigurationConverter.java @@ -3,10 +3,9 @@ import java.lang.annotation.Annotation; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; -import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; -public interface ConfigurationConverter> { +public interface ConfigurationConverter { - C configFrom(A configAnnotation, ControllerConfiguration parentConfiguration, - Class originatingClass); + C configFrom(A configAnnotation, DependentResourceSpec spec, + ControllerConfiguration parentConfiguration); } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceConfigurationResolver.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceConfigurationResolver.java index 06ae7ec683..471b0f6a8e 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceConfigurationResolver.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceConfigurationResolver.java @@ -8,7 +8,6 @@ import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.Utils; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; -import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; @SuppressWarnings({"rawtypes", "unchecked"}) public class DependentResourceConfigurationResolver { @@ -20,39 +19,18 @@ private DependentResourceConfigurationResolver() {} private static final Map, ConfigurationConverter> knownConverters = new HashMap<>(); - public static > void configure( - DependentResource dependentResource, DependentResourceSpec spec, C parentConfiguration) { - if (dependentResource instanceof DependentResourceConfigurator configurator) { - final var config = configurationFor(spec, parentConfiguration); - configurator.configureWith(config); - } - } - - public static > Object configurationFor( - DependentResourceSpec spec, C parentConfiguration) { - // first check if the parent configuration has potentially already resolved the configuration - if (parentConfiguration instanceof DependentResourceConfigurationProvider provider) { - final var configuration = provider.getConfigurationFor(spec); - if (configuration != null) { - return configuration; - } - } - - // find Configured-annotated class if it exists - return extractConfigurationFromConfigured(spec.getDependentResourceClass(), - parentConfiguration); - } - - public static > Object extractConfigurationFromConfigured( - Class dependentResourceClass, C parentConfiguration) { + public static > void configureSpecFromConfigured( + DependentResourceSpec spec, + C parentConfiguration, + Class dependentResourceClass) { var converterAnnotationPair = converters.get(dependentResourceClass); Annotation configAnnotation; if (converterAnnotationPair == null) { var configuredClassPair = getConfigured(dependentResourceClass); if (configuredClassPair == null) { - return null; + return; } // check if we already have a converter registered for the found Configured annotated class @@ -76,7 +54,8 @@ public static > Object // always called even if the annotation is null so that implementations can provide default // values - return converter.configFrom(configAnnotation, parentConfiguration, dependentResourceClass); + final var config = converter.configFrom(configAnnotation, spec, parentConfiguration); + spec.setNullableConfiguration(config); } private static ConfiguredClassPair getConfigured( diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceSpec.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceSpec.java index 1fcd0709fb..accccb3f6e 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceSpec.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceSpec.java @@ -8,23 +8,17 @@ import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition; -public class DependentResourceSpec { +public class DependentResourceSpec { private final Class> dependentResourceClass; - private final String name; - private final Set dependsOn; - private final Condition readyCondition; - private final Condition reconcileCondition; - private final Condition deletePostCondition; - private final Condition activationCondition; - private final String useEventSourceWithName; + private C nullableConfiguration; public DependentResourceSpec(Class> dependentResourceClass, String name, Set dependsOn, Condition readyCondition, @@ -62,7 +56,7 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - DependentResourceSpec that = (DependentResourceSpec) o; + DependentResourceSpec that = (DependentResourceSpec) o; return name.equals(that.name); } @@ -98,4 +92,13 @@ public Condition getActivationCondition() { public Optional getUseEventSourceWithName() { return Optional.ofNullable(useEventSourceWithName); } + + public Optional getConfiguration() { + return Optional.ofNullable(nullableConfiguration); + } + + protected void setNullableConfiguration(C configuration) { + this.nullableConfiguration = configuration; + } + } 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 5371975ec5..6fb37953df 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 @@ -7,10 +7,10 @@ import io.fabric8.kubernetes.api.model.GenericKubernetesResource; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.client.informers.cache.ItemStore; +import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.DefaultResourceConfiguration; import io.javaoperatorsdk.operator.api.config.ResourceConfiguration; import io.javaoperatorsdk.operator.api.config.Utils; -import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; import io.javaoperatorsdk.operator.processing.GroupVersionKind; import io.javaoperatorsdk.operator.processing.event.source.PrimaryToSecondaryMapper; import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper; @@ -20,21 +20,26 @@ import io.javaoperatorsdk.operator.processing.event.source.filter.OnUpdateFilter; import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.DEFAULT_NAMESPACES_SET; +import static io.javaoperatorsdk.operator.api.reconciler.Constants.*; public interface InformerConfiguration extends ResourceConfiguration { + boolean DEFAULT_FOLLOW_CONTROLLER_NAMESPACES_ON_CHANGE = true; + class DefaultInformerConfiguration extends DefaultResourceConfiguration implements InformerConfiguration { + private final String name; private final PrimaryToSecondaryMapper primaryToSecondaryMapper; private final SecondaryToPrimaryMapper secondaryToPrimaryMapper; private final boolean followControllerNamespaceChanges; private final OnDeleteFilter onDeleteFilter; private final GroupVersionKind groupVersionKind; - protected DefaultInformerConfiguration(String labelSelector, + protected DefaultInformerConfiguration( + String name, + String labelSelector, Class resourceClass, GroupVersionKind groupVersionKind, PrimaryToSecondaryMapper primaryToSecondaryMapper, @@ -47,6 +52,7 @@ protected DefaultInformerConfiguration(String labelSelector, ItemStore itemStore, Long informerListLimit) { super(resourceClass, namespaces, labelSelector, onAddFilter, onUpdateFilter, genericFilter, itemStore, informerListLimit); + this.name = name; this.followControllerNamespaceChanges = followControllerNamespaceChanges; this.groupVersionKind = groupVersionKind; this.primaryToSecondaryMapper = primaryToSecondaryMapper; @@ -75,9 +81,28 @@ public

PrimaryToSecondaryMapper

getPrimaryToSecondary return (PrimaryToSecondaryMapper

) primaryToSecondaryMapper; } + @Override public Optional getGroupVersionKind() { return Optional.ofNullable(groupVersionKind); } + + @Override + public String name() { + return name; + } + + public boolean inheritsNamespacesFromController() { + return InformerConfiguration.inheritsNamespacesFromController(getNamespaces()); + } + + @Override + public Set getEffectiveNamespaces(ControllerConfiguration controllerConfiguration) { + if (inheritsNamespacesFromController()) { + return controllerConfiguration.getEffectiveNamespaces(); + } else { + return super.getEffectiveNamespaces(controllerConfiguration); + } + } } /** @@ -117,23 +142,31 @@ public Optional getGroupVersionKind() { Optional getGroupVersionKind(); - @SuppressWarnings("unused") + String name(); + + static boolean inheritsNamespacesFromController(Set namespaces) { + return SAME_AS_CONTROLLER_NAMESPACES_SET.equals(namespaces); + } + + @SuppressWarnings({"unused", "UnusedReturnValue"}) class InformerConfigurationBuilder { private final Class resourceClass; private final GroupVersionKind groupVersionKind; + private final Class primaryResourceClass; + private String name; private PrimaryToSecondaryMapper primaryToSecondaryMapper; private SecondaryToPrimaryMapper secondaryToPrimaryMapper; - private Set namespaces; + private Set namespaces = SAME_AS_CONTROLLER_NAMESPACES_SET; private String labelSelector; private OnAddFilter onAddFilter; private OnUpdateFilter onUpdateFilter; private OnDeleteFilter onDeleteFilter; private GenericFilter genericFilter; - private boolean inheritControllerNamespacesOnChange = false; private ItemStore itemStore; private Long informerListLimit; - private final Class primaryResourceClass; + private boolean followControllerNamespacesOnChange = + DEFAULT_FOLLOW_CONTROLLER_NAMESPACES_ON_CHANGE; private InformerConfigurationBuilder(Class resourceClass, Class primaryResourceClass) { @@ -153,6 +186,11 @@ private InformerConfigurationBuilder(Class resourceClass, this.primaryResourceClass = primaryResourceClass; } + public InformerConfigurationBuilder withName(String name) { + this.name = name; + return this; + } + public

InformerConfigurationBuilder withPrimaryToSecondaryMapper( PrimaryToSecondaryMapper

primaryToSecondaryMapper) { this.primaryToSecondaryMapper = primaryToSecondaryMapper; @@ -187,25 +225,22 @@ public InformerConfigurationBuilder withNamespaces(Set namespaces) { public InformerConfigurationBuilder withNamespaces(Set namespaces, boolean followChanges) { this.namespaces = namespaces != null ? namespaces : DEFAULT_NAMESPACES_SET; - this.inheritControllerNamespacesOnChange = true; + this.followControllerNamespacesOnChange = followChanges; return this; } - /** - * Configures the informer to watch and track the same namespaces as the parent - * {@link io.javaoperatorsdk.operator.processing.Controller}, meaning that the informer will be - * restarted to watch the new namespaces if the parent controller's namespace configuration - * changes. - * - * @param context {@link EventSourceContext} from which the parent - * {@link io.javaoperatorsdk.operator.processing.Controller}'s configuration is retrieved - * @param

the primary resource type associated with the parent controller - * @return the builder instance so that calls can be chained fluently - */ - public

InformerConfigurationBuilder withNamespacesInheritedFromController( - EventSourceContext

context) { - namespaces = context.getControllerConfiguration().getEffectiveNamespaces(); - this.inheritControllerNamespacesOnChange = true; + public

InformerConfigurationBuilder withNamespacesInheritedFromController() { + this.namespaces = SAME_AS_CONTROLLER_NAMESPACES_SET; + return this; + } + + public

InformerConfigurationBuilder withWatchAllNamespaces() { + this.namespaces = WATCH_ALL_NAMESPACE_SET; + return this; + } + + public

InformerConfigurationBuilder withWatchCurrentNamespace() { + this.namespaces = WATCH_CURRENT_NAMESPACE_SET; return this; } @@ -217,8 +252,9 @@ public

InformerConfigurationBuilder withNamespacesInh * controller's namespaces are reconfigured, {@code false} otherwise * @return the builder instance so that calls can be chained fluently */ - public InformerConfigurationBuilder followNamespaceChanges(boolean followChanges) { - this.inheritControllerNamespacesOnChange = followChanges; + public InformerConfigurationBuilder followControllerNamespacesOnChange( + boolean followChanges) { + this.followControllerNamespacesOnChange = followChanges; return this; } @@ -267,13 +303,28 @@ public InformerConfigurationBuilder withInformerListLimit(Long informerListLi return this; } + public String getName() { + return name; + } + + public SecondaryToPrimaryMapper getSecondaryToPrimaryMapper() { + return secondaryToPrimaryMapper; + } + public InformerConfiguration build() { - return new DefaultInformerConfiguration<>(labelSelector, resourceClass, groupVersionKind, + if (groupVersionKind != null + && !GenericKubernetesResource.class.isAssignableFrom(resourceClass)) { + throw new IllegalStateException( + "If GroupVersionKind is set the resource type must be GenericKubernetesDependentResource"); + } + + return new DefaultInformerConfiguration<>(name, labelSelector, resourceClass, + groupVersionKind, primaryToSecondaryMapper, Objects.requireNonNullElse(secondaryToPrimaryMapper, Mappers.fromOwnerReferences(HasMetadata.getApiVersion(primaryResourceClass), HasMetadata.getKind(primaryResourceClass), false)), - namespaces, inheritControllerNamespacesOnChange, onAddFilter, onUpdateFilter, + namespaces, followControllerNamespacesOnChange, onAddFilter, onUpdateFilter, onDeleteFilter, genericFilter, itemStore, informerListLimit); } } @@ -283,31 +334,6 @@ static InformerConfigurationBuilder from( return new InformerConfigurationBuilder<>(resourceClass, primaryResourceClass); } - /** - * Creates a configuration builder that inherits namespaces from the controller and follows - * namespaces changes. - * - * @param resourceClass secondary resource class - * @param eventSourceContext of the initializer - * @return builder - * @param secondary resource type - */ - static InformerConfigurationBuilder from( - Class resourceClass, EventSourceContext eventSourceContext) { - return new InformerConfigurationBuilder<>(resourceClass, - eventSourceContext.getPrimaryResourceClass()) - .withNamespacesInheritedFromController(eventSourceContext); - } - - /** - * For the case when want to use {@link GenericKubernetesResource} - */ - static InformerConfigurationBuilder from( - GroupVersionKind groupVersionKind, EventSourceContext eventSourceContext) { - return new InformerConfigurationBuilder(groupVersionKind, - eventSourceContext.getPrimaryResourceClass()) - .withNamespacesInheritedFromController(eventSourceContext); - } static InformerConfigurationBuilder from( GroupVersionKind groupVersionKind, Class primaryResourceClass) { diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Constants.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Constants.java index 9876fda558..594fcddd09 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Constants.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Constants.java @@ -5,21 +5,23 @@ public final class Constants { - public static final Set DEFAULT_NAMESPACES_SET = + public static final String WATCH_CURRENT_NAMESPACE = "JOSDK_WATCH_CURRENT"; + public static final String WATCH_ALL_NAMESPACES = "JOSDK_ALL_NAMESPACES"; + public static final String SAME_AS_CONTROLLER = "JOSDK_SAME_AS_CONTROLLER"; + + public static final Set WATCH_ALL_NAMESPACE_SET = Collections.singleton(Constants.WATCH_ALL_NAMESPACES); public static final Set WATCH_CURRENT_NAMESPACE_SET = Collections.singleton(Constants.WATCH_CURRENT_NAMESPACE); - public static final Set SAME_AS_CONTROLLER_NAMESPACES_SET = Collections.singleton(Constants.SAME_AS_CONTROLLER); + public static final Set DEFAULT_NAMESPACES_SET = WATCH_ALL_NAMESPACE_SET; + public static final String NO_VALUE_SET = ""; public static final long NO_LONG_VALUE_SET = -1L; - public static final String WATCH_CURRENT_NAMESPACE = "JOSDK_WATCH_CURRENT"; - public static final String WATCH_ALL_NAMESPACES = "JOSDK_ALL_NAMESPACES"; public static final long NO_MAX_RECONCILIATION_INTERVAL = -1L; - public static final String SAME_AS_CONTROLLER = "JOSDK_SAME_AS_CONTROLLER"; public static final String RESOURCE_GVK_KEY = "josdk.resource.gvk"; public static final String CONTROLLER_NAME = "controller.name"; diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceFactory.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceFactory.java index e9e47f6d97..105d2b6c75 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceFactory.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceFactory.java @@ -3,19 +3,28 @@ import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.Utils; import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; - -import static io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfigurationResolver.configure; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.ConfiguredDependentResource; @SuppressWarnings({"rawtypes", "unchecked"}) public interface DependentResourceFactory> { DependentResourceFactory DEFAULT = new DependentResourceFactory() {}; - default DependentResource createFrom(DependentResourceSpec spec, C configuration) { + default DependentResource createFrom(DependentResourceSpec spec, C controllerConfiguration) { final var dependentResourceClass = spec.getDependentResourceClass(); return Utils.instantiateAndConfigureIfNeeded(dependentResourceClass, DependentResource.class, - Utils.contextFor(configuration, dependentResourceClass, Dependent.class), - (instance) -> configure(instance, spec, configuration)); + Utils.contextFor(controllerConfiguration, dependentResourceClass, Dependent.class), + (instance) -> configure(instance, spec, controllerConfiguration)); + } + + default void configure(DependentResource instance, DependentResourceSpec spec, + C controllerConfiguration) { + if (instance instanceof ConfiguredDependentResource configurable) { + final var config = controllerConfiguration.getConfigurationFor(spec); + if (config != null) { + configurable.configureWith(config); + } + } } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/DependentResourceConfigurator.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/ConfiguredDependentResource.java similarity index 76% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/DependentResourceConfigurator.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/ConfiguredDependentResource.java index 2b361626aa..326482aab0 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/DependentResourceConfigurator.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/ConfiguredDependentResource.java @@ -2,7 +2,8 @@ import java.util.Optional; -public interface DependentResourceConfigurator { + +public interface ConfiguredDependentResource { void configureWith(C config); Optional configuration(); diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/GroupVersionKind.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/GroupVersionKind.java index 9e5cbea14d..55e87fb464 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/GroupVersionKind.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/GroupVersionKind.java @@ -32,6 +32,27 @@ public static GroupVersionKind gvkFor(Class resourceClass HasMetadata.getVersion(resourceClass), HasMetadata.getKind(resourceClass)); } + /** + * Parse GVK from a String representation. Expected format is: [group]/[version]/[kind] + *

+ * Sample: "apps/v1/Deployment" + *

+ * or: [version]/[kind] + *

+ * Sample: v1/ConfigMap + **/ + public static GroupVersionKind fromString(String gvk) { + String[] parts = gvk.split("/"); + if (parts.length == 3) { + return new GroupVersionKind(parts[0], parts[1], parts[2]); + } else if (parts.length == 2) { + return new GroupVersionKind(null, parts[0], parts[1]); + } else { + throw new IllegalArgumentException( + "Cannot parse gvk: " + gvk + ". Needs to be in form [group]/[version]/[kind]"); + } + } + public String getGroup() { return group; } @@ -72,4 +93,5 @@ public String toString() { ", kind='" + kind + '\'' + '}'; } + } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractEventSourceHolderDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractEventSourceHolderDependentResource.java index 6de936a5f8..6745a45a72 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractEventSourceHolderDependentResource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractEventSourceHolderDependentResource.java @@ -12,10 +12,6 @@ import io.javaoperatorsdk.operator.processing.event.EventSourceRetriever; import io.javaoperatorsdk.operator.processing.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.EventSource; -import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnUpdateFilter; @Ignore public abstract class AbstractEventSourceHolderDependentResource> @@ -24,10 +20,6 @@ public abstract class AbstractEventSourceHolderDependentResource resourceType; private boolean isCacheFillerEventSource; - protected OnAddFilter onAddFilter; - protected OnUpdateFilter onUpdateFilter; - protected OnDeleteFilter onDeleteFilter; - protected GenericFilter genericFilter; protected String eventSourceNameToUse; protected AbstractEventSourceHolderDependentResource(Class resourceType) { @@ -57,7 +49,6 @@ public synchronized Optional eventSource(EventSourceContext

context) { if (eventSource == null && eventSourceNameToUse == null) { setEventSource(createEventSource(context)); - applyFilters(); } return Optional.ofNullable(eventSource); } @@ -97,18 +88,11 @@ public Class resourceType() { protected abstract T createEventSource(EventSourceContext

context); - protected void setEventSource(T eventSource) { + public void setEventSource(T eventSource) { isCacheFillerEventSource = eventSource instanceof RecentOperationCacheFiller; this.eventSource = eventSource; } - protected void applyFilters() { - this.eventSource.setOnAddFilter(onAddFilter); - this.eventSource.setOnUpdateFilter(onUpdateFilter); - this.eventSource.setOnDeleteFilter(onDeleteFilter); - this.eventSource.setGenericFilter(genericFilter); - } - public Optional eventSource() { return Optional.ofNullable(eventSource); } @@ -132,15 +116,4 @@ private RecentOperationCacheFiller recentOperationCacheFiller() { return (RecentOperationCacheFiller) eventSource; } - public void setOnAddFilter(OnAddFilter onAddFilter) { - this.onAddFilter = onAddFilter; - } - - public void setOnUpdateFilter(OnUpdateFilter onUpdateFilter) { - this.onUpdateFilter = onUpdateFilter; - } - - public void setOnDeleteFilter(OnDeleteFilter onDeleteFilter) { - this.onDeleteFilter = onDeleteFilter; - } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/PerResourcePollingDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/PerResourcePollingDependentResource.java index 581698ffd6..f315619cde 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/PerResourcePollingDependentResource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/PerResourcePollingDependentResource.java @@ -27,10 +27,11 @@ public PerResourcePollingDependentResource(Class resourceType, Duration polli protected ExternalResourceCachingEventSource createEventSource( EventSourceContext

context) { - return new PerResourcePollingEventSource<>(name(), resourceType(), context, + return new PerResourcePollingEventSource<>(resourceType(), context, new PerResourcePollingConfigurationBuilder<>( this, getPollingPeriod()) .withCacheKeyMapper(this) + .withName(name()) .build()); } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/PollingDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/PollingDependentResource.java index 519771d82d..01860cb4c5 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/PollingDependentResource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/PollingDependentResource.java @@ -31,8 +31,8 @@ public PollingDependentResource(Class resourceType, Duration pollingPeriod, @Override protected ExternalResourceCachingEventSource createEventSource( EventSourceContext

context) { - return new PollingEventSource<>(name(), resourceType(), - new PollingConfiguration<>(this, getPollingPeriod(), cacheKeyMapper)); + return new PollingEventSource<>(resourceType(), + new PollingConfiguration<>(name(), this, getPollingPeriod(), cacheKeyMapper)); } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CRUDKubernetesDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CRUDKubernetesDependentResource.java index 5b0a1c3235..f4ccf647ed 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CRUDKubernetesDependentResource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CRUDKubernetesDependentResource.java @@ -22,4 +22,8 @@ public abstract class CRUDKubernetesDependentResource resourceType) { super(resourceType); } + + public CRUDKubernetesDependentResource(Class resourceType, String name) { + super(resourceType, name); + } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesDependentResource.java index ee27445231..3817d8dadc 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesDependentResource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesDependentResource.java @@ -2,8 +2,8 @@ import io.fabric8.kubernetes.api.model.GenericKubernetesResource; import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.api.config.Utils; import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; +import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; import io.javaoperatorsdk.operator.processing.GroupVersionKind; public class GenericKubernetesDependentResource

@@ -16,14 +16,9 @@ public GenericKubernetesDependentResource(GroupVersionKind groupVersionKind) { this.groupVersionKind = groupVersionKind; } - protected InformerConfiguration.InformerConfigurationBuilder informerConfigurationBuilder() { - return InformerConfiguration.from(groupVersionKind, getPrimaryResourceType()); - } - - @SuppressWarnings("unchecked") - @Override - protected Class

getPrimaryResourceType() { - return (Class

) Utils.getFirstTypeArgumentFromExtendedClass(getClass()); + protected InformerConfiguration.InformerConfigurationBuilder informerConfigurationBuilder( + EventSourceContext

context) { + return InformerConfiguration.from(groupVersionKind, context.getPrimaryResourceClass()); } @SuppressWarnings("unused") diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/InformerConfig.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/InformerConfig.java new file mode 100644 index 0000000000..04dc5bc56b --- /dev/null +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/InformerConfig.java @@ -0,0 +1,86 @@ +package io.javaoperatorsdk.operator.processing.dependent.kubernetes; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.javaoperatorsdk.operator.api.reconciler.Constants; +import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter; +import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter; +import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter; +import io.javaoperatorsdk.operator.processing.event.source.filter.OnUpdateFilter; + +import static io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration.DEFAULT_FOLLOW_CONTROLLER_NAMESPACES_ON_CHANGE; +import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_VALUE_SET; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface InformerConfig { + + String name() default NO_VALUE_SET; + + /** + * Specified which namespaces this Controller monitors for custom resources events. If no + * namespace is specified then the controller will monitor the namespaces configured for the + * controller. + * + * You can set a list of namespaces or also constants: + *

+ * + * @return the array of namespaces this controller monitors + */ + String[] namespaces() default {Constants.SAME_AS_CONTROLLER}; + + /** + * Optional label selector used to identify the set of custom resources the controller will act + * upon. The label selector can be made of multiple comma separated requirements that acts as a + * logical AND operator. + * + * @return the label selector + */ + String labelSelector() default NO_VALUE_SET; + + /** + * Optional {@link OnAddFilter} to filter events sent to this KubernetesDependent + * + * @return the {@link OnAddFilter} filter implementation to use, defaulting to the interface + * itself if no value is set + */ + Class onAddFilter() default OnAddFilter.class; + + /** + * Optional {@link OnUpdateFilter} to filter events sent to this KubernetesDependent + * + * @return the {@link OnUpdateFilter} filter implementation to use, defaulting to the interface + * itself if no value is set + */ + Class onUpdateFilter() default OnUpdateFilter.class; + + /** + * Optional {@link OnDeleteFilter} to filter events sent to this KubernetesDependent + * + * @return the {@link OnDeleteFilter} filter implementation to use, defaulting to the interface + * itself if no value is set + */ + Class onDeleteFilter() default OnDeleteFilter.class; + + /** + * Optional {@link GenericFilter} to filter events sent to this KubernetesDependent + * + * @return the {@link GenericFilter} filter implementation to use, defaulting to the interface + * itself if no value is set + */ + Class genericFilter() default GenericFilter.class; + + /** + * Set that in case of a runtime controller namespace changes, the informer should also follow the + * new namespace set. + */ + boolean followControllerNamespacesOnChange() default DEFAULT_FOLLOW_CONTROLLER_NAMESPACES_ON_CHANGE; + +} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependent.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependent.java index 572741dcbd..0c35751563 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependent.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependent.java @@ -5,70 +5,12 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import io.javaoperatorsdk.operator.api.reconciler.Constants; -import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnUpdateFilter; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_VALUE_SET; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) public @interface KubernetesDependent { - String[] DEFAULT_NAMESPACES = {Constants.SAME_AS_CONTROLLER}; - - /** - * Specified which namespaces this Controller monitors for custom resources events. If no - * namespace is specified then the controller will monitor the namespaces configured for the - * controller. - * - * @return the array of namespaces this controller monitors - */ - String[] namespaces() default {Constants.SAME_AS_CONTROLLER}; - - /** - * Optional label selector used to identify the set of custom resources the controller will act - * upon. The label selector can be made of multiple comma separated requirements that acts as a - * logical AND operator. - * - * @return the label selector - */ - String labelSelector() default NO_VALUE_SET; - - /** - * Optional {@link OnAddFilter} to filter events sent to this KubernetesDependent - * - * @return the {@link OnAddFilter} filter implementation to use, defaulting to the interface - * itself if no value is set - */ - Class onAddFilter() default OnAddFilter.class; - - /** - * Optional {@link OnUpdateFilter} to filter events sent to this KubernetesDependent - * - * @return the {@link OnUpdateFilter} filter implementation to use, defaulting to the interface - * itself if no value is set - */ - Class onUpdateFilter() default OnUpdateFilter.class; - - /** - * Optional {@link OnDeleteFilter} to filter events sent to this KubernetesDependent - * - * @return the {@link OnDeleteFilter} filter implementation to use, defaulting to the interface - * itself if no value is set - */ - Class onDeleteFilter() default OnDeleteFilter.class; - - /** - * Optional {@link GenericFilter} to filter events sent to this KubernetesDependent - * - * @return the {@link GenericFilter} filter implementation to use, defaulting to the interface - * itself if no value is set - */ - Class genericFilter() default GenericFilter.class; - /** * Creates the resource only if did not exist before, this applies only if SSA is used. */ @@ -85,4 +27,7 @@ * global configuration */ BooleanWithUndefined useSSA() default BooleanWithUndefined.UNDEFINED; + + InformerConfig informerConfig() default @InformerConfig; + } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentConverter.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentConverter.java index 493f0b0146..04c8e1167d 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentConverter.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentConverter.java @@ -1,12 +1,12 @@ package io.javaoperatorsdk.operator.processing.dependent.kubernetes; -import java.util.Arrays; import java.util.Set; import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.Utils; import io.javaoperatorsdk.operator.api.config.dependent.ConfigurationConverter; +import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; import io.javaoperatorsdk.operator.api.reconciler.Constants; import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter; import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter; @@ -16,49 +16,85 @@ import static io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResourceConfig.DEFAULT_CREATE_RESOURCE_ONLY_IF_NOT_EXISTING_WITH_SSA; public class KubernetesDependentConverter implements - ConfigurationConverter, KubernetesDependentResource> { + ConfigurationConverter> { @Override - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings("unchecked") public KubernetesDependentResourceConfig configFrom(KubernetesDependent configAnnotation, - ControllerConfiguration parentConfiguration, - Class> originatingClass) { - var namespaces = parentConfiguration.getNamespaces(); - var configuredNS = false; - String labelSelector = null; + DependentResourceSpec> spec, + ControllerConfiguration controllerConfig) { var createResourceOnlyIfNotExistingWithSSA = DEFAULT_CREATE_RESOURCE_ONLY_IF_NOT_EXISTING_WITH_SSA; - OnAddFilter onAddFilter = null; - OnUpdateFilter onUpdateFilter = null; - OnDeleteFilter onDeleteFilter = null; - GenericFilter genericFilter = null; + Boolean useSSA = null; if (configAnnotation != null) { - if (!Arrays.equals(KubernetesDependent.DEFAULT_NAMESPACES, configAnnotation.namespaces())) { - namespaces = Set.of(configAnnotation.namespaces()); - configuredNS = true; - } - - final var fromAnnotation = configAnnotation.labelSelector(); - labelSelector = Constants.NO_VALUE_SET.equals(fromAnnotation) ? null : fromAnnotation; - - final var context = Utils.contextFor(parentConfiguration, originatingClass, - configAnnotation.annotationType()); - onAddFilter = Utils.instantiate(configAnnotation.onAddFilter(), OnAddFilter.class, context); - onUpdateFilter = - Utils.instantiate(configAnnotation.onUpdateFilter(), OnUpdateFilter.class, context); - onDeleteFilter = - Utils.instantiate(configAnnotation.onDeleteFilter(), OnDeleteFilter.class, context); - genericFilter = - Utils.instantiate(configAnnotation.genericFilter(), GenericFilter.class, context); - createResourceOnlyIfNotExistingWithSSA = configAnnotation.createResourceOnlyIfNotExistingWithSSA(); useSSA = configAnnotation.useSSA().asBoolean(); } - return new KubernetesDependentResourceConfig(namespaces, labelSelector, configuredNS, - createResourceOnlyIfNotExistingWithSSA, - useSSA, onAddFilter, onUpdateFilter, onDeleteFilter, genericFilter); + var informerConfiguration = createInformerConfig(configAnnotation, + (DependentResourceSpec>) spec, + controllerConfig); + + return new KubernetesDependentResourceConfig<>(useSSA, createResourceOnlyIfNotExistingWithSSA, + informerConfiguration); } + + @SuppressWarnings({"unchecked"}) + private KubernetesDependentInformerConfig createInformerConfig( + KubernetesDependent configAnnotation, + DependentResourceSpec> spec, + ControllerConfiguration controllerConfig) { + Class> dependentResourceClass = + (Class>) spec.getDependentResourceClass(); + + final var config = new KubernetesDependentInformerConfigBuilder(); + if (configAnnotation != null) { + final var informerConfig = configAnnotation.informerConfig(); + if (informerConfig != null) { + + // override default name if more specific one is provided + if (!Constants.NO_VALUE_SET.equals(informerConfig.name())) { + config.withName(informerConfig.name()); + } + + var namespaces = Set.of(informerConfig.namespaces()); + config.withNamespaces(namespaces); + + final var fromAnnotation = informerConfig.labelSelector(); + var labelSelector = Constants.NO_VALUE_SET.equals(fromAnnotation) ? null : fromAnnotation; + config.withLabelSelector(labelSelector); + + final var context = Utils.contextFor(controllerConfig, dependentResourceClass, + configAnnotation.annotationType()); + + var onAddFilter = Utils.instantiate(informerConfig.onAddFilter(), + OnAddFilter.class, context); + config.withOnAddFilter(onAddFilter); + + var onUpdateFilter = + Utils.instantiate(informerConfig.onUpdateFilter(), + OnUpdateFilter.class, context); + config.withOnUpdateFilter(onUpdateFilter); + + var onDeleteFilter = + Utils.instantiate(informerConfig.onDeleteFilter(), + OnDeleteFilter.class, context); + config.withOnDeleteFilter(onDeleteFilter); + + var genericFilter = + Utils.instantiate(informerConfig.genericFilter(), + GenericFilter.class, + context); + + config.withGenericFilter(genericFilter); + + config.withFollowControllerNamespacesOnChange( + informerConfig.followControllerNamespacesOnChange()); + } + } + return config.build(); + } + } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentInformerConfig.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentInformerConfig.java new file mode 100644 index 0000000000..f4f1d29a68 --- /dev/null +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentInformerConfig.java @@ -0,0 +1,101 @@ +package io.javaoperatorsdk.operator.processing.dependent.kubernetes; + +import java.util.Set; + +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.client.informers.cache.ItemStore; +import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; +import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter; +import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter; +import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter; +import io.javaoperatorsdk.operator.processing.event.source.filter.OnUpdateFilter; + + +@SuppressWarnings("unused") +public class KubernetesDependentInformerConfig { + + private final String name; + private final Set namespaces; + private final boolean followControllerNamespacesOnChange; + private final String labelSelector; + private final OnAddFilter onAddFilter; + private final OnUpdateFilter onUpdateFilter; + private final OnDeleteFilter onDeleteFilter; + private final GenericFilter genericFilter; + private final ItemStore itemStore; + private final Long informerListLimit; + + public KubernetesDependentInformerConfig(String name, Set namespaces, + boolean followControllerNamespacesOnChange, + String labelSelector, OnAddFilter onAddFilter, + OnUpdateFilter onUpdateFilter, OnDeleteFilter onDeleteFilter, + GenericFilter genericFilter, ItemStore itemStore, Long informerListLimit) { + this.name = name; + this.namespaces = namespaces; + this.followControllerNamespacesOnChange = followControllerNamespacesOnChange; + this.labelSelector = labelSelector; + this.onAddFilter = onAddFilter; + this.onUpdateFilter = onUpdateFilter; + this.onDeleteFilter = onDeleteFilter; + this.genericFilter = genericFilter; + this.itemStore = itemStore; + this.informerListLimit = informerListLimit; + } + + public String getName() { + return name; + } + + public Set getNamespaces() { + return namespaces; + } + + public boolean isFollowControllerNamespacesOnChange() { + return followControllerNamespacesOnChange; + } + + public String getLabelSelector() { + return labelSelector; + } + + public OnAddFilter getOnAddFilter() { + return onAddFilter; + } + + public OnUpdateFilter getOnUpdateFilter() { + return onUpdateFilter; + } + + public OnDeleteFilter getOnDeleteFilter() { + return onDeleteFilter; + } + + public GenericFilter getGenericFilter() { + return genericFilter; + } + + public ItemStore getItemStore() { + return itemStore; + } + + public Long getInformerListLimit() { + return informerListLimit; + } + + void updateInformerConfigBuilder( + InformerConfiguration.InformerConfigurationBuilder builder) { + if (name != null) { + builder.withName(name); + } + builder.withNamespaces(namespaces); + builder.followControllerNamespacesOnChange(followControllerNamespacesOnChange); + builder.withLabelSelector(labelSelector); + builder.withItemStore(itemStore); + builder.withOnAddFilter(onAddFilter); + builder.withOnUpdateFilter(onUpdateFilter); + builder.withOnDeleteFilter(onDeleteFilter); + builder.withGenericFilter(genericFilter); + builder.withInformerListLimit(informerListLimit); + } + +} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentInformerConfigBuilder.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentInformerConfigBuilder.java new file mode 100644 index 0000000000..a8a60b9638 --- /dev/null +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentInformerConfigBuilder.java @@ -0,0 +1,93 @@ +package io.javaoperatorsdk.operator.processing.dependent.kubernetes; + +import java.util.Set; + +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.client.informers.cache.ItemStore; +import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter; +import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter; +import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter; +import io.javaoperatorsdk.operator.processing.event.source.filter.OnUpdateFilter; + +import static io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration.DEFAULT_FOLLOW_CONTROLLER_NAMESPACES_ON_CHANGE; +import static io.javaoperatorsdk.operator.api.reconciler.Constants.SAME_AS_CONTROLLER_NAMESPACES_SET; + +@SuppressWarnings({"UnusedReturnValue", "unused"}) +public final class KubernetesDependentInformerConfigBuilder { + + private String name; + private Set namespaces = SAME_AS_CONTROLLER_NAMESPACES_SET; + private boolean followControllerNamespacesOnChange = + DEFAULT_FOLLOW_CONTROLLER_NAMESPACES_ON_CHANGE; + private String labelSelector; + private OnAddFilter onAddFilter; + private OnUpdateFilter onUpdateFilter; + private OnDeleteFilter onDeleteFilter; + private GenericFilter genericFilter; + private ItemStore itemStore; + private Long informerListLimit; + + public KubernetesDependentInformerConfigBuilder() {} + + public KubernetesDependentInformerConfigBuilder withName(String name) { + this.name = name; + return this; + } + + public KubernetesDependentInformerConfigBuilder withNamespaces(Set namespaces) { + this.namespaces = namespaces; + return this; + } + + public KubernetesDependentInformerConfigBuilder withFollowControllerNamespacesOnChange( + boolean followControllerNamespacesOnChange) { + this.followControllerNamespacesOnChange = followControllerNamespacesOnChange; + return this; + } + + public KubernetesDependentInformerConfigBuilder withLabelSelector(String labelSelector) { + this.labelSelector = labelSelector; + return this; + } + + public KubernetesDependentInformerConfigBuilder withOnAddFilter( + OnAddFilter onAddFilter) { + this.onAddFilter = onAddFilter; + return this; + } + + public KubernetesDependentInformerConfigBuilder withOnUpdateFilter( + OnUpdateFilter onUpdateFilter) { + this.onUpdateFilter = onUpdateFilter; + return this; + } + + public KubernetesDependentInformerConfigBuilder withOnDeleteFilter( + OnDeleteFilter onDeleteFilter) { + this.onDeleteFilter = onDeleteFilter; + return this; + } + + public KubernetesDependentInformerConfigBuilder withGenericFilter( + GenericFilter genericFilter) { + this.genericFilter = genericFilter; + return this; + } + + public KubernetesDependentInformerConfigBuilder withItemStore(ItemStore itemStore) { + this.itemStore = itemStore; + return this; + } + + public KubernetesDependentInformerConfigBuilder withInformerListLimit(Long informerListLimit) { + this.informerListLimit = informerListLimit; + return this; + } + + public KubernetesDependentInformerConfig build() { + return new KubernetesDependentInformerConfig<>(name, namespaces, + followControllerNamespacesOnChange, + labelSelector, onAddFilter, onUpdateFilter, onDeleteFilter, genericFilter, itemStore, + informerListLimit); + } +} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java index f10e4a1af6..8663081460 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java @@ -11,17 +11,14 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.Namespaced; import io.fabric8.kubernetes.client.dsl.Resource; -import io.javaoperatorsdk.operator.OperatorException; import io.javaoperatorsdk.operator.ReconcilerUtils; -import io.javaoperatorsdk.operator.api.config.Utils; import io.javaoperatorsdk.operator.api.config.dependent.Configured; import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; -import io.javaoperatorsdk.operator.api.reconciler.Constants; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; import io.javaoperatorsdk.operator.api.reconciler.Ignore; import io.javaoperatorsdk.operator.api.reconciler.dependent.GarbageCollected; -import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.ConfiguredDependentResource; import io.javaoperatorsdk.operator.processing.dependent.AbstractEventSourceHolderDependentResource; import io.javaoperatorsdk.operator.processing.dependent.Matcher.Result; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.updatermatcher.GenericResourceUpdaterMatcher; @@ -30,12 +27,13 @@ import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers; + @Ignore @Configured(by = KubernetesDependent.class, with = KubernetesDependentResourceConfig.class, converter = KubernetesDependentConverter.class) public abstract class KubernetesDependentResource extends AbstractEventSourceHolderDependentResource> - implements DependentResourceConfigurator> { + implements ConfiguredDependentResource> { private static final Logger log = LoggerFactory.getLogger(KubernetesDependentResource.class); private final boolean garbageCollected = this instanceof GarbageCollected; @@ -43,8 +41,7 @@ public abstract class KubernetesDependentResource updaterMatcher = usingCustomResourceUpdateMatcher ? (ResourceUpdaterMatcher) this - : GenericResourceUpdaterMatcher.updaterMatcherFor(resourceType()); - private final boolean clustered; + : GenericResourceUpdaterMatcher.updaterMatcherFor(); private KubernetesDependentResourceConfig kubernetesDependentResourceConfig; public KubernetesDependentResource(Class resourceType) { @@ -53,19 +50,6 @@ public KubernetesDependentResource(Class resourceType) { public KubernetesDependentResource(Class resourceType, String name) { super(resourceType, name); - final var primaryResourceType = getPrimaryResourceType(); - clustered = !Namespaced.class.isAssignableFrom(primaryResourceType); - } - - protected KubernetesDependentResource(Class resourceType, String name, - boolean primaryIsClustered) { - super(resourceType, name); - clustered = primaryIsClustered; - } - - @SuppressWarnings("unchecked") - protected Class

getPrimaryResourceType() { - return (Class

) Utils.getTypeArgumentFromExtendedClassByIndex(getClass(), 1); } @Override @@ -73,49 +57,6 @@ public void configureWith(KubernetesDependentResourceConfig config) { this.kubernetesDependentResourceConfig = config; } - private void configureWith(String labelSelector, Set namespaces, - boolean inheritNamespacesOnChange, EventSourceContext

context) { - - if (namespaces.equals(Constants.SAME_AS_CONTROLLER_NAMESPACES_SET)) { - namespaces = context.getControllerConfiguration().getNamespaces(); - } - - var ic = informerConfigurationBuilder() - .withLabelSelector(labelSelector) - .withSecondaryToPrimaryMapper(getSecondaryToPrimaryMapper()) - .withNamespaces(namespaces, inheritNamespacesOnChange) - .build(); - - configureWith(new InformerEventSource<>(name(), ic, context)); - } - - // just to seamlessly handle GenericKubernetesDependentResource - protected InformerConfiguration.InformerConfigurationBuilder informerConfigurationBuilder() { - return InformerConfiguration.from(resourceType(), getPrimaryResourceType()); - } - - @SuppressWarnings("unchecked") - private SecondaryToPrimaryMapper getSecondaryToPrimaryMapper() { - if (this instanceof SecondaryToPrimaryMapper) { - return (SecondaryToPrimaryMapper) this; - } else if (garbageCollected) { - return Mappers.fromOwnerReferences(getPrimaryResourceType(), clustered); - } else if (useNonOwnerRefBasedSecondaryToPrimaryMapping()) { - return Mappers.fromDefaultAnnotations(); - } else { - throw new OperatorException("Provide a SecondaryToPrimaryMapper to associate " + - "this resource with the primary resource. DependentResource: " + getClass().getName()); - } - } - - /** - * Use to share informers between event more resources. - * - * @param informerEventSource informer to use - */ - public void configureWith(InformerEventSource informerEventSource) { - setEventSource(informerEventSource); - } @SuppressWarnings("unused") public R create(R desired, P primary, Context

context) { @@ -164,11 +105,10 @@ public Result match(R actualResource, P primary, Context

context) { return match(actualResource, desired, primary, updaterMatcher, context); } - @SuppressWarnings({"unused", "unchecked"}) + @SuppressWarnings({"unused"}) public Result match(R actualResource, R desired, P primary, Context

context) { return match(actualResource, desired, primary, - (ResourceUpdaterMatcher) GenericResourceUpdaterMatcher - .updaterMatcherFor(actualResource.getClass()), + GenericResourceUpdaterMatcher.updaterMatcherFor(), context); } @@ -209,15 +149,16 @@ protected boolean useSSA(Context

context) { if (usingCustomResourceUpdateMatcher) { return false; } - Optional useSSAConfig = - configuration().flatMap(KubernetesDependentResourceConfig::useSSA); + var useSSAConfig = configuration() + .map(KubernetesDependentResourceConfig::useSSA) + .orElse(null); var configService = context.getControllerConfiguration().getConfigurationService(); // don't use SSA for certain resources by default, only if explicitly overriden - if (useSSAConfig.isEmpty() && configService.defaultNonSSAResource().contains(resourceType())) { + if (useSSAConfig == null && configService.defaultNonSSAResource().contains(resourceType())) { return false; } - return useSSAConfig.orElse(context.getControllerConfiguration().getConfigurationService() - .ssaBasedCreateUpdateMatchForDependentResources()); + return Optional.ofNullable(useSSAConfig) + .orElse(configService.ssaBasedCreateUpdateMatchForDependentResources()); } private boolean usePreviousAnnotation(Context

context) { @@ -257,27 +198,31 @@ protected void addReferenceHandlingMetadata(R desired, P primary) { } @Override - @SuppressWarnings("unchecked") protected InformerEventSource createEventSource(EventSourceContext

context) { - if (kubernetesDependentResourceConfig != null) { - // sets the filters for the dependent resource, which are applied by parent class - onAddFilter = kubernetesDependentResourceConfig.onAddFilter(); - onUpdateFilter = kubernetesDependentResourceConfig.onUpdateFilter(); - onDeleteFilter = kubernetesDependentResourceConfig.onDeleteFilter(); - genericFilter = kubernetesDependentResourceConfig.genericFilter(); - configureWith(kubernetesDependentResourceConfig.labelSelector(), - kubernetesDependentResourceConfig.namespaces(), - !kubernetesDependentResourceConfig.wereNamespacesConfigured(), context); - } else { - configureWith(null, context.getControllerConfiguration().getNamespaces(), - true, context); - log.warn( - "Using default configuration for {} KubernetesDependentResource, call configureWith to provide configuration", - resourceType().getSimpleName()); + final InformerConfiguration.InformerConfigurationBuilder configBuilder = + informerConfigurationBuilder(context) + .withSecondaryToPrimaryMapper(getSecondaryToPrimaryMapper(context).orElseThrow()) + .withName(name()); + + // update configuration from annotation if specified + if (kubernetesDependentResourceConfig != null + && kubernetesDependentResourceConfig.informerConfig() != null) { + kubernetesDependentResourceConfig.informerConfig().updateInformerConfigBuilder(configBuilder); } + + var es = new InformerEventSource<>(configBuilder.build(), context); + setEventSource(es); return eventSource().orElseThrow(); } + /** + * To handle {@link io.fabric8.kubernetes.api.model.GenericKubernetesResource} based dependents. + */ + protected InformerConfiguration.InformerConfigurationBuilder informerConfigurationBuilder( + EventSourceContext

context) { + return InformerConfiguration.from(resourceType(), context.getPrimaryResourceClass()); + } + private boolean useNonOwnerRefBasedSecondaryToPrimaryMapping() { return !garbageCollected && isCreatable(); } @@ -339,4 +284,20 @@ public boolean isDeletable() { return super.isDeletable() && !garbageCollected; } + @SuppressWarnings("unchecked") + protected Optional> getSecondaryToPrimaryMapper( + EventSourceContext

context) { + if (this instanceof SecondaryToPrimaryMapper) { + return Optional.of((SecondaryToPrimaryMapper) this); + } else { + var clustered = !Namespaced.class.isAssignableFrom(context.getPrimaryResourceClass()); + if (garbageCollected) { + return Optional + .of(Mappers.fromOwnerReferences(context.getPrimaryResourceClass(), clustered)); + } else if (isCreatable()) { + return Optional.of(Mappers.fromDefaultAnnotations()); + } + } + return Optional.empty(); + } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResourceConfig.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResourceConfig.java index e302ad437a..e5d5c23c40 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResourceConfig.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResourceConfig.java @@ -1,98 +1,35 @@ package io.javaoperatorsdk.operator.processing.dependent.kubernetes; -import java.util.Optional; -import java.util.Set; -import io.javaoperatorsdk.operator.api.reconciler.Constants; -import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnUpdateFilter; +import io.fabric8.kubernetes.api.model.HasMetadata; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_VALUE_SET; -public class KubernetesDependentResourceConfig { +public class KubernetesDependentResourceConfig { public static final boolean DEFAULT_CREATE_RESOURCE_ONLY_IF_NOT_EXISTING_WITH_SSA = true; - private Set namespaces; - private String labelSelector; - private final boolean namespacesWereConfigured; - private final boolean createResourceOnlyIfNotExistingWithSSA; private final Boolean useSSA; + private final boolean createResourceOnlyIfNotExistingWithSSA; + private final KubernetesDependentInformerConfig informerConfig; - private final OnAddFilter onAddFilter; - private final OnUpdateFilter onUpdateFilter; - private final OnDeleteFilter onDeleteFilter; - private final GenericFilter genericFilter; - - public KubernetesDependentResourceConfig() { - this(Constants.SAME_AS_CONTROLLER_NAMESPACES_SET, NO_VALUE_SET, true, - DEFAULT_CREATE_RESOURCE_ONLY_IF_NOT_EXISTING_WITH_SSA, - null, null, - null, null, null); - } - - public KubernetesDependentResourceConfig(Set namespaces, - String labelSelector, - boolean configuredNS, - boolean createResourceOnlyIfNotExistingWithSSA, + public KubernetesDependentResourceConfig( Boolean useSSA, - OnAddFilter onAddFilter, - OnUpdateFilter onUpdateFilter, - OnDeleteFilter onDeleteFilter, GenericFilter genericFilter) { - this.namespaces = namespaces; - this.labelSelector = labelSelector; - this.namespacesWereConfigured = configuredNS; - this.createResourceOnlyIfNotExistingWithSSA = createResourceOnlyIfNotExistingWithSSA; - this.onAddFilter = onAddFilter; - this.onUpdateFilter = onUpdateFilter; - this.onDeleteFilter = onDeleteFilter; - this.genericFilter = genericFilter; + boolean createResourceOnlyIfNotExistingWithSSA, + KubernetesDependentInformerConfig informerConfig) { this.useSSA = useSSA; - } - - public Set namespaces() { - return namespaces; - } - - public String labelSelector() { - return labelSelector; - } - - public boolean wereNamespacesConfigured() { - return namespacesWereConfigured; - } - - @SuppressWarnings("rawtypes") - public OnAddFilter onAddFilter() { - return onAddFilter; + this.createResourceOnlyIfNotExistingWithSSA = createResourceOnlyIfNotExistingWithSSA; + this.informerConfig = informerConfig; } public boolean createResourceOnlyIfNotExistingWithSSA() { return createResourceOnlyIfNotExistingWithSSA; } - public OnUpdateFilter onUpdateFilter() { - return onUpdateFilter; - } - - public OnDeleteFilter onDeleteFilter() { - return onDeleteFilter; - } - - public GenericFilter genericFilter() { - return genericFilter; - } - - @SuppressWarnings("unused") - protected void setNamespaces(Set namespaces) { - if (!wereNamespacesConfigured() && namespaces != null && !namespaces.isEmpty()) { - this.namespaces = namespaces; - } + public Boolean useSSA() { + return useSSA; } - public Optional useSSA() { - return Optional.ofNullable(useSSA); + public KubernetesDependentInformerConfig informerConfig() { + return informerConfig; } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResourceConfigBuilder.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResourceConfigBuilder.java index 854ec7a56f..42bc379b06 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResourceConfigBuilder.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResourceConfigBuilder.java @@ -1,78 +1,37 @@ package io.javaoperatorsdk.operator.processing.dependent.kubernetes; -import java.util.Set; -import io.javaoperatorsdk.operator.api.reconciler.Constants; -import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter; -import io.javaoperatorsdk.operator.processing.event.source.filter.OnUpdateFilter; +import io.fabric8.kubernetes.api.model.HasMetadata; -public final class KubernetesDependentResourceConfigBuilder { +public final class KubernetesDependentResourceConfigBuilder { - private Set namespaces = Constants.SAME_AS_CONTROLLER_NAMESPACES_SET; - private String labelSelector; private boolean createResourceOnlyIfNotExistingWithSSA; - private Boolean useSSA; - private OnAddFilter onAddFilter; - private OnUpdateFilter onUpdateFilter; - private OnDeleteFilter onDeleteFilter; - private GenericFilter genericFilter; + private Boolean useSSA = null; + private KubernetesDependentInformerConfig kubernetesDependentInformerConfig; public KubernetesDependentResourceConfigBuilder() {} - public static KubernetesDependentResourceConfigBuilder aKubernetesDependentResourceConfig() { - return new KubernetesDependentResourceConfigBuilder<>(); - } - - public KubernetesDependentResourceConfigBuilder withNamespaces(Set namespaces) { - this.namespaces = namespaces; - return this; - } - - public KubernetesDependentResourceConfigBuilder withLabelSelector(String labelSelector) { - this.labelSelector = labelSelector; - return this; - } - + @SuppressWarnings("unused") public KubernetesDependentResourceConfigBuilder withCreateResourceOnlyIfNotExistingWithSSA( boolean createResourceOnlyIfNotExistingWithSSA) { this.createResourceOnlyIfNotExistingWithSSA = createResourceOnlyIfNotExistingWithSSA; return this; } - public KubernetesDependentResourceConfigBuilder withUseSSA(Boolean useSSA) { + public KubernetesDependentResourceConfigBuilder withUseSSA(boolean useSSA) { this.useSSA = useSSA; return this; } - public KubernetesDependentResourceConfigBuilder withOnAddFilter(OnAddFilter onAddFilter) { - this.onAddFilter = onAddFilter; - return this; - } - - public KubernetesDependentResourceConfigBuilder withOnUpdateFilter( - OnUpdateFilter onUpdateFilter) { - this.onUpdateFilter = onUpdateFilter; - return this; - } - - public KubernetesDependentResourceConfigBuilder withOnDeleteFilter( - OnDeleteFilter onDeleteFilter) { - this.onDeleteFilter = onDeleteFilter; - return this; - } - - public KubernetesDependentResourceConfigBuilder withGenericFilter( - GenericFilter genericFilter) { - this.genericFilter = genericFilter; + public KubernetesDependentResourceConfigBuilder withKubernetesDependentInformerConfig( + KubernetesDependentInformerConfig kubernetesDependentInformerConfig) { + this.kubernetesDependentInformerConfig = kubernetesDependentInformerConfig; return this; } public KubernetesDependentResourceConfig build() { - return new KubernetesDependentResourceConfig<>(namespaces, labelSelector, - namespaces != Constants.SAME_AS_CONTROLLER_NAMESPACES_SET, - createResourceOnlyIfNotExistingWithSSA, useSSA, onAddFilter, - onUpdateFilter, onDeleteFilter, genericFilter); + return new KubernetesDependentResourceConfig<>( + useSSA, createResourceOnlyIfNotExistingWithSSA, + kubernetesDependentInformerConfig); } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/GenericResourceUpdaterMatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/GenericResourceUpdaterMatcher.java index 16b72d6dce..418a5dc964 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/GenericResourceUpdaterMatcher.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/updatermatcher/GenericResourceUpdaterMatcher.java @@ -17,8 +17,7 @@ public class GenericResourceUpdaterMatcher implements protected GenericResourceUpdaterMatcher() {} @SuppressWarnings("unchecked") - public static ResourceUpdaterMatcher updaterMatcherFor( - Class resourceType) { + public static ResourceUpdaterMatcher updaterMatcherFor() { return (ResourceUpdaterMatcher) INSTANCE; } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/AbstractWorkflowExecutor.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/AbstractWorkflowExecutor.java index c22bf9d666..319b1a9e56 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/AbstractWorkflowExecutor.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/AbstractWorkflowExecutor.java @@ -135,13 +135,13 @@ protected void registerOrDeregisterEventSourceBasedOnActivation( if (dependentResourceNode.getActivationCondition().isPresent()) { final var dr = dependentResourceNode.getDependentResource(); final var eventSourceRetriever = context.eventSourceRetriever(); + var eventSource = + dr.eventSource(eventSourceRetriever.eventSourceContextForDynamicRegistration()); if (activationConditionMet) { - var eventSource = - dr.eventSource(eventSourceRetriever.eventSourceContextForDynamicRegistration()); var es = eventSource.orElseThrow(); eventSourceRetriever.dynamicallyRegisterEventSource(es); } else { - eventSourceRetriever.dynamicallyDeRegisterEventSource(dr.name()); + eventSourceRetriever.dynamicallyDeRegisterEventSource(eventSource.orElseThrow().name()); } } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/DefaultManagedWorkflow.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/DefaultManagedWorkflow.java index 43bb807e30..64f936c70d 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/DefaultManagedWorkflow.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/DefaultManagedWorkflow.java @@ -31,7 +31,7 @@ protected DefaultManagedWorkflow(List orderedSpecs, boole .map(DependentResourceSpec::getName) .collect(Collectors.toSet()); this.orderedSpecs = orderedSpecs; - for (DependentResourceSpec spec : orderedSpecs) { + for (DependentResourceSpec spec : orderedSpecs) { // add cycle detection? if (spec.getDependsOn().isEmpty()) { topLevelResources.add(spec.getName()); @@ -99,7 +99,7 @@ public Workflow

resolve(KubernetesClient client, } @SuppressWarnings({"rawtypes", "unchecked"}) - private DependentResource resolve(DependentResourceSpec spec, + private DependentResource resolve(DependentResourceSpec spec, KubernetesClient client, ControllerConfiguration

configuration) { final DependentResource dependentResource = diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java index c65d897734..2bb8c7a39a 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java @@ -138,8 +138,8 @@ public final synchronized void registerEventSource(EventSource eventSo Objects.requireNonNull(eventSource, "EventSource must not be null"); try { if (eventSource instanceof ManagedInformerEventSource managedInformerEventSource) { - managedInformerEventSource.setConfigurationService( - controller.getConfiguration().getConfigurationService()); + managedInformerEventSource.setControllerConfiguration( + controller.getConfiguration()); } eventSources.add(eventSource); eventSource.setEventHandler(controller.getEventProcessor()); diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSource.java index 3d66051e16..db457a4e41 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSource.java @@ -48,8 +48,7 @@ public ControllerEventSource(Controller controller) { .ifPresentOrElse(filter -> setOnUpdateFilter(filter.and(internalOnUpdateFilter)), () -> setOnUpdateFilter(internalOnUpdateFilter)); config.genericFilter().ifPresent(this::setGenericFilter); - - setConfigurationService(config.getConfigurationService()); + setControllerConfiguration(config); } @Override diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java index 571e02dbc2..67e5500b24 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java @@ -76,28 +76,21 @@ public class InformerEventSource private final PrimaryToSecondaryMapper

primaryToSecondaryMapper; private final String id = UUID.randomUUID().toString(); - public InformerEventSource(String name, - InformerConfiguration configuration, EventSourceContext

context) { - this(name, configuration, context.getClient(), - context.getControllerConfiguration().getConfigurationService() - .parseResourceVersionsForEventFilteringAndCaching()); - } - public InformerEventSource( InformerConfiguration configuration, EventSourceContext

context) { - this(null, configuration, context.getClient(), + this(configuration, context.getClient(), context.getControllerConfiguration().getConfigurationService() .parseResourceVersionsForEventFilteringAndCaching()); } public InformerEventSource(InformerConfiguration configuration, KubernetesClient client) { - this(null, configuration, client, false); + this(configuration, client, false); } - public InformerEventSource(String name, InformerConfiguration configuration, + public InformerEventSource(InformerConfiguration configuration, KubernetesClient client, boolean parseResourceVersions) { - super(name, + super(configuration.name(), configuration.getGroupVersionKind() .map(gvk -> client.genericKubernetesResources(gvk.apiVersion(), gvk.getKind())) .orElseGet(() -> (MixedOperation) client.resources(configuration.getResourceClass())), 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 a97897b1fa..d8f29e300d 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 @@ -18,7 +18,7 @@ import io.fabric8.kubernetes.client.informers.ResourceEventHandler; import io.javaoperatorsdk.operator.OperatorException; import io.javaoperatorsdk.operator.ReconcilerUtils; -import io.javaoperatorsdk.operator.api.config.ConfigurationService; +import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.ResourceConfiguration; import io.javaoperatorsdk.operator.health.InformerHealthIndicator; import io.javaoperatorsdk.operator.processing.LifecycleAware; @@ -28,49 +28,50 @@ import static io.javaoperatorsdk.operator.api.reconciler.Constants.WATCH_ALL_NAMESPACES; -public class InformerManager> - implements LifecycleAware, IndexerResourceCache { +public class InformerManager> + implements LifecycleAware, IndexerResourceCache { private static final Logger log = LoggerFactory.getLogger(InformerManager.class); - private final Map> sources = new ConcurrentHashMap<>(); + private final Map> sources = new ConcurrentHashMap<>(); private final C configuration; - private final MixedOperation, Resource> client; - private final ResourceEventHandler eventHandler; - private final Map>> indexers = new HashMap<>(); - private ConfigurationService configurationService; + private final MixedOperation, Resource> client; + private final ResourceEventHandler eventHandler; + private final Map>> indexers = new HashMap<>(); + private ControllerConfiguration controllerConfiguration; - InformerManager(MixedOperation, Resource> client, + InformerManager(MixedOperation, Resource> client, C configuration, - ResourceEventHandler eventHandler) { + ResourceEventHandler eventHandler) { this.client = client; this.configuration = configuration; this.eventHandler = eventHandler; } - void setConfigurationService(ConfigurationService configurationService) { - this.configurationService = configurationService; + void setControllerConfiguration(ControllerConfiguration controllerConfiguration) { + this.controllerConfiguration = controllerConfiguration; } @Override public void start() throws OperatorException { initSources(); // make sure informers are all started before proceeding further - configurationService.getExecutorServiceManager().boundedExecuteAndWaitForAllToComplete( - sources.values().stream(), - iw -> { - iw.start(); - return null; - }, - iw -> "InformerStarter-" + iw.getTargetNamespace() + "-" - + configuration.getResourceClass().getSimpleName()); + controllerConfiguration.getConfigurationService().getExecutorServiceManager() + .boundedExecuteAndWaitForAllToComplete( + sources.values().stream(), + iw -> { + iw.start(); + return null; + }, + iw -> "InformerStarter-" + iw.getTargetNamespace() + "-" + + configuration.getResourceClass().getSimpleName()); } private void initSources() { if (!sources.isEmpty()) { throw new IllegalStateException("Some sources already initialized."); } - final var targetNamespaces = configuration.getEffectiveNamespaces(configurationService); + final var targetNamespaces = configuration.getEffectiveNamespaces(controllerConfiguration); if (ResourceConfiguration.allNamespacesWatched(targetNamespaces)) { var source = createEventSourceForNamespace(WATCH_ALL_NAMESPACES); log.debug("Registered {} -> {} for any namespace", this, source); @@ -96,7 +97,7 @@ public void changeNamespaces(Set namespaces) { namespaces.forEach(ns -> { if (!sources.containsKey(ns)) { - final InformerWrapper source = createEventSourceForNamespace(ns); + final InformerWrapper source = createEventSourceForNamespace(ns); source.start(); log.debug("Registered new {} -> {} for namespace: {}", this, source, ns); @@ -105,8 +106,8 @@ public void changeNamespaces(Set namespaces) { } - private InformerWrapper createEventSourceForNamespace(String namespace) { - final InformerWrapper source; + private InformerWrapper createEventSourceForNamespace(String namespace) { + final InformerWrapper source; if (namespace.equals(WATCH_ALL_NAMESPACES)) { final var filteredBySelectorClient = client.inAnyNamespace().withLabelSelector(configuration.getLabelSelector()); @@ -120,13 +121,14 @@ private InformerWrapper createEventSourceForNamespace(String namespace) { return source; } - private InformerWrapper createEventSource( - FilterWatchListDeletable, Resource> filteredBySelectorClient, - ResourceEventHandler eventHandler, String namespaceIdentifier) { + private InformerWrapper createEventSource( + FilterWatchListDeletable, Resource> filteredBySelectorClient, + ResourceEventHandler eventHandler, String namespaceIdentifier) { var informer = configuration.getInformerListLimit().map(filteredBySelectorClient::withLimit) .orElse(filteredBySelectorClient).runnableInformer(0); configuration.getItemStore().ifPresent(informer::itemStore); - var source = new InformerWrapper<>(informer, configurationService, namespaceIdentifier); + var source = new InformerWrapper<>(informer, controllerConfiguration.getConfigurationService(), + namespaceIdentifier); source.addEventHandler(eventHandler); sources.put(namespaceIdentifier, source); return source; @@ -146,7 +148,7 @@ public void stop() { } @Override - public Stream list(Predicate predicate) { + public Stream list(Predicate predicate) { if (predicate == null) { return sources.values().stream().flatMap(IndexerResourceCache::list); } @@ -154,7 +156,7 @@ public Stream list(Predicate predicate) { } @Override - public Stream list(String namespace, Predicate predicate) { + public Stream list(String namespace, Predicate predicate) { if (isWatchingAllNamespaces()) { return getSource(WATCH_ALL_NAMESPACES) .map(source -> source.list(namespace, predicate)) @@ -167,12 +169,13 @@ public Stream list(String namespace, Predicate predicate) { } @Override - public Optional get(ResourceID resourceID) { + public Optional get(ResourceID resourceID) { return getSource(resourceID.getNamespace().orElse(WATCH_ALL_NAMESPACES)) .flatMap(source -> source.get(resourceID)) - .map(r -> configurationService.cloneSecondaryResourcesWhenGettingFromCache() - ? configurationService.getResourceCloner().clone(r) - : r); + .map(r -> controllerConfiguration.getConfigurationService() + .cloneSecondaryResourcesWhenGettingFromCache() + ? controllerConfiguration.getConfigurationService().getResourceCloner().clone(r) + : r); } @Override @@ -184,18 +187,18 @@ private boolean isWatchingAllNamespaces() { return sources.containsKey(WATCH_ALL_NAMESPACES); } - private Optional> getSource(String namespace) { + private Optional> getSource(String namespace) { namespace = isWatchingAllNamespaces() || namespace == null ? WATCH_ALL_NAMESPACES : namespace; return Optional.ofNullable(sources.get(namespace)); } @Override - public void addIndexers(Map>> indexers) { + public void addIndexers(Map>> indexers) { this.indexers.putAll(indexers); } @Override - public List byIndex(String indexName, String indexKey) { + public List byIndex(String indexName, String indexKey) { return sources.values().stream().map(s -> s.byIndex(indexName, indexKey)) .flatMap(List::stream).collect(Collectors.toList()); } @@ -206,7 +209,7 @@ public String toString() { return "InformerManager [" + ReconcilerUtils.getResourceTypeNameWithVersion(configuration.getResourceClass()) + "] watching: " - + configuration.getEffectiveNamespaces(configurationService) + + configuration.getEffectiveNamespaces(controllerConfiguration) + (selector != null ? " selector: " + selector : ""); } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSource.java index dcf0ab3d7e..0e5f8bd896 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSource.java @@ -16,7 +16,7 @@ import io.fabric8.kubernetes.client.dsl.MixedOperation; import io.fabric8.kubernetes.client.informers.ResourceEventHandler; import io.javaoperatorsdk.operator.OperatorException; -import io.javaoperatorsdk.operator.api.config.ConfigurationService; +import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.NamespaceChangeable; import io.javaoperatorsdk.operator.api.config.ResourceConfiguration; import io.javaoperatorsdk.operator.api.reconciler.dependent.RecentOperationCacheFiller; @@ -36,7 +36,7 @@ public abstract class ManagedInformerEventSource cache; private final boolean parseResourceVersions; - private ConfigurationService configurationService; + private ControllerConfiguration controllerConfiguration; private final C configuration; private final Map>> indexers = new HashMap<>(); protected TemporaryResourceCache temporaryResourceCache; @@ -85,7 +85,7 @@ public synchronized void start() { } temporaryResourceCache = new TemporaryResourceCache<>(this, parseResourceVersions); this.cache = new InformerManager<>(client, configuration, this); - cache.setConfigurationService(configurationService); + cache.setControllerConfiguration(controllerConfiguration); cache.addIndexers(indexers); manager().start(); super.start(); @@ -191,8 +191,8 @@ public String toString() { "}"; } - public void setConfigurationService(ConfigurationService configurationService) { - this.configurationService = configurationService; + public void setControllerConfiguration(ControllerConfiguration controllerConfiguration) { + this.controllerConfiguration = controllerConfiguration; } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/Mappers.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/Mappers.java index 24c4d18837..97ab1ef402 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/Mappers.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/Mappers.java @@ -136,4 +136,13 @@ public static SecondaryToPrim .collect(Collectors.toSet()); }; } + + public static class SecondaryToPrimaryFromDefaultAnnotation + implements SecondaryToPrimaryMapper { + @Override + public Set toPrimaryResourceIDs(HasMetadata resource) { + return Mappers.fromDefaultAnnotations().toPrimaryResourceIDs(resource); + } + } + } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingConfiguration.java index 23fa9e023a..52e1fbcd68 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingConfiguration.java @@ -9,17 +9,20 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.processing.event.source.CacheKeyMapper; -public record PerResourcePollingConfiguration(ScheduledExecutorService executorService, CacheKeyMapper cacheKeyMapper, +public record PerResourcePollingConfiguration(String name,ScheduledExecutorService executorService, CacheKeyMapper cacheKeyMapper, PerResourcePollingEventSource.ResourceFetcher resourceFetcher, Predicate

registerPredicate, Duration defaultPollingPeriod) { public static final int DEFAULT_EXECUTOR_THREAD_NUMBER = 1; - public PerResourcePollingConfiguration(ScheduledExecutorService executorService, + public PerResourcePollingConfiguration( + String name, + ScheduledExecutorService executorService, CacheKeyMapper cacheKeyMapper, PerResourcePollingEventSource.ResourceFetcher resourceFetcher, Predicate

registerPredicate, Duration defaultPollingPeriod) { + this.name = name; this.executorService = executorService == null ? new ScheduledThreadPoolExecutor(DEFAULT_EXECUTOR_THREAD_NUMBER) : executorService; this.cacheKeyMapper = cacheKeyMapper == null ? CacheKeyMapper.singleResourceCacheKeyMapper() : cacheKeyMapper; diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingConfigurationBuilder.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingConfigurationBuilder.java index ece10d347e..85b1fcf2b0 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingConfigurationBuilder.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingConfigurationBuilder.java @@ -12,6 +12,7 @@ public final class PerResourcePollingConfigurationBuilder resourceFetcher; + private String name; private Predicate

registerPredicate; private ScheduledExecutorService executorService; private CacheKeyMapper cacheKeyMapper; @@ -42,8 +43,13 @@ public PerResourcePollingConfigurationBuilder withCacheKeyMapper( return this; } + public PerResourcePollingConfigurationBuilder withName(String name) { + this.name = name; + return this; + } + public PerResourcePollingConfiguration build() { - return new PerResourcePollingConfiguration<>(executorService, cacheKeyMapper, + return new PerResourcePollingConfiguration<>(name, executorService, cacheKeyMapper, resourceFetcher, registerPredicate, defaultPollingPeriod); } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingEventSource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingEventSource.java index 2288e7eb75..983679a27a 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingEventSource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PerResourcePollingEventSource.java @@ -50,15 +50,12 @@ public class PerResourcePollingEventSource private final Predicate

registerPredicate; private final Duration period; - public PerResourcePollingEventSource(Class resourceClass, EventSourceContext

context, - PerResourcePollingConfiguration config) { - this(null, resourceClass, context, config); - } - public PerResourcePollingEventSource(String name, Class resourceClass, + + public PerResourcePollingEventSource(Class resourceClass, EventSourceContext

context, PerResourcePollingConfiguration config) { - super(name, resourceClass, config.cacheKeyMapper()); + super(config.name(), resourceClass, config.cacheKeyMapper()); this.primaryResourceCache = context.getPrimaryCache(); this.resourceFetcher = config.resourceFetcher(); this.registerPredicate = config.registerPredicate(); diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingConfiguration.java index 516d0546f7..c66ef38c8f 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingConfiguration.java @@ -5,11 +5,12 @@ import io.javaoperatorsdk.operator.processing.event.source.CacheKeyMapper; -public record PollingConfiguration(PollingEventSource.GenericResourceFetcher genericResourceFetcher, +public record PollingConfiguration(String name,PollingEventSource.GenericResourceFetcher genericResourceFetcher, Duration period, CacheKeyMapper cacheKeyMapper) { - public PollingConfiguration(PollingEventSource.GenericResourceFetcher genericResourceFetcher, Duration period, + public PollingConfiguration(String name,PollingEventSource.GenericResourceFetcher genericResourceFetcher, Duration period, CacheKeyMapper cacheKeyMapper) { + this.name = name; this.genericResourceFetcher = Objects.requireNonNull(genericResourceFetcher); this.period = period; this.cacheKeyMapper = diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingConfigurationBuilder.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingConfigurationBuilder.java index 576f8fdb56..c6bccefa82 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingConfigurationBuilder.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingConfigurationBuilder.java @@ -8,6 +8,7 @@ public final class PollingConfigurationBuilder { private final Duration period; private final PollingEventSource.GenericResourceFetcher genericResourceFetcher; private CacheKeyMapper cacheKeyMapper; + private String name; public PollingConfigurationBuilder(PollingEventSource.GenericResourceFetcher fetcher, Duration period) { @@ -20,7 +21,12 @@ public PollingConfigurationBuilder withCacheKeyMapper(CacheKeyMapper cache return this; } + public PollingConfigurationBuilder withName(String name) { + this.name = name; + return this; + } + public PollingConfiguration build() { - return new PollingConfiguration<>(genericResourceFetcher, period, cacheKeyMapper); + return new PollingConfiguration<>(name, genericResourceFetcher, period, cacheKeyMapper); } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingEventSource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingEventSource.java index 060128576c..6549030c4b 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingEventSource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingEventSource.java @@ -52,12 +52,10 @@ public class PollingEventSource private final Duration period; private final AtomicBoolean healthy = new AtomicBoolean(true); - public PollingEventSource(Class resourceClass, PollingConfiguration config) { - this(null, resourceClass, config); - } - public PollingEventSource(String name, Class resourceClass, PollingConfiguration config) { - super(name, resourceClass, config.cacheKeyMapper()); + + public PollingEventSource(Class resourceClass, PollingConfiguration config) { + super(config.name(), resourceClass, config.cacheKeyMapper()); this.genericResourceFetcher = config.genericResourceFetcher(); this.period = config.period(); } 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 e280009da2..1993c37ad1 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 @@ -19,14 +19,13 @@ import io.javaoperatorsdk.operator.api.reconciler.Workflow; import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; +import io.javaoperatorsdk.operator.api.reconciler.dependent.GarbageCollected; import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult; -import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; -import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; -import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; -import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResourceConfig; -import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResourceConfigBuilder; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.ConfiguredDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.*; import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition; +import static io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration.inheritsNamespacesFromController; import static org.junit.jupiter.api.Assertions.*; class ControllerConfigurationOverriderTest { @@ -66,18 +65,20 @@ void overridingNSShouldPreserveUntouchedDependents() { assertEquals(stringConfig, resourceConfig); } - @SuppressWarnings("rawtypes") + @SuppressWarnings({"unchecked", "rawtypes"}) private KubernetesDependentResourceConfig extractFirstDependentKubernetesResourceConfig( io.javaoperatorsdk.operator.api.config.ControllerConfiguration configuration) { - return (KubernetesDependentResourceConfig) extractDependentKubernetesResourceConfig( + var conf = (KubernetesDependentResourceConfig) extractDependentKubernetesResourceConfig( configuration, 0); + return conf; } - private Object extractDependentKubernetesResourceConfig( + @SuppressWarnings("unchecked") + private static Object extractDependentKubernetesResourceConfig( io.javaoperatorsdk.operator.api.config.ControllerConfiguration configuration, int index) { final var spec = configuration.getWorkflowSpec().orElseThrow().getDependentResourceSpecs().get(index); - return DependentResourceConfigurationResolver.configurationFor(spec, configuration); + return configuration.getConfigurationFor(spec); } private io.javaoperatorsdk.operator.api.config.ControllerConfiguration createConfiguration( @@ -171,8 +172,8 @@ void configuredDependentShouldNotChangeOnParentOverrideEvenWhenInitialConfigIsSa assertEquals(Set.of(OverriddenNSDependent.DEP_NS), configuration.getNamespaces()); // check that the DependentResource inherits has its own configured NS - assertEquals(1, config.namespaces().size()); - assertEquals(Set.of(OverriddenNSDependent.DEP_NS), config.namespaces()); + var informerConfig = config.informerConfig(); + assertEquals(Set.of(OverriddenNSDependent.DEP_NS), informerConfig.getNamespaces()); // override the parent's NS final var newNS = "bar"; @@ -181,8 +182,8 @@ void configuredDependentShouldNotChangeOnParentOverrideEvenWhenInitialConfigIsSa // check that dependent config is still using its own NS config = extractFirstDependentKubernetesResourceConfig(configuration); - assertEquals(1, config.namespaces().size()); - assertEquals(Set.of(OverriddenNSDependent.DEP_NS), config.namespaces()); + informerConfig = config.informerConfig(); + assertEquals(Set.of(OverriddenNSDependent.DEP_NS), informerConfig.getNamespaces()); } @SuppressWarnings("unchecked") @@ -193,17 +194,10 @@ void dependentShouldWatchAllNamespacesIfParentDoesAsWell() { var config = extractFirstDependentKubernetesResourceConfig(configuration); // check that the DependentResource inherits the controller's configuration if applicable - assertTrue(ResourceConfiguration.allNamespacesWatched(config.namespaces())); - - // override the NS - final var newNS = "bar"; - configuration = - ControllerConfigurationOverrider.override(configuration).settingNamespace(newNS).build(); + var informerConfig = config.informerConfig(); + assertTrue( + inheritsNamespacesFromController(informerConfig.getNamespaces())); - // check that dependent config is using the overridden namespace - config = extractFirstDependentKubernetesResourceConfig(configuration); - assertEquals(1, config.namespaces().size()); - assertEquals(Set.of(newNS), config.namespaces()); } @SuppressWarnings("unchecked") @@ -214,7 +208,9 @@ void shouldBePossibleToForceDependentToWatchAllNamespaces() { var config = extractFirstDependentKubernetesResourceConfig(configuration); // check that the DependentResource inherits the controller's configuration if applicable - assertTrue(ResourceConfiguration.allNamespacesWatched(config.namespaces())); + assertTrue( + ResourceConfiguration + .allNamespacesWatched(config.informerConfig().getNamespaces())); // override the NS final var newNS = "bar"; @@ -223,28 +219,20 @@ void shouldBePossibleToForceDependentToWatchAllNamespaces() { // check that dependent config is still configured to watch all NS config = extractFirstDependentKubernetesResourceConfig(configuration); - assertTrue(ResourceConfiguration.allNamespacesWatched(config.namespaces())); + assertTrue( + ResourceConfiguration + .allNamespacesWatched(config.informerConfig().getNamespaces())); } @Test + @SuppressWarnings("unchecked") void overridingNamespacesShouldBePropagatedToDependentsWithDefaultConfig() { var configuration = createConfiguration(new OneDepReconciler()); // retrieve the config for the first (and unique) dependent var config = extractFirstDependentKubernetesResourceConfig(configuration); // check that the DependentResource inherits the controller's configuration if applicable - assertEquals(1, config.namespaces().size()); - assertEquals(Set.of(OneDepReconciler.CONFIGURED_NS), config.namespaces()); - - // override the NS - final var newNS = "bar"; - configuration = - ControllerConfigurationOverrider.override(configuration).settingNamespace(newNS).build(); - - // check that dependent config is using the overridden namespace - config = extractFirstDependentKubernetesResourceConfig(configuration); - assertEquals(1, config.namespaces().size()); - assertEquals(Set.of(newNS), config.namespaces()); + assertEquals(1, config.informerConfig().getNamespaces().size()); } @Test @@ -254,8 +242,8 @@ void alreadyOverriddenDependentNamespacesShouldNotBePropagated() { var config = extractFirstDependentKubernetesResourceConfig(configuration); // DependentResource has its own NS - assertEquals(1, config.namespaces().size()); - assertEquals(Set.of(OverriddenNSDependent.DEP_NS), config.namespaces()); + assertEquals(Set.of(OverriddenNSDependent.DEP_NS), + config.informerConfig().getNamespaces()); // override the NS final var newNS = "bar"; @@ -264,12 +252,12 @@ void alreadyOverriddenDependentNamespacesShouldNotBePropagated() { // check that dependent config is still using its own NS config = extractFirstDependentKubernetesResourceConfig(configuration); - assertEquals(1, config.namespaces().size()); - assertEquals(Set.of(OverriddenNSDependent.DEP_NS), config.namespaces()); + assertEquals(Set.of(OverriddenNSDependent.DEP_NS), + config.informerConfig().getNamespaces()); } - @SuppressWarnings("rawtypes") @Test + @SuppressWarnings({"rawtypes", "unchecked"}) void replaceNamedDependentResourceConfigShouldWork() { var configuration = createConfiguration(new OneDepReconciler()); var dependents = configuration.getWorkflowSpec().orElseThrow().getDependentResourceSpecs(); @@ -283,36 +271,40 @@ void replaceNamedDependentResourceConfigShouldWork() { .filter(dr -> dr.getName().equals(dependentResourceName)) .findFirst().orElseThrow(); assertEquals(ReadOnlyDependent.class, dependentSpec.getDependentResourceClass()); - var maybeConfig = - DependentResourceConfigurationResolver.configurationFor(dependentSpec, configuration); + var maybeConfig = extractFirstDependentKubernetesResourceConfig(configuration); assertNotNull(maybeConfig); assertInstanceOf(KubernetesDependentResourceConfig.class, maybeConfig); var config = (KubernetesDependentResourceConfig) maybeConfig; // check that the DependentResource inherits the controller's configuration if applicable - assertEquals(1, config.namespaces().size()); - assertNull(config.labelSelector()); - assertEquals(Set.of(OneDepReconciler.CONFIGURED_NS), config.namespaces()); + var informerConfig = config.informerConfig(); + assertEquals(1, informerConfig.getNamespaces().size()); + assertNull(informerConfig.getLabelSelector()); // override the namespaces for the dependent resource final var overriddenNS = "newNS"; final var labelSelector = "foo=bar"; + KubernetesDependentInformerConfigBuilder anInformerConfig = + new KubernetesDependentInformerConfigBuilder<>(); + anInformerConfig.withNamespaces(Set.of(overriddenNS)); + anInformerConfig.withLabelSelector(labelSelector); final var overridden = ControllerConfigurationOverrider.override(configuration) .replacingNamedDependentResourceConfig( - DependentResource.defaultNameFor(ReadOnlyDependent.class), - new KubernetesDependentResourceConfigBuilder<>() - .withNamespaces(Set.of(overriddenNS)) - .withLabelSelector(labelSelector) + dependentResourceName, + new KubernetesDependentResourceConfigBuilder() + .withKubernetesDependentInformerConfig(anInformerConfig.build()) + .build()) .build(); dependents = overridden.getWorkflowSpec().orElseThrow().getDependentResourceSpecs(); - dependentSpec = dependents.stream().filter(dr -> dr.getName().equals(dependentResourceName)) - .findFirst().orElseThrow(); - config = (KubernetesDependentResourceConfig) DependentResourceConfigurationResolver - .configurationFor(dependentSpec, overridden); - assertEquals(1, config.namespaces().size()); - assertEquals(labelSelector, config.labelSelector()); - assertEquals(Set.of(overriddenNS), config.namespaces()); + dependentSpec = dependents.stream() + .filter(dr -> dr.getName().equals(dependentResourceName)) + .findFirst() + .orElseThrow(); + config = (KubernetesDependentResourceConfig) overridden.getConfigurationFor(dependentSpec); + informerConfig = config.informerConfig(); + assertEquals(labelSelector, informerConfig.getLabelSelector()); + assertEquals(Set.of(overriddenNS), informerConfig.getNamespaces()); // check that we still have the proper workflow configuration assertInstanceOf(TestCondition.class, dependentSpec.getReadyCondition()); } @@ -360,16 +352,19 @@ public UpdateControl reconcile(ConfigMap resource, Context } } - private static class ReadOnlyDependent extends KubernetesDependentResource { + public static class ReadOnlyDependent extends KubernetesDependentResource + implements GarbageCollected { public ReadOnlyDependent() { super(ConfigMap.class); } } - @KubernetesDependent(namespaces = Constants.WATCH_ALL_NAMESPACES) - private static class WatchAllNSDependent - extends KubernetesDependentResource { + @KubernetesDependent( + informerConfig = @InformerConfig(namespaces = Constants.WATCH_ALL_NAMESPACES)) + public static class WatchAllNSDependent + extends KubernetesDependentResource + implements GarbageCollected { public WatchAllNSDependent() { super(ConfigMap.class); @@ -378,7 +373,7 @@ public WatchAllNSDependent() { @Workflow(dependents = @Dependent(type = OverriddenNSDependent.class)) @ControllerConfiguration(namespaces = OverriddenNSOnDepReconciler.CONFIGURED_NS) - private static class OverriddenNSOnDepReconciler implements Reconciler { + public static class OverriddenNSOnDepReconciler implements Reconciler { private static final String CONFIGURED_NS = "parentNS"; @@ -388,9 +383,10 @@ public UpdateControl reconcile(ConfigMap resource, Context } } - @KubernetesDependent(namespaces = OverriddenNSDependent.DEP_NS) - private static class OverriddenNSDependent - extends KubernetesDependentResource { + @KubernetesDependent(informerConfig = @InformerConfig(namespaces = OverriddenNSDependent.DEP_NS)) + public static class OverriddenNSDependent + extends KubernetesDependentResource + implements GarbageCollected { private static final String DEP_NS = "dependentNS"; @@ -404,7 +400,7 @@ public OverriddenNSDependent() { @Dependent(type = NamedDependentReconciler.ExternalDependentResource.class) }) @ControllerConfiguration - private static class NamedDependentReconciler implements Reconciler { + public static class NamedDependentReconciler implements Reconciler { @Override public UpdateControl reconcile(ConfigMap resource, Context context) { @@ -412,7 +408,8 @@ public UpdateControl reconcile(ConfigMap resource, Context } private static class NamedDependentResource - extends KubernetesDependentResource { + extends KubernetesDependentResource + implements GarbageCollected { public NamedDependentResource() { super(ConfigMap.class); @@ -420,7 +417,7 @@ public NamedDependentResource() { } private static class ExternalDependentResource implements DependentResource, - DependentResourceConfigurator { + ConfiguredDependentResource, GarbageCollected { private String config = "UNSET"; @@ -443,6 +440,9 @@ public void configureWith(String config) { public Optional configuration() { return Optional.of(config); } + + @Override + public void delete(ConfigMap primary, Context context) {} } } } 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 702a12d124..5cc5472798 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 @@ -19,8 +19,9 @@ import io.javaoperatorsdk.operator.api.reconciler.Workflow; import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; +import io.javaoperatorsdk.operator.api.reconciler.dependent.GarbageCollected; import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult; -import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.ConfiguredDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentConverter; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; @@ -47,11 +48,23 @@ private

io.javaoperatorsdk.operator.api.config.Controlle return configurationService.configFor(reconciler); } + @SuppressWarnings({"rawtypes", "unchecked"}) + private static Object extractDependentKubernetesResourceConfig( + io.javaoperatorsdk.operator.api.config.ControllerConfiguration configuration, + Class target) { + final var spec = + configuration.getWorkflowSpec().orElseThrow().getDependentResourceSpecs().stream() + .filter(s -> target.isAssignableFrom(s.getDependentResourceClass())) + .findFirst().orElseThrow(); + return configuration.getConfigurationFor(spec); + } + @Test void controllerConfigurationProvidedShouldBeReturnedIfAvailable() { final var cfg = configFor(new CustomAnnotationReconciler()); - final var customConfig = DependentResourceConfigurationResolver - .extractConfigurationFromConfigured(CustomAnnotatedDep.class, cfg); + + final var customConfig = + extractDependentKubernetesResourceConfig(cfg, CustomAnnotatedDep.class); assertInstanceOf(CustomConfig.class, customConfig); assertEquals(CustomAnnotatedDep.PROVIDED_VALUE, ((CustomConfig) customConfig).getValue()); final var newConfig = new CustomConfig(72); @@ -62,28 +75,17 @@ void controllerConfigurationProvidedShouldBeReturnedIfAvailable() { .filter(s -> DR_NAME.equals(s.getName())) .findFirst() .orElseThrow(); - assertEquals(newConfig, - DependentResourceConfigurationResolver.configurationFor(spec, overridden)); + assertEquals(newConfig, overridden.getConfigurationFor(spec)); } @Test void getConverterShouldWork() { - final var cfg = configFor(new CustomAnnotationReconciler()); - var converter = DependentResourceConfigurationResolver.getConverter(CustomAnnotatedDep.class); - assertNull(converter); - assertNull(DependentResourceConfigurationResolver.getConverter(ChildCustomAnnotatedDep.class)); - // extracting configuration should trigger converter creation - DependentResourceConfigurationResolver.extractConfigurationFromConfigured( - CustomAnnotatedDep.class, cfg); - converter = DependentResourceConfigurationResolver.getConverter(CustomAnnotatedDep.class); + configFor(new CustomAnnotationReconciler()); + var converter = DependentResourceConfigurationResolver.getConverter(CustomAnnotatedDep.class); assertNotNull(converter); assertEquals(CustomConfigConverter.class, converter.getClass()); - converter = DependentResourceConfigurationResolver.getConverter(ChildCustomAnnotatedDep.class); - assertNull(converter); - DependentResourceConfigurationResolver.extractConfigurationFromConfigured( - ChildCustomAnnotatedDep.class, cfg); converter = DependentResourceConfigurationResolver.getConverter(ChildCustomAnnotatedDep.class); assertNotNull(converter); assertEquals(CustomConfigConverter.class, converter.getClass()); @@ -94,31 +96,23 @@ void getConverterShouldWork() { @SuppressWarnings("rawtypes") @Test void registerConverterShouldWork() { - final var cfg = configFor(new CustomAnnotationReconciler()); - var converter = DependentResourceConfigurationResolver.getConverter(ConfigMapDep.class); - assertNull(converter); - DependentResourceConfigurationResolver.extractConfigurationFromConfigured(ConfigMapDep.class, - cfg); - converter = DependentResourceConfigurationResolver.getConverter(ConfigMapDep.class); - assertInstanceOf(KubernetesDependentConverter.class, converter); final var overriddenConverter = new ConfigurationConverter() { + @Override - public Object configFrom(Annotation configAnnotation, - io.javaoperatorsdk.operator.api.config.ControllerConfiguration parentConfiguration, - Class originatingClass) { + public Object configFrom(Annotation configAnnotation, DependentResourceSpec spec, + io.javaoperatorsdk.operator.api.config.ControllerConfiguration parentConfiguration) { return null; } }; - DependentResourceConfigurationResolver.registerConverter(KubernetesDependentResource.class, + DependentResourceConfigurationResolver.registerConverter(ServiceDep.class, overriddenConverter); + configFor(new CustomAnnotationReconciler()); - // already resolved converters are kept unchanged - converter = DependentResourceConfigurationResolver.getConverter(ConfigMapDep.class); + // non overridden dependents should use the default converter + var converter = DependentResourceConfigurationResolver.getConverter(ConfigMapDep.class); assertInstanceOf(KubernetesDependentConverter.class, converter); - // but new converters should use the overridden version - DependentResourceConfigurationResolver.extractConfigurationFromConfigured(ServiceDep.class, - cfg); + // dependent with registered converter should use that one converter = DependentResourceConfigurationResolver.getConverter(ServiceDep.class); assertEquals(overriddenConverter, converter); } @@ -141,14 +135,16 @@ public UpdateControl reconcile(ConfigMap resource, Context } } - private static class ConfigMapDep extends KubernetesDependentResource { + public static class ConfigMapDep extends KubernetesDependentResource + implements GarbageCollected { public ConfigMapDep() { super(ConfigMap.class); } } - private static class ServiceDep extends KubernetesDependentResource { + public static class ServiceDep extends KubernetesDependentResource + implements GarbageCollected { public ServiceDep() { super(Service.class); @@ -159,7 +155,7 @@ public ServiceDep() { @Configured(by = CustomAnnotation.class, with = CustomConfig.class, converter = CustomConfigConverter.class) private static class CustomAnnotatedDep implements DependentResource, - DependentResourceConfigurator { + ConfiguredDependentResource, GarbageCollected { public static final int PROVIDED_VALUE = 42; private CustomConfig config; @@ -183,6 +179,11 @@ public void configureWith(CustomConfig config) { public Optional configuration() { return Optional.ofNullable(config); } + + @Override + public void delete(ConfigMap primary, Context context) { + + } } private static class ChildCustomAnnotatedDep extends CustomAnnotatedDep { @@ -209,14 +210,14 @@ public int getValue() { } private static class CustomConfigConverter - implements ConfigurationConverter { + implements ConfigurationConverter { static final int CONVERTER_PROVIDED_DEFAULT = 7; @Override public CustomConfig configFrom(CustomAnnotation configAnnotation, - io.javaoperatorsdk.operator.api.config.ControllerConfiguration parentConfiguration, - Class originatingClass) { + DependentResourceSpec spec, + io.javaoperatorsdk.operator.api.config.ControllerConfiguration parentConfiguration) { if (configAnnotation == null) { return new CustomConfig(CONVERTER_PROVIDED_DEFAULT); } else { diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/GroupVersionKindTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/GroupVersionKindTest.java index ad69cae800..6f2f91d3a4 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/GroupVersionKindTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/GroupVersionKindTest.java @@ -18,4 +18,21 @@ void testInitFromApiVersion() { assertThat(gvk.getVersion()).isEqualTo("v1"); } + @Test + void parseGVK() { + var gvk = GroupVersionKind.fromString("apps/v1/Deployment"); + assertThat(gvk.getGroup()).isEqualTo("apps"); + assertThat(gvk.getVersion()).isEqualTo("v1"); + assertThat(gvk.getKind()).isEqualTo("Deployment"); + + + gvk = GroupVersionKind.fromString("v1/ConfigMap"); + assertThat(gvk.getGroup()).isNull(); + assertThat(gvk.getVersion()).isEqualTo("v1"); + assertThat(gvk.getKind()).isEqualTo("ConfigMap"); + + assertThrows(IllegalArgumentException.class, () -> GroupVersionKind.fromString("v1#ConfigMap")); + assertThrows(IllegalArgumentException.class, + () -> GroupVersionKind.fromString("api/beta/v1/ConfigMap")); + } } diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcherTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcherTest.java index 370d3d62c1..997f7688e8 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcherTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcherTest.java @@ -146,7 +146,7 @@ void checkServiceAccount() { .addNewImagePullSecret("imagePullSecret3") .build(); - final var matcher = GenericResourceUpdaterMatcher.updaterMatcherFor(ServiceAccount.class); + final var matcher = GenericResourceUpdaterMatcher.updaterMatcherFor(); assertThat(matcher.matches(actual, desired, context)).isTrue(); } diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericResourceUpdaterMatcherTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericResourceUpdaterMatcherTest.java index 44f3fb51ea..bbdb4811fe 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericResourceUpdaterMatcherTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericResourceUpdaterMatcherTest.java @@ -40,7 +40,7 @@ static void setUp() { @Test void preservesValues() { - var processor = GenericResourceUpdaterMatcher.updaterMatcherFor(Deployment.class); + var processor = GenericResourceUpdaterMatcher.updaterMatcherFor(); var desired = createDeployment(); var actual = createDeployment(); actual.getMetadata().setLabels(new HashMap<>()); @@ -57,7 +57,7 @@ void preservesValues() { @Test void checkNamespaces() { - var processor = GenericResourceUpdaterMatcher.updaterMatcherFor(Namespace.class); + var processor = GenericResourceUpdaterMatcher.updaterMatcherFor(); var desired = new NamespaceBuilder().withNewMetadata().withName("foo").endMetadata().build(); var actual = new NamespaceBuilder().withNewMetadata().withName("foo").endMetadata().build(); actual.getMetadata().setLabels(new HashMap<>()); @@ -85,7 +85,7 @@ void checkNamespaces() { @Test void checkSecret() { - var processor = GenericResourceUpdaterMatcher.updaterMatcherFor(Secret.class); + var processor = GenericResourceUpdaterMatcher.updaterMatcherFor(); var desired = new SecretBuilder() .withMetadata(new ObjectMeta()) @@ -102,7 +102,7 @@ void checkSecret() { @Test void checkSeviceAccount() { - var processor = GenericResourceUpdaterMatcher.updaterMatcherFor(ServiceAccount.class); + var processor = GenericResourceUpdaterMatcher.updaterMatcherFor(); var desired = new ServiceAccountBuilder() .withMetadata(new ObjectMetaBuilder().addToLabels("new", "label").build()) .build(); diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/AbstractWorkflowExecutorTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/AbstractWorkflowExecutorTest.java index adebd635f7..970e40eff6 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/AbstractWorkflowExecutorTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/AbstractWorkflowExecutorTest.java @@ -3,18 +3,24 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Optional; import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.ConfigMapBuilder; import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.dependent.GarbageCollected; import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult; import io.javaoperatorsdk.operator.processing.dependent.Creator; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; import io.javaoperatorsdk.operator.sample.simple.TestCustomResource; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + public class AbstractWorkflowExecutorTest { public static final String VALUE = "value"; @@ -39,11 +45,6 @@ public TestDependent(String name) { super(ConfigMap.class, name); } - @Override - protected Class getPrimaryResourceType() { - return TestCustomResource.class; - } - @Override public ReconcileResult reconcile(TestCustomResource primary, Context context) { @@ -52,6 +53,14 @@ public ReconcileResult reconcile(TestCustomResource primary, .resourceCreated(new ConfigMapBuilder().addToBinaryData("key", VALUE).build()); } + @Override + public synchronized Optional> eventSource( + EventSourceContext context) { + var mockIES = mock(InformerEventSource.class); + when(mockIES.name()).thenReturn(name); + return Optional.of(mockIES); + } + @Override public String toString() { return name(); diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/ManagedWorkflowTestUtils.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/ManagedWorkflowTestUtils.java index b314b5b112..ae0731b8f5 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/ManagedWorkflowTestUtils.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/ManagedWorkflowTestUtils.java @@ -11,9 +11,7 @@ import io.javaoperatorsdk.operator.processing.dependent.EmptyTestDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.mockito.Mockito.withSettings; +import static org.mockito.Mockito.*; @SuppressWarnings("rawtypes") public class ManagedWorkflowTestUtils { diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/AbstractEventSourceTestBase.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/AbstractEventSourceTestBase.java index de5df68319..41b8b76623 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/AbstractEventSourceTestBase.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/AbstractEventSourceTestBase.java @@ -2,8 +2,7 @@ import org.junit.jupiter.api.AfterEach; -import io.javaoperatorsdk.operator.api.config.BaseConfigurationService; -import io.javaoperatorsdk.operator.api.config.ConfigurationService; +import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.processing.event.EventHandler; import io.javaoperatorsdk.operator.processing.event.source.informer.ManagedInformerEventSource; @@ -23,7 +22,7 @@ public void setUpSource(S source) { } - public void setUpSource(S source, boolean start, ConfigurationService configurationService) { + public void setUpSource(S source, boolean start, ControllerConfiguration configurationService) { setUpSource(source, (T) mock(EventHandler.class), start, configurationService); } @@ -37,16 +36,16 @@ public void setUpSource(S source, T eventHandler) { } public void setUpSource(S source, T eventHandler, boolean start) { - setUpSource(source, eventHandler, start, new BaseConfigurationService()); + setUpSource(source, eventHandler, start, mock(ControllerConfiguration.class)); } public void setUpSource(S source, T eventHandler, boolean start, - ConfigurationService configurationService) { + ControllerConfiguration controllerConfiguration) { this.eventHandler = eventHandler; this.source = source; if (source instanceof ManagedInformerEventSource) { - ((ManagedInformerEventSource) source).setConfigurationService(configurationService); + ((ManagedInformerEventSource) source).setControllerConfiguration(controllerConfiguration); } source.setEventHandler(eventHandler); diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSourceTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSourceTest.java index ca6c030a88..71670a37b1 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSourceTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerEventSourceTest.java @@ -10,6 +10,7 @@ import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.TestUtils; import io.javaoperatorsdk.operator.api.config.BaseConfigurationService; +import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.ResolvedControllerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; @@ -23,11 +24,7 @@ import io.javaoperatorsdk.operator.sample.simple.TestCustomResource; import static org.mockito.ArgumentMatchers.eq; -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; +import static org.mockito.Mockito.*; class ControllerEventSourceTest extends AbstractEventSourceTestBase, EventHandler> { @@ -36,11 +33,14 @@ class ControllerEventSourceTest extends ReconcilerUtils.getDefaultFinalizerName(TestCustomResource.class); private final TestController testController = new TestController(true); + private final ControllerConfiguration controllerConfig = mock(ControllerConfiguration.class); @BeforeEach public void setup() { - setUpSource(new ControllerEventSource<>(testController), true, - new BaseConfigurationService()); + + when(controllerConfig.getConfigurationService()).thenReturn(new BaseConfigurationService()); + + setUpSource(new ControllerEventSource<>(testController), true, controllerConfig); } @Test @@ -128,7 +128,7 @@ void filtersOutEventsOnAddAndUpdate() { source = new ControllerEventSource<>( new TestController(onAddFilter, onUpdatePredicate, null)); - setUpSource(source); + setUpSource(source, true, controllerConfig); source.eventReceived(ResourceAction.ADDED, cr, null); source.eventReceived(ResourceAction.UPDATED, cr, cr); @@ -142,7 +142,7 @@ void genericFilterFiltersOutAddUpdateAndDeleteEvents() { source = new ControllerEventSource<>(new TestController(null, null, res -> false)); - setUpSource(source); + setUpSource(source, true, controllerConfig); source.eventReceived(ResourceAction.ADDED, cr, null); source.eventReceived(ResourceAction.UPDATED, cr, cr); diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSourceTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSourceTest.java index 5b8aac89e6..a6a5f33570 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSourceTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSourceTest.java @@ -14,6 +14,7 @@ import io.javaoperatorsdk.operator.OperatorException; import io.javaoperatorsdk.operator.api.config.BaseConfigurationService; import io.javaoperatorsdk.operator.api.config.ConfigurationService; +import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.InformerStoppedHandler; import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.processing.event.EventHandler; @@ -56,8 +57,11 @@ void setup() { informerEventSource = new InformerEventSource<>(informerConfiguration, clientMock); + var mockControllerConfig = mock(ControllerConfiguration.class); + when(mockControllerConfig.getConfigurationService()).thenReturn(new BaseConfigurationService()); + informerEventSource.setEventHandler(eventHandlerMock); - informerEventSource.setConfigurationService(new BaseConfigurationService()); + informerEventSource.setControllerConfiguration(mockControllerConfig); SecondaryToPrimaryMapper secondaryToPrimaryMapper = mock(SecondaryToPrimaryMapper.class); when(informerConfiguration.getSecondaryToPrimaryMapper()) .thenReturn(secondaryToPrimaryMapper); @@ -177,11 +181,14 @@ void informerStoppedHandlerShouldBeCalledWhenInformerStops() { ConfigurationService.newOverriddenConfigurationService(new BaseConfigurationService(), o -> o.withInformerStoppedHandler(informerStoppedHandler)); + var mockControllerConfig = mock(ControllerConfiguration.class); + when(mockControllerConfig.getConfigurationService()).thenReturn(configuration); + informerEventSource = new InformerEventSource<>(informerConfiguration, MockKubernetesClient.client(Deployment.class, unused -> { throw exception; })); - informerEventSource.setConfigurationService(configuration); + informerEventSource.setControllerConfiguration(mockControllerConfig); // by default informer fails to start if there is an exception in the client on start. // Throws the exception further. diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingEventSourceTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingEventSourceTest.java index 5dffa65ae7..ced96e9b7d 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingEventSourceTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingEventSourceTest.java @@ -32,7 +32,7 @@ class PollingEventSourceTest mock(PollingEventSource.GenericResourceFetcher.class); private final PollingEventSource pollingEventSource = new PollingEventSource<>(SampleExternalResource.class, - new PollingConfiguration<>(resourceFetcher, POLL_PERIOD, + new PollingConfiguration<>(null, resourceFetcher, POLL_PERIOD, (SampleExternalResource er) -> er.getName() + "#" + er.getValue())); @BeforeEach diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/WorkflowExplicitInvocationIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/WorkflowExplicitInvocationIT.java index dba08faba0..0ba8fa6229 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/WorkflowExplicitInvocationIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/WorkflowExplicitInvocationIT.java @@ -1,5 +1,7 @@ package io.javaoperatorsdk.operator; +import java.time.Duration; + import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -48,7 +50,7 @@ void workflowInvokedExplicitly() { // The ConfigMap is not garbage collected, this tests that even if the cleaner is not // implemented the workflow cleanup still called even if there is explicit invocation - await().untilAsserted(() -> { + await().timeout(Duration.ofSeconds(30)).untilAsserted(() -> { assertThat(extension.get(ConfigMap.class, RESOURCE_NAME)).isNull(); }); } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/BaseConfigurationServiceTest.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/BaseConfigurationServiceTest.java index 820ce1589f..d0c2d67b50 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/BaseConfigurationServiceTest.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/BaseConfigurationServiceTest.java @@ -7,7 +7,6 @@ import java.time.Duration; import java.util.List; import java.util.Optional; -import java.util.Set; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Assertions; @@ -20,7 +19,6 @@ 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; import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; @@ -31,9 +29,9 @@ import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult; -import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.ConfiguredDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; -import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResourceConfig; import io.javaoperatorsdk.operator.processing.event.rate.LinearRateLimiter; import io.javaoperatorsdk.operator.processing.event.rate.RateLimited; @@ -65,29 +63,19 @@ private

io.javaoperatorsdk.operator.api.config.Controlle return configurationService.configFor(reconciler); } - @Test - void defaultValuesShouldBeConsistent() { - final var configuration = configFor(new SelectorReconciler()); - final var annotated = extractDependentKubernetesResourceConfig(configuration, 1); - final var unannotated = extractDependentKubernetesResourceConfig(configuration, 0); - - assertNull(annotated.labelSelector()); - assertNull(unannotated.labelSelector()); - } - - @SuppressWarnings("rawtypes") - private KubernetesDependentResourceConfig extractDependentKubernetesResourceConfig( + @SuppressWarnings({"rawtypes", "unchecked"}) + private static KubernetesDependentResourceConfig extractDependentKubernetesResourceConfig( io.javaoperatorsdk.operator.api.config.ControllerConfiguration configuration, int index) { final var spec = configuration.getWorkflowSpec().orElseThrow().getDependentResourceSpecs().get(index); - return (KubernetesDependentResourceConfig) DependentResourceConfigurationResolver - .configurationFor(spec, configuration); + return (KubernetesDependentResourceConfig) configuration.getConfigurationFor(spec); } @Test - @SuppressWarnings("rawtypes") + @SuppressWarnings({"rawtypes", "unchecked"}) void getDependentResources() { var configuration = configFor(new NoDepReconciler()); + var workflowSpec = configuration.getWorkflowSpec(); assertTrue(workflowSpec.isEmpty()); @@ -99,14 +87,10 @@ void getDependentResources() { assertTrue(dependents.stream().anyMatch(d -> d.getName().equals(dependentResourceName))); var dependentSpec = findByName(dependents, dependentResourceName); assertEquals(ReadOnlyDependent.class, dependentSpec.getDependentResourceClass()); - var maybeConfig = - DependentResourceConfigurationResolver.configurationFor(dependentSpec, configuration); + var maybeConfig = extractDependentKubernetesResourceConfig(configuration, 0); assertNotNull(maybeConfig); assertInstanceOf(KubernetesDependentResourceConfig.class, maybeConfig); final var config = (KubernetesDependentResourceConfig) maybeConfig; - // check that the DependentResource inherits the controller's configuration if applicable - assertEquals(1, config.namespaces().size()); - assertEquals(Set.of(OneDepReconciler.CONFIGURED_NS), config.namespaces()); configuration = configFor(new NamedDepReconciler()); dependents = configuration.getWorkflowSpec().orElseThrow().getDependentResourceSpecs(); @@ -114,8 +98,7 @@ void getDependentResources() { assertEquals(1, dependents.size()); dependentSpec = findByName(dependents, NamedDepReconciler.NAME); assertEquals(ReadOnlyDependent.class, dependentSpec.getDependentResourceClass()); - maybeConfig = DependentResourceConfigurationResolver.configurationFor(dependentSpec, - configuration); + maybeConfig = extractDependentKubernetesResourceConfig(configuration, 0); assertNotNull(maybeConfig); assertInstanceOf(KubernetesDependentResourceConfig.class, maybeConfig); } @@ -230,13 +213,12 @@ void configuringFromCustomAnnotationsShouldWork() { assertEquals(CustomConfigConverter.CONVERTER_PROVIDED_DEFAULT, getValue(config, 1)); } + @SuppressWarnings("unchecked") private static int getValue( io.javaoperatorsdk.operator.api.config.ControllerConfiguration configuration, int index) { - return ((CustomConfig) DependentResourceConfigurationResolver - .configurationFor( - configuration.getWorkflowSpec().orElseThrow().getDependentResourceSpecs().get(index), - configuration)) - .getValue(); + final var spec = + configuration.getWorkflowSpec().orElseThrow().getDependentResourceSpecs().get(index); + return ((CustomConfig) configuration.getConfigurationFor(spec)).value(); } @ControllerConfiguration( @@ -316,7 +298,7 @@ public UpdateControl reconcile(ConfigMap resource, Context @Dependent(type = ReadOnlyDependent.class) }) @ControllerConfiguration - private static class SelectorReconciler implements Reconciler { + public static class SelectorReconciler implements Reconciler { @Override public UpdateControl reconcile(ConfigMap resource, Context context) { @@ -324,7 +306,8 @@ public UpdateControl reconcile(ConfigMap resource, Context } @KubernetesDependent - private static class WithAnnotation extends KubernetesDependentResource { + public static class WithAnnotation + extends CRUDKubernetesDependentResource { public WithAnnotation() { super(ConfigMap.class); @@ -332,7 +315,7 @@ public WithAnnotation() { } } - private static class MissingAnnotationReconciler implements Reconciler { + public static class MissingAnnotationReconciler implements Reconciler { @Override public UpdateControl reconcile(ConfigMap resource, Context context) { @@ -450,7 +433,7 @@ public UpdateControl reconcile(ConfigMap resource, Context @Configured(by = CustomAnnotation.class, with = CustomConfig.class, converter = CustomConfigConverter.class) private static class CustomAnnotatedDep implements DependentResource, - DependentResourceConfigurator { + ConfiguredDependentResource { public static final int PROVIDED_VALUE = 42; private CustomConfig config; @@ -486,28 +469,17 @@ private static class ChildCustomAnnotatedDep extends CustomAnnotatedDep { int value(); } - private static class CustomConfig { - - private final int value; - - private CustomConfig(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - } + private record CustomConfig(int value) {} private static class CustomConfigConverter - implements ConfigurationConverter { + implements ConfigurationConverter { static final int CONVERTER_PROVIDED_DEFAULT = 7; @Override public CustomConfig configFrom(CustomAnnotation configAnnotation, - io.javaoperatorsdk.operator.api.config.ControllerConfiguration parentConfiguration, - Class originatingClass) { + DependentResourceSpec spec, + io.javaoperatorsdk.operator.api.config.ControllerConfiguration parentConfiguration) { if (configAnnotation == null) { return new CustomConfig(CONVERTER_PROVIDED_DEFAULT); } else { diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/bulkdependent/ConfigMapDeleterBulkDependentResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/bulkdependent/ConfigMapDeleterBulkDependentResource.java index 1ee4e3ef24..f9a92f9061 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/bulkdependent/ConfigMapDeleterBulkDependentResource.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/bulkdependent/ConfigMapDeleterBulkDependentResource.java @@ -28,11 +28,6 @@ public ConfigMapDeleterBulkDependentResource() { super(ConfigMap.class); } - @Override - protected Class getPrimaryResourceType() { - return BulkDependentTestCustomResource.class; - } - @Override public Map desiredResources(BulkDependentTestCustomResource primary, Context context) { diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/bulkdependent/readonly/ReadOnlyBulkDependentResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/bulkdependent/readonly/ReadOnlyBulkDependentResource.java index 0f4fb80b8a..661cfb931b 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/bulkdependent/readonly/ReadOnlyBulkDependentResource.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/bulkdependent/readonly/ReadOnlyBulkDependentResource.java @@ -8,6 +8,7 @@ import io.fabric8.kubernetes.api.model.ConfigMap; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.processing.dependent.BulkDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; import io.javaoperatorsdk.operator.processing.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper; @@ -15,6 +16,7 @@ import io.javaoperatorsdk.operator.sample.bulkdependent.BulkDependentTestCustomResource; +@KubernetesDependent public class ReadOnlyBulkDependentResource extends KubernetesDependentResource @@ -27,11 +29,6 @@ public ReadOnlyBulkDependentResource() { super(ConfigMap.class); } - @Override - protected Class getPrimaryResourceType() { - return BulkDependentTestCustomResource.class; - } - @Override public Map getSecondaryResources(BulkDependentTestCustomResource primary, Context context) { @@ -51,4 +48,5 @@ public Set toPrimaryResourceIDs(ConfigMap resource) { return Mappers.fromOwnerReferences(BulkDependentTestCustomResource.class, false) .toPrimaryResourceIDs(resource); } + } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/changenamespace/ChangeNamespaceTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/changenamespace/ChangeNamespaceTestReconciler.java index 00750b30b0..e54e3e3cb7 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/changenamespace/ChangeNamespaceTestReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/changenamespace/ChangeNamespaceTestReconciler.java @@ -24,8 +24,10 @@ public List prepareEventSources( EventSourceContext context) { InformerEventSource configMapES = - new InformerEventSource<>(InformerConfiguration.from(ConfigMap.class, context) - .build(), context); + new InformerEventSource<>( + InformerConfiguration.from(ConfigMap.class, ChangeNamespaceTestCustomResource.class) + .build(), + context); return List.of(configMapES); } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java index ec872bd6b2..f1f66bc3ae 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java @@ -55,11 +55,13 @@ private ConfigMap desired(ClusterScopedCustomResource resource) { @Override public List prepareEventSources( EventSourceContext context) { - var ies = new InformerEventSource<>(InformerConfiguration.from(ConfigMap.class, context) - .withSecondaryToPrimaryMapper( - Mappers.fromOwnerReferences(context.getPrimaryResourceClass(), true)) - .withLabelSelector(TEST_LABEL_KEY + "=" + TEST_LABEL_VALUE) - .build(), context); + var ies = new InformerEventSource<>( + InformerConfiguration.from(ConfigMap.class, ClusterScopedCustomResource.class) + .withSecondaryToPrimaryMapper( + Mappers.fromOwnerReferences(context.getPrimaryResourceClass(), true)) + .withLabelSelector(TEST_LABEL_KEY + "=" + TEST_LABEL_VALUE) + .build(), + context); return List.of(ies); } } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/complexdependent/ComplexDependentReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/complexdependent/ComplexDependentReconciler.java index d2259faeaf..1937a4783e 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/complexdependent/ComplexDependentReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/complexdependent/ComplexDependentReconciler.java @@ -54,12 +54,16 @@ public UpdateControl reconcile( public List prepareEventSources( EventSourceContext context) { InformerEventSource serviceEventSource = - new InformerEventSource<>(SERVICE_EVENT_SOURCE_NAME, - InformerConfiguration.from(Service.class, context).build(), + new InformerEventSource<>( + InformerConfiguration.from(Service.class, ComplexDependentCustomResource.class) + .withName(SERVICE_EVENT_SOURCE_NAME) + .build(), context); InformerEventSource statefulSetEventSource = - new InformerEventSource<>(STATEFUL_SET_EVENT_SOURCE_NAME, - InformerConfiguration.from(StatefulSet.class, context).build(), + new InformerEventSource<>( + InformerConfiguration.from(StatefulSet.class, ComplexDependentCustomResource.class) + .withName(STATEFUL_SET_EVENT_SOURCE_NAME) + .build(), context); return List.of(serviceEventSource, statefulSetEventSource); } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/complexdependent/dependent/BaseDependentResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/complexdependent/dependent/BaseDependentResource.java index eee439cbfe..08e7e5fe2e 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/complexdependent/dependent/BaseDependentResource.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/complexdependent/dependent/BaseDependentResource.java @@ -16,11 +16,6 @@ public BaseDependentResource(Class resourceType, String component) { this.component = component; } - @Override - protected Class getPrimaryResourceType() { - return ComplexDependentCustomResource.class; - } - protected String name(ComplexDependentCustomResource primary) { return String.format("%s-%s", component, primary.getSpec().getProjectId()); } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/createupdateeventfilter/CreateUpdateEventFilterTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/createupdateeventfilter/CreateUpdateEventFilterTestReconciler.java index 8567f49916..13c204d39d 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/createupdateeventfilter/CreateUpdateEventFilterTestReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/createupdateeventfilter/CreateUpdateEventFilterTestReconciler.java @@ -93,7 +93,7 @@ private ConfigMap createConfigMap(CreateUpdateEventFilterTestCustomResource reso public List prepareEventSources( EventSourceContext context) { InformerConfiguration informerConfiguration = - InformerConfiguration.from(ConfigMap.class, context) + InformerConfiguration.from(ConfigMap.class, CreateUpdateEventFilterTestCustomResource.class) .withLabelSelector("integrationtest = " + this.getClass().getSimpleName()) .build(); final var informerEventSource = diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentcustommappingannotation/CustomMappingConfigMapDependentResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentcustommappingannotation/CustomMappingConfigMapDependentResource.java index e17fdb8099..d8b71c9cf9 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentcustommappingannotation/CustomMappingConfigMapDependentResource.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentcustommappingannotation/CustomMappingConfigMapDependentResource.java @@ -8,10 +8,12 @@ import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDNoGCKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; import io.javaoperatorsdk.operator.processing.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper; import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers; +@KubernetesDependent public class CustomMappingConfigMapDependentResource extends CRUDNoGCKubernetesDependentResource implements SecondaryToPrimaryMapper { @@ -20,7 +22,7 @@ public class CustomMappingConfigMapDependentResource public static final String CUSTOM_NAMESPACE_KEY = "customNamespaceKey"; public static final String KEY = "key"; - private final SecondaryToPrimaryMapper mapper = + private static final SecondaryToPrimaryMapper mapper = Mappers.fromAnnotation(CUSTOM_NAME_KEY, CUSTOM_NAMESPACE_KEY); public CustomMappingConfigMapDependentResource() { @@ -39,14 +41,17 @@ protected ConfigMap desired(DependentCustomMappingCustomResource primary, .build(); } - @Override - public Set toPrimaryResourceIDs(ConfigMap resource) { - return mapper.toPrimaryResourceIDs(resource); - } - @Override protected void addSecondaryToPrimaryMapperAnnotations(ConfigMap desired, DependentCustomMappingCustomResource primary) { addSecondaryToPrimaryMapperAnnotations(desired, primary, CUSTOM_NAME_KEY, CUSTOM_NAMESPACE_KEY); } + + + @Override + public Set toPrimaryResourceIDs(ConfigMap resource) { + return mapper.toPrimaryResourceIDs(resource); + } + + } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentfilter/FilteredDependentConfigMap.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentfilter/FilteredDependentConfigMap.java index ee4bd4cde7..18b9aaa510 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentfilter/FilteredDependentConfigMap.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentfilter/FilteredDependentConfigMap.java @@ -6,11 +6,12 @@ import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.InformerConfig; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; import static io.javaoperatorsdk.operator.sample.dependentfilter.DependentFilterTestReconciler.CM_VALUE_KEY; -@KubernetesDependent(onUpdateFilter = UpdateFilter.class) +@KubernetesDependent(informerConfig = @InformerConfig(onUpdateFilter = UpdateFilter.class)) public class FilteredDependentConfigMap extends CRUDKubernetesDependentResource { diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dynamicgenericeventsourceregistration/DynamicGenericEventSourceRegistrationReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dynamicgenericeventsourceregistration/DynamicGenericEventSourceRegistrationReconciler.java index 80153e010a..13fc3f7e4c 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dynamicgenericeventsourceregistration/DynamicGenericEventSourceRegistrationReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dynamicgenericeventsourceregistration/DynamicGenericEventSourceRegistrationReconciler.java @@ -74,9 +74,11 @@ private InformerEventSource clazz, Context context) { - return new InformerEventSource<>(clazz.getSimpleName(), - InformerConfiguration.from(gvkFor(clazz), - context.eventSourceRetriever().eventSourceContextForDynamicRegistration()).build(), + return new InformerEventSource<>( + InformerConfiguration + .from(gvkFor(clazz), DynamicGenericEventSourceRegistrationCustomResource.class) + .withName(clazz.getSimpleName()) + .build(), context.eventSourceRetriever().eventSourceContextForDynamicRegistration()); } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/externalstate/ExternalStateDependentReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/externalstate/ExternalStateDependentReconciler.java index b9c264ba63..8fe2a1f707 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/externalstate/ExternalStateDependentReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/externalstate/ExternalStateDependentReconciler.java @@ -37,7 +37,8 @@ public int getNumberOfExecutions() { public List prepareEventSources( EventSourceContext context) { var configMapEventSource = new InformerEventSource<>( - InformerConfiguration.from(ConfigMap.class, context).build(), context); + InformerConfiguration.from(ConfigMap.class, ExternalStateCustomResource.class).build(), + context); return List.of(configMapEventSource); } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/externalstate/ExternalStateReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/externalstate/ExternalStateReconciler.java index 4f7bb0ce5c..fd5e5aa37f 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/externalstate/ExternalStateReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/externalstate/ExternalStateReconciler.java @@ -111,7 +111,8 @@ public List prepareEventSources( EventSourceContext context) { configMapEventSource = new InformerEventSource<>( - InformerConfiguration.from(ConfigMap.class, context).build(), context); + InformerConfiguration.from(ConfigMap.class, ExternalStateCustomResource.class).build(), + context); configMapEventSource.setEventSourcePriority(EventSourceStartPriority.RESOURCE_STATE_LOADER); final PerResourcePollingEventSource.ResourceFetcher fetcher = diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/externalstate/externalstatebulkdependent/ExternalStateBulkDependentReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/externalstate/externalstatebulkdependent/ExternalStateBulkDependentReconciler.java index 0da96c2e32..a0ea6c0089 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/externalstate/externalstatebulkdependent/ExternalStateBulkDependentReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/externalstate/externalstatebulkdependent/ExternalStateBulkDependentReconciler.java @@ -36,7 +36,9 @@ public int getNumberOfExecutions() { public List prepareEventSources( EventSourceContext context) { var configMapEventSource = new InformerEventSource<>( - InformerConfiguration.from(ConfigMap.class, context).build(), context); + InformerConfiguration.from(ConfigMap.class, ExternalStateBulkDependentCustomResource.class) + .build(), + context); return List.of(configMapEventSource); } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/filter/FilterTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/filter/FilterTestReconciler.java index e611968766..74fbfbbe2d 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/filter/FilterTestReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/filter/FilterTestReconciler.java @@ -54,7 +54,7 @@ public List prepareEventSources( InformerEventSource configMapES = new InformerEventSource<>(InformerConfiguration - .from(ConfigMap.class, context) + .from(ConfigMap.class, FilterTestCustomResource.class) .withOnUpdateFilter((newCM, oldCM) -> !newCM.getData().get(CM_VALUE_KEY) .equals(CONFIG_MAP_FILTER_VALUE)) .build(), context); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/generickubernetesresource/generickubernetesdependentresourcemanaged/ConfigMapGenericKubernetesDependent.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/generickubernetesresource/generickubernetesdependentresourcemanaged/ConfigMapGenericKubernetesDependent.java index d5ab470cfb..00c202436f 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/generickubernetesresource/generickubernetesdependentresourcemanaged/ConfigMapGenericKubernetesDependent.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/generickubernetesresource/generickubernetesdependentresourcemanaged/ConfigMapGenericKubernetesDependent.java @@ -11,7 +11,9 @@ import io.javaoperatorsdk.operator.processing.dependent.Creator; import io.javaoperatorsdk.operator.processing.dependent.Updater; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.GenericKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; +@KubernetesDependent public class ConfigMapGenericKubernetesDependent extends GenericKubernetesDependentResource implements diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/generickubernetesresource/generickubernetesresourcehandling/GenericKubernetesResourceHandlingReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/generickubernetesresource/generickubernetesresourcehandling/GenericKubernetesResourceHandlingReconciler.java index f5c66e8d30..4d93438735 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/generickubernetesresource/generickubernetesresourcehandling/GenericKubernetesResourceHandlingReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/generickubernetesresource/generickubernetesresourcehandling/GenericKubernetesResourceHandlingReconciler.java @@ -69,7 +69,8 @@ public List prepareEventSources( EventSourceContext context) { var informerEventSource = new InformerEventSource<>(InformerConfiguration.from( - new GroupVersionKind("", VERSION, KIND), context).build(), + new GroupVersionKind("", VERSION, KIND), + GenericKubernetesResourceHandlingCustomResource.class).build(), context); return List.of(informerEventSource); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/informereventsource/InformerEventSourceTestCustomReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/informereventsource/InformerEventSourceTestCustomReconciler.java index 232426403d..868dc4f3ed 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/informereventsource/InformerEventSourceTestCustomReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/informereventsource/InformerEventSourceTestCustomReconciler.java @@ -36,7 +36,7 @@ public List prepareEventSources( EventSourceContext context) { InformerConfiguration config = - InformerConfiguration.from(ConfigMap.class, context) + InformerConfiguration.from(ConfigMap.class, InformerEventSourceTestCustomResource.class) .withSecondaryToPrimaryMapper(Mappers.fromAnnotation(RELATED_RESOURCE_NAME)) .build(); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/informerrelatedbehavior/ConfigMapDependentResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/informerrelatedbehavior/ConfigMapDependentResource.java index c9747cbd00..bda0b94845 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/informerrelatedbehavior/ConfigMapDependentResource.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/informerrelatedbehavior/ConfigMapDependentResource.java @@ -7,9 +7,10 @@ import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.InformerConfig; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; -@KubernetesDependent(labelSelector = "app=rbac-test") +@KubernetesDependent(informerConfig = @InformerConfig(labelSelector = "app=rbac-test")) public class ConfigMapDependentResource extends CRUDKubernetesDependentResource { diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentresource/MultipleDependentResourceReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentresource/MultipleDependentResourceReconciler.java index c61d751079..e129b2e3d5 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentresource/MultipleDependentResourceReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentresource/MultipleDependentResourceReconciler.java @@ -36,10 +36,11 @@ public UpdateControl reconcile( public List prepareEventSources( EventSourceContext context) { InformerEventSource eventSource = - new InformerEventSource<>(InformerConfiguration.from(ConfigMap.class, context) + new InformerEventSource<>(InformerConfiguration + .from(ConfigMap.class, MultipleDependentResourceCustomResource.class) .build(), context); - firstDependentResourceConfigMap.configureWith(eventSource); - secondDependentResourceConfigMap.configureWith(eventSource); + firstDependentResourceConfigMap.setEventSource(eventSource); + secondDependentResourceConfigMap.setEventSource(eventSource); return List.of(eventSource); } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentresourcewithdiscriminator/MultipleDependentResourceWithDiscriminatorReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentresourcewithdiscriminator/MultipleDependentResourceWithDiscriminatorReconciler.java index 9e04af6d24..fd90838ddd 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentresourcewithdiscriminator/MultipleDependentResourceWithDiscriminatorReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentresourcewithdiscriminator/MultipleDependentResourceWithDiscriminatorReconciler.java @@ -46,10 +46,11 @@ public int getNumberOfExecutions() { public List prepareEventSources( EventSourceContext context) { InformerEventSource eventSource = - new InformerEventSource<>(InformerConfiguration.from(ConfigMap.class, context) + new InformerEventSource<>(InformerConfiguration.from(ConfigMap.class, + MultipleDependentResourceCustomResourceWithDiscriminator.class) .build(), context); - firstDependentResourceConfigMap.configureWith(eventSource); - secondDependentResourceConfigMap.configureWith(eventSource); + firstDependentResourceConfigMap.setEventSource(eventSource); + secondDependentResourceConfigMap.setEventSource(eventSource); return List.of(eventSource); } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledrsametypenodiscriminator/MultipleManagedDependentSameTypeNoDiscriminatorReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledrsametypenodiscriminator/MultipleManagedDependentSameTypeNoDiscriminatorReconciler.java index 6377385b6e..feec6dc727 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledrsametypenodiscriminator/MultipleManagedDependentSameTypeNoDiscriminatorReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledrsametypenodiscriminator/MultipleManagedDependentSameTypeNoDiscriminatorReconciler.java @@ -49,8 +49,10 @@ public int getNumberOfExecutions() { public List prepareEventSources( EventSourceContext context) { InformerEventSource ies = - new InformerEventSource<>(CONFIG_MAP_EVENT_SOURCE, - InformerConfiguration.from(ConfigMap.class, context) + new InformerEventSource<>( + InformerConfiguration.from(ConfigMap.class, + MultipleManagedDependentNoDiscriminatorCustomResource.class) + .withName(CONFIG_MAP_EVENT_SOURCE) .build(), context); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiplemanageddependentsametype/MultipleManagedDependentResourceReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiplemanageddependentsametype/MultipleManagedDependentResourceReconciler.java index 63c22436d8..53917dd593 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiplemanageddependentsametype/MultipleManagedDependentResourceReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiplemanageddependentsametype/MultipleManagedDependentResourceReconciler.java @@ -49,8 +49,10 @@ public int getNumberOfExecutions() { public List prepareEventSources( EventSourceContext context) { InformerEventSource ies = - new InformerEventSource<>(CONFIG_MAP_EVENT_SOURCE, - InformerConfiguration.from(ConfigMap.class, context) + new InformerEventSource<>( + InformerConfiguration + .from(ConfigMap.class, MultipleManagedDependentResourceCustomResource.class) + .withName(CONFIG_MAP_EVENT_SOURCE) .build(), context); return List.of(ies); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiplemanagedexternaldependenttype/MultipleManagedExternalDependentResourceReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiplemanagedexternaldependenttype/MultipleManagedExternalDependentResourceReconciler.java index 614f3a0b59..786e1c82d6 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiplemanagedexternaldependenttype/MultipleManagedExternalDependentResourceReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiplemanagedexternaldependenttype/MultipleManagedExternalDependentResourceReconciler.java @@ -71,8 +71,9 @@ public List prepareEventSources( }; PollingEventSource pollingEventSource = - new PollingEventSource<>(EVENT_SOURCE_NAME, ExternalResource.class, + new PollingEventSource<>(ExternalResource.class, new PollingConfigurationBuilder<>(fetcher, Duration.ofMillis(1000L)) + .withName(EVENT_SOURCE_NAME) .withCacheKeyMapper(ExternalResource::getId) .build()); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiplesecondaryeventsource/MultipleSecondaryEventSourceReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiplesecondaryeventsource/MultipleSecondaryEventSourceReconciler.java index 88f97a8235..fb216e9edd 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiplesecondaryeventsource/MultipleSecondaryEventSourceReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiplesecondaryeventsource/MultipleSecondaryEventSourceReconciler.java @@ -64,7 +64,8 @@ public int getNumberOfExecutions() { public List prepareEventSources( EventSourceContext context) { - var config = InformerConfiguration.from(ConfigMap.class, context) + var config = InformerConfiguration + .from(ConfigMap.class, MultipleSecondaryEventSourceCustomResource.class) .withNamespaces(context.getControllerConfiguration().getNamespaces()) .withLabelSelector("multisecondary") .withSecondaryToPrimaryMapper(s -> { diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource1.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource1.java index 14530cf17e..8c5a844cfb 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource1.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource1.java @@ -8,9 +8,10 @@ import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.InformerConfig; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; -@KubernetesDependent(labelSelector = "dependent = cm1") +@KubernetesDependent(informerConfig = @InformerConfig(labelSelector = "dependent = cm1")) public class ConfigMapDependentResource1 extends CRUDKubernetesDependentResource { diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource2.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource2.java index 35ae69586e..72a427aad6 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource2.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource2.java @@ -8,9 +8,10 @@ import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.InformerConfig; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; -@KubernetesDependent(labelSelector = "dependent = cm2") +@KubernetesDependent(informerConfig = @InformerConfig(labelSelector = "dependent = cm2")) public class ConfigMapDependentResource2 extends CRUDKubernetesDependentResource { diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primaryindexer/DependentPrimaryIndexerTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primaryindexer/DependentPrimaryIndexerTestReconciler.java index 513cc2cb5d..6c277b0fa6 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primaryindexer/DependentPrimaryIndexerTestReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primaryindexer/DependentPrimaryIndexerTestReconciler.java @@ -1,12 +1,12 @@ package io.javaoperatorsdk.operator.sample.primaryindexer; -import java.util.Optional; -import java.util.Set; +import java.util.List; import java.util.stream.Collectors; import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.ConfigMapBuilder; import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; @@ -15,21 +15,44 @@ import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; import io.javaoperatorsdk.operator.processing.event.ResourceID; -import io.javaoperatorsdk.operator.processing.event.source.IndexerResourceCache; -import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper; +import io.javaoperatorsdk.operator.processing.event.source.EventSource; import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; -@Workflow(dependents = @Dependent( +import static io.javaoperatorsdk.operator.sample.primaryindexer.DependentPrimaryIndexerTestReconciler.CONFIG_MAP_EVENT_SOURCE; + +@Workflow(dependents = @Dependent(useEventSourceWithName = CONFIG_MAP_EVENT_SOURCE, type = DependentPrimaryIndexerTestReconciler.ReadOnlyConfigMapDependent.class)) @ControllerConfiguration public class DependentPrimaryIndexerTestReconciler extends AbstractPrimaryIndexerTestReconciler implements Reconciler { + public static final String CONFIG_MAP_EVENT_SOURCE = "configMapEventSource"; + + @Override + public List prepareEventSources( + EventSourceContext context) { + + var cache = context.getPrimaryCache(); + cache.addIndexer(CONFIG_MAP_RELATION_INDEXER, indexer); + + InformerEventSource es = + new InformerEventSource<>( + InformerConfiguration.from(ConfigMap.class, PrimaryIndexerTestCustomResource.class) + .withName(CONFIG_MAP_EVENT_SOURCE) + .withSecondaryToPrimaryMapper(resource -> cache + .byIndex(CONFIG_MAP_RELATION_INDEXER, resource.getMetadata().getName()) + .stream() + .map(ResourceID::fromResource) + .collect(Collectors.toSet())) + .build(), + context); + + return List.of(es); + } + public static class ReadOnlyConfigMapDependent - extends KubernetesDependentResource implements - SecondaryToPrimaryMapper { - private IndexerResourceCache cache; + extends KubernetesDependentResource { public ReadOnlyConfigMapDependent() { super(ConfigMap.class); @@ -45,21 +68,5 @@ protected ConfigMap desired(PrimaryIndexerTestCustomResource primary, .build()) .build(); } - - @Override - public Set toPrimaryResourceIDs(ConfigMap resource) { - return cache.byIndex(CONFIG_MAP_RELATION_INDEXER, resource.getMetadata().getName()) - .stream() - .map(ResourceID::fromResource) - .collect(Collectors.toSet()); - } - - @Override - public Optional> eventSource( - EventSourceContext context) { - cache = context.getPrimaryCache(); - cache.addIndexer(CONFIG_MAP_RELATION_INDEXER, indexer); - return super.eventSource(context); - } } } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primaryindexer/PrimaryIndexerTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primaryindexer/PrimaryIndexerTestReconciler.java index 547c224e55..e20cf037c2 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primaryindexer/PrimaryIndexerTestReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primaryindexer/PrimaryIndexerTestReconciler.java @@ -22,7 +22,7 @@ public List prepareEventSources( context.getPrimaryCache().addIndexer(CONFIG_MAP_RELATION_INDEXER, indexer); var informerConfiguration = - InformerConfiguration.from(ConfigMap.class, context) + InformerConfiguration.from(ConfigMap.class, PrimaryIndexerTestCustomResource.class) .withSecondaryToPrimaryMapper( (ConfigMap secondaryResource) -> context .getPrimaryCache() diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondary/JobReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondary/JobReconciler.java index 8cd64b95db..afe5845c45 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondary/JobReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondary/JobReconciler.java @@ -65,12 +65,12 @@ public List prepareEventSources(EventSourceContext context) { .of(indexKey(job.getSpec().getClusterName(), job.getMetadata().getNamespace())))); InformerConfiguration.InformerConfigurationBuilder informerConfiguration = - InformerConfiguration.from(Cluster.class, context) + InformerConfiguration.from(Cluster.class, Job.class) .withSecondaryToPrimaryMapper(cluster -> context.getPrimaryCache() .byIndex(JOB_CLUSTER_INDEX, indexKey(cluster.getMetadata().getName(), cluster.getMetadata().getNamespace())) .stream().map(ResourceID::fromResource).collect(Collectors.toSet())) - .withNamespacesInheritedFromController(context); + .withNamespacesInheritedFromController(); if (addPrimaryToSecondaryMapper) { informerConfiguration = informerConfiguration.withPrimaryToSecondaryMapper( diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java index a6cf2cef12..2b48ee0d2a 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java @@ -66,8 +66,9 @@ public List prepareEventSources( context.getPrimaryCache().addIndexer(CONFIG_MAP_INDEX, (primary -> List .of(indexKey(primary.getSpec().getConfigMapName(), primary.getMetadata().getNamespace())))); - var es = new InformerEventSource<>(CONFIG_MAP_EVENT_SOURCE, InformerConfiguration - .from(ConfigMap.class, context) + var es = new InformerEventSource<>(InformerConfiguration + .from(ConfigMap.class, PrimaryToSecondaryDependentCustomResource.class) + .withName(CONFIG_MAP_EVENT_SOURCE) // if there is a many-to-many relationship (thus no direct owner reference) // PrimaryToSecondaryMapper needs to be added .withPrimaryToSecondaryMapper( diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/readonly/ReadOnlyDependent.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/readonly/ReadOnlyDependent.java index 15fb02a0b6..b586e38636 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/readonly/ReadOnlyDependent.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/readonly/ReadOnlyDependent.java @@ -1,8 +1,10 @@ package io.javaoperatorsdk.operator.sample.readonly; import io.fabric8.kubernetes.api.model.ConfigMap; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; +@KubernetesDependent public class ReadOnlyDependent extends KubernetesDependentResource { public ReadOnlyDependent() { diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/restart/ConfigMapDependentResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/restart/ConfigMapDependentResource.java index edb4e2baff..261ebb63b3 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/restart/ConfigMapDependentResource.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/restart/ConfigMapDependentResource.java @@ -7,9 +7,10 @@ import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.InformerConfig; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; -@KubernetesDependent(labelSelector = "app=restart-test") +@KubernetesDependent(informerConfig = @InformerConfig(labelSelector = "app=restart-test")) public class ConfigMapDependentResource extends CRUDKubernetesDependentResource { diff --git a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SchemaDependentResource.java b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SchemaDependentResource.java index 2098b531b3..60875e6ae3 100644 --- a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SchemaDependentResource.java +++ b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SchemaDependentResource.java @@ -16,9 +16,10 @@ import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.dependent.ConfigurationConverter; import io.javaoperatorsdk.operator.api.config.dependent.Configured; +import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter; -import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.ConfiguredDependentResource; import io.javaoperatorsdk.operator.processing.dependent.Creator; import io.javaoperatorsdk.operator.processing.dependent.external.PerResourcePollingDependentResource; import io.javaoperatorsdk.operator.sample.MySQLDbConfig; @@ -38,7 +39,7 @@ converter = ResourcePollerConfigConverter.class) public class SchemaDependentResource extends PerResourcePollingDependentResource - implements DependentResourceConfigurator, + implements ConfiguredDependentResource, Creator, Deleter { public static final String NAME = "schema"; @@ -121,12 +122,12 @@ public Set fetchResources(MySQLSchema primaryResource) { } static class ResourcePollerConfigConverter implements - ConfigurationConverter { + ConfigurationConverter { @Override public ResourcePollerConfig configFrom(SchemaConfig configAnnotation, - ControllerConfiguration parentConfiguration, - Class originatingClass) { + DependentResourceSpec spec, + ControllerConfiguration parentConfiguration) { if (configAnnotation != null) { return new ResourcePollerConfig(Duration.ofMillis(configAnnotation.pollPeriod()), new MySQLDbConfig(configAnnotation.host(), String.valueOf(configAnnotation.port()), diff --git a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SecretDependentResource.java b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SecretDependentResource.java index edaa5707ee..e6cf2a45e7 100644 --- a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SecretDependentResource.java +++ b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SecretDependentResource.java @@ -10,13 +10,16 @@ import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.processing.dependent.Creator; import io.javaoperatorsdk.operator.processing.dependent.Matcher.Result; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; import io.javaoperatorsdk.operator.processing.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper; import io.javaoperatorsdk.operator.sample.MySQLSchema; +@KubernetesDependent public class SecretDependentResource extends KubernetesDependentResource implements Creator, SecondaryToPrimaryMapper { + public static final String NAME = "secret"; public static final String SECRET_SUFFIX = "-secret"; public static final String SECRET_FORMAT = "%s" + SECRET_SUFFIX; @@ -60,10 +63,12 @@ public Result match(Secret actual, MySQLSchema primary, Context toPrimaryResourceIDs(Secret resource) { String name = resource.getMetadata().getName(); return Set.of(new ResourceID(name.substring(0, name.length() - SECRET_SUFFIX.length()), resource.getMetadata().getNamespace())); } + } diff --git a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java index 25e46fad16..e0425235fb 100644 --- a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java +++ b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java @@ -6,9 +6,11 @@ import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.InformerConfig; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; -@KubernetesDependent(labelSelector = "app.kubernetes.io/managed-by=tomcat-operator") +@KubernetesDependent(informerConfig = @InformerConfig( + labelSelector = "app.kubernetes.io/managed-by=tomcat-operator")) public class DeploymentDependentResource extends CRUDKubernetesDependentResource { diff --git a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java index 3b526d02bc..56f3330a45 100644 --- a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java +++ b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java @@ -6,9 +6,11 @@ import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.InformerConfig; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; -@KubernetesDependent(labelSelector = "app.kubernetes.io/managed-by=tomcat-operator") +@KubernetesDependent(informerConfig = @InformerConfig( + labelSelector = "app.kubernetes.io/managed-by=tomcat-operator")) public class ServiceDependentResource extends CRUDKubernetesDependentResource { public ServiceDependentResource() { diff --git a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/WebappReconciler.java b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/WebappReconciler.java index 79194c7990..4a44070f51 100644 --- a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/WebappReconciler.java +++ b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/WebappReconciler.java @@ -59,7 +59,7 @@ public List prepareEventSources(EventSourceContext context) .collect(Collectors.toSet()); InformerConfiguration configuration = - InformerConfiguration.from(Tomcat.class, context) + InformerConfiguration.from(Tomcat.class, Webapp.class) .withSecondaryToPrimaryMapper(webappsMatchingTomcatName) .withPrimaryToSecondaryMapper( (Webapp primary) -> Set.of(new ResourceID(primary.getSpec().getTomcat(), diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageDependentsWorkflowReconciler.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageDependentsWorkflowReconciler.java index d8b64db9fd..ebbbd6f7c8 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageDependentsWorkflowReconciler.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageDependentsWorkflowReconciler.java @@ -9,6 +9,7 @@ import io.fabric8.kubernetes.api.model.networking.v1.Ingress; import io.fabric8.kubernetes.client.KubernetesClient; import io.javaoperatorsdk.operator.api.reconciler.*; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentInformerConfigBuilder; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResourceConfigBuilder; import io.javaoperatorsdk.operator.processing.dependent.workflow.Workflow; @@ -82,7 +83,10 @@ private void initDependentResources(KubernetesClient client) { Arrays.asList(configMapDR, deploymentDR, serviceDR, ingressDR).forEach(dr -> { dr.configureWith(new KubernetesDependentResourceConfigBuilder() - .withLabelSelector(DEPENDENT_RESOURCE_LABEL_SELECTOR).build()); + .withKubernetesDependentInformerConfig(new KubernetesDependentInformerConfigBuilder<>() + .withLabelSelector(DEPENDENT_RESOURCE_LABEL_SELECTOR) + .build()) + .build()); }); } 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 68f55108db..84bfdcdc23 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 @@ -41,19 +41,19 @@ public WebPageReconciler() { @Override public List prepareEventSources(EventSourceContext context) { var configMapEventSource = - new InformerEventSource<>(InformerConfiguration.from(ConfigMap.class, context) + new InformerEventSource<>(InformerConfiguration.from(ConfigMap.class, WebPage.class) .withLabelSelector(SELECTOR) .build(), context); var deploymentEventSource = - new InformerEventSource<>(InformerConfiguration.from(Deployment.class, context) + new InformerEventSource<>(InformerConfiguration.from(Deployment.class, WebPage.class) .withLabelSelector(SELECTOR) .build(), context); var serviceEventSource = - new InformerEventSource<>(InformerConfiguration.from(Service.class, context) + new InformerEventSource<>(InformerConfiguration.from(Service.class, WebPage.class) .withLabelSelector(SELECTOR) .build(), context); var ingressEventSource = - new InformerEventSource<>(InformerConfiguration.from(Ingress.class, context) + new InformerEventSource<>(InformerConfiguration.from(Ingress.class, WebPage.class) .withLabelSelector(SELECTOR) .build(), context); return List.of(configMapEventSource, deploymentEventSource, diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStandaloneDependentsReconciler.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStandaloneDependentsReconciler.java index 4b71f104f6..49a641da01 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStandaloneDependentsReconciler.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStandaloneDependentsReconciler.java @@ -11,6 +11,7 @@ import io.javaoperatorsdk.operator.api.reconciler.EventSourceUtils; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentInformerConfigBuilder; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResourceConfigBuilder; import io.javaoperatorsdk.operator.processing.dependent.workflow.Workflow; import io.javaoperatorsdk.operator.processing.dependent.workflow.WorkflowBuilder; @@ -95,7 +96,9 @@ private Workflow createDependentResourcesAndWorkflow() { // configure them with our label selector Arrays.asList(configMapDR, deploymentDR, serviceDR, ingressDR) .forEach(dr -> dr.configureWith(new KubernetesDependentResourceConfigBuilder() - .withLabelSelector(SELECTOR + "=true").build())); + .withKubernetesDependentInformerConfig(new KubernetesDependentInformerConfigBuilder<>() + .withLabelSelector(SELECTOR + "=true").build()) + .build())); // connect the dependent resources into a workflow, configuring them as we go // Note the method call order is significant and configuration applies to the dependent being diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/ConfigMapDependentResource.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/ConfigMapDependentResource.java index 8641aa343b..aa03aaabca 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/ConfigMapDependentResource.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/ConfigMapDependentResource.java @@ -8,6 +8,7 @@ import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.InformerConfig; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; import io.javaoperatorsdk.operator.sample.customresource.WebPage; @@ -15,7 +16,7 @@ import static io.javaoperatorsdk.operator.sample.WebPageManagedDependentsReconciler.SELECTOR; // this annotation only activates when using managed dependents and is not otherwise needed -@KubernetesDependent(labelSelector = SELECTOR) +@KubernetesDependent(informerConfig = @InformerConfig(labelSelector = SELECTOR)) public class ConfigMapDependentResource extends CRUDKubernetesDependentResource { diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/DeploymentDependentResource.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/DeploymentDependentResource.java index 4b2e373260..3aa90bf54c 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/DeploymentDependentResource.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/DeploymentDependentResource.java @@ -7,6 +7,7 @@ import io.fabric8.kubernetes.api.model.apps.Deployment; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.InformerConfig; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; import io.javaoperatorsdk.operator.sample.Utils; import io.javaoperatorsdk.operator.sample.customresource.WebPage; @@ -17,7 +18,7 @@ import static io.javaoperatorsdk.operator.sample.WebPageManagedDependentsReconciler.SELECTOR; // this annotation only activates when using managed dependents and is not otherwise needed -@KubernetesDependent(labelSelector = SELECTOR) +@KubernetesDependent(informerConfig = @InformerConfig(labelSelector = SELECTOR)) public class DeploymentDependentResource extends CRUDKubernetesDependentResource { diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/IngressDependentResource.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/IngressDependentResource.java index f3a3aa65ba..abfe9a13f5 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/IngressDependentResource.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/IngressDependentResource.java @@ -3,6 +3,7 @@ import io.fabric8.kubernetes.api.model.networking.v1.Ingress; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.InformerConfig; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; import io.javaoperatorsdk.operator.sample.WebPageManagedDependentsReconciler; import io.javaoperatorsdk.operator.sample.customresource.WebPage; @@ -10,7 +11,8 @@ import static io.javaoperatorsdk.operator.sample.Utils.makeDesiredIngress; // this annotation only activates when using managed dependents and is not otherwise needed -@KubernetesDependent(labelSelector = WebPageManagedDependentsReconciler.SELECTOR) +@KubernetesDependent( + informerConfig = @InformerConfig(labelSelector = WebPageManagedDependentsReconciler.SELECTOR)) public class IngressDependentResource extends CRUDKubernetesDependentResource { public IngressDependentResource() { diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/ServiceDependentResource.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/ServiceDependentResource.java index 80d5073a6e..2669fe5f97 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/ServiceDependentResource.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/dependentresource/ServiceDependentResource.java @@ -5,6 +5,7 @@ import io.fabric8.kubernetes.api.model.Service; import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.InformerConfig; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; import io.javaoperatorsdk.operator.sample.Utils; import io.javaoperatorsdk.operator.sample.customresource.WebPage; @@ -15,7 +16,7 @@ import static io.javaoperatorsdk.operator.sample.WebPageManagedDependentsReconciler.SELECTOR; // this annotation only activates when using managed dependents and is not otherwise needed -@KubernetesDependent(labelSelector = SELECTOR) +@KubernetesDependent(informerConfig = @InformerConfig(labelSelector = SELECTOR)) public class ServiceDependentResource extends io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource {