Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
851f281
improve: add license headers to source files (#2980)
csviri Oct 9, 2025
9b63ec9
chore: version to 5.3.0-SNAPSHOT
csviri Oct 14, 2025
be59b6e
Annotation removal using locking (#3015)
shawkins Oct 30, 2025
ee97e61
improve: complete comparable resource version configs (#3027)
csviri Nov 13, 2025
ee73dd9
improve: run pr-s checks for v5.3 (#3042)
csviri Nov 17, 2025
896ae6a
fix: rebase on main after release
csviri Dec 1, 2025
9e61b20
fix(javadoc): invalid method ref blocks snapshot release (#3076)
csviri Dec 1, 2025
f2cfcf9
feat: record desired state in Context (#3082)
metacosm Dec 3, 2025
363c003
improve: rename junit5 module to junit (#3081)
csviri Dec 4, 2025
c7b4f8b
fix: delete empty files result of rebase on main (#3093)
csviri Dec 15, 2025
9986c1e
feat: ReconcileUtils for strongly consistent updates (#3106)
csviri Jan 15, 2026
90cc671
Event filtering now records resource action and previous resource (#3…
csviri Jan 21, 2026
f852af5
improve: facelift samples to use ReconcileUtils (#3135)
csviri Jan 27, 2026
f105902
improve: move compare resource version methods to internal utils (#3137)
csviri Jan 28, 2026
a3bc9e7
feat: move ReconcileUtils methods to ResourceOperations accessible fr…
csviri Feb 2, 2026
0f632f8
improve: KubernetesDependentResource uses resource operations directl…
csviri Feb 2, 2026
b226145
feat: provide de-duplicated secondary resources stream on Context (#3…
metacosm Feb 3, 2026
1b2ff9c
docs: improve mermaid flowchart visual
csviri Feb 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/e2e-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ on:
paths-ignore:
- 'docs/**'
- 'adr/**'
branches: [ main, next ]
branches: [ main, next, v5.3 ]
push:
paths-ignore:
- 'docs/**'
- 'adr/**'
branches:
- main
- next
- v5.3

jobs:
sample_operators_tests:
Expand Down
2 changes: 1 addition & 1 deletion bootstrapper-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>java-operator-sdk</artifactId>
<version>5.2.3-SNAPSHOT</version>
<version>5.3.0-SNAPSHOT</version>
</parent>

<artifactId>bootstrapper</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
</dependency>
<dependency>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework-junit-5</artifactId>
<artifactId>operator-framework-junit</artifactId>
<version>${josdk.version}</version>
<scope>test</scope>
</dependency>
Expand Down
4 changes: 2 additions & 2 deletions caffeine-bounded-cache-support/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<parent>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>java-operator-sdk</artifactId>
<version>5.2.3-SNAPSHOT</version>
<version>5.3.0-SNAPSHOT</version>
</parent>

<artifactId>caffeine-bounded-cache-support</artifactId>
Expand All @@ -43,7 +43,7 @@
</dependency>
<dependency>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework-junit-5</artifactId>
<artifactId>operator-framework-junit</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,26 @@ each secondary resource:

```mermaid
flowchart TD

compute[Compute desired secondary resource based on primary state] --> A
A{Secondary resource exists?}
A -- Yes --> match
A -- No --> Create --> Done

match{Matches desired state?}
match -- Yes --> Done
match -- No --> Update --> Done
Start([Start Reconciliation]) --> Compute
Compute[Compute desired secondary<br/>resource based on<br/>primary state] --> Exists
Exists{Secondary<br/>resource<br/>exists?}
Exists -->|No| Create[Create Resource]
Exists -->|Yes| Match
Match{Matches<br/>desired<br/>state?}
Match -->|Yes| Done
Match -->|No| Update[Update Resource]
Create --> Done([Done])
Update --> Done

classDef startEnd fill:#e1f5e1,stroke:#4caf50,stroke-width:2px
classDef compute fill:#e3f2fd,stroke:#2196f3,stroke-width:2px
classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:2px
classDef action fill:#f3e5f5,stroke:#9c27b0,stroke-width:2px

class Start,Done startEnd
class Compute compute
class Exists,Match decision
class Create,Update action
```

While these steps are not difficult in and of themselves, there are some subtleties that can lead to
Expand Down
29 changes: 29 additions & 0 deletions docs/content/en/docs/migration/v5-3-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
title: Migrating from v5.2 to v5.3
description: Migrating from v5.2 to v5.3
---


## Renamed JUnit Module

If you use JUnit extension in your test just rename it from:

```
<dependency>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework-junit-5</artifactId>
<version>5.2.x<version>
<scope>test</scope>
</dependency>
```

to

```
<dependency>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework-junit</artifactId>
<version>5.3.0<version>
<scope>test</scope>
</dependency>
```
4 changes: 2 additions & 2 deletions micrometer-support/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<parent>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>java-operator-sdk</artifactId>
<version>5.2.3-SNAPSHOT</version>
<version>5.3.0-SNAPSHOT</version>
</parent>

<artifactId>micrometer-support</artifactId>
Expand Down Expand Up @@ -58,7 +58,7 @@
</dependency>
<dependency>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework-junit-5</artifactId>
<artifactId>operator-framework-junit</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
Expand Down
6 changes: 3 additions & 3 deletions operator-framework-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework-bom</artifactId>
<version>5.2.3-SNAPSHOT</version>
<version>5.3.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Operator SDK - Bill of Materials</name>
<description>Java SDK for implementing Kubernetes operators</description>
Expand Down Expand Up @@ -55,7 +55,7 @@
<maven-source-plugin.version>3.4.0</maven-source-plugin.version>
<maven-javadoc-plugin.version>3.12.0</maven-javadoc-plugin.version>
<spotless.version>3.1.0</spotless.version>
<central-publishing-maven-plugin.version>0.10.0</central-publishing-maven-plugin.version>
<central-publishing-maven-plugin.version>0.9.0</central-publishing-maven-plugin.version>
</properties>

<dependencyManagement>
Expand All @@ -77,7 +77,7 @@
</dependency>
<dependency>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework-junit-5</artifactId>
<artifactId>operator-framework-junit</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
Expand Down
2 changes: 1 addition & 1 deletion operator-framework-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<parent>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>java-operator-sdk</artifactId>
<version>5.2.3-SNAPSHOT</version>
<version>5.3.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ public <P extends HasMetadata> RegisteredController<P> register(
"Cannot register reconciler with name "
+ reconciler.getClass().getCanonicalName()
+ " reconciler named "
+ ReconcilerUtils.getNameFor(reconciler)
+ ReconcilerUtilsInternal.getNameFor(reconciler)
+ " because its configuration cannot be found.\n"
+ " Known reconcilers are: "
+ configurationService.getKnownReconcilerNames());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@
import io.fabric8.kubernetes.client.utils.Serialization;
import io.javaoperatorsdk.operator.api.reconciler.Constants;
import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
import io.javaoperatorsdk.operator.api.reconciler.NonComparableResourceVersionException;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;

@SuppressWarnings("rawtypes")
public class ReconcilerUtils {
public class ReconcilerUtilsInternal {

private static final String FINALIZER_NAME_SUFFIX = "/finalizer";
protected static final String MISSING_GROUP_SUFFIX = ".javaoperatorsdk.io";
Expand All @@ -46,7 +47,7 @@ public class ReconcilerUtils {
Pattern.compile(".*http(s?)://[^/]*/api(s?)/(\\S*).*"); // NOSONAR: input is controlled

// prevent instantiation of util class
private ReconcilerUtils() {}
private ReconcilerUtilsInternal() {}

public static boolean isFinalizerValid(String finalizer) {
return HasMetadata.validateFinalizer(finalizer);
Expand Down Expand Up @@ -241,4 +242,123 @@ private static boolean matchesResourceType(
}
return false;
}

/**
* Compares resource versions of two resources. This is a convenience method that extracts the
* resource versions from the metadata and delegates to {@link
* #validateAndCompareResourceVersions(String, String)}.
*
* @param h1 first resource
* @param h2 second resource
* @return negative if h1 is older, zero if equal, positive if h1 is newer
* @throws NonComparableResourceVersionException if either resource version is invalid
*/
public static int validateAndCompareResourceVersions(HasMetadata h1, HasMetadata h2) {
return validateAndCompareResourceVersions(
h1.getMetadata().getResourceVersion(), h2.getMetadata().getResourceVersion());
}

/**
* Compares the resource versions of two Kubernetes resources.
*
* <p>This method extracts the resource versions from the metadata of both resources and delegates
* to {@link #compareResourceVersions(String, String)} for the actual comparison.
*
* @param h1 the first resource to compare
* @param h2 the second resource to compare
* @return a negative integer if h1's version is less than h2's version, zero if they are equal,
* or a positive integer if h1's version is greater than h2's version
* @see #compareResourceVersions(String, String)
*/
public static int compareResourceVersions(HasMetadata h1, HasMetadata h2) {
return compareResourceVersions(
h1.getMetadata().getResourceVersion(), h2.getMetadata().getResourceVersion());
}

/**
* Compares two resource version strings using a length-first, then lexicographic comparison
* algorithm.
*
* <p>The comparison is performed in two steps:
*
* <ol>
* <li>First, compare the lengths of the version strings. A longer version string is considered
* greater than a shorter one. This works correctly for numeric versions because larger
* numbers have more digits (e.g., "100" > "99").
* <li>If the lengths are equal, perform a character-by-character lexicographic comparison until
* a difference is found.
* </ol>
*
* <p>This algorithm is more efficient than parsing the versions as numbers, especially for
* Kubernetes resource versions which are typically monotonically increasing numeric strings.
*
* <p><strong>Note:</strong> This method does not validate that the input strings are numeric. For
* validated numeric comparison, use {@link #validateAndCompareResourceVersions(String, String)}.
*
* @param v1 the first resource version string
* @param v2 the second resource version string
* @return a negative integer if v1 is less than v2, zero if they are equal, or a positive integer
* if v1 is greater than v2
* @see #validateAndCompareResourceVersions(String, String)
*/
public static int compareResourceVersions(String v1, String v2) {
int comparison = v1.length() - v2.length();
if (comparison != 0) {
return comparison;
}
for (int i = 0; i < v2.length(); i++) {
int comp = v1.charAt(i) - v2.charAt(i);
if (comp != 0) {
return comp;
}
}
return 0;
}

/**
* Compares two Kubernetes resource versions numerically. Kubernetes resource versions are
* expected to be numeric strings that increase monotonically. This method assumes both versions
* are valid numeric strings without leading zeros.
*
* @param v1 first resource version
* @param v2 second resource version
* @return negative if v1 is older, zero if equal, positive if v1 is newer
* @throws NonComparableResourceVersionException if either resource version is empty, has leading
* zeros, or contains non-numeric characters
*/
public static int validateAndCompareResourceVersions(String v1, String v2) {
int v1Length = validateResourceVersion(v1);
int v2Length = validateResourceVersion(v2);
int comparison = v1Length - v2Length;
if (comparison != 0) {
return comparison;
}
for (int i = 0; i < v2Length; i++) {
int comp = v1.charAt(i) - v2.charAt(i);
if (comp != 0) {
return comp;
}
}
return 0;
}

private static int validateResourceVersion(String v1) {
int v1Length = v1.length();
if (v1Length == 0) {
throw new NonComparableResourceVersionException("Resource version is empty");
}
for (int i = 0; i < v1Length; i++) {
char char1 = v1.charAt(i);
if (char1 == '0') {
if (i == 0) {
throw new NonComparableResourceVersionException(
"Resource version cannot begin with 0: " + v1);
}
} else if (char1 < '0' || char1 > '9') {
throw new NonComparableResourceVersionException(
"Non numeric characters in resource version: " + v1);
}
}
return v1Length;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.javaoperatorsdk.operator.ReconcilerUtils;
import io.javaoperatorsdk.operator.ReconcilerUtilsInternal;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;

/**
Expand Down Expand Up @@ -145,7 +145,7 @@ private String getReconcilersNameMessage() {
}

protected <R extends HasMetadata> String keyFor(Reconciler<R> reconciler) {
return ReconcilerUtils.getNameFor(reconciler);
return ReconcilerUtilsInternal.getNameFor(reconciler);
}

@SuppressWarnings("unused")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.javaoperatorsdk.operator.ReconcilerUtils;
import io.javaoperatorsdk.operator.ReconcilerUtilsInternal;
import io.javaoperatorsdk.operator.api.config.Utils.Configurator;
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfigurationResolver;
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec;
Expand Down Expand Up @@ -265,7 +265,7 @@ private <P extends HasMetadata> ResolvedControllerConfiguration<P> controllerCon
io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration annotation) {
final var resourceClass = getResourceClassResolver().getPrimaryResourceClass(reconcilerClass);

final var name = ReconcilerUtils.getNameFor(reconcilerClass);
final var name = ReconcilerUtilsInternal.getNameFor(reconcilerClass);
final var generationAware =
valueOrDefaultFromAnnotation(
annotation,
Expand Down
Loading