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 9d912986e1..10ab50138a 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 @@ -79,7 +79,7 @@ public List> prepareEventSources( var es = new InformerEventSource<>( InformerEventSourceConfiguration.from(ConfigMap.class, primaryClass()) - .withInformerConfiguration(c -> c.withItemStore(boundedItemStore)) + .withItemStore(boundedItemStore) .withSecondaryToPrimaryMapper( Mappers.fromOwnerReferences(context.getPrimaryResourceClass(), this instanceof BoundedCacheClusterScopeTestReconciler)) diff --git a/docs/content/en/docs/features/_index.md b/docs/content/en/docs/features/_index.md index 12528d3a7e..de49abe2b5 100644 --- a/docs/content/en/docs/features/_index.md +++ b/docs/content/en/docs/features/_index.md @@ -472,7 +472,7 @@ public class WebappReconciler @Override public Map prepareEventSources(EventSourceContext context) { - InformerConfiguration configuration = + InformerEventSourceConfiguration configuration = InformerEventSourceConfiguration.from(Tomcat.class, Tomcat.class) .withSecondaryToPrimaryMapper(webappsMatchingTomcatName) .withPrimaryToSecondaryMapper( @@ -547,7 +547,7 @@ fabric8 Kubernetes client class, that will listen for events associated with the you configured your `InformerEventSource` with. If you want to listen to Kubernetes resource events, `InformerEventSource` is probably the only thing you need to use. It's highly configurable so you can tune it to your needs. Take a look at -[InformerConfiguration](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java) +[InformerEventSourceConfiguration](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java) and associated classes for more details but some interesting features we can mention here is the ability to filter events so that you can only get notified for events you care about. A particularly interesting feature of the `InformerEventSource`, as opposed to using your own diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java index d0ee1f1cf0..c3c2777049 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerEventSourceConfiguration.java @@ -2,17 +2,26 @@ import java.util.Objects; import java.util.Optional; -import java.util.function.Consumer; +import java.util.Set; import io.fabric8.kubernetes.api.model.GenericKubernetesResource; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.informers.cache.ItemStore; import io.javaoperatorsdk.operator.api.config.Informable; import io.javaoperatorsdk.operator.processing.GroupVersionKind; import io.javaoperatorsdk.operator.processing.event.source.PrimaryToSecondaryMapper; import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper; +import io.javaoperatorsdk.operator.processing.event.source.filter.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.javaoperatorsdk.operator.processing.event.source.informer.Mappers; +import static io.javaoperatorsdk.operator.api.reconciler.Constants.SAME_AS_CONTROLLER_NAMESPACES_SET; +import static io.javaoperatorsdk.operator.api.reconciler.Constants.WATCH_ALL_NAMESPACE_SET; +import static io.javaoperatorsdk.operator.api.reconciler.Constants.WATCH_CURRENT_NAMESPACE_SET; + public interface InformerEventSourceConfiguration extends Informable { @@ -145,12 +154,6 @@ private Builder(Class resourceClass, this.config = InformerConfiguration.builder(resourceClass); } - public Builder withInformerConfiguration( - Consumer.Builder> configurator) { - configurator.accept(config); - return this; - } - public Builder withName(String name) { this.name = name; config.withName(name); @@ -187,6 +190,79 @@ public SecondaryToPrimaryMapper getSecondaryToPrimaryMapper() { return secondaryToPrimaryMapper; } + public Builder withNamespaces(Set namespaces) { + config.withNamespaces(namespaces); + return this; + } + + public Builder withNamespacesInheritedFromController() { + withNamespaces(SAME_AS_CONTROLLER_NAMESPACES_SET); + return this; + } + + public Builder withWatchAllNamespaces() { + withNamespaces(WATCH_ALL_NAMESPACE_SET); + return this; + } + + public Builder withWatchCurrentNamespace() { + withNamespaces(WATCH_CURRENT_NAMESPACE_SET); + return this; + } + + + /** + * Whether the associated informer should track changes made to the parent + * {@link io.javaoperatorsdk.operator.processing.Controller}'s namespaces configuration. + * + * @param followChanges {@code true} to reconfigure the associated informer when the parent + * controller's namespaces are reconfigured, {@code false} otherwise + * @return the builder instance so that calls can be chained fluently + */ + public Builder withFollowControllerNamespacesChanges(boolean followChanges) { + config.withFollowControllerNamespacesChanges(followChanges); + return this; + } + + public Builder withLabelSelector(String labelSelector) { + config.withLabelSelector(labelSelector); + return this; + } + + public Builder withOnAddFilter( + OnAddFilter onAddFilter) { + config.withOnAddFilter(onAddFilter); + return this; + } + + public Builder withOnUpdateFilter( + OnUpdateFilter onUpdateFilter) { + config.withOnUpdateFilter(onUpdateFilter); + return this; + } + + public Builder withOnDeleteFilter( + OnDeleteFilter onDeleteFilter) { + config.withOnDeleteFilter(onDeleteFilter); + return this; + } + + public Builder withGenericFilter( + GenericFilter genericFilter) { + config.withGenericFilter(genericFilter); + return this; + } + + public Builder withItemStore(ItemStore itemStore) { + config.withItemStore(itemStore); + return this; + } + + public Builder withInformerListLimit(Long informerListLimit) { + config.withInformerListLimit(informerListLimit); + return this; + } + public void updateFrom(InformerConfiguration informerConfig) { if (informerConfig != null) { final var informerConfigName = informerConfig.getName(); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/clusterscopedresource/ClusterScopedCustomResourceReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/clusterscopedresource/ClusterScopedCustomResourceReconciler.java index 3be5a055d7..dd3316f8fc 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/clusterscopedresource/ClusterScopedCustomResourceReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/clusterscopedresource/ClusterScopedCustomResourceReconciler.java @@ -63,8 +63,7 @@ public List> prepareEventSources( InformerEventSourceConfiguration.from(ConfigMap.class, ClusterScopedCustomResource.class) .withSecondaryToPrimaryMapper( Mappers.fromOwnerReferences(context.getPrimaryResourceClass(), true)) - .withInformerConfiguration( - c -> c.withLabelSelector(TEST_LABEL_KEY + "=" + TEST_LABEL_VALUE)) + .withLabelSelector(TEST_LABEL_KEY + "=" + TEST_LABEL_VALUE) .build(), context); return List.of(ies); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/createupdateeventfilter/CreateUpdateEventFilterTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/createupdateeventfilter/CreateUpdateEventFilterTestReconciler.java index 041021cf68..4ec65f5673 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/createupdateeventfilter/CreateUpdateEventFilterTestReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/createupdateeventfilter/CreateUpdateEventFilterTestReconciler.java @@ -72,11 +72,11 @@ public List> prepareEv InformerEventSourceConfiguration informerConfiguration = InformerEventSourceConfiguration .from(ConfigMap.class, CreateUpdateEventFilterTestCustomResource.class) - .withInformerConfiguration(c -> c - .withLabelSelector("integrationtest = " + this.getClass().getSimpleName())) + .withLabelSelector("integrationtest = " + this.getClass().getSimpleName()) .build(); + final var informerEventSource = - new InformerEventSource( + new InformerEventSource<>( informerConfiguration, context); this.configMapDR.setEventSource(informerEventSource); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/filter/FilterTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/filter/FilterTestReconciler.java index 22a9bc7067..add0075a3b 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/filter/FilterTestReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/filter/FilterTestReconciler.java @@ -59,9 +59,9 @@ public List> prepareEventSources( final var informerConfiguration = InformerEventSourceConfiguration .from(ConfigMap.class, FilterTestCustomResource.class) - .withInformerConfiguration(c -> c.withOnUpdateFilter((newCM, + .withOnUpdateFilter((newCM, oldCM) -> !newCM.getData().get(CM_VALUE_KEY) - .equals(CONFIG_MAP_FILTER_VALUE))) + .equals(CONFIG_MAP_FILTER_VALUE)) .build(); InformerEventSource configMapES = new InformerEventSource<>(informerConfiguration, context); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/informerremotecluster/InformerRemoteClusterReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/informerremotecluster/InformerRemoteClusterReconciler.java index 9246e0bbd5..30735dd880 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/informerremotecluster/InformerRemoteClusterReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/informerremotecluster/InformerRemoteClusterReconciler.java @@ -5,7 +5,6 @@ import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.fabric8.kubernetes.client.KubernetesClient; -import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.api.config.informer.InformerEventSourceConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; @@ -57,8 +56,7 @@ public List> prepareEventSou Mappers.fromDefaultAnnotations(InformerRemoteClusterCustomResource.class)) // setting remote client for informer .withKubernetesClient(remoteClient) - .withInformerConfiguration( - InformerConfiguration.Builder::withWatchAllNamespaces) + .withWatchAllNamespaces() .build(), context); return List.of(es); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiplesecondaryeventsource/MultipleSecondaryEventSourceReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiplesecondaryeventsource/MultipleSecondaryEventSourceReconciler.java index 77a3b245b0..12ebf45c8c 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiplesecondaryeventsource/MultipleSecondaryEventSourceReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiplesecondaryeventsource/MultipleSecondaryEventSourceReconciler.java @@ -70,12 +70,8 @@ public List> prepareE var config = InformerEventSourceConfiguration .from(ConfigMap.class, MultipleSecondaryEventSourceCustomResource.class) - .withInformerConfiguration(c -> c - // TODO: this shouldn't be needed since this should be the default behavior (tracking - // the controller's namespaces) - .withNamespaces( - context.getControllerConfiguration().getInformerConfig().getNamespaces()) - .withLabelSelector("multisecondary")) + .withNamespacesInheritedFromController() + .withLabelSelector("multisecondary") .withSecondaryToPrimaryMapper(s -> { var name = s.getMetadata().getName().subSequence(0, s.getMetadata().getName().length() - 1); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/primarytosecondary/JobReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/primarytosecondary/JobReconciler.java index b0f369817e..fdca997f7d 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/primarytosecondary/JobReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/primarytosecondary/JobReconciler.java @@ -5,7 +5,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; -import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.api.config.informer.InformerEventSourceConfiguration; import io.javaoperatorsdk.operator.api.reconciler.*; import io.javaoperatorsdk.operator.processing.event.ResourceID; @@ -71,8 +70,7 @@ public List> prepareEventSources(EventSourceContext con .byIndex(JOB_CLUSTER_INDEX, indexKey(cluster.getMetadata().getName(), cluster.getMetadata().getNamespace())) .stream().map(ResourceID::fromResource).collect(Collectors.toSet())) - .withInformerConfiguration( - InformerConfiguration.Builder::withNamespacesInheritedFromController); + .withNamespacesInheritedFromController(); if (addPrimaryToSecondaryMapper) { informerConfiguration = informerConfiguration.withPrimaryToSecondaryMapper( 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 56b66fbfb3..a687929b22 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 @@ -43,25 +43,25 @@ public List> prepareEventSources(EventSourceContext( InformerEventSourceConfiguration.from(ConfigMap.class, WebPage.class) - .withInformerConfiguration(c -> c.withLabelSelector(SELECTOR)) + .withLabelSelector(SELECTOR) .build(), context); var deploymentEventSource = new InformerEventSource<>( InformerEventSourceConfiguration.from(Deployment.class, WebPage.class) - .withInformerConfiguration(c -> c.withLabelSelector(SELECTOR)) + .withLabelSelector(SELECTOR) .build(), context); var serviceEventSource = new InformerEventSource<>( InformerEventSourceConfiguration.from(Service.class, WebPage.class) - .withInformerConfiguration(c -> c.withLabelSelector(SELECTOR)) + .withLabelSelector(SELECTOR) .build(), context); var ingressEventSource = new InformerEventSource<>( InformerEventSourceConfiguration.from(Ingress.class, WebPage.class) - .withInformerConfiguration(c -> c.withLabelSelector(SELECTOR)) + .withLabelSelector(SELECTOR) .build(), context); return List.of(configMapEventSource, deploymentEventSource,