From 792ee8d54f7e8b7d52f4c7f51798e49b37e88b5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Mon, 13 Oct 2025 20:16:17 +0200 Subject: [PATCH 01/13] fix: main version to 5.1.5-SNAPSHOT (#2992) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- bootstrapper-maven-plugin/pom.xml | 2 +- caffeine-bounded-cache-support/pom.xml | 2 +- micrometer-support/pom.xml | 2 +- operator-framework-bom/pom.xml | 2 +- operator-framework-core/pom.xml | 2 +- operator-framework-junit5/pom.xml | 2 +- operator-framework/pom.xml | 2 +- pom.xml | 2 +- sample-operators/controller-namespace-deletion/pom.xml | 2 +- sample-operators/leader-election/pom.xml | 2 +- sample-operators/mysql-schema/pom.xml | 2 +- sample-operators/pom.xml | 2 +- sample-operators/tomcat-operator/pom.xml | 2 +- sample-operators/webpage/pom.xml | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/bootstrapper-maven-plugin/pom.xml b/bootstrapper-maven-plugin/pom.xml index ccdc62f905..c306dcea35 100644 --- a/bootstrapper-maven-plugin/pom.xml +++ b/bootstrapper-maven-plugin/pom.xml @@ -5,7 +5,7 @@ io.javaoperatorsdk java-operator-sdk - 5.1.4-SNAPSHOT + 5.1.5-SNAPSHOT bootstrapper diff --git a/caffeine-bounded-cache-support/pom.xml b/caffeine-bounded-cache-support/pom.xml index bd8c2ccce9..76f3db9abc 100644 --- a/caffeine-bounded-cache-support/pom.xml +++ b/caffeine-bounded-cache-support/pom.xml @@ -4,7 +4,7 @@ io.javaoperatorsdk java-operator-sdk - 5.1.4-SNAPSHOT + 5.1.5-SNAPSHOT caffeine-bounded-cache-support diff --git a/micrometer-support/pom.xml b/micrometer-support/pom.xml index c748690459..c66a2d339f 100644 --- a/micrometer-support/pom.xml +++ b/micrometer-support/pom.xml @@ -4,7 +4,7 @@ io.javaoperatorsdk java-operator-sdk - 5.1.4-SNAPSHOT + 5.1.5-SNAPSHOT micrometer-support diff --git a/operator-framework-bom/pom.xml b/operator-framework-bom/pom.xml index 18548eaee3..7770b05ab8 100644 --- a/operator-framework-bom/pom.xml +++ b/operator-framework-bom/pom.xml @@ -4,7 +4,7 @@ io.javaoperatorsdk operator-framework-bom - 5.1.4-SNAPSHOT + 5.1.5-SNAPSHOT pom Operator SDK - Bill of Materials Java SDK for implementing Kubernetes operators diff --git a/operator-framework-core/pom.xml b/operator-framework-core/pom.xml index c242becc0a..5b4281a1ec 100644 --- a/operator-framework-core/pom.xml +++ b/operator-framework-core/pom.xml @@ -4,7 +4,7 @@ io.javaoperatorsdk java-operator-sdk - 5.1.4-SNAPSHOT + 5.1.5-SNAPSHOT ../pom.xml diff --git a/operator-framework-junit5/pom.xml b/operator-framework-junit5/pom.xml index 37c52d11c5..5aeeb92d45 100644 --- a/operator-framework-junit5/pom.xml +++ b/operator-framework-junit5/pom.xml @@ -4,7 +4,7 @@ io.javaoperatorsdk java-operator-sdk - 5.1.4-SNAPSHOT + 5.1.5-SNAPSHOT operator-framework-junit-5 diff --git a/operator-framework/pom.xml b/operator-framework/pom.xml index cb26ce74c6..f1a100eb75 100644 --- a/operator-framework/pom.xml +++ b/operator-framework/pom.xml @@ -4,7 +4,7 @@ io.javaoperatorsdk java-operator-sdk - 5.1.4-SNAPSHOT + 5.1.5-SNAPSHOT operator-framework diff --git a/pom.xml b/pom.xml index 6a99236079..70055e2843 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ io.javaoperatorsdk java-operator-sdk - 5.1.4-SNAPSHOT + 5.1.5-SNAPSHOT pom Operator SDK for Java Java SDK for implementing Kubernetes operators diff --git a/sample-operators/controller-namespace-deletion/pom.xml b/sample-operators/controller-namespace-deletion/pom.xml index 3fd18e45d7..bb2a8fe099 100644 --- a/sample-operators/controller-namespace-deletion/pom.xml +++ b/sample-operators/controller-namespace-deletion/pom.xml @@ -5,7 +5,7 @@ io.javaoperatorsdk sample-operators - 5.1.4-SNAPSHOT + 5.1.5-SNAPSHOT sample-controller-namespace-deletion diff --git a/sample-operators/leader-election/pom.xml b/sample-operators/leader-election/pom.xml index 87b85fb312..23873c5d45 100644 --- a/sample-operators/leader-election/pom.xml +++ b/sample-operators/leader-election/pom.xml @@ -5,7 +5,7 @@ io.javaoperatorsdk sample-operators - 5.1.4-SNAPSHOT + 5.1.5-SNAPSHOT sample-leader-election diff --git a/sample-operators/mysql-schema/pom.xml b/sample-operators/mysql-schema/pom.xml index 5ac2a62d85..8201c1148e 100644 --- a/sample-operators/mysql-schema/pom.xml +++ b/sample-operators/mysql-schema/pom.xml @@ -5,7 +5,7 @@ io.javaoperatorsdk sample-operators - 5.1.4-SNAPSHOT + 5.1.5-SNAPSHOT sample-mysql-schema-operator diff --git a/sample-operators/pom.xml b/sample-operators/pom.xml index 508d420ce4..c19bb7f3f6 100644 --- a/sample-operators/pom.xml +++ b/sample-operators/pom.xml @@ -5,7 +5,7 @@ io.javaoperatorsdk java-operator-sdk - 5.1.4-SNAPSHOT + 5.1.5-SNAPSHOT sample-operators diff --git a/sample-operators/tomcat-operator/pom.xml b/sample-operators/tomcat-operator/pom.xml index e3620b5fa8..0c43071f16 100644 --- a/sample-operators/tomcat-operator/pom.xml +++ b/sample-operators/tomcat-operator/pom.xml @@ -5,7 +5,7 @@ io.javaoperatorsdk sample-operators - 5.1.4-SNAPSHOT + 5.1.5-SNAPSHOT sample-tomcat-operator diff --git a/sample-operators/webpage/pom.xml b/sample-operators/webpage/pom.xml index 8acea5adcb..55eafa8490 100644 --- a/sample-operators/webpage/pom.xml +++ b/sample-operators/webpage/pom.xml @@ -5,7 +5,7 @@ io.javaoperatorsdk sample-operators - 5.1.4-SNAPSHOT + 5.1.5-SNAPSHOT sample-webpage-operator From ca756ea4fc3e5594657fd49f8f3245f8b3d49b5b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 08:19:54 +0200 Subject: [PATCH 02/13] chore(deps): bump me.fabriciorby:maven-surefire-junit5-tree-reporter (#2993) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 70055e2843..d86889c3d3 100644 --- a/pom.xml +++ b/pom.xml @@ -279,7 +279,7 @@ me.fabriciorby maven-surefire-junit5-tree-reporter - 1.4.0 + 1.5.1 From 0dee1bf93f84acb959e5b77acf5c56d66599a0e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 08:21:23 +0200 Subject: [PATCH 03/13] chore(deps): bump io.micrometer:micrometer-core from 1.15.4 to 1.15.5 (#2994) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d86889c3d3..6a76c1c7a0 100644 --- a/pom.xml +++ b/pom.xml @@ -63,7 +63,7 @@ 3.27.6 4.3.0 2.7.3 - 1.15.4 + 1.15.5 3.2.2 0.9.14 2.20.0 From b351b520dcec51f1cb3bede60292389640e9f5d0 Mon Sep 17 00:00:00 2001 From: Steven Hawkins Date: Fri, 17 Oct 2025 03:38:56 -0400 Subject: [PATCH 04/13] fix: reducing log level of failure to patch in handleErrorStatusHandler (#2983) closes: #2981 Signed-off-by: Steve Hawkins --- .../event/ReconciliationDispatcher.java | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) 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 8e0293f3b4..ea79bb8483 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 @@ -1,10 +1,12 @@ package io.javaoperatorsdk.operator.processing.event; import java.lang.reflect.InvocationTargetException; +import java.net.HttpURLConnection; import java.util.function.Function; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.slf4j.event.Level; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.KubernetesResourceList; @@ -216,12 +218,35 @@ public boolean isLastAttempt() { customResourceFacade.patchStatus( errorStatusUpdateControl.getResource().orElseThrow(), originalResource); } catch (Exception ex) { - log.error( - "updateErrorStatus failed for resource: {} with version: {} for error {}", - getUID(resource), - getVersion(resource), - e.getMessage(), - ex); + int code = ex instanceof KubernetesClientException kcex ? kcex.getCode() : -1; + Level exceptionLevel = Level.ERROR; + String failedMessage = ""; + if (context.isNextReconciliationImminent() + || !(errorStatusUpdateControl.isNoRetry() || retryInfo.isLastAttempt())) { + if (code == HttpURLConnection.HTTP_CONFLICT + || (originalResource.getMetadata().getResourceVersion() != null && code == 422)) { + exceptionLevel = Level.DEBUG; + failedMessage = " due to conflict"; + log.info( + "ErrorStatusUpdateControl.patchStatus of {} failed due to a conflict, but the next" + + " reconiliation is imminent.", + ResourceID.fromResource(originalResource)); + } else { + exceptionLevel = Level.WARN; + failedMessage = ", but will be retried soon,"; + } + } + + log.atLevel(exceptionLevel) + .log( + "ErrorStatusUpdateControl.patchStatus failed{} for {} with UID: {} and version: {}" + + " for error {}", + failedMessage, + ResourceID.fromResource(originalResource), + getUID(resource), + getVersion(resource), + e.getMessage(), + ex); } } if (errorStatusUpdateControl.isNoRetry()) { From 3db519a67f75ad60b13a419cc94aa7c77ecce5fb Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Fri, 17 Oct 2025 15:06:37 +0200 Subject: [PATCH 05/13] fix: typo (#3005) Signed-off-by: Chris Laprun --- .../operator/processing/event/ReconciliationDispatcher.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 ea79bb8483..90bdc93979 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 @@ -229,7 +229,7 @@ public boolean isLastAttempt() { failedMessage = " due to conflict"; log.info( "ErrorStatusUpdateControl.patchStatus of {} failed due to a conflict, but the next" - + " reconiliation is imminent.", + + " reconciliation is imminent.", ResourceID.fromResource(originalResource)); } else { exceptionLevel = Level.WARN; @@ -503,7 +503,6 @@ public R patchStatus(R resource, R originalResource) { } } - @SuppressWarnings("unchecked") private R editStatus(R resource, R originalResource) { String resourceVersion = resource.getMetadata().getResourceVersion(); // the cached resource should not be changed in any circumstances From d6e76d20f7ff84e00ca644f53f39514ecc970cb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Fri, 17 Oct 2025 15:52:18 +0200 Subject: [PATCH 06/13] feat: CI for java 25 (#2947) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: java 25 support Signed-off-by: Attila Mészáros * use zulu distribution Signed-off-by: Attila Mészáros * fix Signed-off-by: Attila Mészáros * latest google format Signed-off-by: Attila Mészáros * chore: use temurin distribution again, adjust versions Signed-off-by: Chris Laprun --------- Signed-off-by: Attila Mészáros Signed-off-by: Chris Laprun Co-authored-by: Chris Laprun --- .github/workflows/build.yml | 6 +++--- .github/workflows/e2e-test.yml | 2 +- .github/workflows/pr.yml | 2 +- .github/workflows/release-project-in-dir.yml | 2 +- .github/workflows/snapshot-releases.yml | 4 ++-- .github/workflows/sonar.yml | 2 +- pom.xml | 1 + 7 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e37ab5d8d5..25b234846a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ jobs: integration_tests: strategy: matrix: - java: [ 17, 21, 24 ] + java: [ 17, 21, 25 ] # Use the latest versions supported by minikube, otherwise GitHub it will # end up in a throttling requests from minikube and workflow will fail. # Minikube does such requests only if a version is not officially supported. @@ -26,7 +26,7 @@ jobs: httpclient: [ 'vertx', 'jdk', 'jetty' ] uses: ./.github/workflows/integration-tests.yml with: - java-version: 24 + java-version: 25 kube-version: '1.32.0' http-client: ${{ matrix.httpclient }} experimental: true @@ -36,7 +36,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ 17, 21, 24 ] + java: [ 17, 21, 25 ] steps: - uses: actions/checkout@v5 - name: Set up Java and Maven diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index f72a0af43b..7aa92a409c 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -43,7 +43,7 @@ jobs: - name: Set up Java and Maven uses: actions/setup-java@v5 with: - java-version: 17 + java-version: 25 distribution: temurin cache: 'maven' diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index df5819f33d..79660cfb1b 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -22,7 +22,7 @@ jobs: uses: actions/setup-java@v5 with: distribution: temurin - java-version: 21 + java-version: 25 cache: 'maven' - name: Check code format run: | diff --git a/.github/workflows/release-project-in-dir.yml b/.github/workflows/release-project-in-dir.yml index 0683b01b1f..0313aebe4d 100644 --- a/.github/workflows/release-project-in-dir.yml +++ b/.github/workflows/release-project-in-dir.yml @@ -80,4 +80,4 @@ jobs: uses: ad-m/github-push-action@master with: branch: "${{inputs.version_branch}}" - github_token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/snapshot-releases.yml b/.github/workflows/snapshot-releases.yml index a12d9aaed5..0f560dd2cb 100644 --- a/.github/workflows/snapshot-releases.yml +++ b/.github/workflows/snapshot-releases.yml @@ -21,7 +21,7 @@ jobs: uses: actions/setup-java@v5 with: distribution: temurin - java-version: 17 + java-version: 21 cache: 'maven' - name: Build and test project run: ./mvnw ${MAVEN_ARGS} clean install --file pom.xml @@ -33,7 +33,7 @@ jobs: - name: Set up Java and Maven uses: actions/setup-java@v5 with: - java-version: 17 + java-version: 21 distribution: temurin cache: 'maven' server-id: central diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index 370f36303c..132575edaa 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -28,7 +28,7 @@ jobs: uses: actions/setup-java@v5 with: distribution: temurin - java-version: 17 + java-version: 25 cache: 'maven' - name: Cache SonarCloud packages uses: actions/cache@v4 diff --git a/pom.xml b/pom.xml index 6a76c1c7a0..303c11f79b 100644 --- a/pom.xml +++ b/pom.xml @@ -344,6 +344,7 @@ + 1.28.0 true From fa288d168ffd2f37b23214aaac8b92a8ba8615d0 Mon Sep 17 00:00:00 2001 From: Donnerbart Date: Tue, 21 Oct 2025 16:01:08 +0200 Subject: [PATCH 07/13] Improve PodTemplateSpec sanitizer for GKE Autopilot compatibility (#3012) * test: update type parameters in SSABasedGenericKubernetesResourceMatcherTest for better type safety * fix: improve PodTemplateSpec sanitizer for GKE Autopilot compatibility Signed-off-by: David Sondermann --- .../kubernetes/PodTemplateSpecSanitizer.java | 1 - .../PodTemplateSpecSanitizerTest.java | 69 +++++++++++++++---- ...dGenericKubernetesResourceMatcherTest.java | 18 ++--- 3 files changed, 62 insertions(+), 26 deletions(-) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/PodTemplateSpecSanitizer.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/PodTemplateSpecSanitizer.java index 962059961e..fd1dcff49c 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/PodTemplateSpecSanitizer.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/PodTemplateSpecSanitizer.java @@ -124,7 +124,6 @@ private static void sanitizeQuantities( "resources", quantityPath)) .map(Map.class::cast) - .filter(m -> m.size() == desiredResource.size()) .ifPresent( m -> actualResource.forEach( diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/PodTemplateSpecSanitizerTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/PodTemplateSpecSanitizerTest.java index 091a1a666c..e7756b45bc 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/PodTemplateSpecSanitizerTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/PodTemplateSpecSanitizerTest.java @@ -132,19 +132,6 @@ void testSanitizePodTemplateSpec_whenResourceIsNull_doNothing() { verifyNoInteractions(actualMap); } - @Test - void testSanitizeResourceRequirements_whenResourceSizeMismatch_doNothing() { - final var actualMap = - sanitizeRequestsAndLimits( - ContainerType.CONTAINER, - Map.of("cpu", new Quantity("2")), - Map.of(), - Map.of("cpu", new Quantity("4")), - Map.of("cpu", new Quantity("4"), "memory", new Quantity("4Gi"))); - assertContainerResources(actualMap, "requests").hasSize(1).containsEntry("cpu", "2"); - assertContainerResources(actualMap, "limits").hasSize(1).containsEntry("cpu", "4"); - } - @Test void testSanitizeResourceRequirements_whenResourceKeyMismatch_doNothing() { final var actualMap = @@ -187,6 +174,34 @@ void testSanitizePodTemplateSpec_whenResourcesHaveNumericalAmountMismatch_doNoth assertInitContainerResources(actualMap, "limits").hasSize(1).containsEntry("cpu", "2"); } + @Test + void + testSanitizePodTemplateSpec_whenResourcesHaveNumericalAmountMismatch_withEphemeralStorageAddedByOtherOperator_doNothing() { + // mimics an environment like GKE Autopilot that enforces ephemeral-storage requests and limits + final var actualMap = + sanitizeRequestsAndLimits( + ContainerType.INIT_CONTAINER, + Map.of( + "cpu", + new Quantity("2"), + "memory", + new Quantity("4Gi"), + "ephemeral-storage", + new Quantity("1Gi")), + Map.of("cpu", new Quantity("4"), "memory", new Quantity("4Ti")), + Map.of("cpu", new Quantity("2"), "ephemeral-storage", new Quantity("1Gi")), + Map.of("cpu", new Quantity("4000m"))); + assertInitContainerResources(actualMap, "requests") + .hasSize(3) + .containsEntry("cpu", "2") + .containsEntry("memory", "4Gi") + .containsEntry("ephemeral-storage", "1Gi"); + assertInitContainerResources(actualMap, "limits") + .hasSize(2) + .containsEntry("cpu", "2") + .containsEntry("ephemeral-storage", "1Gi"); + } + @Test void testSanitizeResourceRequirements_whenResourcesHaveAmountAndFormatMismatchWithSameNumericalAmount_thenSanitizeActualMap() { @@ -204,6 +219,34 @@ void testSanitizePodTemplateSpec_whenResourcesHaveNumericalAmountMismatch_doNoth assertContainerResources(actualMap, "limits").hasSize(1).containsEntry("cpu", "4000m"); } + @Test + void + testSanitizeResourceRequirements_whenResourcesHaveAmountAndFormatMismatchWithSameNumericalAmount_withEphemeralStorageAddedByOtherOperator_thenSanitizeActualMap() { + // mimics an environment like GKE Autopilot that enforces ephemeral-storage requests and limits + final var actualMap = + sanitizeRequestsAndLimits( + ContainerType.CONTAINER, + Map.of( + "cpu", + new Quantity("2"), + "memory", + new Quantity("4Gi"), + "ephemeral-storage", + new Quantity("1Gi")), + Map.of("cpu", new Quantity("2000m"), "memory", new Quantity("4096Mi")), + Map.of("cpu", new Quantity("4"), "ephemeral-storage", new Quantity("1Gi")), + Map.of("cpu", new Quantity("4000m"))); + assertContainerResources(actualMap, "requests") + .hasSize(3) + .containsEntry("cpu", "2000m") + .containsEntry("memory", "4096Mi") + .containsEntry("ephemeral-storage", "1Gi"); + assertContainerResources(actualMap, "limits") + .hasSize(2) + .containsEntry("cpu", "4000m") + .containsEntry("ephemeral-storage", "1Gi"); + } + @Test void testSanitizePodTemplateSpec_whenEnvVarsIsEmpty_doNothing() { final var template = diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/SSABasedGenericKubernetesResourceMatcherTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/SSABasedGenericKubernetesResourceMatcherTest.java index c339e5ebf6..e441516d46 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/SSABasedGenericKubernetesResourceMatcherTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/SSABasedGenericKubernetesResourceMatcherTest.java @@ -30,7 +30,7 @@ class SSABasedGenericKubernetesResourceMatcherTest { - private final Context mockedContext = mock(); + private final Context mockedContext = mock(); private final SSABasedGenericKubernetesResourceMatcher matcher = SSABasedGenericKubernetesResourceMatcher.getInstance(); @@ -325,8 +325,8 @@ void testSanitizeState_daemonSet_withResourceTypeMismatch() { void testCustomMatcher_returnsExpectedMatchBasedOnReadOnlyLabel(boolean readOnly) { var dr = new ConfigMapDR(); dr.configureWith( - new KubernetesDependentResourceConfigBuilder() - .withSSAMatcher(new ReadOnlyAwareMatcher()) + new KubernetesDependentResourceConfigBuilder() + .withSSAMatcher(new ReadOnlyAwareMatcher<>()) .build()); var desiredConfigMap = loadResource("configmap.empty-owner-reference-desired.yaml", ConfigMap.class); @@ -334,14 +334,8 @@ void testCustomMatcher_returnsExpectedMatchBasedOnReadOnlyLabel(boolean readOnly var actualConfigMap = loadResource("configmap.empty-owner-reference.yaml", ConfigMap.class); actualConfigMap.getMetadata().getLabels().put("readonly", Boolean.toString(readOnly)); - ConfigMap ignoredPrimary = null; - assertThat( - dr.match( - actualConfigMap, - desiredConfigMap, - ignoredPrimary, - (Context) mockedContext) - .matched()) + HasMetadata primary = mock(); + assertThat(dr.match(actualConfigMap, desiredConfigMap, primary, mockedContext).matched()) .isEqualTo(readOnly); } @@ -391,7 +385,7 @@ private static R loadResource(String fileName, Class clazz) { clazz, SSABasedGenericKubernetesResourceMatcherTest.class, fileName); } - private static class ConfigMapDR extends KubernetesDependentResource { + private static class ConfigMapDR extends KubernetesDependentResource { public ConfigMapDR() { super(ConfigMap.class); } From a25ddb132c23b6e30de37c524c31f6e885083696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Wed, 22 Oct 2025 12:57:35 +0200 Subject: [PATCH 08/13] improve: showcase issue where updating the spec with SSA removes the finalizer (#2848) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- .../SSASpecUpdateCustomResource.java | 14 ++++++ .../SSASpecUpdateCustomResourceSpec.java | 14 ++++++ .../SSASpecUpdateCustomResourceStatus.java | 15 ++++++ .../ssaissue/specupdate/SSASpecUpdateIT.java | 41 ++++++++++++++++ .../specupdate/SSASpecUpdateReconciler.java | 47 +++++++++++++++++++ 5 files changed, 131 insertions(+) create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateCustomResource.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateCustomResourceSpec.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateCustomResourceStatus.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateIT.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateReconciler.java diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateCustomResource.java new file mode 100644 index 0000000000..c4ee2dd1a5 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateCustomResource.java @@ -0,0 +1,14 @@ +package io.javaoperatorsdk.operator.baseapi.ssaissue.specupdate; + +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("ssul") +public class SSASpecUpdateCustomResource + extends CustomResource + implements Namespaced {} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateCustomResourceSpec.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateCustomResourceSpec.java new file mode 100644 index 0000000000..47953ccce0 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateCustomResourceSpec.java @@ -0,0 +1,14 @@ +package io.javaoperatorsdk.operator.baseapi.ssaissue.specupdate; + +public class SSASpecUpdateCustomResourceSpec { + + 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/baseapi/ssaissue/specupdate/SSASpecUpdateCustomResourceStatus.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateCustomResourceStatus.java new file mode 100644 index 0000000000..e5f103dc69 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateCustomResourceStatus.java @@ -0,0 +1,15 @@ +package io.javaoperatorsdk.operator.baseapi.ssaissue.specupdate; + +public class SSASpecUpdateCustomResourceStatus { + + private Integer value = 0; + + public Integer getValue() { + return value; + } + + public SSASpecUpdateCustomResourceStatus setValue(Integer value) { + this.value = value; + return this; + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateIT.java new file mode 100644 index 0000000000..9cccd32e3c --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateIT.java @@ -0,0 +1,41 @@ +package io.javaoperatorsdk.operator.baseapi.ssaissue.specupdate; + +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 SSASpecUpdateIT { + + public static final String TEST_RESOURCE_NAME = "test"; + + @RegisterExtension + LocallyRunOperatorExtension operator = + LocallyRunOperatorExtension.builder().withReconciler(SSASpecUpdateReconciler.class).build(); + + // showcases that if the spec of the resources is updated with SSA, but the finalizer + // is not explicitly added to the fresh resource, the update removes the finalizer + @Test + void showFinalizerRemovalWhenSpecUpdated() { + SSASpecUpdateCustomResource res = createResource(); + operator.create(res); + + await() + .untilAsserted( + () -> { + var actual = operator.get(SSASpecUpdateCustomResource.class, TEST_RESOURCE_NAME); + assertThat(actual.getSpec()).isNotNull(); + assertThat(actual.getFinalizers()).isEmpty(); + }); + } + + SSASpecUpdateCustomResource createResource() { + SSASpecUpdateCustomResource res = new SSASpecUpdateCustomResource(); + res.setMetadata(new ObjectMetaBuilder().withName(TEST_RESOURCE_NAME).build()); + return res; + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateReconciler.java new file mode 100644 index 0000000000..483060ad59 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/specupdate/SSASpecUpdateReconciler.java @@ -0,0 +1,47 @@ +package io.javaoperatorsdk.operator.baseapi.ssaissue.specupdate; + +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +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 SSASpecUpdateReconciler + implements Reconciler, Cleaner { + + @Override + public UpdateControl reconcile( + SSASpecUpdateCustomResource resource, Context context) { + + var copy = createFreshCopy(resource); + copy.getSpec().setValue("value"); + context + .getClient() + .resource(copy) + .fieldManager(context.getControllerConfiguration().fieldManager()) + .serverSideApply(); + + return UpdateControl.noUpdate(); + } + + SSASpecUpdateCustomResource createFreshCopy(SSASpecUpdateCustomResource resource) { + var res = new SSASpecUpdateCustomResource(); + res.setMetadata( + new ObjectMetaBuilder() + .withName(resource.getMetadata().getName()) + .withNamespace(resource.getMetadata().getNamespace()) + .build()); + res.setSpec(new SSASpecUpdateCustomResourceSpec()); + return res; + } + + @Override + public DeleteControl cleanup( + SSASpecUpdateCustomResource resource, Context context) { + + return DeleteControl.defaultDelete(); + } +} From 61ed0ef0ab00afd4aaf06d47f50f7e94699bdf37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Wed, 22 Oct 2025 16:57:25 +0200 Subject: [PATCH 09/13] improve: showcase initialized spec deleted when adding finalizer with SSA with same fieldManager (#2847) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Attila Mészáros --- .../SSAFinalizerIssueCustomResource.java | 13 ++++ .../finalizer/SSAFinalizerIssueIT.java | 66 +++++++++++++++++++ .../SSAFinalizerIssueReconciler.java | 26 ++++++++ .../finalizer/SSAFinalizerIssueSpec.java | 26 ++++++++ .../finalizer/SSAFinalizerIssueStatus.java | 19 ++++++ 5 files changed, 150 insertions(+) create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueCustomResource.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueIT.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueReconciler.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueSpec.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueStatus.java diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueCustomResource.java new file mode 100644 index 0000000000..0e31be2dfb --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueCustomResource.java @@ -0,0 +1,13 @@ +package io.javaoperatorsdk.operator.baseapi.ssaissue.finalizer; + +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("ssfi") +public class SSAFinalizerIssueCustomResource + extends CustomResource implements Namespaced {} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueIT.java new file mode 100644 index 0000000000..a830675518 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueIT.java @@ -0,0 +1,66 @@ +package io.javaoperatorsdk.operator.baseapi.ssaissue.finalizer; + +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.fabric8.kubernetes.client.dsl.base.PatchContext; +import io.fabric8.kubernetes.client.dsl.base.PatchType; +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 extension = + LocallyRunOperatorExtension.builder() + .withReconciler(new SSAFinalizerIssueReconciler()) + .build(); + + /** + * Showcases possibly a case with SSA: When the resource is created with the same field manager + * that used by the controller, when adding a finalizer, it deletes other parts of the spec. + */ + @Test + void addingFinalizerRemoveListValues() { + var fieldManager = + extension + .getRegisteredControllerForReconcile(SSAFinalizerIssueReconciler.class) + .getConfiguration() + .fieldManager(); + + extension + .getKubernetesClient() + .resource(testResource()) + .inNamespace(extension.getNamespace()) + .patch( + new PatchContext.Builder() + .withFieldManager(fieldManager) + .withForce(true) + .withPatchType(PatchType.SERVER_SIDE_APPLY) + .build()); + + await() + .untilAsserted( + () -> { + var actual = extension.get(SSAFinalizerIssueCustomResource.class, TEST_1); + assertThat(actual.getFinalizers()).hasSize(1); + assertThat(actual.getSpec()).isNull(); + }); + } + + 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/finalizer/SSAFinalizerIssueReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueReconciler.java new file mode 100644 index 0000000000..441819834a --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueReconciler.java @@ -0,0 +1,26 @@ +package io.javaoperatorsdk.operator.baseapi.ssaissue.finalizer; + +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/finalizer/SSAFinalizerIssueSpec.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueSpec.java new file mode 100644 index 0000000000..d1c9dd5966 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueSpec.java @@ -0,0 +1,26 @@ +package io.javaoperatorsdk.operator.baseapi.ssaissue.finalizer; + +import java.util.List; + +public class SSAFinalizerIssueSpec { + + private String value; + + private List list = null; + + 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/finalizer/SSAFinalizerIssueStatus.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueStatus.java new file mode 100644 index 0000000000..471372af40 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ssaissue/finalizer/SSAFinalizerIssueStatus.java @@ -0,0 +1,19 @@ +package io.javaoperatorsdk.operator.baseapi.ssaissue.finalizer; + +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 385f1a302381e20113eb7d50a7f07f6e1f69a4fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 08:24:41 +0100 Subject: [PATCH 10/13] chore(deps): bump org.apache.maven.plugin-tools:maven-plugin-annotations (#3023) Bumps [org.apache.maven.plugin-tools:maven-plugin-annotations](https://github.com/apache/maven-plugin-tools) from 3.15.1 to 3.15.2. - [Release notes](https://github.com/apache/maven-plugin-tools/releases) - [Commits](https://github.com/apache/maven-plugin-tools/compare/maven-plugin-tools-3.15.1...maven-plugin-tools-3.15.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugin-tools:maven-plugin-annotations dependency-version: 3.15.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- bootstrapper-maven-plugin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrapper-maven-plugin/pom.xml b/bootstrapper-maven-plugin/pom.xml index c306dcea35..659c52796e 100644 --- a/bootstrapper-maven-plugin/pom.xml +++ b/bootstrapper-maven-plugin/pom.xml @@ -14,7 +14,7 @@ Operator SDK - Bootstrapper Maven Plugin - 3.15.1 + 3.15.2 3.9.11 3.0.0 3.15.1 From 358ed4ee4e839f6ca5ba57e65f953e504df87fe5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 08:24:49 +0100 Subject: [PATCH 11/13] chore(deps): bump org.apache.maven.plugins:maven-plugin-plugin (#3022) Bumps [org.apache.maven.plugins:maven-plugin-plugin](https://github.com/apache/maven-plugin-tools) from 3.15.1 to 3.15.2. - [Release notes](https://github.com/apache/maven-plugin-tools/releases) - [Commits](https://github.com/apache/maven-plugin-tools/compare/maven-plugin-tools-3.15.1...maven-plugin-tools-3.15.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-plugin-plugin dependency-version: 3.15.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- bootstrapper-maven-plugin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrapper-maven-plugin/pom.xml b/bootstrapper-maven-plugin/pom.xml index 659c52796e..5952379112 100644 --- a/bootstrapper-maven-plugin/pom.xml +++ b/bootstrapper-maven-plugin/pom.xml @@ -17,7 +17,7 @@ 3.15.2 3.9.11 3.0.0 - 3.15.1 + 3.15.2 From 6127066bf52afd9dcd41f10cf239c89f6871b1ae Mon Sep 17 00:00:00 2001 From: Donnerbart Date: Mon, 27 Oct 2025 09:54:15 +0100 Subject: [PATCH 12/13] improve: Small health check improvements (#3021) Signed-off-by: David Sondermann --- ...nformerWrappingEventSourceHealthIndicator.java | 9 +++------ .../event/source/informer/InformerWrapper.java | 4 ++-- .../event/source/timer/TimerEventSource.java | 6 ++++++ .../source/polling/PollingEventSourceTest.java | 2 +- .../event/source/timer/TimerEventSourceTest.java | 15 ++++++++++++--- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/health/InformerWrappingEventSourceHealthIndicator.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/health/InformerWrappingEventSourceHealthIndicator.java index 2c337f3cd7..720ce0227c 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/health/InformerWrappingEventSourceHealthIndicator.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/health/InformerWrappingEventSourceHealthIndicator.java @@ -11,11 +11,8 @@ public interface InformerWrappingEventSourceHealthIndicator i.getStatus() != Status.HEALTHY) - .findAny(); - - return nonUp.isPresent() ? Status.UNHEALTHY : Status.HEALTHY; + var hasNonHealthy = + informerHealthIndicators().values().stream().anyMatch(i -> i.getStatus() != Status.HEALTHY); + return hasNonHealthy ? Status.UNHEALTHY : Status.HEALTHY; } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerWrapper.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerWrapper.java index c07ffdbf46..2bb6dcbc75 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerWrapper.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerWrapper.java @@ -204,8 +204,8 @@ public boolean isRunning() { public Status getStatus() { var status = isRunning() && hasSynced() && isWatching() ? Status.HEALTHY : Status.UNHEALTHY; log.debug( - "Informer status: {} for for type: {}, namespace: {}, details[ is running: {}, has synced:" - + " {}, is watching: {} ]", + "Informer status: {} for type: {}, namespace: {}, details [is running: {}, has synced: {}," + + " is watching: {}]", status, informer.getApiTypeClass().getSimpleName(), namespaceIdentifier, diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/timer/TimerEventSource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/timer/TimerEventSource.java index 53c0d328a8..a6801b5f39 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/timer/TimerEventSource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/timer/TimerEventSource.java @@ -10,6 +10,7 @@ import org.slf4j.LoggerFactory; import io.fabric8.kubernetes.api.model.HasMetadata; +import io.javaoperatorsdk.operator.health.Status; import io.javaoperatorsdk.operator.processing.event.Event; import io.javaoperatorsdk.operator.processing.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.AbstractEventSource; @@ -77,6 +78,11 @@ public void stop() { } } + @Override + public Status getStatus() { + return isRunning() ? Status.HEALTHY : Status.UNHEALTHY; + } + @Override public Set getSecondaryResources(HasMetadata primary) { return Set.of(); diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingEventSourceTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingEventSourceTest.java index 0f7d26446d..448537e9aa 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingEventSourceTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/polling/PollingEventSourceTest.java @@ -87,7 +87,7 @@ void propagatesEventOnNewResourceForPrimary() throws InterruptedException { } @Test - void updatesHealthIndicatorBasedOnExceptionsInFetcher() throws InterruptedException { + void updatesHealthIndicatorBasedOnExceptionsInFetcher() { when(resourceFetcher.fetchResources()).thenReturn(testResponseWithOneValue()); pollingEventSource.start(); assertThat(pollingEventSource.getStatus()).isEqualTo(Status.HEALTHY); diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/timer/TimerEventSourceTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/timer/TimerEventSourceTest.java index 9396411777..825bc6adab 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/timer/TimerEventSourceTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/timer/TimerEventSourceTest.java @@ -1,6 +1,5 @@ package io.javaoperatorsdk.operator.processing.event.source.timer; -import java.io.IOException; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeUnit; @@ -12,6 +11,7 @@ import org.junit.jupiter.api.Test; import io.javaoperatorsdk.operator.TestUtils; +import io.javaoperatorsdk.operator.health.Status; import io.javaoperatorsdk.operator.processing.event.Event; import io.javaoperatorsdk.operator.processing.event.EventHandler; import io.javaoperatorsdk.operator.processing.event.ResourceID; @@ -42,6 +42,7 @@ public void schedulesOnce() { untilAsserted(() -> assertThat(eventHandler.events).hasSize(1)); untilAsserted(PERIOD * 2, 0, () -> assertThat(eventHandler.events).hasSize(1)); + assertThat(source.getStatus()).isEqualTo(Status.HEALTHY); } @Test @@ -52,6 +53,7 @@ public void canCancelOnce() { source.cancelOnceSchedule(resourceID); untilAsserted(() -> assertThat(eventHandler.events).isEmpty()); + assertThat(source.getStatus()).isEqualTo(Status.HEALTHY); } @Test @@ -62,6 +64,7 @@ public void canRescheduleOnceEvent() { source.scheduleOnce(resourceID, 2 * PERIOD); untilAsserted(PERIOD * 2, PERIOD, () -> assertThat(eventHandler.events).hasSize(1)); + assertThat(source.getStatus()).isEqualTo(Status.HEALTHY); } @Test @@ -72,23 +75,29 @@ public void deRegistersOnceEventSources() { source.onResourceDeleted(customResource); untilAsserted(() -> assertThat(eventHandler.events).isEmpty()); + assertThat(source.getStatus()).isEqualTo(Status.HEALTHY); } @Test - public void eventNotRegisteredIfStopped() throws IOException { + public void eventNotRegisteredIfStopped() { var resourceID = ResourceID.fromResource(TestUtils.testCustomResource()); + assertThat(source.getStatus()).isEqualTo(Status.HEALTHY); source.stop(); assertThatExceptionOfType(IllegalStateException.class) .isThrownBy(() -> source.scheduleOnce(resourceID, PERIOD)); + assertThat(source.getStatus()).isEqualTo(Status.UNHEALTHY); } @Test - public void eventNotFiredIfStopped() throws IOException { + public void eventNotFiredIfStopped() { source.scheduleOnce(ResourceID.fromResource(TestUtils.testCustomResource()), PERIOD); + assertThat(source.getStatus()).isEqualTo(Status.HEALTHY); + source.stop(); untilAsserted(() -> assertThat(eventHandler.events).isEmpty()); + assertThat(source.getStatus()).isEqualTo(Status.UNHEALTHY); } private void untilAsserted(ThrowingRunnable assertion) { From 1c881f55757fa768b085bbff234ecf0dc80e9a87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Oct 2025 08:45:51 +0100 Subject: [PATCH 13/13] chore(deps): bump com.github.ben-manes.caffeine:caffeine (#3025) Bumps [com.github.ben-manes.caffeine:caffeine](https://github.com/ben-manes/caffeine) from 3.2.2 to 3.2.3. - [Release notes](https://github.com/ben-manes/caffeine/releases) - [Commits](https://github.com/ben-manes/caffeine/compare/v3.2.2...v3.2.3) --- updated-dependencies: - dependency-name: com.github.ben-manes.caffeine:caffeine dependency-version: 3.2.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 303c11f79b..ca4dd282d6 100644 --- a/pom.xml +++ b/pom.xml @@ -64,7 +64,7 @@ 4.3.0 2.7.3 1.15.5 - 3.2.2 + 3.2.3 0.9.14 2.20.0 4.16