Skip to content

Commit a0e06c3

Browse files
csvirimetacosm
andcommitted
refactor: simplify handling of reused event sources (#1518)
Co-authored-by: Chris Laprun <[email protected]>
1 parent 33a6818 commit a0e06c3

24 files changed

+142
-146
lines changed

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AnnotationControllerConfiguration.java

+4-5
Original file line numberDiff line numberDiff line change
@@ -219,13 +219,15 @@ public List<DependentResourceSpec> getDependentResources() {
219219
throw new IllegalArgumentException(
220220
"A DependentResource named '" + name + "' already exists: " + spec);
221221
}
222+
var eventSourceName = dependent.useEventSourceWithName();
223+
eventSourceName = Constants.NO_VALUE_SET.equals(eventSourceName) ? null : eventSourceName;
222224
final var context = Utils.contextFor(this, dependentType, null);
223225
spec = new DependentResourceSpec(dependentType, config, name,
224226
Set.of(dependent.dependsOn()),
225227
Utils.instantiate(dependent.readyPostcondition(), Condition.class, context),
226228
Utils.instantiate(dependent.reconcilePrecondition(), Condition.class, context),
227229
Utils.instantiate(dependent.deletePostcondition(), Condition.class, context),
228-
dependent.provideEventSource());
230+
eventSourceName);
229231
specsMap.put(name, spec);
230232
}
231233

@@ -256,7 +258,6 @@ private Object createKubernetesResourceConfig(Class<? extends DependentResource>
256258
OnDeleteFilter<? extends HasMetadata> onDeleteFilter = null;
257259
GenericFilter<? extends HasMetadata> genericFilter = null;
258260
ResourceDiscriminator<?, ? extends HasMetadata> resourceDiscriminator = null;
259-
String eventSourceNameToUse = null;
260261
if (kubeDependent != null) {
261262
if (!Arrays.equals(KubernetesDependent.DEFAULT_NAMESPACES,
262263
kubeDependent.namespaces())) {
@@ -279,14 +280,12 @@ private Object createKubernetesResourceConfig(Class<? extends DependentResource>
279280
resourceDiscriminator =
280281
Utils.instantiate(kubeDependent.resourceDiscriminator(),
281282
ResourceDiscriminator.class, context);
282-
eventSourceNameToUse = Constants.NO_VALUE_SET.equals(kubeDependent.eventSourceToUse()) ? null
283-
: kubeDependent.eventSourceToUse();
284283
}
285284

286285
config =
287286
new KubernetesDependentResourceConfig(namespaces, labelSelector, configuredNS,
288287
resourceDiscriminator, onAddFilter,
289-
onUpdateFilter, onDeleteFilter, genericFilter, eventSourceNameToUse);
288+
onUpdateFilter, onDeleteFilter, genericFilter);
290289

291290
return config;
292291
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverrider.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ private void replaceConfig(String name, Object newConfig, DependentResourceSpec<
174174
namedDependentResourceSpecs.put(name,
175175
new DependentResourceSpec<>(current.getDependentResourceClass(), newConfig, name,
176176
current.getDependsOn(), current.getReadyCondition(), current.getReconcileCondition(),
177-
current.getDeletePostCondition(), current.provideEventSource()));
177+
current.getDeletePostCondition(), current.getUseEventSourceWithName().orElse(null)));
178178
}
179179

180180
@SuppressWarnings("unchecked")
@@ -220,7 +220,8 @@ public ControllerConfiguration<R> build() {
220220
KubernetesDependentResourceConfig c) {
221221
return new DependentResourceSpec(spec.getDependentResourceClass(),
222222
c.setNamespaces(namespaces), name, spec.getDependsOn(), spec.getReadyCondition(),
223-
spec.getReconcileCondition(), spec.getDeletePostCondition(), spec.provideEventSource());
223+
spec.getReconcileCondition(), spec.getDeletePostCondition(),
224+
(String) spec.getUseEventSourceWithName().orElse(null));
224225
}
225226

226227
public static <R extends HasMetadata> ControllerConfigurationOverrider<R> override(

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceSpec.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,20 @@ public class DependentResourceSpec<T extends DependentResource<?, ?>, C> {
2323

2424
private final Condition<?, ?> deletePostCondition;
2525

26-
private final boolean provideEventSource;
26+
private final String useEventSourceWithName;
2727

2828
public DependentResourceSpec(Class<T> dependentResourceClass, C dependentResourceConfig,
2929
String name, Set<String> dependsOn, Condition<?, ?> readyCondition,
3030
Condition<?, ?> reconcileCondition, Condition<?, ?> deletePostCondition,
31-
boolean provideEventSource) {
31+
String useEventSourceWithName) {
3232
this.dependentResourceClass = dependentResourceClass;
3333
this.dependentResourceConfig = dependentResourceConfig;
3434
this.name = name;
3535
this.dependsOn = dependsOn;
3636
this.readyCondition = readyCondition;
3737
this.reconcileCondition = reconcileCondition;
3838
this.deletePostCondition = deletePostCondition;
39-
this.provideEventSource = provideEventSource;
39+
this.useEventSourceWithName = useEventSourceWithName;
4040
}
4141

4242
public Class<T> getDependentResourceClass() {
@@ -94,7 +94,7 @@ public Condition getDeletePostCondition() {
9494
return deletePostCondition;
9595
}
9696

97-
public boolean provideEventSource() {
98-
return provideEventSource;
97+
public Optional<String> getUseEventSourceWithName() {
98+
return Optional.ofNullable(useEventSourceWithName);
9999
}
100100
}

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

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

3+
import io.javaoperatorsdk.operator.api.reconciler.Constants;
34
import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
45

56
import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_VALUE_SET;
@@ -59,11 +60,11 @@
5960
String[] dependsOn() default {};
6061

6162
/**
62-
* Setting this to false means that the event source provided by the dependent resource won't be
63-
* used. This is helpful if more dependent resources created for the same type, and want to share
64-
* a common event source. In that case an event source needs to be explicitly registered.
63+
* Setting here a name of the event source means that dependent resource will use an event source
64+
* registered with that name. So won't create one. This is helpful if more dependent resources
65+
* created for the same type, and want to share a common event source.
6566
*
66-
* @return if the event source (if any) provided by the dependent resource should be used or not.
67+
* @return event source name (if any) provided by the dependent resource should be used.
6768
*/
68-
boolean provideEventSource() default true;
69+
String useEventSourceWithName() default NO_VALUE_SET;
6970
}

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

-7
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,6 @@ default Optional<ResourceEventSource<R, P>> eventSource(
4949
return Optional.empty();
5050
}
5151

52-
/**
53-
* Calling this method, instructs the implementation to not provide an event source, even if it
54-
* normally does.
55-
*/
56-
void doNotProvideEventSource();
57-
58-
5952
default Optional<R> getSecondaryResource(P primary, Context<P> context) {
6053
return Optional.empty();
6154
}

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

-10
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package io.javaoperatorsdk.operator.api.reconciler.dependent;
2+
3+
import io.javaoperatorsdk.operator.OperatorException;
4+
5+
public class EventSourceNotFoundException extends OperatorException {
6+
7+
private String eventSourceName;
8+
9+
public EventSourceNotFoundException(String eventSourceName) {
10+
this.eventSourceName = eventSourceName;
11+
}
12+
13+
public String getEventSourceName() {
14+
return eventSourceName;
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package io.javaoperatorsdk.operator.api.reconciler.dependent;
2+
3+
import io.fabric8.kubernetes.api.model.HasMetadata;
4+
import io.javaoperatorsdk.operator.processing.event.EventSourceRetriever;
5+
6+
public interface EventSourceReferencer<P extends HasMetadata> {
7+
8+
default void useEventSourceWithName(String name) {}
9+
10+
/**
11+
* Throws {@link EventSourceNotFoundException} an exception if the target event source to use is
12+
* not found.
13+
*/
14+
void resolveEventSource(EventSourceRetriever<P> eventSourceRetriever)
15+
throws EventSourceNotFoundException;
16+
17+
}

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

+39-20
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package io.javaoperatorsdk.operator.processing;
22

3+
import java.util.ArrayList;
4+
import java.util.HashMap;
5+
import java.util.List;
36
import java.util.Map;
47
import java.util.Optional;
58
import java.util.Set;
@@ -32,8 +35,9 @@
3235
import io.javaoperatorsdk.operator.api.reconciler.Ignore;
3336
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
3437
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
35-
import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceAware;
38+
import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceNotFoundException;
3639
import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceProvider;
40+
import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceReferencer;
3741
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DefaultManagedDependentResourceContext;
3842
import io.javaoperatorsdk.operator.processing.dependent.workflow.ManagedWorkflow;
3943
import io.javaoperatorsdk.operator.processing.dependent.workflow.WorkflowCleanupResult;
@@ -214,25 +218,40 @@ public void initAndRegisterEventSources(EventSourceContext<P> context) {
214218
final var ownSources = provider.prepareEventSources(context);
215219
ownSources.forEach(eventSourceManager::registerEventSource);
216220
}
217-
managedWorkflow
218-
.getDependentResourcesByName().entrySet().stream()
219-
.forEach(drEntry -> {
220-
if (drEntry.getValue() instanceof EventSourceProvider) {
221-
final var provider = (EventSourceProvider) drEntry.getValue();
222-
final var source = provider.initEventSource(context);
223-
eventSourceManager.registerEventSource(drEntry.getKey(), source);
224-
} else {
225-
Optional<ResourceEventSource> eventSource =
226-
drEntry.getValue().eventSource(context);
227-
eventSource.ifPresent(es -> {
228-
eventSourceManager.registerEventSource(drEntry.getKey(), es);
229-
});
230-
}
231-
});
232-
managedWorkflow.getDependentResourcesByName().entrySet().stream().map(Map.Entry::getValue)
233-
.filter(EventSourceAware.class::isInstance)
234-
.forEach(dr -> ((EventSourceAware) dr)
235-
.selectEventSources(eventSourceManager));
221+
222+
// register created event sources
223+
final var dependentResourcesByName = managedWorkflow.getDependentResourcesByName();
224+
final var size = dependentResourcesByName.size();
225+
if (size > 0) {
226+
dependentResourcesByName.forEach((key, value) -> {
227+
if (value instanceof EventSourceProvider) {
228+
final var provider = (EventSourceProvider) value;
229+
final var source = provider.initEventSource(context);
230+
eventSourceManager.registerEventSource(key, source);
231+
} else {
232+
Optional<ResourceEventSource> eventSource = value.eventSource(context);
233+
eventSource.ifPresent(es -> eventSourceManager.registerEventSource(key, es));
234+
}
235+
});
236+
237+
// resolve event sources referenced by name for dependents that reuse an existing event source
238+
final Map<String, List<EventSourceReferencer>> unresolvable = new HashMap<>(size);
239+
dependentResourcesByName.values().stream()
240+
.filter(EventSourceReferencer.class::isInstance)
241+
.map(EventSourceReferencer.class::cast)
242+
.forEach(dr -> {
243+
try {
244+
((EventSourceReferencer<P>) dr)
245+
.resolveEventSource(eventSourceManager);
246+
} catch (EventSourceNotFoundException e) {
247+
unresolvable.computeIfAbsent(e.getEventSourceName(), s -> new ArrayList<>()).add(dr);
248+
}
249+
});
250+
if (!unresolvable.isEmpty()) {
251+
throw new IllegalStateException(
252+
"Couldn't resolve referenced EventSources: " + unresolvable);
253+
}
254+
}
236255
}
237256

238257
@Override

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

-23
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,11 @@
99

1010
import io.fabric8.kubernetes.api.model.HasMetadata;
1111
import io.javaoperatorsdk.operator.api.reconciler.Context;
12-
import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
1312
import io.javaoperatorsdk.operator.api.reconciler.Ignore;
1413
import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
1514
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
1615
import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult;
1716
import io.javaoperatorsdk.operator.processing.event.ResourceID;
18-
import io.javaoperatorsdk.operator.processing.event.source.ResourceEventSource;
1917

2018
@Ignore
2119
public abstract class AbstractDependentResource<R, P extends HasMetadata>
@@ -29,7 +27,6 @@ public abstract class AbstractDependentResource<R, P extends HasMetadata>
2927
protected Creator<R, P> creator;
3028
protected Updater<R, P> updater;
3129
protected BulkDependentResource<R, P> bulkDependentResource;
32-
private boolean returnEventSource = true;
3330

3431
protected List<ResourceDiscriminator<R, P>> resourceDiscriminator = new ArrayList<>(1);
3532

@@ -41,23 +38,6 @@ public AbstractDependentResource() {
4138
bulkDependentResource = bulk ? (BulkDependentResource<R, P>) this : null;
4239
}
4340

44-
@Override
45-
public void doNotProvideEventSource() {
46-
this.returnEventSource = false;
47-
}
48-
49-
@Override
50-
public Optional<ResourceEventSource<R, P>> eventSource(EventSourceContext<P> eventSourceContext) {
51-
if (!returnEventSource) {
52-
return Optional.empty();
53-
} else {
54-
return Optional.of(provideEventSource(eventSourceContext));
55-
}
56-
}
57-
58-
protected abstract ResourceEventSource<R, P> provideEventSource(
59-
EventSourceContext<P> eventSourceContext);
60-
6141
@Override
6242
public ReconcileResult<R> reconcile(P primary, Context<P> context) {
6343
if (bulk) {
@@ -239,7 +219,4 @@ protected int lastKnownBulkSize() {
239219
return resourceDiscriminator.size();
240220
}
241221

242-
protected boolean getReturnEventSource() {
243-
return returnEventSource;
244-
}
245222
}

0 commit comments

Comments
 (0)