diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/EventSourceInitializer.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/EventSourceInitializer.java index 38f21683d8..e539e10b3a 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/EventSourceInitializer.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/EventSourceInitializer.java @@ -14,11 +14,12 @@ public interface EventSourceInitializer
{
/**
- * Prepares a list of {@link EventSource} implementations to be registered by the SDK.
+ * Prepares a map of {@link EventSource} implementations keyed by the name with which they need to
+ * be registered by the SDK.
*
* @param context a {@link EventSourceContext} providing access to information useful to event
* sources
- * @return list of event sources to register
+ * @return a map of event sources to register
*/
Map context);
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/UpdateControl.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/UpdateControl.java
index 1762198286..eb44735a89 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/UpdateControl.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/UpdateControl.java
@@ -2,7 +2,6 @@
import io.fabric8.kubernetes.api.model.HasMetadata;
-@SuppressWarnings("rawtypes")
public class UpdateControl {
* @return the initiated event source.
*/
EventSource initEventSource(EventSourceContext context);
-
- EventSource getEventSource();
}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java
index 2a96965000..f0fdd07b16 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java
@@ -209,7 +209,6 @@ public UpdateControl execute() throws Exception {
.collect(Collectors.joining("\n")),
exceptions);
}
-
return reconciler.reconcile(resource, context);
}
});
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResource.java
index 8b1a634c08..8c4ef11b1b 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResource.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResource.java
@@ -5,12 +5,7 @@
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter;
-import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
-import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceProvider;
-import io.javaoperatorsdk.operator.api.reconciler.dependent.RecentOperationCacheFiller;
-import io.javaoperatorsdk.operator.api.reconciler.dependent.RecentOperationEventFilter;
-import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.*;
import io.javaoperatorsdk.operator.processing.event.ResourceID;
public abstract class AbstractDependentResource context) {
protected R handleCreate(R desired, P primary, Context context) {
ResourceID resourceID = ResourceID.fromResource(primary);
- R created = null;
- try {
- prepareEventFiltering(desired, resourceID);
- created = creator.create(desired, primary, context);
- cacheAfterCreate(resourceID, created);
- return created;
- } catch (RuntimeException e) {
- cleanupAfterEventFiltering(desired, resourceID, created);
- throw e;
- }
- }
-
- private void cleanupAfterEventFiltering(R desired, ResourceID resourceID, R created) {
- if (isFilteringEventSource()) {
- eventSourceAsRecentOperationEventFilter()
- .cleanupOnCreateOrUpdateEventFiltering(resourceID, created);
- }
- }
-
- private void cacheAfterCreate(ResourceID resourceID, R created) {
- if (isRecentOperationCacheFiller()) {
- eventSourceAsRecentOperationCacheFiller().handleRecentResourceCreate(resourceID, created);
- }
+ R created = creator.create(desired, primary, context);
+ cacheAfterCreate(resourceID, created);
+ return created;
}
- private void cacheAfterUpdate(R actual, ResourceID resourceID, R updated) {
- if (isRecentOperationCacheFiller()) {
- eventSourceAsRecentOperationCacheFiller().handleRecentResourceUpdate(resourceID, updated,
- actual);
- }
- }
+ protected abstract void cacheAfterCreate(ResourceID resourceID, R created);
- private void prepareEventFiltering(R desired, ResourceID resourceID) {
- if (isFilteringEventSource()) {
- eventSourceAsRecentOperationEventFilter().prepareForCreateOrUpdateEventFiltering(resourceID,
- desired);
- }
- }
+ protected abstract void cacheAfterUpdate(R actual, ResourceID resourceID, R updated);
protected R handleUpdate(R actual, R desired, P primary, Context context) {
ResourceID resourceID = ResourceID.fromResource(primary);
- R updated = null;
- try {
- prepareEventFiltering(desired, resourceID);
- updated = updater.update(actual, desired, primary, context);
- cacheAfterUpdate(actual, resourceID, updated);
- return updated;
- } catch (RuntimeException e) {
- cleanupAfterEventFiltering(desired, resourceID, updated);
- throw e;
- }
- }
-
- @SuppressWarnings("unchecked")
- private RecentOperationEventFilter ) this).getEventSource();
- }
-
- @SuppressWarnings("unchecked")
- private RecentOperationCacheFiller ) this).getEventSource();
- }
-
- @SuppressWarnings("unchecked")
- // this cannot be done in constructor since event source might be initialized later
- protected boolean isFilteringEventSource() {
- if (this instanceof EventSourceProvider) {
- final var eventSource = ((EventSourceProvider ) this).getEventSource();
- return eventSource instanceof RecentOperationEventFilter;
- } else {
- return false;
- }
- }
-
- @SuppressWarnings("unchecked")
- // this cannot be done in constructor since event source might be initialized later
- protected boolean isRecentOperationCacheFiller() {
- if (this instanceof EventSourceProvider) {
- final var eventSource = ((EventSourceProvider ) this).getEventSource();
- return eventSource instanceof RecentOperationCacheFiller;
- } else {
- return false;
- }
+ R updated = updater.update(actual, desired, primary, context);
+ cacheAfterUpdate(actual, resourceID, updated);
+ return updated;
}
protected R desired(P primary, Context context) {
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
new file mode 100644
index 0000000000..d104425140
--- /dev/null
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractEventSourceHolderDependentResource.java
@@ -0,0 +1,120 @@
+package io.javaoperatorsdk.operator.processing.dependent;
+
+import io.fabric8.kubernetes.api.model.HasMetadata;
+import io.javaoperatorsdk.operator.OperatorException;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceProvider;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.RecentOperationCacheFiller;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.RecentOperationEventFilter;
+import io.javaoperatorsdk.operator.processing.event.EventHandler;
+import io.javaoperatorsdk.operator.processing.event.ResourceID;
+import io.javaoperatorsdk.operator.processing.event.source.EventSource;
+
+public abstract class AbstractEventSourceHolderDependentResource {
+ private T eventSource;
+ private boolean isFilteringEventSource;
+ private boolean isCacheFillerEventSource;
+
+ @Override
+ public void start() throws OperatorException {
+ eventSource.start();
+ }
+
+ @Override
+ public void stop() throws OperatorException {
+ eventSource.stop();
+ }
+
+ public EventSource initEventSource(EventSourceContext context) {
+ // some sub-classes (e.g. KubernetesDependentResource) can have their event source created
+ // before this method is called in the managed case, so only create the event source if it
+ // hasn't already been set
+ if (eventSource == null) {
+ eventSource = createEventSource(context);
+ }
+
+ // but we still need to record which interfaces the event source implements even if it has
+ // already been set before this method is called
+ isFilteringEventSource = eventSource instanceof RecentOperationEventFilter;
+ isCacheFillerEventSource = eventSource instanceof RecentOperationCacheFiller;
+ return this;
+ }
+
+ protected abstract T createEventSource(EventSourceContext context);
+
+ protected void setEventSource(T eventSource) {
+ this.eventSource = eventSource;
+ }
+
+ @Override
+ public void setEventHandler(EventHandler handler) {
+ eventSource.setEventHandler(handler);
+ }
+
+ protected T eventSource() {
+ return eventSource;
+ }
+
+ protected R handleCreate(R desired, P primary, Context context) {
+ ResourceID resourceID = ResourceID.fromResource(primary);
+ R created = null;
+ try {
+ prepareEventFiltering(desired, resourceID);
+ created = super.handleCreate(desired, primary, context);
+ return created;
+ } catch (RuntimeException e) {
+ cleanupAfterEventFiltering(desired, resourceID, created);
+ throw e;
+ }
+ }
+
+ protected R handleUpdate(R actual, R desired, P primary, Context context) {
+ ResourceID resourceID = ResourceID.fromResource(primary);
+ R updated = null;
+ try {
+ prepareEventFiltering(desired, resourceID);
+ updated = super.handleUpdate(actual, desired, primary, context);
+ return updated;
+ } catch (RuntimeException e) {
+ cleanupAfterEventFiltering(desired, resourceID, updated);
+ throw e;
+ }
+ }
+
+
+ protected void cacheAfterCreate(ResourceID resourceID, R created) {
+ if (isCacheFillerEventSource) {
+ recentOperationCacheFiller().handleRecentResourceCreate(resourceID, created);
+ }
+ }
+
+ protected void cacheAfterUpdate(R actual, ResourceID resourceID, R updated) {
+ if (isCacheFillerEventSource) {
+ recentOperationCacheFiller().handleRecentResourceUpdate(resourceID, updated, actual);
+ }
+ }
+
+ private void prepareEventFiltering(R desired, ResourceID resourceID) {
+ if (isFilteringEventSource) {
+ recentOperationEventFilter().prepareForCreateOrUpdateEventFiltering(resourceID, desired);
+ }
+ }
+
+ private void cleanupAfterEventFiltering(R desired, ResourceID resourceID, R created) {
+ if (isFilteringEventSource) {
+ recentOperationEventFilter().cleanupOnCreateOrUpdateEventFiltering(resourceID, created);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private RecentOperationEventFilter {
-
- protected ExternalResourceCachingEventSource context) {
protected abstract void deleteResource(P primary, Context context);
@Override
- protected R handleCreate(R desired, P primary, Context context) {
- var res = this.creator.create(desired, primary, context);
- cache.put(ResourceID.fromResource(primary), res);
- return res;
+ protected void cacheAfterCreate(ResourceID resourceID, R created) {
+ cache.put(resourceID, created);
}
@Override
- protected R handleUpdate(R actual, R desired, P primary, Context context) {
- var res = updater.update(actual, desired, primary, context);
- cache.put(ResourceID.fromResource(primary), res);
- return res;
+ protected void cacheAfterUpdate(R actual, ResourceID resourceID, R updated) {
+ cache.put(resourceID, updated);
}
public Matcher.Result context) {
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 11b18832a7..b598073a21 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
@@ -2,7 +2,7 @@
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
-import io.javaoperatorsdk.operator.processing.event.source.EventSource;
+import io.javaoperatorsdk.operator.processing.event.ExternalResourceCachingEventSource;
import io.javaoperatorsdk.operator.processing.event.source.polling.PerResourcePollingEventSource;
public abstract class PerResourcePollingDependentResource context) {
- eventSource = new PerResourcePollingEventSource<>(this, context.getPrimaryCache(),
+ protected ExternalResourceCachingEventSource context) {
+ return new PerResourcePollingEventSource<>(this, context.getPrimaryCache(),
getPollingPeriod(), resourceType());
- return eventSource;
}
}
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 58723a6f11..1cc6e22afe 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
@@ -5,8 +5,8 @@
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
+import io.javaoperatorsdk.operator.processing.event.ExternalResourceCachingEventSource;
import io.javaoperatorsdk.operator.processing.event.ResourceID;
-import io.javaoperatorsdk.operator.processing.event.source.EventSource;
import io.javaoperatorsdk.operator.processing.event.source.polling.PollingEventSource;
public abstract class PollingDependentResource context) {
- eventSource = new PollingEventSource<>(this, getPollingPeriod(), resourceType());
- return eventSource;
+ protected ExternalResourceCachingEventSource context) {
+ return new PollingEventSource<>(this, getPollingPeriod(), resourceType());
}
}
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 f77ec0b4aa..c96f993126 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
@@ -14,28 +14,25 @@
import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
-import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceProvider;
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator;
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.KubernetesClientAware;
-import io.javaoperatorsdk.operator.processing.dependent.AbstractDependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.AbstractEventSourceHolderDependentResource;
import io.javaoperatorsdk.operator.processing.dependent.Matcher;
import io.javaoperatorsdk.operator.processing.dependent.Matcher.Result;
import io.javaoperatorsdk.operator.processing.event.ResourceID;
-import io.javaoperatorsdk.operator.processing.event.source.EventSource;
import io.javaoperatorsdk.operator.processing.event.source.PrimaryToSecondaryMapper;
import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper;
import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers;
public abstract class KubernetesDependentResource ,
+ extends AbstractEventSourceHolderDependentResource context) {
return prepare(target, primary, "Creating").create(target);
}
@@ -121,19 +117,11 @@ protected NonNamespaceOperation context) {
- if (informerEventSource == null) {
- configureWith(null, context.getControllerConfiguration().getNamespaces());
- log.warn("Using default configuration for " + resourceType().getSimpleName()
- + " KubernetesDependentResource, call configureWith to provide configuration");
- }
- return informerEventSource;
- }
-
- public KubernetesDependentResource context) {
+ configureWith(null, context.getControllerConfiguration().getNamespaces());
+ log.warn("Using default configuration for " + resourceType().getSimpleName()
+ + " KubernetesDependentResource, call configureWith to provide configuration");
+ return eventSource();
}
protected boolean addOwnerReference() {
@@ -147,7 +135,7 @@ public Class context) {
return super.desired(primary, context);
}
-
- @Override
- public EventSource getEventSource() {
- return informerEventSource;
- }
}
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 34c7686b45..4ac7dd103d 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
@@ -1,13 +1,13 @@
package io.javaoperatorsdk.operator.sample;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import io.fabric8.kubernetes.api.model.ConfigMap;
-import io.fabric8.kubernetes.api.model.Service;
-import io.fabric8.kubernetes.api.model.apps.Deployment;
+import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
@@ -37,20 +37,25 @@ public class WebPageStandaloneDependentsReconciler
private static final Logger log =
LoggerFactory.getLogger(WebPageStandaloneDependentsReconciler.class);
- private KubernetesDependentResource