diff --git a/integration-tests/cdi/pom.xml b/integration-tests/cdi/pom.xml
new file mode 100644
index 000000000..acaf34a98
--- /dev/null
+++ b/integration-tests/cdi/pom.xml
@@ -0,0 +1,160 @@
+
+
+ 4.0.0
+
+ io.quarkiverse.operatorsdk
+ quarkus-operator-sdk-integration-tests-parent
+ 7.3.1-SNAPSHOT
+ ../pom.xml
+
+ quarkus-operator-sdk-integration-tests-cdi
+ Quarkus - Operator SDK - Integration Tests - CDI
+
+
+ io.quarkus
+ quarkus-resteasy
+
+
+ io.quarkiverse.operatorsdk
+ quarkus-operator-sdk
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+ io.quarkus
+ quarkus-test-kubernetes-client
+ test
+
+
+ io.quarkus
+ quarkus-resteasy-jackson
+
+
+ io.rest-assured
+ rest-assured
+ test
+
+
+ org.awaitility
+ awaitility
+ test
+
+
+
+ io.quarkus
+ quarkus-micrometer-registry-prometheus
+
+
+ org.bouncycastle
+ bcpkix-jdk18on
+ true
+
+
+
+
+
+ io.quarkus
+ quarkus-maven-plugin
+
+
+
+ build
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ test-jar
+
+
+
+
+
+ maven-surefire-plugin
+
+
+ fromEnvVarNS
+ fromEnv1,fromEnv2
+
+ variableNSFromEnv
+ JOSDK_ALL_NAMESPACES
+
+
+
+
+
+
+
+
+ native-image
+
+
+ native
+
+
+
+
+
+ maven-surefire-plugin
+
+ ${native.surefire.skip}
+
+ org.jboss.logmanager.LogManager
+
+ ${maven.home}
+
+
+ fromEnvVarNS
+ fromEnv1,fromEnv2
+
+ variableNSFromEnv
+ JOSDK_ALL_NAMESPACES
+
+
+
+
+
+ maven-failsafe-plugin
+
+
+
+ integration-test
+ verify
+
+
+
+
+ ${project.build.directory}/${project.build.finalName}-runner
+
+ org.jboss.logmanager.LogManager
+
+ ${maven.home}
+
+
+ fromEnvVarNS
+ fromEnv1,fromEnv2
+
+ variableNSFromEnv
+ JOSDK_ALL_NAMESPACES
+
+
+
+
+
+
+
+
+
+ native
+
+
+
+
diff --git a/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/ConfigMapDependent.java b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/ConfigMapDependent.java
new file mode 100644
index 000000000..a37c47652
--- /dev/null
+++ b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/ConfigMapDependent.java
@@ -0,0 +1,57 @@
+package io.quarkiverse.operatorsdk.it.cdi;
+
+import java.util.Map;
+import java.util.Optional;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.fabric8.kubernetes.api.model.ConfigMap;
+import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
+import io.javaoperatorsdk.operator.processing.event.ResourceID;
+
+public class ConfigMapDependent extends CRUDKubernetesDependentResource {
+
+ private static final Logger log = LoggerFactory.getLogger(ConfigMapDependent.class);
+
+ @Override
+ protected ConfigMap desired(TestResource primary, Context context) {
+ Optional optionalConfigMap = getConfigMap(primary, context);
+ if (!optionalConfigMap.isPresent()) {
+ ConfigMap configMap = new ConfigMap();
+ configMap.setMetadata(
+ new ObjectMetaBuilder()
+ .withName(primary.getMetadata().getName() + "-cm")
+ .withNamespace(primary.getMetadata().getNamespace())
+ .build());
+ configMap.setData(Map.of("key", "data"));
+ return configMap;
+ }
+ return optionalConfigMap.get();
+ }
+
+ @Override
+ public void delete(TestResource primary, Context context) {
+ Optional optionalConfigMap = getConfigMap(primary, context);
+ if (optionalConfigMap == null)
+ return;
+ optionalConfigMap.ifPresent(
+ (configMap -> {
+ if (configMap.getMetadata().getAnnotations() != null) {
+ context.getClient().resource(configMap).delete();
+ }
+ }));
+
+ }
+
+ private static Optional getConfigMap(TestResource primary, Context context) {
+ Optional optionalConfigMap = context.getSecondaryResource(ConfigMap.class);
+ if (optionalConfigMap.isEmpty()) {
+ log.debug("Config Map not found for primary: {}", ResourceID.fromResource(primary));
+ return Optional.empty();
+ }
+ return optionalConfigMap;
+ }
+}
diff --git a/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/CustomActionvationCondition.java b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/CustomActionvationCondition.java
new file mode 100644
index 000000000..2d8fdaa28
--- /dev/null
+++ b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/CustomActionvationCondition.java
@@ -0,0 +1,30 @@
+package io.quarkiverse.operatorsdk.it.cdi;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+
+import io.fabric8.kubernetes.api.model.HasMetadata;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
+import io.quarkus.arc.Unremovable;
+
+@ApplicationScoped
+@Unremovable
+public class CustomActionvationCondition implements Condition {
+
+ @Inject
+ TestUUIDBean testUUIDBean;
+
+ private String uuid;
+
+ @Override
+ public boolean isMet(DependentResource dependentResource, HasMetadata primary, Context context) {
+ uuid = testUUIDBean.uuid();
+ return true;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+}
diff --git a/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/DeletePostCondition.java b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/DeletePostCondition.java
new file mode 100644
index 000000000..9a98697f6
--- /dev/null
+++ b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/DeletePostCondition.java
@@ -0,0 +1,30 @@
+package io.quarkiverse.operatorsdk.it.cdi;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+
+import io.fabric8.kubernetes.api.model.HasMetadata;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
+import io.quarkus.arc.Unremovable;
+
+@ApplicationScoped
+@Unremovable
+public class DeletePostCondition implements Condition {
+
+ @Inject
+ TestUUIDBean testUUIDBean;
+
+ private String uuid;
+
+ @Override
+ public boolean isMet(DependentResource dependentResource, HasMetadata primary, Context context) {
+ this.uuid = testUUIDBean.uuid();
+ return true;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+}
diff --git a/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/DeploymentDependent.java b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/DeploymentDependent.java
new file mode 100644
index 000000000..27a9d5dce
--- /dev/null
+++ b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/DeploymentDependent.java
@@ -0,0 +1,37 @@
+package io.quarkiverse.operatorsdk.it.cdi;
+
+import java.util.Map;
+
+import org.jboss.logging.Logger;
+
+import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.fabric8.kubernetes.api.model.apps.Deployment;
+import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDNoGCKubernetesDependentResource;
+
+public class DeploymentDependent extends CRUDNoGCKubernetesDependentResource {
+
+ private static final Logger LOG = Logger.getLogger(DeploymentDependent.class);
+
+ @Override
+ protected Deployment desired(TestResource primary, Context context) {
+ return new DeploymentBuilder()
+ .withMetadata(new ObjectMetaBuilder()
+ .withName(primary.getMetadata().getName() + "-deployment")
+ .withNamespace("default")
+ .withLabels(Map.of("app", primary.getMetadata().getName()))
+ .build())
+ .withNewSpec()
+ .withNewSelector().withMatchLabels(Map.of("app", primary.getMetadata().getName())).endSelector()
+ .withNewTemplate().withNewMetadata().withLabels(Map.of("app", primary.getMetadata().getName())).endMetadata()
+ .withNewSpec().addNewContainer()
+ .withName("nginx").withImage("nginx:1.14.2")
+ .addNewPort().withName("http").withProtocol("TCP").withContainerPort(8080).endPort()
+ .endContainer()
+ .endSpec()
+ .endTemplate()
+ .endSpec()
+ .build();
+ }
+}
diff --git a/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/ReadyPostCondition.java b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/ReadyPostCondition.java
new file mode 100644
index 000000000..c3ea0b013
--- /dev/null
+++ b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/ReadyPostCondition.java
@@ -0,0 +1,34 @@
+package io.quarkiverse.operatorsdk.it.cdi;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+
+import io.fabric8.kubernetes.api.model.apps.Deployment;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
+import io.quarkus.arc.Unremovable;
+
+@ApplicationScoped
+@Unremovable
+public class ReadyPostCondition implements Condition {
+
+ @Inject
+ TestUUIDBean testUUIDBean;
+
+ private String uuid;
+
+ @Override
+ public boolean isMet(DependentResource dependentResource, TestResource primary,
+ Context context) {
+ uuid = testUUIDBean.uuid();
+ return dependentResource
+ .getSecondaryResource(primary, context)
+ .map(deployment -> deployment.getSpec().getReplicas().equals(1))
+ .orElse(false);
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+}
diff --git a/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/ReconcilePrecondition.java b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/ReconcilePrecondition.java
new file mode 100644
index 000000000..f17dbe697
--- /dev/null
+++ b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/ReconcilePrecondition.java
@@ -0,0 +1,31 @@
+package io.quarkiverse.operatorsdk.it.cdi;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+
+import io.fabric8.kubernetes.api.model.HasMetadata;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
+import io.quarkus.arc.Unremovable;
+
+@ApplicationScoped
+@Unremovable
+public class ReconcilePrecondition implements Condition {
+
+ @Inject
+ TestUUIDBean testUUIDBean;
+
+ private String uuid;
+
+ @Override
+
+ public boolean isMet(DependentResource dependentResource, HasMetadata primary, Context context) {
+ uuid = testUUIDBean.uuid();
+ return true;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+}
diff --git a/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/TestReconciler.java b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/TestReconciler.java
new file mode 100644
index 000000000..86a957b85
--- /dev/null
+++ b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/TestReconciler.java
@@ -0,0 +1,30 @@
+package io.quarkiverse.operatorsdk.it.cdi;
+
+import io.javaoperatorsdk.operator.api.reconciler.Cleaner;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
+import io.javaoperatorsdk.operator.api.reconciler.DeleteControl;
+import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
+import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+import io.javaoperatorsdk.operator.api.reconciler.Workflow;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
+
+@Workflow(dependents = {
+ @Dependent(name = TestReconciler.DEPLOYMENT, type = DeploymentDependent.class, activationCondition = CustomActionvationCondition.class, readyPostcondition = ReadyPostCondition.class, reconcilePrecondition = ReconcilePrecondition.class),
+ @Dependent(type = ConfigMapDependent.class, deletePostcondition = DeletePostCondition.class, dependsOn = TestReconciler.DEPLOYMENT)
+})
+@ControllerConfiguration
+public class TestReconciler implements Reconciler, Cleaner {
+
+ public static final String DEPLOYMENT = "deployment";
+
+ @Override
+ public UpdateControl reconcile(TestResource resource, Context context) throws Exception {
+ return UpdateControl.noUpdate();
+ }
+
+ @Override
+ public DeleteControl cleanup(TestResource resource, Context context) throws Exception {
+ return DeleteControl.defaultDelete();
+ }
+}
diff --git a/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/TestResource.java b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/TestResource.java
new file mode 100644
index 000000000..fec60654a
--- /dev/null
+++ b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/TestResource.java
@@ -0,0 +1,12 @@
+package io.quarkiverse.operatorsdk.it.cdi;
+
+import io.fabric8.kubernetes.client.CustomResource;
+import io.fabric8.kubernetes.model.annotation.Group;
+import io.fabric8.kubernetes.model.annotation.ShortNames;
+import io.fabric8.kubernetes.model.annotation.Version;
+
+@Group("josdk.quarkiverse.io")
+@Version("v1alpha1")
+@ShortNames("tr")
+public class TestResource extends CustomResource {
+}
diff --git a/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/TestSpec.java b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/TestSpec.java
new file mode 100644
index 000000000..6e8d7188c
--- /dev/null
+++ b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/TestSpec.java
@@ -0,0 +1,4 @@
+package io.quarkiverse.operatorsdk.it.cdi;
+
+public class TestSpec {
+}
diff --git a/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/TestStatus.java b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/TestStatus.java
new file mode 100644
index 000000000..f0cda6bf4
--- /dev/null
+++ b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/TestStatus.java
@@ -0,0 +1,12 @@
+package io.quarkiverse.operatorsdk.it.cdi;
+
+public class TestStatus {
+ public String value;
+
+ public TestStatus() {
+ }
+
+ public TestStatus(String value) {
+ this.value = value;
+ }
+}
diff --git a/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/TestUUIDBean.java b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/TestUUIDBean.java
new file mode 100644
index 000000000..686f74e4c
--- /dev/null
+++ b/integration-tests/cdi/src/main/java/io/quarkiverse/operatorsdk/it/cdi/TestUUIDBean.java
@@ -0,0 +1,15 @@
+package io.quarkiverse.operatorsdk.it.cdi;
+
+import java.util.UUID;
+
+import jakarta.enterprise.context.ApplicationScoped;
+
+@ApplicationScoped
+public class TestUUIDBean {
+
+ private final String id = UUID.randomUUID().toString();
+
+ public String uuid() {
+ return id;
+ }
+}
diff --git a/integration-tests/cdi/src/main/resources/application.properties b/integration-tests/cdi/src/main/resources/application.properties
new file mode 100644
index 000000000..e69de29bb
diff --git a/integration-tests/cdi/src/test/java/io/quarkiverse/operatorsdk/it/cdi/ConditionsCDITest.java b/integration-tests/cdi/src/test/java/io/quarkiverse/operatorsdk/it/cdi/ConditionsCDITest.java
new file mode 100644
index 000000000..4da761bb6
--- /dev/null
+++ b/integration-tests/cdi/src/test/java/io/quarkiverse/operatorsdk/it/cdi/ConditionsCDITest.java
@@ -0,0 +1,80 @@
+package io.quarkiverse.operatorsdk.it.cdi;
+
+import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.time.Duration;
+
+import jakarta.inject.Inject;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.fabric8.kubernetes.client.KubernetesClient;
+import io.quarkus.test.junit.QuarkusTest;
+
+/**
+ * Verify that the Condition subclasses are properly recognized as CDI beans.
+ */
+@QuarkusTest
+class ConditionsCDITest {
+
+ private static final Duration timeout = Duration.ofSeconds(30);
+
+ @Inject
+ KubernetesClient kubernetesClient;
+
+ @Inject
+ TestUUIDBean testUUIDBean;
+
+ @Inject
+ ReadyPostCondition readyPostCondition;
+
+ @Inject
+ CustomActionvationCondition customActionvationCondition;
+
+ @Inject
+ ReconcilePrecondition reconcilePrecondition;
+
+ @Inject
+ DeletePostCondition deletePostCondition;
+
+ @AfterEach
+ void cleanup() {
+ kubernetesClient.apiextensions().v1().customResourceDefinitions().withName("testresources.josdk.quarkiverse.io")
+ .delete();
+ }
+
+ @Test
+ void conditionsInjectionsTest() {
+ String expectedUUID = testUUIDBean.uuid();
+
+ TestResource testResource = createTestResource();
+ kubernetesClient.resource(testResource).create();
+
+ // All conditions should be ready after ReadyPostCondition is evaluated, so waiting for it is enough
+ await().atMost(timeout)
+ .untilAsserted(() -> assertNotNull(readyPostCondition.getUuid()));
+
+ assertEquals(expectedUUID, readyPostCondition.getUuid(), "ReadyPostCondition injection not processed");
+ assertEquals(expectedUUID, customActionvationCondition.getUuid(), "CustomActivationCondition injection not processed");
+ assertEquals(expectedUUID, reconcilePrecondition.getUuid(), "ReconcilePrecondition injection not processed");
+
+ kubernetesClient.resource(testResource).delete();
+
+ await().atMost(timeout)
+ .untilAsserted(() -> assertEquals(expectedUUID, deletePostCondition.getUuid(),
+ "DeletePostCondition injection not processed"));
+
+ }
+
+ private static TestResource createTestResource() {
+ var tr = new TestResource();
+ tr.setMetadata(new ObjectMetaBuilder()
+ .withName("test-resource-sample").build());
+ tr.setSpec(new TestSpec());
+ return tr;
+ }
+}
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 29dc54c4d..6a466da25 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -12,5 +12,6 @@
pom
basic
+ cdi