From f35f1cccded9ee942630e3d682b1072511c134a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Mon, 30 Jun 2025 16:05:03 +0200 Subject: [PATCH 1/2] ssa issue reproducer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- .../SSAFinalizerIssueCustomResource.java | 15 +++++++ .../baseapi/ssaissue/SSAFinalizerIssueIT.java | 45 +++++++++++++++++++ .../ssaissue/SSAFinalizerIssueReconciler.java | 26 +++++++++++ .../ssaissue/SSAFinalizerIssueSpec.java | 26 +++++++++++ .../ssaissue/SSAFinalizerIssueStatus.java | 19 ++++++++ 5 files changed, 131 insertions(+) create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueCustomResource.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueIT.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueReconciler.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueSpec.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueStatus.java diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueCustomResource.java new file mode 100644 index 0000000000..8f39468361 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueCustomResource.java @@ -0,0 +1,15 @@ +package io.javaoperatorsdk.operator.baseapi.ssaissue; + +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("CustomService") +@ShortNames("ssaf") +public class SSAFinalizerIssueCustomResource + extends CustomResource implements Namespaced {} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueIT.java new file mode 100644 index 0000000000..f02e01e31a --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueIT.java @@ -0,0 +1,45 @@ +package io.javaoperatorsdk.operator.baseapi.ssaissue; + +import java.util.List; + +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 static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +class SSAFinalizerIssueIT { + + public static final String TEST_1 = "test1"; + + @RegisterExtension + LocallyRunOperatorExtension operator = + LocallyRunOperatorExtension.builder() + .withReconciler(new SSAFinalizerIssueReconciler()) + .build(); + + @Test + void addingFinalizerRemoveListValues() { + operator.create(testResource()); + + await() + .untilAsserted( + () -> { + var actual = operator.get(SSAFinalizerIssueCustomResource.class, TEST_1); + assertThat(actual.getFinalizers()).hasSize(1); + assertThat(actual.getSpec().getList()).isEmpty(); + }); + } + + SSAFinalizerIssueCustomResource testResource() { + var res = new SSAFinalizerIssueCustomResource(); + res.setMetadata(new ObjectMetaBuilder().withName(TEST_1).build()); + res.setSpec(new SSAFinalizerIssueSpec()); + res.getSpec().setValue("val"); + res.getSpec().setList(List.of("val1", "val2")); + return res; + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueReconciler.java new file mode 100644 index 0000000000..7941554d66 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueReconciler.java @@ -0,0 +1,26 @@ +package io.javaoperatorsdk.operator.baseapi.ssaissue; + +import io.javaoperatorsdk.operator.api.reconciler.Cleaner; +import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; +import io.javaoperatorsdk.operator.api.reconciler.DeleteControl; +import io.javaoperatorsdk.operator.api.reconciler.Reconciler; +import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; + +@ControllerConfiguration +public class SSAFinalizerIssueReconciler + implements Reconciler, + Cleaner { + + @Override + public DeleteControl cleanup( + SSAFinalizerIssueCustomResource resource, Context context) { + return DeleteControl.defaultDelete(); + } + + @Override + public UpdateControl reconcile( + SSAFinalizerIssueCustomResource resource, Context context) { + return UpdateControl.noUpdate(); + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueSpec.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueSpec.java new file mode 100644 index 0000000000..0a1d16dae3 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueSpec.java @@ -0,0 +1,26 @@ +package io.javaoperatorsdk.operator.baseapi.ssaissue; + +import java.util.List; + +public class SSAFinalizerIssueSpec { + + private String value; + + private List list; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueStatus.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueStatus.java new file mode 100644 index 0000000000..1c4de53d2b --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueStatus.java @@ -0,0 +1,19 @@ +package io.javaoperatorsdk.operator.baseapi.ssaissue; + +public class SSAFinalizerIssueStatus { + + private String configMapStatus; + + public String getConfigMapStatus() { + return configMapStatus; + } + + public void setConfigMapStatus(String configMapStatus) { + this.configMapStatus = configMapStatus; + } + + @Override + public String toString() { + return "TestCustomResourceStatus{" + "configMapStatus='" + configMapStatus + '\'' + '}'; + } +} From cd1434dc0b42c241cd642e00d47dc94ae3964298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Fri, 4 Jul 2025 13:52:12 +0200 Subject: [PATCH 2/2] feat: showcase initilized list cleanup when adding finalizer with SSA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- .../{ => finalizer}/SSAFinalizerIssueCustomResource.java | 2 +- .../ssaissue/{ => finalizer}/SSAFinalizerIssueIT.java | 7 ++++++- .../{ => finalizer}/SSAFinalizerIssueReconciler.java | 2 +- .../ssaissue/{ => finalizer}/SSAFinalizerIssueSpec.java | 7 +++++-- .../ssaissue/{ => finalizer}/SSAFinalizerIssueStatus.java | 2 +- 5 files changed, 14 insertions(+), 6 deletions(-) rename operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/{ => finalizer}/SSAFinalizerIssueCustomResource.java (89%) rename operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/{ => finalizer}/SSAFinalizerIssueIT.java (80%) rename operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/{ => finalizer}/SSAFinalizerIssueReconciler.java (93%) rename operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/{ => finalizer}/SSAFinalizerIssueSpec.java (52%) rename operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/{ => finalizer}/SSAFinalizerIssueStatus.java (86%) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueCustomResource.java similarity index 89% rename from operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueCustomResource.java rename to operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueCustomResource.java index 8f39468361..757e2019cc 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueCustomResource.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueCustomResource.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.operator.baseapi.ssaissue; +package io.javaoperatorsdk.operator.baseapi.ssaissue.finalizer; import io.fabric8.kubernetes.api.model.Namespaced; import io.fabric8.kubernetes.client.CustomResource; diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueIT.java similarity index 80% rename from operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueIT.java rename to operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueIT.java index f02e01e31a..5a172a4d24 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueIT.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.operator.baseapi.ssaissue; +package io.javaoperatorsdk.operator.baseapi.ssaissue.finalizer; import java.util.List; @@ -21,6 +21,11 @@ class SSAFinalizerIssueIT { .withReconciler(new SSAFinalizerIssueReconciler()) .build(); + /** + * Showcases the problem when we add a finalizer and in the spec a list is initialized with an + * empty list by default. This at the end results in a change that when adding the finalizer the + * SSA patch deletes the initial values in the spec. + */ @Test void addingFinalizerRemoveListValues() { operator.create(testResource()); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueReconciler.java similarity index 93% rename from operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueReconciler.java rename to operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueReconciler.java index 7941554d66..441819834a 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueReconciler.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.operator.baseapi.ssaissue; +package io.javaoperatorsdk.operator.baseapi.ssaissue.finalizer; import io.javaoperatorsdk.operator.api.reconciler.Cleaner; import io.javaoperatorsdk.operator.api.reconciler.Context; diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueSpec.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueSpec.java similarity index 52% rename from operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueSpec.java rename to operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueSpec.java index 0a1d16dae3..99c9f76b7b 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueSpec.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueSpec.java @@ -1,12 +1,15 @@ -package io.javaoperatorsdk.operator.baseapi.ssaissue; +package io.javaoperatorsdk.operator.baseapi.ssaissue.finalizer; +import java.util.ArrayList; import java.util.List; public class SSAFinalizerIssueSpec { private String value; - private List list; + // List is initialized, that at the end becomes problematic when adding the finalizer + // If the list is not initialized like this (this its null) it works fine + private List list = new ArrayList<>(); public String getValue() { return value; diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueStatus.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueStatus.java similarity index 86% rename from operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueStatus.java rename to operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueStatus.java index 1c4de53d2b..471372af40 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/SSAFinalizerIssueStatus.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueStatus.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.operator.baseapi.ssaissue; +package io.javaoperatorsdk.operator.baseapi.ssaissue.finalizer; public class SSAFinalizerIssueStatus {