diff --git a/.github/workflows/hugo.yaml b/.github/workflows/hugo.yaml
index 2c0a63d50d..50a2d83182 100644
--- a/.github/workflows/hugo.yaml
+++ b/.github/workflows/hugo.yaml
@@ -45,6 +45,16 @@ jobs:
with:
submodules: recursive
fetch-depth: 0
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+ cache: maven
+ - name: Build test-index-processor and generate test documentation
+ run: |
+ ./mvnw clean install -DskipTests -pl test-index-processor
+ ./mvnw process-test-classes -DskipTests -pl operator-framework
- name: Setup Pages
id: pages
uses: actions/configure-pages@v5
diff --git a/operator-framework/pom.xml b/operator-framework/pom.xml
index 1cf2a0aa9e..6dc9549be0 100644
--- a/operator-framework/pom.xml
+++ b/operator-framework/pom.xml
@@ -84,6 +84,13 @@
kube-api-test-client-inject
test
+
+ io.javaoperatorsdk
+ test-index-processor
+ ${project.version}
+ test
+ true
+
@@ -106,6 +113,23 @@
+
+
+ default-testCompile
+
+ testCompile
+
+ test-compile
+
+
+
+ io.javaoperatorsdk
+ test-index-processor
+ ${project.version}
+
+
+
+
@@ -138,6 +162,50 @@
org.apache.maven.plugins
maven-surefire-plugin
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+
+
+ copy-samples-to-docs
+
+ copy-resources
+
+ process-test-classes
+
+ ${project.basedir}/../docs/content/en/docs/testindex
+
+
+ ${project.build.directory}/generated-test-sources/test-annotations
+
+ samples.md
+
+ false
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+ 3.1.0
+
+
+ rename-samples-to-index
+
+ run
+
+ process-test-classes
+
+
+
+
+
+
+
+
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/CRDMappingInTestExtensionIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/CRDMappingInTestExtensionIT.java
index 9153ae4ff5..62f5508731 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/CRDMappingInTestExtensionIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/CRDMappingInTestExtensionIT.java
@@ -12,6 +12,7 @@
import io.fabric8.kubernetes.model.annotation.Group;
import io.fabric8.kubernetes.model.annotation.Kind;
import io.fabric8.kubernetes.model.annotation.Version;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
@@ -21,6 +22,15 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Custom CRD Mapping in Test Extension",
+ description =
+ """
+ Demonstrates how to manually specify and apply Custom Resource Definitions (CRDs) in \
+ integration tests using the LocallyRunOperatorExtension. This test verifies that CRDs \
+ can be loaded from specified file paths and properly registered with the Kubernetes API \
+ server during test execution.
+ """)
public class CRDMappingInTestExtensionIT {
private final KubernetesClient client = new KubernetesClientBuilder().build();
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ConcurrencyIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ConcurrencyIT.java
index 80fb09095d..3a336bfb6b 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ConcurrencyIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ConcurrencyIT.java
@@ -10,6 +10,7 @@
import org.slf4j.LoggerFactory;
import io.fabric8.kubernetes.api.model.ConfigMap;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.baseapi.simple.TestCustomResource;
import io.javaoperatorsdk.operator.baseapi.simple.TestReconciler;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
@@ -18,6 +19,15 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Concurrent Reconciliation of Multiple Resources",
+ description =
+ """
+ Demonstrates the operator's ability to handle concurrent reconciliation of multiple \
+ resources. The test creates, updates, and deletes many resources simultaneously to \
+ verify proper handling of concurrent operations, ensuring thread safety and correct \
+ resource state management under load.
+ """)
class ConcurrencyIT {
public static final int NUMBER_OF_RESOURCES_CREATED = 50;
public static final int NUMBER_OF_RESOURCES_DELETED = 30;
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/InformerErrorHandlerStartIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/InformerErrorHandlerStartIT.java
index 18a107d9b2..f018ba44e7 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/InformerErrorHandlerStartIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/InformerErrorHandlerStartIT.java
@@ -9,12 +9,22 @@
import io.fabric8.kubernetes.client.ConfigBuilder;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.Operator;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+@Sample(
+ tldr = "Operator Startup with Informer Errors",
+ description =
+ """
+ Demonstrates that the operator can start successfully even when informers encounter \
+ errors during startup, such as insufficient access rights. By setting \
+ stopOnInformerErrorDuringStartup to false, the operator gracefully handles permission \
+ errors and continues initialization, allowing it to operate with partial access.
+ """)
class InformerErrorHandlerStartIT {
/** Test showcases that the operator starts even if there is no access right for some resource. */
@Test
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/LeaderElectionPermissionIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/LeaderElectionPermissionIT.java
index 51b1f4b3d5..4ff7e9c295 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/LeaderElectionPermissionIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/LeaderElectionPermissionIT.java
@@ -8,6 +8,7 @@
import io.fabric8.kubernetes.client.ConfigBuilder;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.Operator;
import io.javaoperatorsdk.operator.OperatorException;
import io.javaoperatorsdk.operator.ReconcilerUtils;
@@ -21,6 +22,15 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
+@Sample(
+ tldr = "Leader Election with Insufficient Permissions",
+ description =
+ """
+ Verifies that the operator fails gracefully when leader election is configured but \
+ the service account lacks permissions to access lease resources. This test ensures \
+ proper error handling and messaging when RBAC permissions are insufficient for \
+ leader election functionality.
+ """)
class LeaderElectionPermissionIT {
KubernetesClient adminClient = new KubernetesClientBuilder().build();
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/builtinresourcecleaner/BuiltInResourceCleanerIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/builtinresourcecleaner/BuiltInResourceCleanerIT.java
index 9d914d080c..94ee5325e3 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/builtinresourcecleaner/BuiltInResourceCleanerIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/builtinresourcecleaner/BuiltInResourceCleanerIT.java
@@ -8,6 +8,7 @@
import org.slf4j.LoggerFactory;
import io.fabric8.kubernetes.api.model.Service;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.ReconcilerUtils;
import io.javaoperatorsdk.operator.dependent.standalonedependent.StandaloneDependentResourceIT;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
@@ -15,6 +16,15 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Cleanup handler for built-in Kubernetes resources",
+ description =
+ """
+ Demonstrates how to implement cleanup handlers (finalizers) for built-in Kubernetes \
+ resources like Service and Pod. These resources don't use generation the same way \
+ as custom resources, so this sample shows the proper approach to handle their \
+ lifecycle and cleanup logic.
+ """)
class BuiltInResourceCleanerIT {
private static final Logger log = LoggerFactory.getLogger(BuiltInResourceCleanerIT.class);
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/changenamespace/ChangeNamespaceIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/changenamespace/ChangeNamespaceIT.java
index 67f65c64ca..478f351d94 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/changenamespace/ChangeNamespaceIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/changenamespace/ChangeNamespaceIT.java
@@ -14,6 +14,7 @@
import io.fabric8.kubernetes.api.model.NamespaceBuilder;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.client.KubernetesClient;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.RegisteredController;
import io.javaoperatorsdk.operator.api.reconciler.Constants;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
@@ -21,6 +22,16 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Dynamically Changing Watched Namespaces",
+ description =
+ """
+ Demonstrates how to dynamically change the set of namespaces that an operator watches at \
+ runtime. This feature allows operators to add or remove namespaces from their watch \
+ list, including switching between specific namespaces and watching all namespaces. \
+ The test verifies that resources in newly added namespaces are reconciled and \
+ resources in removed namespaces are no longer watched.
+ """)
class ChangeNamespaceIT {
public static final String TEST_RESOURCE_NAME_1 = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/cleanerforreconciler/CleanerForReconcilerIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/cleanerforreconciler/CleanerForReconcilerIT.java
index 6ccb34f0e3..03fa506d07 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/cleanerforreconciler/CleanerForReconcilerIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/cleanerforreconciler/CleanerForReconcilerIT.java
@@ -4,11 +4,23 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMeta;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Implementing Cleanup Logic with Cleaner Interface",
+ description =
+ """
+ Demonstrates how to implement cleanup logic for custom resources using the Cleaner \
+ interface. When a reconciler implements Cleaner, the framework automatically adds a \
+ finalizer to resources and calls the cleanup method when the resource is deleted. \
+ This pattern is useful for cleaning up external resources or performing custom \
+ deletion logic. The test verifies finalizer handling, cleanup execution, and the \
+ ability to reschedule cleanup operations.
+ """)
class CleanerForReconcilerIT {
public static final String TEST_RESOURCE_NAME = "cleaner-for-reconciler-test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/cleanupconflict/CleanupConflictIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/cleanupconflict/CleanupConflictIT.java
index 19ef6df9a0..0993f76c8f 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/cleanupconflict/CleanupConflictIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/cleanupconflict/CleanupConflictIT.java
@@ -6,12 +6,21 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMeta;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.baseapi.cleanupconflict.CleanupConflictReconciler.WAIT_TIME;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Cleanup Finalizer Removal Without Conflicts",
+ description =
+ """
+ Tests that finalizers are removed correctly during cleanup without causing conflicts, \
+ even when multiple finalizers are present and removed concurrently. This verifies the \
+ operator's ability to handle finalizer updates safely during resource deletion.
+ """)
class CleanupConflictIT {
private static final String ADDITIONAL_FINALIZER = "javaoperatorsdk.io/additionalfinalizer";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/clusterscopedresource/ClusterScopedResourceIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/clusterscopedresource/ClusterScopedResourceIT.java
index 4c92fbada7..2a690035da 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/clusterscopedresource/ClusterScopedResourceIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/clusterscopedresource/ClusterScopedResourceIT.java
@@ -7,12 +7,22 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.IntegrationTestConstants.GARBAGE_COLLECTION_TIMEOUT_SECONDS;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Cluster-scoped resource reconciliation",
+ description =
+ """
+ Demonstrates how to reconcile cluster-scoped custom resources (non-namespaced). This \
+ test shows CRUD operations on cluster-scoped resources and verifies that \
+ dependent resources are created, updated, and properly cleaned up when the \
+ primary resource is deleted.
+ """)
class ClusterScopedResourceIT {
public static final String TEST_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/concurrentfinalizerremoval/ConcurrentFinalizerRemovalIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/concurrentfinalizerremoval/ConcurrentFinalizerRemovalIT.java
index da166ce2c1..d83c1b1b79 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/concurrentfinalizerremoval/ConcurrentFinalizerRemovalIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/concurrentfinalizerremoval/ConcurrentFinalizerRemovalIT.java
@@ -6,12 +6,22 @@
import org.slf4j.LoggerFactory;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import io.javaoperatorsdk.operator.processing.retry.GenericRetry;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Concurrent Finalizer Removal by Multiple Reconcilers",
+ description =
+ """
+ Demonstrates safe concurrent finalizer removal when multiple reconcilers manage the \
+ same resource with different finalizers. Tests that finalizers can be removed \
+ concurrently without conflicts or race conditions, ensuring proper cleanup even when \
+ multiple controllers are involved.
+ """)
class ConcurrentFinalizerRemovalIT {
private static final Logger log = LoggerFactory.getLogger(ConcurrentFinalizerRemovalIT.class);
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/createupdateeventfilter/CreateUpdateInformerEventSourceEventFilterIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/createupdateeventfilter/CreateUpdateInformerEventSourceEventFilterIT.java
index 2d9a7db573..38cdb8726b 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/createupdateeventfilter/CreateUpdateInformerEventSourceEventFilterIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/createupdateeventfilter/CreateUpdateInformerEventSourceEventFilterIT.java
@@ -7,12 +7,22 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMeta;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.baseapi.createupdateeventfilter.CreateUpdateEventFilterTestReconciler.CONFIG_MAP_TEST_DATA_KEY;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Event filtering for create and update operations",
+ description =
+ """
+ Shows how to configure event filters on informer event sources to control which create and \
+ update events trigger reconciliation. This is useful for preventing unnecessary \
+ reconciliation loops when dependent resources are modified by the controller \
+ itself.
+ """)
class CreateUpdateInformerEventSourceEventFilterIT {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/createupdateeventfilter/PreviousAnnotationDisabledIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/createupdateeventfilter/PreviousAnnotationDisabledIT.java
index b5554493ee..90ba1d9cb1 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/createupdateeventfilter/PreviousAnnotationDisabledIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/createupdateeventfilter/PreviousAnnotationDisabledIT.java
@@ -3,8 +3,17 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
+@Sample(
+ tldr = "Event Filtering with Previous Annotation Disabled",
+ description =
+ """
+ Tests event filtering behavior when the previous annotation feature for dependent \
+ resources is disabled. Verifies that update events are properly received and handled \
+ even without the annotation tracking mechanism that compares previous resource states.
+ """)
class PreviousAnnotationDisabledIT {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/deployment/KubernetesResourceStatusUpdateIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/deployment/KubernetesResourceStatusUpdateIT.java
index 5fe9bfa939..fc6ee36387 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/deployment/KubernetesResourceStatusUpdateIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/deployment/KubernetesResourceStatusUpdateIT.java
@@ -17,12 +17,23 @@
import io.fabric8.kubernetes.api.model.PodTemplateSpec;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.apps.DeploymentSpec;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.baseapi.deployment.DeploymentReconciler.STATUS_MESSAGE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Reconciling Non-Custom Kubernetes Resources with Status Updates",
+ description =
+ """
+ Demonstrates how to reconcile standard Kubernetes resources (like Deployments) instead of \
+ custom resources, and how to update their status subresource. This pattern is useful when \
+ building operators that manage native Kubernetes resources rather than custom resource \
+ definitions. The test verifies that the operator can watch, reconcile, and update the \
+ status of a Deployment resource.
+ """)
class KubernetesResourceStatusUpdateIT {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/dynamicgenericeventsourceregistration/DynamicGenericEventSourceRegistrationIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/dynamicgenericeventsourceregistration/DynamicGenericEventSourceRegistrationIT.java
index 5c05850b4a..c9e1fbc713 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/dynamicgenericeventsourceregistration/DynamicGenericEventSourceRegistrationIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/dynamicgenericeventsourceregistration/DynamicGenericEventSourceRegistrationIT.java
@@ -8,11 +8,21 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.Secret;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Dynamic Generic Event Source Registration",
+ description =
+ """
+ Demonstrates dynamic registration of generic event sources during runtime. The test \
+ verifies that event sources can be dynamically added to a reconciler and properly \
+ trigger reconciliation when the associated resources change, enabling flexible event \
+ source management.
+ """)
class DynamicGenericEventSourceRegistrationIT {
public static final String TEST_RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/errorstatushandler/ErrorStatusHandlerIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/errorstatushandler/ErrorStatusHandlerIT.java
index b888143d2d..9ee3df10e1 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/errorstatushandler/ErrorStatusHandlerIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/errorstatushandler/ErrorStatusHandlerIT.java
@@ -6,12 +6,22 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import io.javaoperatorsdk.operator.processing.retry.GenericRetry;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Error Status Handler for Failed Reconciliations",
+ description =
+ """
+ Demonstrates how to implement error status handlers that update resource status when \
+ reconciliations fail. The test verifies that error messages are properly recorded in the \
+ resource status after each failed retry attempt. This provides visibility into \
+ reconciliation failures and helps with debugging operator issues.
+ """)
class ErrorStatusHandlerIT {
public static final int MAX_RETRY_ATTEMPTS = 3;
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/event/EventSourceIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/event/EventSourceIT.java
index eaa881709b..185b6c08f0 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/event/EventSourceIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/event/EventSourceIT.java
@@ -6,12 +6,22 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import io.javaoperatorsdk.operator.support.TestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Custom Event Source for Periodic Reconciliation",
+ description =
+ """
+ Demonstrates how to implement custom event sources that trigger reconciliation on a \
+ periodic basis. The test verifies that reconciliations are triggered at regular intervals \
+ by a timer-based event source. This enables operators to perform periodic checks or \
+ updates independent of resource changes.
+ """)
class EventSourceIT {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/filter/FilterIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/filter/FilterIT.java
index 1e51ad5ab0..6cb24473ab 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/filter/FilterIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/filter/FilterIT.java
@@ -6,12 +6,22 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.baseapi.filter.FilterTestReconciler.CONFIG_MAP_FILTER_VALUE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Filtering Events for Primary and Secondary Resources",
+ description =
+ """
+ Demonstrates how to implement event filters for both primary custom resources and \
+ secondary dependent resources. The test verifies that resource updates matching specific \
+ filter criteria are ignored and don't trigger reconciliation. This helps reduce \
+ unnecessary reconciliation executions and improve operator efficiency.
+ """)
class FilterIT {
public static final String RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/generickubernetesresourcehandling/GenericKubernetesResourceHandlingIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/generickubernetesresourcehandling/GenericKubernetesResourceHandlingIT.java
index 3b2fccfe59..44d8c7fabb 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/generickubernetesresourcehandling/GenericKubernetesResourceHandlingIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/generickubernetesresourcehandling/GenericKubernetesResourceHandlingIT.java
@@ -3,10 +3,21 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.dependent.generickubernetesresource.GenericKubernetesDependentSpec;
import io.javaoperatorsdk.operator.dependent.generickubernetesresource.GenericKubernetesDependentTestBase;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
+@Sample(
+ tldr = "Working with GenericKubernetesResource for Dynamic Resource Types",
+ description =
+ """
+ Demonstrates how to use GenericKubernetesResource to work with Kubernetes resources \
+ dynamically without requiring compile-time type definitions. This approach is useful when \
+ building operators that need to manage arbitrary Kubernetes resources or when the resource \
+ types are not known at compile time. The test shows how to handle generic resources as \
+ dependent resources in a reconciler.
+ """)
public class GenericKubernetesResourceHandlingIT
extends GenericKubernetesDependentTestBase {
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/gracefulstop/GracefulStopIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/gracefulstop/GracefulStopIT.java
index 4f499b256b..a16a6cafc5 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/gracefulstop/GracefulStopIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/gracefulstop/GracefulStopIT.java
@@ -6,12 +6,22 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.baseapi.gracefulstop.GracefulStopTestReconciler.RECONCILER_SLEEP;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Graceful Operator Shutdown with Reconciliation Timeout",
+ description =
+ """
+ Demonstrates how to configure graceful shutdown behavior with reconciliation termination \
+ timeouts. The test verifies that in-progress reconciliations are allowed to complete when \
+ the operator stops. This ensures clean shutdown without interrupting ongoing \
+ reconciliation work.
+ """)
public class GracefulStopIT {
public static final String TEST_1 = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/informereventsource/InformerEventSourceIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/informereventsource/InformerEventSourceIT.java
index c1a857c22c..3b442666d5 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/informereventsource/InformerEventSourceIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/informereventsource/InformerEventSourceIT.java
@@ -8,6 +8,7 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMeta;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.baseapi.informereventsource.InformerEventSourceTestCustomReconciler.MISSING_CONFIG_MAP;
@@ -17,6 +18,15 @@
import static org.assertj.core.api.Assertions.fail;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Using Informer Event Source to Watch Secondary Resources",
+ description =
+ """
+ Demonstrates how to use InformerEventSource to watch changes in secondary resources \
+ (ConfigMaps) and trigger reconciliation when those resources are created, updated, or \
+ deleted. The test verifies that the reconciler responds to ConfigMap changes and updates \
+ the primary resource status accordingly.
+ """)
class InformerEventSourceIT {
public static final String RESOURCE_NAME = "informertestcr";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/informerremotecluster/InformerRemoteClusterIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/informerremotecluster/InformerRemoteClusterIT.java
index 3cd5ddccbc..9d27c5d2d9 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/informerremotecluster/InformerRemoteClusterIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/informerremotecluster/InformerRemoteClusterIT.java
@@ -10,6 +10,7 @@
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.client.KubernetesClient;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers;
@@ -17,6 +18,14 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Watching resources in a remote Kubernetes cluster",
+ description =
+ """
+ Demonstrates how to configure an informer event source to watch resources in a different \
+ Kubernetes cluster from where the operator is running. This enables multi-cluster \
+ scenarios where an operator in one cluster manages resources in another cluster.
+ """)
@EnableKubeAPIServer
class InformerRemoteClusterIT {
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/labelselector/LabelSelectorIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/labelselector/LabelSelectorIT.java
index b073bee248..b6820459f2 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/labelselector/LabelSelectorIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/labelselector/LabelSelectorIT.java
@@ -8,6 +8,7 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.baseapi.labelselector.LabelSelectorTestReconciler.LABEL_KEY;
@@ -15,6 +16,15 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Label Selector for Custom Resource Filtering",
+ description =
+ """
+ Demonstrates how to configure label selectors to filter which custom resources an \
+ operator watches. The test verifies that only resources with matching labels trigger \
+ reconciliation. This allows operators to selectively manage a subset of custom resources \
+ based on their labels.
+ """)
class LabelSelectorIT {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/leaderelectionchangenamespace/LeaderElectionChangeNamespaceIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/leaderelectionchangenamespace/LeaderElectionChangeNamespaceIT.java
index f6194439e2..f35b2380a4 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/leaderelectionchangenamespace/LeaderElectionChangeNamespaceIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/leaderelectionchangenamespace/LeaderElectionChangeNamespaceIT.java
@@ -14,12 +14,22 @@
import io.fabric8.kubernetes.api.model.coordination.v1.LeaseSpecBuilder;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Leader election with namespace change handling",
+ description =
+ """
+ Tests that when an operator is not elected as leader, changing the watched namespaces does \
+ not start processing. This ensures that only the leader operator actively \
+ reconciles resources, preventing conflicts in multi-instance deployments with \
+ leader election.
+ """)
public class LeaderElectionChangeNamespaceIT {
public static final String LEASE_NAME = "nschangelease";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/manualobservedgeneration/ManualObservedGenerationIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/manualobservedgeneration/ManualObservedGenerationIT.java
index f90fda5c5e..55836c5617 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/manualobservedgeneration/ManualObservedGenerationIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/manualobservedgeneration/ManualObservedGenerationIT.java
@@ -4,11 +4,20 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Manually managing observedGeneration in status",
+ description =
+ """
+ Shows how to manually track and update the observedGeneration field in status to indicate \
+ which generation of the resource spec has been successfully processed. This is useful for \
+ providing clear feedback to users about reconciliation progress.
+ """)
public class ManualObservedGenerationIT {
public static final String RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/maxinterval/MaxIntervalIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/maxinterval/MaxIntervalIT.java
index af7cdbe8ec..9ecf50741c 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/maxinterval/MaxIntervalIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/maxinterval/MaxIntervalIT.java
@@ -6,11 +6,21 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMeta;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Maximum Reconciliation Interval Configuration",
+ description =
+ """
+ Demonstrates how to configure a maximum interval for periodic reconciliation triggers. \
+ The test verifies that reconciliation is automatically triggered at the configured \
+ interval even when there are no resource changes, enabling periodic validation and drift \
+ detection.
+ """)
class MaxIntervalIT {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/maxintervalafterretry/MaxIntervalAfterRetryIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/maxintervalafterretry/MaxIntervalAfterRetryIT.java
index bc55fa6035..40659a5793 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/maxintervalafterretry/MaxIntervalAfterRetryIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/maxintervalafterretry/MaxIntervalAfterRetryIT.java
@@ -6,11 +6,20 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMeta;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Maximum Reconciliation Interval After Retry",
+ description =
+ """
+ Tests that reconciliation is repeatedly triggered based on the maximum interval setting \
+ even after retries. This ensures periodic reconciliation continues at the configured \
+ maximum interval, maintaining eventual consistency regardless of retry attempts.
+ """)
class MaxIntervalAfterRetryIT {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiplereconcilersametype/MultipleReconcilerSameTypeIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiplereconcilersametype/MultipleReconcilerSameTypeIT.java
index 81cfa7fd07..23fe9c815a 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiplereconcilersametype/MultipleReconcilerSameTypeIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiplereconcilersametype/MultipleReconcilerSameTypeIT.java
@@ -4,11 +4,21 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Multiple reconcilers for the same resource type",
+ description =
+ """
+ Demonstrates how to register multiple reconcilers for the same custom resource type, with \
+ each reconciler handling different resources based on label selectors or other \
+ criteria. This enables different processing logic for different subsets of the same \
+ resource type.
+ """)
public class MultipleReconcilerSameTypeIT {
public static final String TEST_RESOURCE_1 = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiplesecondaryeventsource/MultipleSecondaryEventSourceIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiplesecondaryeventsource/MultipleSecondaryEventSourceIT.java
index 18a937040f..776054e893 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiplesecondaryeventsource/MultipleSecondaryEventSourceIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiplesecondaryeventsource/MultipleSecondaryEventSourceIT.java
@@ -7,10 +7,20 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Managing Multiple Secondary Event Sources",
+ description =
+ """
+ Demonstrates how to configure and use multiple secondary event sources for a single \
+ reconciler. The test verifies that the reconciler is triggered by changes to different \
+ secondary resources and handles events from multiple sources correctly, including periodic \
+ event sources.
+ """)
class MultipleSecondaryEventSourceIT {
public static final String TEST_RESOURCE_NAME = "testresource";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiversioncrd/MultiVersionCRDIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiversioncrd/MultiVersionCRDIT.java
index 9e0c6eb1fb..11b26e6ae3 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiversioncrd/MultiVersionCRDIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiversioncrd/MultiVersionCRDIT.java
@@ -13,6 +13,7 @@
import io.fabric8.kubernetes.client.WatcherException;
import io.fabric8.kubernetes.client.informers.SharedIndexInformer;
import io.fabric8.kubernetes.client.utils.Serialization;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.api.config.InformerStoppedHandler;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
@@ -21,6 +22,16 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Handling Multiple CRD Versions",
+ description =
+ """
+ Demonstrates how to work with Custom Resource Definitions that have multiple API \
+ versions. The test shows how to configure multiple reconcilers for different versions of \
+ the same CRD, handle version-specific schemas, and deal with incompatible version \
+ conversions. It also demonstrates error handling through InformerStoppedHandler when \
+ deserialization fails due to schema incompatibilities between versions.
+ """)
class MultiVersionCRDIT {
private static final Logger log = LoggerFactory.getLogger(MultiVersionCRDIT.class);
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/nextreconciliationimminent/NextReconciliationImminentIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/nextreconciliationimminent/NextReconciliationImminentIT.java
index 03bd6b0a7a..ca21390259 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/nextreconciliationimminent/NextReconciliationImminentIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/nextreconciliationimminent/NextReconciliationImminentIT.java
@@ -8,11 +8,20 @@
import org.slf4j.LoggerFactory;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Skipping status updates when next reconciliation is imminent",
+ description =
+ """
+ Shows how to use the nextReconciliationImminent flag to skip status updates when another \
+ reconciliation event is already pending. This optimization prevents unnecessary \
+ status patch operations when rapid consecutive reconciliations occur.
+ """)
public class NextReconciliationImminentIT {
private static final Logger log = LoggerFactory.getLogger(NextReconciliationImminentIT.class);
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/patchresourceandstatusnossa/PatchResourceAndStatusNoSSAIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/patchresourceandstatusnossa/PatchResourceAndStatusNoSSAIT.java
index a835dd2de6..301b91fea1 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/patchresourceandstatusnossa/PatchResourceAndStatusNoSSAIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/patchresourceandstatusnossa/PatchResourceAndStatusNoSSAIT.java
@@ -7,6 +7,7 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import io.javaoperatorsdk.operator.support.TestUtils;
@@ -15,6 +16,14 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Patching resource and status without Server-Side Apply",
+ description =
+ """
+ Demonstrates how to patch both the primary resource metadata/spec and status subresource \
+ using traditional JSON merge patch instead of Server-Side Apply. This shows the \
+ legacy approach for updating resources when SSA is disabled.
+ """)
class PatchResourceAndStatusNoSSAIT {
@RegisterExtension
LocallyRunOperatorExtension extension =
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/patchresourcewithssa/PatchResourceAndStatusWithSSAIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/patchresourcewithssa/PatchResourceAndStatusWithSSAIT.java
index f395706092..7c251c91fa 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/patchresourcewithssa/PatchResourceAndStatusWithSSAIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/patchresourcewithssa/PatchResourceAndStatusWithSSAIT.java
@@ -1,7 +1,17 @@
package io.javaoperatorsdk.operator.baseapi.patchresourcewithssa;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
+@Sample(
+ tldr = "Patching resource and status with Server-Side Apply",
+ description =
+ """
+ Demonstrates how to use Server-Side Apply (SSA) to patch both the primary resource and its \
+ status subresource. SSA provides better conflict resolution and field management \
+ tracking compared to traditional merge patches, making it the recommended approach \
+ for resource updates.
+ """)
public class PatchResourceAndStatusWithSSAIT extends PatchWithSSAITBase {
@Override
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/patchresourcewithssa/PatchResourceWithSSAIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/patchresourcewithssa/PatchResourceWithSSAIT.java
index d512665d06..e8ca8ffc57 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/patchresourcewithssa/PatchResourceWithSSAIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/patchresourcewithssa/PatchResourceWithSSAIT.java
@@ -1,7 +1,17 @@
package io.javaoperatorsdk.operator.baseapi.patchresourcewithssa;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
+@Sample(
+ tldr = "Patching Resources with Server-Side Apply (SSA)",
+ description =
+ """
+ Demonstrates how to use Server-Side Apply (SSA) for patching primary resources in \
+ Kubernetes. The test verifies that the reconciler can patch resources using SSA, which \
+ provides better conflict resolution and field management compared to traditional update \
+ approaches, including proper handling of managed fields.
+ """)
public class PatchResourceWithSSAIT extends PatchWithSSAITBase {
@Override
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/perresourceeventsource/PerResourcePollingEventSourceIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/perresourceeventsource/PerResourcePollingEventSourceIT.java
index 20f89e0d39..f2fa6f0064 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/perresourceeventsource/PerResourcePollingEventSourceIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/perresourceeventsource/PerResourcePollingEventSourceIT.java
@@ -4,11 +4,20 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Per-resource polling event source implementation",
+ description =
+ """
+ Shows how to implement a per-resource polling event source where each primary resource has \
+ its own polling schedule to fetch external state. This is useful for integrating \
+ with external systems that don't support event-driven notifications.
+ """)
class PerResourcePollingEventSourceIT {
public static final String NAME_1 = "name1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/primaryindexer/PrimaryIndexerIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/primaryindexer/PrimaryIndexerIT.java
index 9063ef0fcb..784fe0a579 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/primaryindexer/PrimaryIndexerIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/primaryindexer/PrimaryIndexerIT.java
@@ -7,12 +7,23 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMeta;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.baseapi.primaryindexer.AbstractPrimaryIndexerTestReconciler.CONFIG_MAP_NAME;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Using Primary Indexer for Secondary Resource Mapping",
+ description =
+ """
+ Demonstrates how to use primary indexers to efficiently map secondary resources back to \
+ their primary resources. When a secondary resource (like a ConfigMap) changes, the primary \
+ indexer allows the framework to determine which primary resources should be reconciled. \
+ This pattern enables efficient one-to-many and many-to-many relationships between primary \
+ and secondary resources without polling or full scans.
+ """)
public class PrimaryIndexerIT {
public static final String RESOURCE_NAME1 = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/primarytosecondary/PrimaryToSecondaryIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/primarytosecondary/PrimaryToSecondaryIT.java
index d82c24a55f..778745cca2 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/primarytosecondary/PrimaryToSecondaryIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/primarytosecondary/PrimaryToSecondaryIT.java
@@ -6,11 +6,21 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Primary to Secondary Resource Mapping",
+ description =
+ """
+ Demonstrates many-to-one mapping between primary and secondary resources where multiple \
+ primary resources can reference the same secondary resource. The test verifies that \
+ changes in the secondary resource trigger reconciliation of all related primary resources, \
+ enabling shared resource patterns.
+ """)
class PrimaryToSecondaryIT {
public static final String CLUSTER_NAME = "cluster1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/primarytosecondary/PrimaryToSecondaryMissingIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/primarytosecondary/PrimaryToSecondaryMissingIT.java
index 84e6910b35..c27ebeb75f 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/primarytosecondary/PrimaryToSecondaryMissingIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/primarytosecondary/PrimaryToSecondaryMissingIT.java
@@ -3,6 +3,7 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.baseapi.primarytosecondary.PrimaryToSecondaryIT.cluster;
@@ -14,6 +15,15 @@
* The intention with this IT is to show the use cases why the PrimaryToSecondary Mapper is needed,
* and the situation when it is not working.
*/
+@Sample(
+ tldr = "Issues When Primary-to-Secondary Mapper Is Missing",
+ description =
+ """
+ Demonstrates the problems that occur when accessing secondary resources without a \
+ proper PrimaryToSecondaryMapper configured. The test shows that accessing secondary \
+ resources through the context fails without the mapper, while direct cache access works \
+ as a workaround, highlighting the importance of proper mapper configuration.
+ """)
class PrimaryToSecondaryMissingIT {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ratelimit/RateLimitIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ratelimit/RateLimitIT.java
index 8b04fd0095..ed0a595a96 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ratelimit/RateLimitIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/ratelimit/RateLimitIT.java
@@ -9,12 +9,21 @@
import org.slf4j.LoggerFactory;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.baseapi.ratelimit.RateLimitReconciler.REFRESH_PERIOD;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Rate Limiting Reconciliation Executions",
+ description =
+ """
+ Demonstrates how to implement rate limiting to control how frequently reconciliations \
+ execute. The test shows that multiple rapid resource updates are batched and executed at a \
+ controlled rate. This prevents overwhelming the system when resources change frequently.
+ """)
class RateLimitIT {
private static final Logger log = LoggerFactory.getLogger(RateLimitIT.class);
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/retry/RetryIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/retry/RetryIT.java
index 410d34a390..ef91272f70 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/retry/RetryIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/retry/RetryIT.java
@@ -6,6 +6,7 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import io.javaoperatorsdk.operator.processing.retry.GenericRetry;
import io.javaoperatorsdk.operator.support.TestUtils;
@@ -13,6 +14,15 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Automatic Retry for Failed Reconciliations",
+ description =
+ """
+ Demonstrates how to configure automatic retry logic for reconciliations that fail \
+ temporarily. The test shows that failed executions are automatically retried with \
+ configurable intervals and max attempts. After a specified number of retries, the \
+ reconciliation succeeds and updates the resource status accordingly.
+ """)
class RetryIT {
public static final int RETRY_INTERVAL = 150;
public static final int MAX_RETRY_ATTEMPTS = 5;
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/retry/RetryMaxAttemptIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/retry/RetryMaxAttemptIT.java
index f57a70201f..07cc458713 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/retry/RetryMaxAttemptIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/retry/RetryMaxAttemptIT.java
@@ -3,12 +3,22 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import io.javaoperatorsdk.operator.processing.retry.GenericRetry;
import static io.javaoperatorsdk.operator.baseapi.retry.RetryIT.createTestCustomResource;
import static org.assertj.core.api.Assertions.assertThat;
+@Sample(
+ tldr = "Maximum Retry Attempts Configuration",
+ description =
+ """
+ Demonstrates how to configure a maximum number of retry attempts for failed \
+ reconciliations. The test verifies that the operator stops retrying after reaching the \
+ configured maximum attempts. This prevents infinite retry loops when reconciliations \
+ consistently fail.
+ """)
class RetryMaxAttemptIT {
public static final int MAX_RETRY_ATTEMPTS = 3;
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/simple/ReconcilerExecutorIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/simple/ReconcilerExecutorIT.java
index cbd8de4459..c744830f5d 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/simple/ReconcilerExecutorIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/simple/ReconcilerExecutorIT.java
@@ -7,12 +7,21 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ConfigMap;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import io.javaoperatorsdk.operator.support.TestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Basic reconciler execution",
+ description =
+ """
+ Demonstrates the basic reconciler execution flow including resource creation, status \
+ updates, and cleanup. This test verifies that a reconciler can create dependent resources \
+ (ConfigMap), update status, and properly handle cleanup when resources are deleted.
+ """)
class ReconcilerExecutorIT {
@RegisterExtension
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
index a830675518..25cd6fbd91 100644
--- 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
@@ -8,11 +8,21 @@
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.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Server-Side Apply Finalizer Field Manager Issue",
+ description =
+ """
+ Demonstrates a potential issue with Server-Side Apply (SSA) when adding finalizers. \
+ When a resource is created with the same field manager used by the controller, adding \
+ a finalizer can unexpectedly remove other spec fields, showcasing field manager \
+ ownership conflicts in SSA.
+ """)
class SSAFinalizerIssueIT {
public static final String TEST_1 = "test1";
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
index 9cccd32e3c..af4c668884 100644
--- 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
@@ -4,11 +4,21 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Server-Side Apply Finalizer Removal on Spec Update",
+ description =
+ """
+ Demonstrates an issue with Server-Side Apply (SSA) where updating the resource spec \
+ without explicitly including the finalizer causes the finalizer to be removed. This \
+ highlights the importance of including all desired fields when using SSA to avoid \
+ unintended field removal.
+ """)
class SSASpecUpdateIT {
public static final String TEST_RESOURCE_NAME = "test";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/startsecondaryaccess/StartupSecondaryAccessIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/startsecondaryaccess/StartupSecondaryAccessIT.java
index 61fc40803c..157569530d 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/startsecondaryaccess/StartupSecondaryAccessIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/startsecondaryaccess/StartupSecondaryAccessIT.java
@@ -7,6 +7,7 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.baseapi.startsecondaryaccess.StartupSecondaryAccessReconciler.LABEL_KEY;
@@ -14,6 +15,15 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Accessing Secondary Resources During Operator Startup",
+ description =
+ """
+ Verifies that reconcilers can properly access all secondary resources during operator \
+ startup, even when a large number of secondary resources exist. The test ensures that \
+ the informer cache is fully synchronized before reconciliation begins, allowing access \
+ to all related resources.
+ """)
class StartupSecondaryAccessIT {
public static final int SECONDARY_NUMBER = 200;
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuscache/StatusPatchCacheIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuscache/StatusPatchCacheIT.java
index 9d0b923056..f6e91f80dc 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuscache/StatusPatchCacheIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuscache/StatusPatchCacheIT.java
@@ -6,11 +6,21 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Status patch caching for consistency",
+ description =
+ """
+ Demonstrates how the framework caches status patches to ensure consistency when status is \
+ updated frequently. The cache guarantees that status values are monotonically \
+ increasing and always reflect the most recent state, even with rapid successive \
+ updates.
+ """)
public class StatusPatchCacheIT {
public static final String TEST_1 = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuspatchnonlocking/StatusPatchNotLockingForNonSSAIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuspatchnonlocking/StatusPatchNotLockingForNonSSAIT.java
index 4913b900a0..8cb06adbed 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuspatchnonlocking/StatusPatchNotLockingForNonSSAIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuspatchnonlocking/StatusPatchNotLockingForNonSSAIT.java
@@ -7,6 +7,7 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.baseapi.statuspatchnonlocking.StatusPatchLockingReconciler.MESSAGE;
@@ -14,6 +15,15 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Status Patching Without Optimistic Locking for Non-SSA",
+ description =
+ """
+ Tests status update behavior when not using Server-Side Apply (SSA), verifying that \
+ optimistic locking is not enforced on status patches. The test also demonstrates proper \
+ field deletion when values are set to null, ensuring correct status management without \
+ SSA optimistic locking.
+ """)
class StatusPatchNotLockingForNonSSAIT {
public static final String TEST_RESOURCE_NAME = "test";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuspatchnonlocking/StatusPatchSSAMigrationIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuspatchnonlocking/StatusPatchSSAMigrationIT.java
index a301e9f61a..44158fdd8e 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuspatchnonlocking/StatusPatchSSAMigrationIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statuspatchnonlocking/StatusPatchSSAMigrationIT.java
@@ -11,12 +11,22 @@
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.Operator;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Migrating Status Patching from Non-SSA to SSA",
+ description =
+ """
+ Demonstrates the process and challenges of migrating status patching from traditional \
+ update methods to Server-Side Apply (SSA). Tests show a known Kubernetes issue where \
+ field deletion doesn't work correctly during migration, and provides a workaround by \
+ removing managed field entries from the previous update method.
+ """)
public class StatusPatchSSAMigrationIT {
public static final String TEST_RESOURCE_NAME = "test";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statusupdatelocking/StatusUpdateLockingIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statusupdatelocking/StatusUpdateLockingIT.java
index ad51d82059..b745f82bc6 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statusupdatelocking/StatusUpdateLockingIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/statusupdatelocking/StatusUpdateLockingIT.java
@@ -7,12 +7,22 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.baseapi.statusupdatelocking.StatusUpdateLockingReconciler.WAIT_TIME;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Status Update Locking and Concurrency Control",
+ description =
+ """
+ Demonstrates how the framework handles concurrent status updates and ensures no \
+ optimistic locking conflicts occur when updating status subresources. The test verifies \
+ that status updates can proceed independently of spec updates without causing version \
+ conflicts or requiring retries.
+ """)
class StatusUpdateLockingIT {
public static final String TEST_RESOURCE_NAME = "test";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/subresource/SubResourceUpdateIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/subresource/SubResourceUpdateIT.java
index 7544e3b791..b74c6dc78d 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/subresource/SubResourceUpdateIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/subresource/SubResourceUpdateIT.java
@@ -7,6 +7,7 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import io.javaoperatorsdk.operator.support.TestUtils;
@@ -14,6 +15,15 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Status Subresource Updates",
+ description =
+ """
+ Demonstrates how to properly update the status subresource of custom resources. The test \
+ verifies that status updates are handled correctly without triggering unnecessary \
+ reconciliations, and that concurrent spec and status updates are managed properly with \
+ optimistic locking and retry mechanisms.
+ """)
class SubResourceUpdateIT {
public static final int WAIT_AFTER_EXECUTION = 500;
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/unmodifiabledependentpart/UnmodifiableDependentPartIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/unmodifiabledependentpart/UnmodifiableDependentPartIT.java
index 735255c54c..2435e71fdd 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/unmodifiabledependentpart/UnmodifiableDependentPartIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/unmodifiabledependentpart/UnmodifiableDependentPartIT.java
@@ -5,6 +5,7 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.baseapi.unmodifiabledependentpart.UnmodifiablePartConfigMapDependent.ACTUAL_DATA_KEY;
@@ -12,6 +13,15 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Unmodifiable Parts in Dependent Resources",
+ description =
+ """
+ Demonstrates how to preserve certain parts of a dependent resource from being modified \
+ during updates while allowing other parts to change. This test shows that initial data \
+ can be marked as unmodifiable and will remain unchanged even when the primary resource \
+ spec is updated, enabling partial update control.
+ """)
public class UnmodifiableDependentPartIT {
public static final String TEST_RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/updatestatusincleanupandreschedule/UpdateStatusInCleanupAndRescheduleIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/updatestatusincleanupandreschedule/UpdateStatusInCleanupAndRescheduleIT.java
index b2a2b463ba..34cbedf310 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/updatestatusincleanupandreschedule/UpdateStatusInCleanupAndRescheduleIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/updatestatusincleanupandreschedule/UpdateStatusInCleanupAndRescheduleIT.java
@@ -4,11 +4,21 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Update Status in Cleanup and Reschedule",
+ description =
+ """
+ Tests the ability to update resource status during cleanup and reschedule the cleanup \
+ operation. This demonstrates that cleanup methods can perform status updates and request \
+ to be called again after a delay, enabling multi-step cleanup processes with status \
+ tracking.
+ """)
public class UpdateStatusInCleanupAndRescheduleIT {
public static final String TEST_RESOURCE = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/BulkDependentDeleterIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/BulkDependentDeleterIT.java
index 108607283b..5952396fc1 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/BulkDependentDeleterIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/BulkDependentDeleterIT.java
@@ -2,9 +2,19 @@
import org.junit.jupiter.api.extension.RegisterExtension;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.dependent.bulkdependent.managed.ManagedDeleterBulkReconciler;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
+@Sample(
+ tldr = "Bulk Dependent Resource Deleter Implementation",
+ description =
+ """
+ Demonstrates implementation of a bulk dependent resource with custom deleter logic. \
+ This test extends BulkDependentTestBase to verify that bulk dependent resources can \
+ implement custom deletion strategies, managing multiple resources efficiently during \
+ cleanup operations.
+ """)
public class BulkDependentDeleterIT extends BulkDependentTestBase {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/condition/BulkDependentWithConditionIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/condition/BulkDependentWithConditionIT.java
index eb3a6e7368..f9027c089d 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/condition/BulkDependentWithConditionIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/condition/BulkDependentWithConditionIT.java
@@ -3,6 +3,7 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.dependent.bulkdependent.BulkDependentTestCustomResource;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
@@ -13,6 +14,15 @@
import static org.assertj.core.api.Assertions.*;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Bulk Dependent Resources with Ready Conditions",
+ description =
+ """
+ Tests bulk dependent resources with preconditions that control when reconciliation \
+ occurs. This demonstrates using ready conditions to ensure bulk operations only execute \
+ when the primary resource is in the appropriate state, coordinating complex multi-resource \
+ management.
+ """)
class BulkDependentWithConditionIT {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/external/BulkExternalDependentIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/external/BulkExternalDependentIT.java
index 4f7d425729..3080beb001 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/external/BulkExternalDependentIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/external/BulkExternalDependentIT.java
@@ -3,12 +3,22 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.dependent.bulkdependent.BulkDependentTestBase.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Managing External Bulk Resources",
+ description =
+ """
+ Demonstrates managing multiple external resources (non-Kubernetes) using bulk dependent \
+ resources. This pattern allows operators to manage a variable number of external resources \
+ based on primary resource specifications, handling creation, updates, and deletion of \
+ external resources at scale.
+ """)
class BulkExternalDependentIT {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/managed/ManagedBulkDependentIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/managed/ManagedBulkDependentIT.java
index 61b7f62a24..7353887ef4 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/managed/ManagedBulkDependentIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/managed/ManagedBulkDependentIT.java
@@ -2,9 +2,20 @@
import org.junit.jupiter.api.extension.RegisterExtension;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.dependent.bulkdependent.BulkDependentTestBase;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
+@Sample(
+ tldr = "Bulk Dependent Resources with Managed Workflow",
+ description =
+ """
+ Demonstrates how to manage bulk dependent resources using the managed workflow approach. \
+ This test extends the base bulk dependent test to show how multiple instances of \
+ the same type of dependent resource can be created and managed together. The \
+ managed workflow handles the orchestration of creating, updating, and deleting \
+ multiple dependent resources based on the primary resource specification.
+ """)
public class ManagedBulkDependentIT extends BulkDependentTestBase {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/readonly/ReadOnlyBulkDependentIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/readonly/ReadOnlyBulkDependentIT.java
index 422360b7b2..c2524f635c 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/readonly/ReadOnlyBulkDependentIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/readonly/ReadOnlyBulkDependentIT.java
@@ -7,6 +7,7 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.dependent.bulkdependent.BulkDependentTestCustomResource;
import io.javaoperatorsdk.operator.dependent.bulkdependent.BulkDependentTestSpec;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
@@ -14,6 +15,15 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Read-Only Bulk Dependent Resources",
+ description =
+ """
+ Demonstrates how to use read-only bulk dependent resources to observe and react to \
+ multiple existing resources without managing them. This test shows how an operator \
+ can monitor a collection of resources created externally and update the custom \
+ resource status based on their state, without creating or modifying them.
+ """)
public class ReadOnlyBulkDependentIT {
public static final int EXPECTED_NUMBER_OF_RESOURCES = 2;
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/standalone/StandaloneBulkDependentIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/standalone/StandaloneBulkDependentIT.java
index a74102db0d..3c2a12a680 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/standalone/StandaloneBulkDependentIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/bulkdependent/standalone/StandaloneBulkDependentIT.java
@@ -2,9 +2,19 @@
import org.junit.jupiter.api.extension.RegisterExtension;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.dependent.bulkdependent.BulkDependentTestBase;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
+@Sample(
+ tldr = "Standalone Bulk Dependent Resources",
+ description =
+ """
+ Demonstrates how to use standalone bulk dependent resources to manage multiple \
+ resources of the same type efficiently. This test shows how bulk operations can be \
+ performed on a collection of resources without individual reconciliation cycles, \
+ improving performance when managing many similar resources.
+ """)
class StandaloneBulkDependentIT extends BulkDependentTestBase {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/cleanermanageddependent/CleanerForManagedDependentResourcesOnlyIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/cleanermanageddependent/CleanerForManagedDependentResourcesOnlyIT.java
index b0b716e8e2..37d82c313c 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/cleanermanageddependent/CleanerForManagedDependentResourcesOnlyIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/cleanermanageddependent/CleanerForManagedDependentResourcesOnlyIT.java
@@ -4,11 +4,21 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMeta;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Cleanup handlers for managed dependent resources",
+ description =
+ """
+ Shows how to implement cleanup logic for managed dependent resources using the Cleaner \
+ interface. The framework automatically adds finalizers and invokes the cleanup \
+ method when the primary resource is deleted, ensuring proper cleanup of dependent \
+ resources.
+ """)
class CleanerForManagedDependentResourcesOnlyIT {
public static final String TEST_RESOURCE_NAME = "cleaner-for-reconciler-test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/createonlyifnotexistsdependentwithssa/CreateOnlyIfNotExistingDependentWithSSAIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/createonlyifnotexistsdependentwithssa/CreateOnlyIfNotExistingDependentWithSSAIT.java
index 3c41bae977..1d405a788d 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/createonlyifnotexistsdependentwithssa/CreateOnlyIfNotExistingDependentWithSSAIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/createonlyifnotexistsdependentwithssa/CreateOnlyIfNotExistingDependentWithSSAIT.java
@@ -10,11 +10,21 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Create-Only Dependent Resources with Server-Side Apply",
+ description =
+ """
+ Demonstrates how to configure a dependent resource that is only created if it doesn't \
+ exist, using Server-Side Apply (SSA). This test shows that when a resource already \
+ exists, the dependent resource implementation will not modify it, preserving any \
+ external changes.
+ """)
class CreateOnlyIfNotExistingDependentWithSSAIT {
public static final String TEST_RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentannotationsecondarymapper/DependentAnnotationSecondaryMapperIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentannotationsecondarymapper/DependentAnnotationSecondaryMapperIT.java
index 466837de4e..5a4862bebf 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentannotationsecondarymapper/DependentAnnotationSecondaryMapperIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentannotationsecondarymapper/DependentAnnotationSecondaryMapperIT.java
@@ -7,6 +7,7 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.processing.event.source.informer.Mappers.DEFAULT_ANNOTATION_FOR_NAME;
@@ -14,6 +15,15 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Annotation-Based Secondary Resource Mapping for Dependents",
+ description =
+ """
+ Demonstrates using annotations instead of owner references to map secondary resources \
+ to primary resources in dependent resources. This approach is useful when owner references \
+ cannot be used (e.g., cross-namespace or cluster-scoped relationships), using special \
+ annotations to establish the relationship.
+ """)
class DependentAnnotationSecondaryMapperIT {
public static final String TEST_RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentcustommappingannotation/DependentCustomMappingAnnotationIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentcustommappingannotation/DependentCustomMappingAnnotationIT.java
index 42f365884f..d9a1525d0c 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentcustommappingannotation/DependentCustomMappingAnnotationIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentcustommappingannotation/DependentCustomMappingAnnotationIT.java
@@ -5,6 +5,7 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.dependent.dependentcustommappingannotation.CustomMappingConfigMapDependentResource.CUSTOM_NAMESPACE_KEY;
@@ -12,6 +13,15 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Custom Annotation Keys for Resource Mapping",
+ description =
+ """
+ Tests custom annotation-based mapping for dependent resources using configurable \
+ annotation keys instead of the default ones. This allows developers to customize which \
+ annotations are used to establish relationships between primary and secondary resources, \
+ providing flexibility for different naming conventions or avoiding conflicts.
+ """)
class DependentCustomMappingAnnotationIT {
public static final String INITIAL_VALUE = "initial value";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentdifferentnamespace/DependentDifferentNamespaceIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentdifferentnamespace/DependentDifferentNamespaceIT.java
index c02bac5a5d..fbddee518f 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentdifferentnamespace/DependentDifferentNamespaceIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentdifferentnamespace/DependentDifferentNamespaceIT.java
@@ -5,12 +5,23 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.dependent.dependentdifferentnamespace.ConfigMapDependentResource.KEY;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Dependent Resources in Different Namespaces",
+ description =
+ """
+ Demonstrates how to manage dependent resources in a namespace different from the primary \
+ resource. This test shows how to configure dependent resources to be created in a \
+ specific namespace rather than inheriting the namespace from the primary resource. \
+ The test verifies full CRUD operations for a ConfigMap that lives in a different \
+ namespace than the custom resource that manages it.
+ """)
class DependentDifferentNamespaceIT {
public static final String TEST_1 = "different-ns-test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentfilter/DependentFilterIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentfilter/DependentFilterIT.java
index bc7b578d7f..c988ef2741 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentfilter/DependentFilterIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentfilter/DependentFilterIT.java
@@ -8,6 +8,7 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.dependent.dependentfilter.DependentFilterTestReconciler.CM_VALUE_KEY;
@@ -15,6 +16,17 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Filtering Reconciliation Triggers from Dependent Resources",
+ description =
+ """
+ Demonstrates how to filter events from dependent resources to prevent unnecessary \
+ reconciliation triggers. This test shows how to configure filters on dependent \
+ resources so that only specific changes trigger a reconciliation of the primary \
+ resource. The test verifies that updates to filtered fields in the dependent \
+ resource do not cause the reconciler to execute, improving efficiency and avoiding \
+ reconciliation loops.
+ """)
class DependentFilterIT {
public static final String RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentoperationeventfiltering/DependentOperationEventFilterIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentoperationeventfiltering/DependentOperationEventFilterIT.java
index e9ddc6cd6e..60e2670099 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentoperationeventfiltering/DependentOperationEventFilterIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentoperationeventfiltering/DependentOperationEventFilterIT.java
@@ -7,11 +7,21 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMeta;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Event filtering for dependent resource operations",
+ description =
+ """
+ Demonstrates how to configure event filters on dependent resources to prevent \
+ reconciliation loops. When a dependent resource is created or updated by the \
+ controller, the filter prevents those events from triggering unnecessary \
+ reconciliations.
+ """)
class DependentOperationEventFilterIT {
public static final String TEST = "test";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentreinitialization/DependentReInitializationIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentreinitialization/DependentReInitializationIT.java
index 270b89a6a5..760f354007 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentreinitialization/DependentReInitializationIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentreinitialization/DependentReInitializationIT.java
@@ -4,9 +4,19 @@
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.Operator;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
+@Sample(
+ tldr = "Reusing Dependent Resource Instances Across Tests",
+ description =
+ """
+ Demonstrates that dependent resource instances can be safely reused across multiple \
+ operator start/stop cycles. This is particularly useful in CDI-managed environments \
+ like Quarkus, where dependent resources are managed as beans and should be reusable \
+ across test executions.
+ """)
class DependentReInitializationIT {
/**
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentresourcecrossref/DependentResourceCrossRefIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentresourcecrossref/DependentResourceCrossRefIT.java
index 1b71c79448..740cd81e1a 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentresourcecrossref/DependentResourceCrossRefIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentresourcecrossref/DependentResourceCrossRefIT.java
@@ -8,11 +8,21 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.Secret;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Dependent Resources with Cross-References",
+ description =
+ """
+ Tests dependent resources that reference each other, creating interdependencies between \
+ multiple secondary resources. The test verifies that resources with circular or \
+ cross-references can be safely created, managed, and deleted without causing issues, \
+ even under concurrent operations with multiple primary resources.
+ """)
class DependentResourceCrossRefIT {
public static final String TEST_RESOURCE_NAME = "test";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentssa/DependentSSAMatchingIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentssa/DependentSSAMatchingIT.java
index 8ab686b1b8..3fab17116f 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentssa/DependentSSAMatchingIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentssa/DependentSSAMatchingIT.java
@@ -11,11 +11,23 @@
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.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Server-Side Apply (SSA) with Dependent Resources",
+ description =
+ """
+ Demonstrates how to use Server-Side Apply (SSA) with dependent resources and field manager \
+ matching. This test shows how SSA allows multiple controllers to manage different \
+ fields of the same resource without conflicts. The test verifies that changes made \
+ by different field managers are properly isolated, and that the operator only \
+ updates its own fields when changes occur, preserving fields managed by other \
+ controllers.
+ """)
public class DependentSSAMatchingIT {
public static final String TEST_RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentssa/DependentSSAMigrationIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentssa/DependentSSAMigrationIT.java
index 0d354febdf..18f7421293 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentssa/DependentSSAMigrationIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/dependentssa/DependentSSAMigrationIT.java
@@ -11,12 +11,22 @@
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.Operator;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Migrating Dependent Resources from Legacy to SSA",
+ description =
+ """
+ Demonstrates migrating dependent resource management from legacy update methods to \
+ Server-Side Apply (SSA). Tests show bidirectional migration scenarios and field manager \
+ handling, including using the default fabric8 field manager to avoid creating duplicate \
+ managed field entries during migration.
+ """)
class DependentSSAMigrationIT {
public static final String FABRIC8_CLIENT_DEFAULT_FIELD_MANAGER = "fabric8-kubernetes-client";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/externalstate/ExternalStateDependentIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/externalstate/ExternalStateDependentIT.java
index 87e588673d..23f19a2143 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/externalstate/ExternalStateDependentIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/externalstate/ExternalStateDependentIT.java
@@ -2,8 +2,18 @@
import org.junit.jupiter.api.extension.RegisterExtension;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
+@Sample(
+ tldr = "External State Tracking in Dependent Resources",
+ description =
+ """
+ Demonstrates managing dependent resources with external state that needs to be tracked \
+ independently of Kubernetes resources. This pattern allows operators to maintain state \
+ information for external systems or resources, ensuring proper reconciliation even when \
+ the external state differs from the desired Kubernetes resource state.
+ """)
public class ExternalStateDependentIT extends ExternalStateTestBase {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/externalstate/ExternalStateIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/externalstate/ExternalStateIT.java
index bae36431b5..e4c8bab47c 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/externalstate/ExternalStateIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/externalstate/ExternalStateIT.java
@@ -5,6 +5,7 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import io.javaoperatorsdk.operator.support.ExternalIDGenServiceMock;
@@ -12,6 +13,17 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Managing External Resources with Persistent State",
+ description =
+ """
+ Demonstrates how to manage external resources (outside of Kubernetes) while maintaining \
+ their state in Kubernetes resources. This test shows a pattern for reconciling \
+ external systems by storing external resource identifiers in a ConfigMap. The test \
+ verifies that external resources can be created, updated, and deleted in \
+ coordination with Kubernetes resources, with the ConfigMap serving as a state store \
+ for external resource IDs.
+ """)
class ExternalStateIT {
private static final String TEST_RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/externalstate/externalstatebulkdependent/ExternalStateBulkIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/externalstate/externalstatebulkdependent/ExternalStateBulkIT.java
index b2714fab47..d9c7693d70 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/externalstate/externalstatebulkdependent/ExternalStateBulkIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/externalstate/externalstatebulkdependent/ExternalStateBulkIT.java
@@ -6,12 +6,22 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import io.javaoperatorsdk.operator.support.ExternalIDGenServiceMock;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Bulk External State Management with Persistent State",
+ description =
+ """
+ Demonstrates managing multiple external resources with persistent state tracking using \
+ bulk dependent resources. This combines external state management with bulk operations, \
+ allowing operators to track and reconcile a variable number of external resources with \
+ persistent state that survives operator restarts.
+ """)
class ExternalStateBulkIT {
private static final String TEST_RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/generickubernetesresource/generickubernetesdependentresourcemanaged/GenericKubernetesDependentManagedIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/generickubernetesresource/generickubernetesdependentresourcemanaged/GenericKubernetesDependentManagedIT.java
index 93fc34fbf0..416843c723 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/generickubernetesresource/generickubernetesdependentresourcemanaged/GenericKubernetesDependentManagedIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/generickubernetesresource/generickubernetesdependentresourcemanaged/GenericKubernetesDependentManagedIT.java
@@ -3,10 +3,20 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.dependent.generickubernetesresource.GenericKubernetesDependentSpec;
import io.javaoperatorsdk.operator.dependent.generickubernetesresource.GenericKubernetesDependentTestBase;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
+@Sample(
+ tldr = "Generic Kubernetes Dependent Resource (Managed)",
+ description =
+ """
+ Demonstrates how to use GenericKubernetesResource as a managed dependent resource. This \
+ test shows how to work with generic Kubernetes resources that don't have a specific \
+ Java model class, allowing the operator to manage any Kubernetes resource type \
+ dynamically.
+ """)
public class GenericKubernetesDependentManagedIT
extends GenericKubernetesDependentTestBase {
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/generickubernetesresource/generickubernetesdependentstandalone/GenericKubernetesDependentStandaloneIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/generickubernetesresource/generickubernetesdependentstandalone/GenericKubernetesDependentStandaloneIT.java
index 9afdec5474..97ae13ae2a 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/generickubernetesresource/generickubernetesdependentstandalone/GenericKubernetesDependentStandaloneIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/generickubernetesresource/generickubernetesdependentstandalone/GenericKubernetesDependentStandaloneIT.java
@@ -3,10 +3,20 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.dependent.generickubernetesresource.GenericKubernetesDependentSpec;
import io.javaoperatorsdk.operator.dependent.generickubernetesresource.GenericKubernetesDependentTestBase;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
+@Sample(
+ tldr = "Generic Kubernetes Resource as Standalone Dependent",
+ description =
+ """
+ Tests using GenericKubernetesResource as a standalone dependent resource. This approach \
+ allows operators to manage arbitrary Kubernetes resources without requiring specific Java \
+ classes for each resource type, providing flexibility for managing various resource types \
+ dynamically.
+ """)
public class GenericKubernetesDependentStandaloneIT
extends GenericKubernetesDependentTestBase {
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/kubernetesdependentgarbagecollection/KubernetesDependentGarbageCollectionIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/kubernetesdependentgarbagecollection/KubernetesDependentGarbageCollectionIT.java
index 8e08c4e739..0ee286a65a 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/kubernetesdependentgarbagecollection/KubernetesDependentGarbageCollectionIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/kubernetesdependentgarbagecollection/KubernetesDependentGarbageCollectionIT.java
@@ -7,12 +7,24 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.IntegrationTestConstants;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Kubernetes Native Garbage Collection for Dependent Resources",
+ description =
+ """
+ Demonstrates how to leverage Kubernetes native garbage collection for dependent resources \
+ using owner references. This test shows how dependent resources are automatically \
+ cleaned up by Kubernetes when the owner resource is deleted, and how to \
+ conditionally create or delete dependent resources based on the primary resource \
+ state. Owner references ensure that dependent resources don't outlive their \
+ owners.
+ """)
class KubernetesDependentGarbageCollectionIT {
public static final String TEST_RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipledependentresource/MultipleDependentResourceIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipledependentresource/MultipleDependentResourceIT.java
index a7dfefdaa8..962dfaa959 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipledependentresource/MultipleDependentResourceIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipledependentresource/MultipleDependentResourceIT.java
@@ -7,6 +7,7 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.dependent.multipledependentresource.MultipleDependentResourceConfigMap.DATA_KEY;
@@ -16,6 +17,16 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Managing Multiple Dependent Resources",
+ description =
+ """
+ Demonstrates how to manage multiple dependent resources from a single reconciler. This \
+ test shows how a single custom resource can create, update, and delete multiple \
+ ConfigMaps (or other Kubernetes resources) as dependents. The test verifies that \
+ all dependent resources are created together, updated together when the primary \
+ resource changes, and properly cleaned up when the primary resource is deleted.
+ """)
public class MultipleDependentResourceIT {
public static final String CHANGED_VALUE = "changed value";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipledependentresourcewithsametype/MultipleDependentResourceWithNoDiscriminatorIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipledependentresourcewithsametype/MultipleDependentResourceWithNoDiscriminatorIT.java
index 8be51ebf1a..4817078b7c 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipledependentresourcewithsametype/MultipleDependentResourceWithNoDiscriminatorIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipledependentresourcewithsametype/MultipleDependentResourceWithNoDiscriminatorIT.java
@@ -8,11 +8,20 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Multiple Dependents of Same Type Without Discriminator",
+ description =
+ """
+ Demonstrates managing multiple dependent resources of the same type (ConfigMaps) without \
+ using discriminators. The framework uses resource names to differentiate between them, \
+ simplifying configuration when distinct names are sufficient for identification.
+ """)
class MultipleDependentResourceWithNoDiscriminatorIT {
public static final String TEST_RESOURCE_NAME = "multipledependentresource-testresource";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipledependentsametypemultiinformer/MultipleDependentSameTypeMultiInformerIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipledependentsametypemultiinformer/MultipleDependentSameTypeMultiInformerIT.java
index 5ba6d56be3..0d4e40e5ee 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipledependentsametypemultiinformer/MultipleDependentSameTypeMultiInformerIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipledependentsametypemultiinformer/MultipleDependentSameTypeMultiInformerIT.java
@@ -7,6 +7,7 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.IntegrationTestConstants.GARBAGE_COLLECTION_TIMEOUT_SECONDS;
@@ -14,6 +15,15 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Multiple Managed Dependents of Same Type with Multi-Informer",
+ description =
+ """
+ Tests managing multiple dependent resources of the same type using separate informers \
+ for each. This approach allows for independent event handling and caching for resources \
+ of the same type, useful when different caching strategies or event filtering is needed \
+ for different instances.
+ """)
class MultipleDependentSameTypeMultiInformerIT {
public static final String TEST_RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipledrsametypenodiscriminator/MultipleManagedDependentNoDiscriminatorIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipledrsametypenodiscriminator/MultipleManagedDependentNoDiscriminatorIT.java
index 1ed1da56f9..715b4763b5 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipledrsametypenodiscriminator/MultipleManagedDependentNoDiscriminatorIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipledrsametypenodiscriminator/MultipleManagedDependentNoDiscriminatorIT.java
@@ -7,12 +7,22 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.dependent.multipledrsametypenodiscriminator.MultipleManagedDependentSameTypeNoDiscriminatorReconciler.DATA_KEY;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Multiple Managed Dependents of Same Type Without Discriminator",
+ description =
+ """
+ Demonstrates managing multiple managed dependent resources of the same type without \
+ explicit discriminators. The test verifies complete CRUD operations on multiple ConfigMaps, \
+ showing that resource names alone can differentiate between dependents when a \
+ discriminator is not needed.
+ """)
public class MultipleManagedDependentNoDiscriminatorIT {
public static final String RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multiplemanageddependentsametype/MultipleManagedDependentSameTypeIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multiplemanageddependentsametype/MultipleManagedDependentSameTypeIT.java
index a835b5a255..4958f84ff1 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multiplemanageddependentsametype/MultipleManagedDependentSameTypeIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multiplemanageddependentsametype/MultipleManagedDependentSameTypeIT.java
@@ -7,6 +7,7 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.IntegrationTestConstants.GARBAGE_COLLECTION_TIMEOUT_SECONDS;
@@ -14,6 +15,15 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Managing Multiple Dependent Resources of the Same Type",
+ description =
+ """
+ Demonstrates how to manage multiple dependent resources of the same type from a single \
+ reconciler. This test shows how multiple ConfigMaps with the same type can be \
+ created, updated, and deleted as dependent resources of a custom resource, \
+ verifying proper CRUD operations and garbage collection.
+ """)
class MultipleManagedDependentSameTypeIT {
public static final String TEST_RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multiplemanagedexternaldependenttype/MultipleManagedExternalDependentSameTypeIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multiplemanagedexternaldependenttype/MultipleManagedExternalDependentSameTypeIT.java
index a8c1f889d0..cf39c66cc7 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multiplemanagedexternaldependenttype/MultipleManagedExternalDependentSameTypeIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multiplemanagedexternaldependenttype/MultipleManagedExternalDependentSameTypeIT.java
@@ -4,6 +4,7 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.dependent.multiplemanageddependentsametype.MultipleManagedDependentResourceSpec;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import io.javaoperatorsdk.operator.support.ExternalServiceMock;
@@ -11,6 +12,14 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Multiple Managed External Dependents of Same Type",
+ description =
+ """
+ Tests managing multiple external (non-Kubernetes) dependent resources of the same type. \
+ This demonstrates that operators can manage multiple instances of external resources \
+ simultaneously, handling their lifecycle including creation, updates, and deletion.
+ """)
class MultipleManagedExternalDependentSameTypeIT {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipleupdateondependent/MultiOwnerDependentTriggeringIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipleupdateondependent/MultiOwnerDependentTriggeringIT.java
index d5a704ca0c..975e30ecf3 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipleupdateondependent/MultiOwnerDependentTriggeringIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/multipleupdateondependent/MultiOwnerDependentTriggeringIT.java
@@ -7,11 +7,21 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Dependent Resource Shared by Multiple Owners",
+ description =
+ """
+ Demonstrates a dependent resource (ConfigMap) that is managed by multiple primary \
+ resources simultaneously. Tests verify that updates from any owner trigger proper \
+ reconciliation, owner references are correctly maintained, and the shared resource \
+ properly aggregates data from all owners.
+ """)
class MultiOwnerDependentTriggeringIT {
public static final String VALUE_1 = "value1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/prevblocklist/PrevAnnotationBlockReconcilerIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/prevblocklist/PrevAnnotationBlockReconcilerIT.java
index 137e2ba663..375327376c 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/prevblocklist/PrevAnnotationBlockReconcilerIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/prevblocklist/PrevAnnotationBlockReconcilerIT.java
@@ -7,11 +7,21 @@
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.apps.Deployment;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Blocking Previous Annotation for Specific Resource Types",
+ description =
+ """
+ Tests the previous annotation blocklist feature, which prevents storing previous resource \
+ state annotations for specific resource types like Deployments. This optimization avoids \
+ unnecessary reconciliation loops for resources that have server-side mutations, improving \
+ performance and stability.
+ """)
class PrevAnnotationBlockReconcilerIT {
public static final String TEST_1 = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/primaryindexer/DependentPrimaryIndexerIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/primaryindexer/DependentPrimaryIndexerIT.java
index 16bb0d46a7..774a446188 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/primaryindexer/DependentPrimaryIndexerIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/primaryindexer/DependentPrimaryIndexerIT.java
@@ -1,8 +1,18 @@
package io.javaoperatorsdk.operator.dependent.primaryindexer;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.baseapi.primaryindexer.PrimaryIndexerIT;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
+@Sample(
+ tldr = "Primary Resource Indexer with Dependent Resources",
+ description =
+ """
+ Extends PrimaryIndexerIT to test primary resource indexing functionality with dependent \
+ resources. Demonstrates how custom indexes on primary resources can be used to efficiently \
+ query and access resources within dependent resource implementations, enabling performant \
+ lookups.
+ """)
public class DependentPrimaryIndexerIT extends PrimaryIndexerIT {
protected LocallyRunOperatorExtension buildOperator() {
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/primarytosecondaydependent/PrimaryToSecondaryDependentIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/primarytosecondaydependent/PrimaryToSecondaryDependentIT.java
index 11a080a8bf..212fb1e3de 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/primarytosecondaydependent/PrimaryToSecondaryDependentIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/primarytosecondaydependent/PrimaryToSecondaryDependentIT.java
@@ -9,6 +9,7 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.Secret;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.dependent.primarytosecondaydependent.ConfigMapDependent.TEST_CONFIG_MAP_NAME;
@@ -17,6 +18,16 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Primary to Secondary Dependent Resource",
+ description =
+ """
+ Demonstrates how to configure dependencies between dependent resources where one \
+ dependent resource (secondary) depends on another dependent resource (primary). \
+ This test shows how a Secret's creation can be conditioned on the state of a \
+ ConfigMap, illustrating the use of reconcile preconditions and dependent resource \
+ chaining.
+ """)
class PrimaryToSecondaryDependentIT {
public static final String TEST_CR_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/restart/OperatorRestartIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/restart/OperatorRestartIT.java
index b8adb562dd..32923d0843 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/restart/OperatorRestartIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/restart/OperatorRestartIT.java
@@ -3,12 +3,21 @@
import org.junit.jupiter.api.*;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.Operator;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Operator restart and state recovery",
+ description =
+ """
+ Tests that an operator can be stopped and restarted while maintaining correct behavior. \
+ After restart, the operator should resume processing existing resources without \
+ losing track of their state, demonstrating proper state recovery and persistence.
+ """)
class OperatorRestartIT {
private static final Operator operator = new Operator(o -> o.withCloseClientOnStop(false));
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/servicestrictmatcher/ServiceStrictMatcherIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/servicestrictmatcher/ServiceStrictMatcherIT.java
index 72edd4ae40..4742a5d621 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/servicestrictmatcher/ServiceStrictMatcherIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/servicestrictmatcher/ServiceStrictMatcherIT.java
@@ -6,11 +6,20 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Strict matching for Service resources",
+ description =
+ """
+ Shows how to use a strict matcher for Service dependent resources that correctly handles \
+ Service-specific fields. This prevents unnecessary updates when Kubernetes adds \
+ default values or modifies certain fields, avoiding reconciliation loops.
+ """)
public class ServiceStrictMatcherIT {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/specialresourcesdependent/SpecialResourcesDependentIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/specialresourcesdependent/SpecialResourcesDependentIT.java
index 3d62512bd7..58265b22b5 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/specialresourcesdependent/SpecialResourcesDependentIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/specialresourcesdependent/SpecialResourcesDependentIT.java
@@ -5,6 +5,7 @@
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.ServiceAccount;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.dependent.specialresourcesdependent.SpecialResourceSpec.CHANGED_VALUE;
@@ -16,6 +17,15 @@
* Test for resources that are somehow special, currently mostly to cover the approach to handle
* resources without spec. Not all the resources added here.
*/
+@Sample(
+ tldr = "Handling special Kubernetes resources without spec",
+ description =
+ """
+ Demonstrates how to handle special built-in Kubernetes resources like ServiceAccount that \
+ don't have a spec field. These resources require different handling approaches \
+ since their configuration is stored directly in the resource body rather than in a \
+ spec section.
+ """)
public class SpecialResourcesDependentIT {
public static final String RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/ssalegacymatcher/SSAWithLegacyMatcherIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/ssalegacymatcher/SSAWithLegacyMatcherIT.java
index 63afd73d1a..42cf9cf8e7 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/ssalegacymatcher/SSAWithLegacyMatcherIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/ssalegacymatcher/SSAWithLegacyMatcherIT.java
@@ -5,11 +5,21 @@
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.Service;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Using Legacy Resource Matcher with SSA",
+ description =
+ """
+ Demonstrates using the legacy resource matcher with Server-Side Apply (SSA). The legacy \
+ matcher provides backward compatibility for matching logic while using SSA for updates, \
+ ensuring that resource comparisons work correctly even when migrating from traditional \
+ update methods to SSA.
+ """)
public class SSAWithLegacyMatcherIT {
public static final String TEST_RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/standalonedependent/StandaloneDependentResourceIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/standalonedependent/StandaloneDependentResourceIT.java
index 91fbd64a19..9e8f383b84 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/standalonedependent/StandaloneDependentResourceIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/standalonedependent/StandaloneDependentResourceIT.java
@@ -9,6 +9,7 @@
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.kubernetes.api.model.apps.Deployment;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.api.config.*;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
@@ -16,6 +17,17 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Standalone Dependent Resources",
+ description =
+ """
+ Demonstrates how to use standalone dependent resources that are managed independently \
+ without explicit workflow configuration. This test shows how dependent resources \
+ can be created and managed programmatically, with the dependent resource handling \
+ CRUD operations on a Kubernetes Deployment. The test verifies both creation and \
+ update scenarios, including cache updates when the dependent resource state \
+ changes.
+ """)
public class StandaloneDependentResourceIT {
public static final String DEPENDENT_TEST_NAME = "dependent-test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/statefulsetdesiredsanitizer/StatefulSetDesiredSanitizerIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/statefulsetdesiredsanitizer/StatefulSetDesiredSanitizerIT.java
index f54708a9ea..fd51afb4e0 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/statefulsetdesiredsanitizer/StatefulSetDesiredSanitizerIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/dependent/statefulsetdesiredsanitizer/StatefulSetDesiredSanitizerIT.java
@@ -7,11 +7,20 @@
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.apps.StatefulSet;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Sanitizing StatefulSet desired state for SSA",
+ description =
+ """
+ Shows how to properly sanitize StatefulSet resources before using Server-Side Apply. \
+ StatefulSets have immutable fields and server-managed fields that need to be \
+ removed from the desired state to prevent conflicts and unnecessary updates.
+ """)
public class StatefulSetDesiredSanitizerIT {
public static final String TEST_1 = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/complexdependent/ComplexWorkflowIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/complexdependent/ComplexWorkflowIT.java
index 4af8467c5c..8baed835b1 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/complexdependent/ComplexWorkflowIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/complexdependent/ComplexWorkflowIT.java
@@ -9,6 +9,7 @@
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.apps.StatefulSet;
import io.fabric8.kubernetes.client.readiness.Readiness;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import io.javaoperatorsdk.operator.workflow.complexdependent.dependent.FirstService;
import io.javaoperatorsdk.operator.workflow.complexdependent.dependent.FirstStatefulSet;
@@ -18,6 +19,14 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Complex Workflow with Multiple Dependents",
+ description =
+ """
+ Demonstrates a complex workflow with multiple dependent resources (StatefulSets and \
+ Services) that have dependencies on each other. This test shows how to orchestrate \
+ the reconciliation of interconnected dependent resources in a specific order.
+ """)
class ComplexWorkflowIT {
public static final String TEST_RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/crdpresentactivation/CRDPresentActivationConditionIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/crdpresentactivation/CRDPresentActivationConditionIT.java
index 1793cceefa..a6a77d8a6e 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/crdpresentactivation/CRDPresentActivationConditionIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/crdpresentactivation/CRDPresentActivationConditionIT.java
@@ -8,11 +8,21 @@
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinition;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Workflow Activation Based on CRD Presence",
+ description =
+ """
+ Tests workflow activation conditions that depend on the presence of specific Custom \
+ Resource Definitions (CRDs). Dependent resources are only created when their corresponding \
+ CRDs exist in the cluster, allowing operators to gracefully handle optional dependencies \
+ and multi-cluster scenarios.
+ """)
public class CRDPresentActivationConditionIT {
public static final String TEST_1 = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/getnonactivesecondary/WorkflowActivationConditionIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/getnonactivesecondary/WorkflowActivationConditionIT.java
index 0de986ccf9..156ba5b7fd 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/getnonactivesecondary/WorkflowActivationConditionIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/getnonactivesecondary/WorkflowActivationConditionIT.java
@@ -4,11 +4,21 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Workflow Functions on Vanilla Kubernetes Despite Inactive Resources",
+ description =
+ """
+ Verifies that workflows function correctly on vanilla Kubernetes even when they include \
+ resources that are not available on the platform (like OpenShift Routes). The operator \
+ successfully reconciles by skipping inactive dependents based on activation conditions, \
+ demonstrating platform-agnostic operator design.
+ """)
public class WorkflowActivationConditionIT {
public static final String TEST_RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/manageddependentdeletecondition/ManagedDependentDeleteConditionIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/manageddependentdeletecondition/ManagedDependentDeleteConditionIT.java
index 482d2e5091..1c382247b8 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/manageddependentdeletecondition/ManagedDependentDeleteConditionIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/manageddependentdeletecondition/ManagedDependentDeleteConditionIT.java
@@ -9,11 +9,21 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.Secret;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Managed Dependent Delete Condition",
+ description =
+ """
+ Demonstrates how to use delete conditions to control when dependent resources can be \
+ deleted. This test shows how the primary resource deletion can be blocked until \
+ dependent resources are properly cleaned up, ensuring graceful shutdown and \
+ preventing orphaned resources.
+ """)
public class ManagedDependentDeleteConditionIT {
public static final String RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/multipledependentwithactivation/MultipleDependentWithActivationIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/multipledependentwithactivation/MultipleDependentWithActivationIT.java
index 2360660adc..4845dfe476 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/multipledependentwithactivation/MultipleDependentWithActivationIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/multipledependentwithactivation/MultipleDependentWithActivationIT.java
@@ -6,11 +6,21 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.Secret;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Multiple Dependents with Activation Conditions",
+ description =
+ """
+ Demonstrates how to use activation conditions with multiple dependent resources. This test \
+ shows how different dependent resources can be dynamically enabled or disabled \
+ based on runtime conditions, allowing flexible workflow behavior that adapts to \
+ changing requirements.
+ """)
public class MultipleDependentWithActivationIT {
public static final String INITIAL_VALUE = "initial_value";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/orderedmanageddependent/OrderedManagedDependentIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/orderedmanageddependent/OrderedManagedDependentIT.java
index ff25911a8c..56ff94d1f1 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/orderedmanageddependent/OrderedManagedDependentIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/orderedmanageddependent/OrderedManagedDependentIT.java
@@ -6,11 +6,20 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMeta;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Ordered Managed Dependent Resources",
+ description =
+ """
+ Demonstrates how to control the order of reconciliation for managed dependent resources. \
+ This test verifies that dependent resources are reconciled in a specific sequence, \
+ ensuring proper orchestration when dependencies have ordering requirements.
+ """)
class OrderedManagedDependentIT {
@RegisterExtension
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowactivationcleanup/WorkflowActivationCleanupIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowactivationcleanup/WorkflowActivationCleanupIT.java
index 80bbf22d40..3c366877fd 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowactivationcleanup/WorkflowActivationCleanupIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowactivationcleanup/WorkflowActivationCleanupIT.java
@@ -8,12 +8,21 @@
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.Operator;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Workflow Activation Cleanup",
+ description =
+ """
+ Demonstrates how workflow cleanup is handled when activation conditions are involved. This \
+ test verifies that resources are properly cleaned up on operator startup even when \
+ marked for deletion, ensuring no orphaned resources remain after restarts.
+ """)
public class WorkflowActivationCleanupIT {
private final KubernetesClient client = new KubernetesClientBuilder().build();
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowactivationcondition/WorkflowActivationConditionIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowactivationcondition/WorkflowActivationConditionIT.java
index a5b5b23fe3..108a7d4a54 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowactivationcondition/WorkflowActivationConditionIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowactivationcondition/WorkflowActivationConditionIT.java
@@ -5,12 +5,22 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.workflow.workflowactivationcondition.ConfigMapDependentResource.DATA_KEY;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Workflow Activation Condition",
+ description =
+ """
+ Demonstrates how to use activation conditions to conditionally enable or disable parts of \
+ a workflow. This test shows how the workflow can adapt to different environments \
+ (e.g., vanilla Kubernetes vs. OpenShift) by activating only the relevant dependent \
+ resources based on runtime conditions.
+ """)
public class WorkflowActivationConditionIT {
public static final String TEST_RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowallfeature/WorkflowAllFeatureIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowallfeature/WorkflowAllFeatureIT.java
index 93551dcf43..9cf798033a 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowallfeature/WorkflowAllFeatureIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowallfeature/WorkflowAllFeatureIT.java
@@ -9,12 +9,22 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.apps.Deployment;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.workflow.workflowallfeature.ConfigMapDependentResource.READY_TO_DELETE_ANNOTATION;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Comprehensive workflow with reconcile and delete conditions",
+ description =
+ """
+ Demonstrates a complete workflow implementation including reconcile conditions, delete \
+ conditions, and ready conditions. Shows how to control when dependent resources are \
+ created or deleted based on conditions, and how to coordinate dependencies that \
+ must wait for others to be ready.
+ """)
public class WorkflowAllFeatureIT {
public static final String RESOURCE_NAME = "test";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowexplicitcleanup/WorkflowExplicitCleanupIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowexplicitcleanup/WorkflowExplicitCleanupIT.java
index b6d4969fd3..a0227de13b 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowexplicitcleanup/WorkflowExplicitCleanupIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowexplicitcleanup/WorkflowExplicitCleanupIT.java
@@ -5,11 +5,21 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Explicit Workflow Cleanup Invocation",
+ description =
+ """
+ Tests explicit workflow cleanup invocation, demonstrating that workflow cleanup is called \
+ even when using explicit workflow invocation mode. This ensures that dependent resources \
+ are properly cleaned up during deletion regardless of how the workflow is invoked, \
+ maintaining consistent cleanup behavior.
+ """)
public class WorkflowExplicitCleanupIT {
public static final String RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowexplicitinvocation/WorkflowExplicitInvocationIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowexplicitinvocation/WorkflowExplicitInvocationIT.java
index eaa799300f..8027750346 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowexplicitinvocation/WorkflowExplicitInvocationIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowexplicitinvocation/WorkflowExplicitInvocationIT.java
@@ -7,11 +7,21 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Workflow Explicit Invocation",
+ description =
+ """
+ Demonstrates how to explicitly control when a workflow is invoked rather than having it \
+ run automatically on every reconciliation. This test shows how to programmatically \
+ trigger workflow execution and how cleanup is still performed even with explicit \
+ invocation.
+ """)
public class WorkflowExplicitInvocationIT {
public static final String RESOURCE_NAME = "test1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowmultipleactivation/WorkflowMultipleActivationIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowmultipleactivation/WorkflowMultipleActivationIT.java
index 0d5f3b60f1..cd40d2c08a 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowmultipleactivation/WorkflowMultipleActivationIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowmultipleactivation/WorkflowMultipleActivationIT.java
@@ -8,12 +8,22 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.Secret;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static io.javaoperatorsdk.operator.workflow.workflowactivationcondition.ConfigMapDependentResource.DATA_KEY;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Dynamic Workflow Activation and Deactivation",
+ description =
+ """
+ Tests dynamic activation and deactivation of workflow dependents based on changing \
+ conditions. Demonstrates that dependents can be conditionally activated or deactivated \
+ during the resource lifecycle, with proper cleanup and recreation, and verifies that \
+ inactive dependents don't trigger reconciliation or maintain informers.
+ """)
public class WorkflowMultipleActivationIT {
public static final String INITIAL_DATA = "initial data";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowsilentexceptionhandling/WorkflowSilentExceptionHandlingIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowsilentexceptionhandling/WorkflowSilentExceptionHandlingIT.java
index 2f5b7246c6..926d7d7622 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowsilentexceptionhandling/WorkflowSilentExceptionHandlingIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/workflow/workflowsilentexceptionhandling/WorkflowSilentExceptionHandlingIT.java
@@ -4,11 +4,21 @@
import org.junit.jupiter.api.extension.RegisterExtension;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.annotation.Sample;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+@Sample(
+ tldr = "Silent Workflow Exception Handling in Reconciler",
+ description =
+ """
+ Demonstrates handling workflow exceptions silently within the reconciler rather than \
+ propagating them. Tests verify that exceptions from dependent resources during both \
+ reconciliation and cleanup are captured in the result object, allowing custom error \
+ handling logic without failing the entire reconciliation.
+ """)
public class WorkflowSilentExceptionHandlingIT {
@RegisterExtension
diff --git a/pom.xml b/pom.xml
index 9931eefb7f..c2e6ae8443 100644
--- a/pom.xml
+++ b/pom.xml
@@ -36,6 +36,7 @@
sample-operators
caffeine-bounded-cache-support
bootstrapper-maven-plugin
+ test-index-processor
diff --git a/test-index-processor/pom.xml b/test-index-processor/pom.xml
new file mode 100644
index 0000000000..dc3e84ab3e
--- /dev/null
+++ b/test-index-processor/pom.xml
@@ -0,0 +1,31 @@
+
+
+ 4.0.0
+
+
+ io.javaoperatorsdk
+ java-operator-sdk
+ 5.1.6-SNAPSHOT
+
+
+ test-index-processor
+ Test Index Annotation Processor
+ Annotation processor for generating integration test index documentation
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ -proc:none
+
+
+
+
+
diff --git a/test-index-processor/src/main/java/io/javaoperatorsdk/annotation/Sample.java b/test-index-processor/src/main/java/io/javaoperatorsdk/annotation/Sample.java
new file mode 100644
index 0000000000..3bfb1a4e79
--- /dev/null
+++ b/test-index-processor/src/main/java/io/javaoperatorsdk/annotation/Sample.java
@@ -0,0 +1,29 @@
+package io.javaoperatorsdk.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to mark integration tests as samples for documentation generation. Tests annotated
+ * with @Sample will be included in the generated samples.md documentation file.
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface Sample {
+
+ /**
+ * A short title describing the test sample.
+ *
+ * @return the short title
+ */
+ String tldr();
+
+ /**
+ * A detailed description of what the test does and demonstrates.
+ *
+ * @return the detailed description
+ */
+ String description();
+}
diff --git a/test-index-processor/src/main/java/io/javaoperatorsdk/processor/SampleProcessor.java b/test-index-processor/src/main/java/io/javaoperatorsdk/processor/SampleProcessor.java
new file mode 100644
index 0000000000..d59e7bf687
--- /dev/null
+++ b/test-index-processor/src/main/java/io/javaoperatorsdk/processor/SampleProcessor.java
@@ -0,0 +1,143 @@
+package io.javaoperatorsdk.processor;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+
+import io.javaoperatorsdk.annotation.Sample;
+
+/**
+ * Annotation processor that generates a samples.md file containing documentation for all
+ * integration tests annotated with @Sample.
+ */
+@SupportedAnnotationTypes("io.javaoperatorsdk.annotation.Sample")
+@SupportedSourceVersion(SourceVersion.RELEASE_17)
+public class SampleProcessor extends AbstractProcessor {
+
+ private final List samples = new ArrayList<>();
+ private boolean processed = false;
+
+ @Override
+ public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ if (processed) {
+ return true;
+ }
+
+ // Collect all @Sample annotated elements
+ for (Element element : roundEnv.getElementsAnnotatedWith(Sample.class)) {
+ if (element instanceof TypeElement) {
+ TypeElement typeElement = (TypeElement) element;
+ Sample sample = element.getAnnotation(Sample.class);
+
+ String className = typeElement.getQualifiedName().toString();
+ String simpleName = typeElement.getSimpleName().toString();
+ String tldr = sample.tldr();
+ String description = sample.description();
+
+ samples.add(new SampleInfo(className, simpleName, tldr, description));
+ }
+ }
+
+ // Generate the markdown file in the last round
+ if (roundEnv.processingOver() && !samples.isEmpty()) {
+ generateMarkdownFile();
+ processed = true;
+ }
+
+ return true;
+ }
+
+ private void generateMarkdownFile() {
+ try {
+ // Sort samples by class name for consistent ordering
+ samples.sort(Comparator.comparing(s -> s.className));
+
+ // Create the samples.md file in the source output location
+ FileObject file =
+ processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", "samples.md");
+
+ try (BufferedWriter writer = new BufferedWriter(file.openWriter())) {
+ writer.write("---\n");
+ writer.write("title: Integration Test Index\n");
+ writer.write("weight: 105\n");
+ writer.write("---\n\n");
+ writer.write(
+ "This document provides an index of all integration tests annotated with @Sample.\n\n"
+ + "These server also as sample for various use cases. "
+ + "Your are encouraged to improve both the tests and/or descriptions.\n\n");
+
+ // Generate table of contents
+ writer.write("## Contents\n\n");
+ for (SampleInfo sample : samples) {
+ String anchor = sample.simpleName.toLowerCase();
+ writer.write("- [" + sample.tldr + "](#" + anchor + ")\n");
+ }
+ writer.write("\n---\n\n");
+
+ // Generate individual test sections
+ for (SampleInfo sample : samples) {
+ writer.write("## " + sample.simpleName + "\n\n");
+ writer.write("**" + sample.tldr + "**\n\n");
+ writer.write(sample.description + "\n\n");
+ writer.write("**Package:** " + getGitHubPackageLink(sample.className) + "\n\n");
+ writer.write("---\n\n");
+ }
+ }
+
+ processingEnv
+ .getMessager()
+ .printMessage(
+ Diagnostic.Kind.NOTE, "Generated samples.md with " + samples.size() + " samples");
+ } catch (IOException e) {
+ processingEnv
+ .getMessager()
+ .printMessage(Diagnostic.Kind.ERROR, "Failed to generate samples.md: " + e.getMessage());
+ }
+ }
+
+ private String getGitHubPackageLink(String className) {
+ // Extract package name by removing the simple class name
+ int lastDot = className.lastIndexOf('.');
+ if (lastDot == -1) {
+ return "[root package]";
+ }
+
+ String packageName = className.substring(0, lastDot);
+ String packagePath = packageName.replace('.', '/');
+
+ // GitHub repository base URL
+ String baseUrl = "https://github.com/operator-framework/java-operator-sdk/tree/main";
+ String sourcePath = "operator-framework/src/test/java";
+
+ String githubUrl = baseUrl + "/" + sourcePath + "/" + packagePath;
+ return "[" + packageName + "](" + githubUrl + ")";
+ }
+
+ private static class SampleInfo {
+ final String className;
+ final String simpleName;
+ final String tldr;
+ final String description;
+
+ SampleInfo(String className, String simpleName, String tldr, String description) {
+ this.className = className;
+ this.simpleName = simpleName;
+ this.tldr = tldr;
+ this.description = description;
+ }
+ }
+}
diff --git a/test-index-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/test-index-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 0000000000..a9fb2eb851
--- /dev/null
+++ b/test-index-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1 @@
+io.javaoperatorsdk.processor.SampleProcessor