diff --git a/operator/pom.xml b/operator/pom.xml
index 2827889048..457190b95f 100644
--- a/operator/pom.xml
+++ b/operator/pom.xml
@@ -32,8 +32,8 @@
11
UTF-8
UTF-8
- 3.0.2
- 2.6.1.Final
+ 3.0.4
+ 2.7.3.Final
keycloak
eclipse-temurin:11
Never
diff --git a/operator/src/main/java/org/keycloak/operator/v2alpha1/KeycloakController.java b/operator/src/main/java/org/keycloak/operator/v2alpha1/KeycloakController.java
index e27a47a468..24365a5100 100644
--- a/operator/src/main/java/org/keycloak/operator/v2alpha1/KeycloakController.java
+++ b/operator/src/main/java/org/keycloak/operator/v2alpha1/KeycloakController.java
@@ -37,15 +37,18 @@ import org.keycloak.operator.Constants;
import org.keycloak.operator.v2alpha1.crds.Keycloak;
import org.keycloak.operator.v2alpha1.crds.KeycloakStatus;
import org.keycloak.operator.v2alpha1.crds.KeycloakStatusBuilder;
+import org.keycloak.operator.v2alpha1.crds.KeycloakStatusCondition;
import javax.inject.Inject;
import java.util.List;
import java.util.Optional;
+import java.util.concurrent.TimeUnit;
import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_FINALIZER;
import static io.javaoperatorsdk.operator.api.reconciler.Constants.WATCH_CURRENT_NAMESPACE;
-@ControllerConfiguration(namespaces = WATCH_CURRENT_NAMESPACE, finalizerName = NO_FINALIZER)
+// TODO: remove "generationAwareEventProcessing = false" when the race condition is fixed
+@ControllerConfiguration(namespaces = WATCH_CURRENT_NAMESPACE, finalizerName = NO_FINALIZER, generationAwareEventProcessing = false)
public class KeycloakController implements Reconciler, EventSourceInitializer, ErrorStatusHandler {
@Inject
@@ -98,13 +101,23 @@ public class KeycloakController implements Reconciler, EventSourceInit
Log.info("--- Reconciliation finished successfully");
+ UpdateControl updateControl;
if (status.equals(kc.getStatus())) {
- return UpdateControl.noUpdate();
+ updateControl = UpdateControl.noUpdate();
}
else {
kc.setStatus(status);
- return UpdateControl.updateStatus(kc);
+ updateControl = UpdateControl.updateStatus(kc);
}
+
+ if (status
+ .getConditions()
+ .stream()
+ .anyMatch(c -> c.getType().equals(KeycloakStatusCondition.READY) && !c.getStatus())) {
+ updateControl.rescheduleAfter(10, TimeUnit.SECONDS);
+ }
+
+ return updateControl;
}
@Override
diff --git a/operator/src/main/java/org/keycloak/operator/v2alpha1/KeycloakDeployment.java b/operator/src/main/java/org/keycloak/operator/v2alpha1/KeycloakDeployment.java
index e823aeb46c..84c3a47492 100644
--- a/operator/src/main/java/org/keycloak/operator/v2alpha1/KeycloakDeployment.java
+++ b/operator/src/main/java/org/keycloak/operator/v2alpha1/KeycloakDeployment.java
@@ -510,6 +510,7 @@ public class KeycloakDeployment extends OperatorManagedResource implements Statu
|| existingDeployment.getStatus().getReadyReplicas() == null
|| existingDeployment.getStatus().getReadyReplicas() < keycloakCR.getSpec().getInstances()) {
status.addNotReadyMessage("Waiting for more replicas");
+ return;
}
}
diff --git a/operator/src/main/java/org/keycloak/operator/v2alpha1/KeycloakRealmImportController.java b/operator/src/main/java/org/keycloak/operator/v2alpha1/KeycloakRealmImportController.java
index 085537313e..f046fe9329 100644
--- a/operator/src/main/java/org/keycloak/operator/v2alpha1/KeycloakRealmImportController.java
+++ b/operator/src/main/java/org/keycloak/operator/v2alpha1/KeycloakRealmImportController.java
@@ -32,19 +32,24 @@ import io.javaoperatorsdk.operator.processing.event.source.EventSource;
import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers;
import io.quarkus.logging.Log;
+import org.keycloak.operator.v2alpha1.crds.Keycloak;
import org.keycloak.operator.v2alpha1.crds.KeycloakRealmImport;
import org.keycloak.operator.v2alpha1.crds.KeycloakRealmImportStatus;
import org.keycloak.operator.v2alpha1.crds.KeycloakRealmImportStatusBuilder;
+import org.keycloak.operator.v2alpha1.crds.KeycloakRealmImportStatusCondition;
+import org.keycloak.operator.v2alpha1.crds.KeycloakStatusCondition;
import javax.inject.Inject;
import java.util.List;
import java.util.Optional;
+import java.util.concurrent.TimeUnit;
import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_FINALIZER;
import static io.javaoperatorsdk.operator.api.reconciler.Constants.WATCH_CURRENT_NAMESPACE;
-@ControllerConfiguration(namespaces = WATCH_CURRENT_NAMESPACE, finalizerName = NO_FINALIZER)
+// TODO: remove "generationAwareEventProcessing = false" when the race condition is fixed
+@ControllerConfiguration(namespaces = WATCH_CURRENT_NAMESPACE, finalizerName = NO_FINALIZER, generationAwareEventProcessing = false)
public class KeycloakRealmImportController implements Reconciler, EventSourceInitializer, ErrorStatusHandler {
@Inject
@@ -83,12 +88,22 @@ public class KeycloakRealmImportController implements Reconciler updateControl;
if (status.equals(realm.getStatus())) {
- return UpdateControl.noUpdate();
+ updateControl = UpdateControl.noUpdate();
} else {
realm.setStatus(status);
- return UpdateControl.updateStatus(realm);
+ updateControl = UpdateControl.updateStatus(realm);
}
+
+ if (status
+ .getConditions()
+ .stream()
+ .anyMatch(c -> c.getType().equals(KeycloakRealmImportStatusCondition.DONE) && !c.getStatus())) {
+ updateControl.rescheduleAfter(10, TimeUnit.SECONDS);
+ }
+
+ return updateControl;
}
@Override
diff --git a/operator/src/test/java/org/keycloak/operator/utils/K8sUtils.java b/operator/src/test/java/org/keycloak/operator/utils/K8sUtils.java
index 30fc9d1090..7813bb3a0a 100644
--- a/operator/src/test/java/org/keycloak/operator/utils/K8sUtils.java
+++ b/operator/src/test/java/org/keycloak/operator/utils/K8sUtils.java
@@ -34,8 +34,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
-
-import static java.util.concurrent.TimeUnit.MINUTES;
+import java.util.concurrent.TimeUnit;
/**
* @author Vaclav Muzikar
@@ -75,8 +74,8 @@ public final class K8sUtils {
public static void waitForKeycloakToBeReady(KubernetesClient client, Keycloak kc) {
Log.infof("Waiting for Keycloak \"%s\"", kc.getMetadata().getName());
Awaitility.await()
- .pollInterval(Duration.ofSeconds(1))
- .timeout(Duration.ofMinutes(5))
+ .pollInterval(1, TimeUnit.SECONDS)
+ .timeout(5, TimeUnit.MINUTES)
.ignoreExceptions()
.untilAsserted(() -> {
var currentKc = client
@@ -106,7 +105,7 @@ public final class K8sUtils {
.build())
.done();
Log.info("Waiting for curl Pod to finish running");
- Awaitility.await().atMost(3, MINUTES)
+ Awaitility.await().atMost(3, TimeUnit.MINUTES)
.until(() -> {
String phase =
k8sclient.pods().inNamespace(namespace).withName(podName).get()
@@ -124,7 +123,7 @@ public final class K8sUtils {
} finally {
Log.info("Deleting curl Pod");
k8sclient.pods().inNamespace(namespace).withName(podName).delete();
- Awaitility.await().atMost(2, MINUTES)
+ Awaitility.await().atMost(2, TimeUnit.MINUTES)
.until(() -> k8sclient.pods().inNamespace(namespace).withName(podName)
.get() == null);
}