Skip to content

Commit a464205

Browse files
committed
feat: optional event source from dependent resources
1 parent 43db6ad commit a464205

File tree

14 files changed

+89
-262
lines changed

14 files changed

+89
-262
lines changed

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/EventSourceInitializer.java

+15
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
import java.util.HashMap;
44
import java.util.Map;
5+
import java.util.Optional;
56

67
import io.fabric8.kubernetes.api.model.HasMetadata;
8+
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
79
import io.javaoperatorsdk.operator.processing.event.source.EventSource;
10+
import io.javaoperatorsdk.operator.processing.event.source.ResourceEventSource;
811

912
/**
1013
* An interface that a {@link Reconciler} can implement to have the SDK register the provided
@@ -39,6 +42,18 @@ static Map<String, EventSource> nameEventSources(EventSource... eventSources) {
3942
return eventSourceMap;
4043
}
4144

45+
@SuppressWarnings("unchecked,rawtypes")
46+
static <K extends HasMetadata> Map<String, EventSource> nameEventSourcesFromDependentResource(
47+
EventSourceContext<K> context, DependentResource... dependentResources) {
48+
49+
Map<String, EventSource> eventSourceMap = new HashMap<>(dependentResources.length);
50+
for (DependentResource dependentResource : dependentResources) {
51+
Optional<ResourceEventSource> es = dependentResource.provideEventSource(context);
52+
es.ifPresent(e -> eventSourceMap.put(generateNameFor(e), e));
53+
}
54+
return eventSourceMap;
55+
}
56+
4257
/**
4358
* This is for the use case when the event sources are not access explicitly by name in the
4459
* reconciler.

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java

+9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package io.javaoperatorsdk.operator.api.reconciler.dependent;
22

3+
import java.util.Optional;
4+
35
import io.fabric8.kubernetes.api.model.HasMetadata;
46
import io.javaoperatorsdk.operator.api.reconciler.Context;
7+
import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
8+
import io.javaoperatorsdk.operator.processing.event.source.ResourceEventSource;
59

610
/**
711
* An interface to implement and provide dependent resource support.
@@ -27,6 +31,11 @@ public interface DependentResource<R, P extends HasMetadata> {
2731
*/
2832
Class<R> resourceType();
2933

34+
default Optional<ResourceEventSource<R, P>> provideEventSource(
35+
EventSourceContext<P> eventSourceContext) {
36+
return Optional.empty();
37+
}
38+
3039
/**
3140
* Computes a default name for the specified DependentResource class
3241
*

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/EventSourceProvider.java

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
55
import io.javaoperatorsdk.operator.processing.event.source.EventSource;
66

7+
/**
8+
* @deprecated now event source related methods are directly on {@link DependentResource}
9+
* @param <P> primary resource
10+
*/
11+
@Deprecated(forRemoval = true)
712
public interface EventSourceProvider<P extends HasMetadata> {
813
/**
914
* @param context - event source context where the event source is initialized

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java

+12-5
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import io.javaoperatorsdk.operator.processing.event.EventProcessor;
4040
import io.javaoperatorsdk.operator.processing.event.EventSourceManager;
4141
import io.javaoperatorsdk.operator.processing.event.ResourceID;
42+
import io.javaoperatorsdk.operator.processing.event.source.ResourceEventSource;
4243

4344
import static io.javaoperatorsdk.operator.api.reconciler.Constants.WATCH_CURRENT_NAMESPACE;
4445

@@ -209,13 +210,19 @@ private void initContextIfNeeded(P resource, Context<P> context) {
209210
public void initAndRegisterEventSources(EventSourceContext<P> context) {
210211
managedWorkflow
211212
.getDependentResourcesByName().entrySet().stream()
212-
.filter(drEntry -> drEntry.getValue() instanceof EventSourceProvider)
213213
.forEach(drEntry -> {
214-
final var provider = (EventSourceProvider) drEntry.getValue();
215-
final var source = provider.initEventSource(context);
216-
eventSourceManager.registerEventSource(drEntry.getKey(), source);
214+
if (drEntry.getValue() instanceof EventSourceProvider) {
215+
final var provider = (EventSourceProvider) drEntry.getValue();
216+
final var source = provider.initEventSource(context);
217+
eventSourceManager.registerEventSource(drEntry.getKey(), source);
218+
} else {
219+
Optional<ResourceEventSource> eventSource =
220+
drEntry.getValue().provideEventSource(context);
221+
eventSource.ifPresent(es -> {
222+
eventSourceManager.registerEventSource(drEntry.getKey(), es);
223+
});
224+
}
217225
});
218-
219226
// add manually defined event sources
220227
if (reconciler instanceof EventSourceInitializer) {
221228
final var provider = (EventSourceInitializer<P>) this.reconciler;

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractEventSourceHolderDependentResource.java

+29-10
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package io.javaoperatorsdk.operator.processing.dependent;
22

3+
import java.util.Optional;
4+
35
import io.fabric8.kubernetes.api.model.HasMetadata;
46
import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
57
import io.javaoperatorsdk.operator.api.reconciler.Ignore;
6-
import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceProvider;
78
import io.javaoperatorsdk.operator.api.reconciler.dependent.RecentOperationCacheFiller;
89
import io.javaoperatorsdk.operator.processing.event.ResourceID;
9-
import io.javaoperatorsdk.operator.processing.event.source.EventSource;
1010
import io.javaoperatorsdk.operator.processing.event.source.ResourceEventSource;
1111
import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter;
1212
import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter;
@@ -15,8 +15,7 @@
1515

1616
@Ignore
1717
public abstract class AbstractEventSourceHolderDependentResource<R, P extends HasMetadata, T extends ResourceEventSource<R, P>>
18-
extends AbstractDependentResource<R, P>
19-
implements EventSourceProvider<P> {
18+
extends AbstractDependentResource<R, P> {
2019

2120
private T eventSource;
2221
private boolean isCacheFillerEventSource;
@@ -25,26 +24,42 @@ public abstract class AbstractEventSourceHolderDependentResource<R, P extends Ha
2524
protected OnDeleteFilter<R> onDeleteFilter;
2625
protected GenericFilter<R> genericFilter;
2726

27+
/**
28+
* Even a dependent resource holds an event source, it might not provide it. For example if event
29+
* sources are shared between multiple dependent resources. Typically
30+
* {@link io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource}
31+
* needs to be aware of event source even if the actual state of the resource is not read directly
32+
* from the event source.
33+
*/
34+
private boolean provideEventSource = true;
35+
2836

29-
public EventSource initEventSource(EventSourceContext<P> context) {
37+
public Optional<ResourceEventSource<R, P>> provideEventSource(EventSourceContext<P> context) {
38+
if (!provideEventSource) {
39+
return Optional.empty();
40+
}
3041
// some sub-classes (e.g. KubernetesDependentResource) can have their event source created
3142
// before this method is called in the managed case, so only create the event source if it
3243
// hasn't already been set.
3344
// The filters are applied automatically only if event source is created automatically. So if an
3445
// event source
3546
// is shared between dependent resources this does not override the existing filters.
3647
if (eventSource == null) {
37-
eventSource = createEventSource(context);
48+
setEventSource(createEventSource(context));
3849
applyFilters();
3950
}
51+
return Optional.of(eventSource);
52+
}
4053

41-
isCacheFillerEventSource = eventSource instanceof RecentOperationCacheFiller;
42-
return eventSource;
54+
/** To make this backwards compatible even for respect of overriding */
55+
public T initEventSource(EventSourceContext<P> context) {
56+
return (T) provideEventSource(context).orElseThrow();
4357
}
4458

4559
protected abstract T createEventSource(EventSourceContext<P> context);
4660

4761
protected void setEventSource(T eventSource) {
62+
isCacheFillerEventSource = eventSource instanceof RecentOperationCacheFiller;
4863
this.eventSource = eventSource;
4964
}
5065

@@ -55,8 +70,8 @@ protected void applyFilters() {
5570
this.eventSource.setGenericFilter(genericFilter);
5671
}
5772

58-
protected T eventSource() {
59-
return eventSource;
73+
public Optional<ResourceEventSource<R, P>> eventSource() {
74+
return Optional.ofNullable(eventSource);
6075
}
6176

6277
protected void onCreated(ResourceID primaryResourceId, R created) {
@@ -87,4 +102,8 @@ public void setOnUpdateFilter(OnUpdateFilter<R> onUpdateFilter) {
87102
public void setOnDeleteFilter(OnDeleteFilter<R> onDeleteFilter) {
88103
this.onDeleteFilter = onDeleteFilter;
89104
}
105+
106+
public void setProvideEventSource(boolean provideEventSource) {
107+
this.provideEventSource = provideEventSource;
108+
}
90109
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/AbstractSimpleDependentResource.java

-81
This file was deleted.

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ protected InformerEventSource<R, P> createEventSource(EventSourceContext<P> cont
179179
"Using default configuration for {} KubernetesDependentResource, call configureWith to provide configuration",
180180
resourceType().getSimpleName());
181181
}
182-
return eventSource();
182+
return (InformerEventSource<R, P>) eventSource().orElseThrow();
183183
}
184184

185185
private boolean useDefaultAnnotationsToIdentifyPrimary() {
@@ -227,11 +227,13 @@ protected R desired(P primary, Context<P> context) {
227227
}
228228

229229
private void prepareEventFiltering(R desired, ResourceID resourceID) {
230-
eventSource().prepareForCreateOrUpdateEventFiltering(resourceID, desired);
230+
((InformerEventSource<R, P>) eventSource().orElseThrow())
231+
.prepareForCreateOrUpdateEventFiltering(resourceID, desired);
231232
}
232233

233234
private void cleanupAfterEventFiltering(ResourceID resourceID) {
234-
eventSource().cleanupOnCreateOrUpdateEventFiltering(resourceID);
235+
((InformerEventSource<R, P>) eventSource().orElseThrow())
236+
.cleanupOnCreateOrUpdateEventFiltering(resourceID);
235237
}
236238

237239
}

0 commit comments

Comments
 (0)