Skip to content

Commit 7b2189f

Browse files
authored
feat: remove feature of filter event with observed generation (#902)
1 parent 14403fb commit 7b2189f

File tree

4 files changed

+14
-78
lines changed

4 files changed

+14
-78
lines changed

docs/documentation/features.md

+13-15
Original file line numberDiff line numberDiff line change
@@ -137,17 +137,13 @@ mostly for the cases when there is a long waiting period after a delete operatio
137137
you might want to either schedule a timed event to make sure
138138
`cleanup` is executed again or use event sources to get notified about the state changes of a deleted resource.
139139

140-
## Generation Awareness and Automatic Observed Generation Handling
140+
## Automatic Observed Generation Handling
141141

142142
Having `.observedGeneration` value on the status of the resource is a best practice to indicate the last generation of
143143
the resource reconciled successfully by the controller. This helps the users / administrators to check if the custom
144-
resource was reconciled, but it is used to decide if a reconciliation should happen or not. Filtering events based on
145-
generation is supported by the framework and turned on by default. There are two modes.
144+
resource was reconciled.
146145

147-
### Primary (preferred) Mode
148-
149-
The first and the **preferred** one is to check after a resource event received, if the generation of the resource is
150-
larger than the `.observedGeneration` field on status. In order to have this feature working:
146+
In order to have this feature working:
151147

152148
- the **status class** (not the resource) must implement the
153149
[`ObservedGenerationAware`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/ObservedGenerationAware.java)
@@ -189,16 +185,18 @@ public class WebPage extends CustomResource<WebPageSpec, WebPageStatus>
189185
}
190186
```
191187

192-
### The Second (Fallback) Mode
188+
## Generation Awareness and Event Filtering
189+
190+
On an operator startup, the best practice is to reconcile all the resources. Since while operator was down, changes
191+
might have made both to custom resource and dependent resources.
193192

194-
The second, fallback mode is (when the conditions from above are not met to handle the observed generation automatically
195-
in status) to handle generation filtering in memory. Thus, if an event is received, the generation of the received
196-
resource is compared with the resource in the cache.
193+
When the first reconciliation is done successfully, the next reconciliation is triggered if either the dependent
194+
resources are changed or the custom resource `.spec` is changed. If other fields like `.metadata` is changed on the
195+
custom resource, the reconciliation could be skipped. This is supported out of the box, thus the reconciliation by
196+
default is not triggered if the change to the main custom resource does not increase the `.metadata.generation` field.
197+
Note that the increase of `.metada.generation` is handled automatically by Kubernetes.
197198

198-
Note that the **first approach has significant benefits** in the situation when the operator is restarted and there is
199-
no cached resource anymore. In case two this leads to a reconciliation of every resource in all cases,
200-
event if the resource is not changed while the operator was not running. However, in case informers are used
201-
the reconciliation from startup will happen anyway, since events will be propagated by the informer.
199+
To turn on this feature set `generationAwareEventProcessing` to `false` for the `Reconciler`.
202200

203201
## Support for Well Known (non-custom) Kubernetes Resources
204202

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

+1-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66

77
/**
88
* If the custom resource's status implements this interface, the observed generation will be
9-
* automatically handled. The last observed generation will be updated on status. In addition to
10-
* that, controller configuration will be checked if is set to be generation aware. If generation
11-
* aware config is turned off, this interface is ignored.
9+
* automatically handled. The last observed generation will be updated on status.
1210
* <p>
1311
* In order for this automatic handling to work the status object returned by
1412
* {@link CustomResource#getStatus()} should not be null.

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

-12
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package io.javaoperatorsdk.operator.processing.event.source.controller;
22

33
import io.fabric8.kubernetes.api.model.HasMetadata;
4-
import io.fabric8.kubernetes.client.CustomResource;
5-
import io.javaoperatorsdk.operator.api.ObservedGenerationAware;
64

75
/**
86
* Convenience implementations of, and utility methods for, {@link ResourceEventFilter}.
@@ -25,16 +23,6 @@ public final class ResourceEventFilters {
2523
private static final ResourceEventFilter<HasMetadata> GENERATION_AWARE =
2624
(configuration, oldResource, newResource) -> {
2725
final var generationAware = configuration.isGenerationAware();
28-
if (newResource instanceof CustomResource<?, ?>) {
29-
var newCustomResource = (CustomResource<?, ?>) newResource;
30-
final var status = newCustomResource.getStatus();
31-
if (generationAware && status instanceof ObservedGenerationAware) {
32-
var actualGeneration = newResource.getMetadata().getGeneration();
33-
var observedGeneration = ((ObservedGenerationAware) status)
34-
.getObservedGeneration();
35-
return observedGeneration == null || actualGeneration > observedGeneration;
36-
}
37-
}
3826
return oldResource == null || !generationAware ||
3927
oldResource.getMetadata().getGeneration() < newResource.getMetadata().getGeneration();
4028
};

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

-48
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
import io.fabric8.kubernetes.api.model.HasMetadata;
1010
import io.fabric8.kubernetes.api.model.KubernetesResourceList;
11-
import io.fabric8.kubernetes.api.model.ObjectMeta;
1211
import io.fabric8.kubernetes.client.dsl.MixedOperation;
1312
import io.fabric8.kubernetes.client.dsl.Resource;
1413
import io.javaoperatorsdk.operator.TestUtils;
@@ -20,7 +19,6 @@
2019
import io.javaoperatorsdk.operator.processing.event.source.controller.ControllerResourceEventSource;
2120
import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceAction;
2221
import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter;
23-
import io.javaoperatorsdk.operator.sample.observedgeneration.ObservedGenCustomResource;
2422
import io.javaoperatorsdk.operator.sample.simple.TestCustomResource;
2523

2624
import static org.mockito.Mockito.any;
@@ -101,27 +99,6 @@ public void eventFilteredByCustomPredicateAndGenerationAware() {
10199
verify(eventHandler, times(1)).handleEvent(any());
102100
}
103101

104-
@Test
105-
public void observedGenerationFiltering() {
106-
var config = new ObservedGenControllerConfig(FINALIZER, true, null);
107-
108-
var eventSource = init(new ObservedGenController(config));
109-
110-
ObservedGenCustomResource cr = new ObservedGenCustomResource();
111-
cr.setMetadata(new ObjectMeta());
112-
cr.getMetadata().setFinalizers(List.of(FINALIZER));
113-
cr.getMetadata().setGeneration(5L);
114-
cr.getStatus().setObservedGeneration(5L);
115-
116-
eventSource.eventReceived(ResourceAction.UPDATED, cr, null);
117-
verify(eventHandler, times(0)).handleEvent(any());
118-
119-
cr.getMetadata().setGeneration(6L);
120-
121-
eventSource.eventReceived(ResourceAction.UPDATED, cr, null);
122-
verify(eventHandler, times(1)).handleEvent(any());
123-
}
124-
125102
@Test
126103
public void eventAlwaysFilteredByCustomPredicate() {
127104
var config = new TestControllerConfig(
@@ -147,13 +124,6 @@ public TestControllerConfig(String finalizer, boolean generationAware,
147124
super(finalizer, generationAware, eventFilter, TestCustomResource.class);
148125
}
149126
}
150-
private static class ObservedGenControllerConfig
151-
extends ControllerConfig<ObservedGenCustomResource> {
152-
public ObservedGenControllerConfig(String finalizer, boolean generationAware,
153-
ResourceEventFilter<ObservedGenCustomResource> eventFilter) {
154-
super(finalizer, generationAware, eventFilter, ObservedGenCustomResource.class);
155-
}
156-
}
157127

158128
private static class ControllerConfig<T extends HasMetadata> extends
159129
DefaultControllerConfiguration<T> {
@@ -192,22 +162,4 @@ public MixedOperation<TestCustomResource, KubernetesResourceList<TestCustomResou
192162
}
193163
}
194164

195-
private static class ObservedGenController
196-
extends Controller<ObservedGenCustomResource> {
197-
198-
public ObservedGenController(
199-
ControllerConfiguration<ObservedGenCustomResource> configuration) {
200-
super(null, configuration, null);
201-
}
202-
203-
@Override
204-
public EventSourceManager<ObservedGenCustomResource> getEventSourceManager() {
205-
return mock(EventSourceManager.class);
206-
}
207-
208-
@Override
209-
public MixedOperation<ObservedGenCustomResource, KubernetesResourceList<ObservedGenCustomResource>, Resource<ObservedGenCustomResource>> getCRClient() {
210-
return mock(MixedOperation.class);
211-
}
212-
}
213165
}

0 commit comments

Comments
 (0)