diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index 8bf0b029f97e6..1fe99f3f8b4a7 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -171,7 +171,7 @@
5.8.0
4.9.2
1.1.4.Final
- 17.0.0
+ 17.0.1
1.15.0
3.21.3
2.11.0
diff --git a/build-parent/pom.xml b/build-parent/pom.xml
index 0177d4e0df024..4a8633c1467c9 100644
--- a/build-parent/pom.xml
+++ b/build-parent/pom.xml
@@ -96,7 +96,7 @@
- 17.0.0
+ 17.0.1
quay.io/keycloak/keycloak:${keycloak.version}
quay.io/keycloak/keycloak:${keycloak.version}-legacy
diff --git a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/DevServicesConfig.java b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/DevServicesConfig.java
index 0f2d667110836..e969184e2d343 100644
--- a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/DevServicesConfig.java
+++ b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/DevServicesConfig.java
@@ -28,7 +28,7 @@ public class DevServicesConfig {
*
* Image with a Quarkus based distribution is used by default.
* Image with a WildFly based distribution can be selected instead, for example:
- * 'quay.io/keycloak/keycloak:17.0.0-legacy'.
+ * 'quay.io/keycloak/keycloak:17.0.1-legacy'.
*
* Note Keycloak Quarkus and Keycloak WildFly images are initialized differently.
* By default, Dev Services for Keycloak will assume it is a Keycloak Quarkus image if the image version does not end with a
@@ -36,7 +36,7 @@ public class DevServicesConfig {
* string.
* Set 'quarkus.keycloak.devservices.keycloak-x-image' to override this check.
*/
- @ConfigItem(defaultValue = "quay.io/keycloak/keycloak:17.0.0")
+ @ConfigItem(defaultValue = "quay.io/keycloak/keycloak:17.0.1")
public String imageName;
/**
diff --git a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/KeycloakDevServicesProcessor.java b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/KeycloakDevServicesProcessor.java
index 5aa660ab49686..703bad81487f2 100644
--- a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/KeycloakDevServicesProcessor.java
+++ b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/KeycloakDevServicesProcessor.java
@@ -3,6 +3,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
+import java.net.ConnectException;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.URI;
@@ -21,6 +22,7 @@
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Set;
+import java.util.function.Predicate;
import java.util.function.Supplier;
import org.eclipse.microprofile.config.ConfigProvider;
@@ -58,6 +60,7 @@
import io.quarkus.oidc.deployment.devservices.OidcDevServicesUtils;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.configuration.ConfigUtils;
+import io.smallrye.mutiny.Uni;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpHeaders;
import io.vertx.mutiny.core.buffer.Buffer;
@@ -407,7 +410,8 @@ protected void configure() {
if (keycloakX) {
addEnv(KEYCLOAK_QUARKUS_ADMIN_PROP, KEYCLOAK_ADMIN_USER);
addEnv(KEYCLOAK_QUARKUS_ADMIN_PASSWORD_PROP, KEYCLOAK_ADMIN_PASSWORD);
- withCommand(KEYCLOAK_QUARKUS_START_CMD);
+ withCommand(KEYCLOAK_QUARKUS_START_CMD
+ + (useSharedNetwork ? " --hostname-port=" + fixedExposedPort.getAsInt() : ""));
} else {
addEnv(KEYCLOAK_WILDFLY_USER_PROP, KEYCLOAK_ADMIN_USER);
addEnv(KEYCLOAK_WILDFLY_PASSWORD_PROP, KEYCLOAK_ADMIN_PASSWORD);
@@ -521,16 +525,32 @@ private void createRealm(String keycloakUrl, RealmRepresentation realm) {
keycloakUrl + "/realms/master/protocol/openid-connect/token",
"admin-cli", null, "admin", "admin", null, capturedDevServicesConfiguration.webClienTimeout);
- HttpResponse response = client.postAbs(keycloakUrl + "/admin/realms")
+ HttpResponse createRealmResponse = client.postAbs(keycloakUrl + "/admin/realms")
.putHeader(HttpHeaders.CONTENT_TYPE.toString(), "application/json")
.putHeader(HttpHeaders.AUTHORIZATION.toString(), "Bearer " + token)
.sendBuffer(Buffer.buffer().appendString(JsonSerialization.writeValueAsString(realm)))
.await().atMost(capturedDevServicesConfiguration.webClienTimeout);
- if (response.statusCode() > 299) {
- LOG.errorf("Realm %s can not be created %d - %s ", realm.getRealm(), response.statusCode(),
- response.statusMessage());
+ if (createRealmResponse.statusCode() > 299) {
+ LOG.errorf("Realm %s can not be created %d - %s ", realm.getRealm(), createRealmResponse.statusCode(),
+ createRealmResponse.statusMessage());
}
+
+ Uni realmStatusCodeUni = client.getAbs(keycloakUrl + "/realms/" + realm.getRealm())
+ .send().onItem()
+ .transform(resp -> {
+ LOG.debugf("Realm status: %d", resp.statusCode());
+ if (resp.statusCode() == 200) {
+ return 200;
+ } else {
+ throw new RealmEndpointAccessException(resp.statusCode());
+ }
+ }).onFailure(realmEndpointNotAvailable())
+ .retry()
+ .withBackOff(Duration.ofSeconds(2), Duration.ofSeconds(2))
+ .expireIn(10 * 1000)
+ .onFailure().transform(t -> t.getCause());
+ realmStatusCodeUni.await().atMost(Duration.ofSeconds(10));
} catch (Throwable t) {
LOG.errorf("Realm %s can not be created: %s", realm.getRealm(), t.getMessage());
} finally {
@@ -538,6 +558,24 @@ private void createRealm(String keycloakUrl, RealmRepresentation realm) {
}
}
+ @SuppressWarnings("serial")
+ static class RealmEndpointAccessException extends RuntimeException {
+ private final int errorStatus;
+
+ public RealmEndpointAccessException(int errorStatus) {
+ this.errorStatus = errorStatus;
+ }
+
+ public int getErrorStatus() {
+ return errorStatus;
+ }
+ }
+
+ public static Predicate super Throwable> realmEndpointNotAvailable() {
+ return t -> (t instanceof ConnectException
+ || (t instanceof RealmEndpointAccessException && ((RealmEndpointAccessException) t).getErrorStatus() == 404));
+ }
+
private Map getUsers(Map configuredUsers, boolean createRealm) {
if (configuredUsers.isEmpty() && createRealm) {
Map users = new LinkedHashMap();