mirror of
https://github.com/keycloak/keycloak.git
synced 2026-05-28 04:13:22 -04:00
fix: simplifying quarkus integration test annotations (#48977)
* fix: simplifying quarkus integration test annotations closes: #48796 Signed-off-by: Steve Hawkins <shawkins@redhat.com> * refining quarkus integration tests to use KeycloakDistributionDecorator Signed-off-by: Steve Hawkins <shawkins@redhat.com> * implementing review feedback. KeycloakRunner replaces KeycloakDistributionDecorator Signed-off-by: Steve Hawkins <shawkins@redhat.com> --------- Signed-off-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
parent
710539ca14
commit
03624df8db
63 changed files with 933 additions and 1372 deletions
|
|
@ -21,6 +21,7 @@ import java.util.List;
|
|||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
|
@ -58,6 +59,8 @@ import static org.keycloak.quarkus.runtime.Environment.hasEarlyExitLaunchMode;
|
|||
@ApplicationScoped
|
||||
public class KeycloakMain implements QuarkusApplication {
|
||||
|
||||
public static final String KC_SERVER_PRINT_RUNNING = "kc.server.print_running";
|
||||
public static final String RUNNING_MESSAGE = "The server is running";
|
||||
private static AbstractNonServerCommand COMMAND;
|
||||
private static Consumer<Throwable> ERROR_HANDLER;
|
||||
|
||||
|
|
@ -163,8 +166,8 @@ public class KeycloakMain implements QuarkusApplication {
|
|||
*/
|
||||
@Override
|
||||
public int run(String... args) throws Exception {
|
||||
QuarkusKeycloakApplication application = Arc.container().instance(QuarkusKeycloakApplication.class).get();
|
||||
if (COMMAND != null) {
|
||||
QuarkusKeycloakApplication application = Arc.container().instance(QuarkusKeycloakApplication.class).get();
|
||||
QuarkusKeycloakSessionFactory sessionFactory = Arc.container().instance(QuarkusKeycloakSessionFactory.class).get();
|
||||
COMMAND.onStart(application, sessionFactory);
|
||||
}
|
||||
|
|
@ -173,6 +176,15 @@ public class KeycloakMain implements QuarkusApplication {
|
|||
// we should be managing this behavior more dynamically depending on the tests requirements (short/long lived)
|
||||
Quarkus.asyncExit(ApplicationLifecycleManager.getExitCode());
|
||||
} else {
|
||||
if (Boolean.getBoolean(KC_SERVER_PRINT_RUNNING)) {
|
||||
BiConsumer<Void, Throwable> started = (v, t) -> {
|
||||
if (t == null) {
|
||||
System.out.println("\n" + RUNNING_MESSAGE);
|
||||
}
|
||||
};
|
||||
application.getBootstrapFuture().ifPresentOrElse(future -> future.whenComplete(started),
|
||||
() -> started.accept(null, null));
|
||||
}
|
||||
Quarkus.waitForExit();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package org.keycloak.quarkus.runtime.integration.jaxrs;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import jakarta.enterprise.event.Observes;
|
||||
|
|
@ -59,6 +60,8 @@ public class QuarkusKeycloakApplication extends KeycloakApplication {
|
|||
private static final String KEYCLOAK_ADMIN_PASSWORD_ENV_VAR = "KEYCLOAK_ADMIN_PASSWORD";
|
||||
|
||||
private static final Logger logger = Logger.getLogger(QuarkusKeycloakApplication.class);
|
||||
|
||||
private CompletableFuture<Void> bootstrapFuture;
|
||||
|
||||
@Override
|
||||
protected String getDataDir() {
|
||||
|
|
@ -77,12 +80,16 @@ public class QuarkusKeycloakApplication extends KeycloakApplication {
|
|||
startup();
|
||||
} else {
|
||||
ManagedExecutor executor = Arc.container().instance(ManagedExecutor.class).get();
|
||||
CompletableFuture.runAsync(this::startup, executor).exceptionally(cause -> {
|
||||
bootstrapFuture = CompletableFuture.runAsync(this::startup, executor).exceptionally(cause -> {
|
||||
KeycloakMain.asyncExit(1, cause);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<CompletableFuture<Void>> getBootstrapFuture() {
|
||||
return Optional.ofNullable(bootstrapFuture);
|
||||
}
|
||||
|
||||
void onShutdownEvent(@Observes ShutdownEvent event) {
|
||||
shutdown();
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ import java.util.function.Consumer;
|
|||
import org.keycloak.it.TestProvider;
|
||||
import org.keycloak.it.junit5.extension.BeforeStartDistribution;
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
import org.keycloak.quarkus.runtime.cli.command.StartDev;
|
||||
|
||||
|
|
@ -32,13 +32,13 @@ abstract class AbstractPathDistTest {
|
|||
@BeforeStartDistribution(AddCustomScriptsProvider.class)
|
||||
@RawDistOnly(reason = "Testing installation path handling")
|
||||
@Test
|
||||
void testApplicationBuildAndStart(KeycloakDistribution dist) throws IOException {
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
void testApplicationBuildAndStart(KeycloakRunner runner) throws IOException {
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
Path distPath = rawDist.getDistPath();
|
||||
Path newPath = distPath.getParent().resolve(getSubPath()).resolve(distPath.getFileName());
|
||||
rawDist.setDistPath(newPath);
|
||||
try {
|
||||
CLIResult result = dist.run(StartDev.NAME);
|
||||
CLIResult result = runner.run(StartDev.NAME);
|
||||
result.assertStartedDevMode();
|
||||
assertThat(result.getOutput(), containsString("Updating the configuration and installing your custom providers, if any. Please wait."));
|
||||
} finally {
|
||||
|
|
@ -46,11 +46,10 @@ abstract class AbstractPathDistTest {
|
|||
}
|
||||
}
|
||||
|
||||
public static final class AddCustomScriptsProvider implements Consumer<KeycloakDistribution> {
|
||||
public static final class AddCustomScriptsProvider implements Consumer<RawKeycloakDistribution> {
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
RawKeycloakDistribution rawDist = distribution.unwrap(RawKeycloakDistribution.class);
|
||||
rawDist.copyProvider(new ScriptProviderForTest());
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.copyProvider(new ScriptProviderForTest());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,10 @@ package org.keycloak.it.cli.dist;
|
|||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.junit5.extension.WithEnvVars;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
|
|
@ -87,14 +88,15 @@ public class BootstrapAdminDistTest {
|
|||
|
||||
@Test
|
||||
@WithEnvVars({"MY_SECRET", "admin123"})
|
||||
void createAndUseSericeAccountAdmin(KeycloakDistribution dist) throws Exception {
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
CLIResult result = rawDist.run("bootstrap-admin", "service", "--db=dev-file", "--client-id=admin", "--client-secret:env=MY_SECRET");
|
||||
void createAndUseSericeAccountAdmin(KeycloakRunner runner) throws Exception {
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
CLIResult result = runner.run("bootstrap-admin", "service", "--db=dev-file", "--client-id=admin", "--client-secret:env=MY_SECRET");
|
||||
|
||||
assertTrue(result.getErrorOutput().isEmpty(), result.getErrorOutput());
|
||||
|
||||
rawDist.setManualStop(true);
|
||||
rawDist.run("start-dev");
|
||||
runner.setStopServer(Mode.MANUAL);
|
||||
result = runner.run("start-dev");
|
||||
result.assertStartedDevMode();
|
||||
|
||||
CLIResult adminResult = rawDist.kcadm("get", "clients", "--server", "http://localhost:8080", "--realm", "master", "--client", "admin", "--secret", "admin123");
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,11 @@ package org.keycloak.it.cli.dist;
|
|||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.DryRun;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.StopServer;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.junit5.extension.WithEnvVars;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
|
|
@ -36,21 +37,20 @@ import static org.keycloak.quarkus.runtime.cli.command.AbstractAutoBuildCommand.
|
|||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@WithEnvVars({"KC_CACHE", "local"}) // avoid flakey port conflicts
|
||||
@DistributionTest
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
@TestMethodOrder(OrderAnnotation.class)
|
||||
@Tag(DistributionTest.WIN)
|
||||
public class BuildAndStartDistTest {
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
void testBuildAndStart(KeycloakDistribution dist) {
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
void testBuildAndStart(KeycloakRunner runner) {
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
// start using based on the build options set via CLI
|
||||
CLIResult cliResult = rawDist.run("build", "--db=dev-file");
|
||||
CLIResult cliResult = runner.run("build", "--db=dev-file");
|
||||
cliResult.assertBuild();
|
||||
cliResult = rawDist.run("start", "--http-enabled=true", "--hostname-strict=false", OPTIMIZED_BUILD_OPTION_LONG);
|
||||
cliResult = runner.run("start", "--http-enabled=true", "--hostname-strict=false", OPTIMIZED_BUILD_OPTION_LONG);
|
||||
cliResult.assertNoBuild();
|
||||
assertTrue(cliResult.getErrorOutput().isBlank());
|
||||
|
||||
|
|
@ -59,19 +59,19 @@ public class BuildAndStartDistTest {
|
|||
rawDist.setProperty("hostname-strict", "false");
|
||||
rawDist.setProperty("http-relative-path", "/auth");
|
||||
rawDist.setProperty("db", "dev-file");
|
||||
cliResult = rawDist.run("build");
|
||||
cliResult = runner.run("build");
|
||||
cliResult.assertBuild();
|
||||
cliResult = rawDist.run("start", OPTIMIZED_BUILD_OPTION_LONG);
|
||||
cliResult = runner.run("start", OPTIMIZED_BUILD_OPTION_LONG);
|
||||
cliResult.assertNoBuild();
|
||||
assertTrue(cliResult.getErrorOutput().isBlank(), cliResult.getErrorOutput());
|
||||
// running start without optimized flag should not cause a build
|
||||
cliResult = rawDist.run("start");
|
||||
cliResult = runner.run("start");
|
||||
cliResult.assertNoBuild();
|
||||
assertTrue(cliResult.getErrorOutput().isBlank());
|
||||
|
||||
// remove the build option from conf file to force a build during start
|
||||
rawDist.removeProperty("http-relative-path");
|
||||
cliResult = rawDist.run("start");
|
||||
cliResult = runner.run("start");
|
||||
cliResult.assertBuild();
|
||||
assertTrue(cliResult.getErrorOutput().isBlank());
|
||||
}
|
||||
|
|
@ -79,31 +79,31 @@ public class BuildAndStartDistTest {
|
|||
@Test
|
||||
@WithEnvVars({"KEYCLOAK_ADMIN", "oldadmin123", "KEYCLOAK_ADMIN_PASSWORD", "oldadmin123"})
|
||||
@Launch({"start-dev"})
|
||||
void testCreateLegacyAdmin(KeycloakDistribution dist, LaunchResult result) {
|
||||
assertAdminCreation(dist, result, "oldadmin123", "oldadmin123", "oldadmin123");
|
||||
void testCreateLegacyAdmin(KeycloakRunner runner, LaunchResult result) {
|
||||
assertAdminCreation(runner, result, "oldadmin123", "oldadmin123", "oldadmin123");
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithEnvVars({"KC_BOOTSTRAP_ADMIN_USERNAME", "admin123", "KC_BOOTSTRAP_ADMIN_PASSWORD", "admin123"})
|
||||
@Launch({"start-dev"})
|
||||
void testCreateAdmin(KeycloakDistribution dist, LaunchResult result) {
|
||||
assertAdminCreation(dist, result, "admin123", "admin123", "admin123");
|
||||
void testCreateAdmin(KeycloakRunner runner, LaunchResult result) {
|
||||
assertAdminCreation(runner, result, "admin123", "admin123", "admin123");
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithEnvVars({"KC_BOOTSTRAP_ADMIN_USERNAME", "admin123", "KC_BOOTSTRAP_ADMIN_PASSWORD", "admin123"})
|
||||
@Launch({"start-dev"})
|
||||
void testCreateDifferentAdmin(KeycloakDistribution dist, LaunchResult result) {
|
||||
assertAdminCreation(dist, result, "admin123", "new-admin", "new-admin");
|
||||
void testCreateDifferentAdmin(KeycloakRunner runner, LaunchResult result) {
|
||||
assertAdminCreation(runner, result, "admin123", "new-admin", "new-admin");
|
||||
}
|
||||
|
||||
private void assertAdminCreation(KeycloakDistribution dist, LaunchResult result, String initialUsername, String nextUsername, String password) {
|
||||
private void assertAdminCreation(KeycloakRunner runner, LaunchResult result, String initialUsername, String nextUsername, String password) {
|
||||
assertTrue(result.getOutput().contains("Created temporary admin user with username " + initialUsername),
|
||||
() -> "The Output:\n" + result.getOutput() + "doesn't contains the expected string.");
|
||||
|
||||
dist.setEnvVar("KC_BOOTSTRAP_ADMIN_USERNAME", nextUsername);
|
||||
dist.setEnvVar("KC_BOOTSTRAP_ADMIN_PASSWORD", password);
|
||||
CLIResult cliResult = dist.run("start-dev", "--log-level=org.keycloak.services:debug");
|
||||
runner.setEnvVar("KC_BOOTSTRAP_ADMIN_USERNAME", nextUsername);
|
||||
runner.setEnvVar("KC_BOOTSTRAP_ADMIN_PASSWORD", password);
|
||||
CLIResult cliResult = runner.run("start-dev", "--log-level=org.keycloak.services:debug");
|
||||
|
||||
cliResult.assertNoMessage("Added temporary admin user '");
|
||||
cliResult.assertStartedDevMode();
|
||||
|
|
|
|||
|
|
@ -22,9 +22,11 @@ import java.nio.file.Paths;
|
|||
import org.keycloak.config.database.Database;
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.WithEnvVars;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
|
@ -84,20 +86,21 @@ class BuildCommandDistTest {
|
|||
|
||||
@Test
|
||||
@RawDistOnly(reason = "Raw is enough and we avoid issues with including custom conf file in the container")
|
||||
public void testFailInvalidOptionInConf(KeycloakDistribution distribution) {
|
||||
CLIResult cliResult = distribution.run(CONFIG_FILE_LONG_NAME + "=" + Paths.get("src/test/resources/BuildCommandDistTest/keycloak.conf").toAbsolutePath().normalize(), "build");
|
||||
public void testFailInvalidOptionInConf(KeycloakRunner runner) {
|
||||
CLIResult cliResult = runner.run(CONFIG_FILE_LONG_NAME + "=" + Paths.get("src/test/resources/BuildCommandDistTest/keycloak.conf").toAbsolutePath().normalize(), "build");
|
||||
cliResult.assertError("Invalid value for option 'kc.db' in keycloak.conf: foo. Expected values are: dev-file, dev-mem, mariadb, mssql, mysql, oracle, postgres");
|
||||
}
|
||||
|
||||
@Test
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
void testDoNotRecordRuntimeOptionsDuringBuild(KeycloakDistribution distribution) {
|
||||
distribution.setProperty("db-url", "invalid");
|
||||
CLIResult cliResult = distribution.run("build");
|
||||
void testDoNotRecordRuntimeOptionsDuringBuild(KeycloakRunner runner) {
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
rawDist.setProperty("db-url", "invalid");
|
||||
CLIResult cliResult = runner.run("build");
|
||||
cliResult.assertBuild();
|
||||
distribution.removeProperty("db-url");
|
||||
rawDist.removeProperty("db-url");
|
||||
|
||||
CLIResult result = distribution.run("start", "--hostname=mykeycloak", "--cache=local", "--http-enabled=true", OPTIMIZED_BUILD_OPTION_LONG);
|
||||
CLIResult result = runner.run("start", "--hostname=mykeycloak", "--cache=local", "--http-enabled=true", OPTIMIZED_BUILD_OPTION_LONG);
|
||||
result.assertStarted();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,21 +24,20 @@ import java.util.Arrays;
|
|||
import org.keycloak.config.CachingOptions;
|
||||
import org.keycloak.config.Option;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.DryRun;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.SkipRealmBootstrap;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.junit5.extension.StopServer;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@DistributionTest
|
||||
@SkipRealmBootstrap
|
||||
@DistributionTest(stopServer = Mode.BEFORE_BOOTSTRAP)
|
||||
public class CacheEmbeddedMtlsDistTest {
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
public void testCacheEmbeddedMtlsDisabled(KeycloakDistribution dist) {
|
||||
public void testCacheEmbeddedMtlsDisabled(KeycloakRunner runner) {
|
||||
for (var option : Arrays.asList(
|
||||
CachingOptions.CACHE_EMBEDDED_MTLS_TRUSTSTORE,
|
||||
CachingOptions.CACHE_EMBEDDED_MTLS_KEYSTORE,
|
||||
|
|
@ -46,24 +45,24 @@ public class CacheEmbeddedMtlsDistTest {
|
|||
CachingOptions.CACHE_EMBEDDED_MTLS_TRUSTSTORE_PASSWORD,
|
||||
CachingOptions.CACHE_EMBEDDED_MTLS_ROTATION
|
||||
)) {
|
||||
var result = dist.run("start-dev", "--cache=ispn", "--cache-embedded-mtls-enabled=false", "--%s=1".formatted(option.getKey()));
|
||||
var result = runner.run("start-dev", "--cache=ispn", "--cache-embedded-mtls-enabled=false", "--%s=1".formatted(option.getKey()));
|
||||
result.assertError("Disabled option: '--%s'. Available only when property 'cache-embedded-mtls-enabled' is enabled".formatted(option.getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
public void testCacheEmbeddedMtlsFileValidation(KeycloakDistribution dist) {
|
||||
doFileAndPasswordValidation(dist, CachingOptions.CACHE_EMBEDDED_MTLS_KEYSTORE, CachingOptions.CACHE_EMBEDDED_MTLS_KEYSTORE_PASSWORD);
|
||||
doFileAndPasswordValidation(dist, CachingOptions.CACHE_EMBEDDED_MTLS_TRUSTSTORE, CachingOptions.CACHE_EMBEDDED_MTLS_TRUSTSTORE_PASSWORD);
|
||||
public void testCacheEmbeddedMtlsFileValidation(KeycloakRunner runner) {
|
||||
doFileAndPasswordValidation(runner, CachingOptions.CACHE_EMBEDDED_MTLS_KEYSTORE, CachingOptions.CACHE_EMBEDDED_MTLS_KEYSTORE_PASSWORD);
|
||||
doFileAndPasswordValidation(runner, CachingOptions.CACHE_EMBEDDED_MTLS_TRUSTSTORE, CachingOptions.CACHE_EMBEDDED_MTLS_TRUSTSTORE_PASSWORD);
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
public void testCacheEmbeddedMtlsFileExistsValidation(KeycloakDistribution dist) throws IOException {
|
||||
var result = dist.run(
|
||||
public void testCacheEmbeddedMtlsFileExistsValidation(KeycloakRunner runner) throws IOException {
|
||||
var result = runner.run(
|
||||
"start-dev",
|
||||
"--cache=ispn",
|
||||
"--cache-embedded-mtls-enabled=true",
|
||||
|
|
@ -75,7 +74,7 @@ public class CacheEmbeddedMtlsDistTest {
|
|||
result.assertError("The 'cache-embedded-mtls-key-store-file' file 'keystore.p12' does not exist");
|
||||
|
||||
File keystore = Util.createTempFile("key", ".p12");
|
||||
result = dist.run(
|
||||
result = runner.run(
|
||||
"start-dev",
|
||||
"--cache=ispn",
|
||||
"--cache-embedded-mtls-enabled=true",
|
||||
|
|
@ -87,37 +86,37 @@ public class CacheEmbeddedMtlsDistTest {
|
|||
result.assertError("The 'cache-embedded-mtls-trust-store-file' file 'truststore.p12' does not exist");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
public void testCacheEmbeddedMtlsValidation(KeycloakDistribution dist) {
|
||||
public void testCacheEmbeddedMtlsValidation(KeycloakRunner runner) {
|
||||
var key = CachingOptions.CACHE_EMBEDDED_MTLS_ROTATION.getKey();
|
||||
// test zero
|
||||
var result = dist.run("start-dev", "--cache=ispn", "--cache-embedded-mtls-enabled=true", "--%s=0".formatted(key));
|
||||
var result = runner.run("start-dev", "--cache=ispn", "--cache-embedded-mtls-enabled=true", "--%s=0".formatted(key));
|
||||
result.assertError("JGroups MTLS certificate rotation in '%s' option must positive.".formatted(key));
|
||||
|
||||
// test negative
|
||||
result = dist.run("start-dev", "--cache=ispn", "--cache-embedded-mtls-enabled=true", "--%s=-1".formatted(key));
|
||||
result = runner.run("start-dev", "--cache=ispn", "--cache-embedded-mtls-enabled=true", "--%s=-1".formatted(key));
|
||||
result.assertError("JGroups MTLS certificate rotation in '%s' option must positive.".formatted(key));
|
||||
|
||||
// test blank
|
||||
result = dist.run("start-dev", "--cache=ispn", "--cache-embedded-mtls-enabled=true", "--%s=".formatted(key));
|
||||
result = runner.run("start-dev", "--cache=ispn", "--cache-embedded-mtls-enabled=true", "--%s=".formatted(key));
|
||||
result.assertError("Invalid empty value for option '--%s'".formatted(key));
|
||||
}
|
||||
|
||||
@Test
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
public void testCacheEmbeddedMtlsEnabled(KeycloakDistribution dist) {
|
||||
var result = dist.run("start-dev", "--cache=ispn", "--cache-embedded-mtls-enabled=true");
|
||||
public void testCacheEmbeddedMtlsEnabled(KeycloakRunner runner) {
|
||||
var result = runner.run("start-dev", "--cache=ispn", "--cache-embedded-mtls-enabled=true");
|
||||
result.assertMessage("JGroups JDBC_PING discovery enabled.");
|
||||
result.assertMessage("JGroups Encryption enabled (mTLS).");
|
||||
}
|
||||
|
||||
private void doFileAndPasswordValidation(KeycloakDistribution dist, Option<String> fileOption, Option<String> passwordOption) {
|
||||
var result = dist.run("start-dev", "--cache=ispn", "--cache-embedded-mtls-enabled=true", "--%s=file".formatted(fileOption.getKey()));
|
||||
private void doFileAndPasswordValidation(KeycloakRunner runner, Option<String> fileOption, Option<String> passwordOption) {
|
||||
var result = runner.run("start-dev", "--cache=ispn", "--cache-embedded-mtls-enabled=true", "--%s=file".formatted(fileOption.getKey()));
|
||||
result.assertError("The option '%s' requires '%s' to be enabled.".formatted(fileOption.getKey(), passwordOption.getKey()));
|
||||
|
||||
result = dist.run("start-dev", "--cache=ispn", "--cache-embedded-mtls-enabled=true", "--%s=secret".formatted(passwordOption.getKey()));
|
||||
result = runner.run("start-dev", "--cache=ispn", "--cache-embedded-mtls-enabled=true", "--%s=secret".formatted(passwordOption.getKey()));
|
||||
result.assertError("The option '%s' requires '%s' to be enabled.".formatted(passwordOption.getKey(), fileOption.getKey()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@ import java.util.function.Consumer;
|
|||
import org.keycloak.it.junit5.extension.BeforeStartDistribution;
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.SkipRealmBootstrap;
|
||||
import org.keycloak.it.junit5.extension.Storage;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import io.quarkus.test.junit.main.LaunchResult;
|
||||
|
|
@ -45,10 +45,8 @@ import org.junit.jupiter.api.condition.OS;
|
|||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.testcontainers.shaded.com.google.common.io.Files;
|
||||
|
||||
@DistributionTest(defaultOptions = {"--db=dev-file", "--http-enabled=true", "--hostname-strict=false"})
|
||||
@DistributionTest(localCache = false, stopServer = Mode.BEFORE_BOOTSTRAP, defaultOptions = {"--db=dev-file", "--http-enabled=true", "--hostname-strict=false"})
|
||||
@RawDistOnly(reason = "Not possible to mount files using docker.")
|
||||
@Storage(defaultLocalCache = false)
|
||||
@SkipRealmBootstrap
|
||||
@Tag(DistributionTest.SMOKE)
|
||||
@Tag(DistributionTest.SLOW)
|
||||
@TestMethodOrder(OrderAnnotation.class)
|
||||
|
|
@ -210,19 +208,19 @@ public class ClusterConfigDistTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testAbsoluteCacheFile(KeycloakDistribution dist, @TempDir Path tempDir) throws Exception {
|
||||
void testAbsoluteCacheFile(KeycloakRunner runner, @TempDir Path tempDir) throws Exception {
|
||||
File customCacheFile = tempDir.resolve("my-custom-cache.xml").toFile();
|
||||
File missingCacheFile = tempDir.resolve("my-missing-cache.xml").toFile();
|
||||
try (InputStream is = ClusterConfigDistTest.class.getResourceAsStream("/cache-ispn-custom-cache.xml")) {
|
||||
Files.write(is.readAllBytes(), customCacheFile);
|
||||
}
|
||||
|
||||
LaunchResult result = dist.run("start", "--cache-config-file=" + customCacheFile.getAbsolutePath());
|
||||
LaunchResult result = runner.run("start", "--cache-config-file=" + customCacheFile.getAbsolutePath());
|
||||
Assertions.assertEquals(0, result.exitCode());
|
||||
MatcherAssert.assertThat(result.getOutput(), Matchers.containsString(WARN_DEFAULT_CACHE_MUTATIONS));
|
||||
|
||||
String absolutePath = missingCacheFile.getAbsolutePath();
|
||||
result = dist.run("start", "--cache-config-file=" + absolutePath);
|
||||
result = runner.run("start", "--cache-config-file=" + absolutePath);
|
||||
Assertions.assertEquals(2, result.exitCode());
|
||||
MatcherAssert.assertThat(result.getErrorOutput(), Matchers.matchesRegex("Cache config file '" + absolutePath + "' does not exist"));
|
||||
}
|
||||
|
|
@ -264,18 +262,18 @@ public class ClusterConfigDistTest {
|
|||
result.assertNoMessage("Ignoring unbounded max-count for cache 'sessions'");
|
||||
}
|
||||
|
||||
public static class ConfigureCacheUsingAsyncEncryption implements Consumer<KeycloakDistribution> {
|
||||
public static class ConfigureCacheUsingAsyncEncryption implements Consumer<RawKeycloakDistribution> {
|
||||
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.copyOrReplaceFileFromClasspath("/cache-ispn-asym-enc.xml", Path.of("conf", "cache-ispn-asym-enc.xml"));
|
||||
}
|
||||
}
|
||||
|
||||
public static class ConfigureCustomCache implements Consumer<KeycloakDistribution> {
|
||||
public static class ConfigureCustomCache implements Consumer<RawKeycloakDistribution> {
|
||||
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.copyOrReplaceFileFromClasspath("/cache-ispn-custom-cache.xml", Path.of("conf", "cache-ispn-custom-cache.xml"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,10 +27,11 @@ import java.util.stream.Stream;
|
|||
|
||||
import org.keycloak.config.CachingOptions;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.junit5.extension.TestProvider;
|
||||
import org.keycloak.it.resource.realm.TestRealmResourceTestProvider;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
|
||||
import com.google.common.base.CaseFormat;
|
||||
import org.infinispan.commons.dataconversion.MediaType;
|
||||
|
|
@ -51,12 +52,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||
/**
|
||||
* @author Ryan Emerson <remerson@redhat.com>
|
||||
*/
|
||||
@DistributionTest(keepAlive = true, enableTls = true)
|
||||
@DistributionTest(stopServer = Mode.MANUAL, enableTls = true)
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
public class ClusterConfigKeepAliveDistTest {
|
||||
@Test
|
||||
@TestProvider(TestRealmResourceTestProvider.class)
|
||||
void testMaxCountApplied(KeycloakDistribution dist) {
|
||||
void testMaxCountApplied(KeycloakRunner runner) {
|
||||
int maxCount = 100;
|
||||
Set<String> maxCountCaches = Stream.of(CachingOptions.LOCAL_MAX_COUNT_CACHES, CachingOptions.CLUSTERED_MAX_COUNT_CACHES)
|
||||
.flatMap(Arrays::stream)
|
||||
|
|
@ -67,7 +68,7 @@ public class ClusterConfigKeepAliveDistTest {
|
|||
sb.append(" --").append(CachingOptions.cacheMaxCountProperty(cache)).append("=").append(maxCount);
|
||||
|
||||
String args = sb.toString();
|
||||
dist.run(args.split(" "));
|
||||
runner.run(args.split(" "));
|
||||
|
||||
for (String cache : maxCountCaches) {
|
||||
Configuration config = getCacheConfiguration(cache);
|
||||
|
|
@ -77,19 +78,19 @@ public class ClusterConfigKeepAliveDistTest {
|
|||
|
||||
@Test
|
||||
@TestProvider(TestRealmResourceTestProvider.class)
|
||||
void testNumOwnersWithPersistentSessions(KeycloakDistribution dist) {
|
||||
doNumOwnerTest(dist, false);
|
||||
void testNumOwnersWithPersistentSessions(KeycloakRunner runner) {
|
||||
doNumOwnerTest(runner, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestProvider(TestRealmResourceTestProvider.class)
|
||||
void testNumOwnersWithVolatileSessions(KeycloakDistribution dist) {
|
||||
doNumOwnerTest(dist, true);
|
||||
void testNumOwnersWithVolatileSessions(KeycloakRunner runner) {
|
||||
doNumOwnerTest(runner, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestProvider(TestRealmResourceTestProvider.class)
|
||||
void testCheckMinimumNumOwners(KeycloakDistribution dist) {
|
||||
void testCheckMinimumNumOwners(KeycloakRunner runner) {
|
||||
List<String> args = new ArrayList<>();
|
||||
args.add("start-dev");
|
||||
args.add("--cache=ispn");
|
||||
|
|
@ -99,13 +100,13 @@ public class ClusterConfigKeepAliveDistTest {
|
|||
.map(cache -> CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, cache))
|
||||
.map("--spi-cache-embedded--default--%s-owners=1"::formatted)
|
||||
.forEach(args::add);
|
||||
dist.run(args);
|
||||
runner.run(args);
|
||||
|
||||
// forces the numOwner to 2 to prevent data loss.
|
||||
assertNumOwner(Arrays.stream(CLUSTERED_CACHE_NUM_OWNERS), 2);
|
||||
}
|
||||
|
||||
private void doNumOwnerTest(KeycloakDistribution dist, boolean volatileSessions) {
|
||||
private void doNumOwnerTest(KeycloakRunner runner, boolean volatileSessions) {
|
||||
final int owners = 5;
|
||||
List<String> args = new ArrayList<>();
|
||||
args.add("start-dev");
|
||||
|
|
@ -118,7 +119,7 @@ public class ClusterConfigKeepAliveDistTest {
|
|||
.map(cache -> CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, cache))
|
||||
.map(cache -> "--spi-cache-embedded--default--%s-owners=%s".formatted(cache, owners))
|
||||
.forEach(args::add);
|
||||
dist.run(args);
|
||||
runner.run(args);
|
||||
|
||||
Stream<String> caches = Arrays.stream(CLUSTERED_CACHE_NUM_OWNERS);
|
||||
if (!volatileSessions) {
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ package org.keycloak.it.cli.dist;
|
|||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.TestProvider;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
|
||||
import com.acme.provider.legacy.jpa.entity.CustomJpaEntityProvider;
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
|
|
@ -37,13 +37,13 @@ public class CustomJpaEntityProviderDistTest {
|
|||
private static final String MULTIPLE_DATASOURCES_MSG = "Multiple datasources are specified: <default>, client-store, new-user-store, pu-without-dialect-store";
|
||||
|
||||
@Test
|
||||
void dbKindSpecifiedInBuildTime(KeycloakDistribution dist) {
|
||||
var result = dist.run("build", "--db=dev-file", "--db-kind-new-user-store=dev-mem", "--db-kind-pu-without-dialect-store=dev-mem");
|
||||
void dbKindSpecifiedInBuildTime(KeycloakRunner runner) {
|
||||
var result = runner.run("build", "--db=dev-file", "--db-kind-new-user-store=dev-mem", "--db-kind-pu-without-dialect-store=dev-mem");
|
||||
result.assertMessage(MULTIPLE_DATASOURCES_MSG);
|
||||
result.assertMessage("You have set DB kind for 'client-store' datasource via a Quarkus property. This approach is deprecated and you should use the Keycloak 'db-kind-client-store' property.");
|
||||
result.assertBuild();
|
||||
|
||||
result = dist.run("start", "--optimized", "--http-enabled=true", "--hostname-strict=false");
|
||||
result = runner.run("start", "--optimized", "--http-enabled=true", "--hostname-strict=false");
|
||||
result.assertNoError("Detected additional named datasources. You need to explicitly set the DB kind for the datasource(s) to properly work as: db-kind-user-store");
|
||||
|
||||
result.assertMessage("Datasource 'client-store' was deactivated automatically because its URL is not set");
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ import java.nio.file.Path;
|
|||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
|
||||
import org.junit.jupiter.api.Tag;
|
||||
|
|
@ -36,48 +36,48 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
public class ExportDistTest {
|
||||
|
||||
@Test
|
||||
void testExport(KeycloakDistribution dist) {
|
||||
CLIResult cliResult = dist.run("build");
|
||||
void testExport(KeycloakRunner runner) {
|
||||
CLIResult cliResult = runner.run("build");
|
||||
|
||||
cliResult = dist.run("export", "--realm=master", "--dir=.");
|
||||
cliResult = runner.run("export", "--realm=master", "--dir=.");
|
||||
cliResult.assertMessage("Export of realm 'master' requested.");
|
||||
cliResult.assertMessage("Export finished successfully");
|
||||
cliResult.assertNoMessage("Changes detected in configuration");
|
||||
cliResult.assertNoMessage("Listening on: http");
|
||||
|
||||
cliResult = dist.run("export", "--realm=master");
|
||||
cliResult = runner.run("export", "--realm=master");
|
||||
cliResult.assertError("Must specify either --dir or --file options.");
|
||||
|
||||
cliResult = dist.run("export", "--file=master", "--users=skip");
|
||||
cliResult = runner.run("export", "--file=master", "--users=skip");
|
||||
cliResult.assertError("Property '--users' can be used only when exporting to a directory, or value set to 'same_file' when exporting to a file.");
|
||||
|
||||
cliResult = dist.run("export", "--file=some-file", "--users=same_file");
|
||||
cliResult = runner.run("export", "--file=some-file", "--users=same_file");
|
||||
cliResult.assertNoError("Property '--users' can be used only when exporting to a directory, or value set to 'same_file' when exporting to a file.");
|
||||
cliResult.assertMessage("Exporting model into file");
|
||||
|
||||
cliResult = dist.run("export", "--dir=some-dir", "--users=skip");
|
||||
cliResult = runner.run("export", "--dir=some-dir", "--users=skip");
|
||||
cliResult.assertMessage("Realm 'master' - data exported");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExportRealmFGAPEnabled(KeycloakDistribution dist) {
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
void testExportRealmFGAPEnabled(KeycloakRunner runner) {
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
Path importDir = rawDist.getDistPath().resolve("data").resolve("import");
|
||||
assertTrue(importDir.toFile().mkdirs());
|
||||
dist.copyOrReplaceFileFromClasspath("/fgap-realm.json", importDir.resolve("fgap-realm.json"));
|
||||
rawDist.run("start-dev","-v", "--import-realm", "--features=admin-fine-grained-authz:v2");
|
||||
rawDist.copyOrReplaceFileFromClasspath("/fgap-realm.json", importDir.resolve("fgap-realm.json"));
|
||||
runner.run("start-dev","-v", "--import-realm", "--features=admin-fine-grained-authz:v2");
|
||||
rawDist.stop();
|
||||
CLIResult cliResult = rawDist.run("export", "--realm=fgap", "--dir=" + importDir.toAbsolutePath(), "--features=admin-fine-grained-authz:v2");
|
||||
CLIResult cliResult = runner.run("export", "--realm=fgap", "--dir=" + importDir.toAbsolutePath(), "--features=admin-fine-grained-authz:v2");
|
||||
cliResult.assertMessage("Export of realm 'fgap' requested.");
|
||||
cliResult.assertMessage("Export finished successfully");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExportNonExistent(KeycloakDistribution dist) {
|
||||
CLIResult cliResult = dist.run("build");
|
||||
void testExportNonExistent(KeycloakRunner runner) {
|
||||
CLIResult cliResult = runner.run("build");
|
||||
|
||||
cliResult = dist.run("export", "--realm=non-existent-realm", "--dir=.");
|
||||
cliResult = runner.run("export", "--realm=non-existent-realm", "--dir=.");
|
||||
cliResult.assertMessage("realm not found by realm name 'non-existent-realm'");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ import java.util.stream.Collectors;
|
|||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.SkipRealmBootstrap;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.quarkus.runtime.cli.command.Build;
|
||||
import org.keycloak.quarkus.runtime.cli.command.Start;
|
||||
import org.keycloak.quarkus.runtime.cli.command.StartDev;
|
||||
|
|
@ -27,11 +27,10 @@ import static org.keycloak.quarkus.runtime.cli.command.AbstractAutoBuildCommand.
|
|||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
@DistributionTest
|
||||
@DistributionTest(stopServer = Mode.BEFORE_BOOTSTRAP)
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
@Tag(DistributionTest.SMOKE)
|
||||
@SkipRealmBootstrap
|
||||
public class FeaturesDistTest {
|
||||
|
||||
private static final String PREVIEW_FEATURES_EXPECTED_LOG = "Preview features enabled: " + Arrays.stream(Profile.Feature.values())
|
||||
|
|
@ -48,12 +47,12 @@ public class FeaturesDistTest {
|
|||
.collect(Collectors.joining(", "));
|
||||
|
||||
@Test
|
||||
public void testEnableOnBuild(KeycloakDistribution dist) {
|
||||
CLIResult cliResult = dist.run(Build.NAME, "--db=dev-file", "--features=preview");
|
||||
public void testEnableOnBuild(KeycloakRunner runner) {
|
||||
CLIResult cliResult = runner.run(Build.NAME, "--db=dev-file", "--features=preview");
|
||||
cliResult.assertBuild();
|
||||
assertPreviewFeaturesEnabled(cliResult);
|
||||
|
||||
cliResult = dist.run(Start.NAME, "--http-enabled=true", "--hostname-strict=false", OPTIMIZED_BUILD_OPTION_LONG);
|
||||
cliResult = runner.run(Start.NAME, "--http-enabled=true", "--hostname-strict=false", OPTIMIZED_BUILD_OPTION_LONG);
|
||||
assertPreviewFeaturesEnabled(cliResult);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,15 +22,16 @@ import java.nio.file.Path;
|
|||
import org.keycloak.crypto.fips.FIPS1402Provider;
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@DistributionTest(keepAlive = true, defaultOptions = { "--db=dev-file", "--features=fips", "--http-enabled=true", "--hostname-strict=false" })
|
||||
@DistributionTest(stopServer = Mode.MANUAL, defaultOptions = { "--db=dev-file", "--features=fips", "--http-enabled=true", "--hostname-strict=false" })
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
@Tag(DistributionTest.SLOW)
|
||||
public class FipsDistTest {
|
||||
|
|
@ -38,9 +39,9 @@ public class FipsDistTest {
|
|||
private static final String BCFIPS_VERSION = "BCFIPS version 2.0102";
|
||||
|
||||
@Test
|
||||
void testFipsNonApprovedMode(KeycloakDistribution dist) {
|
||||
runOnFipsEnabledDistribution(dist, () -> {
|
||||
CLIResult cliResult = dist.run("start");
|
||||
void testFipsNonApprovedMode(KeycloakRunner runner) {
|
||||
runOnFipsEnabledDistribution(runner, () -> {
|
||||
CLIResult cliResult = runner.run("start");
|
||||
cliResult.assertStarted();
|
||||
// Not shown as FIPS is not a preview anymore
|
||||
cliResult.assertMessageWasShownExactlyNumberOfTimes("Preview features enabled: fips:v1", 0);
|
||||
|
|
@ -49,17 +50,17 @@ public class FipsDistTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testFipsApprovedMode(KeycloakDistribution dist) {
|
||||
runOnFipsEnabledDistribution(dist, () -> {
|
||||
dist.setEnvVar("KC_BOOTSTRAP_ADMIN_USERNAME", "admin");
|
||||
dist.setEnvVar("KC_BOOTSTRAP_ADMIN_PASSWORD", "admin");
|
||||
void testFipsApprovedMode(KeycloakRunner runner) {
|
||||
runOnFipsEnabledDistribution(runner, () -> {
|
||||
runner.setEnvVar("KC_BOOTSTRAP_ADMIN_USERNAME", "admin");
|
||||
runner.setEnvVar("KC_BOOTSTRAP_ADMIN_PASSWORD", "admin");
|
||||
|
||||
CLIResult cliResult = dist.run("start", "--fips-mode=strict");
|
||||
CLIResult cliResult = runner.run("start", "--fips-mode=strict");
|
||||
cliResult.assertMessage("password must be at least 112 bits");
|
||||
cliResult.assertMessage("FIPS1402Provider created: KC(" + BCFIPS_VERSION + " Approved Mode, FIPS-JVM: " + FIPS1402Provider.isSystemFipsEnabled() + ")");
|
||||
|
||||
dist.setEnvVar("KC_BOOTSTRAP_ADMIN_PASSWORD", "adminadminadmin");
|
||||
cliResult = dist.run("start", "--fips-mode=strict");
|
||||
runner.setEnvVar("KC_BOOTSTRAP_ADMIN_PASSWORD", "adminadminadmin");
|
||||
cliResult = runner.run("start", "--fips-mode=strict");
|
||||
cliResult.assertStarted();
|
||||
cliResult.assertMessage("Created temporary admin user with username admin");
|
||||
});
|
||||
|
|
@ -72,101 +73,101 @@ public class FipsDistTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testUnsupportedHttpsJksKeyStoreInStrictMode(KeycloakDistribution dist) {
|
||||
runOnFipsEnabledDistribution(dist, () -> {
|
||||
dist.copyOrReplaceFileFromClasspath("/server.keystore", Path.of("conf", "server.keystore"));
|
||||
CLIResult cliResult = dist.run("start", "--fips-mode=strict");
|
||||
void testUnsupportedHttpsJksKeyStoreInStrictMode(KeycloakRunner runner) {
|
||||
runOnFipsEnabledDistribution(runner, () -> {
|
||||
runner.getDistribution(RawKeycloakDistribution.class).copyOrReplaceFileFromClasspath("/server.keystore", Path.of("conf", "server.keystore"));
|
||||
CLIResult cliResult = runner.run("start", "--fips-mode=strict");
|
||||
cliResult.assertMessage("ERROR: java.lang.IllegalArgumentException: malformed sequence");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHttpsBcfksKeyStoreInStrictMode(KeycloakDistribution dist) {
|
||||
runOnFipsEnabledDistribution(dist, () -> {
|
||||
dist.copyOrReplaceFileFromClasspath("/server.keystore.bcfks", Path.of("conf", "server.keystore"));
|
||||
CLIResult cliResult = dist.run("start", "--fips-mode=strict", "--https-key-store-password=passwordpassword");
|
||||
void testHttpsBcfksKeyStoreInStrictMode(KeycloakRunner runner) {
|
||||
runOnFipsEnabledDistribution(runner, () -> {
|
||||
runner.getDistribution(RawKeycloakDistribution.class).copyOrReplaceFileFromClasspath("/server.keystore.bcfks", Path.of("conf", "server.keystore"));
|
||||
CLIResult cliResult = runner.run("start", "--fips-mode=strict", "--https-key-store-password=passwordpassword");
|
||||
cliResult.assertStarted();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHttpsBcfksTrustStoreInStrictMode(KeycloakDistribution dist) {
|
||||
runOnFipsEnabledDistribution(dist, () -> {
|
||||
dist.copyOrReplaceFileFromClasspath("/server.keystore.bcfks", Path.of("conf", "server.keystore"));
|
||||
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
void testHttpsBcfksTrustStoreInStrictMode(KeycloakRunner runner) {
|
||||
runOnFipsEnabledDistribution(runner, () -> {
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
rawDist.copyOrReplaceFileFromClasspath("/server.keystore.bcfks", Path.of("conf", "server.keystore"));
|
||||
|
||||
Path truststorePath = rawDist.getDistPath().resolve("conf").resolve("server.keystore").toAbsolutePath();
|
||||
|
||||
// https-trust-store-type should be automatically set to bcfks in fips-mode=strict
|
||||
CLIResult cliResult = dist.run("--verbose", "start", "--fips-mode=strict", "--https-key-store-password=passwordpassword",
|
||||
CLIResult cliResult = runner.run("--verbose", "start", "--fips-mode=strict", "--https-key-store-password=passwordpassword",
|
||||
"--https-trust-store-file=" + truststorePath, "--https-trust-store-password=passwordpassword");
|
||||
cliResult.assertStarted();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUnencryptedPkcs12TrustStoreInStrictMode(KeycloakDistribution dist) {
|
||||
runOnFipsEnabledDistribution(dist, () -> {
|
||||
void testUnencryptedPkcs12TrustStoreInStrictMode(KeycloakRunner runner) {
|
||||
runOnFipsEnabledDistribution(runner, () -> {
|
||||
String truststoreName = "keycloak-truststore.p12";
|
||||
dist.copyOrReplaceFileFromClasspath("/" + truststoreName, Path.of("conf", truststoreName));
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
rawDist.copyOrReplaceFileFromClasspath("/" + truststoreName, Path.of("conf", truststoreName));
|
||||
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
Path truststorePath = rawDist.getDistPath().resolve("conf").resolve(truststoreName).toAbsolutePath();
|
||||
|
||||
CLIResult cliResult = dist.run("--verbose", "start", "--fips-mode=strict", "--truststore-paths=" + truststorePath);
|
||||
CLIResult cliResult = runner.run("--verbose", "start", "--fips-mode=strict", "--truststore-paths=" + truststorePath);
|
||||
cliResult.assertStarted();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUnsupportedHttpsPkcs12KeyStoreInStrictMode(KeycloakDistribution dist) {
|
||||
runOnFipsEnabledDistribution(dist, () -> {
|
||||
dist.copyOrReplaceFileFromClasspath("/server.keystore.pkcs12", Path.of("conf", "server.keystore"));
|
||||
CLIResult cliResult = dist.run("start", "--fips-mode=strict", "--https-key-store-password=passwordpassword");
|
||||
void testUnsupportedHttpsPkcs12KeyStoreInStrictMode(KeycloakRunner runner) {
|
||||
runOnFipsEnabledDistribution(runner, () -> {
|
||||
runner.getDistribution(RawKeycloakDistribution.class).copyOrReplaceFileFromClasspath("/server.keystore.pkcs12", Path.of("conf", "server.keystore"));
|
||||
CLIResult cliResult = runner.run("start", "--fips-mode=strict", "--https-key-store-password=passwordpassword");
|
||||
cliResult.assertMessage("ERROR: java.lang.IllegalArgumentException: malformed sequence");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHttpsPkcs12KeyStoreInNonApprovedMode(KeycloakDistribution dist) {
|
||||
runOnFipsEnabledDistribution(dist, () -> {
|
||||
dist.copyOrReplaceFileFromClasspath("/server.keystore.pkcs12", Path.of("conf", "server.keystore"));
|
||||
CLIResult cliResult = dist.run("start", "--fips-mode=non-strict", "--https-key-store-password=passwordpassword");
|
||||
void testHttpsPkcs12KeyStoreInNonApprovedMode(KeycloakRunner runner) {
|
||||
runOnFipsEnabledDistribution(runner, () -> {
|
||||
runner.getDistribution(RawKeycloakDistribution.class).copyOrReplaceFileFromClasspath("/server.keystore.pkcs12", Path.of("conf", "server.keystore"));
|
||||
CLIResult cliResult = runner.run("start", "--fips-mode=non-strict", "--https-key-store-password=passwordpassword");
|
||||
cliResult.assertStarted();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHttpsPkcs12TrustStoreInNonApprovedMode(KeycloakDistribution dist) {
|
||||
runOnFipsEnabledDistribution(dist, () -> {
|
||||
dist.copyOrReplaceFileFromClasspath("/server.keystore.pkcs12", Path.of("conf", "server.keystore"));
|
||||
void testHttpsPkcs12TrustStoreInNonApprovedMode(KeycloakRunner runner) {
|
||||
runOnFipsEnabledDistribution(runner, () -> {
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
rawDist.copyOrReplaceFileFromClasspath("/server.keystore.pkcs12", Path.of("conf", "server.keystore"));
|
||||
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
Path truststorePath = rawDist.getDistPath().resolve("conf").resolve("server.keystore").toAbsolutePath();
|
||||
|
||||
CLIResult cliResult = dist.run("--verbose", "start", "--fips-mode=non-strict", "--https-key-store-password=passwordpassword",
|
||||
CLIResult cliResult = runner.run("--verbose", "start", "--fips-mode=non-strict", "--https-key-store-password=passwordpassword",
|
||||
"--https-trust-store-file=" + truststorePath, "--https-trust-store-password=passwordpassword");
|
||||
cliResult.assertMessage("Unable to determine 'https-trust-store-type' automatically. Adjust the file extension or specify the property.");
|
||||
dist.stop();
|
||||
runner.stop();
|
||||
|
||||
dist.copyOrReplaceFileFromClasspath("/server.keystore.pkcs12", Path.of("conf", "server.p12"));
|
||||
rawDist.copyOrReplaceFileFromClasspath("/server.keystore.pkcs12", Path.of("conf", "server.p12"));
|
||||
|
||||
rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
truststorePath = rawDist.getDistPath().resolve("conf").resolve("server.p12").toAbsolutePath();
|
||||
|
||||
cliResult = dist.run("--verbose", "start", "--fips-mode=non-strict", "--https-key-store-password=passwordpassword",
|
||||
cliResult = runner.run("--verbose", "start", "--fips-mode=non-strict", "--https-key-store-password=passwordpassword",
|
||||
"--https-trust-store-file=" + truststorePath, "--https-trust-store-password=passwordpassword");
|
||||
cliResult.assertStarted();
|
||||
});
|
||||
}
|
||||
|
||||
private void runOnFipsEnabledDistribution(KeycloakDistribution dist, Runnable runnable) {
|
||||
installBcFips(dist);
|
||||
private void runOnFipsEnabledDistribution(KeycloakRunner runner, Runnable runnable) {
|
||||
installBcFips(runner);
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
private void installBcFips(KeycloakDistribution dist) {
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
private void installBcFips(KeycloakRunner runner) {
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
rawDist.copyProvider("org.bouncycastle", "bc-fips");
|
||||
rawDist.copyProvider("org.bouncycastle", "bctls-fips");
|
||||
rawDist.copyProvider("org.bouncycastle", "bcpkix-fips");
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ import java.util.concurrent.CompletableFuture;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import io.quarkus.test.junit.main.LaunchResult;
|
||||
|
|
@ -36,7 +37,7 @@ import static org.hamcrest.CoreMatchers.equalTo;
|
|||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@DistributionTest(keepAlive = true,
|
||||
@DistributionTest(stopServer = Mode.MANUAL,
|
||||
requestPort = 9000,
|
||||
containerExposedPorts = {8080, 9000})
|
||||
@Tag(DistributionTest.SLOW)
|
||||
|
|
@ -44,16 +45,16 @@ public class HealthDistTest {
|
|||
|
||||
@Test
|
||||
@Launch({ "start-dev" })
|
||||
void testHealthEndpointNotEnabled(KeycloakDistribution distribution) {
|
||||
void testHealthEndpointNotEnabled(KeycloakRunner runner) {
|
||||
assertThrows(IOException.class, () -> when().get("/health"), "Connection refused must be thrown");
|
||||
distribution.setRequestPort(8080);
|
||||
runner.setRequestPort(8080);
|
||||
when().get("/health").then()
|
||||
.statusCode(404);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Launch({ "start-dev", "--health-enabled=true" })
|
||||
void testHealthEndpoint(KeycloakDistribution distribution) {
|
||||
void testHealthEndpoint(KeycloakRunner runner) {
|
||||
when().get("/health").then()
|
||||
.statusCode(200);
|
||||
when().get("/health/live").then()
|
||||
|
|
@ -67,15 +68,15 @@ public class HealthDistTest {
|
|||
.statusCode(404);
|
||||
|
||||
// still nothing on main
|
||||
distribution.setRequestPort(8080);
|
||||
runner.setRequestPort(8080);
|
||||
when().get("/health/ready").then()
|
||||
.statusCode(404);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Launch({ "start-dev", "--health-enabled=true", "--http-management-health-enabled=false" })
|
||||
void testHealthEndpointOnMain(KeycloakDistribution distribution) {
|
||||
distribution.setRequestPort(8080);
|
||||
void testHealthEndpointOnMain(KeycloakRunner runner) {
|
||||
runner.setRequestPort(8080);
|
||||
when().get("/health/ready").then().statusCode(200);
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +96,7 @@ public class HealthDistTest {
|
|||
private static final String BOOTSTRAP_COMPLETED = "Bootstrap completed";
|
||||
|
||||
@Test
|
||||
@Launch({ "start", "--health-enabled=true", "--http-enabled=true", "--hostname-strict=false" })
|
||||
@Launch({ "start", "--cache=ispn", "--health-enabled=true", "--http-enabled=true", "--hostname-strict=false" })
|
||||
void testAsyncStartupEnabled(LaunchResult result) {
|
||||
when().get("/health/live").then()
|
||||
.statusCode(200);
|
||||
|
|
@ -140,21 +141,21 @@ public class HealthDistTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testUsingRelativePath(KeycloakDistribution distribution) {
|
||||
void testUsingRelativePath(KeycloakRunner runner) {
|
||||
for (String relativePath : List.of("/auth", "/auth/", "auth")) {
|
||||
distribution.run("start-dev", "--health-enabled=true", "--http-management-relative-path=" + relativePath);
|
||||
runner.run("start-dev", "--health-enabled=true", "--http-management-relative-path=" + relativePath);
|
||||
if (!relativePath.endsWith("/")) {
|
||||
relativePath = relativePath + "/";
|
||||
}
|
||||
when().get(relativePath + "health").then().statusCode(200);
|
||||
distribution.stop();
|
||||
runner.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultipleRequests(KeycloakDistribution distribution) throws Exception {
|
||||
void testMultipleRequests(KeycloakRunner runner) throws Exception {
|
||||
for (String relativePath : List.of("/", "/auth/", "auth")) {
|
||||
distribution.run("start-dev", "--health-enabled=true", "--http-management-relative-path=" + relativePath);
|
||||
runner.run("start-dev", "--health-enabled=true", "--http-management-relative-path=" + relativePath);
|
||||
CompletableFuture<?> future = CompletableFuture.completedFuture(null);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
|
|
@ -173,7 +174,7 @@ public class HealthDistTest {
|
|||
|
||||
future.get(5, TimeUnit.MINUTES);
|
||||
|
||||
distribution.stop();
|
||||
runner.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,9 @@ import java.util.List;
|
|||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.WithEnvVars;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.quarkus.runtime.Environment;
|
||||
import org.keycloak.quarkus.runtime.cli.command.BootstrapAdmin;
|
||||
import org.keycloak.quarkus.runtime.cli.command.BootstrapAdminService;
|
||||
|
|
@ -48,7 +48,7 @@ import org.junit.jupiter.api.Test;
|
|||
import static org.keycloak.quarkus.runtime.cli.command.AbstractAutoBuildCommand.OPTIMIZED_BUILD_OPTION_LONG;
|
||||
|
||||
@WithEnvVars({"KEYCLOAK_COMMAND_MODE", "ALL", "KEYCLOAK_HELP_WIDTH", "80"})
|
||||
@DistributionTest
|
||||
@DistributionTest(localCache = false)
|
||||
@RawDistOnly(reason = "Verifying the help message output doesn't need long spin-up of docker dist tests.")
|
||||
@Tag(DistributionTest.WIN)
|
||||
public class HelpCommandDistTest {
|
||||
|
|
@ -188,7 +188,7 @@ public class HelpCommandDistTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testHelpDoesNotStartReAugJvm(KeycloakDistribution dist) {
|
||||
public void testHelpDoesNotStartReAugJvm(KeycloakRunner runner) {
|
||||
for (String helpCmd : List.of("-h", "--help", "--help-all")) {
|
||||
for (String cmd : List.of("", "start", "start-dev", "build")) {
|
||||
String debugOption = "--debug";
|
||||
|
|
@ -197,7 +197,7 @@ public class HelpCommandDistTest {
|
|||
debugOption = "--debug=8787";
|
||||
}
|
||||
|
||||
CLIResult run = dist.run(debugOption, cmd, helpCmd);
|
||||
CLIResult run = runner.run(debugOption, cmd, helpCmd);
|
||||
assertSingleJvmStarted(run);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ package org.keycloak.it.cli.dist;
|
|||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.SkipRealmBootstrap;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import io.quarkus.test.junit.main.LaunchResult;
|
||||
|
|
@ -29,9 +29,8 @@ import org.junit.jupiter.api.Test;
|
|||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
@DistributionTest
|
||||
@DistributionTest(stopServer = Mode.BEFORE_BOOTSTRAP)
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
@SkipRealmBootstrap
|
||||
public class HostnameV2DistTest {
|
||||
@Test
|
||||
@Launch({"start", "--db=dev-file", "--http-enabled=true"})
|
||||
|
|
|
|||
|
|
@ -26,10 +26,11 @@ import java.util.concurrent.Executors;
|
|||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.junit5.extension.TestProvider;
|
||||
import org.keycloak.it.resource.realm.TestRealmResourceTestProvider;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
|
|
@ -44,13 +45,13 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
@DistributionTest(keepAlive = true, enableTls = true)
|
||||
@DistributionTest(stopServer = Mode.MANUAL, enableTls = true)
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
public class HttpDistTest {
|
||||
@Test
|
||||
@TestProvider(TestRealmResourceTestProvider.class)
|
||||
public void maxQueuedRequestsTest(KeycloakDistribution dist) {
|
||||
dist.run("start-dev", "--http-max-queued-requests=1", "--http-pool-max-threads=1");
|
||||
public void maxQueuedRequestsTest(KeycloakRunner runner) {
|
||||
runner.run("start-dev", "--http-max-queued-requests=1", "--http-pool-max-threads=1");
|
||||
|
||||
ExecutorService executor = Executors.newFixedThreadPool(5);
|
||||
try {
|
||||
|
|
@ -93,24 +94,24 @@ public class HttpDistTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void httpStoreTypeValidation(KeycloakDistribution dist) {
|
||||
CLIResult result = dist.run("start", "--https-key-store-file=not-there.ks", "--hostname-strict=false");
|
||||
public void httpStoreTypeValidation(KeycloakRunner runner) {
|
||||
CLIResult result = runner.run("start", "--https-key-store-file=not-there.ks", "--hostname-strict=false");
|
||||
result.assertExitCode(-1);
|
||||
result.assertMessage("ERROR: Unable to determine 'https-key-store-type' automatically. Adjust the file extension or specify the property");
|
||||
|
||||
result = dist.run("start", "--https-trust-store-file=not-there.ks", "--hostname-strict=false");
|
||||
result = runner.run("start", "--https-trust-store-file=not-there.ks", "--hostname-strict=false");
|
||||
result.assertExitCode(-1);
|
||||
result.assertMessage("ERROR: Unable to determine 'https-trust-store-type' automatically. Adjust the file extension or specify the property");
|
||||
|
||||
result = dist.run("start", "--https-key-store-file=not-there.ks", "--hostname-strict=false", "--https-key-store-type=jdk");
|
||||
result = runner.run("start", "--https-key-store-file=not-there.ks", "--hostname-strict=false", "--https-key-store-type=jdk");
|
||||
result.assertExitCode(-1);
|
||||
result.assertMessage("ERROR: Failed to load 'https-*' material: NoSuchFileException not-there.ks");
|
||||
|
||||
dist.copyOrReplaceFileFromClasspath("/server.keystore.pkcs12", Path.of("conf", "server.p12"));
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
rawDist.copyOrReplaceFileFromClasspath("/server.keystore.pkcs12", Path.of("conf", "server.p12"));
|
||||
Path truststorePath = rawDist.getDistPath().resolve("conf").resolve("server.p12").toAbsolutePath();
|
||||
|
||||
result = dist.run("start", "--https-trust-store-file=" + truststorePath, "--hostname-strict=false");
|
||||
result = runner.run("start", "--https-trust-store-file=" + truststorePath, "--hostname-strict=false");
|
||||
result.assertExitCode(-1);
|
||||
result.assertMessage("ERROR: No trust store password provided");
|
||||
}
|
||||
|
|
@ -123,9 +124,9 @@ public class HttpDistTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testShutdownParametersNegativeValue(KeycloakDistribution dist) {
|
||||
public void testShutdownParametersNegativeValue(KeycloakRunner runner) {
|
||||
// Test that negative values are rejected
|
||||
CLIResult result = dist.run("start-dev", "--shutdown-delay=-1s");
|
||||
CLIResult result = runner.run("start-dev", "--shutdown-delay=-1s");
|
||||
result.assertError("Invalid duration '-1s'. Duration must be zero or positive");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ import java.util.function.Consumer;
|
|||
import org.keycloak.it.junit5.extension.BeforeStartDistribution;
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
|
||||
import io.quarkus.deployment.util.FileUtil;
|
||||
|
|
@ -50,15 +50,15 @@ public class ImportAtStartupDistTest {
|
|||
|
||||
@Test
|
||||
@BeforeStartDistribution(CreateRealmConfigurationFile.class)
|
||||
void testMultipleImport(KeycloakDistribution dist) throws IOException {
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
void testMultipleImport(KeycloakRunner runner) throws IOException {
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
Path dir = rawDist.getDistPath().resolve("data").resolve("import");
|
||||
|
||||
// add another realm
|
||||
Files.write(dir.resolve("realm2.json"), Files.readAllLines(dir.resolve("realm.json")).stream()
|
||||
.map(s -> s.replace("quickstart-realm", "other-realm")).toList());
|
||||
|
||||
CLIResult cliResult = dist.run("start-dev", "--import-realm");
|
||||
CLIResult cliResult = runner.run("start-dev", "--import-realm");
|
||||
cliResult.assertMessage("Realm 'quickstart-realm' imported");
|
||||
cliResult.assertMessage("Realm 'other-realm' imported");
|
||||
}
|
||||
|
|
@ -80,13 +80,13 @@ public class ImportAtStartupDistTest {
|
|||
|
||||
@Test
|
||||
@BeforeStartDistribution(CreateRealmConfigurationFile.class)
|
||||
void testImportFromFileCreatedByExportAllRealms(KeycloakDistribution dist) throws IOException {
|
||||
dist.run("start-dev", "--import-realm");
|
||||
dist.run("--profile=dev", "export", "--file=../data/import/realm.json", "--verbose");
|
||||
void testImportFromFileCreatedByExportAllRealms(KeycloakRunner runner) throws IOException {
|
||||
runner.run("start-dev", "--import-realm");
|
||||
runner.run("--profile=dev", "export", "--file=../data/import/realm.json", "--verbose");
|
||||
|
||||
dist.unwrap(RawKeycloakDistribution.class).resetH2Dir();
|
||||
runner.getDistribution(RawKeycloakDistribution.class).resetH2Dir();
|
||||
|
||||
CLIResult result = dist.run("start-dev", "--import-realm");
|
||||
CLIResult result = runner.run("start-dev", "--import-realm");
|
||||
result.assertMessage("Realm 'quickstart-realm' imported");
|
||||
result.assertMessage("Realm 'master' imported");
|
||||
result.assertNoMessage("Realm 'master' already exists. Import skipped");
|
||||
|
|
@ -94,56 +94,53 @@ public class ImportAtStartupDistTest {
|
|||
|
||||
@Test
|
||||
@BeforeStartDistribution(CreateRealmConfigurationFile.class)
|
||||
void testImportFromFileCreatedByExportSingleRealm(KeycloakDistribution dist) throws IOException {
|
||||
dist.run("start-dev", "--import-realm");
|
||||
dist.run("--profile=dev", "export", "--realm=quickstart-realm", "--file=../data/import/realm.json");
|
||||
void testImportFromFileCreatedByExportSingleRealm(KeycloakRunner runner) throws IOException {
|
||||
runner.run("start-dev", "--import-realm");
|
||||
runner.run("--profile=dev", "export", "--realm=quickstart-realm", "--file=../data/import/realm.json");
|
||||
|
||||
dist.unwrap(RawKeycloakDistribution.class).resetH2Dir();
|
||||
runner.getDistribution(RawKeycloakDistribution.class).resetH2Dir();
|
||||
|
||||
CLIResult result = dist.run("start-dev", "--import-realm");
|
||||
CLIResult result = runner.run("start-dev", "--import-realm");
|
||||
result.assertMessage("Realm 'quickstart-realm' imported");
|
||||
result.assertNoMessage("Not importing realm master from file");
|
||||
}
|
||||
|
||||
@Test
|
||||
@BeforeStartDistribution(CreateRealmConfigurationFile.class)
|
||||
void testImportFromDirCreatedByExport(KeycloakDistribution dist) throws IOException {
|
||||
dist.run("start-dev", "--import-realm");
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
void testImportFromDirCreatedByExport(KeycloakRunner runner) throws IOException {
|
||||
runner.run("start-dev", "--import-realm");
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
FileUtil.deleteDirectory(rawDist.getDistPath().resolve("data").resolve("import").toAbsolutePath());
|
||||
dist.run("--profile=dev", "export", "--dir=../data/import");
|
||||
runner.run("--profile=dev", "export", "--dir=../data/import");
|
||||
|
||||
dist.unwrap(RawKeycloakDistribution.class).resetH2Dir();
|
||||
runner.getDistribution(RawKeycloakDistribution.class).resetH2Dir();
|
||||
|
||||
CLIResult result = dist.run("start-dev", "--import-realm");
|
||||
CLIResult result = runner.run("start-dev", "--import-realm");
|
||||
result.assertMessage("Realm 'quickstart-realm' imported");
|
||||
result.assertNoMessage("Not importing realm master from file");
|
||||
}
|
||||
|
||||
public static class CreateRealmConfigurationFile implements Consumer<KeycloakDistribution> {
|
||||
public static class CreateRealmConfigurationFile implements Consumer<RawKeycloakDistribution> {
|
||||
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.copyOrReplaceFileFromClasspath("/quickstart-realm.json", Path.of("data", "import", "realm.json"));
|
||||
}
|
||||
}
|
||||
|
||||
public static class CreateRealmConfigurationFileAndDir implements Consumer<KeycloakDistribution> {
|
||||
|
||||
public static class CreateRealmConfigurationFileAndDir implements Consumer<RawKeycloakDistribution> {
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.copyOrReplaceFileFromClasspath("/quickstart-realm.json", Path.of("data", "import", "realm.json"));
|
||||
|
||||
RawKeycloakDistribution rawDist = distribution.unwrap(RawKeycloakDistribution.class);
|
||||
|
||||
rawDist.getDistPath().resolve("data").resolve("import").resolve("sub-dir").toFile().mkdirs();
|
||||
distribution.getDistPath().resolve("data").resolve("import").resolve("sub-dir").toFile().mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
public static class CreateRealmConfigurationFileWithUnsupportedExtension implements Consumer<KeycloakDistribution> {
|
||||
public static class CreateRealmConfigurationFileWithUnsupportedExtension implements Consumer<RawKeycloakDistribution> {
|
||||
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.copyOrReplaceFileFromClasspath("/quickstart-realm.json", Path.of("data", "import", "realm"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,10 @@ import java.io.IOException;
|
|||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.junit5.extension.StopServer;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
|
||||
|
|
@ -46,12 +48,12 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
public class ImportDistTest {
|
||||
|
||||
@Test
|
||||
void testImport(KeycloakDistribution dist) throws IOException {
|
||||
CLIResult cliResult = dist.run("build");
|
||||
void testImport(KeycloakRunner runner) throws IOException {
|
||||
CLIResult cliResult = runner.run("build");
|
||||
|
||||
File dir = new File("target");
|
||||
|
||||
cliResult = dist.run("export", "--realm=master", "--dir=" + dir.getAbsolutePath());
|
||||
cliResult = runner.run("export", "--realm=master", "--dir=" + dir.getAbsolutePath());
|
||||
cliResult.assertMessage("Export of realm 'master' requested.");
|
||||
cliResult.assertMessage("Export finished successfully");
|
||||
cliResult.assertNoMessage("local_addr");
|
||||
|
|
@ -63,31 +65,31 @@ public class ImportDistTest {
|
|||
node.put("enabled", "${REALM_ENABLED}");
|
||||
mapper.writer().writeValue(file, node);
|
||||
|
||||
dist.setEnvVar("REALM_ENABLED", "true");
|
||||
dist.setEnvVar("KC_HOSTNAME_STRICT", "false");
|
||||
dist.setEnvVar("KC_CACHE", "ispn");
|
||||
cliResult = dist.run("import", "--dir=" + dir.getAbsolutePath());
|
||||
runner.setEnvVar("REALM_ENABLED", "true");
|
||||
runner.setEnvVar("KC_HOSTNAME_STRICT", "false");
|
||||
runner.setEnvVar("KC_CACHE", "ispn");
|
||||
cliResult = runner.run("import", "--dir=" + dir.getAbsolutePath());
|
||||
cliResult.assertMessage("Realm 'master' imported");
|
||||
cliResult.assertMessage("Import finished successfully");
|
||||
cliResult.assertNoMessage("Changes detected in configuration");
|
||||
cliResult.assertNoMessage("Listening on: http");
|
||||
cliResult.assertNoMessage("local_addr");
|
||||
|
||||
cliResult = dist.run("import");
|
||||
cliResult = runner.run("import");
|
||||
cliResult.assertError("Must specify either --dir or --file options.");
|
||||
}
|
||||
|
||||
@StopServer(Mode.MANUAL)
|
||||
@Test
|
||||
void testImportNewRealm(KeycloakDistribution dist) throws IOException {
|
||||
dist.setEnvVar("MY_SECRET", "admin123");
|
||||
void testImportNewRealm(KeycloakRunner runner) throws IOException {
|
||||
runner.setEnvVar("MY_SECRET", "admin123");
|
||||
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
CLIResult result = rawDist.run("bootstrap-admin", "service", "--db=dev-file", "--client-id=admin", "--client-secret:env=MY_SECRET");
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
CLIResult result = rawDist.kc("bootstrap-admin", "service", "--db=dev-file", "--client-id=admin", "--client-secret:env=MY_SECRET");
|
||||
|
||||
assertTrue(result.getErrorOutput().isEmpty(), result.getErrorOutput());
|
||||
|
||||
rawDist.setManualStop(true);
|
||||
result = rawDist.run("start-dev", "--db-url-properties=;AUTO_SERVER=TRUE;DB_CLOSE_ON_EXIT=TRUE");
|
||||
result = runner.run("start-dev", "--db-url-properties=;AUTO_SERVER=TRUE;DB_CLOSE_ON_EXIT=TRUE");
|
||||
|
||||
File file = new File("target/realm.json");
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import java.net.ConnectException;
|
|||
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
|
@ -32,7 +33,7 @@ import static org.hamcrest.CoreMatchers.is;
|
|||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@DistributionTest(keepAlive = true, defaultOptions = { "--db=dev-file", "--http-enabled=true", "--hostname-strict=false"})
|
||||
@DistributionTest(stopServer = Mode.MANUAL, defaultOptions = { "--db=dev-file", "--http-enabled=true", "--hostname-strict=false"})
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
public class IpStackDistTest {
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
package org.keycloak.it.cli.dist;
|
||||
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.DryRun;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.junit5.extension.WithEnvVars;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
|
|
@ -34,8 +34,7 @@ import static org.hamcrest.CoreMatchers.not;
|
|||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.matchesPattern;
|
||||
|
||||
@DryRun
|
||||
@DistributionTest
|
||||
@DistributionTest(stopServer = Mode.BEFORE_QUARKUS)
|
||||
@RawDistOnly(reason = "No need to test script again on container")
|
||||
@WithEnvVars({"PRINT_ENV", "true"})
|
||||
@Tag(DistributionTest.WIN)
|
||||
|
|
|
|||
|
|
@ -22,9 +22,10 @@ import java.util.concurrent.TimeUnit;
|
|||
import org.keycloak.it.jaxrs.filter.TestFilterTestProvider;
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.junit5.extension.TestProvider;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
|
||||
import org.awaitility.Awaitility;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
|
|
@ -33,15 +34,15 @@ import org.junit.jupiter.api.Test;
|
|||
import static io.restassured.RestAssured.when;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@DistributionTest(keepAlive = true)
|
||||
@DistributionTest(stopServer = Mode.MANUAL)
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
@Tag(DistributionTest.SMOKE)
|
||||
public class JaxRsDistTest {
|
||||
|
||||
@Test
|
||||
@TestProvider(TestFilterTestProvider.class)
|
||||
public void requestFilterTest(KeycloakDistribution dist) {
|
||||
CLIResult cliResult = dist.run("start-dev");
|
||||
public void requestFilterTest(KeycloakRunner runner) {
|
||||
CLIResult cliResult = runner.run("start-dev");
|
||||
|
||||
cliResult.assertStartedDevMode();
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ package org.keycloak.it.cli.dist;
|
|||
import java.io.IOException;
|
||||
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
|
||||
import io.quarkus.deployment.util.FileUtil;
|
||||
|
|
@ -17,16 +17,16 @@ import org.junit.jupiter.api.Test;
|
|||
public class LiquibaseDistTest {
|
||||
|
||||
@Test
|
||||
public void dbLockMultipleExecution(KeycloakDistribution distribution) throws IOException {
|
||||
public void dbLockMultipleExecution(KeycloakRunner runner) throws IOException {
|
||||
// force a full db initialization
|
||||
RawKeycloakDistribution rawDist = distribution.unwrap(RawKeycloakDistribution.class);
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
FileUtil.deleteDirectory(rawDist.getDistPath().resolve("data").resolve("h2").toAbsolutePath());
|
||||
var result = distribution.run("start-dev", "--log-level=org.keycloak.connections.jpa.updater.liquibase.lock.CustomLockService:trace");
|
||||
var result = runner.run("start-dev", "--log-level=org.keycloak.connections.jpa.updater.liquibase.lock.CustomLockService:trace");
|
||||
result.assertMessage("Initialize Database Lock Table, current locks []");
|
||||
result.assertMessage("Initialized record in the database lock table");
|
||||
|
||||
// the code block in the CustomLockService should not be executed for the second time
|
||||
result = distribution.run("start-dev", "--log-level=org.keycloak.connections.jpa.updater.liquibase.lock.CustomLockService:trace");
|
||||
result = runner.run("start-dev", "--log-level=org.keycloak.connections.jpa.updater.liquibase.lock.CustomLockService:trace");
|
||||
result.assertNoMessage("Initialize Database Lock Table, current locks");
|
||||
result.assertNoMessage("Initialized record in the database lock table");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,9 +32,10 @@ import org.keycloak.connections.httpclient.HttpClientBuilder;
|
|||
import org.keycloak.cookie.CookieType;
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.DryRun;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.junit5.extension.StopServer;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.utils.RawDistRootPath;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
|
||||
|
|
@ -61,7 +62,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
|
|||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@DistributionTest(keepAlive = true)
|
||||
@DistributionTest(stopServer = Mode.MANUAL)
|
||||
@RawDistOnly(reason = "Too verbose for docker and enough to check raw dist")
|
||||
@Tag(DistributionTest.SLOW)
|
||||
public class LoggingDistTest {
|
||||
|
|
@ -107,18 +108,18 @@ public class LoggingDistTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testJsonFormatApplied(KeycloakDistribution dist) throws IOException {
|
||||
dist.unwrap(RawKeycloakDistribution.class).resetH2Dir();
|
||||
CLIResult cliResult = dist.run("start-dev", "--log-console-output=json");
|
||||
void testJsonFormatApplied(KeycloakRunner runner) throws IOException {
|
||||
runner.getDistribution(RawKeycloakDistribution.class).resetH2Dir();
|
||||
CLIResult cliResult = runner.run("start-dev", "--log-console-output=json");
|
||||
cliResult.assertJsonLogDefaultsApplied();
|
||||
cliResult.assertStartedDevMode();
|
||||
assertFalse(cliResult.getOutput().contains("\"loggerName\":\"liquibase.servicelocator\",\"level\":\"FINE\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLogLevelSettingsAppliedWhenJsonEnabled(KeycloakDistribution dist) throws IOException {
|
||||
dist.unwrap(RawKeycloakDistribution.class).resetH2Dir();
|
||||
CLIResult cliResult = dist.run("start-dev", "--log-level=off,org.keycloak:debug,liquibase:debug", "--log-console-output=json");
|
||||
void testLogLevelSettingsAppliedWhenJsonEnabled(KeycloakRunner runner) throws IOException {
|
||||
runner.getDistribution(RawKeycloakDistribution.class).resetH2Dir();
|
||||
CLIResult cliResult = runner.run("start-dev", "--log-level=off,org.keycloak:debug,liquibase:debug", "--log-console-output=json");
|
||||
assertFalse(cliResult.getOutput().contains("\"loggerName\":\"io.quarkus\",\"level\":\"INFO\")"));
|
||||
assertTrue(cliResult.getOutput().contains("\"loggerName\":\"org.keycloak.services.resources.KeycloakApplication\",\"level\":\"DEBUG\""));
|
||||
assertTrue(cliResult.getOutput().contains("\"loggerName\":\"liquibase.servicelocator\",\"level\":\"FINE\""));
|
||||
|
|
@ -147,16 +148,16 @@ public class LoggingDistTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void failUnknownHandlersInConfFile(KeycloakDistribution dist) {
|
||||
dist.copyOrReplaceFileFromClasspath("/logging/keycloak.conf", Paths.get("conf", "keycloak.conf"));
|
||||
CLIResult cliResult = dist.run("start-dev");
|
||||
void failUnknownHandlersInConfFile(KeycloakRunner runner) {
|
||||
runner.getDistribution(RawKeycloakDistribution.class).copyOrReplaceFileFromClasspath("/logging/keycloak.conf", Paths.get("conf", "keycloak.conf"));
|
||||
CLIResult cliResult = runner.run("start-dev");
|
||||
cliResult.assertError("Invalid value for option 'kc.log' in keycloak.conf: foo. Expected values are: console, file, syslog");
|
||||
}
|
||||
|
||||
@Test
|
||||
void failEmptyLogErrorFromConfFileError(KeycloakDistribution dist) {
|
||||
dist.copyOrReplaceFileFromClasspath("/logging/emptylog.conf", Paths.get("conf", "emptylog.conf"));
|
||||
CLIResult cliResult = dist.run(CONFIG_FILE_LONG_NAME+"=../conf/emptylog.conf", "start-dev");
|
||||
void failEmptyLogErrorFromConfFileError(KeycloakRunner runner) {
|
||||
runner.getDistribution(RawKeycloakDistribution.class).copyOrReplaceFileFromClasspath("/logging/emptylog.conf", Paths.get("conf", "emptylog.conf"));
|
||||
CLIResult cliResult = runner.run(CONFIG_FILE_LONG_NAME+"=../conf/emptylog.conf", "start-dev");
|
||||
cliResult.assertError("Invalid value for option 'kc.log' in emptylog.conf: . Expected values are: console, file, syslog");
|
||||
}
|
||||
|
||||
|
|
@ -182,14 +183,14 @@ public class LoggingDistTest {
|
|||
|
||||
@Test
|
||||
@Launch({"start-dev", "--log-console-level=wrong"})
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
void wrongLevelForHandlers(CLIResult cliResult) {
|
||||
cliResult.assertError("Invalid value for option '--log-console-level': wrong. Expected values are (case insensitive): off, fatal, error, warn, info, debug, trace, all");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Launch({"start-dev", "--log-level-org.keycloak=wrong"})
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
void wrongLevelForCategory(CLIResult cliResult) {
|
||||
cliResult.assertError("Invalid log level: wrong. Possible values are: warn, trace, debug, error, fatal, info.");
|
||||
}
|
||||
|
|
@ -324,7 +325,7 @@ public class LoggingDistTest {
|
|||
// HTTP Access log
|
||||
@Test
|
||||
@Launch({"start-dev", "--http-access-log-enabled=true", "--http-access-log-pattern='%A %{METHOD} %{REQUEST_URL} %{i,User-Agent}'", "--http-access-log-exclude=/realms/master/clients/.*"})
|
||||
void httpAccessLogNotNamedPattern(CLIResult cliResult, KeycloakDistribution dist, RawDistRootPath path) {
|
||||
void httpAccessLogNotNamedPattern(CLIResult cliResult, KeycloakRunner runner, RawDistRootPath path) {
|
||||
when().get("http://127.0.0.1:8080/realms/master/.well-known/openid-configuration").then()
|
||||
.statusCode(200);
|
||||
Awaitility.await().atMost(5, TimeUnit.SECONDS).untilAsserted(
|
||||
|
|
@ -337,7 +338,7 @@ public class LoggingDistTest {
|
|||
cliResult.assertNoMessage("127.0.0.1 GET /realms/master/clients/account/redirect");
|
||||
|
||||
// file
|
||||
CLIResult fileCliResult = dist.run("start-dev", "--http-access-log-enabled=true", "--http-access-log-file-enabled=true", "--http-access-log-pattern='%A %{METHOD} %{REQUEST_URL} %{i,User-Agent}'", "--http-access-log-exclude=/realms/master/clients/.*");
|
||||
CLIResult fileCliResult = runner.run("start-dev", "--http-access-log-enabled=true", "--http-access-log-file-enabled=true", "--http-access-log-pattern='%A %{METHOD} %{REQUEST_URL} %{i,User-Agent}'", "--http-access-log-exclude=/realms/master/clients/.*");
|
||||
fileCliResult.assertStartedDevMode();
|
||||
when().get("http://127.0.0.1:8080/realms/master/.well-known/openid-configuration").then()
|
||||
.statusCode(200);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ import java.io.IOException;
|
|||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.DistributionType;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import io.quarkus.test.junit.main.LaunchResult;
|
||||
|
|
@ -37,7 +38,7 @@ import static org.hamcrest.CoreMatchers.containsString;
|
|||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@DistributionTest(keepAlive = true,
|
||||
@DistributionTest(stopServer = Mode.MANUAL,
|
||||
defaultOptions = {"--db=dev-file", "--health-enabled=true", "--metrics-enabled=true"},
|
||||
requestPort = 9000,
|
||||
containerExposedPorts = {9000, 8080, 9005})
|
||||
|
|
@ -57,14 +58,14 @@ public class ManagementDistTest {
|
|||
@Test
|
||||
@Order(2)
|
||||
@Launch({"start-dev", "--legacy-observability-interface=true"})
|
||||
void testManagementDisabled(LaunchResult result, KeycloakDistribution distribution) {
|
||||
void testManagementDisabled(LaunchResult result, KeycloakRunner runner) {
|
||||
CLIResult cliResult = (CLIResult) result;
|
||||
cliResult.assertNoMessage("Management interface listening on");
|
||||
|
||||
assertThrows(IOException.class, () -> when().get("/"), "Connection refused must be thrown");
|
||||
assertThrows(IOException.class, () -> when().get("/health"), "Connection refused must be thrown");
|
||||
|
||||
distribution.setRequestPort(8080);
|
||||
runner.setRequestPort(8080);
|
||||
|
||||
when().get("/health").then()
|
||||
.statusCode(200);
|
||||
|
|
@ -124,11 +125,11 @@ public class ManagementDistTest {
|
|||
|
||||
@Test
|
||||
@Launch({"start-dev", "--http-management-port=9005"})
|
||||
void testManagementDifferentPort(LaunchResult result, KeycloakDistribution distribution) {
|
||||
void testManagementDifferentPort(LaunchResult result, KeycloakRunner runner) {
|
||||
CLIResult cliResult = (CLIResult) result;
|
||||
cliResult.assertMessage("Management interface listening on http://0.0.0.0:9005");
|
||||
|
||||
distribution.setRequestPort(9005);
|
||||
runner.setRequestPort(9005);
|
||||
|
||||
when().get("/").then()
|
||||
.statusCode(200)
|
||||
|
|
@ -158,10 +159,10 @@ public class ManagementDistTest {
|
|||
|
||||
@Test
|
||||
@Launch({"start-dev", "--http-relative-path=/auth", "--http-management-relative-path=/management"})
|
||||
void testManagementRootRedirects(LaunchResult result, KeycloakDistribution distribution) {
|
||||
void testManagementRootRedirects(LaunchResult result, KeycloakRunner runner) {
|
||||
assertRelativePath(result, "/management");
|
||||
|
||||
distribution.setRequestPort(8080);
|
||||
runner.setRequestPort(8080);
|
||||
|
||||
given().redirects().follow(false).when().get("/").then().statusCode(302).header("Location", is("/auth"));
|
||||
when().get("/").then().statusCode(200).body(containsString("Welcome to Keycloak"));
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.keycloak.it.cli.dist;
|
|||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import io.quarkus.test.junit.main.LaunchResult;
|
||||
|
|
@ -30,7 +31,7 @@ import org.junit.jupiter.api.Test;
|
|||
import static io.restassured.RestAssured.when;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
|
||||
@DistributionTest(keepAlive = true,
|
||||
@DistributionTest(stopServer = Mode.MANUAL,
|
||||
enableTls = true,
|
||||
defaultOptions = {"--db=dev-file", "--health-enabled=true", "--metrics-enabled=true"},
|
||||
requestPort = 9000)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import java.io.IOException;
|
|||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import io.quarkus.test.junit.main.LaunchResult;
|
||||
|
|
@ -28,7 +29,7 @@ import org.junit.jupiter.api.Test;
|
|||
import static io.restassured.RestAssured.when;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@DistributionTest(keepAlive = true,
|
||||
@DistributionTest(stopServer = Mode.MANUAL,
|
||||
requestPort = 9000,
|
||||
containerExposedPorts = {9000, 8080})
|
||||
public class ManagementOffDistTest {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
|
|
@ -37,7 +38,7 @@ import static org.hamcrest.Matchers.matchesPattern;
|
|||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@DistributionTest(keepAlive = true,
|
||||
@DistributionTest(stopServer = Mode.MANUAL,
|
||||
requestPort = 9000,
|
||||
containerExposedPorts = {8080, 9000})
|
||||
@Tag(DistributionTest.SLOW)
|
||||
|
|
@ -45,11 +46,11 @@ public class MetricsDistTest {
|
|||
|
||||
@Test
|
||||
@Launch({ "start-dev" })
|
||||
void testMetricsEndpointNotEnabled(KeycloakDistribution distribution) {
|
||||
void testMetricsEndpointNotEnabled(KeycloakRunner runner) {
|
||||
assertThrows(IOException.class, () -> when().get("/metrics"), "Connection refused must be thrown");
|
||||
assertThrows(IOException.class, () -> when().get("/q/metrics"), "Connection refused must be thrown");
|
||||
|
||||
distribution.setRequestPort(8080);
|
||||
runner.setRequestPort(8080);
|
||||
|
||||
when().get("/metrics").then()
|
||||
.statusCode(404);
|
||||
|
|
@ -138,10 +139,10 @@ public class MetricsDistTest {
|
|||
|
||||
@Test
|
||||
@Launch({ "start-dev", "--metrics-enabled=true", "--tracing-enabled=true" })
|
||||
void testMetricsEndpointWithCacheMetricsHistogramsAndExemplars(KeycloakDistribution distribution) {
|
||||
runClientCredentialGrantWithUnknownClientId(distribution);
|
||||
void testMetricsEndpointWithCacheMetricsHistogramsAndExemplars(KeycloakRunner runner) {
|
||||
runClientCredentialGrantWithUnknownClientId(runner);
|
||||
|
||||
distribution.setRequestPort(9000);
|
||||
runner.setRequestPort(9000);
|
||||
// Exemplars are only present when metrics and traces are enabled
|
||||
given().accept("application/openmetrics-text; version=1.0.0; charset=utf-8");
|
||||
when().get("/metrics").then()
|
||||
|
|
@ -153,10 +154,10 @@ public class MetricsDistTest {
|
|||
|
||||
@Test
|
||||
@Launch({ "start-dev", "--metrics-enabled=true", "--features=user-event-metrics", "--event-metrics-user-enabled=true" })
|
||||
void testMetricsEndpointWithUserEventMetrics(KeycloakDistribution distribution) {
|
||||
runClientCredentialGrantWithUnknownClientId(distribution);
|
||||
void testMetricsEndpointWithUserEventMetrics(KeycloakRunner runner) {
|
||||
runClientCredentialGrantWithUnknownClientId(runner);
|
||||
|
||||
distribution.setRequestPort(9000);
|
||||
runner.setRequestPort(9000);
|
||||
when().get("/metrics").then()
|
||||
.statusCode(200)
|
||||
.body(containsString("keycloak_user_events_total{error=\"client_not_found\",event=\"client_login\",realm=\"master\"}"));
|
||||
|
|
@ -165,18 +166,18 @@ public class MetricsDistTest {
|
|||
|
||||
@Test
|
||||
@Launch({ "start-dev", "--metrics-enabled=true", "--features=user-event-metrics", "--event-metrics-user-enabled=false" })
|
||||
void testMetricsEndpointWithoutUserEventMetrics(KeycloakDistribution distribution) {
|
||||
runClientCredentialGrantWithUnknownClientId(distribution);
|
||||
void testMetricsEndpointWithoutUserEventMetrics(KeycloakRunner runner) {
|
||||
runClientCredentialGrantWithUnknownClientId(runner);
|
||||
|
||||
distribution.setRequestPort(9000);
|
||||
runner.setRequestPort(9000);
|
||||
when().get("/metrics").then()
|
||||
.statusCode(200)
|
||||
.body(not(containsString("keycloak_user_events_total{error=\"client_not_found\",event=\"client_login\",realm=\"master\"}")));
|
||||
|
||||
}
|
||||
|
||||
private static void runClientCredentialGrantWithUnknownClientId(KeycloakDistribution distribution) {
|
||||
distribution.setRequestPort(8080);
|
||||
private static void runClientCredentialGrantWithUnknownClientId(KeycloakRunner runner) {
|
||||
runner.setRequestPort(8080);
|
||||
given().formParam("grant_type", "client_credentials")
|
||||
.formParam("client_id", "unknown")
|
||||
.formParam("client_secret", "unknown").
|
||||
|
|
@ -186,21 +187,21 @@ public class MetricsDistTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testUsingRelativePath(KeycloakDistribution distribution) {
|
||||
void testUsingRelativePath(KeycloakRunner runner) {
|
||||
for (String relativePath : List.of("/auth", "/auth/", "auth")) {
|
||||
distribution.run("start-dev", "--metrics-enabled=true", "--http-management-relative-path=" + relativePath);
|
||||
runner.run("start-dev", "--metrics-enabled=true", "--http-management-relative-path=" + relativePath);
|
||||
if (!relativePath.endsWith("/")) {
|
||||
relativePath = relativePath + "/";
|
||||
}
|
||||
when().get(relativePath + "metrics").then().statusCode(200);
|
||||
distribution.stop();
|
||||
runner.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultipleRequests(KeycloakDistribution distribution) throws Exception {
|
||||
void testMultipleRequests(KeycloakRunner runner) throws Exception {
|
||||
for (String relativePath : List.of("/", "/auth/", "auth")) {
|
||||
distribution.run("start-dev", "--metrics-enabled=true", "--http-management-relative-path=" + relativePath);
|
||||
runner.run("start-dev", "--metrics-enabled=true", "--http-management-relative-path=" + relativePath);
|
||||
CompletableFuture<Void> future = CompletableFuture.completedFuture(null);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
|
|
@ -222,7 +223,7 @@ public class MetricsDistTest {
|
|||
|
||||
future.get(5, TimeUnit.MINUTES);
|
||||
|
||||
distribution.stop();
|
||||
runner.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,9 @@ import java.io.IOException;
|
|||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.DryRun;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.StopServer;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
|
|
@ -36,7 +38,7 @@ import static org.hamcrest.Matchers.equalTo;
|
|||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@DistributionTest(keepAlive = true, requestPort = 9000, containerExposedPorts = {8080, 9000})
|
||||
@DistributionTest(stopServer = Mode.MANUAL, requestPort = 9000, containerExposedPorts = {8080, 9000})
|
||||
@Tag(DistributionTest.SLOW)
|
||||
public class OpenApiDistTest {
|
||||
|
||||
|
|
@ -48,11 +50,11 @@ public class OpenApiDistTest {
|
|||
|
||||
@Test
|
||||
@Launch({"start-dev", FEATURES_OPTION})
|
||||
void testOpenApiEndpointNotEnabled(KeycloakDistribution distribution) {
|
||||
void testOpenApiEndpointNotEnabled(KeycloakRunner runner) {
|
||||
assertThrows(IOException.class, () -> when().get(OPENAPI_ENDPOINT), "Connection refused must be thrown");
|
||||
assertThrows(IOException.class, () -> when().get(OPENAPI_UI_ENDPOINT), "Connection refused must be thrown");
|
||||
|
||||
distribution.setRequestPort(8080);
|
||||
runner.setRequestPort(8080);
|
||||
|
||||
when().get(OPENAPI_ENDPOINT).then()
|
||||
.statusCode(404);
|
||||
|
|
@ -76,20 +78,20 @@ public class OpenApiDistTest {
|
|||
.statusCode(200);
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start-dev", "--openapi-ui-enabled=true", FEATURES_OPTION})
|
||||
void testOpenApiUiFailsWhenOpenApiIsNotEnabled(CLIResult cliResult) {
|
||||
cliResult.assertError("Disabled option: '--openapi-ui-enabled'. Available only when OpenAPI Endpoint is enabled");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
void testOpenApiRequiresFeatures(KeycloakDistribution dist) {
|
||||
CLIResult cliResult = dist.run("start-dev", "--openapi-enabled=true", "--features=openapi");
|
||||
void testOpenApiRequiresFeatures(KeycloakRunner runner) {
|
||||
CLIResult cliResult = runner.run("start-dev", "--openapi-enabled=true", "--features=openapi");
|
||||
cliResult.assertError("ERROR: Feature openapi depends on disabled feature client-admin-api-v2");
|
||||
|
||||
cliResult = dist.run("start-dev", "--openapi-enabled=true", "--features=client-admin-api:v2");
|
||||
cliResult = runner.run("start-dev", "--openapi-enabled=true", "--features=client-admin-api:v2");
|
||||
cliResult.assertError("Disabled option: '--openapi-enabled'. Available only when OpenAPI feature is enabled");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,10 +21,11 @@ import java.nio.file.Paths;
|
|||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.DryRun;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.StopServer;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.junit5.extension.WithEnvVars;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
|
|
@ -38,7 +39,7 @@ import static org.keycloak.quarkus.runtime.cli.command.Main.CONFIG_FILE_LONG_NAM
|
|||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
public class OptionsDistTest {
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Order(1)
|
||||
@Launch({"build", "--db=invalid"})
|
||||
|
|
@ -46,7 +47,7 @@ public class OptionsDistTest {
|
|||
result.assertError("Invalid value for option '--db': invalid. Expected values are: dev-file, dev-mem, mariadb, mssql, mysql, oracle, postgres");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Order(2)
|
||||
@Launch({"start", "--db=dev-file", "--test=invalid"})
|
||||
|
|
@ -54,7 +55,7 @@ public class OptionsDistTest {
|
|||
result.assertError("Unknown option: '--test'");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Order(3)
|
||||
@Launch({"start", "--db=dev-file", "--log=console", "--log-file-output=json", "--http-enabled=true", "--hostname-strict=false"})
|
||||
|
|
@ -63,7 +64,7 @@ public class OptionsDistTest {
|
|||
result.assertError("Possible solutions: --log-console-output, --log-level, --log, --log-console-level, --log-console-format, --log-console-async, --log-async");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Order(4)
|
||||
@Launch({"start", "--db=dev-file", "--log=file", "--log-file-output=json", "--http-enabled=true", "--hostname-strict=false"})
|
||||
|
|
@ -82,13 +83,13 @@ public class OptionsDistTest {
|
|||
cliResult.assertStarted();
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Order(6)
|
||||
@RawDistOnly(reason = "Raw is enough and we avoid issues with including custom conf file in the container")
|
||||
public void testExpressionsInConfigFile(KeycloakDistribution distribution) {
|
||||
distribution.setEnvVar("MY_LOG_LEVEL", "warn");
|
||||
CLIResult result = distribution.run(CONFIG_FILE_LONG_NAME + "=" + Paths.get("src/test/resources/OptionsDistTest/keycloak.conf").toAbsolutePath().normalize(), "start", "--db=dev-file", "--http-enabled=true", "--hostname-strict=false");
|
||||
public void testExpressionsInConfigFile(KeycloakRunner runner) {
|
||||
runner.setEnvVar("MY_LOG_LEVEL", "warn");
|
||||
CLIResult result = runner.run(CONFIG_FILE_LONG_NAME + "=" + Paths.get("src/test/resources/OptionsDistTest/keycloak.conf").toAbsolutePath().normalize(), "start", "--db=dev-file", "--http-enabled=true", "--hostname-strict=false");
|
||||
result.assertNoMessage("INFO [io.quarkus]");
|
||||
result.assertNoMessage("Listening on:");
|
||||
|
||||
|
|
@ -100,7 +101,7 @@ public class OptionsDistTest {
|
|||
|
||||
// Start-dev should be executed as last tests - build is done for development mode
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Order(7)
|
||||
@Launch({"start-dev", "--test=invalid"})
|
||||
|
|
@ -108,7 +109,7 @@ public class OptionsDistTest {
|
|||
result.assertError("Unknown option: '--test'");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Order(8)
|
||||
@Launch({"start-dev", "--log=console", "--log-file-output=json"})
|
||||
|
|
@ -117,7 +118,7 @@ public class OptionsDistTest {
|
|||
result.assertError("Possible solutions: --log-console-output, --log-level, --log, --log-console-level, --log-console-format, --log-console-async, --log-async");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Order(9)
|
||||
@Launch({"start-dev", "--log=file", "--log-file-output=json", "--log-console-color=true"})
|
||||
|
|
@ -127,7 +128,7 @@ public class OptionsDistTest {
|
|||
result.assertError("Possible solutions: --log, --log-file, --log-level, --log-file-level, --log-file-json-format, --log-file-format, --log-file-async");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Order(10)
|
||||
@Launch({"start-dev", "--cache-remote-host=localhost"})
|
||||
|
|
@ -135,7 +136,7 @@ public class OptionsDistTest {
|
|||
result.assertError( "cache-remote-host available only when feature 'multi-site' or 'clusterless' is set");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Order(11)
|
||||
@Launch({"start-dev", "--cache-remote-port=11222"})
|
||||
|
|
@ -143,7 +144,7 @@ public class OptionsDistTest {
|
|||
assertDisabledDueToMissingRemoteHost(result, "--cache-remote-port");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Order(12)
|
||||
@Launch({"start-dev", "--cache-remote-username=user"})
|
||||
|
|
@ -151,7 +152,7 @@ public class OptionsDistTest {
|
|||
assertDisabledDueToMissingRemoteHost(result, "--cache-remote-username");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Order(13)
|
||||
@Launch({"start-dev", "--cache-remote-password=pass"})
|
||||
|
|
@ -159,7 +160,7 @@ public class OptionsDistTest {
|
|||
assertDisabledDueToMissingRemoteHost(result, "--cache-remote-password");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Order(14)
|
||||
@Launch({"start-dev", "--cache-remote-tls-enabled=false"})
|
||||
|
|
@ -167,7 +168,7 @@ public class OptionsDistTest {
|
|||
assertDisabledDueToMissingRemoteHost(result, "--cache-remote-tls-enabled");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Order(15)
|
||||
@Launch({"start-dev", "--features=multi-site"})
|
||||
|
|
@ -175,7 +176,7 @@ public class OptionsDistTest {
|
|||
result.assertError("- cache-remote-host: Required when feature 'multi-site' or 'clusterless' is set.");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Order(16)
|
||||
@Launch({"start-dev", "--features=multi-site", "--cache-remote-host=localhost", "--cache-remote-username=user"})
|
||||
|
|
@ -183,7 +184,7 @@ public class OptionsDistTest {
|
|||
result.assertError("The option 'cache-remote-password' is required when 'cache-remote-username' is set.");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Order(17)
|
||||
@Launch({"start-dev", "--features=multi-site", "--cache-remote-host=localhost", "--cache-remote-password=secret"})
|
||||
|
|
|
|||
|
|
@ -19,11 +19,12 @@ package org.keycloak.it.cli.dist;
|
|||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.junit5.extension.TestProvider;
|
||||
import org.keycloak.it.junit5.extension.WithEnvVars;
|
||||
import org.keycloak.it.resource.realm.TestRealmResourceTestProvider;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
|
|
@ -40,7 +41,7 @@ import static io.restassured.RestAssured.given;
|
|||
import static io.restassured.RestAssured.when;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
@DistributionTest(keepAlive = true, enableTls = true)
|
||||
@DistributionTest(stopServer = Mode.MANUAL, enableTls = true)
|
||||
@WithEnvVars({"KC_BOOTSTRAP_ADMIN_USERNAME", "admin123", "KC_BOOTSTRAP_ADMIN_PASSWORD", "admin123"})
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
public class ProxyHostnameV2DistTest {
|
||||
|
|
@ -66,14 +67,14 @@ public class ProxyHostnameV2DistTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testTrustedProxiesWithoutProxyHeaders(KeycloakDistribution distribution) {
|
||||
CLIResult result = distribution.run("start-dev", "--proxy-trusted-addresses=1.0.0.0");
|
||||
void testTrustedProxiesWithoutProxyHeaders(KeycloakRunner runner) {
|
||||
CLIResult result = runner.run("start-dev", "--proxy-trusted-addresses=1.0.0.0");
|
||||
result.assertError("proxy-trusted-addresses available only when proxy-headers is set");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTrustedProxiesWithInvalidAddress(KeycloakDistribution distribution) {
|
||||
CLIResult result = distribution.run("start-dev", "--proxy-headers=xforwarded", "--proxy-trusted-addresses=1.0.0.0:8080");
|
||||
void testTrustedProxiesWithInvalidAddress(KeycloakRunner runner) {
|
||||
CLIResult result = runner.run("start-dev", "--proxy-headers=xforwarded", "--proxy-trusted-addresses=1.0.0.0:8080");
|
||||
result.assertError("1.0.0.0:8080 is not a valid IP address (IPv4 or IPv6) nor valid CIDR notation.");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import org.keycloak.it.junit5.extension.CLIResult;
|
|||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.WithEnvVars;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
|
|
@ -124,35 +124,35 @@ public class QuarkusPropertiesAutoBuildDistTest {
|
|||
cliResult.assertStarted();
|
||||
}
|
||||
|
||||
public static class EnableAdditionalConsoleHandler implements Consumer<KeycloakDistribution> {
|
||||
public static class EnableAdditionalConsoleHandler implements Consumer<RawKeycloakDistribution> {
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.setQuarkusProperty("quarkus.log.handler.console.\"console-2\".enable", "true");
|
||||
distribution.setQuarkusProperty("quarkus.log.handler.console.\"console-2\".format", "Keycloak is the best");
|
||||
distribution.setQuarkusProperty("quarkus.log.handlers", "console-2");
|
||||
}
|
||||
}
|
||||
|
||||
public static class DisableAdditionalConsoleHandler implements Consumer<KeycloakDistribution> {
|
||||
public static class DisableAdditionalConsoleHandler implements Consumer<RawKeycloakDistribution> {
|
||||
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.setQuarkusProperty("quarkus.log.handler.console.\"console-2\".enable", "false");
|
||||
}
|
||||
}
|
||||
|
||||
public static class AddAdditionalDatasource implements Consumer<KeycloakDistribution> {
|
||||
public static class AddAdditionalDatasource implements Consumer<RawKeycloakDistribution> {
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.setProperty("db-kind-user-store", "dev-mem");
|
||||
distribution.setProperty("db-username-user-store", "sa");
|
||||
distribution.setProperty("db-url-full-user-store", "jdbc:h2:mem:user-store;DB_CLOSE_DELAY=-1");
|
||||
}
|
||||
}
|
||||
|
||||
public static class AddAdditionalDatasource2 implements Consumer<KeycloakDistribution> {
|
||||
public static class AddAdditionalDatasource2 implements Consumer<RawKeycloakDistribution> {
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.setProperty("db-kind-user-store2", "dev-mem");
|
||||
distribution.setProperty("transaction-xa-enabled-user-store2", "true");
|
||||
distribution.setProperty("db-username-user-store2", "sa");
|
||||
|
|
@ -160,9 +160,9 @@ public class QuarkusPropertiesAutoBuildDistTest {
|
|||
}
|
||||
}
|
||||
|
||||
public static class AddNonXADatasource implements Consumer<KeycloakDistribution> {
|
||||
public static class AddNonXADatasource implements Consumer<RawKeycloakDistribution> {
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.setProperty("db-kind-user-store3", "dev-mem");
|
||||
distribution.setProperty("transaction-xa-enabled-user-store3", "false");
|
||||
distribution.setProperty("db-username-user-store3", "sa");
|
||||
|
|
@ -170,24 +170,23 @@ public class QuarkusPropertiesAutoBuildDistTest {
|
|||
}
|
||||
}
|
||||
|
||||
public static class ChangeAdditionalDatasourceUsername implements Consumer<KeycloakDistribution> {
|
||||
public static class ChangeAdditionalDatasourceUsername implements Consumer<RawKeycloakDistribution> {
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.setProperty("db-username-user-store", "foo");
|
||||
}
|
||||
}
|
||||
|
||||
public static class ChangeAdditionalDatasourceDbKind implements Consumer<KeycloakDistribution> {
|
||||
public static class ChangeAdditionalDatasourceDbKind implements Consumer<RawKeycloakDistribution> {
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.setProperty("db-kind-user-store", "dev-mem");
|
||||
}
|
||||
}
|
||||
|
||||
public static class SetDatabaseKind implements Consumer<KeycloakDistribution> {
|
||||
public static class SetDatabaseKind implements Consumer<RawKeycloakDistribution> {
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
distribution.setManualStop(true);
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.setQuarkusProperty("quarkus.datasource.db-kind", "postgres");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,11 +24,10 @@ import java.util.function.Consumer;
|
|||
import org.keycloak.it.junit5.extension.BeforeStartDistribution;
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.DryRun;
|
||||
import org.keycloak.it.junit5.extension.KeepServerAlive;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.WithEnvVars;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.junit5.extension.StopServer;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import io.restassured.RestAssured;
|
||||
|
|
@ -47,7 +46,6 @@ import static org.hamcrest.Matchers.containsString;
|
|||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@DistributionTest(defaultOptions = "--db=dev-file")
|
||||
@WithEnvVars({"KC_CACHE", "local"}) // avoid flakey port conflicts
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
@Tag(DistributionTest.WIN)
|
||||
@TestMethodOrder(OrderAnnotation.class)
|
||||
|
|
@ -64,7 +62,7 @@ public class QuarkusPropertiesDistTest {
|
|||
cliResult.assertMessage("Keycloak is the best");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@BeforeStartDistribution(UpdateConsoleHandlerFromKeycloakConf.class)
|
||||
@Launch({"build"})
|
||||
|
|
@ -74,7 +72,7 @@ public class QuarkusPropertiesDistTest {
|
|||
cliResult.assertBuild();
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@BeforeStartDistribution(UpdateConsoleHandlerFromQuarkusProps.class)
|
||||
@Launch({"start", "--http-enabled=true", "--hostname-strict=false"})
|
||||
|
|
@ -95,7 +93,7 @@ public class QuarkusPropertiesDistTest {
|
|||
|
||||
@Test
|
||||
@BeforeStartDistribution(UpdateHibernateMetricsFromQuarkusProps.class)
|
||||
@KeepServerAlive
|
||||
@StopServer(Mode.MANUAL)
|
||||
@Launch({ "start", "--http-enabled=true", "--hostname-strict=false", "--metrics-enabled=true"})
|
||||
@Order(8)
|
||||
void testUnknownQuarkusBuildTimePropertyApplied(CLIResult cliResult) {
|
||||
|
|
@ -170,45 +168,45 @@ public class QuarkusPropertiesDistTest {
|
|||
cliResult.assertMessage("ERROR: Failed to load 'https-*' material: NoSuchFileException C:");
|
||||
}
|
||||
|
||||
public static class AddConsoleHandlerFromQuarkusProps implements Consumer<KeycloakDistribution> {
|
||||
public static class AddConsoleHandlerFromQuarkusProps implements Consumer<RawKeycloakDistribution> {
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.setQuarkusProperty(QUARKUS_RUNTIME_CONSOLE_HANDLER_ENABLED_KEY, "true");
|
||||
distribution.setQuarkusProperty("quarkus.log.handler.console.\"console-2\".format", "Keycloak is the best");
|
||||
distribution.setQuarkusProperty("quarkus.log.handlers", "console-2");
|
||||
}
|
||||
}
|
||||
|
||||
public static class UpdateConsoleHandlerFromKeycloakConf implements Consumer<KeycloakDistribution> {
|
||||
public static class UpdateConsoleHandlerFromKeycloakConf implements Consumer<RawKeycloakDistribution> {
|
||||
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.deleteQuarkusProperties();
|
||||
distribution.setProperty(QUARKUS_RUNTIME_CONSOLE_HANDLER_ENABLED_KEY, "false");
|
||||
}
|
||||
}
|
||||
|
||||
public static class UpdateConsoleHandlerFromQuarkusProps implements Consumer<KeycloakDistribution> {
|
||||
public static class UpdateConsoleHandlerFromQuarkusProps implements Consumer<RawKeycloakDistribution> {
|
||||
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.deleteQuarkusProperties();
|
||||
distribution.setQuarkusProperty(QUARKUS_RUNTIME_CONSOLE_HANDLER_ENABLED_KEY, "true");
|
||||
}
|
||||
}
|
||||
|
||||
public static class UpdateHibernateMetricsFromQuarkusProps implements Consumer<KeycloakDistribution> {
|
||||
public static class UpdateHibernateMetricsFromQuarkusProps implements Consumer<RawKeycloakDistribution> {
|
||||
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.deleteQuarkusProperties();
|
||||
distribution.setQuarkusProperty(QUARKUS_BUILDTIME_HIBERNATE_METRICS_KEY, "true");
|
||||
}
|
||||
}
|
||||
|
||||
public static class CopyKeystoreToConf implements Consumer<KeycloakDistribution> {
|
||||
public static class CopyKeystoreToConf implements Consumer<RawKeycloakDistribution> {
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.copyOrReplaceFileFromClasspath("/keystore", Path.of("conf", "keystore"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
package org.keycloak.it.cli.dist;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.DryRun;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.StopServer;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.junit5.extension.WithEnvVars;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.quarkus.runtime.cli.command.ShowConfig;
|
||||
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers;
|
||||
|
||||
|
|
@ -26,23 +26,23 @@ import static org.hamcrest.Matchers.not;
|
|||
@DistributionTest
|
||||
public class ShowConfigCommandDistTest {
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
void testShowConfigPicksUpRightConfigDependingOnCurrentMode(KeycloakDistribution distribution) {
|
||||
CLIResult initialResult = distribution.run("show-config");
|
||||
void testShowConfigPicksUpRightConfigDependingOnCurrentMode(KeycloakRunner runner) {
|
||||
CLIResult initialResult = runner.run("show-config");
|
||||
initialResult.assertMessage("Current Mode: production");
|
||||
initialResult.assertNoMessage("kc.db = dev-file");
|
||||
|
||||
distribution.run("start-dev");
|
||||
runner.run("start-dev");
|
||||
|
||||
CLIResult devModeResult = distribution.run("show-config");
|
||||
CLIResult devModeResult = runner.run("show-config");
|
||||
devModeResult.assertMessage("Current Mode: development");
|
||||
devModeResult.assertMessage("kc.db = dev-file");
|
||||
|
||||
distribution.run("build", "--db=dev-file");
|
||||
runner.run("build", "--db=dev-file");
|
||||
|
||||
CLIResult resetResult = distribution.run("show-config");
|
||||
CLIResult resetResult = runner.run("show-config");
|
||||
resetResult.assertMessage("Current Mode: production");
|
||||
resetResult.assertMessage("kc.db = dev-file");
|
||||
}
|
||||
|
|
@ -65,8 +65,8 @@ public class ShowConfigCommandDistTest {
|
|||
|
||||
@Test
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
void testShowConfigCommandHidesCredentialsInProfiles(KeycloakDistribution distribution) {
|
||||
CLIResult result = distribution.run(String.format("%s=%s", CONFIG_FILE_LONG_NAME, Paths.get("src/test/resources/ShowConfigCommandTest/keycloak.conf").toAbsolutePath().normalize()), ShowConfig.NAME, "all");
|
||||
void testShowConfigCommandHidesCredentialsInProfiles(KeycloakRunner runner) {
|
||||
CLIResult result = runner.run(String.format("%s=%s", CONFIG_FILE_LONG_NAME, Paths.get("src/test/resources/ShowConfigCommandTest/keycloak.conf").toAbsolutePath().normalize()), ShowConfig.NAME, "all");
|
||||
String output = result.getOutput();
|
||||
Assertions.assertFalse(output.contains("testpw1"));
|
||||
Assertions.assertFalse(output.contains("testpw2"));
|
||||
|
|
@ -76,9 +76,9 @@ public class ShowConfigCommandDistTest {
|
|||
|
||||
@Test
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
void testSmallRyeKeyStoreConfigSource(KeycloakDistribution distribution) {
|
||||
void testSmallRyeKeyStoreConfigSource(KeycloakRunner runner) {
|
||||
// keystore is shared with QuarkusPropertiesDistTest#testSmallRyeKeyStoreConfigSource
|
||||
CLIResult result = distribution.run(
|
||||
CLIResult result = runner.run(
|
||||
String.format("%s=%s", CONFIG_FILE_LONG_NAME, Paths.get("src/test/resources/ShowConfigCommandTest/keycloak-keystore.conf").toAbsolutePath().normalize()),
|
||||
"--config-keystore=" + Paths.get("src/test/resources/keystore").toAbsolutePath().normalize(),
|
||||
ShowConfig.NAME, "all");
|
||||
|
|
@ -104,14 +104,14 @@ public class ShowConfigCommandDistTest {
|
|||
|
||||
@Test
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
void testConfigSourceNames(KeycloakDistribution distribution) {
|
||||
CLIResult result = distribution.run("build");
|
||||
void testConfigSourceNames(KeycloakRunner runner) {
|
||||
CLIResult result = runner.run("build");
|
||||
result.assertBuild();
|
||||
|
||||
distribution.setEnvVar("KC_LOG", "file");
|
||||
distribution.copyOrReplaceFile(Paths.get("src/test/resources/ShowConfigCommandTest/quarkus.properties"), Path.of("conf", "quarkus.properties"));
|
||||
runner.setEnvVar("KC_LOG", "file");
|
||||
runner.getDistribution().copyConfigFile(Paths.get("src/test/resources/ShowConfigCommandTest/quarkus.properties"));
|
||||
|
||||
result = distribution.run(
|
||||
result = runner.run(
|
||||
String.format("%s=%s", CONFIG_FILE_LONG_NAME, Paths.get("src/test/resources/ShowConfigCommandTest/keycloak-keystore.conf").toAbsolutePath().normalize()),
|
||||
"--config-keystore=" + Paths.get("src/test/resources/keystore").toAbsolutePath().normalize(),
|
||||
ShowConfig.NAME, "all", "--db=dev-file");
|
||||
|
|
|
|||
|
|
@ -19,8 +19,10 @@ package org.keycloak.it.cli.dist;
|
|||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.DryRun;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.StopServer;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.junit5.extension.TestProvider;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
|
||||
|
|
@ -40,7 +42,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
public class StartAutoBuildDistTest {
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "--verbose", "start", "--db=dev-file", "--http-enabled=true", "--hostname-strict=false" })
|
||||
@Order(1)
|
||||
|
|
@ -54,7 +56,7 @@ public class StartAutoBuildDistTest {
|
|||
assertTrue(cliResult.getErrorOutput().isBlank());
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start", "--db=dev-file", "--http-enabled=true", "--hostname-strict=false" })
|
||||
@Order(2)
|
||||
|
|
@ -63,7 +65,7 @@ public class StartAutoBuildDistTest {
|
|||
assertTrue(cliResult.getErrorOutput().isBlank());
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start", "--db=dev-mem", "--http-enabled=true", "--hostname-strict=false" })
|
||||
@Order(3)
|
||||
|
|
@ -72,7 +74,7 @@ public class StartAutoBuildDistTest {
|
|||
assertTrue(cliResult.getErrorOutput().isBlank());
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start", "--db=dev-mem", "--http-enabled=true", "--hostname-strict=false" })
|
||||
@Order(4)
|
||||
|
|
@ -81,7 +83,7 @@ public class StartAutoBuildDistTest {
|
|||
assertTrue(cliResult.getErrorOutput().isBlank());
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "build", "--db=postgres" })
|
||||
@Order(5)
|
||||
|
|
@ -89,7 +91,7 @@ public class StartAutoBuildDistTest {
|
|||
cliResult.assertBuild();
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start", "--db=dev-file", "--http-enabled=true", "--hostname-strict=false" })
|
||||
@Order(6)
|
||||
|
|
@ -98,7 +100,7 @@ public class StartAutoBuildDistTest {
|
|||
assertTrue(cliResult.getErrorOutput().isBlank());
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start", "--db=postgres", "--http-enabled=true", "--hostname-strict=false" })
|
||||
@Order(7)
|
||||
|
|
@ -106,7 +108,7 @@ public class StartAutoBuildDistTest {
|
|||
cliResult.assertBuild();
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start", "--db=dev-file", "--http-enabled=true", "--hostname-strict=false", OPTIMIZED_BUILD_OPTION_LONG})
|
||||
@Order(8)
|
||||
|
|
@ -114,7 +116,7 @@ public class StartAutoBuildDistTest {
|
|||
cliResult.assertNoBuild();
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start-dev" })
|
||||
@Order(8)
|
||||
|
|
@ -123,7 +125,7 @@ public class StartAutoBuildDistTest {
|
|||
cliResult.assertStartedDevMode();
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start-dev" })
|
||||
@Order(9)
|
||||
|
|
@ -133,46 +135,46 @@ public class StartAutoBuildDistTest {
|
|||
cliResult.assertStartedDevMode();
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@TestProvider(CustomUserProvider.class)
|
||||
@Order(10)
|
||||
void testSpiAutoBuild(KeycloakDistribution dist) {
|
||||
CLIResult cliResult = dist.run("start-dev", "--spi-user-provider=custom_jpa", "--spi-user-jpa-enabled=false");
|
||||
void testSpiAutoBuild(KeycloakRunner runner) {
|
||||
CLIResult cliResult = runner.run("start-dev", "--spi-user-provider=custom_jpa", "--spi-user-jpa-enabled=false");
|
||||
cliResult.assertMessage("Updating the configuration");
|
||||
cliResult.assertStartedDevMode();
|
||||
dist.stop();
|
||||
runner.stop();
|
||||
|
||||
// we should persist the spi provider and know not to rebuild
|
||||
cliResult = dist.run("start-dev", "--spi-user-provider=custom_jpa", "--spi-user-jpa-enabled=false");
|
||||
cliResult = runner.run("start-dev", "--spi-user-provider=custom_jpa", "--spi-user-jpa-enabled=false");
|
||||
cliResult.assertNoMessage("Updating the configuration");
|
||||
cliResult.assertStartedDevMode();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(11)
|
||||
void testLogLevelNotPeristed(KeycloakDistribution dist) {
|
||||
CLIResult cliResult = dist.run("start", "--db=dev-file", "--log-level=org.hibernate.SQL:debug", "--http-enabled=true", "--hostname-strict=false");
|
||||
void testLogLevelNotPeristed(KeycloakRunner runner) {
|
||||
CLIResult cliResult = runner.run("start", "--db=dev-file", "--log-level=org.hibernate.SQL:debug", "--http-enabled=true", "--hostname-strict=false");
|
||||
cliResult.assertMessage("DEBUG [org.hibernate.SQL]");
|
||||
cliResult.assertStarted();
|
||||
dist.stop();
|
||||
runner.stop();
|
||||
|
||||
// logging runtime defaults should not be used
|
||||
cliResult = dist.run("start", "--db=dev-file", "--http-enabled=true", "--hostname-strict=false");
|
||||
cliResult = runner.run("start", "--db=dev-file", "--http-enabled=true", "--hostname-strict=false");
|
||||
cliResult.assertNoMessage("DEBUG [org.hibernate.SQL]");
|
||||
cliResult.assertStarted();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(12)
|
||||
void testLogLevelWildcardNotPeristed(KeycloakDistribution dist) {
|
||||
CLIResult cliResult = dist.run("start-dev", "--log-level-org.hibernate.SQL=debug");
|
||||
void testLogLevelWildcardNotPeristed(KeycloakRunner runner) {
|
||||
CLIResult cliResult = runner.run("start-dev", "--log-level-org.hibernate.SQL=debug");
|
||||
cliResult.assertMessage("DEBUG [org.hibernate.SQL]");
|
||||
cliResult.assertStartedDevMode();
|
||||
dist.stop();
|
||||
runner.stop();
|
||||
|
||||
// logging runtime defaults should not be used
|
||||
cliResult = dist.run("start-dev");
|
||||
cliResult = runner.run("start-dev");
|
||||
cliResult.assertNoMessage("DEBUG [org.hibernate.SQL]");
|
||||
cliResult.assertStartedDevMode();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,10 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.DryRun;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.StopServer;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.junit5.extension.TestProvider;
|
||||
import org.keycloak.it.junit5.extension.WithEnvVars;
|
||||
import org.keycloak.it.resource.realm.TestRealmResourceTestProvider;
|
||||
|
|
@ -32,7 +34,6 @@ import org.keycloak.it.utils.RawKeycloakDistribution;
|
|||
|
||||
import io.quarkus.test.common.QuarkusTestResource;
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
|
|
@ -47,14 +48,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@WithEnvVars({"KC_CACHE", "local"}) // avoid flakey port conflicts
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
@DistributionTest
|
||||
@Tag(DistributionTest.WIN)
|
||||
@QuarkusTestResource(RawDistributionLifecycleManager.class)
|
||||
public class StartCommandDistTest {
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start", "--db=dev-file", "--hostname-strict=false" })
|
||||
void failNoTls(CLIResult cliResult) {
|
||||
|
|
@ -62,7 +62,7 @@ public class StartCommandDistTest {
|
|||
() -> "The Output:\n" + cliResult.getErrorOutput() + "doesn't contains the expected string.");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start", "--db=dev-file", "--spi-events-listener-jboss-logging-success-level" })
|
||||
void failSpiArgMissingValue(CLIResult cliResult) {
|
||||
|
|
@ -70,7 +70,7 @@ public class StartCommandDistTest {
|
|||
() -> "The Output:\n" + cliResult.getErrorOutput() + "doesn't contains the expected string.");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "build", "--db=dev-file", "--spi-events-listener-jboss-logging-success-level=debug" })
|
||||
void warnSpiRuntimeAtBuildtime(CLIResult cliResult) {
|
||||
|
|
@ -78,47 +78,47 @@ public class StartCommandDistTest {
|
|||
() -> "The Output:\n" + cliResult.getOutput() + "doesn't contains the expected string.");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
void errorSpiBuildtimeAtRuntime(KeycloakDistribution dist) {
|
||||
CLIResult cliResult = dist.run("build", "--db=dev-file");
|
||||
void errorSpiBuildtimeAtRuntime(KeycloakRunner runner) {
|
||||
CLIResult cliResult = runner.run("build", "--db=dev-file");
|
||||
cliResult.assertBuild();
|
||||
|
||||
cliResult = dist.run("start", "--optimized", "--http-enabled=true", "--hostname-strict=false", "--spi-events-listener--jboss-logging--enabled=false");
|
||||
cliResult = runner.run("start", "--optimized", "--http-enabled=true", "--hostname-strict=false", "--spi-events-listener--jboss-logging--enabled=false");
|
||||
cliResult.assertError("The following build time options have values that differ from what is persisted - the new values will NOT be used until another build is run: kc.spi-events-listener--jboss-logging--enabled");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@WithEnvVars({"KC_SPI_EVENTS_LISTENER__JBOSS_LOGGING__ENABLED", "false"})
|
||||
@Test
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
void noErrorSpiBuildtimeNotChanged(KeycloakDistribution dist) {
|
||||
CLIResult cliResult = dist.run("build", "--db=dev-file");
|
||||
void noErrorSpiBuildtimeNotChanged(KeycloakRunner runner) {
|
||||
CLIResult cliResult = runner.run("build", "--db=dev-file");
|
||||
cliResult.assertBuild();
|
||||
|
||||
cliResult = dist.run("start", "--optimized", "--http-enabled=true", "--hostname-strict=false");
|
||||
cliResult = runner.run("start", "--optimized", "--http-enabled=true", "--hostname-strict=false");
|
||||
cliResult.assertNoError("The following build time options");
|
||||
}
|
||||
|
||||
@Test
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
void terminateStartOptimized(KeycloakDistribution dist) {
|
||||
CLIResult cliResult = dist.run("build", "--db=dev-file");
|
||||
void terminateStartOptimized(KeycloakRunner runner) {
|
||||
CLIResult cliResult = runner.run("build", "--db=dev-file");
|
||||
cliResult.assertBuild();
|
||||
|
||||
dist.setManualStop(true);
|
||||
cliResult = dist.run("start", "--optimized", "--http-enabled=true", "--hostname-strict=false");
|
||||
runner.setStopServer(Mode.MANUAL);
|
||||
cliResult = runner.run("start", "--optimized", "--http-enabled=true", "--hostname-strict=false");
|
||||
cliResult.assertStarted();
|
||||
|
||||
// if the child java process does not clean up, then subsequent start will fail
|
||||
dist.stop();
|
||||
runner.stop();
|
||||
|
||||
cliResult = dist.run("start", "--optimized", "--http-enabled=true", "--hostname-strict=false");
|
||||
cliResult = runner.run("start", "--optimized", "--http-enabled=true", "--hostname-strict=false");
|
||||
cliResult.assertStarted();
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "--profile=dev", "start", "--db=dev-file" })
|
||||
void failUsingDevProfile(CLIResult cliResult) {
|
||||
|
|
@ -132,7 +132,7 @@ public class StartCommandDistTest {
|
|||
cliResult.assertStarted();
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "--profile=dev", "start", "--http-enabled=true", "--hostname-strict=false" })
|
||||
void failIfAutoBuildUsingDevProfile(CLIResult cliResult) {
|
||||
|
|
@ -140,7 +140,7 @@ public class StartCommandDistTest {
|
|||
assertEquals(4, cliResult.getErrorStream().size());
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@WithEnvVars({"KC_HTTP_ENABLED", "true", "KC_HOSTNAME_STRICT", "false"})
|
||||
@Test
|
||||
@Launch({ "start", "--optimized" })
|
||||
|
|
@ -149,7 +149,7 @@ public class StartCommandDistTest {
|
|||
cliResult.assertError("The '--optimized' flag was used for first ever server start.");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start", "--optimized", "--http-enabled=true", "--hostname-strict=false" })
|
||||
@Order(2)
|
||||
|
|
@ -164,7 +164,7 @@ public class StartCommandDistTest {
|
|||
() -> "The Output:\n" + cliResult.getOutput() + "doesn't contains the expected string.");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start", "--db=dev-file", "--http-enabled=true", "--hostname-strict=false", "--metrics-enabled=true" })
|
||||
void testStartUsingAutoBuild(CLIResult cliResult) {
|
||||
|
|
@ -178,14 +178,14 @@ public class StartCommandDistTest {
|
|||
assertTrue(cliResult.getErrorOutput().isBlank(), cliResult.getErrorOutput());
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start", "--db=dev-file", "--http-enabled=true", "--cache-remote-host=localhost", "--hostname-strict=false", "--cache-remote-tls-enabled=false", "--transaction-xa-enabled=true" })
|
||||
void testStartNoWarningOnDisabledRuntimeOption(CLIResult cliResult) {
|
||||
cliResult.assertNoMessage("cache-remote-tls-enabled: Available only when remote host is set");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@WithEnvVars({"KC_LOG", "invalid"})
|
||||
@Launch({ "start", "--db=dev-file", "--http-enabled=false", "--hostname-strict=false" })
|
||||
|
|
@ -193,13 +193,13 @@ public class StartCommandDistTest {
|
|||
cliResult.assertError("Invalid value for option 'KC_LOG': invalid. Expected values are: console, file, syslog");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
void testWarningWhenOverridingBuildOptionsDuringStart(KeycloakDistribution dist) {
|
||||
CLIResult cliResult = dist.run("build", "--db=postgres", "--features=preview");
|
||||
void testWarningWhenOverridingBuildOptionsDuringStart(KeycloakRunner runner) {
|
||||
CLIResult cliResult = runner.run("build", "--db=postgres", "--features=preview");
|
||||
cliResult.assertBuild();
|
||||
cliResult = dist.run("start", "--db=dev-file", "--hostname=localhost", "--http-enabled=true");
|
||||
cliResult = runner.run("start", "--db=dev-file", "--hostname=localhost", "--http-enabled=true");
|
||||
cliResult.assertMessage("The previous optimized build will be overridden with the following build options:");
|
||||
cliResult.assertMessage("- db=postgres > db=dev-file"); // back to the default value
|
||||
cliResult.assertMessage("- features=preview > features=<unset>"); // no default value, the <unset> is shown
|
||||
|
|
@ -207,51 +207,51 @@ public class StartCommandDistTest {
|
|||
assertTrue(cliResult.getErrorOutput().isBlank());
|
||||
// should not show warning if the re-augmentation did not happen through the build command
|
||||
// an optimized server image should ideally be created by running a build
|
||||
cliResult = dist.run("start", "--db=dev-mem", "--hostname=localhost", "--http-enabled=true");
|
||||
cliResult = runner.run("start", "--db=dev-mem", "--hostname=localhost", "--http-enabled=true");
|
||||
cliResult.assertNoMessage("The previous optimized build will be overridden with the following build options:");
|
||||
assertTrue(cliResult.getErrorOutput().isBlank());
|
||||
dist.run("build", "--db=postgres");
|
||||
cliResult = dist.run("start", "--db=dev-file", "--hostname=localhost", "--http-enabled=true");
|
||||
runner.run("build", "--db=postgres");
|
||||
cliResult = runner.run("start", "--db=dev-file", "--hostname=localhost", "--http-enabled=true");
|
||||
cliResult.assertMessage("- db=postgres > db=dev-file");
|
||||
cliResult.assertNoMessage("- features=preview > features=<unset>");
|
||||
assertTrue(cliResult.getErrorOutput().isBlank());
|
||||
dist.run("build", "--db=postgres");
|
||||
cliResult = dist.run("start", "--db=dev-mem", "--hostname=localhost", "--http-enabled=true");
|
||||
runner.run("build", "--db=postgres");
|
||||
cliResult = runner.run("start", "--db=dev-mem", "--hostname=localhost", "--http-enabled=true");
|
||||
cliResult.assertMessage("- db=postgres > db=dev-mem"); // option overridden during the start
|
||||
assertTrue(cliResult.getErrorOutput().isBlank());
|
||||
dist.run("build", "--db=dev-mem");
|
||||
cliResult = dist.run("start", "--db=dev-mem", "--hostname=localhost", "--http-enabled=true");
|
||||
runner.run("build", "--db=dev-mem");
|
||||
cliResult = runner.run("start", "--db=dev-mem", "--hostname=localhost", "--http-enabled=true");
|
||||
cliResult.assertNoMessage("- db=postgres > db=postgres"); // option did not change not need to show
|
||||
assertTrue(cliResult.getErrorOutput().isBlank());
|
||||
dist.run("build", "--db=dev-mem");
|
||||
cliResult = dist.run("start", "--db=dev-mem", "--cache=local", "--hostname=localhost", "--http-enabled=true");
|
||||
runner.run("build", "--db=dev-mem");
|
||||
cliResult = runner.run("start", "--db=dev-mem", "--cache=local", "--hostname=localhost", "--http-enabled=true");
|
||||
cliResult.assertNoMessage("The previous optimized build will be overridden with the following build options:"); // no message, same values provided during auto-build
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
void testStartAfterStartDev(KeycloakDistribution dist) {
|
||||
CLIResult cliResult = dist.run("start-dev");
|
||||
void testStartAfterStartDev(KeycloakRunner runner) {
|
||||
CLIResult cliResult = runner.run("start-dev");
|
||||
cliResult.assertStartedDevMode();
|
||||
|
||||
cliResult = dist.run("start", "--db=dev-file", "--http-enabled", "true", "--hostname-strict", "false");
|
||||
cliResult = runner.run("start", "--db=dev-file", "--http-enabled", "true", "--hostname-strict", "false");
|
||||
cliResult.assertNotDevMode();
|
||||
assertTrue(cliResult.getErrorOutput().isBlank());
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
void testErrorWhenOverridingNonCliBuildOptionsDuringStart(KeycloakDistribution dist) {
|
||||
CLIResult cliResult = dist.run("build", "--db=dev-file", "--features=preview");
|
||||
void testErrorWhenOverridingNonCliBuildOptionsDuringStart(KeycloakRunner runner) {
|
||||
CLIResult cliResult = runner.run("build", "--db=dev-file", "--features=preview");
|
||||
cliResult.assertBuild();
|
||||
dist.setEnvVar("KC_DB", "postgres");
|
||||
cliResult = dist.run("start", "--optimized", "--hostname=localhost", "--http-enabled=true");
|
||||
runner.setEnvVar("KC_DB", "postgres");
|
||||
cliResult = runner.run("start", "--optimized", "--hostname=localhost", "--http-enabled=true");
|
||||
cliResult.assertError("The following build time options have values that differ from what is persisted - the new values will NOT be used until another build is run: kc.db");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({CONFIG_FILE_LONG_NAME + "=src/test/resources/non-existing.conf", "start", "--db=dev-file"})
|
||||
void testInvalidConfigFileOption(CLIResult cliResult) {
|
||||
|
|
@ -259,7 +259,7 @@ public class StartCommandDistTest {
|
|||
cliResult.assertError(String.format("Try '%s --help' for more information on the available options.", KeycloakDistribution.SCRIPT_CMD));
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({CONFIG_FILE_LONG_NAME + "=src/test/resources/keycloak.properties", "start", "--db=dev-file"})
|
||||
void testConfigFileWithWrongExtension(CLIResult cliResult) {
|
||||
|
|
@ -268,20 +268,20 @@ public class StartCommandDistTest {
|
|||
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
@Test
|
||||
void testRuntimeValuesAreNotCaptured(KeycloakDistribution dist) {
|
||||
void testRuntimeValuesAreNotCaptured(KeycloakRunner runner) {
|
||||
// confirm that the invalid value prevents startup - if this passes, then we need to use a different
|
||||
// spi provider
|
||||
CLIResult cliResult = dist.run("start", "--db=dev-file", "--spi-events-listener-jboss-logging-success-level=invalid", "--http-enabled", "true", "--hostname-strict", "false");
|
||||
CLIResult cliResult = runner.run("start", "--db=dev-file", "--spi-events-listener-jboss-logging-success-level=invalid", "--http-enabled", "true", "--hostname-strict", "false");
|
||||
cliResult.assertError("Failed to start quarkus");
|
||||
|
||||
// if there was no auto-build use an explicit build to potentially capture the runtime default
|
||||
if (!cliResult.getOutput().contains("Server configuration updated and persisted")) {
|
||||
cliResult = dist.run("build", "--db=dev-file", "--spi-events-listener-jboss-logging-success-level=invalid");
|
||||
cliResult = runner.run("build", "--db=dev-file", "--spi-events-listener-jboss-logging-success-level=invalid");
|
||||
cliResult.assertBuild();
|
||||
}
|
||||
|
||||
// the invalid value should not be the default
|
||||
cliResult = dist.run("start", "--db=dev-file", "--http-enabled", "true", "--hostname-strict", "false");
|
||||
cliResult = runner.run("start", "--db=dev-file", "--http-enabled", "true", "--hostname-strict", "false");
|
||||
cliResult.assertNoBuild();
|
||||
cliResult.assertStarted();
|
||||
}
|
||||
|
|
@ -289,15 +289,15 @@ public class StartCommandDistTest {
|
|||
@RawDistOnly(reason = "Containers are immutable")
|
||||
@Test
|
||||
@TestProvider(TestRealmResourceTestProvider.class)
|
||||
void testAsyncBootstrapFails(KeycloakDistribution dist) {
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
dist.setManualStop(true);
|
||||
CLIResult result = dist.run("start", "--server-async-bootstrap=true", "--hostname-strict=false", "--db=dev-file", "--http-enabled=true", "--spi-realm-restapi-extension--test-resources--fail=true");
|
||||
Awaitility.await().atMost(2, TimeUnit.MINUTES).until(() -> !rawDist.isRunning());
|
||||
dist.stop();
|
||||
void testAsyncBootstrapFails(KeycloakRunner runner) {
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
runner.setStopServer(Mode.MANUAL);
|
||||
CLIResult result = runner.run("start", "--server-async-bootstrap=true", "--hostname-strict=false", "--db=dev-file", "--http-enabled=true", "--spi-realm-restapi-extension--test-resources--fail=true");
|
||||
rawDist.waitFor(false, TimeUnit.MINUTES.toMillis(2));
|
||||
runner.stop();
|
||||
result.assertMessage("Failed to start server");
|
||||
result.assertMessage("I've failed");
|
||||
assertEquals(1, dist.getExitCode());
|
||||
assertEquals(1, rawDist.getExitCode());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ import java.nio.file.Paths;
|
|||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.DryRun;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
import org.keycloak.it.junit5.extension.StopServer;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
|
|
@ -42,7 +42,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
@Tag(DistributionTest.WIN)
|
||||
public class StartDevCommandDistTest {
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start-dev" })
|
||||
void testDevModeWarning(CLIResult cliResult) {
|
||||
|
|
@ -53,7 +53,7 @@ public class StartDevCommandDistTest {
|
|||
assertFalse(out.contains("0.0.0.0") || out.contains("all addresses"));
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start-dev", "--db=dev-mem" })
|
||||
void testBuildPropertyAvailable(CLIResult cliResult) {
|
||||
|
|
@ -70,7 +70,7 @@ public class StartDevCommandDistTest {
|
|||
cliResult.assertNoMessage("Build time property cannot");
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "build", "--debug", "--db=dev-file" })
|
||||
void testBuildMustNotRunTwoJVMs(CLIResult cliResult) {
|
||||
|
|
@ -78,7 +78,7 @@ public class StartDevCommandDistTest {
|
|||
cliResult.assertBuild();
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
@Launch({ "start-dev", "--verbose" })
|
||||
void testVerboseAfterCommand(CLIResult cliResult) {
|
||||
|
|
@ -86,8 +86,8 @@ public class StartDevCommandDistTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testConfigKeystoreAbsolutePath(KeycloakDistribution dist) {
|
||||
CLIResult cliResult = dist.run("start-dev", "--config-keystore=" + Paths.get("src/test/resources/keystore").toAbsolutePath().normalize(),
|
||||
void testConfigKeystoreAbsolutePath(KeycloakRunner runner) {
|
||||
CLIResult cliResult = runner.run("start-dev", "--config-keystore=" + Paths.get("src/test/resources/keystore").toAbsolutePath().normalize(),
|
||||
"--config-keystore-password=secret");
|
||||
|
||||
// keytool -importpass -alias kc.log-level -keystore keystore -storepass secret -storetype PKCS12 -v (with "org.keycloak.timer:debug" as the stored password)
|
||||
|
|
@ -99,17 +99,16 @@ public class StartDevCommandDistTest {
|
|||
cliResult.assertStartedDevMode();
|
||||
}
|
||||
|
||||
@DryRun
|
||||
@StopServer(Mode.BEFORE_QUARKUS)
|
||||
@Test
|
||||
void testStartDevThenImportRebuild(KeycloakDistribution dist) throws Exception {
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
CLIResult result = rawDist.run("start-dev");
|
||||
void testStartDevThenImportRebuild(KeycloakRunner runner) throws Exception {
|
||||
CLIResult result = runner.run("start-dev");
|
||||
assertTrue(result.getErrorOutput().isEmpty(), result.getErrorOutput());
|
||||
|
||||
File target = new File("./target");
|
||||
|
||||
// feature change should trigger a build
|
||||
result = rawDist.run("--profile=dev", "export", "--features=docker", "--dir=" + target.getAbsolutePath());
|
||||
result = runner.run("--profile=dev", "export", "--features=docker", "--dir=" + target.getAbsolutePath());
|
||||
result.assertMessage("Updating the configuration and installing your custom providers, if any. Please wait.");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ package org.keycloak.it.cli.dist;
|
|||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.SkipRealmBootstrap;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import io.quarkus.test.junit.main.LaunchResult;
|
||||
|
|
@ -30,9 +30,8 @@ import org.junit.jupiter.api.Test;
|
|||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
@DistributionTest
|
||||
@DistributionTest(stopServer = Mode.BEFORE_BOOTSTRAP)
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
@SkipRealmBootstrap
|
||||
public class TracingDistTest {
|
||||
|
||||
static void assertTracingEnabled(CLIResult result) {
|
||||
|
|
|
|||
|
|
@ -21,10 +21,11 @@ import java.io.IOException;
|
|||
import java.util.Map;
|
||||
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.junit5.extension.TestProvider;
|
||||
import org.keycloak.it.resource.realm.TestRealmResourceTestProvider;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
|
@ -34,38 +35,38 @@ import org.junit.jupiter.api.Test;
|
|||
import static io.restassured.RestAssured.when;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
@DistributionTest(keepAlive = true)
|
||||
@DistributionTest(stopServer = Mode.MANUAL)
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
public class TransactionDistTest {
|
||||
|
||||
@Test
|
||||
void testZeroTransactionTimeout(KeycloakDistribution dist) {
|
||||
var result = dist.run("start-dev", "--transaction-default-timeout=0s");
|
||||
void testZeroTransactionTimeout(KeycloakRunner runner) {
|
||||
var result = runner.run("start-dev", "--transaction-default-timeout=0s");
|
||||
result.assertError("Invalid duration '0s' for option 'transaction-default-timeout. Duration must be positive.");
|
||||
result = dist.run("start-dev", "--transaction-setup-timeout=0s");
|
||||
result = runner.run("start-dev", "--transaction-setup-timeout=0s");
|
||||
result.assertError("Invalid duration '0s' for option 'transaction-setup-timeout. Duration must be positive.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNegativeTransactionTimeout(KeycloakDistribution dist) {
|
||||
var result = dist.run("start-dev", "--transaction-default-timeout=-1s");
|
||||
void testNegativeTransactionTimeout(KeycloakRunner runner) {
|
||||
var result = runner.run("start-dev", "--transaction-default-timeout=-1s");
|
||||
result.assertError("Invalid duration '-1s' for option 'transaction-default-timeout. Duration must be positive.");
|
||||
result = dist.run("start-dev", "--transaction-setup-timeout=-2s");
|
||||
result = runner.run("start-dev", "--transaction-setup-timeout=-2s");
|
||||
result.assertError("Invalid duration '-2s' for option 'transaction-setup-timeout. Duration must be positive.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNonNumberTransactionTimeout(KeycloakDistribution dist) {
|
||||
var result = dist.run("start-dev", "--transaction-default-timeout=abc");
|
||||
void testNonNumberTransactionTimeout(KeycloakRunner runner) {
|
||||
var result = runner.run("start-dev", "--transaction-default-timeout=abc");
|
||||
result.assertError("Invalid duration format 'abc' for option 'transaction-default-timeout'. May be an ISO 8601 duration value, an integer number of seconds, or an integer followed by one of [ms, h, m, s, d].");
|
||||
result = dist.run("start-dev", "--transaction-setup-timeout=def");
|
||||
result = runner.run("start-dev", "--transaction-setup-timeout=def");
|
||||
result.assertError("Invalid duration format 'def' for option 'transaction-setup-timeout'. May be an ISO 8601 duration value, an integer number of seconds, or an integer followed by one of [ms, h, m, s, d].");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestProvider(TestRealmResourceTestProvider.class)
|
||||
void testValidTransactionTimeout(KeycloakDistribution dist) throws IOException {
|
||||
var result = dist.run("start-dev", "--transaction-default-timeout=123s", "--transaction-setup-timeout=456s");
|
||||
void testValidTransactionTimeout(KeycloakRunner runner) throws IOException {
|
||||
var result = runner.run("start-dev", "--transaction-default-timeout=123s", "--transaction-setup-timeout=456s");
|
||||
result.assertStartedDevMode();
|
||||
assertTimeouts();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,9 @@ import java.util.stream.Collectors;
|
|||
import java.util.stream.Stream;
|
||||
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
import org.keycloak.truststore.TruststoreBuilder;
|
||||
|
||||
|
|
@ -35,7 +36,7 @@ import org.junit.jupiter.api.Test;
|
|||
|
||||
import static io.restassured.RestAssured.given;
|
||||
|
||||
@DistributionTest(keepAlive = true)
|
||||
@DistributionTest(stopServer = Mode.MANUAL)
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
@Tag(DistributionTest.SMOKE)
|
||||
public class TruststoreDistTest {
|
||||
|
|
@ -46,19 +47,19 @@ public class TruststoreDistTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testMutualAuthWithTruststorePaths(KeycloakDistribution dist) {
|
||||
void testMutualAuthWithTruststorePaths(KeycloakRunner runner) {
|
||||
String[] truststoreNames = new String[] { "keycloak-truststore.p12", "self-signed.pem" };
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
Stream.of(truststoreNames).forEach(truststoreName -> {
|
||||
dist.copyOrReplaceFileFromClasspath("/" + truststoreName, Path.of("conf", truststoreName));
|
||||
rawDist.copyOrReplaceFileFromClasspath("/" + truststoreName, Path.of("conf", truststoreName));
|
||||
});
|
||||
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
String paths = Stream.of(truststoreNames).map(truststoreName -> rawDist.getDistPath().resolve("conf")
|
||||
.resolve(truststoreName).toAbsolutePath().toString()).collect(Collectors.joining(","));
|
||||
dist.copyOrReplaceFileFromClasspath("/self-signed.p12", Path.of("conf", "self-signed.p12"));
|
||||
rawDist.copyOrReplaceFileFromClasspath("/self-signed.p12", Path.of("conf", "self-signed.p12"));
|
||||
Path keyStore = rawDist.getDistPath().resolve("conf").resolve("self-signed.p12").toAbsolutePath();
|
||||
|
||||
rawDist.run("--verbose", "start", "--db=dev-file", "--http-enabled=true", "--hostname=mykeycloak.org",
|
||||
runner.run("--verbose", "start", "--db=dev-file", "--http-enabled=true", "--hostname=mykeycloak.org",
|
||||
"--truststore-paths=" + paths, "--https-client-auth=required", "--https-key-store-file=" + keyStore);
|
||||
|
||||
given().trustStore(TruststoreDistTest.class.getResource("/self-signed-truststore.p12").getPath(), TruststoreBuilder.DUMMY_PASSWORD)
|
||||
|
|
@ -67,17 +68,17 @@ public class TruststoreDistTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testMutualAuthWithDefaultTruststoresDir(KeycloakDistribution dist) {
|
||||
void testMutualAuthWithDefaultTruststoresDir(KeycloakRunner runner) {
|
||||
String[] truststoreNames = new String[] { "keycloak-truststore.p12", "self-signed.pem" };
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
Stream.of(truststoreNames).forEach(truststoreName -> {
|
||||
dist.copyOrReplaceFileFromClasspath("/" + truststoreName, Path.of("conf", "truststores", truststoreName));
|
||||
rawDist.copyOrReplaceFileFromClasspath("/" + truststoreName, Path.of("conf", "truststores", truststoreName));
|
||||
});
|
||||
|
||||
RawKeycloakDistribution rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
dist.copyOrReplaceFileFromClasspath("/self-signed.p12", Path.of("conf", "self-signed.p12"));
|
||||
rawDist.copyOrReplaceFileFromClasspath("/self-signed.p12", Path.of("conf", "self-signed.p12"));
|
||||
Path keyStore = rawDist.getDistPath().resolve("conf").resolve("self-signed.p12").toAbsolutePath();
|
||||
|
||||
rawDist.run("--verbose", "start", "--db=dev-file", "--http-enabled=true", "--hostname=mykeycloak.org",
|
||||
runner.run("--verbose", "start", "--db=dev-file", "--http-enabled=true", "--hostname=mykeycloak.org",
|
||||
"--https-client-auth=required", "--https-key-store-file=" + keyStore);
|
||||
|
||||
given().trustStore(TruststoreDistTest.class.getResource("/self-signed-truststore.p12").getPath(), TruststoreBuilder.DUMMY_PASSWORD)
|
||||
|
|
|
|||
|
|
@ -29,8 +29,9 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.KeycloakRunner;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.utils.RawDistRootPath;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
|
|
@ -57,20 +58,16 @@ public class WindowsServiceDistTest {
|
|||
private static final int SERVICE_START_TIMEOUT_SECONDS = 120;
|
||||
private static final int SERVICE_STOP_TIMEOUT_SECONDS = 60;
|
||||
|
||||
private RawKeycloakDistribution rawDist;
|
||||
private Path distPath;
|
||||
private String testServiceName;
|
||||
private boolean serviceCreated = false;
|
||||
private boolean prunsrvAvailable = false;
|
||||
|
||||
@BeforeEach
|
||||
void setUp(KeycloakDistribution dist) {
|
||||
this.rawDist = dist.unwrap(RawKeycloakDistribution.class);
|
||||
this.distPath = rawDist.getDistPath();
|
||||
void setUp(KeycloakRunner runner, RawDistRootPath path) {
|
||||
this.testServiceName = TEST_SERVICE_NAME_PREFIX + System.currentTimeMillis();
|
||||
|
||||
// Check if prunsrv.exe is available in the distribution
|
||||
Path prunsrvPath = distPath.resolve("bin").resolve("prunsrv.exe");
|
||||
Path prunsrvPath = path.getDistRootPath().resolve("bin").resolve("prunsrv.exe");
|
||||
if (!Files.exists(prunsrvPath)) {
|
||||
String prunsrvSystemPath = findPrunsrvInSystem();
|
||||
if (prunsrvSystemPath != null) {
|
||||
|
|
@ -87,7 +84,7 @@ public class WindowsServiceDistTest {
|
|||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
void tearDown(KeycloakRunner runner) {
|
||||
if (serviceCreated) {
|
||||
try {
|
||||
stopService();
|
||||
|
|
@ -95,7 +92,7 @@ public class WindowsServiceDistTest {
|
|||
System.err.println("Failed to stop service during cleanup: " + e.getMessage());
|
||||
}
|
||||
try {
|
||||
deleteService();
|
||||
deleteService(runner);
|
||||
} catch (Exception e) {
|
||||
System.err.println("Failed to delete service during cleanup: " + e.getMessage());
|
||||
}
|
||||
|
|
@ -103,20 +100,21 @@ public class WindowsServiceDistTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testServiceLifecycle() throws Exception {
|
||||
void testServiceLifecycle(KeycloakRunner runner) throws Exception {
|
||||
assertPrunsrvAvailable();
|
||||
assertAdminPrivileges();
|
||||
|
||||
String customDisplayName = "Keycloak Test Service " + testServiceName;
|
||||
String customDescription = "Keycloak integration test service";
|
||||
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
rawDist.setProperty("http-enabled", "true");
|
||||
rawDist.setProperty("hostname-strict", "false");
|
||||
rawDist.setProperty("log", "console,file");
|
||||
rawDist.setProperty("log-file", distPath.resolve("log").resolve("keycloak.log").toString());
|
||||
rawDist.setProperty("log-file", rawDist.getDistPath().resolve("log").resolve("keycloak.log").toString());
|
||||
|
||||
// Install the service with custom name and display name
|
||||
CLIResult installResult = rawDist.run("tools", "windows-service", "install",
|
||||
CLIResult installResult = runner.run("tools", "windows-service", "install",
|
||||
"--name=" + testServiceName,
|
||||
"--display-name=" + customDisplayName,
|
||||
"--description=" + customDescription,
|
||||
|
|
@ -137,7 +135,7 @@ public class WindowsServiceDistTest {
|
|||
assertEquals("RUNNING", getServiceState(testServiceName), "Service should be in RUNNING state");
|
||||
|
||||
// Verify log file was created and contains startup message
|
||||
Path logFile = distPath.resolve("log").resolve("keycloak.log");
|
||||
Path logFile = rawDist.getDistPath().resolve("log").resolve("keycloak.log");
|
||||
assertTrue(waitForLogFile(logFile), "Log file should be created");
|
||||
String logContent = Files.readString(logFile);
|
||||
assertThat("Log should contain Keycloak startup message", logContent, containsString("Listening on:"));
|
||||
|
|
@ -148,7 +146,7 @@ public class WindowsServiceDistTest {
|
|||
assertFalse(isKeycloakAccessible(), "Keycloak should not be accessible after service stop");
|
||||
|
||||
// Test service uninstall
|
||||
CLIResult uninstallResult = rawDist.run("tools", "windows-service", "uninstall", "--name=" + testServiceName);
|
||||
CLIResult uninstallResult = runner.run("tools", "windows-service", "uninstall", "--name=" + testServiceName);
|
||||
assertEquals(0, uninstallResult.exitCode(), "Service uninstallation failed: " + uninstallResult.getOutput());
|
||||
assertThat(uninstallResult.getOutput(), containsString("uninstalled successfully"));
|
||||
serviceCreated = false;
|
||||
|
|
@ -237,8 +235,8 @@ public class WindowsServiceDistTest {
|
|||
return true;
|
||||
}
|
||||
|
||||
private void deleteService() {
|
||||
rawDist.run("tools", "windows-service", "uninstall", "--name=" + testServiceName);
|
||||
private void deleteService(KeycloakRunner runner) {
|
||||
runner.run("tools", "windows-service", "uninstall", "--name=" + testServiceName);
|
||||
}
|
||||
|
||||
private boolean isServiceCreated(String serviceName) {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
|||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.InfinispanContainer;
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.junit5.extension.WithExternalInfinispan;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
|
|
@ -30,7 +31,7 @@ import org.junit.jupiter.api.Test;
|
|||
|
||||
import static io.restassured.RestAssured.when;
|
||||
|
||||
@DistributionTest(keepAlive = true)
|
||||
@DistributionTest(stopServer = Mode.MANUAL)
|
||||
@WithExternalInfinispan
|
||||
@Tag(DistributionTest.STORAGE)
|
||||
public class ExternalInfinispanTest {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import io.quarkus.test.junit.main.Launch;
|
|||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@DistributionTest(removeBuildOptionsAfterBuild = true)
|
||||
@DistributionTest
|
||||
@WithDatabase(alias = "mariadb")
|
||||
public class MariaDBDistTest extends MariaDBTest {
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import org.keycloak.it.storage.database.MssqlSQLTest;
|
|||
|
||||
import org.junit.jupiter.api.Tag;
|
||||
|
||||
@DistributionTest(removeBuildOptionsAfterBuild = true)
|
||||
@DistributionTest
|
||||
@WithDatabase(alias = "mssql")
|
||||
@Tag(DistributionTest.STORAGE)
|
||||
public class MssqlDistTest extends MssqlSQLTest {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import org.junit.jupiter.api.Test;
|
|||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
@DistributionTest(removeBuildOptionsAfterBuild = true)
|
||||
@DistributionTest
|
||||
@WithDatabase(alias = "mysql")
|
||||
public class MySQLDistTest extends MySQLTest {
|
||||
|
||||
|
|
|
|||
|
|
@ -17,11 +17,15 @@
|
|||
|
||||
package org.keycloak.it.storage.database.dist;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.keycloak.it.junit5.extension.BeforeStartDistribution;
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.WithDatabase;
|
||||
import org.keycloak.it.storage.database.PostgreSQLTest;
|
||||
import org.keycloak.it.utils.RawDistRootPath;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
import org.keycloak.quarkus.runtime.cli.command.AbstractAutoBuildCommand;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
|
|
@ -31,16 +35,24 @@ import org.junit.jupiter.api.Test;
|
|||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
@DistributionTest(removeBuildOptionsAfterBuild = true)
|
||||
@DistributionTest
|
||||
@WithDatabase(alias = "postgres")
|
||||
@Tag(DistributionTest.STORAGE)
|
||||
public class PostgreSQLDistTest extends PostgreSQLTest {
|
||||
|
||||
@BeforeStartDistribution(RemoveDB.class)
|
||||
@Test
|
||||
@Launch("show-config")
|
||||
public void testDbOptionFromPersistedConfigSource(CLIResult cliResult) {
|
||||
assertThat(cliResult.getOutput(),containsString("postgres (Persisted)"));
|
||||
}
|
||||
|
||||
public static final class RemoveDB implements Consumer<RawKeycloakDistribution> {
|
||||
@Override
|
||||
public void accept(RawKeycloakDistribution distribution) {
|
||||
distribution.removeProperty("db");
|
||||
}
|
||||
}
|
||||
|
||||
@Tag(DistributionTest.STORAGE)
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import java.lang.annotation.RetentionPolicy;
|
|||
import java.lang.annotation.Target;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
|
||||
/**
|
||||
* {@link BeforeStartDistribution} is used to perform additional steps prior to starting the distribution.
|
||||
|
|
@ -32,6 +32,6 @@ import org.keycloak.it.utils.KeycloakDistribution;
|
|||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface BeforeStartDistribution {
|
||||
|
||||
Class<? extends Consumer<KeycloakDistribution>> value();
|
||||
Class<? extends Consumer<RawKeycloakDistribution>> value();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import java.lang.reflect.Method;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.keycloak.Keycloak;
|
||||
|
|
@ -29,7 +30,6 @@ import org.keycloak.it.utils.KeycloakDistribution;
|
|||
import org.keycloak.it.utils.RawDistRootPath;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
import org.keycloak.quarkus.runtime.Environment;
|
||||
import org.keycloak.quarkus.runtime.cli.command.DryRunMixin;
|
||||
import org.keycloak.quarkus.runtime.cli.command.Start;
|
||||
import org.keycloak.quarkus.runtime.cli.command.StartDev;
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ import static org.keycloak.quarkus.runtime.Environment.forceExitAfterStartLaunch
|
|||
|
||||
public class CLITestExtension extends QuarkusMainTestExtension {
|
||||
|
||||
private KeycloakDistribution dist;
|
||||
private KeycloakRunner runner;
|
||||
private DatabaseContainer databaseContainer;
|
||||
private InfinispanContainer infinispanContainer;
|
||||
private CLIResult result;
|
||||
|
|
@ -74,9 +74,9 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
|||
});
|
||||
}
|
||||
|
||||
if (isRaw() && distConfig != null && dist != null) {
|
||||
if (isRaw() && distConfig != null && runner != null) {
|
||||
try {
|
||||
dist.unwrap(RawKeycloakDistribution.class).reset(beforeAll);
|
||||
runner.getDistribution(RawKeycloakDistribution.class).reset(beforeAll);
|
||||
beforeAll = false;
|
||||
} catch (Exception cause) {
|
||||
throw new RuntimeException("Failed to partially reset", cause);
|
||||
|
|
@ -87,12 +87,10 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
|||
infinispanContainer = configureExternalInfinispan(context);
|
||||
|
||||
if (distConfig != null) {
|
||||
if (dist == null) {
|
||||
dist = createDistribution(distConfig, getStoreConfig(context), getDatabaseConfig(context));
|
||||
if (runner == null) {
|
||||
runner = createDistribution(distConfig);
|
||||
}
|
||||
|
||||
onKeepServerAlive(context.getRequiredTestMethod().getAnnotation(KeepServerAlive.class), true);
|
||||
|
||||
copyTestProvider(context.getRequiredTestClass().getAnnotation(TestProvider.class));
|
||||
copyTestProvider(context.getRequiredTestMethod().getAnnotation(TestProvider.class));
|
||||
onBeforeStartDistribution(context.getRequiredTestClass().getAnnotation(BeforeStartDistribution.class));
|
||||
|
|
@ -100,19 +98,13 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
|||
|
||||
configureEnvVars(context.getRequiredTestClass().getAnnotation(WithEnvVars.class));
|
||||
configureEnvVars(context.getRequiredTestMethod().getAnnotation(WithEnvVars.class));
|
||||
boolean dryRun = context.getRequiredTestClass().getAnnotation(DryRun.class) != null
|
||||
|| context.getRequiredTestMethod().getAnnotation(DryRun.class) != null;
|
||||
if (dryRun && isRaw()) {
|
||||
dist.setEnvVar(DryRunMixin.KC_DRY_RUN_ENV, "true");
|
||||
dist.setEnvVar(DryRunMixin.KC_DRY_RUN_BUILD_ENV, "true");
|
||||
}
|
||||
if (isRaw() && (context.getRequiredTestClass().getAnnotation(SkipRealmBootstrap.class) != null
|
||||
|| context.getRequiredTestMethod().getAnnotation(SkipRealmBootstrap.class) != null)) {
|
||||
dist.unwrap(RawKeycloakDistribution.class).setLaunchMode(Environment.LAUNCH_MODE_EXIT_BEFORE_BOOTSTRAP);
|
||||
}
|
||||
|
||||
var stopServer = Optional.ofNullable(context.getRequiredTestMethod().getAnnotation(StopServer.class)).map(StopServer::value).orElse(distConfig.stopServer());
|
||||
|
||||
runner.setStopServer(stopServer);
|
||||
|
||||
if (launch != null) {
|
||||
result = dist.run(List.of(launch.value()));
|
||||
result = runner.run(List.of(launch.value()));
|
||||
}
|
||||
} else {
|
||||
if (!Keycloak.initSys(launch == null ? new String[] {} : launch.value())) {
|
||||
|
|
@ -123,10 +115,6 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
|||
}
|
||||
}
|
||||
|
||||
private static Storage getStoreConfig(ExtensionContext context) {
|
||||
return context.getTestClass().get().getDeclaredAnnotation(Storage.class);
|
||||
}
|
||||
|
||||
private void copyTestProvider(TestProvider provider) {
|
||||
if (provider == null) {
|
||||
return;
|
||||
|
|
@ -134,7 +122,7 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
|||
|
||||
if (isRaw()) {
|
||||
try {
|
||||
dist.unwrap(RawKeycloakDistribution.class).copyProvider(provider.value().getDeclaredConstructor().newInstance());
|
||||
runner.getDistribution(RawKeycloakDistribution.class).copyProvider(provider.value().getDeclaredConstructor().newInstance());
|
||||
} catch (Exception cause) {
|
||||
throw new RuntimeException("Failed to instantiate test provider: " + provider.getClass(), cause);
|
||||
}
|
||||
|
|
@ -148,7 +136,7 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
|||
@Override
|
||||
public void interceptTestMethod(Invocation<Void> invocation,
|
||||
ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
|
||||
if (dist == null) {
|
||||
if (runner == null) {
|
||||
super.interceptTestMethod(invocation, invocationContext, extensionContext);
|
||||
} else {
|
||||
invocation.proceed();
|
||||
|
|
@ -158,34 +146,20 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
|||
private void onBeforeStartDistribution(BeforeStartDistribution annotation) {
|
||||
if (annotation != null) {
|
||||
try {
|
||||
annotation.value().getDeclaredConstructor().newInstance().accept(dist);
|
||||
annotation.value().getDeclaredConstructor().newInstance().accept(runner.getDistribution(RawKeycloakDistribution.class));
|
||||
} catch (Exception cause) {
|
||||
throw new RuntimeException("Error when invoking " + annotation.value() + " instance before starting distribution", cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onKeepServerAlive(KeepServerAlive annotation, boolean setting) {
|
||||
if(annotation != null && dist != null) {
|
||||
try {
|
||||
dist.setManualStop(setting);
|
||||
} catch (Exception cause) {
|
||||
throw new RuntimeException("Error when invoking " + annotation, cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterEach(ExtensionContext context) throws Exception {
|
||||
DistributionTest distConfig = getDistributionConfig(context);
|
||||
|
||||
if (dist != null) {
|
||||
onKeepServerAlive(context.getRequiredTestMethod().getAnnotation(KeepServerAlive.class), false);
|
||||
dist.stop();
|
||||
dist.clearEnv();
|
||||
if (isRaw()) {
|
||||
dist.unwrap(RawKeycloakDistribution.class).setLaunchMode(Environment.LAUNCH_MODE_EXIT_AFTER_START);
|
||||
}
|
||||
if (runner != null) {
|
||||
runner.stop();
|
||||
runner.getDistribution().clearEnv();
|
||||
}
|
||||
|
||||
super.afterEach(context);
|
||||
|
|
@ -229,7 +203,7 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
|||
DistributionTest distConfig = getDistributionConfig(context);
|
||||
|
||||
if (distConfig != null) {
|
||||
dist = createDistribution(distConfig, getStoreConfig(context), getDatabaseConfig(context));
|
||||
runner = createDistribution(distConfig);
|
||||
} else {
|
||||
forceExitAfterStartLaunchMode();
|
||||
}
|
||||
|
|
@ -239,15 +213,15 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
|||
|
||||
@Override
|
||||
public void afterAll(ExtensionContext context) throws Exception {
|
||||
if (dist != null) {
|
||||
if (runner != null) {
|
||||
// just to make sure the server is stopped after all tests
|
||||
dist.stop();
|
||||
runner.stop();
|
||||
}
|
||||
super.afterAll(context);
|
||||
}
|
||||
|
||||
private KeycloakDistribution createDistribution(DistributionTest config, Storage storeConfig, WithDatabase databaseConfig) {
|
||||
return new KeycloakDistributionDecorator(storeConfig, databaseConfig, config, DistributionType.getCurrent().orElse(RAW).newInstance(config));
|
||||
private KeycloakRunner createDistribution(DistributionTest config) {
|
||||
return new KeycloakRunner(config, DistributionType.getCurrent().orElse(RAW).newInstance(config));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -274,12 +248,16 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
|||
//assuming the path to the distribution directory
|
||||
return getDistPath();
|
||||
}
|
||||
|
||||
if (type.equals(KeycloakRunner.class)) {
|
||||
return this.runner;
|
||||
}
|
||||
|
||||
if (type.equals(KeycloakDistribution.class)) {
|
||||
if (KeycloakDistribution.class.isAssignableFrom(type)) {
|
||||
if (context.getTestClass().orElse(Object.class).getDeclaredAnnotation(DistributionTest.class) == null) {
|
||||
throw new RuntimeException("Only tests annotated with " + DistributionTest.class + " can inject a distribution instance");
|
||||
}
|
||||
return dist;
|
||||
return runner.getDistribution((Class<? extends KeycloakDistribution>) type);
|
||||
}
|
||||
|
||||
// for now, no support for manual launching using QuarkusMainLauncher
|
||||
|
|
@ -290,7 +268,7 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
|||
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
|
||||
throws ParameterResolutionException {
|
||||
Class<?> type = parameterContext.getParameter().getType();
|
||||
return type == LaunchResult.class || type == CLIResult.class || type == RawDistRootPath.class || type == KeycloakDistribution.class;
|
||||
return type == LaunchResult.class || type == CLIResult.class || type == RawDistRootPath.class || type == KeycloakDistribution.class || type == KeycloakRunner.class;
|
||||
}
|
||||
|
||||
private void configureProfile(ExtensionContext context) {
|
||||
|
|
@ -310,7 +288,7 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
|||
WithDatabase database = getDatabaseConfig(context);
|
||||
|
||||
if (database != null) {
|
||||
if (dist == null) {
|
||||
if (runner == null) {
|
||||
configureDevServices();
|
||||
setProperty("kc.db", database.alias());
|
||||
setProperty("kc.db-password", DatabaseContainer.DEFAULT_PASSWORD);
|
||||
|
|
@ -319,19 +297,20 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
|||
|
||||
databaseContainer.start();
|
||||
|
||||
RawKeycloakDistribution rawDist = runner.getDistribution(RawKeycloakDistribution.class);
|
||||
if (database.buildOptions().length == 0) {
|
||||
dist.setProperty("db", database.alias());
|
||||
rawDist.setProperty("db", database.alias());
|
||||
} else {
|
||||
for (String option : database.buildOptions()) {
|
||||
dist.setProperty(option.substring(0, option.indexOf('=')), option.substring(option.indexOf('=') + 1));
|
||||
rawDist.setProperty(option.substring(0, option.indexOf('=')), option.substring(option.indexOf('=') + 1));
|
||||
}
|
||||
}
|
||||
|
||||
databaseContainer.configureDistribution(dist);
|
||||
databaseContainer.configureDistribution(rawDist);
|
||||
|
||||
dist.run("build");
|
||||
runner.run("build");
|
||||
}
|
||||
} else if (dist == null) {
|
||||
} else if (runner == null) {
|
||||
// This is for re-creating the H2 database instead of using the default in home
|
||||
setProperty("kc.db-url-path", Keycloak.initTempDirectory("h2-home").toFile().getAbsolutePath());
|
||||
}
|
||||
|
|
@ -374,7 +353,7 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
|||
}
|
||||
|
||||
for (int i=0; i<envVars.value().length; i=i+2) {
|
||||
dist.setEnvVar(envVars.value()[i], envVars.value()[i+1]);
|
||||
runner.getDistribution().setEnvVar(envVars.value()[i], envVars.value()[i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -393,6 +372,6 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
|||
}
|
||||
|
||||
private RawDistRootPath getDistPath(){
|
||||
return new RawDistRootPath(dist.unwrap(RawKeycloakDistribution.class).getDistPath());
|
||||
return new RawDistRootPath(runner.getDistribution(RawKeycloakDistribution.class).getDistPath());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ package org.keycloak.it.junit5.extension;
|
|||
import java.time.Duration;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
|
||||
import org.jboss.logmanager.Level;
|
||||
import org.jboss.logmanager.LogManager;
|
||||
|
|
@ -53,7 +53,7 @@ public class DatabaseContainer {
|
|||
return container.isRunning();
|
||||
}
|
||||
|
||||
void configureDistribution(KeycloakDistribution dist) {
|
||||
void configureDistribution(RawKeycloakDistribution dist) {
|
||||
dist.setProperty("db-username", getUsername());
|
||||
dist.setProperty("db-password", getPassword());
|
||||
dist.setProperty("db-url", getJdbcUrl());
|
||||
|
|
|
|||
|
|
@ -26,9 +26,12 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
|||
|
||||
/**
|
||||
* A Test that runs against a Keycloak distribution, which can be from a Docker container or zip (raw).
|
||||
* <br>
|
||||
* <p>
|
||||
* Note with the raw distribution test methods are not completely isolated for performance reasons.
|
||||
* Only a single distribution will be installed and it will only have its augmentation state reset before each test class.
|
||||
* <p>
|
||||
* Also the test logic assumes defaults, such as local cache mode (see {@link DistributionTest#localCache()} and
|
||||
* a 0 second shutdown delay.
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@ExtendWith({ CLITestExtension.class })
|
||||
|
|
@ -42,16 +45,11 @@ public @interface DistributionTest {
|
|||
|
||||
boolean debug() default false;
|
||||
/**
|
||||
* If the distribution should be left running after the launch.
|
||||
* Controls how the server stops.
|
||||
*/
|
||||
boolean keepAlive() default false;
|
||||
StopServer.Mode stopServer() default StopServer.Mode.AFTER_START;
|
||||
boolean enableTls() default false;
|
||||
|
||||
/**
|
||||
* If any build option must be unset after the running the build command.
|
||||
*/
|
||||
boolean removeBuildOptionsAfterBuild() default false;
|
||||
|
||||
/**
|
||||
* If any option must be set when starting the server.
|
||||
*/
|
||||
|
|
@ -66,4 +64,9 @@ public @interface DistributionTest {
|
|||
* Default port for making HTTP requests with RestAssured
|
||||
*/
|
||||
int requestPort() default 8080;
|
||||
|
||||
/**
|
||||
* If the cache should default to local even when the start command is used.
|
||||
*/
|
||||
boolean localCache() default true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,20 +32,11 @@ public enum DistributionType {
|
|||
|
||||
private static KeycloakDistribution createDockerDistribution(DistributionTest config) {
|
||||
return new DockerKeycloakDistribution(
|
||||
config.debug(),
|
||||
config.keepAlive(),
|
||||
config.requestPort(),
|
||||
config.containerExposedPorts());
|
||||
}
|
||||
|
||||
private static KeycloakDistribution createRawDistribution(DistributionTest config) {
|
||||
return new RawKeycloakDistribution(
|
||||
config.debug(),
|
||||
config.keepAlive(),
|
||||
config.enableTls(),
|
||||
false,
|
||||
config.removeBuildOptionsAfterBuild(),
|
||||
config.requestPort());
|
||||
return new RawKeycloakDistribution(false);
|
||||
}
|
||||
|
||||
private final Function<DistributionTest, KeycloakDistribution> factory;
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.it.junit5.extension;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* {@link DryRun} is used to configure a non-running, non-augmenting distribution
|
||||
*/
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DryRun {
|
||||
|
||||
}
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
/*
|
||||
* Copyright 2022 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.it.junit5.extension;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
|
||||
public class KeycloakDistributionDecorator implements KeycloakDistribution {
|
||||
|
||||
private Storage storageConfig;
|
||||
private WithDatabase databaseConfig;
|
||||
private DistributionTest config;
|
||||
private KeycloakDistribution delegate;
|
||||
|
||||
public KeycloakDistributionDecorator(Storage storageConfig, WithDatabase databaseConfig, DistributionTest config,
|
||||
KeycloakDistribution delegate) {
|
||||
this.storageConfig = storageConfig;
|
||||
this.databaseConfig = databaseConfig;
|
||||
this.config = config;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CLIResult run(List<String> rawArgs) {
|
||||
List<String> args = new ArrayList<>(rawArgs);
|
||||
args.addAll(List.of(config.defaultOptions()));
|
||||
setEnvVar("KC_SHUTDOWN_DELAY", "0s");
|
||||
return delegate.run(new ServerOptions(storageConfig, databaseConfig, args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
delegate.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getOutputStream() {
|
||||
return delegate.getOutputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getErrorStream() {
|
||||
return delegate.getErrorStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getExitCode() {
|
||||
return delegate.getExitCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebug() {
|
||||
return delegate.isDebug();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isManualStop() {
|
||||
return delegate.isManualStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getCliArgs(List<String> arguments) {
|
||||
return delegate.getCliArgs(arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setManualStop(boolean manualStop) {
|
||||
delegate.setManualStop(manualStop);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQuarkusProperty(String key, String value) {
|
||||
delegate.setQuarkusProperty(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(String key, String value) {
|
||||
delegate.setProperty(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteQuarkusProperties() {
|
||||
delegate.deleteQuarkusProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyOrReplaceFileFromClasspath(String file, Path distDir) {
|
||||
delegate.copyOrReplaceFileFromClasspath(file, distDir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeProperty(String name) {
|
||||
delegate.removeProperty(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvVar(String name, String value) {
|
||||
delegate.setEnvVar(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyOrReplaceFile(Path file, Path targetFile) {
|
||||
delegate.copyOrReplaceFile(file, targetFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequestPort() {
|
||||
delegate.setRequestPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequestPort(int port) {
|
||||
delegate.setRequestPort(port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <D extends KeycloakDistribution> D unwrap(Class<D> type) {
|
||||
if (!KeycloakDistribution.class.isAssignableFrom(type)) {
|
||||
throw new IllegalArgumentException("Not a " + KeycloakDistribution.class + " type");
|
||||
}
|
||||
|
||||
if (type.isInstance(delegate)) {
|
||||
//noinspection unchecked
|
||||
return (D) delegate;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Not a " + type + " type");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearEnv() {
|
||||
delegate.clearEnv();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright 2022 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.it.junit5.extension;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.keycloak.it.junit5.extension.StopServer.Mode;
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||
import org.keycloak.quarkus.runtime.cli.command.DryRunMixin;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
|
||||
import static org.keycloak.quarkus.runtime.Environment.LAUNCH_MODE;
|
||||
import static org.keycloak.quarkus.runtime.Environment.LAUNCH_MODE_EXIT_AFTER_START;
|
||||
import static org.keycloak.quarkus.runtime.Environment.LAUNCH_MODE_EXIT_BEFORE_BOOTSTRAP;
|
||||
|
||||
/**
|
||||
* Wraps the distribution to provide a run methods that configure the distribution
|
||||
* to match the expectations of the test related annotations.
|
||||
*/
|
||||
public class KeycloakRunner {
|
||||
|
||||
private DistributionTest config;
|
||||
private KeycloakDistribution delegate;
|
||||
private StopServer.Mode stopServer;
|
||||
private long startTimeout = TimeUnit.SECONDS.toMillis(Long.getLong("keycloak.distribution.start.timeout", 120L));
|
||||
|
||||
public KeycloakRunner(DistributionTest config,
|
||||
KeycloakDistribution delegate) {
|
||||
this.config = config;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public CLIResult run(String ... rawArgs) {
|
||||
return run(List.of(rawArgs));
|
||||
}
|
||||
|
||||
public CLIResult run(List<String> rawArgs) {
|
||||
delegate.stop();
|
||||
|
||||
List<String> args = new ArrayList<>(rawArgs);
|
||||
args.addAll(List.of(config.defaultOptions()));
|
||||
if (config.debug() && delegate.supportsDebug()) {
|
||||
delegate.setEnvVar("KC_DEBUG", "true");
|
||||
delegate.setEnvVar("KC_DEBUG_SUSPEND", "y");
|
||||
}
|
||||
delegate.setEnvVar("KC_SHUTDOWN_DELAY", "0s");
|
||||
if (config.localCache()) {
|
||||
delegate.setEnvVar("KC_CACHE", "local");
|
||||
} else {
|
||||
args.add("-Djgroups.join_timeout=50");
|
||||
}
|
||||
if (stopServer == Mode.BEFORE_QUARKUS) {
|
||||
delegate.setEnvVar(DryRunMixin.KC_DRY_RUN_ENV, "true");
|
||||
delegate.setEnvVar(DryRunMixin.KC_DRY_RUN_BUILD_ENV, "true");
|
||||
} else if (stopServer != Mode.MANUAL) {
|
||||
args.add("-D" + LAUNCH_MODE + "=" + (stopServer == Mode.BEFORE_BOOTSTRAP ? LAUNCH_MODE_EXIT_BEFORE_BOOTSTRAP : LAUNCH_MODE_EXIT_AFTER_START));
|
||||
}
|
||||
|
||||
if (config.enableTls()) {
|
||||
getDistribution(RawKeycloakDistribution.class).copyOrReplaceFileFromClasspath("/server.keystore", Path.of("conf", "server.keystore"));
|
||||
}
|
||||
try {
|
||||
delegate.runKc(args);
|
||||
delegate.waitFor(stopServer == Mode.MANUAL, startTimeout);
|
||||
} finally {
|
||||
if (stopServer != Mode.MANUAL) {
|
||||
delegate.stop();
|
||||
}
|
||||
}
|
||||
|
||||
setRequestPort(config.requestPort());
|
||||
|
||||
return CLIResult.create(delegate.getOutputStream(), delegate.getErrorStream(), delegate.getExitCode());
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
delegate.stop();
|
||||
}
|
||||
|
||||
public void setStopServer(Mode mode) {
|
||||
this.stopServer = mode;
|
||||
}
|
||||
|
||||
public void setRequestPort(int port) {
|
||||
RestAssured.port = delegate.getMappedPort(port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the underlying distribution - NOTE directly calling {@link KeycloakDistribution#runKc(List)}
|
||||
* on the unwrapped distribution is not recommended. The {@link #run(List)} methods on class should be used
|
||||
* instead as they ensure the arguments and env match the expectations of the test and method annotations
|
||||
*/
|
||||
public <D extends KeycloakDistribution> D getDistribution(Class<D> type) {
|
||||
if (!KeycloakDistribution.class.isAssignableFrom(type)) {
|
||||
throw new IllegalArgumentException("Not a " + KeycloakDistribution.class + " type");
|
||||
}
|
||||
|
||||
if (type.isInstance(delegate)) {
|
||||
//noinspection unchecked
|
||||
return (D) delegate;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Not a " + type + " type");
|
||||
}
|
||||
|
||||
public KeycloakDistribution getDistribution() {
|
||||
return this.delegate;
|
||||
}
|
||||
|
||||
public void setEnvVar(String key, String value) {
|
||||
this.delegate.setEnvVar(key, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
* Copyright 2022 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.it.junit5.extension;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.keycloak.quarkus.runtime.cli.command.Export;
|
||||
import org.keycloak.quarkus.runtime.cli.command.Import;
|
||||
import org.keycloak.quarkus.runtime.cli.command.ShowConfig;
|
||||
|
||||
import static org.keycloak.quarkus.runtime.cli.command.AbstractAutoBuildCommand.OPTIMIZED_BUILD_OPTION_LONG;
|
||||
|
||||
final class ServerOptions extends ArrayList<String> {
|
||||
|
||||
private static final Predicate<String> IGNORED_ARGUMENTS = ((Predicate<String>) s -> false)
|
||||
.or(OPTIMIZED_BUILD_OPTION_LONG::equals)
|
||||
.or(Export.NAME::equals)
|
||||
.or(Import.NAME::equals)
|
||||
.or("--help"::equals)
|
||||
.or("--help-all"::equals)
|
||||
.or("-h"::equals)
|
||||
.or(ShowConfig.NAME::equals);
|
||||
|
||||
private boolean isBuildPhase = false;
|
||||
|
||||
ServerOptions(Storage storageConfig, WithDatabase withDatabase, List<String> rawOptions) {
|
||||
if (rawOptions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isBuildPhase = rawOptions.contains("build");
|
||||
|
||||
for (Map.Entry<String, Predicate<String>> entry : getDefaultOptions(storageConfig, withDatabase).entrySet()) {
|
||||
if (contains(entry.getKey())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!rawOptions.stream().anyMatch(entry.getValue())) {
|
||||
add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
addAll(0, rawOptions);
|
||||
}
|
||||
|
||||
private Map<String, Predicate<String>> getDefaultOptions(Storage storageConfig, WithDatabase withDatabase) {
|
||||
Map<String, Predicate<String>> defaultOptions = new HashMap<>();
|
||||
|
||||
if (!isBuildPhase) {
|
||||
defaultOptions.put("--cache=local", ignoreCacheLocal(storageConfig));
|
||||
}
|
||||
|
||||
return defaultOptions;
|
||||
}
|
||||
|
||||
private Predicate<String> ignoreCacheLocal(Storage storageConfig) {
|
||||
return new Predicate<String>() {
|
||||
@Override
|
||||
public boolean test(String arg) {
|
||||
return arg.contains("--cache") || storageConfig == null || !storageConfig.defaultLocalCache();
|
||||
}
|
||||
}.or(IGNORED_ARGUMENTS);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package org.keycloak.it.junit5.extension;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Skips realm bootstrap (DB lock, realm creation, admin user setup) after provider initialization.
|
||||
* Liquibase schema migration and provider {@code postInit()} still run.
|
||||
* Useful for tests that only assert on log messages from server startup and don't need realm data.
|
||||
*/
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SkipRealmBootstrap {
|
||||
|
||||
}
|
||||
|
|
@ -22,13 +22,37 @@ import java.lang.annotation.Retention;
|
|||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.keycloak.it.utils.KeycloakDistribution;
|
||||
|
||||
/**
|
||||
* {@link KeepServerAlive} is used in a distributiontest to keep the server alive on test / method level.
|
||||
* Used when when {@link DistributionTest} is invoked on class level not using keepAlive=true param, but
|
||||
* for a specific test we need to run e.g. RestAssured verifications.
|
||||
* {@link StopServer} is used to control when a distribution server stops at a
|
||||
* method level.
|
||||
*/
|
||||
@Target({ ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface KeepServerAlive {
|
||||
public @interface StopServer {
|
||||
|
||||
public enum Mode {
|
||||
/**
|
||||
* Stops the server process before quarkus augmentation or startup.
|
||||
*/
|
||||
BEFORE_QUARKUS,
|
||||
/**
|
||||
* Stops the server process after database initialization, but before
|
||||
* bootstrapping (creating the master realm, boostrap admin, etc.).
|
||||
*/
|
||||
BEFORE_BOOTSTRAP,
|
||||
/**
|
||||
* Stops the server immediately after it successfully starts.
|
||||
*/
|
||||
AFTER_START,
|
||||
/**
|
||||
* Server will stop if {@link KeycloakDistribution#stop()} is called, another run is called.
|
||||
* If the server is still running at the end of the method, it will be stopped automatically.
|
||||
*/
|
||||
MANUAL
|
||||
}
|
||||
|
||||
Mode value() default Mode.AFTER_START;
|
||||
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.it.junit5.extension;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
/**
|
||||
* Use this annotation to change the default storage configuration when running a test.
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@ExtendWith({ CLITestExtension.class })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Storage {
|
||||
|
||||
/**
|
||||
* If {@code true}, the cache is set to local by default.
|
||||
*/
|
||||
boolean defaultLocalCache() default true;
|
||||
}
|
||||
|
|
@ -12,11 +12,9 @@ import java.util.function.Consumer;
|
|||
import java.util.stream.IntStream;
|
||||
|
||||
import org.keycloak.common.Version;
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
|
||||
import com.github.dockerjava.api.DockerClient;
|
||||
import com.github.dockerjava.api.exception.NotFoundException;
|
||||
import io.restassured.RestAssured;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.testcontainers.DockerClientFactory;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
|
|
@ -59,9 +57,6 @@ public final class DockerKeycloakDistribution implements KeycloakDistribution {
|
|||
|
||||
public static final int STARTUP_TIMEOUT_SECONDS = 120;
|
||||
|
||||
private final boolean debug;
|
||||
private final boolean manualStop;
|
||||
private final int requestPort;
|
||||
private final Integer[] exposedPorts;
|
||||
|
||||
private int exitCode = -1;
|
||||
|
|
@ -79,17 +74,19 @@ public final class DockerKeycloakDistribution implements KeycloakDistribution {
|
|||
|
||||
private final Map<MountableFile, String> copyToContainer = new HashMap<>();
|
||||
|
||||
public DockerKeycloakDistribution(boolean debug, boolean manualStop, int requestPort, int[] exposedPorts) {
|
||||
this(debug, manualStop, requestPort, exposedPorts, null);
|
||||
public DockerKeycloakDistribution(int[] exposedPorts) {
|
||||
this(exposedPorts, null);
|
||||
}
|
||||
|
||||
public DockerKeycloakDistribution(boolean debug, boolean manualStop, int requestPort, int[] exposedPorts, LazyFuture<String> image) {
|
||||
this.debug = debug;
|
||||
this.manualStop = manualStop;
|
||||
this.requestPort = requestPort;
|
||||
public DockerKeycloakDistribution(int[] exposedPorts, LazyFuture<String> image) {
|
||||
this.exposedPorts = IntStream.of(exposedPorts).boxed().toArray(Integer[]::new);
|
||||
this.image = image == null ? createImage(false) : image;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsDebug() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvVar(String name, String value) {
|
||||
|
|
@ -150,8 +147,10 @@ public final class DockerKeycloakDistribution implements KeycloakDistribution {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CLIResult run(List<String> arguments) {
|
||||
stop();
|
||||
public void runKc(List<String> arguments) {
|
||||
if (keycloakContainer != null) {
|
||||
throw new IllegalStateException("Stop has not been called");
|
||||
}
|
||||
try {
|
||||
this.exitCode = -1;
|
||||
this.stdout = "";
|
||||
|
|
@ -168,35 +167,17 @@ public final class DockerKeycloakDistribution implements KeycloakDistribution {
|
|||
.withCommand(arguments.toArray(new String[0]))
|
||||
.start();
|
||||
containerId = keycloakContainer.getContainerId();
|
||||
|
||||
waitForStableOutput();
|
||||
} catch (Exception cause) {
|
||||
this.exitCode = -1;
|
||||
this.stdout = backupConsumer.stdOut.toUtf8String();
|
||||
this.stderr = backupConsumer.stdErr.toUtf8String();
|
||||
cleanupContainer();
|
||||
keycloakContainer = null;
|
||||
LOGGER.warn("Failed to start Keycloak container", cause);
|
||||
} finally {
|
||||
if (!manualStop) {
|
||||
stop();
|
||||
try {
|
||||
cleanupContainer();
|
||||
} catch (Exception stopException) {
|
||||
cause.addSuppressed(stopException);
|
||||
}
|
||||
}
|
||||
|
||||
setRequestPort();
|
||||
|
||||
return CLIResult.create(getOutputStream(), getErrorStream(), getExitCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequestPort() {
|
||||
setRequestPort(requestPort);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequestPort(int port) {
|
||||
if (keycloakContainer != null) {
|
||||
RestAssured.port = keycloakContainer.getMappedPort(port);
|
||||
keycloakContainer = null;
|
||||
throw new RuntimeException("Failed to start the server", cause);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -212,9 +193,11 @@ public final class DockerKeycloakDistribution implements KeycloakDistribution {
|
|||
public void copyConfigFile(Path configFilePath) {
|
||||
copyToContainer.put(MountableFile.forHostPath(configFilePath), "/opt/keycloak/conf/" + configFilePath.getFileName());
|
||||
}
|
||||
|
||||
|
||||
// After the web server is responding we are still producing some logs that got checked in the tests
|
||||
private void waitForStableOutput() {
|
||||
@Override
|
||||
public void waitFor(boolean ready, long timeoutMillis) {
|
||||
// TODO: doesn't differentiate ready, nor implements the timeout
|
||||
int retry = 10;
|
||||
String lastLine = "";
|
||||
boolean stableOutput = false;
|
||||
|
|
@ -319,34 +302,12 @@ public final class DockerKeycloakDistribution implements KeycloakDistribution {
|
|||
return this.exitCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebug() {
|
||||
return this.debug;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isManualStop() {
|
||||
return this.manualStop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <D extends KeycloakDistribution> D unwrap(Class<D> type) {
|
||||
if (!KeycloakDistribution.class.isAssignableFrom(type)) {
|
||||
throw new IllegalArgumentException("Not a " + KeycloakDistribution.class + " type");
|
||||
}
|
||||
|
||||
if (type.isInstance(this)) {
|
||||
return type.cast(this);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Not a " + type + " type");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearEnv() {
|
||||
this.envVars.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMappedPort(int port) {
|
||||
if (keycloakContainer == null || !keycloakContainer.isRunning()) {
|
||||
throw new IllegalStateException("KeycloakContainer is not running.");
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package org.keycloak.it.utils;
|
|||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.quarkus.runtime.Environment;
|
||||
|
||||
public interface KeycloakDistribution {
|
||||
|
|
@ -12,64 +11,40 @@ public interface KeycloakDistribution {
|
|||
|
||||
String SCRIPT_KCADM_CMD = Environment.isWindows() ? "kcadm.bat" : "kcadm.sh";
|
||||
|
||||
CLIResult run(List<String> arguments);
|
||||
default CLIResult run(String... arguments) {
|
||||
return run(List.of(arguments));
|
||||
/**
|
||||
* Run the kc command and immediately return without waiting for the process
|
||||
*/
|
||||
void runKc(List<String> arguments);
|
||||
/**
|
||||
* Run the kc command and immediately return without waiting for the process
|
||||
*/
|
||||
default void runKc(String... arguments) {
|
||||
runKc(List.of(arguments));
|
||||
}
|
||||
|
||||
|
||||
void waitFor(boolean ready, long timeoutMillis);
|
||||
|
||||
void stop();
|
||||
|
||||
int getMappedPort(int port);
|
||||
|
||||
List<String> getOutputStream();
|
||||
|
||||
List<String> getErrorStream();
|
||||
|
||||
/**
|
||||
* Available after the main process exits, which may require {@link #stop()} to be called
|
||||
*/
|
||||
int getExitCode();
|
||||
|
||||
boolean supportsDebug();
|
||||
|
||||
boolean isDebug();
|
||||
|
||||
boolean isManualStop();
|
||||
|
||||
void setRequestPort();
|
||||
|
||||
void setRequestPort(int port);
|
||||
|
||||
default String[] getCliArgs(List<String> arguments) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
default void setManualStop(boolean manualStop) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
default void setQuarkusProperty(String key, String value) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
default void setProperty(String key, String value) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
default void deleteQuarkusProperties() {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
default void copyOrReplaceFileFromClasspath(String file, Path distDir) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
default void removeProperty(String name) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
default void setEnvVar(String name, String value) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
default void copyOrReplaceFile(Path file, Path targetFile) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
<D extends KeycloakDistribution> D unwrap(Class<D> type);
|
||||
void setEnvVar(String name, String value);
|
||||
|
||||
void clearEnv();
|
||||
|
||||
void copyProvider(String groupId, String artifactId);
|
||||
|
||||
void copyConfigFile(Path configFilePath);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,13 +13,7 @@ public class RawDistributionLifecycleManager implements QuarkusTestResourceLifec
|
|||
|
||||
@Override
|
||||
public Map<String, String> start() {
|
||||
dist = new RawKeycloakDistribution(
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
8080);
|
||||
dist = new RawKeycloakDistribution(true);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,18 +24,12 @@ import java.io.FileOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
|
@ -45,31 +39,24 @@ import java.util.Map;
|
|||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import org.keycloak.common.Version;
|
||||
import org.keycloak.it.TestProvider;
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.quarkus.runtime.Environment;
|
||||
import org.keycloak.quarkus.runtime.cli.command.Build;
|
||||
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper;
|
||||
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers;
|
||||
import org.keycloak.quarkus.runtime.KeycloakMain;
|
||||
|
||||
import io.quarkus.deployment.util.FileUtil;
|
||||
import io.quarkus.fs.util.ZipUtils;
|
||||
import io.restassured.RestAssured;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.jboss.logging.Logger;
|
||||
|
|
@ -91,31 +78,12 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
private Process keycloak;
|
||||
private int exitCode = -1;
|
||||
private Path distPath;
|
||||
private boolean manualStop;
|
||||
private String relativePath;
|
||||
private int httpPort;
|
||||
private int httpsPort;
|
||||
private final boolean debug;
|
||||
private final boolean enableTls;
|
||||
private final boolean reCreate;
|
||||
private final boolean removeBuildOptionsAfterBuild;
|
||||
private final int requestPort;
|
||||
private ExecutorService outputExecutor;
|
||||
private final Map<String, String> envVars = new HashMap<>();
|
||||
private final OutputConsumer outputConsumer;
|
||||
private long startTimeout = TimeUnit.SECONDS.toMillis(Long.getLong("keycloak.distribution.start.timeout", 120L));
|
||||
private boolean throwErrorIfFailedToStart = false;
|
||||
private boolean threadDump = true;
|
||||
private String launchMode = Environment.LAUNCH_MODE_EXIT_AFTER_START;
|
||||
private final DefaultOutputConsumer outputConsumer;
|
||||
|
||||
public RawKeycloakDistribution(boolean debug, boolean manualStop, boolean enableTls, boolean reCreate, boolean removeBuildOptionsAfterBuild, int requestPort) {
|
||||
this.debug = debug;
|
||||
this.manualStop = manualStop;
|
||||
this.enableTls = enableTls;
|
||||
this.reCreate = reCreate;
|
||||
this.removeBuildOptionsAfterBuild = removeBuildOptionsAfterBuild;
|
||||
this.requestPort = requestPort;
|
||||
this.distPath = prepareDistribution();
|
||||
public RawKeycloakDistribution(boolean reCreate) {
|
||||
this.distPath = prepareDistribution(reCreate);
|
||||
if (reCreate) {
|
||||
try {
|
||||
preInitH2(distPath);
|
||||
|
|
@ -125,20 +93,34 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
}
|
||||
this.outputConsumer = new DefaultOutputConsumer();
|
||||
}
|
||||
|
||||
public RawKeycloakDistribution withThrowErrorIfFailedToStart(boolean throwErrorIfFailedToStart) {
|
||||
this.throwErrorIfFailedToStart = throwErrorIfFailedToStart;
|
||||
return this;
|
||||
|
||||
@Override
|
||||
public int getMappedPort(int port) {
|
||||
return port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void waitFor(boolean ready, long timeoutMillis) {
|
||||
if (!isRunning()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (ready) {
|
||||
this.outputConsumer.running.get(timeoutMillis, TimeUnit.MILLISECONDS);
|
||||
} else {
|
||||
this.keycloak.onExit().get(timeoutMillis, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException(e);
|
||||
} catch (ExecutionException|TimeoutException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public RawKeycloakDistribution withThreadDump(boolean threadDump) {
|
||||
this.threadDump = threadDump;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RawKeycloakDistribution withStartTimeout(long startTimeout) {
|
||||
this.startTimeout = startTimeout;
|
||||
return this;
|
||||
@Override
|
||||
public boolean supportsDebug() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public CLIResult kc(String... arguments) throws IOException {
|
||||
|
|
@ -160,22 +142,13 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
private CLIResult invoke(String script, List<String> arguments) throws IOException {
|
||||
List<String> allArgs = new ArrayList<>();
|
||||
|
||||
invoke(allArgs, script);
|
||||
|
||||
if (this.isDebug()) {
|
||||
allArgs.add("-x");
|
||||
}
|
||||
addPlatformSpecificCommand(allArgs, script);
|
||||
|
||||
allArgs.addAll(arguments);
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(allArgs);
|
||||
ProcessBuilder builder = pb.directory(distPath.resolve("bin").toFile());
|
||||
|
||||
// TODO: it is possible to debug kcadm, but it's more involved
|
||||
/*if (debug) {
|
||||
builder.environment().put("DEBUG_SUSPEND", "y");
|
||||
}*/
|
||||
|
||||
addAOTEnvVars();
|
||||
|
||||
builder.environment().putAll(envVars);
|
||||
|
|
@ -190,30 +163,23 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
return CLIResult.create(outputConsumer.getStdOut(), outputConsumer.getErrOut(), exitValue);
|
||||
}
|
||||
|
||||
private void invoke(List<String> allArgs, String cmd) {
|
||||
private void addPlatformSpecificCommand(List<String> allArgs, String cmd) {
|
||||
if (isWindows()) {
|
||||
allArgs.add(distPath.resolve("bin") + File.separator + cmd);
|
||||
} else {
|
||||
allArgs.add("./" + cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CLIResult run(List<String> arguments) {
|
||||
stop();
|
||||
if (manualStop && isRunning()) {
|
||||
throw new IllegalStateException("Server already running. You should manually stop the server before starting it again.");
|
||||
|
||||
@Override
|
||||
public void runKc(List<String> arguments) {
|
||||
if (isRunning()) {
|
||||
throw new IllegalStateException("Stop has not been called");
|
||||
}
|
||||
reset();
|
||||
resetForNextRun();
|
||||
try {
|
||||
configureServer();
|
||||
startServer(arguments);
|
||||
if (manualStop) {
|
||||
asyncReadOutput();
|
||||
waitForReadiness();
|
||||
} else {
|
||||
readOutput();
|
||||
}
|
||||
asyncReadOutput();
|
||||
} catch (Exception cause) {
|
||||
try {
|
||||
stop();
|
||||
|
|
@ -221,27 +187,6 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
cause.addSuppressed(stopException);
|
||||
}
|
||||
throw new RuntimeException("Failed to start the server", cause);
|
||||
} finally {
|
||||
if (arguments.contains(Build.NAME) && removeBuildOptionsAfterBuild) {
|
||||
for (List<PropertyMapper<?>> mappers : PropertyMappers.getBuildTimeMappers().values()) {
|
||||
for (PropertyMapper<?> mapper : mappers) {
|
||||
removeProperty(mapper.getFrom().substring(3));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!manualStop) {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
setRequestPort();
|
||||
|
||||
return CLIResult.create(getOutputStream(), getErrorStream(), getExitCode());
|
||||
}
|
||||
|
||||
private void configureServer() {
|
||||
if (enableTls) {
|
||||
copyOrReplaceFileFromClasspath("/server.keystore", Path.of("conf", "server.keystore"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -325,124 +270,14 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
return exitCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebug() { return this.debug; }
|
||||
|
||||
@Override
|
||||
public boolean isManualStop() { return this.manualStop; }
|
||||
|
||||
@Override
|
||||
public String[] getCliArgs(List<String> arguments) {
|
||||
List<String> allArgs = new ArrayList<>();
|
||||
|
||||
invoke(allArgs, SCRIPT_CMD);
|
||||
|
||||
if (this.isDebug()) {
|
||||
allArgs.add("--debug");
|
||||
}
|
||||
|
||||
if (!this.isManualStop()) {
|
||||
allArgs.add("-D" + LAUNCH_MODE + "=" + launchMode);
|
||||
}
|
||||
|
||||
allArgs.add("-Djgroups.join_timeout=50");
|
||||
|
||||
this.relativePath = arguments.stream().filter(arg -> arg.startsWith("--http-relative-path")).map(arg -> arg.substring(arg.indexOf('=') + 1)).findAny().orElse("/");
|
||||
this.httpPort = Integer.parseInt(arguments.stream().filter(arg -> arg.startsWith("--http-port")).map(arg -> arg.substring(arg.indexOf('=') + 1)).findAny().orElse("8080"));
|
||||
this.httpsPort = Integer.parseInt(arguments.stream().filter(arg -> arg.startsWith("--https-port")).map(arg -> arg.substring(arg.indexOf('=') + 1)).findAny().orElse("8443"));
|
||||
|
||||
allArgs.add("-Dkc.home.dir=" + distPath + File.separator);
|
||||
allArgs.addAll(arguments);
|
||||
|
||||
return allArgs.toArray(String[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequestPort() {
|
||||
setRequestPort(requestPort);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequestPort(int port) {
|
||||
RestAssured.port = port;
|
||||
}
|
||||
|
||||
private void waitForReadiness() throws MalformedURLException {
|
||||
waitForReadiness("http", httpPort);
|
||||
|
||||
if (enableTls) {
|
||||
waitForReadiness("https", httpsPort);
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForReadiness(String scheme, int port) throws MalformedURLException {
|
||||
var myRelativePath = relativePath;
|
||||
if (!myRelativePath.endsWith("/")) {
|
||||
myRelativePath += "/";
|
||||
}
|
||||
URL contextRoot = new URL(scheme + "://localhost:" + port + myRelativePath + "realms/master/");
|
||||
HttpURLConnection connection = null;
|
||||
long startTime = System.currentTimeMillis();
|
||||
Exception ex = null;
|
||||
|
||||
while (true) {
|
||||
if (System.currentTimeMillis() - startTime > getStartTimeout()) {
|
||||
threadDump();
|
||||
throw new IllegalStateException(
|
||||
"Timeout [" + getStartTimeout() + "] while waiting for Quarkus server", ex);
|
||||
}
|
||||
|
||||
if (!keycloak.isAlive()) {
|
||||
if (throwErrorIfFailedToStart) {
|
||||
throw new RuntimeException("Keycloak failed to start: process terminated");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// wait before checking for opening a new connection
|
||||
if ("https".equals(contextRoot.getProtocol())) {
|
||||
HttpsURLConnection httpsConnection = (HttpsURLConnection) (connection = (HttpURLConnection) contextRoot.openConnection());
|
||||
httpsConnection.setSSLSocketFactory(createInsecureSslSocketFactory());
|
||||
httpsConnection.setHostnameVerifier(createInsecureHostnameVerifier());
|
||||
} else {
|
||||
connection = (HttpURLConnection) contextRoot.openConnection();
|
||||
}
|
||||
|
||||
connection.setReadTimeout((int) getStartTimeout());
|
||||
connection.setConnectTimeout((int) getStartTimeout());
|
||||
connection.connect();
|
||||
|
||||
if (connection.getResponseCode() == 200) {
|
||||
break;
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
ex = ignore;
|
||||
} finally {
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void threadDump() {
|
||||
if (!threadDump) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Environment.isWindows()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ProcessBuilder builder = new ProcessBuilder("kill", "-3", String.valueOf(keycloak.pid()));
|
||||
Process p = builder.start();
|
||||
p.onExit().get(getStartTimeout(), TimeUnit.MILLISECONDS);
|
||||
p.onExit().get(DEFAULT_SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS);
|
||||
} catch (Exception e) {
|
||||
LOG.warn("A thread dump may not have been successfully triggered", e);
|
||||
return;
|
||||
|
|
@ -451,43 +286,6 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
.until(() -> getOutputStream().stream().anyMatch(s -> s.contains("JNI global refs")));
|
||||
}
|
||||
|
||||
private long getStartTimeout() {
|
||||
return startTimeout;
|
||||
}
|
||||
|
||||
private HostnameVerifier createInsecureHostnameVerifier() {
|
||||
return (s, sslSession) -> true;
|
||||
}
|
||||
|
||||
private SSLSocketFactory createInsecureSslSocketFactory() throws IOException {
|
||||
TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
|
||||
@Override
|
||||
public void checkClientTrusted(final X509Certificate[] chain, final String authType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(final X509Certificate[] chain, final String authType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
}};
|
||||
|
||||
SSLContext sslContext;
|
||||
SSLSocketFactory socketFactory;
|
||||
|
||||
try {
|
||||
sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, trustAllCerts, new SecureRandom());
|
||||
socketFactory = sslContext.getSocketFactory();
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException e) {
|
||||
throw new IOException("Can't create unsecure trust manager");
|
||||
}
|
||||
return socketFactory;
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return keycloak != null && keycloak.isAlive();
|
||||
}
|
||||
|
|
@ -511,7 +309,7 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
}
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
private void resetForNextRun() {
|
||||
outputConsumer.reset();
|
||||
exitCode = -1;
|
||||
shutdownOutputExecutor();
|
||||
|
|
@ -533,7 +331,7 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
throw new RuntimeException(String.format("ZIP file '%s' doesn't contain any directories", distPath));
|
||||
}
|
||||
|
||||
private Path prepareDistribution() {
|
||||
public Path prepareDistribution(boolean reCreate) {
|
||||
try {
|
||||
Path distRootPath = Paths.get(System.getProperty("java.io.tmpdir")).resolve("kc-tests");
|
||||
distRootPath.toFile().mkdirs();
|
||||
|
|
@ -575,7 +373,6 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
|
||||
private void preInitH2(Path dPath) throws IOException {
|
||||
ProcessHandle.current().info().command().ifPresent(command -> {
|
||||
Runtime.Version runtimeVersion = Runtime.version();
|
||||
boolean useAot = false;
|
||||
if (Boolean.getBoolean("kc.quarkus.tests.aot")) {
|
||||
if (Runtime.version().feature() < 25) {
|
||||
|
|
@ -658,18 +455,25 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
* @throws Exception if something bad happens
|
||||
*/
|
||||
private void startServer(List<String> arguments) throws Exception {
|
||||
ProcessBuilder pb = new ProcessBuilder(getCliArgs(arguments));
|
||||
List<String> allArgs = new ArrayList<>();
|
||||
|
||||
addPlatformSpecificCommand(allArgs, SCRIPT_CMD);
|
||||
|
||||
// used to detect readiness rather than http(s) probing
|
||||
allArgs.add("-D%s=true".formatted(KeycloakMain.KC_SERVER_PRINT_RUNNING));
|
||||
|
||||
allArgs.addAll(arguments);
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(allArgs);
|
||||
ProcessBuilder builder = pb.directory(distPath.resolve("bin").toFile());
|
||||
|
||||
if (debug) {
|
||||
builder.environment().put("DEBUG_SUSPEND", "y");
|
||||
}
|
||||
|
||||
addAOTEnvVars();
|
||||
|
||||
builder.environment().putAll(envVars);
|
||||
|
||||
keycloak = builder.start();
|
||||
var future = outputConsumer.running;
|
||||
keycloak.onExit().whenComplete((p, t) -> future.complete(null));
|
||||
}
|
||||
|
||||
private void addAOTEnvVars() {
|
||||
|
|
@ -681,12 +485,6 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setManualStop(boolean manualStop) {
|
||||
this.manualStop = manualStop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(String key, String value) {
|
||||
updateProperties(properties -> properties.put(key, value), distPath.resolve("conf").resolve("keycloak.conf").toFile());
|
||||
}
|
||||
|
|
@ -696,21 +494,14 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
this.envVars.put(name, value);
|
||||
}
|
||||
|
||||
public void setLaunchMode(String launchMode) {
|
||||
this.launchMode = launchMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeProperty(String name) {
|
||||
updateProperties(properties -> properties.remove(name), distPath.resolve("conf").resolve("keycloak.conf").toFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQuarkusProperty(String key, String value) {
|
||||
updateProperties(properties -> properties.put(key, value), getQuarkusPropertiesFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteQuarkusProperties() {
|
||||
File file = getQuarkusPropertiesFile();
|
||||
|
||||
|
|
@ -719,7 +510,6 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyOrReplaceFileFromClasspath(String file, Path targetFile) {
|
||||
Path path = distPath.resolve(targetFile);
|
||||
|
||||
|
|
@ -732,7 +522,6 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyOrReplaceFile(Path file, Path targetFile) {
|
||||
if (!file.toFile().exists()) {
|
||||
return;
|
||||
|
|
@ -749,6 +538,7 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyProvider(String groupId, String artifactId) {
|
||||
copyProvider(getDistPath(), groupId, artifactId);
|
||||
}
|
||||
|
|
@ -766,6 +556,7 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyConfigFile(Path configFilePath) {
|
||||
try {
|
||||
Files.copy(configFilePath, distPath.resolve("conf").resolve(configFilePath.getFileName()));
|
||||
|
|
@ -833,19 +624,6 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
providerJar.as(ZipExporter.class).exportTo(getDistPath().resolve("providers").resolve(providerJar.getName()).toFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <D extends KeycloakDistribution> D unwrap(Class<D> type) {
|
||||
if (!KeycloakDistribution.class.isAssignableFrom(type)) {
|
||||
throw new IllegalArgumentException("Not a " + KeycloakDistribution.class + " type");
|
||||
}
|
||||
|
||||
if (type.isInstance(this)) {
|
||||
return type.cast(type);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Not a " + type + " type");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearEnv() {
|
||||
this.envVars.clear();
|
||||
|
|
@ -855,9 +633,13 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
|
||||
private final List<String> stdOut = Collections.synchronizedList(new ArrayList<>());
|
||||
private final List<String> errOut = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
private CompletableFuture<Void> running = new CompletableFuture<Void>();
|
||||
|
||||
@Override
|
||||
public void onStdOut(String line) {
|
||||
if (line.equals(KeycloakMain.RUNNING_MESSAGE)) {
|
||||
running.complete(null);
|
||||
}
|
||||
System.out.println(line);
|
||||
stdOut.add(line);
|
||||
}
|
||||
|
|
@ -872,6 +654,7 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
public void reset() {
|
||||
stdOut.clear();
|
||||
errOut.clear();
|
||||
this.running = new CompletableFuture<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -883,6 +666,7 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
|||
public List<String> getStdOut() {
|
||||
return stdOut;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void resetH2Dir() throws IOException {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ import org.testcontainers.utility.LazyFuture;
|
|||
public class ClusteredKeycloakServer implements KeycloakServer {
|
||||
|
||||
private static final String CLUSTER_VIEW_REGEX = ".*ISPN000093.*(?<=\\()(%1$d)(?=\\)).*|.*ISPN000094.*(?<=\\()(%1$d)(?=\\)).*";
|
||||
private static final boolean MANUAL_STOP = true;
|
||||
private static final int REQUEST_PORT = 8080;
|
||||
private static final int MANAGEMENT_PORT = 9000;
|
||||
public static final String SNAPSHOT_IMAGE = "-";
|
||||
|
|
@ -100,13 +99,13 @@ public class ClusteredKeycloakServer implements KeycloakServer {
|
|||
} else {
|
||||
resolvedImage = new RemoteDockerImage(DockerImageName.parse(imagePeServer[i]));
|
||||
}
|
||||
var container = new DockerKeycloakDistribution(false, MANUAL_STOP, REQUEST_PORT, exposedPorts, resolvedImage);
|
||||
var container = new DockerKeycloakDistribution(exposedPorts, resolvedImage);
|
||||
containers[i] = container;
|
||||
|
||||
copyProvidersAndConfigs(container, configBuilder);
|
||||
|
||||
configureLogConsumers(container, i, clusterLatch);
|
||||
container.run(configBuilder.toArgs());
|
||||
container.runKc(configBuilder.toArgs());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -116,12 +115,12 @@ public class ClusteredKeycloakServer implements KeycloakServer {
|
|||
defaultImage() :
|
||||
new RemoteDockerImage(DockerImageName.parse(image));
|
||||
for (int i = 0; i < containers.length; ++i) {
|
||||
var container = new DockerKeycloakDistribution(false, MANUAL_STOP, REQUEST_PORT, exposedPorts, imageFuture);
|
||||
var container = new DockerKeycloakDistribution(exposedPorts, imageFuture);
|
||||
containers[i] = container;
|
||||
|
||||
copyProvidersAndConfigs(container, configBuilder);
|
||||
configureLogConsumers(container, i, clusterLatch);
|
||||
container.run(configBuilder.toArgs());
|
||||
container.runKc(configBuilder.toArgs());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue