From faed9f93cbb584aeb44157264971364d24825c31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Mon, 17 Feb 2025 09:42:31 +0100 Subject: [PATCH 01/10] docs: blog on ssa vs non-SSA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- docs/content/en/blog/news/_index.md | 2 +- docs/content/en/blog/news/csa-to-ssa.md | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 docs/content/en/blog/news/csa-to-ssa.md diff --git a/docs/content/en/blog/news/_index.md b/docs/content/en/blog/news/_index.md index c609aa2543..646c97f954 100644 --- a/docs/content/en/blog/news/_index.md +++ b/docs/content/en/blog/news/_index.md @@ -1,4 +1,4 @@ --- -title: News +title: Posts weight: 20 --- diff --git a/docs/content/en/blog/news/csa-to-ssa.md b/docs/content/en/blog/news/csa-to-ssa.md new file mode 100644 index 0000000000..2dfe29fd3f --- /dev/null +++ b/docs/content/en/blog/news/csa-to-ssa.md @@ -0,0 +1,23 @@ +--- +title: From client side to server side apply +date: 2025-02-17 +--- + +From version 5 of Java Operator SDK [server side apply](https://kubernetes.io/docs/reference/using-api/server-side-apply/) +is a first-class feature, and used by default to update resources. Since, as we will see, +unfortunately (or fortunately) to use is it requires changes for your reconciler implementation. + +For this reason, we prepared a feature flag, which you can flip if not prepared to migrate yet: +[`ConfigurationService.useSSAToPatchPrimaryResource`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java#L493) + +Setting this flag to false will make the operations done by `UpdateControl` using the former approach (not SSA). +As well as adding the finalizer with SSA if needed + +For dependent resources a separate flag exists (this was true also before v5) to use SSA or not: + + +## Resource handling without and with SSA + + +## Migrating to SSA + From c5db32a1a1d37390e81b0c85c568fee12c02ceee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Mon, 17 Feb 2025 09:43:43 +0100 Subject: [PATCH 02/10] rename file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- docs/content/en/blog/news/{csa-to-ssa.md => nonssa-vs-ssa.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/content/en/blog/news/{csa-to-ssa.md => nonssa-vs-ssa.md} (100%) diff --git a/docs/content/en/blog/news/csa-to-ssa.md b/docs/content/en/blog/news/nonssa-vs-ssa.md similarity index 100% rename from docs/content/en/blog/news/csa-to-ssa.md rename to docs/content/en/blog/news/nonssa-vs-ssa.md From 0a7c7ae1b5a0b9fec12e2227aa172e41394c6c01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Mon, 17 Feb 2025 14:55:19 +0100 Subject: [PATCH 03/10] wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- docs/content/en/blog/news/nonssa-vs-ssa.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/content/en/blog/news/nonssa-vs-ssa.md b/docs/content/en/blog/news/nonssa-vs-ssa.md index 2dfe29fd3f..ee161b595b 100644 --- a/docs/content/en/blog/news/nonssa-vs-ssa.md +++ b/docs/content/en/blog/news/nonssa-vs-ssa.md @@ -1,5 +1,5 @@ --- -title: From client side to server side apply +title: From client side to server-side apply date: 2025-02-17 --- @@ -18,6 +18,26 @@ For dependent resources a separate flag exists (this was true also before v5) to ## Resource handling without and with SSA +Until version 5 changing primary resource through `UpdateControl` did not use server-side apply. +So usually the implementation of reconciler looked something like this: + +```java + + @Override + public UpdateControl reconcile(WebPage webPage, Context context) { + + reconcileLogicForManagedResources(webPage); + webPage.setStatus(updatedStatusForWebPage(webPage)); + + return UpdateControl.patchStatus(webPage); + } + +``` + +In other words, after reconciliation of managed resources the reconcile updated the status on the +primary resource passed as argument to the reconciler. +Such changes on primary are fine, since we don't work directly with the cached object, the argument is +already cloned. ## Migrating to SSA From 546e24ac27ea0a8fd9ca2bfe839c8d5e97e4e3ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Mon, 17 Feb 2025 15:00:34 +0100 Subject: [PATCH 04/10] wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- docs/content/en/blog/news/nonssa-vs-ssa.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/content/en/blog/news/nonssa-vs-ssa.md b/docs/content/en/blog/news/nonssa-vs-ssa.md index ee161b595b..3f1995f750 100644 --- a/docs/content/en/blog/news/nonssa-vs-ssa.md +++ b/docs/content/en/blog/news/nonssa-vs-ssa.md @@ -36,8 +36,10 @@ So usually the implementation of reconciler looked something like this: In other words, after reconciliation of managed resources the reconcile updated the status on the primary resource passed as argument to the reconciler. -Such changes on primary are fine, since we don't work directly with the cached object, the argument is +Such changes on primary are fine since we don't work directly with the cached object, the argument is already cloned. -## Migrating to SSA +So how does this change with SSA? + + From 4ef1411d6a50ca07d557a57e52ed8196d07a963e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Tue, 25 Feb 2025 14:02:51 +0100 Subject: [PATCH 05/10] wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- docs/content/en/blog/news/nonssa-vs-ssa.md | 63 ++++++++++++++++++++-- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/docs/content/en/blog/news/nonssa-vs-ssa.md b/docs/content/en/blog/news/nonssa-vs-ssa.md index 3f1995f750..29695a2995 100644 --- a/docs/content/en/blog/news/nonssa-vs-ssa.md +++ b/docs/content/en/blog/news/nonssa-vs-ssa.md @@ -4,16 +4,18 @@ date: 2025-02-17 --- From version 5 of Java Operator SDK [server side apply](https://kubernetes.io/docs/reference/using-api/server-side-apply/) -is a first-class feature, and used by default to update resources. Since, as we will see, -unfortunately (or fortunately) to use is it requires changes for your reconciler implementation. +is a first-class feature, and used by default to update resources. +As we will see, unfortunately (or fortunately) to use of it requires changes for your reconciler implementation. For this reason, we prepared a feature flag, which you can flip if not prepared to migrate yet: [`ConfigurationService.useSSAToPatchPrimaryResource`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java#L493) Setting this flag to false will make the operations done by `UpdateControl` using the former approach (not SSA). -As well as adding the finalizer with SSA if needed +Similarly, the finalizer handling won't utilize SSA handling. +The plan is to keep this flag and allow to use the former approach (non-SSA) also in future releases. -For dependent resources a separate flag exists (this was true also before v5) to use SSA or not: +For dependent resources, a separate flag exists (this was true also before v5) to use SSA or not: +[`ConfigurationService.ssaBasedCreateUpdateMatchForDependentResources`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java#L373) ## Resource handling without and with SSA @@ -34,12 +36,63 @@ So usually the implementation of reconciler looked something like this: ``` -In other words, after reconciliation of managed resources the reconcile updated the status on the +In other words, after reconciliation of managed resources, the reconciler updates the status on the primary resource passed as argument to the reconciler. Such changes on primary are fine since we don't work directly with the cached object, the argument is already cloned. So how does this change with SSA? +For SSA, the updates should contain (only) the "fully specified intent". +In other words, we should fill only the values that we care about. +In practice means creating a **fresh copy** of the resource and setting only what is necessary: + +```java + +@Override +public UpdateControl reconcile(WebPage webPage, Context context) { + + reconcileLogicForManagedResources(webPage); + + WebPage statusPatch = new WebPage(); + statusPatch.setMetadata(new ObjectMetaBuilder() + .withName(webPage.getMetadata().getName()) + .withNamespace(webPage.getMetadata().getNamespace()) + .build()); + statusPatch.setStatus(createStatus(configMapName)); + + return UpdateControl.patchStatus(statusPatch); +} +``` + +Note that we just filled the status here, since we patch the status (not the resource spec). +Since the status is a sub-resource in Kubernetes, it will only update the status part. + +Every controller you register will have its own default [field manager](https://kubernetes.io/docs/reference/using-api/server-side-apply/#managers). +You can override the field manager name using [`ControllerConfiguration.fieldManager`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java#L89). +That will set the field manager for the updates of the primary resource and dependent resources. + +## Migrating to SSA + +Using the legacy or the new SSA way of resource management works well. +However, migrating existing resources to SSA might be a challenge. +So we strongly encourage everyone to test the migration, thus write an integration test where +a custom resource is created using legacy approach is getting managed by new approach. + +We prepared an integration test to demonstrate how such migration even in a simple case can go wrong, +and how to fix it. + +Note that fixing might that you need to [strip managed fields](https://kubernetes.io/docs/reference/using-api/server-side-apply/#clearing-managedfields) +from the custom resource. + +See [`StatusPatchSSAMigrationIT`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuspatchnonlocking/StatusPatchSSAMigrationIT.java) for details. + +Also feel free to report common issues, so we can in case prepare some utilities to handle them. + + + + + + From 5450eab5826ad4d0b53f107b1a9c8e57eda5d638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Tue, 25 Feb 2025 14:10:57 +0100 Subject: [PATCH 06/10] wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- docs/content/en/blog/news/nonssa-vs-ssa.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/en/blog/news/nonssa-vs-ssa.md b/docs/content/en/blog/news/nonssa-vs-ssa.md index 29695a2995..c1124870d5 100644 --- a/docs/content/en/blog/news/nonssa-vs-ssa.md +++ b/docs/content/en/blog/news/nonssa-vs-ssa.md @@ -1,6 +1,6 @@ --- title: From client side to server-side apply -date: 2025-02-17 +date: 2025-02-25 --- From version 5 of Java Operator SDK [server side apply](https://kubernetes.io/docs/reference/using-api/server-side-apply/) @@ -81,7 +81,7 @@ a custom resource is created using legacy approach is getting managed by new app We prepared an integration test to demonstrate how such migration even in a simple case can go wrong, and how to fix it. -Note that fixing might that you need to [strip managed fields](https://kubernetes.io/docs/reference/using-api/server-side-apply/#clearing-managedfields) +To fix some cases, you might need to [strip managed fields](https://kubernetes.io/docs/reference/using-api/server-side-apply/#clearing-managedfields) from the custom resource. See [`StatusPatchSSAMigrationIT`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuspatchnonlocking/StatusPatchSSAMigrationIT.java) for details. From 6ba45ea437788f4dbf41d69b5f0a14b87f3801d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Tue, 25 Feb 2025 14:16:44 +0100 Subject: [PATCH 07/10] Update nonssa-vs-ssa.md --- docs/content/en/blog/news/nonssa-vs-ssa.md | 47 +++++++++------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/docs/content/en/blog/news/nonssa-vs-ssa.md b/docs/content/en/blog/news/nonssa-vs-ssa.md index c1124870d5..41b7a8d106 100644 --- a/docs/content/en/blog/news/nonssa-vs-ssa.md +++ b/docs/content/en/blog/news/nonssa-vs-ssa.md @@ -4,15 +4,15 @@ date: 2025-02-25 --- From version 5 of Java Operator SDK [server side apply](https://kubernetes.io/docs/reference/using-api/server-side-apply/) -is a first-class feature, and used by default to update resources. -As we will see, unfortunately (or fortunately) to use of it requires changes for your reconciler implementation. +is a first-class feature and is used by default to update resources. +As we will see, unfortunately (or fortunately), using it requires changes for your reconciler implementation. -For this reason, we prepared a feature flag, which you can flip if not prepared to migrate yet: +For this reason, we prepared a feature flag, which you can flip if you are not prepared to migrate yet: [`ConfigurationService.useSSAToPatchPrimaryResource`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java#L493) Setting this flag to false will make the operations done by `UpdateControl` using the former approach (not SSA). Similarly, the finalizer handling won't utilize SSA handling. -The plan is to keep this flag and allow to use the former approach (non-SSA) also in future releases. +The plan is to keep this flag and allow the use of the former approach (non-SSA) also in future releases. For dependent resources, a separate flag exists (this was true also before v5) to use SSA or not: [`ConfigurationService.ssaBasedCreateUpdateMatchForDependentResources`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java#L373) @@ -20,8 +20,8 @@ For dependent resources, a separate flag exists (this was true also before v5) t ## Resource handling without and with SSA -Until version 5 changing primary resource through `UpdateControl` did not use server-side apply. -So usually the implementation of reconciler looked something like this: +Until version 5, changing primary resources through `UpdateControl` did not use server-side apply. +So usually, the implementation of the reconciler looked something like this: ```java @@ -36,15 +36,15 @@ So usually the implementation of reconciler looked something like this: ``` -In other words, after reconciliation of managed resources, the reconciler updates the status on the -primary resource passed as argument to the reconciler. -Such changes on primary are fine since we don't work directly with the cached object, the argument is +In other words, after the reconciliation of managed resources, the reconciler updates the status of the +primary resource passed as an argument to the reconciler. +Such changes on the primary are fine since we don't work directly with the cached object, the argument is already cloned. -So how does this change with SSA? +So, how does this change with SSA? For SSA, the updates should contain (only) the "fully specified intent". -In other words, we should fill only the values that we care about. -In practice means creating a **fresh copy** of the resource and setting only what is necessary: +In other words, we should only fill in the values we care about. +In practice, it means creating a **fresh copy** of the resource and setting only what is necessary: ```java @@ -64,21 +64,21 @@ public UpdateControl reconcile(WebPage webPage, Context contex } ``` -Note that we just filled the status here, since we patch the status (not the resource spec). +Note that we just filled out the status here since we patched the status (not the resource spec). Since the status is a sub-resource in Kubernetes, it will only update the status part. -Every controller you register will have its own default [field manager](https://kubernetes.io/docs/reference/using-api/server-side-apply/#managers). +Every controller you register will have its default [field manager](https://kubernetes.io/docs/reference/using-api/server-side-apply/#managers). You can override the field manager name using [`ControllerConfiguration.fieldManager`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java#L89). -That will set the field manager for the updates of the primary resource and dependent resources. +That will set the field manager for the primary resource and dependent resources as well. ## Migrating to SSA Using the legacy or the new SSA way of resource management works well. However, migrating existing resources to SSA might be a challenge. -So we strongly encourage everyone to test the migration, thus write an integration test where -a custom resource is created using legacy approach is getting managed by new approach. +We strongly recommend testing the migration, thus implementing an integration test where +a custom resource is created using the legacy approach and is managed by the new approach. -We prepared an integration test to demonstrate how such migration even in a simple case can go wrong, +We prepared an integration test to demonstrate how such migration, even in a simple case, can go wrong, and how to fix it. To fix some cases, you might need to [strip managed fields](https://kubernetes.io/docs/reference/using-api/server-side-apply/#clearing-managedfields) @@ -86,13 +86,4 @@ from the custom resource. See [`StatusPatchSSAMigrationIT`](https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuspatchnonlocking/StatusPatchSSAMigrationIT.java) for details. -Also feel free to report common issues, so we can in case prepare some utilities to handle them. - - - - - - - - - +Feel free to report common issues, so we can prepare some utilities to handle them. From 538ebc57ebdc64c74e3ba97458c36d76fa5ee3ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Tue, 25 Feb 2025 14:17:32 +0100 Subject: [PATCH 08/10] Update nonssa-vs-ssa.md --- docs/content/en/blog/news/nonssa-vs-ssa.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/en/blog/news/nonssa-vs-ssa.md b/docs/content/en/blog/news/nonssa-vs-ssa.md index 41b7a8d106..4bed6926c4 100644 --- a/docs/content/en/blog/news/nonssa-vs-ssa.md +++ b/docs/content/en/blog/news/nonssa-vs-ssa.md @@ -1,5 +1,5 @@ --- -title: From client side to server-side apply +title: From legacy approach to server-side apply date: 2025-02-25 --- From fcbd2f09b27fe1fec8e4b4a897f9825d542c788f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Tue, 25 Feb 2025 14:19:44 +0100 Subject: [PATCH 09/10] wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- docs/content/en/blog/news/nonssa-vs-ssa.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/en/blog/news/nonssa-vs-ssa.md b/docs/content/en/blog/news/nonssa-vs-ssa.md index 4bed6926c4..241828d3e3 100644 --- a/docs/content/en/blog/news/nonssa-vs-ssa.md +++ b/docs/content/en/blog/news/nonssa-vs-ssa.md @@ -58,7 +58,7 @@ public UpdateControl reconcile(WebPage webPage, Context contex .withName(webPage.getMetadata().getName()) .withNamespace(webPage.getMetadata().getNamespace()) .build()); - statusPatch.setStatus(createStatus(configMapName)); + statusPatch.setStatus(updatedStatusForWebPage(webPage)); return UpdateControl.patchStatus(statusPatch); } From 4297bbda2f8f679a8a4dee2a51ab08072f9addc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Tue, 25 Feb 2025 14:23:46 +0100 Subject: [PATCH 10/10] link MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- docs/content/en/blog/releases/v5-release.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/en/blog/releases/v5-release.md b/docs/content/en/blog/releases/v5-release.md index 8d5fe36dbe..6d14dfb73a 100644 --- a/docs/content/en/blog/releases/v5-release.md +++ b/docs/content/en/blog/releases/v5-release.md @@ -41,7 +41,7 @@ to `false`. See some identified problematic migration cases and how to handle them in [StatusPatchSSAMigrationIT](https://github.com/operator-framework/java-operator-sdk/blob/1635c9ea338f8e89bacc547808d2b409de8734cf/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuspatchnonlocking/StatusPatchSSAMigrationIT.java). -TODO using new instance to update status always, +For more detailed description, see our [blog post](../news/nonssa-vs-ssa.md) on SSA. ### Event Sources related changes