Skip to content

Commit 5150d9e

Browse files
csvirimetacosm
andcommitted
feat: remove automatic observed generation handling (#2382)
Signed-off-by: Attila Mészáros <csviri@gmail.com> Signed-off-by: Chris Laprun <claprun@redhat.com> Co-authored-by: Chris Laprun <claprun@redhat.com> Signed-off-by: Attila Mészáros <csviri@gmail.com>
1 parent fbc2601 commit 5150d9e

File tree

25 files changed

+163
-249
lines changed

25 files changed

+163
-249
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ It makes it easy to implement best practices and patterns for an Operator. Featu
4040
* Handling dependent resources, related events, and caching.
4141
* Automatic Retries
4242
* Smart event scheduling
43-
* Handling Observed Generations automatically
4443
* Easy to use Error Handling
4544
* ... and everything that a batteries included framework needs
4645

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package {{groupId}};
22

3-
import io.javaoperatorsdk.operator.api.ObservedGenerationAwareStatus;
4-
5-
public class {{artifactClassId}}Status extends ObservedGenerationAwareStatus {
3+
public class {{artifactClassId}}Status {
64

75
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
package io.javaoperatorsdk.operator.processing.event.source.cache.sample.namespacescope;
22

3-
import io.javaoperatorsdk.operator.api.ObservedGenerationAwareStatus;
4-
5-
public class BoundedCacheTestStatus extends ObservedGenerationAwareStatus {
3+
public class BoundedCacheTestStatus {
64
}

docs/documentation/v5-0-migration.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,6 @@ permalink: /docs/v5-0-migration
4444
where it is demonstrated. Also, the related part of
4545
a [workaround](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/StatusPatchSSAMigrationIT.java#L110-L116).
4646

47-
Related automatic observed generation handling changes:
48-
Automated Observed Generation (see features in docs), is automatically handled for non-SSA, even if
49-
the status sub-resource is not instructed to be updated. This is not true for SSA, observed generation is updated
50-
only when patch status is instructed by `UpdateControl`.
51-
5247
6. `ManagedDependentResourceContext` has been renamed to `ManagedWorkflowAndDependentResourceContext` and is accessed
5348
via the accordingly renamed `managedWorkflowAndDependentResourceContext` method.
5449
7. `ResourceDiscriminator` was removed. In most of the cases you can just delete the discriminator, everything should
@@ -57,3 +52,9 @@ permalink: /docs/v5-0-migration
5752
8. `ConfigurationService.getTerminationTimeoutSeconds` and associated overriding mechanism have been removed,
5853
use `Operator.stop(Duration)` instead.
5954
9. `Operator.installShutdownHook()` has been removed, use `Operator.installShutdownHook(Duration)` instead
55+
10. Automated observed generation handling feature was removed (`ObservedGenerationAware` interface
56+
and `ObservedGenerationAwareStatus` class were deleted). Manually handling observed generation is fairly easy to do
57+
in your reconciler, however, it cannot be done automatically when using SSA. We therefore removed the feature since
58+
it would have been confusing to have a different behavior for SSA and non-SSA cases. For an example of how to do
59+
observed generation handling manually in your reconciler, see
60+
[this sample](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationReconciler.java).

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

Lines changed: 0 additions & 29 deletions
This file was deleted.

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

Lines changed: 0 additions & 19 deletions
This file was deleted.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ default boolean parseResourceVersionsForEventFilteringAndCaching() {
395395
/**
396396
* {@link io.javaoperatorsdk.operator.api.reconciler.UpdateControl} patch resource or status can
397397
* either use simple patches or SSA. Setting this to {@code true}, controllers will use SSA for
398-
* adding finalizers, managing observed generation, patching resources and status.
398+
* adding finalizers, patching resources and status.
399399
*
400400
* @return {@code true} if Server-Side Apply (SSA) should be used when patching the primary
401401
* resources, {@code false} otherwise

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

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,12 @@
1010
import io.fabric8.kubernetes.api.model.KubernetesResourceList;
1111
import io.fabric8.kubernetes.api.model.Namespaced;
1212
import io.fabric8.kubernetes.api.model.ObjectMeta;
13-
import io.fabric8.kubernetes.client.CustomResource;
1413
import io.fabric8.kubernetes.client.KubernetesClientException;
1514
import io.fabric8.kubernetes.client.dsl.MixedOperation;
1615
import io.fabric8.kubernetes.client.dsl.Resource;
1716
import io.fabric8.kubernetes.client.dsl.base.PatchContext;
1817
import io.fabric8.kubernetes.client.dsl.base.PatchType;
1918
import io.javaoperatorsdk.operator.OperatorException;
20-
import io.javaoperatorsdk.operator.api.ObservedGenerationAware;
2119
import io.javaoperatorsdk.operator.api.config.Cloner;
2220
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
2321
import io.javaoperatorsdk.operator.api.reconciler.BaseControl;
@@ -166,13 +164,8 @@ private PostExecutionControl<P> reconcileExecution(ExecutionScope<P> executionSc
166164
}
167165
}
168166

169-
// check if status also needs to be updated
170-
final var updateObservedGeneration = updateControl.isNoUpdate()
171-
? shouldUpdateObservedGenerationAutomatically(resourceForExecution)
172-
: shouldUpdateObservedGenerationAutomatically(updatedCustomResource);
173-
// if using SSA the observed generation is updated only if user instructs patching the status
174-
if (updateControl.isPatchStatus() || (updateObservedGeneration && !useSSA)) {
175-
updatedCustomResource = patchStatusGenerationAware(toUpdate, originalResource);
167+
if (updateControl.isPatchStatus()) {
168+
customResourceFacade.patchStatus(toUpdate, originalResource);
176169
}
177170
return createPostExecutionControl(updatedCustomResource, updateControl);
178171
}
@@ -202,9 +195,8 @@ public boolean isLastAttempt() {
202195

203196
P updatedResource = null;
204197
if (errorStatusUpdateControl.getResource().isPresent()) {
205-
updatedResource =
206-
patchStatusGenerationAware(errorStatusUpdateControl.getResource().orElseThrow(),
207-
originalResource);
198+
updatedResource = customResourceFacade
199+
.patchStatus(errorStatusUpdateControl.getResource().orElseThrow(), originalResource);
208200
}
209201
if (errorStatusUpdateControl.isNoRetry()) {
210202
PostExecutionControl<P> postExecutionControl;
@@ -230,38 +222,9 @@ private boolean isErrorStatusHandlerPresent() {
230222
}
231223

232224
private P patchStatusGenerationAware(P resource, P originalResource) {
233-
updateStatusObservedGenerationIfRequired(resource);
234225
return customResourceFacade.patchStatus(resource, originalResource);
235226
}
236227

237-
@SuppressWarnings("rawtypes")
238-
private boolean shouldUpdateObservedGenerationAutomatically(P resource) {
239-
if (configuration().isGenerationAware() && resource instanceof CustomResource<?, ?>) {
240-
var customResource = (CustomResource) resource;
241-
var status = customResource.getStatus();
242-
// Note that if status is null we won't update the observed generation.
243-
if (status instanceof ObservedGenerationAware) {
244-
var observedGen = ((ObservedGenerationAware) status).getObservedGeneration();
245-
var currentGen = resource.getMetadata().getGeneration();
246-
return !currentGen.equals(observedGen);
247-
}
248-
}
249-
return false;
250-
}
251-
252-
@SuppressWarnings("rawtypes")
253-
private void updateStatusObservedGenerationIfRequired(P resource) {
254-
if (configuration().isGenerationAware() && resource instanceof CustomResource<?, ?>) {
255-
var customResource = (CustomResource) resource;
256-
var status = customResource.getStatus();
257-
// Note that if status is null we won't update the observed generation.
258-
if (status instanceof ObservedGenerationAware) {
259-
((ObservedGenerationAware) status)
260-
.setObservedGeneration(resource.getMetadata().getGeneration());
261-
}
262-
}
263-
}
264-
265228
private PostExecutionControl<P> createPostExecutionControl(P updatedCustomResource,
266229
UpdateControl<P> updateControl) {
267230
PostExecutionControl<P> postExecutionControl;

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

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -435,29 +435,6 @@ void reScheduleOnDeleteWithoutFinalizerRemoval() {
435435
.isEqualTo(1000L);
436436
}
437437

438-
@Test
439-
void setObservedGenerationForStatusIfNeeded() throws Exception {
440-
var observedGenResource = createObservedGenCustomResource();
441-
442-
Reconciler<ObservedGenCustomResource> reconciler = mock(Reconciler.class);
443-
ControllerConfiguration<ObservedGenCustomResource> config =
444-
MockControllerConfiguration.forResource(ObservedGenCustomResource.class);
445-
CustomResourceFacade<ObservedGenCustomResource> facade = mock(CustomResourceFacade.class);
446-
var dispatcher = init(observedGenResource, reconciler, config, facade, true);
447-
448-
when(config.isGenerationAware()).thenReturn(true);
449-
450-
when(reconciler.reconcile(any(), any()))
451-
.thenReturn(UpdateControl.patchStatus(observedGenResource));
452-
when(facade.patchStatus(eq(observedGenResource), any())).thenReturn(observedGenResource);
453-
454-
PostExecutionControl<ObservedGenCustomResource> control = dispatcher.handleExecution(
455-
executionScopeWithCREvent(observedGenResource));
456-
assertThat(control.getUpdatedCustomResource().orElseGet(() -> fail("Missing optional"))
457-
.getStatus().getObservedGeneration())
458-
.isEqualTo(1L);
459-
}
460-
461438
@Test
462439
void doesNotUpdatesObservedGenerationIfStatusIsNotPatchedWhenUsingSSA() throws Exception {
463440
var observedGenResource = createObservedGenCustomResource();
@@ -476,28 +453,6 @@ void doesNotUpdatesObservedGenerationIfStatusIsNotPatchedWhenUsingSSA() throws E
476453
assertThat(control.getUpdatedCustomResource()).isEmpty();
477454
}
478455

479-
@Test
480-
void patchObservedGenerationOnCustomResourcePatchIfNoSSA() throws Exception {
481-
var observedGenResource = createObservedGenCustomResource();
482-
483-
Reconciler<ObservedGenCustomResource> reconciler = mock(Reconciler.class);
484-
final var config = MockControllerConfiguration.forResource(ObservedGenCustomResource.class);
485-
CustomResourceFacade<ObservedGenCustomResource> facade = mock(CustomResourceFacade.class);
486-
when(config.isGenerationAware()).thenReturn(true);
487-
when(reconciler.reconcile(any(), any()))
488-
.thenReturn(UpdateControl.patchResource(observedGenResource));
489-
when(facade.patchResource(any(), any())).thenReturn(observedGenResource);
490-
when(facade.patchStatus(eq(observedGenResource), any())).thenReturn(observedGenResource);
491-
initConfigService(false);
492-
var dispatcher = init(observedGenResource, reconciler, config, facade, true);
493-
494-
PostExecutionControl<ObservedGenCustomResource> control = dispatcher.handleExecution(
495-
executionScopeWithCREvent(observedGenResource));
496-
assertThat(control.getUpdatedCustomResource().orElseGet(() -> fail("Missing optional"))
497-
.getStatus().getObservedGeneration())
498-
.isEqualTo(1L);
499-
}
500-
501456
@Test
502457
void doesNotPatchObservedGenerationOnCustomResourcePatch() throws Exception {
503458
var observedGenResource = createObservedGenCustomResource();
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package io.javaoperatorsdk.operator.sample.observedgeneration;
22

3-
import io.javaoperatorsdk.operator.api.ObservedGenerationAwareStatus;
4-
5-
public class ObservedGenStatus extends ObservedGenerationAwareStatus {
3+
public class ObservedGenStatus {
64

75
}

0 commit comments

Comments
 (0)