Harden operator CI

This commit is contained in:
andreaTP 2022-03-08 10:21:00 +00:00 committed by Bruno Oliveira da Silva
parent 18f391d8c4
commit 6504c058dd
5 changed files with 42 additions and 14 deletions

View file

@ -32,8 +32,8 @@
<maven.compiler.target>11</maven.compiler.target> <maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<quarkus.operator.sdk.version>3.0.2</quarkus.operator.sdk.version> <quarkus.operator.sdk.version>3.0.4</quarkus.operator.sdk.version>
<quarkus.version>2.6.1.Final</quarkus.version> <quarkus.version>2.7.3.Final</quarkus.version>
<quarkus.container-image.group>keycloak</quarkus.container-image.group> <quarkus.container-image.group>keycloak</quarkus.container-image.group>
<quarkus.jib.base-jvm-image>eclipse-temurin:11</quarkus.jib.base-jvm-image> <quarkus.jib.base-jvm-image>eclipse-temurin:11</quarkus.jib.base-jvm-image>
<quarkus.kubernetes.image-pull-policy>Never</quarkus.kubernetes.image-pull-policy> <quarkus.kubernetes.image-pull-policy>Never</quarkus.kubernetes.image-pull-policy>

View file

@ -37,15 +37,18 @@ import org.keycloak.operator.Constants;
import org.keycloak.operator.v2alpha1.crds.Keycloak; import org.keycloak.operator.v2alpha1.crds.Keycloak;
import org.keycloak.operator.v2alpha1.crds.KeycloakStatus; import org.keycloak.operator.v2alpha1.crds.KeycloakStatus;
import org.keycloak.operator.v2alpha1.crds.KeycloakStatusBuilder; import org.keycloak.operator.v2alpha1.crds.KeycloakStatusBuilder;
import org.keycloak.operator.v2alpha1.crds.KeycloakStatusCondition;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.List; import java.util.List;
import java.util.Optional; 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.NO_FINALIZER;
import static io.javaoperatorsdk.operator.api.reconciler.Constants.WATCH_CURRENT_NAMESPACE; 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<Keycloak>, EventSourceInitializer<Keycloak>, ErrorStatusHandler<Keycloak> { public class KeycloakController implements Reconciler<Keycloak>, EventSourceInitializer<Keycloak>, ErrorStatusHandler<Keycloak> {
@Inject @Inject
@ -98,13 +101,23 @@ public class KeycloakController implements Reconciler<Keycloak>, EventSourceInit
Log.info("--- Reconciliation finished successfully"); Log.info("--- Reconciliation finished successfully");
UpdateControl<Keycloak> updateControl;
if (status.equals(kc.getStatus())) { if (status.equals(kc.getStatus())) {
return UpdateControl.noUpdate(); updateControl = UpdateControl.noUpdate();
} }
else { else {
kc.setStatus(status); 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 @Override

View file

@ -510,6 +510,7 @@ public class KeycloakDeployment extends OperatorManagedResource implements Statu
|| existingDeployment.getStatus().getReadyReplicas() == null || existingDeployment.getStatus().getReadyReplicas() == null
|| existingDeployment.getStatus().getReadyReplicas() < keycloakCR.getSpec().getInstances()) { || existingDeployment.getStatus().getReadyReplicas() < keycloakCR.getSpec().getInstances()) {
status.addNotReadyMessage("Waiting for more replicas"); status.addNotReadyMessage("Waiting for more replicas");
return;
} }
} }

View file

@ -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.InformerEventSource;
import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers; import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers;
import io.quarkus.logging.Log; 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.KeycloakRealmImport;
import org.keycloak.operator.v2alpha1.crds.KeycloakRealmImportStatus; import org.keycloak.operator.v2alpha1.crds.KeycloakRealmImportStatus;
import org.keycloak.operator.v2alpha1.crds.KeycloakRealmImportStatusBuilder; 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 javax.inject.Inject;
import java.util.List; import java.util.List;
import java.util.Optional; 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.NO_FINALIZER;
import static io.javaoperatorsdk.operator.api.reconciler.Constants.WATCH_CURRENT_NAMESPACE; 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<KeycloakRealmImport>, EventSourceInitializer<KeycloakRealmImport>, ErrorStatusHandler<KeycloakRealmImport> { public class KeycloakRealmImportController implements Reconciler<KeycloakRealmImport>, EventSourceInitializer<KeycloakRealmImport>, ErrorStatusHandler<KeycloakRealmImport> {
@Inject @Inject
@ -83,12 +88,22 @@ public class KeycloakRealmImportController implements Reconciler<KeycloakRealmIm
Log.info("--- Realm reconciliation finished successfully"); Log.info("--- Realm reconciliation finished successfully");
UpdateControl<KeycloakRealmImport> updateControl;
if (status.equals(realm.getStatus())) { if (status.equals(realm.getStatus())) {
return UpdateControl.noUpdate(); updateControl = UpdateControl.noUpdate();
} else { } else {
realm.setStatus(status); 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 @Override

View file

@ -34,8 +34,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.MINUTES;
/** /**
* @author Vaclav Muzikar <vmuzikar@redhat.com> * @author Vaclav Muzikar <vmuzikar@redhat.com>
@ -75,8 +74,8 @@ public final class K8sUtils {
public static void waitForKeycloakToBeReady(KubernetesClient client, Keycloak kc) { public static void waitForKeycloakToBeReady(KubernetesClient client, Keycloak kc) {
Log.infof("Waiting for Keycloak \"%s\"", kc.getMetadata().getName()); Log.infof("Waiting for Keycloak \"%s\"", kc.getMetadata().getName());
Awaitility.await() Awaitility.await()
.pollInterval(Duration.ofSeconds(1)) .pollInterval(1, TimeUnit.SECONDS)
.timeout(Duration.ofMinutes(5)) .timeout(5, TimeUnit.MINUTES)
.ignoreExceptions() .ignoreExceptions()
.untilAsserted(() -> { .untilAsserted(() -> {
var currentKc = client var currentKc = client
@ -106,7 +105,7 @@ public final class K8sUtils {
.build()) .build())
.done(); .done();
Log.info("Waiting for curl Pod to finish running"); Log.info("Waiting for curl Pod to finish running");
Awaitility.await().atMost(3, MINUTES) Awaitility.await().atMost(3, TimeUnit.MINUTES)
.until(() -> { .until(() -> {
String phase = String phase =
k8sclient.pods().inNamespace(namespace).withName(podName).get() k8sclient.pods().inNamespace(namespace).withName(podName).get()
@ -124,7 +123,7 @@ public final class K8sUtils {
} finally { } finally {
Log.info("Deleting curl Pod"); Log.info("Deleting curl Pod");
k8sclient.pods().inNamespace(namespace).withName(podName).delete(); 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) .until(() -> k8sclient.pods().inNamespace(namespace).withName(podName)
.get() == null); .get() == null);
} }