From 6ab197941492094ad676f2e9ce33cec1c82ae402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Tue, 14 May 2024 10:11:18 +0200 Subject: [PATCH 1/7] feat: remove automatic observed generation handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- .../src/main/resources/templates/Status.java | 4 +- .../BoundedCacheTestStatus.java | 4 +- .../operator/api/ObservedGenerationAware.java | 29 ------------ .../api/ObservedGenerationAwareStatus.java | 19 -------- .../event/ReconciliationDispatcher.java | 46 +++---------------- .../event/ReconciliationDispatcherTest.java | 45 ------------------ .../observedgeneration/ObservedGenStatus.java | 4 +- .../ObservedGenerationHandlingIT.java | 37 --------------- ...teEventFilterTestCustomResourceStatus.java | 4 +- .../GracefulStopTestCustomResourceStatus.java | 11 ++++- .../GracefulStopTestReconciler.java | 1 + .../ObservedGenerationTestCustomResource.java | 18 -------- ...vedGenerationTestCustomResourceStatus.java | 7 --- .../ObservedGenerationTestReconciler.java | 28 ----------- .../RateLimitCustomResourceStatus.java | 4 +- .../operator/sample/SchemaStatus.java | 4 +- .../sample/customresource/WebPageStatus.java | 4 +- 17 files changed, 23 insertions(+), 246 deletions(-) delete mode 100644 operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/ObservedGenerationAware.java delete mode 100644 operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/ObservedGenerationAwareStatus.java delete mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/ObservedGenerationHandlingIT.java delete mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenerationTestCustomResource.java delete mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenerationTestCustomResourceStatus.java delete mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenerationTestReconciler.java diff --git a/bootstrapper-maven-plugin/src/main/resources/templates/Status.java b/bootstrapper-maven-plugin/src/main/resources/templates/Status.java index 4c37b99947..52bd0fd4d2 100644 --- a/bootstrapper-maven-plugin/src/main/resources/templates/Status.java +++ b/bootstrapper-maven-plugin/src/main/resources/templates/Status.java @@ -1,7 +1,5 @@ package {{groupId}}; -import io.javaoperatorsdk.operator.api.ObservedGenerationAwareStatus; - -public class {{artifactClassId}}Status extends ObservedGenerationAwareStatus { +public class {{artifactClassId}}Status { } diff --git a/caffeine-bounded-cache-support/src/test/java/io/javaoperatorsdk/operator/processing/event/source/cache/sample/namespacescope/BoundedCacheTestStatus.java b/caffeine-bounded-cache-support/src/test/java/io/javaoperatorsdk/operator/processing/event/source/cache/sample/namespacescope/BoundedCacheTestStatus.java index 03a311529e..2bdd434d23 100644 --- a/caffeine-bounded-cache-support/src/test/java/io/javaoperatorsdk/operator/processing/event/source/cache/sample/namespacescope/BoundedCacheTestStatus.java +++ b/caffeine-bounded-cache-support/src/test/java/io/javaoperatorsdk/operator/processing/event/source/cache/sample/namespacescope/BoundedCacheTestStatus.java @@ -1,6 +1,4 @@ package io.javaoperatorsdk.operator.processing.event.source.cache.sample.namespacescope; -import io.javaoperatorsdk.operator.api.ObservedGenerationAwareStatus; - -public class BoundedCacheTestStatus extends ObservedGenerationAwareStatus { +public class BoundedCacheTestStatus { } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/ObservedGenerationAware.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/ObservedGenerationAware.java deleted file mode 100644 index eafe51e6f4..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/ObservedGenerationAware.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.javaoperatorsdk.operator.api; - -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.client.CustomResource; -import io.javaoperatorsdk.operator.api.config.ConfigurationService; -import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; - -/** - * If the custom resource's status implements this interface, the observed generation will be - * automatically handled. The last observed generation will be updated on status. - *

- * In order for this automatic handling to work the status object returned by - * {@link CustomResource#getStatus()} should not be null. - *

- * The observed generation is updated with SSA mode only if - * {@link UpdateControl#patchStatus(HasMetadata)} or - * {@link UpdateControl#patchResourceAndStatus(HasMetadata)} is called. In non-SSA mode (see - * {@link ConfigurationService#useSSAToPatchPrimaryResource()}) observed generation is update even - * if patch is not called. - * - * @see ObservedGenerationAwareStatus - */ -public interface ObservedGenerationAware { - - void setObservedGeneration(Long generation); - - Long getObservedGeneration(); - -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/ObservedGenerationAwareStatus.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/ObservedGenerationAwareStatus.java deleted file mode 100644 index d2048c9513..0000000000 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/ObservedGenerationAwareStatus.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.javaoperatorsdk.operator.api; - -/** - * A helper base class for status sub-resources classes to extend to support generate awareness. - */ -public class ObservedGenerationAwareStatus implements ObservedGenerationAware { - - private Long observedGeneration; - - @Override - public void setObservedGeneration(Long generation) { - this.observedGeneration = generation; - } - - @Override - public Long getObservedGeneration() { - return observedGeneration; - } -} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java index 531917adac..3e9ac9aaba 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java @@ -10,14 +10,12 @@ import io.fabric8.kubernetes.api.model.KubernetesResourceList; import io.fabric8.kubernetes.api.model.Namespaced; import io.fabric8.kubernetes.api.model.ObjectMeta; -import io.fabric8.kubernetes.client.CustomResource; import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.dsl.MixedOperation; import io.fabric8.kubernetes.client.dsl.Resource; import io.fabric8.kubernetes.client.dsl.base.PatchContext; import io.fabric8.kubernetes.client.dsl.base.PatchType; import io.javaoperatorsdk.operator.OperatorException; -import io.javaoperatorsdk.operator.api.ObservedGenerationAware; import io.javaoperatorsdk.operator.api.config.Cloner; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.BaseControl; @@ -170,13 +168,11 @@ private PostExecutionControl

reconcileExecution(ExecutionScope

executionSc } } - // check if status also needs to be updated - final var updateObservedGeneration = updateControl.isNoUpdate() - ? shouldUpdateObservedGenerationAutomatically(resourceForExecution) - : shouldUpdateObservedGenerationAutomatically(updatedCustomResource); + + // if using SSA the observed generation is updated only if user instructs patching the status - if (updateControl.isPatchStatus() || (updateObservedGeneration && !useSSA)) { - updatedCustomResource = patchStatusGenerationAware(toUpdate, originalResource); + if (updateControl.isPatchStatus()) { + customResourceFacade.patchStatus(toUpdate, originalResource); } return createPostExecutionControl(updatedCustomResource, updateControl); } @@ -206,9 +202,8 @@ public boolean isLastAttempt() { P updatedResource = null; if (errorStatusUpdateControl.getResource().isPresent()) { - updatedResource = - patchStatusGenerationAware(errorStatusUpdateControl.getResource().orElseThrow(), - originalResource); + updatedResource = customResourceFacade + .patchStatus(errorStatusUpdateControl.getResource().orElseThrow(), originalResource); } if (errorStatusUpdateControl.isNoRetry()) { PostExecutionControl

postExecutionControl; @@ -234,38 +229,9 @@ private boolean isErrorStatusHandlerPresent() { } private P patchStatusGenerationAware(P resource, P originalResource) { - updateStatusObservedGenerationIfRequired(resource); return customResourceFacade.patchStatus(resource, originalResource); } - @SuppressWarnings("rawtypes") - private boolean shouldUpdateObservedGenerationAutomatically(P resource) { - if (configuration().isGenerationAware() && resource instanceof CustomResource) { - var customResource = (CustomResource) resource; - var status = customResource.getStatus(); - // Note that if status is null we won't update the observed generation. - if (status instanceof ObservedGenerationAware) { - var observedGen = ((ObservedGenerationAware) status).getObservedGeneration(); - var currentGen = resource.getMetadata().getGeneration(); - return !currentGen.equals(observedGen); - } - } - return false; - } - - @SuppressWarnings("rawtypes") - private void updateStatusObservedGenerationIfRequired(P resource) { - if (configuration().isGenerationAware() && resource instanceof CustomResource) { - var customResource = (CustomResource) resource; - var status = customResource.getStatus(); - // Note that if status is null we won't update the observed generation. - if (status instanceof ObservedGenerationAware) { - ((ObservedGenerationAware) status) - .setObservedGeneration(resource.getMetadata().getGeneration()); - } - } - } - private PostExecutionControl

createPostExecutionControl(P updatedCustomResource, UpdateControl

updateControl) { PostExecutionControl

postExecutionControl; diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcherTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcherTest.java index bf4e5a8f27..7e80f4aedc 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcherTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcherTest.java @@ -435,29 +435,6 @@ void reScheduleOnDeleteWithoutFinalizerRemoval() { .isEqualTo(1000L); } - @Test - void setObservedGenerationForStatusIfNeeded() throws Exception { - var observedGenResource = createObservedGenCustomResource(); - - Reconciler reconciler = mock(Reconciler.class); - ControllerConfiguration config = - MockControllerConfiguration.forResource(ObservedGenCustomResource.class); - CustomResourceFacade facade = mock(CustomResourceFacade.class); - var dispatcher = init(observedGenResource, reconciler, config, facade, true); - - when(config.isGenerationAware()).thenReturn(true); - - when(reconciler.reconcile(any(), any())) - .thenReturn(UpdateControl.patchStatus(observedGenResource)); - when(facade.patchStatus(eq(observedGenResource), any())).thenReturn(observedGenResource); - - PostExecutionControl control = dispatcher.handleExecution( - executionScopeWithCREvent(observedGenResource)); - assertThat(control.getUpdatedCustomResource().orElseGet(() -> fail("Missing optional")) - .getStatus().getObservedGeneration()) - .isEqualTo(1L); - } - @Test void doesNotUpdatesObservedGenerationIfStatusIsNotPatchedWhenUsingSSA() throws Exception { var observedGenResource = createObservedGenCustomResource(); @@ -476,28 +453,6 @@ void doesNotUpdatesObservedGenerationIfStatusIsNotPatchedWhenUsingSSA() throws E assertThat(control.getUpdatedCustomResource()).isEmpty(); } - @Test - void patchObservedGenerationOnCustomResourcePatchIfNoSSA() throws Exception { - var observedGenResource = createObservedGenCustomResource(); - - Reconciler reconciler = mock(Reconciler.class); - final var config = MockControllerConfiguration.forResource(ObservedGenCustomResource.class); - CustomResourceFacade facade = mock(CustomResourceFacade.class); - when(config.isGenerationAware()).thenReturn(true); - when(reconciler.reconcile(any(), any())) - .thenReturn(UpdateControl.patchResource(observedGenResource)); - when(facade.patchResource(any(), any())).thenReturn(observedGenResource); - when(facade.patchStatus(eq(observedGenResource), any())).thenReturn(observedGenResource); - initConfigService(false); - var dispatcher = init(observedGenResource, reconciler, config, facade, true); - - PostExecutionControl control = dispatcher.handleExecution( - executionScopeWithCREvent(observedGenResource)); - assertThat(control.getUpdatedCustomResource().orElseGet(() -> fail("Missing optional")) - .getStatus().getObservedGeneration()) - .isEqualTo(1L); - } - @Test void doesNotPatchObservedGenerationOnCustomResourcePatch() throws Exception { var observedGenResource = createObservedGenCustomResource(); diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenStatus.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenStatus.java index d4ffee5416..81ce9a435d 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenStatus.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenStatus.java @@ -1,7 +1,5 @@ package io.javaoperatorsdk.operator.sample.observedgeneration; -import io.javaoperatorsdk.operator.api.ObservedGenerationAwareStatus; - -public class ObservedGenStatus extends ObservedGenerationAwareStatus { +public class ObservedGenStatus { } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/ObservedGenerationHandlingIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/ObservedGenerationHandlingIT.java deleted file mode 100644 index 0e28ddec4c..0000000000 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/ObservedGenerationHandlingIT.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.javaoperatorsdk.operator; - -import java.util.concurrent.TimeUnit; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.fabric8.kubernetes.api.model.ObjectMeta; -import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension; -import io.javaoperatorsdk.operator.sample.observedgeneration.ObservedGenerationTestCustomResource; -import io.javaoperatorsdk.operator.sample.observedgeneration.ObservedGenerationTestReconciler; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; - -class ObservedGenerationHandlingIT { - @RegisterExtension - LocallyRunOperatorExtension operator = - LocallyRunOperatorExtension.builder().withReconciler(new ObservedGenerationTestReconciler()) - .build(); - - @Test - void testReconciliationOfNonCustomResourceAndStatusUpdate() { - var resource = new ObservedGenerationTestCustomResource(); - resource.setMetadata(new ObjectMeta()); - resource.getMetadata().setName("observed-gen1"); - - var createdResource = operator.create(resource); - - await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { - var d = operator.get(ObservedGenerationTestCustomResource.class, - createdResource.getMetadata().getName()); - assertThat(d.getStatus().getObservedGeneration()).isNotNull(); - assertThat(d.getStatus().getObservedGeneration()).isEqualTo(1); - }); - } -} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/createupdateeventfilter/CreateUpdateEventFilterTestCustomResourceStatus.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/createupdateeventfilter/CreateUpdateEventFilterTestCustomResourceStatus.java index 6733e1a7cd..e8f8da78f4 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/createupdateeventfilter/CreateUpdateEventFilterTestCustomResourceStatus.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/createupdateeventfilter/CreateUpdateEventFilterTestCustomResourceStatus.java @@ -1,7 +1,5 @@ package io.javaoperatorsdk.operator.sample.createupdateeventfilter; -import io.javaoperatorsdk.operator.api.ObservedGenerationAwareStatus; - -public class CreateUpdateEventFilterTestCustomResourceStatus extends ObservedGenerationAwareStatus { +public class CreateUpdateEventFilterTestCustomResourceStatus { } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/gracefulstop/GracefulStopTestCustomResourceStatus.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/gracefulstop/GracefulStopTestCustomResourceStatus.java index f59f5b1163..fa80e79c19 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/gracefulstop/GracefulStopTestCustomResourceStatus.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/gracefulstop/GracefulStopTestCustomResourceStatus.java @@ -1,7 +1,14 @@ package io.javaoperatorsdk.operator.sample.gracefulstop; -import io.javaoperatorsdk.operator.api.ObservedGenerationAwareStatus; +public class GracefulStopTestCustomResourceStatus { -public class GracefulStopTestCustomResourceStatus extends ObservedGenerationAwareStatus { + private long observedGeneration; + public long getObservedGeneration() { + return observedGeneration; + } + + public void setObservedGeneration(long observedGeneration) { + this.observedGeneration = observedGeneration; + } } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/gracefulstop/GracefulStopTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/gracefulstop/GracefulStopTestReconciler.java index cf266c0b48..7ff0d9d246 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/gracefulstop/GracefulStopTestReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/gracefulstop/GracefulStopTestReconciler.java @@ -22,6 +22,7 @@ public UpdateControl reconcile( numberOfExecutions.addAndGet(1); resource.setStatus(new GracefulStopTestCustomResourceStatus()); + resource.getStatus().setObservedGeneration(resource.getMetadata().getGeneration()); Thread.sleep(RECONCILER_SLEEP); return UpdateControl.patchStatus(resource); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenerationTestCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenerationTestCustomResource.java deleted file mode 100644 index 8a0ede3a5d..0000000000 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenerationTestCustomResource.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.javaoperatorsdk.operator.sample.observedgeneration; - -import io.fabric8.kubernetes.api.model.Namespaced; -import io.fabric8.kubernetes.client.CustomResource; -import io.fabric8.kubernetes.model.annotation.Group; -import io.fabric8.kubernetes.model.annotation.Kind; -import io.fabric8.kubernetes.model.annotation.ShortNames; -import io.fabric8.kubernetes.model.annotation.Version; - -@Group("sample.javaoperatorsdk") -@Version("v1") -@Kind("ObservedGenerationTestCustomResource") -@ShortNames("og") -public class ObservedGenerationTestCustomResource - extends CustomResource - implements Namespaced { - -} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenerationTestCustomResourceStatus.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenerationTestCustomResourceStatus.java deleted file mode 100644 index 14071775f3..0000000000 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenerationTestCustomResourceStatus.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.javaoperatorsdk.operator.sample.observedgeneration; - -import io.javaoperatorsdk.operator.api.ObservedGenerationAwareStatus; - -public class ObservedGenerationTestCustomResourceStatus extends ObservedGenerationAwareStatus { - -} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenerationTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenerationTestReconciler.java deleted file mode 100644 index 7e2127ec7c..0000000000 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenerationTestReconciler.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.javaoperatorsdk.operator.sample.observedgeneration; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; -import io.javaoperatorsdk.operator.api.reconciler.Reconciler; -import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; - -@ControllerConfiguration -public class ObservedGenerationTestReconciler - implements Reconciler { - - private static final Logger log = LoggerFactory.getLogger(ObservedGenerationTestReconciler.class); - - @Override - public UpdateControl reconcile( - ObservedGenerationTestCustomResource resource, - Context context) { - log.info("Reconcile ObservedGenerationTestCustomResource: {}", - resource.getMetadata().getName()); - if (resource.getStatus() == null) { - resource.setStatus(new ObservedGenerationTestCustomResourceStatus()); - } - return UpdateControl.patchStatus(resource); - } -} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/ratelimit/RateLimitCustomResourceStatus.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/ratelimit/RateLimitCustomResourceStatus.java index 087408fc16..975728c18c 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/ratelimit/RateLimitCustomResourceStatus.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/ratelimit/RateLimitCustomResourceStatus.java @@ -1,7 +1,5 @@ package io.javaoperatorsdk.operator.sample.ratelimit; -import io.javaoperatorsdk.operator.api.ObservedGenerationAwareStatus; - -public class RateLimitCustomResourceStatus extends ObservedGenerationAwareStatus { +public class RateLimitCustomResourceStatus { } diff --git a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaStatus.java b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaStatus.java index 92ddb67a63..168cd8db15 100644 --- a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaStatus.java +++ b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaStatus.java @@ -1,8 +1,6 @@ package io.javaoperatorsdk.operator.sample; -import io.javaoperatorsdk.operator.api.ObservedGenerationAwareStatus; - -public class SchemaStatus extends ObservedGenerationAwareStatus { +public class SchemaStatus { private String url; diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/customresource/WebPageStatus.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/customresource/WebPageStatus.java index 7ab20c76be..36409ac7f9 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/customresource/WebPageStatus.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/customresource/WebPageStatus.java @@ -1,8 +1,6 @@ package io.javaoperatorsdk.operator.sample.customresource; -import io.javaoperatorsdk.operator.api.ObservedGenerationAwareStatus; - -public class WebPageStatus extends ObservedGenerationAwareStatus { +public class WebPageStatus { private String htmlConfigMap; From 8850e90b2576166dd95e192d61dc8f2418fcce7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Tue, 14 May 2024 10:21:23 +0200 Subject: [PATCH 2/7] docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- docs/documentation/features.md | 51 ---------------------------- docs/documentation/v5-0-migration.md | 3 ++ 2 files changed, 3 insertions(+), 51 deletions(-) diff --git a/docs/documentation/features.md b/docs/documentation/features.md index d2ead0710b..62656c1ab6 100644 --- a/docs/documentation/features.md +++ b/docs/documentation/features.md @@ -186,57 +186,6 @@ annotation. If you do not specify a finalizer name, one will be automatically ge From v5 by default finalizer is added using Served Side Apply. See also UpdateControl in docs. -## Automatic Observed Generation Handling - -Having an `.observedGeneration` value on your resources' status is a best practice to -indicate the last generation of the resource which was successfully reconciled by the controller. -This helps users / administrators diagnose potential issues. - -In order to have this feature working: - -- the **status class** (not the resource itself) must implement the - [`ObservedGenerationAware`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/ObservedGenerationAware.java) - interface. See also - the [`ObservedGenerationAwareStatus`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/ObservedGenerationAwareStatus.java) - convenience implementation that you can extend in your own status class implementations. -- The other condition is that the `CustomResource.getStatus()` method should not return `null`. - So the status should be instantiated when the object is returned using the `UpdateControl`. - -If these conditions are fulfilled and generation awareness is activated, the observed generation -is automatically set by the framework after the `reconcile` method is called. - -When using SSA based patches, the observed generation is only updated when `UpdateControl.patchStatus` or -`UpdateControl.patchResourceAndStatus` is returned. In case the of non-SSA based patches -the observed generation is also updated even when `UpdateControl.noUpdate()` is returned from the -reconciler. -See this feature at work in the [WebPage example](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStatus.java#L5). -See turning off an on the SSA based patching at [`ConfigurationServcice.useSSAToPatchPrimaryResource()`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java#L385-L385). - -```java -public class WebPageStatus extends ObservedGenerationAwareStatus { - // omitted code -} -``` - -Initializing status automatically on custom resource could be done by overriding the `initStatus` method -of `CustomResource`. However, this is NOT advised, since breaks the status patching if you use: -`UpdateControl.patchStatus`. See -also [javadocs](https://github.com/java-operator-sdk/java-operator-sdk/blob/3994f5ffc1fb000af81aa198abf72a5f75fd3e97/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/UpdateControl.java#L41-L42) -. - -```java -@Group("sample.javaoperatorsdk") -@Version("v1") -public class WebPage extends CustomResource - implements Namespaced { - - @Override - protected WebPageStatus initStatus() { - return new WebPageStatus(); - } -} -``` - ## Generation Awareness and Event Filtering A best practice when an operator starts up is to reconcile all the associated resources because diff --git a/docs/documentation/v5-0-migration.md b/docs/documentation/v5-0-migration.md index b051e2018f..53201abe7f 100644 --- a/docs/documentation/v5-0-migration.md +++ b/docs/documentation/v5-0-migration.md @@ -57,3 +57,6 @@ permalink: /docs/v5-0-migration 8. `ConfigurationService.getTerminationTimeoutSeconds` and associated overriding mechanism have been removed, use `Operator.stop(Duration)` instead. 9. `Operator.installShutdownHook()` has been removed, use `Operator.installShutdownHook(Duration)` instead +10. Automated observed generation handling feature was removed, since it is trivial to do manually and + since it cannot be done automatically in all cases with SSA, having different behavior for SSA and non-SSA + usage would be confusing. \ No newline at end of file From 82fb183f1985f4d5d6b77c95c21ea573c690dfec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Tue, 14 May 2024 10:25:18 +0200 Subject: [PATCH 3/7] docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- README.md | 1 - docs/documentation/features.md | 4 +--- docs/documentation/v5-0-migration.md | 5 ----- .../operator/api/config/ConfigurationService.java | 2 +- .../operator/processing/event/ReconciliationDispatcher.java | 3 --- 5 files changed, 2 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index d850c4551d..a58a8dcd51 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,6 @@ It makes it easy to implement best practices and patterns for an Operator. Featu * Handling dependent resources, related events, and caching. * Automatic Retries * Smart event scheduling -* Handling Observed Generations automatically * Easy to use Error Handling * ... and everything that a batteries included framework needs diff --git a/docs/documentation/features.md b/docs/documentation/features.md index 62656c1ab6..68e8422c7c 100644 --- a/docs/documentation/features.md +++ b/docs/documentation/features.md @@ -203,9 +203,7 @@ To turn off this feature, set `generationAwareEventProcessing` to `false` for th ## Support for Well Known (non-custom) Kubernetes Resources A Controller can be registered for a non-custom resource, so well known Kubernetes resources like ( -`Ingress`, `Deployment`,...). Note that automatic observed generation handling is not supported -for these resources, though, in this case, the handling of the observed generation is probably -handled by the primary controller. +`Ingress`, `Deployment`,...). See the [integration test](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/deployment/DeploymentReconciler.java) diff --git a/docs/documentation/v5-0-migration.md b/docs/documentation/v5-0-migration.md index 53201abe7f..500b435f6b 100644 --- a/docs/documentation/v5-0-migration.md +++ b/docs/documentation/v5-0-migration.md @@ -44,11 +44,6 @@ permalink: /docs/v5-0-migration where it is demonstrated. Also, the related part of a [workaround](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/StatusPatchSSAMigrationIT.java#L110-L116). - Related automatic observed generation handling changes: - Automated Observed Generation (see features in docs), is automatically handled for non-SSA, even if - the status sub-resource is not instructed to be updated. This is not true for SSA, observed generation is updated - only when patch status is instructed by `UpdateControl`. - 6. `ManagedDependentResourceContext` has been renamed to `ManagedWorkflowAndDependentResourceContext` and is accessed via the accordingly renamed `managedWorkflowAndDependentResourceContext` method. 7. `ResourceDiscriminator` was removed. In most of the cases you can just delete the discriminator, everything should diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java index eb3c9a9b01..16d01c4ddd 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java @@ -395,7 +395,7 @@ default boolean parseResourceVersionsForEventFilteringAndCaching() { /** * {@link io.javaoperatorsdk.operator.api.reconciler.UpdateControl} patch resource or status can * either use simple patches or SSA. Setting this to {@code true}, controllers will use SSA for - * adding finalizers, managing observed generation, patching resources and status. + * adding finalizers, patching resources and status. * * @return {@code true} if Server-Side Apply (SSA) should be used when patching the primary * resources, {@code false} otherwise diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java index 3e9ac9aaba..601a92ba60 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java @@ -168,9 +168,6 @@ private PostExecutionControl

reconcileExecution(ExecutionScope

executionSc } } - - - // if using SSA the observed generation is updated only if user instructs patching the status if (updateControl.isPatchStatus()) { customResourceFacade.patchStatus(toUpdate, originalResource); } From dcc418f7c4ef8859aa90a0d9127b291f5dea0b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Tue, 14 May 2024 10:57:20 +0200 Subject: [PATCH 4/7] fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- .../CreateUpdateEventFilterTestCustomResource.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/createupdateeventfilter/CreateUpdateEventFilterTestCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/createupdateeventfilter/CreateUpdateEventFilterTestCustomResource.java index 5797a44d9d..8a0ee77474 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/createupdateeventfilter/CreateUpdateEventFilterTestCustomResource.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/createupdateeventfilter/CreateUpdateEventFilterTestCustomResource.java @@ -11,12 +11,7 @@ @ShortNames("cue") public class CreateUpdateEventFilterTestCustomResource extends - CustomResource + CustomResource implements Namespaced { - @Override - protected CreateUpdateEventFilterTestCustomResourceStatus initStatus() { - return new CreateUpdateEventFilterTestCustomResourceStatus(); - } - } From b41aaa9c0af7a6e573dc072febdb782345941d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Tue, 14 May 2024 14:37:46 +0200 Subject: [PATCH 5/7] docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- docs/documentation/v5-0-migration.md | 3 +- .../operator/ManualObservedGenerationIT.java | 61 +++++++++++++++++++ ...anualObservedGenerationCustomResource.java | 15 +++++ .../ManualObservedGenerationReconciler.java | 48 +++++++++++++++ .../ManualObservedGenerationSpec.java | 14 +++++ .../ManualObservedGenerationStatus.java | 14 +++++ 6 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/ManualObservedGenerationIT.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationCustomResource.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationReconciler.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationSpec.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationStatus.java diff --git a/docs/documentation/v5-0-migration.md b/docs/documentation/v5-0-migration.md index 500b435f6b..6c2898f129 100644 --- a/docs/documentation/v5-0-migration.md +++ b/docs/documentation/v5-0-migration.md @@ -54,4 +54,5 @@ permalink: /docs/v5-0-migration 9. `Operator.installShutdownHook()` has been removed, use `Operator.installShutdownHook(Duration)` instead 10. Automated observed generation handling feature was removed, since it is trivial to do manually and since it cannot be done automatically in all cases with SSA, having different behavior for SSA and non-SSA - usage would be confusing. \ No newline at end of file + usage would be confusing. See sample how to do observed generation handling manually + [here](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationReconciler.java). \ No newline at end of file diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/ManualObservedGenerationIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/ManualObservedGenerationIT.java new file mode 100644 index 0000000000..efb659561f --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/ManualObservedGenerationIT.java @@ -0,0 +1,61 @@ +package io.javaoperatorsdk.operator; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension; +import io.javaoperatorsdk.operator.sample.manualobservedgeneration.ManualObservedGenerationCustomResource; +import io.javaoperatorsdk.operator.sample.manualobservedgeneration.ManualObservedGenerationReconciler; +import io.javaoperatorsdk.operator.sample.manualobservedgeneration.ManualObservedGenerationSpec; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +public class ManualObservedGenerationIT { + + public static final String RESOURCE_NAME = "test1"; + @RegisterExtension + LocallyRunOperatorExtension extension = + LocallyRunOperatorExtension.builder().withReconciler(new ManualObservedGenerationReconciler()) + .build(); + + + + @Test + void observedGenerationUpdated() { + extension.create(testResource()); + + await().untilAsserted(() -> { + var r = extension.get(ManualObservedGenerationCustomResource.class, RESOURCE_NAME); + assertThat(r).isNotNull(); + assertThat(r.getStatus().getObservedGeneration()).isEqualTo(1); + assertThat(r.getStatus().getObservedGeneration()).isEqualTo(r.getMetadata().getGeneration()); + }); + + var changed = testResource(); + changed.getSpec().setValue("changed value"); + extension.replace(changed); + + await().untilAsserted(() -> { + var r = extension.get(ManualObservedGenerationCustomResource.class, RESOURCE_NAME); + assertThat(r).isNotNull(); + assertThat(r.getStatus().getObservedGeneration()).isEqualTo(2); + assertThat(r.getStatus().getObservedGeneration()).isEqualTo(r.getMetadata().getGeneration()); + }); + + } + + + ManualObservedGenerationCustomResource testResource() { + var res = new ManualObservedGenerationCustomResource(); + res.setMetadata(new ObjectMetaBuilder() + .withName(RESOURCE_NAME) + .build()); + res.setSpec(new ManualObservedGenerationSpec()); + res.getSpec().setValue("Initial Value"); + return res; + } + + +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationCustomResource.java new file mode 100644 index 0000000000..10b54fe79d --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationCustomResource.java @@ -0,0 +1,15 @@ +package io.javaoperatorsdk.operator.sample.manualobservedgeneration; + +import io.fabric8.kubernetes.api.model.Namespaced; +import io.fabric8.kubernetes.client.CustomResource; +import io.fabric8.kubernetes.model.annotation.Group; +import io.fabric8.kubernetes.model.annotation.ShortNames; +import io.fabric8.kubernetes.model.annotation.Version; + +@Group("sample.javaoperatorsdk") +@Version("v1") +@ShortNames("mog") +public class ManualObservedGenerationCustomResource + extends CustomResource + implements Namespaced { +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationReconciler.java new file mode 100644 index 0000000000..6e3aa15dce --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationReconciler.java @@ -0,0 +1,48 @@ +package io.javaoperatorsdk.operator.sample.manualobservedgeneration; + +import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; + +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import io.javaoperatorsdk.operator.api.reconciler.*; + +@ControllerConfiguration +public class ManualObservedGenerationReconciler + implements Reconciler { + + private final AtomicInteger numberOfExecutions = new AtomicInteger(0); + + @Override + public UpdateControl reconcile( + ManualObservedGenerationCustomResource resource, + Context context) { + numberOfExecutions.addAndGet(1); + var resourceForStatusPatch = resourceForStatusPatch(resource); + if (!Objects.equals(resource.getMetadata().getGeneration(), + resourceForStatusPatch.getStatus().getObservedGeneration())) { + resourceForStatusPatch.getStatus() + .setObservedGeneration(resource.getMetadata().getGeneration()); + return UpdateControl.patchStatus(resourceForStatusPatch); + } else { + return UpdateControl.noUpdate(); + } + } + + private ManualObservedGenerationCustomResource resourceForStatusPatch( + ManualObservedGenerationCustomResource original) { + var res = new ManualObservedGenerationCustomResource(); + res.setMetadata(new ObjectMetaBuilder() + .withName(original.getMetadata().getName()) + .withNamespace(original.getMetadata().getNamespace()) + .build()); + res.setStatus(original.getStatus()); + if (res.getStatus() == null) { + res.setStatus(new ManualObservedGenerationStatus()); + } + return res; + } + + public int getNumberOfExecutions() { + return numberOfExecutions.get(); + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationSpec.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationSpec.java new file mode 100644 index 0000000000..35b04685aa --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationSpec.java @@ -0,0 +1,14 @@ +package io.javaoperatorsdk.operator.sample.manualobservedgeneration; + +public class ManualObservedGenerationSpec { + + private String value; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationStatus.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationStatus.java new file mode 100644 index 0000000000..cdb6d56b2e --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationStatus.java @@ -0,0 +1,14 @@ +package io.javaoperatorsdk.operator.sample.manualobservedgeneration; + +public class ManualObservedGenerationStatus { + + private long observedGeneration; + + public long getObservedGeneration() { + return observedGeneration; + } + + public void setObservedGeneration(long observedGeneration) { + this.observedGeneration = observedGeneration; + } +} From f94cdd7de5216e5d70eed7ea43824bdfc47deeb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Tue, 14 May 2024 14:42:29 +0200 Subject: [PATCH 6/7] decorations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- .../operator/ManualObservedGenerationIT.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/ManualObservedGenerationIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/ManualObservedGenerationIT.java index efb659561f..ddfb2370d6 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/ManualObservedGenerationIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/ManualObservedGenerationIT.java @@ -20,8 +20,6 @@ public class ManualObservedGenerationIT { LocallyRunOperatorExtension.builder().withReconciler(new ManualObservedGenerationReconciler()) .build(); - - @Test void observedGenerationUpdated() { extension.create(testResource()); @@ -39,14 +37,11 @@ void observedGenerationUpdated() { await().untilAsserted(() -> { var r = extension.get(ManualObservedGenerationCustomResource.class, RESOURCE_NAME); - assertThat(r).isNotNull(); assertThat(r.getStatus().getObservedGeneration()).isEqualTo(2); assertThat(r.getStatus().getObservedGeneration()).isEqualTo(r.getMetadata().getGeneration()); }); - } - ManualObservedGenerationCustomResource testResource() { var res = new ManualObservedGenerationCustomResource(); res.setMetadata(new ObjectMetaBuilder() @@ -56,6 +51,4 @@ ManualObservedGenerationCustomResource testResource() { res.getSpec().setValue("Initial Value"); return res; } - - } From 6a72ca64d9a7de9866c18309b45fad3400b7c528 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Tue, 14 May 2024 15:56:11 +0200 Subject: [PATCH 7/7] docs: mention removed classes Signed-off-by: Chris Laprun --- docs/documentation/v5-0-migration.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/documentation/v5-0-migration.md b/docs/documentation/v5-0-migration.md index 6c2898f129..f338d97381 100644 --- a/docs/documentation/v5-0-migration.md +++ b/docs/documentation/v5-0-migration.md @@ -52,7 +52,9 @@ permalink: /docs/v5-0-migration 8. `ConfigurationService.getTerminationTimeoutSeconds` and associated overriding mechanism have been removed, use `Operator.stop(Duration)` instead. 9. `Operator.installShutdownHook()` has been removed, use `Operator.installShutdownHook(Duration)` instead -10. Automated observed generation handling feature was removed, since it is trivial to do manually and - since it cannot be done automatically in all cases with SSA, having different behavior for SSA and non-SSA - usage would be confusing. See sample how to do observed generation handling manually - [here](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationReconciler.java). \ No newline at end of file +10. Automated observed generation handling feature was removed (`ObservedGenerationAware` interface + and `ObservedGenerationAwareStatus` class were deleted). Manually handling observed generation is fairly easy to do + in your reconciler, however, it cannot be done automatically when using SSA. We therefore removed the feature since + it would have been confusing to have a different behavior for SSA and non-SSA cases. For an example of how to do + observed generation handling manually in your reconciler, see + [this sample](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/manualobservedgeneration/ManualObservedGenerationReconciler.java). \ No newline at end of file