Skip to content

Commit 48f4e18

Browse files
committed
fix: make sure event sources are properly registered
1 parent 5ef8fd8 commit 48f4e18

File tree

9 files changed

+46
-39
lines changed

9 files changed

+46
-39
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ public void prepareEventSources(EventSourceRegistry<R> eventSourceRegistry, Clon
144144
configuration.getDependentResources().forEach(dependent -> {
145145
final var dependentConfiguration = dependent.getConfiguration();
146146
final var source = new AbstractResourceEventSource<>(dependentConfiguration,
147-
kubernetesClient.resources(dependentConfiguration.getResourceClass()), cloner) {
147+
kubernetesClient.resources(dependentConfiguration.getResourceClass()), cloner,
148+
eventSourceRegistry) {
148149
@Override
149150
protected ResourceEventFilter initFilter(ResourceConfiguration configuration) {
150151
return configuration.getEventFilter();
@@ -156,7 +157,8 @@ protected EventSourceWrapper wrapEventSource(
156157
return new InformerEventSourceEventSourceWrapper(filteredBySelectorClient, cloner,
157158
dependentConfiguration.getPrimaryResourcesRetriever(),
158159
dependentConfiguration.getAssociatedResourceRetriever(),
159-
dependentConfiguration.skipUpdateIfUnchanged());
160+
dependentConfiguration.skipUpdateIfUnchanged(),
161+
eventSourceRegistry);
160162
}
161163
};
162164
eventSourceRegistry.registerEventSource(source);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public class EventSourceManager<R extends HasMetadata>
3939

4040
public EventSourceManager(Controller<R> controller) {
4141
this.controller = controller;
42-
controllerResourceEventSource = new ControllerResourceEventSource<>(controller);
42+
controllerResourceEventSource = new ControllerResourceEventSource<>(controller, this);
4343
this.eventProcessor = new EventProcessor<>(this);
4444
registerEventSource(controllerResourceEventSource);
4545
initRetryEventSource();

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/AbstractResourceEventSource.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@ public abstract class AbstractResourceEventSource<T extends HasMetadata, U exten
3636
private ResourceCache<T> cache;
3737

3838
public AbstractResourceEventSource(U configuration,
39-
MixedOperation<T, KubernetesResourceList<T>, Resource<T>> client, Cloner cloner) {
39+
MixedOperation<T, KubernetesResourceList<T>, Resource<T>> client, Cloner cloner,
40+
EventSourceRegistry<P> registry) {
4041
this.configuration = configuration;
4142
this.client = client;
4243
this.filter = initFilter(configuration);
4344
this.cloner = cloner;
45+
setEventRegistry(registry);
4446
}
4547

4648
protected abstract ResourceEventFilter<T, U> initFilter(U configuration);

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/ControllerResourceEventSource.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ public class ControllerResourceEventSource<T extends HasMetadata>
2323
private final Controller<T> controller;
2424
private OnceWhitelistEventFilterEventFilter<T> onceWhitelistEventFilterEventFilter;
2525

26-
public ControllerResourceEventSource(Controller<T> controller) {
26+
public ControllerResourceEventSource(Controller<T> controller, EventSourceRegistry<T> registry) {
2727
super(controller.getConfiguration(),
2828
controller.getCRClient(),
29-
controller.getConfiguration().getConfigurationService().getResourceCloner());
29+
controller.getConfiguration().getConfigurationService().getResourceCloner(),
30+
registry);
3031
this.controller = controller;
3132
}
3233

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/InformerEventSource.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public InformerEventSource(SharedInformer<T> sharedInformer,
5454
"Informer is already running on event source creation, this is not desirable and may " +
5555
"lead to non deterministic behavior.");
5656
}
57-
this.cache = new InformerResourceCache<T>(sharedInformer, cloner);
57+
this.cache = new InformerResourceCache<>(sharedInformer, cloner);
5858

5959
this.associatedWith = Objects.requireNonNullElseGet(associatedWith,
6060
() -> (cr, registry) -> cache.get(ResourceID.fromResource(cr)).orElse(null));

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/InformerEventSourceEventSourceWrapper.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,12 @@ public InformerEventSourceEventSourceWrapper(
2222
FilterWatchListDeletable<T, KubernetesResourceList<T>> client, Cloner cloner,
2323
PrimaryResourcesRetriever<T, P> secondaryToPrimaryResourcesIdSet,
2424
AssociatedSecondaryRetriever<T, P> associatedWith,
25-
boolean skipUpdateEventPropagationIfNoChange) {
25+
boolean skipUpdateEventPropagationIfNoChange, EventSourceRegistry<P> registry) {
2626
final var informer = client.runnableInformer(0);
2727
source = new InformerEventSource<>(informer,
2828
secondaryToPrimaryResourcesIdSet,
2929
associatedWith, skipUpdateEventPropagationIfNoChange, cloner);
30+
registry.registerEventSource(source);
3031
this.cache = new InformerResourceCache<>(informer, cloner);
3132
}
3233

operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/ControllerResourceEventSourceTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ class ControllerResourceEventSourceTest {
3030
private static final MixedOperation<TestCustomResource, KubernetesResourceList<TestCustomResource>, Resource<TestCustomResource>> client =
3131
mock(MixedOperation.class);
3232
EventHandler eventHandler = mock(EventHandler.class);
33+
EventSourceRegistry registry = mock(EventSourceRegistry.class);
3334

3435
private ControllerResourceEventSource<TestCustomResource> controllerResourceEventSource =
35-
new ControllerResourceEventSource<>(new TestController(true));
36+
new ControllerResourceEventSource<>(new TestController(true), registry);
3637

3738
@BeforeEach
3839
public void setup() {
@@ -89,7 +90,7 @@ public void normalExecutionIfGenerationChanges() {
8990
@Test
9091
public void handlesAllEventIfNotGenerationAware() {
9192
controllerResourceEventSource =
92-
new ControllerResourceEventSource<>(new TestController(false));
93+
new ControllerResourceEventSource<>(new TestController(false), registry);
9394
setup();
9495

9596
TestCustomResource customResource1 = TestUtils.testCustomResource();

operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/ResourceEventFilterTest.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class ResourceEventFilterTest {
3030
public static final String FINALIZER = "finalizer";
3131

3232
private EventHandler eventHandler;
33+
private EventSourceRegistry registry = mock(EventSourceRegistry.class);
3334

3435
@BeforeEach
3536
public void before() {
@@ -46,7 +47,7 @@ public void eventFilteredByCustomPredicate() {
4647
newResource.getStatus().getConfigMapStatus()));
4748

4849
var controller = new TestController(config);
49-
var eventSource = new ControllerResourceEventSource<>(controller);
50+
var eventSource = new ControllerResourceEventSource<>(controller, registry);
5051
eventSource.setEventHandler(eventHandler);
5152

5253
TestCustomResource cr = TestUtils.testCustomResource();
@@ -74,7 +75,7 @@ public void eventFilteredByCustomPredicateAndGenerationAware() {
7475
newResource.getStatus().getConfigMapStatus()));
7576

7677
var controller = new TestController(config);
77-
var eventSource = new ControllerResourceEventSource<>(controller);
78+
var eventSource = new ControllerResourceEventSource<>(controller, registry);
7879
eventSource.setEventHandler(eventHandler);
7980

8081
TestCustomResource cr = TestUtils.testCustomResource();
@@ -104,7 +105,7 @@ public void observedGenerationFiltering() {
104105
.thenReturn(ConfigurationService.DEFAULT_CLONER);
105106

106107
var controller = new ObservedGenController(config);
107-
var eventSource = new ControllerResourceEventSource<>(controller);
108+
var eventSource = new ControllerResourceEventSource<>(controller, registry);
108109
eventSource.setEventHandler(eventHandler);
109110

110111
ObservedGenCustomResource cr = new ObservedGenCustomResource();
@@ -135,7 +136,7 @@ public void eventNotFilteredByCustomPredicateIfFinalizerIsRequired() {
135136
.thenReturn(ConfigurationService.DEFAULT_CLONER);
136137

137138
var controller = new TestController(config);
138-
var eventSource = new ControllerResourceEventSource<>(controller);
139+
var eventSource = new ControllerResourceEventSource<>(controller, registry);
139140
eventSource.setEventHandler(eventHandler);
140141

141142
TestCustomResource cr = TestUtils.testCustomResource();

sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/WebappReconciler.java

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.io.ByteArrayOutputStream;
44
import java.util.List;
55
import java.util.Objects;
6+
import java.util.Set;
67
import java.util.concurrent.CompletableFuture;
78
import java.util.concurrent.ExecutionException;
89
import java.util.concurrent.TimeUnit;
@@ -17,22 +18,23 @@
1718
import io.fabric8.kubernetes.client.KubernetesClient;
1819
import io.fabric8.kubernetes.client.dsl.ExecListener;
1920
import io.fabric8.kubernetes.client.dsl.ExecWatch;
20-
import io.javaoperatorsdk.operator.api.config.Cloner;
21-
import io.fabric8.kubernetes.client.informers.cache.Cache;
2221
import io.javaoperatorsdk.operator.api.reconciler.Context;
2322
import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
2423
import io.javaoperatorsdk.operator.api.reconciler.DeleteControl;
25-
import io.javaoperatorsdk.operator.api.reconciler.EventSourceInitializer;
2624
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
2725
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
26+
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResourceConfiguration;
2827
import io.javaoperatorsdk.operator.processing.event.ResourceID;
2928
import io.javaoperatorsdk.operator.processing.event.source.EventSourceRegistry;
30-
import io.javaoperatorsdk.operator.processing.event.source.InformerEventSource;
29+
import io.javaoperatorsdk.operator.processing.event.source.PrimaryResourcesRetriever;
30+
import io.javaoperatorsdk.operator.sample.WebappReconciler.WebappRetriever;
3131

3232
import okhttp3.Response;
3333

34-
@ControllerConfiguration
35-
public class WebappReconciler implements Reconciler<Webapp>, EventSourceInitializer<Webapp> {
34+
@ControllerConfiguration(
35+
dependents = @DependentResourceConfiguration(creatable = false, resourceType = Tomcat.class,
36+
associatedPrimariesRetriever = WebappRetriever.class))
37+
public class WebappReconciler implements Reconciler<Webapp> {
3638

3739
private KubernetesClient kubernetesClient;
3840

@@ -42,22 +44,19 @@ public WebappReconciler(KubernetesClient kubernetesClient) {
4244
this.kubernetesClient = kubernetesClient;
4345
}
4446

45-
private InformerEventSource<Tomcat> tomcatEventSource;
46-
47-
@Override
48-
public void prepareEventSources(EventSourceRegistry<Webapp> eventSourceRegistry, Cloner cloner) {
49-
tomcatEventSource =
50-
new InformerEventSource<>(kubernetesClient, Tomcat.class, (t, registry) -> {
51-
// To create an event to a related WebApp resource and trigger the reconciliation
52-
// we need to find which WebApp this Tomcat custom resource is related to.
53-
// To find the related customResourceId of the WebApp resource we traverse the cache to
54-
// and identify it based on naming convention.
55-
return eventSourceRegistry.getControllerResourceEventSource().getResourceCache()
56-
.list(webApp -> webApp.getSpec().getTomcat().equals(t.getMetadata().getName()))
57-
.map(ResourceID::fromResource)
58-
.collect(Collectors.toSet());
59-
}, cloner);
60-
eventSourceRegistry.registerEventSource(tomcatEventSource);
47+
public static class WebappRetriever implements PrimaryResourcesRetriever<Tomcat, Webapp> {
48+
@Override
49+
public Set<ResourceID> associatedPrimaryResources(Tomcat t,
50+
EventSourceRegistry<Webapp> registry) {
51+
// To create an event to a related WebApp resource and trigger the reconciliation
52+
// we need to find which WebApp this Tomcat custom resource is related to.
53+
// To find the related customResourceId of the WebApp resource we traverse the cache to
54+
// and identify it based on naming convention.
55+
return registry.getControllerResourceEventSource().getResourceCache()
56+
.list(webApp -> webApp.getSpec().getTomcat().equals(t.getMetadata().getName()))
57+
.map(ResourceID::fromResource)
58+
.collect(Collectors.toSet());
59+
}
6160
}
6261

6362
/**
@@ -71,9 +70,9 @@ public UpdateControl<Webapp> reconcile(Webapp webapp, Context context) {
7170
return UpdateControl.noUpdate();
7271
}
7372

74-
Tomcat tomcat = tomcatEventSource.getStore()
75-
.getByKey(Cache.namespaceKeyFunc(webapp.getMetadata().getNamespace(),
76-
webapp.getSpec().getTomcat()));
73+
var tomcatClient = kubernetesClient.customResources(Tomcat.class);
74+
Tomcat tomcat = tomcatClient.inNamespace(webapp.getMetadata().getNamespace())
75+
.withName(webapp.getSpec().getTomcat()).get();
7776
if (tomcat == null) {
7877
throw new IllegalStateException("Cannot find Tomcat " + webapp.getSpec().getTomcat()
7978
+ " for Webapp " + webapp.getMetadata().getName() + " in namespace "

0 commit comments

Comments
 (0)