KEYCLOAK-19547 Switch arquillian quarkus container to use autobuild to prevent timeo… (#8576)

* KEYCLOAK-19547 Switch arquillian quarkus container to use autobuild to prevent timeouts when reaugmentation is longer than 10s

Co-authored-by: Dominik Guhr <dguhr@redhat.com>
This commit is contained in:
Dominik Guhr 2021-10-18 13:53:12 +02:00 committed by GitHub
parent 8ee992e638
commit c45a6fde12
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 76 deletions

View file

@ -168,9 +168,11 @@ public final class PropertyMappers {
} }
public static boolean isBuildTimeProperty(String name) { public static boolean isBuildTimeProperty(String name) {
if ("kc.features".equals(name)) {
if (isFeaturesBuildTimeProperty(name) || isSpiBuildTimeProperty(name)) {
return true; return true;
} }
return name.startsWith(MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX) return name.startsWith(MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX)
&& PropertyMapper.MAPPERS.entrySet().stream() && PropertyMapper.MAPPERS.entrySet().stream()
.anyMatch(entry -> entry.getValue().getFrom().equals(name) && entry.getValue().isBuildTime()) .anyMatch(entry -> entry.getValue().getFrom().equals(name) && entry.getValue().isBuildTime())
@ -184,6 +186,14 @@ public final class PropertyMappers {
&& !PropertyMappers.toCLIFormat("kc.config.file").equals(name); && !PropertyMappers.toCLIFormat("kc.config.file").equals(name);
} }
private static boolean isSpiBuildTimeProperty(String name) {
return name.startsWith("kc.spi") && (name.endsWith("provider") || name.endsWith("enabled"));
}
private static boolean isFeaturesBuildTimeProperty(String name) {
return name.startsWith("kc.features");
}
public static String toCLIFormat(String name) { public static String toCLIFormat(String name) {
if (name.indexOf('.') == -1) { if (name.indexOf('.') == -1) {
return name; return name;

View file

@ -44,7 +44,7 @@ import org.keycloak.testsuite.arquillian.SuiteContext;
*/ */
public class KeycloakQuarkusServerDeployableContainer implements DeployableContainer<KeycloakQuarkusConfiguration> { public class KeycloakQuarkusServerDeployableContainer implements DeployableContainer<KeycloakQuarkusConfiguration> {
protected static final Logger log = Logger.getLogger(KeycloakQuarkusServerDeployableContainer.class); private static final Logger log = Logger.getLogger(KeycloakQuarkusServerDeployableContainer.class);
private KeycloakQuarkusConfiguration configuration; private KeycloakQuarkusConfiguration configuration;
private Process container; private Process container;
@ -53,9 +53,7 @@ public class KeycloakQuarkusServerDeployableContainer implements DeployableConta
@Inject @Inject
private Instance<SuiteContext> suiteContext; private Instance<SuiteContext> suiteContext;
private boolean forceReaugmentation; private List<String> additionalBuildArgs = Collections.emptyList();
private List<String> additionalArgs = Collections.emptyList();
private List<String> runtimeProperties = Collections.emptyList();
@Override @Override
public Class<KeycloakQuarkusConfiguration> getConfigurationClass() { public Class<KeycloakQuarkusConfiguration> getConfigurationClass() {
@ -98,7 +96,7 @@ public class KeycloakQuarkusServerDeployableContainer implements DeployableConta
try { try {
deployArchiveToServer(archive); deployArchiveToServer(archive);
restartServer(true); restartServer();
} catch (Exception e) { } catch (Exception e) {
throw new DeploymentException(e.getMessage(),e); throw new DeploymentException(e.getMessage(),e);
} }
@ -111,7 +109,7 @@ public class KeycloakQuarkusServerDeployableContainer implements DeployableConta
File wrkDir = configuration.getProvidersPath().resolve("providers").toFile(); File wrkDir = configuration.getProvidersPath().resolve("providers").toFile();
try { try {
Files.deleteIfExists(wrkDir.toPath().resolve(archive.getName())); Files.deleteIfExists(wrkDir.toPath().resolve(archive.getName()));
restartServer(true); restartServer();
} catch (Exception e) { } catch (Exception e) {
throw new DeploymentException(e.getMessage(),e); throw new DeploymentException(e.getMessage(),e);
} }
@ -145,33 +143,16 @@ public class KeycloakQuarkusServerDeployableContainer implements DeployableConta
FileUtils.deleteDirectory(configuration.getProvidersPath().resolve("data").toFile()); FileUtils.deleteDirectory(configuration.getProvidersPath().resolve("data").toFile());
} }
if (isReaugmentBeforeStart()) {
List<String> commands = new ArrayList<>(Arrays.asList("./kc.sh", "build", "-Dquarkus.http.root-path=/auth", "--http-enabled=true"));
addAdditionalCommands(commands);
ProcessBuilder reaugment = new ProcessBuilder(commands);
reaugment.directory(wrkDir).inheritIO();
try {
log.infof("Re-building the server with the new configuration");
reaugment.start().waitFor(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException("Timeout while waiting for re-augmentation", e);
}
}
return builder.start(); return builder.start();
} }
private boolean isReaugmentBeforeStart() {
return configuration.isReaugmentBeforeStart() || forceReaugmentation;
}
private String[] getProcessCommands() { private String[] getProcessCommands() {
List<String> commands = new ArrayList<>(); List<String> commands = new ArrayList<>();
commands.add("./kc.sh"); commands.add("./kc.sh");
commands.add("-Dquarkus.http.root-path=/auth");
commands.add("--auto-build");
commands.add("--http-enabled=true");
if (configuration.getDebugPort() > 0) { if (configuration.getDebugPort() > 0) {
commands.add("--debug"); commands.add("--debug");
@ -184,25 +165,16 @@ public class KeycloakQuarkusServerDeployableContainer implements DeployableConta
commands.add("--http-port=" + configuration.getBindHttpPort()); commands.add("--http-port=" + configuration.getBindHttpPort());
commands.add("--https-port=" + configuration.getBindHttpsPort()); commands.add("--https-port=" + configuration.getBindHttpsPort());
//for setting the spi.login-protocol.saml.known-protocols values correctly in keycloak.properties
commands.add("-Dauth.server.http.port=" + configuration.getBindHttpPort());
commands.add("-Dauth.server.https.port=" + configuration.getBindHttpsPort());
if (configuration.getRoute() != null) { if (configuration.getRoute() != null) {
commands.add("-Djboss.node.name=" + configuration.getRoute()); commands.add("-Djboss.node.name=" + configuration.getRoute());
} }
commands.add("--cluster=" + System.getProperty("auth.server.quarkus.cluster.config", "local")); commands.add("--cluster=" + System.getProperty("auth.server.quarkus.cluster.config", "local"));
commands.addAll(getRuntimeProperties()); commands.addAll(getAdditionalBuildArgs());
addAdditionalCommands(commands);
return commands.toArray(new String[0]); return commands.toArray(new String[0]);
} }
private void addAdditionalCommands(List<String> commands) {
commands.addAll(additionalArgs);
}
private void waitForReadiness() throws MalformedURLException, LifecycleException { private void waitForReadiness() throws MalformedURLException, LifecycleException {
SuiteContext suiteContext = this.suiteContext.get(); SuiteContext suiteContext = this.suiteContext.get();
//TODO: not sure if the best endpoint but it makes sure that everything is properly initialized. Once we have //TODO: not sure if the best endpoint but it makes sure that everything is properly initialized. Once we have
@ -295,17 +267,8 @@ public class KeycloakQuarkusServerDeployableContainer implements DeployableConta
return TimeUnit.SECONDS.toMillis(configuration.getStartupTimeoutInSeconds()); return TimeUnit.SECONDS.toMillis(configuration.getStartupTimeoutInSeconds());
} }
public void forceReAugmentation(String... args) { public void resetConfiguration() {
forceReaugmentation = true; additionalBuildArgs = Collections.emptyList();
additionalArgs = Arrays.asList(args);
}
public void resetConfiguration(boolean isReAugmentationNeeded) {
additionalArgs = Collections.emptyList();
runtimeProperties = Collections.emptyList();
if (isReAugmentationNeeded) {
forceReAugmentation();
}
} }
private void deployArchiveToServer(Archive<?> archive) throws IOException { private void deployArchiveToServer(Archive<?> archive) throws IOException {
@ -314,19 +277,16 @@ public class KeycloakQuarkusServerDeployableContainer implements DeployableConta
Files.copy(zipStream, providersDir.toPath().resolve(archive.getName()), StandardCopyOption.REPLACE_EXISTING); Files.copy(zipStream, providersDir.toPath().resolve(archive.getName()), StandardCopyOption.REPLACE_EXISTING);
} }
public void restartServer(boolean isReaugmentation) throws Exception { public void restartServer() throws Exception {
if(isReaugmentation) {
forceReaugmentation = true;
}
stop(); stop();
start(); start();
} }
public List<String> getRuntimeProperties() { public List<String> getAdditionalBuildArgs() {
return runtimeProperties; return additionalBuildArgs;
} }
public void setRuntimeProperties(List<String> runtimeProperties) { public void setAdditionalBuildArgs(List<String> newArgs) {
this.runtimeProperties = runtimeProperties; additionalBuildArgs = newArgs;
} }
} }

View file

@ -9,6 +9,7 @@ import org.wildfly.extras.creaper.core.online.CliException;
import org.wildfly.extras.creaper.core.online.OnlineManagementClient; import org.wildfly.extras.creaper.core.online.OnlineManagementClient;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
public class SpiProvidersSwitchingUtils { public class SpiProvidersSwitchingUtils {
@ -24,7 +25,7 @@ public class SpiProvidersSwitchingUtils {
System.setProperty("keycloak." + annotation.spi() + ".provider", annotation.providerId()); System.setProperty("keycloak." + annotation.spi() + ".provider", annotation.providerId());
} else if (authServerInfo.isQuarkus()) { } else if (authServerInfo.isQuarkus()) {
KeycloakQuarkusServerDeployableContainer container = (KeycloakQuarkusServerDeployableContainer) authServerInfo.getArquillianContainer().getDeployableContainer(); KeycloakQuarkusServerDeployableContainer container = (KeycloakQuarkusServerDeployableContainer) authServerInfo.getArquillianContainer().getDeployableContainer();
container.forceReAugmentation(KEYCLOAKX_ARG_SPI_PREFIX + toDashCase(annotation.spi()) +"-provider="+annotation.providerId()); container.setAdditionalBuildArgs(Collections.singletonList(KEYCLOAKX_ARG_SPI_PREFIX + toDashCase(annotation.spi()) + "-provider=" + annotation.providerId()));
} else { } else {
OnlineManagementClient client = AuthServerTestEnricher.getManagementClient(); OnlineManagementClient client = AuthServerTestEnricher.getManagementClient();
@ -45,7 +46,8 @@ public class SpiProvidersSwitchingUtils {
System.clearProperty("keycloak." + annotation.spi() + ".provider"); System.clearProperty("keycloak." + annotation.spi() + ".provider");
} else if (authServerInfo.isQuarkus()) { } else if (authServerInfo.isQuarkus()) {
KeycloakQuarkusServerDeployableContainer container = (KeycloakQuarkusServerDeployableContainer) authServerInfo.getArquillianContainer().getDeployableContainer(); KeycloakQuarkusServerDeployableContainer container = (KeycloakQuarkusServerDeployableContainer) authServerInfo.getArquillianContainer().getDeployableContainer();
container.resetConfiguration(true); container.resetConfiguration();
container.setAdditionalBuildArgs(Collections.singletonList(KEYCLOAKX_ARG_SPI_PREFIX + toDashCase(annotation.spi()) + "-provider=default"));
} else { } else {
OnlineManagementClient client = AuthServerTestEnricher.getManagementClient(); OnlineManagementClient client = AuthServerTestEnricher.getManagementClient();
if (annotation.onlyUpdateDefault()) { if (annotation.onlyUpdateDefault()) {

View file

@ -160,7 +160,7 @@ public class ClientSearchTest extends AbstractClientTest {
String s = String.join(",",searchableAttributes); String s = String.join(",",searchableAttributes);
controller.stop(suiteContext.getAuthServerInfo().getQualifier()); controller.stop(suiteContext.getAuthServerInfo().getQualifier());
KeycloakQuarkusServerDeployableContainer container = (KeycloakQuarkusServerDeployableContainer)suiteContext.getAuthServerInfo().getArquillianContainer().getDeployableContainer(); KeycloakQuarkusServerDeployableContainer container = (KeycloakQuarkusServerDeployableContainer)suiteContext.getAuthServerInfo().getArquillianContainer().getDeployableContainer();
container.setRuntimeProperties(Collections.singletonList("--spi-client-jpa-searchable-attributes=\""+ s + "\"")); container.setAdditionalBuildArgs(Collections.singletonList("--spi-client-jpa-searchable-attributes=\""+ s + "\""));
controller.start(suiteContext.getAuthServerInfo().getQualifier()); controller.start(suiteContext.getAuthServerInfo().getQualifier());
} else { } else {
throw new RuntimeException("Don't know how to config"); throw new RuntimeException("Don't know how to config");
@ -180,8 +180,8 @@ public class ClientSearchTest extends AbstractClientTest {
executeCli("/subsystem=keycloak-server/spi=client:remove"); executeCli("/subsystem=keycloak-server/spi=client:remove");
} else if(suiteContext.getAuthServerInfo().isQuarkus()) { } else if(suiteContext.getAuthServerInfo().isQuarkus()) {
KeycloakQuarkusServerDeployableContainer container = (KeycloakQuarkusServerDeployableContainer)suiteContext.getAuthServerInfo().getArquillianContainer().getDeployableContainer(); KeycloakQuarkusServerDeployableContainer container = (KeycloakQuarkusServerDeployableContainer)suiteContext.getAuthServerInfo().getArquillianContainer().getDeployableContainer();
container.setRuntimeProperties(Collections.emptyList()); container.setAdditionalBuildArgs(Collections.emptyList());
container.restartServer(false); container.restartServer();
} else { } else {
throw new RuntimeException("Don't know how to config"); throw new RuntimeException("Don't know how to config");
} }

View file

@ -10,14 +10,13 @@ import org.wildfly.extras.creaper.core.online.OnlineManagementClient;
import org.wildfly.extras.creaper.core.online.operations.admin.Administration; import org.wildfly.extras.creaper.core.online.operations.admin.Administration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
public abstract class AbstractHostnameTest extends AbstractKeycloakTest { public abstract class AbstractHostnameTest extends AbstractKeycloakTest {
private static final Logger LOGGER = Logger.getLogger(AbstractHostnameTest.class); private static final Logger LOGGER = Logger.getLogger(AbstractHostnameTest.class);
private boolean isReaugmentationNeeded;
@ArquillianResource @ArquillianResource
protected ContainerController controller; protected ContainerController controller;
@ -42,7 +41,8 @@ public abstract class AbstractHostnameTest extends AbstractKeycloakTest {
} else if (suiteContext.getAuthServerInfo().isQuarkus()) { } else if (suiteContext.getAuthServerInfo().isQuarkus()) {
controller.stop(suiteContext.getAuthServerInfo().getQualifier()); controller.stop(suiteContext.getAuthServerInfo().getQualifier());
KeycloakQuarkusServerDeployableContainer container = (KeycloakQuarkusServerDeployableContainer)suiteContext.getAuthServerInfo().getArquillianContainer().getDeployableContainer(); KeycloakQuarkusServerDeployableContainer container = (KeycloakQuarkusServerDeployableContainer)suiteContext.getAuthServerInfo().getArquillianContainer().getDeployableContainer();
container.resetConfiguration(isReaugmentationNeeded); container.resetConfiguration();
container.setAdditionalBuildArgs(Collections.singletonList("--spi-hostname-provider=default"));
controller.start(suiteContext.getAuthServerInfo().getQualifier()); controller.start(suiteContext.getAuthServerInfo().getQualifier());
} else { } else {
throw new RuntimeException("Don't know how to config"); throw new RuntimeException("Don't know how to config");
@ -73,15 +73,14 @@ public abstract class AbstractHostnameTest extends AbstractKeycloakTest {
} else if (suiteContext.getAuthServerInfo().isQuarkus()) { } else if (suiteContext.getAuthServerInfo().isQuarkus()) {
controller.stop(suiteContext.getAuthServerInfo().getQualifier()); controller.stop(suiteContext.getAuthServerInfo().getQualifier());
KeycloakQuarkusServerDeployableContainer container = (KeycloakQuarkusServerDeployableContainer)suiteContext.getAuthServerInfo().getArquillianContainer().getDeployableContainer(); KeycloakQuarkusServerDeployableContainer container = (KeycloakQuarkusServerDeployableContainer)suiteContext.getAuthServerInfo().getArquillianContainer().getDeployableContainer();
List<String> runtimeProperties = new ArrayList<>(); List<String> additionalArgs = new ArrayList<>();
runtimeProperties.add("--spi-hostname-default-frontend-url="+frontendUrl); additionalArgs.add("--spi-hostname-default-frontend-url="+frontendUrl);
runtimeProperties.add("--spi-hostname-default-force-backend-url-to-frontend-url="+ forceBackendUrlToFrontendUrl); additionalArgs.add("--spi-hostname-default-force-backend-url-to-frontend-url="+ forceBackendUrlToFrontendUrl);
if (adminUrl != null){ if (adminUrl != null){
runtimeProperties.add("--spi-hostname-default-admin-url="+adminUrl); additionalArgs.add("--spi-hostname-default-admin-url="+adminUrl);
} }
container.setRuntimeProperties(runtimeProperties); container.setAdditionalBuildArgs(additionalArgs);
controller.start(suiteContext.getAuthServerInfo().getQualifier()); controller.start(suiteContext.getAuthServerInfo().getQualifier());
isReaugmentationNeeded = false;
} else { } else {
throw new RuntimeException("Don't know how to config"); throw new RuntimeException("Don't know how to config");
} }
@ -106,13 +105,12 @@ public abstract class AbstractHostnameTest extends AbstractKeycloakTest {
} else if (suiteContext.getAuthServerInfo().isQuarkus()) { } else if (suiteContext.getAuthServerInfo().isQuarkus()) {
controller.stop(suiteContext.getAuthServerInfo().getQualifier()); controller.stop(suiteContext.getAuthServerInfo().getQualifier());
KeycloakQuarkusServerDeployableContainer container = (KeycloakQuarkusServerDeployableContainer)suiteContext.getAuthServerInfo().getArquillianContainer().getDeployableContainer(); KeycloakQuarkusServerDeployableContainer container = (KeycloakQuarkusServerDeployableContainer)suiteContext.getAuthServerInfo().getArquillianContainer().getDeployableContainer();
container.forceReAugmentation("--spi-hostname-provider=fixed" + container.setAdditionalBuildArgs(Collections.singletonList("--spi-hostname-provider=fixed" +
" --spi-hostname-fixed-hostname="+ hostname + " --spi-hostname-fixed-hostname=" + hostname +
" --spi-hostname-fixed-http-port="+ httpPort + " --spi-hostname-fixed-http-port=" + httpPort +
" --spi-hostname-fixed-https-port="+ httpsPort + " --spi-hostname-fixed-https-port=" + httpsPort +
" --spi-hostname-fixed-always-https="+ alwaysHttps); " --spi-hostname-fixed-always-https=" + alwaysHttps));
controller.start(suiteContext.getAuthServerInfo().getQualifier()); controller.start(suiteContext.getAuthServerInfo().getQualifier());
isReaugmentationNeeded = true;
} else { } else {
throw new RuntimeException("Don't know how to config"); throw new RuntimeException("Don't know how to config");
} }