Giter Site home page Giter Site logo

dasniko / testcontainers-keycloak Goto Github PK

View Code? Open in Web Editor NEW
313.0 9.0 48.0 222 KB

A Testcontainer implementation for Keycloak IAM & SSO.

License: Apache License 2.0

Java 99.44% Shell 0.56%
keycloak testcontainers testing sso java iam oidc docker container

testcontainers-keycloak's Introduction

Keycloak Testcontainer

A Testcontainers implementation for Keycloak SSO.

CI build Maven Central

IMPORTANT!!!

This version only handles Keycloak from version 22.x and up, as there are major changes coming with this release. See also the blog post.
For older Keycloak versions (until 21.x), see version 2.x branch.

How to use

The @Container annotation used here in the readme is from the JUnit 5 support of Testcontainers. Please refer to the Testcontainers documentation for more information.

Default

Simply spin up a default Keycloak instance:

@Container
KeycloakContainer keycloak = new KeycloakContainer();

Custom image

Use another Keycloak Docker image/version than used in this Testcontainer:

@Container
KeycloakContainer keycloak = new KeycloakContainer("quay.io/keycloak/keycloak:24.0");

Realm Import

Power up a Keycloak instance with one or more existing realm JSON config files (from classpath):

@Container
KeycloakContainer keycloak = new KeycloakContainer()
    .withRealmImportFile("/test-realm.json");

or

    .withRealmImportFiles("/test-realm-1.json", "/test-realm-2.json");

Initial admin user credentials

Use different admin credentials than the defaut internal (admin/admin) ones:

@Container
KeycloakContainer keycloak = new KeycloakContainer()
    .withAdminUsername("myKeycloakAdminUser")
    .withAdminPassword("tops3cr3t");

Getting an admin client and other information from the testcontainer

You can get an instance of org.keycloak.admin.Keycloak admin client directly from the container, using

org.keycloak.admin.Keycloak keycloakAdmin = keycloakContainer.getKeycloakAdminClient();

The admin client is configured with current admin credentials.

The org.keycloak:keycloak-admin-client package is now a transitive dependency of this project, ready to be used by you in your tests, no more need to add it on your own.

You can also obtain several properties from the Keycloak container:

String authServerUrl = keycloak.getAuthServerUrl();
String adminUsername = keycloak.getAdminUsername();
String adminPassword = keycloak.getAdminPassword();

with these properties, you can create e.g. a custom org.keycloak.admin.client.Keycloak object to connect to the container and do optional further configuration:

Keycloak keycloakAdminClient = KeycloakBuilder.builder()
    .serverUrl(keycloak.getAuthServerUrl())
    .realm("master")
    .clientId("admin-cli")
    .username(keycloak.getAdminUsername())
    .password(keycloak.getAdminPassword())
    .build();

Context Path

As Keycloak comes with the default context path /, you can set your custom context path, e.g. for compatibility reasons to previous versions, with:

@Container
KeycloakContainer keycloak = new KeycloakContainer()
    .withContextPath("/auth");

Memory Settings

As of Keycloak 24 the container doesn't use an absolute amount of memory, but a relative percentage of the overall available memory to the container, see also here.

This testcontainer has an initial memory setting of

JAVA_OPTS_KC_HEAP="-XX:InitialRAMPercentage=1 -XX:MaxRAMPercentage=5"

to not overload your environment. You can override this settng with the withRamPercentage(initial, max) method:

@Container
KeycloakContainer keycloak = new KeycloakContainer()
    .withRamPercentage(50, 70);

TLS (SSL) Usage

You have three options to use HTTPS/TLS secured communication with your Keycloak Testcontainer.

Built-in TLS Keystore

This Keycloak Testcontainer comes with built-in TLS certificate (tls.crt), key (tls.key) and Java KeyStore (tls.jks) files, located in the resources folder. You can use this configuration by only configuring your testcontainer like this:

@Container
KeycloakContainer keycloak = new KeycloakContainer().useTls();

The password for the provided Java KeyStore file is changeit. See also KeycloakContainerHttpsTest.shouldStartKeycloakWithProvidedTlsKeystore.

The method getAuthServerUrl() will then return the HTTPS url.

Custom TLS Cert and Key

Of course you can also provide your own certificate and key file for usage in this Testcontainer:

@Container
private KeycloakContainer keycloak = new KeycloakContainer()
.useTls("your_custom.crt", "your_custom.key");

See also KeycloakContainerHttpsTest.shouldStartKeycloakWithCustomTlsCertAndKey.

The method getAuthServerUrl() will also return the HTTPS url.

Custom TLS Keystore

Last but not least, you can also provide your own keystore file for usage in this Testcontainer:

@Container
KeycloakContainer keycloak = new KeycloakContainer()
    .useTlsKeystore("your_custom.jks", "password_for_your_custom_keystore");

See also KeycloakContainerHttpsTest.shouldStartKeycloakWithCustomTlsKeystore.

The method getAuthServerUrl() will also return the HTTPS url.

Features

You can enable and disable features on your Testcontainer:

@Container
KeycloakContainer keycloak = new KeycloakContainer()
    .withFeaturesEnabled("docker", "scripts", "...")
    .withFeaturesDisabled("authorization", "impersonation", "...");

Testing Custom Extensions

To ease extension testing, you can tell the Keycloak Testcontainer to detect extensions in a given classpath folder. This allows to test extensions directly in the same module without a packaging step.

If you have your Keycloak extension code in the src/main/java folder, then the resulting classes will be generated to the target/classes folder. To test your extensions you just need to tell KeycloakContainer to consider extensions from the target/classes folder.

Keycloak Testcontainer will then dynamically generate a packaged jar file with the extension code that is then picked up by Keycloak.

KeycloakContainer keycloak = new KeycloakContainer()
    .withProviderClassesFrom("target/classes");

For your convenience, there's now (since 3.3) a default method, which yields to target/classes internally:

KeycloakContainer keycloak = new KeycloakContainer()
    .withDefaultProviderClasses();

See also KeycloakContainerExtensionTest class.

Dependencies & 3rd-party Libraries

If you need to provide any 3rd-party dependency or library, you can do this with

List<File> libs = ...;
KeycloakContainer keycloak = new KeycloakContainer()
    .withProviderLibsFrom(libs);

You have to provide a list of resolvable Files.

Extending KeycloakContainer

In case you need a custom implementation of the default KeycloakContainer, you should inherit from ExtendableKeycloakContainer. This allows to set the generics and use your custom implementation without the need for type casts.

public class MyCustomKeycloakContainer extends ExtendableKeycloakContainer<MyCustomKeycloakContainer> {

	public MyCustomKeycloakContainer() {
		super();
	}

	public MyCustomKeycloakContainer(String dockerImageName) {
		super(dockerImageName);
	}
	
}

...

MyCustomKeycloakContainer keycloakContainer = new MyCustomKeycloakContainer()
    .withAdminPassword("password");

TIPP

If you want/need to use dependencies from e.g. Maven (or Gradle), you can use ShrinkWrap Resolvers. See, as an example, how this is used at the KeycloakContainerExtensionTest#shouldDeployProviderWithDependencyAndCallCustomEndpoint() test.

Remote Debugger Support

You can tell the Keycloak Testcontainer to open a debug port for attaching a remote debugger.

This command will enable remote debugging in Keycloak and expose the used debug port in the container on a random port to the outside:

KeycloakContainer keycloak = new KeycloakContainer()
    .withDebug();

If you want to enable remote debugging on a fixed port and optionally have Keycloak wait (suspend) until a debugger has attached to this port, use this command:

KeycloakContainer keycloak = new KeycloakContainer()
    .withDebugFixedPort(int hostPort, boolean suspend);

Setup

The release versions of this project are available at Maven Central. Simply put the dependency coordinates to your pom.xml (or something similar, if you use e.g. Gradle or something else):

<dependency>
  <groupId>com.github.dasniko</groupId>
  <artifactId>testcontainers-keycloak</artifactId>
  <version>VERSION</version>
  <scope>test</scope>
</dependency>

JUnit4 Dependency

The testcontainers project itself has a dependency on JUnit4 although it is not needed for this project in order to run (see this issue for more details). To avoid pulling in JUnit4 this project comes with a dependency on the quarkus-junit4-mock library which includes all needed classes as empty stubs. If you need JUnit4 in your project you should exclude this mock library when declaring the dependency to testcontainers-keycloak to avoid issues. Example for maven:

<dependency>
    <!-- ... see above -->
    <exclusions>
        <exclusion>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-junit4-mock</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Usage in your application framework tests

This info is not specific to the Keycloak Testcontainer, but using Testcontainers generally.

I mention it here, as I see people asking again and again on how to use it in their test setup, when they think they need to specify a fixed port in their properties or YAML files...
You don't have to!
But you have to read the Testcontainers docs and the docs of your application framework on testing resources!!

Spring (Boot)

Dynamic context configuration with context initializers is your friend. In particular, look for @ContextConfiguration and ApplicationContextInitializer<ConfigurableApplicationContext>:

Quarkus

Read the docs about the Quarkus Test Resources and use @QuarkusTestResource with QuarkusTestResourceLifecycleManager

Others

Consult the docs of your application framework testing capabilities on how to dynamically configure your stack for testing!

YouTube Video about Keycloak Testcontainers

Testcontainers & Keycloak version compatiblity

For Keycloak versions until 21.x, see version 2.x branch

Testcontainers-Keycloak Testcontainers Keycloak
3.0.0 1.18.3 22.0
3.1.0 1.18.3 22.0.5
3.2.0 1.19.3 23.0
3.3.0 1.19.6 24.0

There might also be other possible version configurations which will work.

See also the Releases page for version and feature update notes.

Credits

Many thanks to the creators and maintainers of Testcontainers. You do an awesome job!

Same goes to the whole Keycloak team!

Kudos to @thomasdarimont for some inspiration for this project.

License

Apache License 2.0

Copyright (c) 2019-2023 Niko Köbler

See LICENSE file for details.

testcontainers-keycloak's People

Contributors

aivinog1 avatar carstenlenz avatar dasniko avatar everflux avatar gaetancollaud avatar hasalex avatar joshiste avatar martinleim avatar mkuchin avatar nils-christian avatar sventorben avatar thomasdarimont avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

testcontainers-keycloak's Issues

Add generics to the KeycloakContainer class

Description

Please add generics to the KeycloakContainer class and use them throughout the class.

public class KeycloakContainer<SELF extends KeycloakContainer<SELF>> extends GenericContainer<SELF> {
...
  public SELF withRealmImportFile(String importFile) {
    this.importFiles.add(importFile);
    return self();
  }
...

Motivation

In our tests we are using a custom implementation of the KeycloakContainer. It adds some additional behaviour (specific for our tests) as well as some additional methods. This works fine up until the point where we use the with-methods to configure the container, as one "looses" our custom class.

public final class MyCustomKeycloakContainer extends KeycloakContainer {

	public MyCustomKeycloakContainer( final String dockerImageName ) {
		super( dockerImageName );
	}
	public void myCustomMethod( ) {
		...
	}

}
@Container
private static final MyCustomKeycloakContainer keycloakContainer = ( MyCustomKeycloakContainer ) new MyCustomKeycloakContainer( "quay.io/keycloak/keycloak:18.0" )
		.withAdminUsername( "admin" )
		.withAdminPassword( "password" );

Details

Note that some other frameworks are using the generics as well. For example Postgresql:

public class PostgreSQLContainer<SELF extends PostgreSQLContainer<SELF>> extends JdbcDatabaseContainer<SELF>

Provide theme support

Like custom extensions, provide an option to include one or more custom themes to include to the testcontainer, so that one can add UI tests for custom themes.

Inject system properties into Docker environment

Description

Is there a way to inject -Dkeycloak.migration.strategy=OVERWRITE_EXISTING ?

Motivation

Further customization of docker setup to provide more flexible ways of tailoring the KC configuration.

Details

In our tests we need to override master realm with a predefined configuration file.

Unable to reuse the test container between tests with the new version 2.1.1 (KC 17)

Hello,

It seems since version 2.x test container cannot be reused between tests.
The next test cannot reuse the test container which was not stopped (stop() method not called).

We have an exception indicating the test realm cannot be imported (because already/previously imported)

2022-03-14 10:32:01,910 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (executor-thread-2) Unique index or primary key violation: "PRIMARY_KEY_62 ON PUBLIC.REALM(ID) VALUES ('test', 23)"; SQL statement:
insert into REALM (ACCESS_CODE_LIFESPAN, LOGIN_LIFESPAN, USER_ACTION_LIFESPAN, ACCESS_TOKEN_LIFESPAN, ACCESS_TOKEN_LIFE_IMPLICIT, ACCOUNT_THEME, ADMIN_EVENTS_DETAILS_ENABLED, ADMIN_EVENTS_ENABLED, ADMIN_THEME, ALLOW_USER_MANAGED_ACCESS, BROWSER_FLOW, CLIENT_AUTH_FLOW, DEFAULT_LOCALE, DEFAULT_ROLE, DIRECT_GRANT_FLOW, DOCKER_AUTH_FLOW, DUPLICATE_EMAILS_ALLOWED, EDIT_USERNAME_ALLOWED, EMAIL_THEME, ENABLED, EVENTS_ENABLED, EVENTS_EXPIRATION, INTERNATIONALIZATION_ENABLED, LOGIN_THEME, LOGIN_WITH_EMAIL_ALLOWED, MASTER_ADMIN_CLIENT, NAME, NOT_BEFORE, OFFLINE_SESSION_IDLE_TIMEOUT, OTP_POLICY_ALG, OTP_POLICY_DIGITS, OTP_POLICY_COUNTER, OTP_POLICY_WINDOW, OTP_POLICY_PERIOD, OTP_POLICY_TYPE, PASSWORD_POLICY, REFRESH_TOKEN_MAX_REUSE, REGISTRATION_ALLOWED, REG_EMAIL_AS_USERNAME, REGISTRATION_FLOW, REMEMBER_ME, RESET_CREDENTIALS_FLOW, RESET_PASSWORD_ALLOWED, REVOKE_REFRESH_TOKEN, SSL_REQUIRED, SSO_IDLE_TIMEOUT, SSO_IDLE_TIMEOUT_REMEMBER_ME, SSO_MAX_LIFESPAN, SSO_MAX_LIFESPAN_REMEMBER_ME, VERIFY_EMAIL, ID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [23505-197]

Could you please check that ?

Regards

Custom commands are overwritten by keycloak container

hello!

could it be, that a custom command for the KeycloakContainer like this:

...
keycloakContainer = new KeycloakContainer("quay.io/keycloak/keycloak:15.0.2"). withCopyFileToContainer().withCommand( "-c standalone.xml", "-b 0.0.0.0", "-Dkeycloak.profile.feature.upload_scripts=enabled", "-Dkeycloak.migration.action=import", "-Dkeycloak.migration.strategy=OVERWRITE_EXISTING", "-Dkeycloak.migration.provider=singleFile", "-Dkeycloak.migration.file=/tmp/keycloak.json" )
...

is overwritten in the configure() method of the KeycloakContainer class?

@Override protected void configure() { withCommand( "-c standalone.xml", // don't start infinispan cluster "-b 0.0.0.0", // ensure proper binding "-Dkeycloak.profile.feature.upload_scripts=enabled" // enable script uploads );

I debugged a little bit and my custom command is set correctly until the configure method is called. Maybe it's the same issue as it was for the PostgreSQLContainer mentioned here? --> https://github.com/testcontainers/testcontainers-java/pull/938/files# and here --> testcontainers/testcontainers-java#937

How to adjust "auth-server-url" at runtime

Hi @dasniko,

I really like your Keycloak Testcontainer. Is there an easy way to adjust the "keycloak.auth-server-url" property in my "application.yaml" in my integration tests at runtime? Because otherwise, my application does not know how it could validate e.g. a given access token.

My workaround was to customize your Java class "KeycloakContainer" and change this class to extend FixedHostPortGenericContainer instead of GenericContainer. However, it seems to me that I should not be the only one (hopefully ;-) with this problem.

My current project setup:

  • Spring Boot (Java)
  • Spock testing framework (Groovy)

Thank you in advance.

BR
Niklas

Can't update from 1.9.0 to 2.5; Can't load realm

Describe the bug

I'm looking at updating my testcontainer for keycloak from 1.9.0 to 2.5.0. Unfortunately, this comes up with problems.

Initially, I get the following error:

Failed to migrate json representation for version: 21.0.0: java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "adminTheme" is null

From this, I add the "adminTheme": "keycloak" entry in my keycloak-realm.json file, but then I get an additional error:

[org.keycloak.services] (main) KC-SERVICES0050: Initializing master realm
INFO  [org.keycloak.exportimport.dir.DirImportProvider] (main) Importing from directory /opt/keycloak/bin/../data/import
INFO  [org.keycloak.exportimport.util.ImportUtils] (main) Realm 'apps' imported
ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to start server in (development) mode
ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Script upload is disabled

I have tried enabling that feature with .withFeaturesEnabled("upload_scripts") on my container object, but no help there.

Any ideas?

Version

2.5

Expected behavior

No response

Actual behavior

No response

How to Reproduce?

No response

Relevant log output

No response

Anything else?

No response

How to obtain client secret key from the imported keycloak file

Hello,

I am currently using the Keycloak-Testcontainer.
I have instantiated my keycloak test container by importing a keycloak file. The keycloak file has the client secret anonymized but I have a copy of it. The problem is when I try to get the token by injecting the client secret, I am consistently getting an error that the client secret is invalid. It seems the imported file wasn't properly mounted or perhaps, it does change the client secret. Not sure why this is the situation. Could someone help clarify this for me?

Thanks

Not enough / duplicate Junit Classes in Jar

I've tried updating to 2.0 of testcontainers-keycloak and stumbled over the now included junit4 classes (b3ce4dc) .
As part of our build we use a plugin that verifies that classes only appear in one jar and this of course conflicted with the jars already in junit:junit that where pulled in via testcontainers.

I tried excluding junit:junit from my build but as a result of that I startet to get java.lang.NoClassDefFoundError: org/junit/rules/ExternalResource via org.testcontainers.containers.Network.NetworkImpl. It seems you copied over some of the classes, but not all required by Testcontainers.

I've seen the junit4 issue at testcontainers github: testcontainers/testcontainers-java#970 . What do you think about including a dependency on https://github.com/quarkusio/quarkus/tree/main/core/junit4-mock instead of copying the junit classes to your jar? That way you wouldn't have to include junit sources and would give the projects that use your library the option to choose where they get their currently still necessary junit 4 classes from.

Binding in wrong interface.

There is a bug with user-defined network. If this network name alphabetically is after default "bridge", then container is available only in this network. But if network name alphabetically is before "bridge", then container is available in this network and from host too.
In testcontainers network name is UUID, so these tests are flaky.

Sergei Egorov from testcontainers noticed that a container binds on wrong interface and starting container with a command

.withCommand(
                "-c standalone.xml",
                "-b 0.0.0.0",
                "-Dkeycloak.profile.feature.upload_scripts=enabled"
            )

solves the problem.

Example can be found here (it uses GenericContainer, but can be easily applied to KeycloakContainer):
https://github.com/wirtsleg/testcontainers-network-bug

Add option to add 3rd party libraries to classpath

When testing extensions with .withExtensionClassesFrom() it might become necessary to add 3rd party libs as dependencies to the classpath, as the extensions rely on these libraries. Currently that's not possible.

A method like .withExtensionLibsFrom() might be a good solution.

(this issue is deviated from discussion #57)

Deployment of extension classes fail when Keycloak testcontainer runs on a remote docker host

First of great work on creating this very useful test container! I do however hit a bump. When the Keycloak testcontainer is spawned on a remote docker host, the extension classes are never deployed. I suspect it has to do with the addFileSystemBind which is registered on the directory. This directory is not present on the host where the Keycloak testcontainer is running.

NoSuchMethodError when upgrading to 2.1

I get the following exception after upgrading from version 2.0 to 2.1:

java.lang.NoSuchMethodError: 'org.jboss.resteasy.spi.ResteasyProviderFactory org.jboss.resteasy.plugins.providers.RegisterBuiltin.getClientInitializedResteasyProviderFactory(java.lang.ClassLoader)'

	at org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl.getProviderFactory(ResteasyClientBuilderImpl.java:377)
	at org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl.register(ResteasyClientBuilderImpl.java:479)
	at dasniko.testcontainers.keycloak.KeycloakContainer.getKeycloakAdminClient(KeycloakContainer.java:328)
	at dasniko.testcontainers.keycloak.KeycloakContainer.containerIsStarted(KeycloakContainer.java:184)
	at org.testcontainers.containers.GenericContainer.containerIsStarted(GenericContainer.java:688)
	at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:504)
	at org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:331)
	at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:81)
	at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:329)
	at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:317)
	at org.testcontainers.junit.jupiter.TestcontainersExtension$StoreAdapter.start(TestcontainersExtension.java:242)
	at org.testcontainers.junit.jupiter.TestcontainersExtension$StoreAdapter.access$200(TestcontainersExtension.java:229)
	at org.testcontainers.junit.jupiter.TestcontainersExtension.lambda$null$1(TestcontainersExtension.java:59)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore.lambda$getOrComputeIfAbsent$4(ExtensionValuesStore.java:86)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.computeValue(ExtensionValuesStore.java:223)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.get(ExtensionValuesStore.java:211)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore$StoredValue.evaluate(ExtensionValuesStore.java:191)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore$StoredValue.access$100(ExtensionValuesStore.java:171)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore.getOrComputeIfAbsent(ExtensionValuesStore.java:89)
	at org.junit.jupiter.engine.execution.NamespaceAwareStore.getOrComputeIfAbsent(NamespaceAwareStore.java:53)
	at org.testcontainers.junit.jupiter.TestcontainersExtension.lambda$beforeAll$2(TestcontainersExtension.java:59)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507)
	at org.testcontainers.junit.jupiter.TestcontainersExtension.beforeAll(TestcontainersExtension.java:59)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeBeforeAllCallbacks$10(ClassBasedTestDescriptor.java:381)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeBeforeAllCallbacks(ClassBasedTestDescriptor.java:381)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:205)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:80)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:148)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
	at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)

Check this build or this PR for details.

I already tried to remove the explicit dependency to keycloak-admin-client, but that did not help either.

How to include local dependency

Hi, thank you for the great project.

How can I include my local dependency together with the extension I want to test?

Example:

  • extension
    • src/main/...
    • src/test/...
  • another-extension
    • src/main/...
  • core
    • src/main/...

I want to test my extension, which has a dependency to my core package e.g. some exception or util classes.
When I start the testcontainer test in the extension/src/test while passing withExtensionClassesFrom("target/classes") I get an error org.jboss.modules.ModuleNotFoundException: core.exception.

Maybe we can define multiple paths for withExtensionClassesFrom?

new Container is always started even with reuse enabled

Hi!

I face the issue that always a new container get's started (while the one from the prev test run is still running).
For other containers (pgSQL, min.io) the withReuse feature works as expected therefore I think it is not a general problem with my local setup.

I update to version 2.1.2 today as I saw some changes regarding withReuse in that release - but nothing changed.

I start the container with the following code:

keycloakContainer = new KeycloakContainer()
                .withRealmImportFile("/realm.json")
                .withProviderClassesFrom("target/test-classes")
                .withReuse(true);

keycloakContainer.start();

While debugging in I found out that testcontainers compares a hash on the running containers against the start command of the container you want to start to see if a container instance is found that can be re-used.

For two runs I extracted the JSON on which this hash is calculated and found the following difference:
"org.testcontainers.copied_files.hash": "21ab144e"
-> So the hash of the files copied to the container seems to be different

I analyzed further how this has is calculated and ended up in GenericContainer.hashCopiedFiles() there is a map copyToFileContainerPathMap that contains files that are copied to the container.
That map contains exactly one file that is a providers.jar. It seems this jar is dynamically generated

image

Is there a way to keep this "stable" between two runs so that the hash would be the same?

Resteasy exception when using Keycloak Admin Client

Describe the bug

I'm using the following test code to create a Keycloak testcontainer and get the admin client:

@Testcontainers
public class OrganizationResourceTest {

  @Container KeycloakContainer server = new KeycloakContainer().withContextPath("/auth/").withProviderClassesFrom("target/classes");

  Keycloak getKeycloak() {
    assertTrue(server.isRunning());
    return server.getKeycloakAdminClient();
  }

  @Test
  public void testCreateDeleteOrg() throws Exception {
    Keycloak keycloak = getKeycloak();
    ...

After the containers start up, I get the following error:

[ERROR] io.phasetwo.service.resources.OrganizationResourceTest.testCreateDeleteOrg  Time elapsed: 69.911 s  <<< ERROR!
java.lang.InstantiationError: org.jboss.resteasy.spi.ResteasyProviderFactory
	at org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder.getProviderFactory(ResteasyClientBuilder.java:405)
	at org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder.register(ResteasyClientBuilder.java:559)
	at org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder.register(ResteasyClientBuilder.java:48)
	at org.keycloak.admin.client.spi.ResteasyClientClassicProvider.newRestEasyClient(ResteasyClientClassicProvider.java:40)
	at org.keycloak.admin.client.Keycloak.newRestEasyClient(Keycloak.java:98)
	at org.keycloak.admin.client.Keycloak.getInstance(Keycloak.java:110)
	at org.keycloak.admin.client.Keycloak.getInstance(Keycloak.java:126)
	at dasniko.testcontainers.keycloak.KeycloakContainer.getKeycloakAdminClient(KeycloakContainer.java:318)
	at io.phasetwo.service.resources.OrganizationResourceTest.getKeycloak(OrganizationResourceTest.java:57)
	at io.phasetwo.service.resources.OrganizationResourceTest.testCreateDeleteOrg(OrganizationResourceTest.java:73)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
	at org.apache.maven.surefire.junitplatform.LazyLauncher.execute(LazyLauncher.java:55)
	at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:223)
	at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:175)
	at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:139)
	at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:456)
	at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:169)
	at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:595)
	at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:581)

here are my dependencies

    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter</artifactId>
      <version>5.9.0</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.testcontainers</groupId>
      <artifactId>testcontainers</artifactId>
      <version>1.17.3</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.testcontainers</groupId>
      <artifactId>junit-jupiter</artifactId>
      <version>1.17.3</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.github.dasniko</groupId>
      <artifactId>testcontainers-keycloak</artifactId>
      <version>2.3.0</version>
      <scope>test</scope>
    </dependency>

Any ideas on what is happening?

Version

2.3.0

Expected behavior

The admin client should instantiate without error.

Actual behavior

See exception

How to Reproduce?

run mvn clean install in this branch https://github.com/p2-inc/keycloak-orgs/tree/testcontainers

Relevant log output

see description

Anything else?

No response

The elements [keycloak.client-id] were left unbound.

Hi,

Could you please help with the above error, I am not sure what I am doing wrong. Please ask if you want me to provide any more info/code

Initializer:

public class KeyCloakTestContext implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    KeycloakContainer keycloakContainer;

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        keycloakContainer = new KeycloakContainer();
        keycloakContainer.withAdminUsername("john").withAdminPassword("pw");
        keycloakContainer.start();

        System.setProperty("keycloak.auth-server-url", keycloakContainer.getAuthServerUrl());
        System.setProperty("keycloak.realm", "SpringBootKeycloak");
        System.setProperty("keycloak.resource", "login-app");
        System.setProperty("keycloak.public-client", "true");
        System.setProperty("keycloak.client-id", "hi");
    }
}

Test class:

@SpringBootTest(
        classes = TaxApplication.class,
        webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Testcontainers
@ContextConfiguration(initializers = KeyCloakTestContext.class)
class Testy {

    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    AccessTokenProvider accessTokenProvider;

    @Container
    public static CustomMySqlContainer mySqlContainer = CustomMySqlContainer.getInstance().withInitScript("database/schema.sql");

    @Container
    private KeycloakContainer keycloak = new KeycloakContainer("jboss/keycloak:15.0.2");
    @Test
    public void test_endpoint() {

        String token = accessTokenProvider.getAccessToken("john", "pw", "hi", "SpringBootKeycloak");
        restTemplate.getRestTemplate().setInterceptors(
                Collections.singletonList((request, body, execution) -> {
                    request.getHeaders()
                            .add("Authorization", "Bearer "+token);
                    return execution.execute(request, body);
                }));

        ResponseEntity<String> customerResponse = restTemplate.getForEntity("/api/test", String.class);

        assertThat(customerResponse.getStatusCode(), is(HttpStatus.OK));

    }
}

application.properties file

keycloak.auth-server-url=http://localhost:8000
keycloak.realm=SpringBootKeycloak
keycloak.resource=login-app
keycloak.client-id=hi
keycloak.public-client=true

Error

Binding to target [Bindable@68f2363 type = org.keycloak.adapters.springboot.KeycloakSpringBootProperties, value = 'provided', annotations = array<Annotation>[@org.springframework.boot.context.properties.ConfigurationProperties(ignoreInvalidFields=false, ignoreUnknownFields=false, prefix=keycloak, value=keycloak)]] failed:

    Property: keycloak.client-id
    Value: hi
    Origin: class path resource [application.properties] - 4:20
    Reason: The elements [keycloak.client-id] were left unbound.

Action:

Update your application's configuration

Add DB_VENDOR=h2 environment variable as a default setting

The Keycloak Docker container has some "DNS magic" to determine which database to use, if there is a host with a specific name on the network. This yields into startup errors for various users, depending on their netowrk, VPN, DNS, etc. There are multiple reasons for that.

As the Keycloak Testcontainer doesn't need an external DB and should only use the internal built-in DB h2, the usage of this DB should be forced. This can be achieved by setting the environment variable DB_VENDOR to the value h2.

If one really wants or needs to use the testcontainer with another DB, the user still could override the value as desired.

Configurable command and cli args

Description

It would be nice if the command to run could be configured: Currently "start-dev" is hard-coded, which is great for most testing scenarios. But for some scenarios it would be better to have a more production-like setup, where it makes sense to use the "start" command.

Furthermore, it would be nice, if arbitrary CLI args could be configured for the command.

Motivation

After updating testcontainers-keycloak to the latest version (from 2.1.2 to 2.3.0), most of our selenium tests (running against our keycloak extensions) failed. It turned out that they were failing because the account page loaded seemingly forever...
Then I checked what changed in testcontainers-keycloak and found that the command changed from "start" to "start-dev", which amongst other things, disables the cache.

With the following workaround, I explicitly enabled the cache and the selenium tests ran fine again:

public class KeycloakXContainer extends KeycloakContainer {

    public KeycloakXContainer(final String dockerImageName) {
        super(dockerImageName);
    }

    @Override
    protected void configure() {
        super.configure();

        customConfigure();
    }

    private void customConfigure() {
        var commandParts = getCommandParts();
       ...

        /*
         * Have to enable theme caching (which is disabled in dev by default): otherwise pages load too slow, leading to
         * many UI test failures.
         */
        var updatedCommandParts = new ArrayList<>(Arrays.asList(commandParts));
        updatedCommandParts.add("--spi-theme-cache-themes=true");
        updatedCommandParts.add("--spi-theme-cache-templates=true");
        updatedCommandParts.add("--spi-theme-static-max-age=2592000");

        setCommandParts(updatedCommandParts.toArray(new String[0]));
    }

}

Details

If you think this extension could also be useful for others, I would be happy to implement a PR.

Image name substitution not working

Describe the bug

I tried to use the the testcontainers-keycloak extension with an automatic image name substitution, but it turns out this doesn't work. I want to add a prefix to the image name from the property hub.image.name.prefix which is defined in a testcontainers.properties file inside my test resource folder, but the prefix is not added.

Version

2.2.2

Expected behavior

The prefix from the property hub.image.name.prefix should be added to the image name.

Actual behavior

The prefix from the property hub.image.name.prefix is not added to the image name.

How to Reproduce?

No response

Relevant log output

No response

Anything else?

In addition to the keycloak container I have a MongoDbContainer and a GenericContainer from the testcontainers library in my integration tests. With those the image name substitution works fine.

DB_ADDR: unbound variable

I grabbed the latest from master, loaded it into eclipse, and tried to execute KeycloakContainerTest.java but the container failed to start.

I thought it had worked for me the first time, but I have no idea why it would suddenly stop working, and so I'm guessing that I had just missed the log output that said it failed.

14:00:50.987 [main] INFO  org.testcontainers.dockerclient.DockerClientProviderStrategy - Loaded org.testcontainers.dockerclient.UnixSocketClientProviderStrategy from ~/.testcontainers.properties, will try it first
14:00:51.814 [main] INFO  org.testcontainers.dockerclient.DockerClientProviderStrategy - Found Docker environment with local Unix socket (unix:///var/run/docker.sock)
14:00:51.815 [main] INFO  org.testcontainers.DockerClientFactory - Docker host IP address is localhost
14:00:51.870 [main] INFO  org.testcontainers.DockerClientFactory - Connected to docker: 
  Server Version: 19.03.13
  API Version: 1.40
  Operating System: Docker Desktop
  Total Memory: 7962 MB
14:00:51.875 [main] INFO  org.testcontainers.utility.ImageNameSubstitutor - Image name substitution will be performed by: DefaultImageNameSubstitutor (composite of 'ConfigurationFileImageNameSubstitutor' and 'PrefixingImageNameSubstitutor')
14:00:52.915 [main] INFO  org.testcontainers.DockerClientFactory - Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
14:00:52.915 [main] INFO  org.testcontainers.DockerClientFactory - Checking the system...
14:00:52.916 [main] INFO  org.testcontainers.DockerClientFactory - ✔︎ Docker server version should be at least 1.6.0
14:00:53.064 [main] INFO  org.testcontainers.DockerClientFactory - ✔︎ Docker environment should have more than 2GB free disk space
14:00:53.424 [main] INFO  🐳 [quay.io/keycloak/keycloak:12.0.1] - Creating container for image: quay.io/keycloak/keycloak:12.0.1
14:00:53.558 [main] INFO  🐳 [quay.io/keycloak/keycloak:12.0.1] - Starting container with ID: 6d5668aa062ba6c8bb4fb6df85fad14149e750c75fd76c9ffd0f0eaf29a49602
14:00:54.016 [main] INFO  🐳 [quay.io/keycloak/keycloak:12.0.1] - Container quay.io/keycloak/keycloak:12.0.1 is starting: 6d5668aa062ba6c8bb4fb6df85fad14149e750c75fd76c9ffd0f0eaf29a49602
14:00:54.037 [main] INFO  org.testcontainers.containers.wait.strategy.HttpWaitStrategy - /dazzling_williamson: Waiting for 120 seconds for URL: http://localhost:32840/auth
14:02:54.063 [main] ERROR 🐳 [quay.io/keycloak/keycloak:12.0.1] - Could not start container
java.lang.IllegalStateException: Container exited with code 1
	at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:469)
	at org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:325)
	at org.testcontainers.containers.GenericContainer$$Lambda$160/0x0000000000000000.call(Unknown Source)
	at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:81)
	at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:323)
	at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:311)
	at dasniko.testcontainers.keycloak.KeycloakContainerTest.shouldStartKeycloak(KeycloakContainerTest.java:21)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
14:02:54.108 [main] ERROR 🐳 [quay.io/keycloak/keycloak:12.0.1] - Log output from the failed container:
Added 'admin' to '/opt/jboss/keycloak/standalone/configuration/keycloak-add-user.json', restart server to load user

/opt/jboss/tools/docker-entrypoint.sh: line 165: DB_ADDR: unbound variable

Fix docker-compose command

I am trying to set up a keycloak service with docker-compose. For this I need several commands. But in the source code everything under "command" is treated as string. So an exception is raised during casting.

Location:

package org.lorislab.quarkus.testcontainers;
line: (86)
command = (String) data.get("command");

The problem is that the result is not a string but an ArrayList of strings.

Admin client cannot connect when TLS is enabled

Describe the bug

When the container is started with the useTls() option, the admin client is not able to connect.

Version

2.2.1

Expected behavior

No response

Actual behavior

No response

How to Reproduce?

    @Test
    public void shouldAdminClientBeAbleToConnect() {
        try (KeycloakContainer keycloak = new KeycloakContainer().useTls()) {
            keycloak.start();

            Keycloak admin = keycloak.getKeycloakAdminClient();
            ServerInfoResource serverInfoResource = admin.serverInfo();
            assertNotNull(serverInfoResource.getInfo());
        }
    }

Relevant log output

javax.ws.rs.ProcessingException: RESTEASY004655: Unable to invoke request: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:328)
	at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:443)
	at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:149)
	at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:112)
	at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76)
	at jdk.proxy2/jdk.proxy2.$Proxy36.grantToken(Unknown Source)
	at org.keycloak.admin.client.token.TokenManager.grantToken(TokenManager.java:98)
	at org.keycloak.admin.client.token.TokenManager.getAccessToken(TokenManager.java:74)
	at org.keycloak.admin.client.token.TokenManager.getAccessTokenString(TokenManager.java:69)
	at org.keycloak.admin.client.resource.BearerAuthFilter.filter(BearerAuthFilter.java:52)
	at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.filterRequest(ClientInvocation.java:579)
	at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:440)
	at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:149)
	at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:112)
	at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76)
	at jdk.proxy2/jdk.proxy2.$Proxy38.getInfo(Unknown Source)
	at dasniko.testcontainers.keycloak.KeycloakContainerHttpsTest.shouldAdminClientBeAbleToConnect(KeycloakContainerHttpsTest.java:83)
	at ...
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
	at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
	at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
	at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
	... 103 more

Anything else?

Can be solved with a SSLContext.

Nullpointer Exception while copying archive to container (with Java 17)

Hi i get currently the following error when i start the Keycloak container with a custom RealmResourceProvider in the source folder

09:38:26.373 [main] DEBUG com.github.dockerjava.zerodep.ApacheDockerHttpClientImpl$ApacheResponse - Failed to close the response java.nio.channels.ClosedChannelException: null at java.base/sun.nio.ch.SocketChannelImpl.ensureOpenAndConnected(SocketChannelImpl.java:215) at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:403) at java.base/sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:59) at java.base/sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:107) at java.base/sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:101) at com.github.dockerjava.zerodep.shaded.org.apache.hc.client5.http.impl.io.LoggingInputStream.read(LoggingInputStream.java:81) at com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:149) at com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:280) at com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.impl.io.ChunkedInputStream.getChunkSize(ChunkedInputStream.java:261) at com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.impl.io.ChunkedInputStream.nextChunk(ChunkedInputStream.java:222) at com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:183) at com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:210) at com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.impl.io.ChunkedInputStream.close(ChunkedInputStream.java:319) at com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.io.Closer.close(Closer.java:48) at com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.impl.io.IncomingHttpEntity.close(IncomingHttpEntity.java:111) at com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.io.entity.HttpEntityWrapper.close(HttpEntityWrapper.java:120) at com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.io.Closer.close(Closer.java:48) at com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.message.BasicClassicHttpResponse.close(BasicClassicHttpResponse.java:93) at com.github.dockerjava.zerodep.shaded.org.apache.hc.client5.http.impl.classic.CloseableHttpResponse.close(CloseableHttpResponse.java:200) at com.github.dockerjava.zerodep.ApacheDockerHttpClientImpl$ApacheResponse.close(ApacheDockerHttpClientImpl.java:248) at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.put(DefaultInvocationBuilder.java:223) at org.testcontainers.shaded.com.github.dockerjava.core.exec.CopyArchiveToContainerCmdExec.execute(CopyArchiveToContainerCmdExec.java:32) at org.testcontainers.shaded.com.github.dockerjava.core.exec.CopyArchiveToContainerCmdExec.execute(CopyArchiveToContainerCmdExec.java:13) at org.testcontainers.shaded.com.github.dockerjava.core.exec.AbstrSyncDockerCmdExec.exec(AbstrSyncDockerCmdExec.java:21) at org.testcontainers.shaded.com.github.dockerjava.core.command.AbstrDockerCmd.exec(AbstrDockerCmd.java:35) at org.testcontainers.shaded.com.github.dockerjava.core.command.CopyArchiveToContainerCmdImpl.exec(CopyArchiveToContainerCmdImpl.java:154) at org.testcontainers.containers.ContainerState.copyFileToContainer(ContainerState.java:284) at org.testcontainers.containers.ContainerState.copyFileToContainer(ContainerState.java:253) at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:416) at org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:331) at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:81) at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:329) at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:317) at com.cubic.cumo.keycloak.endpoint.RegisterAccountRealmResourceProviderTest.shouldDeployProviderAndCallCustomEndpoint(RegisterAccountRealmResourceProviderTest.java:22) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725) at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84) at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115) at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86) at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86) at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53) at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71) at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38) at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

Extension packaging seems to rely on maven to be in use

When trying to startup a test keycloak container to test a rest extension, in this part it seems to assume Maven is being used.
When using gradle, I get this exception:

Caused by: java.nio.file.NoSuchFileException: target/keycloak13563541036773513476.jar
	at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92)
	at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
	at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116)
	at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:219)
	at java.base/java.nio.file.Files.newByteChannel(Files.java:370)
	at java.base/java.nio.file.Files.createFile(Files.java:647)
	at java.base/java.nio.file.TempFileHelper.create(TempFileHelper.java:137)
	at java.base/java.nio.file.TempFileHelper.createTempFile(TempFileHelper.java:160)
	at java.base/java.nio.file.Files.createTempFile(Files.java:867)
	at dasniko.testcontainers.keycloak.KeycloakContainer.createKeycloakExtensionDeployment(KeycloakContainer.java:220)

The problematic assumption IMO is here:
https://github.com/dasniko/testcontainers-keycloak/blob/2.1.1/src/main/java/dasniko/testcontainers/keycloak/KeycloakContainer.java#L220

There are some references in README.md to paths that also assume the use of Maven, in this related block:
https://github.com/dasniko/testcontainers-keycloak/blob/main/README.md?plain=1#L165

For a gradle build, it works with "java/main" rather than "target/classes".

I've found an easy workaround, which I'm using until this is fixed: to create a target folder in the root of the module/application where the test will run.

I hope this helps, and thanks for the amazing plugin, it's helping me a lot!

Container not starting when run on M1 chip

I get the following error when running application tests:
11:30:56.050 [main] ERROR 🐳 [quay.io/keycloak/keycloak:15.0.2] - Could not start container org.testcontainers.containers.ContainerLaunchException: Timed out waiting for URL to be accessible (http://localhost:50853/auth should return HTTP 200)

Application was also not starting when using image jboss/keycloak. I was able to resolve this by using image wizzn/keycloak:14 locally.

Any workarounds available?

Failed to read realm JSON file with the new version 2.1.1 (and thus KC 17)

Hello,

I was using KC test container for a while.
It was working correctly with the version 1.9.0.
Then I deciced today to test it with version 2.1.1 (and thus KC 17)
image
but KC does not want to start anymore, I have the exception :

`22-03-13 17:26:58.031 / INFO --- [eam--1508215392] 🐳 [quay.io/keycloak/keycloak:17.0.0] : STDOUT: 2022-03-13 16:21:53,586 INFO [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, infinispan-client, jdbc-h2, jdbc-mariadb, jdbc-mssql, jdbc-mysql, jdbc-oracle, jdbc-postgresql, keycloak, narayana-jta, reactive-routes, resteasy, resteasy-jackson, smallrye-context-propagation, smallrye-health, smallrye-metrics, vault, vertx]
2022-03-13 17:26:58.041 / INFO --- [ main] o.t.c.wait.strategy.HttpWaitStrategy : /gracious_lederberg: Waiting for 120 seconds for URL: http://localhost:56189/ (where port 56189 maps to container port 8080)
2022-03-13 17:26:58.082 / INFO --- [ main] 🐳 [quay.io/keycloak/keycloak:17.0.0] : Container quay.io/keycloak/keycloak:17.0.0 started in PT1.3515094S
2022-03-13 17:26:58.082 / INFO --- [ main] 🐳 [quay.io/keycloak/keycloak:17.0.0] : Connect to Keycloak container to import given realm files.
2022-03-13 17:26:58.685 / INFO --- [ main] 🐳 [quay.io/keycloak/keycloak:17.0.0] : Importing realm from file keycloak-test-realm.json
2022-03-13 17:26:58.821 / ERROR --- [ main] 🐳 [quay.io/keycloak/keycloak:17.0.0] : Could not start container

java.lang.IllegalArgumentException: argument "src" is null
at com.fasterxml.jackson.databind.ObjectMapper._assertNotNull(ObjectMapper.java:4757)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3478)
at dasniko.testcontainers.keycloak.KeycloakContainer.containerIsStarted(KeycloakContainer.java:185)
at org.testcontainers.containers.GenericContainer.containerIsStarted(GenericContainer.java:688)
at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:504)
at org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:331)
at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:81)
at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:329)
at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:317)
at ch.hcuge.keycloak.test.extension.KeyCloakTestContainerExtension.beforeAll(KeyCloakTestContainerExtension.java:63)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeBeforeAllCallbacks$10(ClassBasedTestDescriptor.java:381)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeBeforeAllCallbacks(ClassBasedTestDescriptor.java:381)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:205)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:80)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:148)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:95)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:91)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:60)
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:98)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
`

It seems it failed while importing my realm JSON (cf. attached file)
keycloak-test-realm.json.txt

Test extension :
image

Errors when trying to import realm from a folder

Describe the bug

When I'm trying to import a realm file from a folder:

KeycloakContainer keycloak = new KeycloakContainer().withRealmImportFile("/single-test-folder/test-realm.json");

My container didn't start and I got such errors in the container:

16:36:34.212 [docker-java-stream-438386004] INFO  🐳 [quay.io/keycloak/keycloak:18.0.0] - STDOUT: 2022-04-29 09:36:34,218 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to start server in (development) mode
16:36:34.221 [docker-java-stream-438386004] INFO  🐳 [quay.io/keycloak/keycloak:18.0.0] - STDOUT: 2022-04-29 09:36:34,219 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to parse realm configuration file: /opt/keycloak/bin/../data/import/single-test-folder
16:36:34.221 [docker-java-stream-438386004] INFO  🐳 [quay.io/keycloak/keycloak:18.0.0] - STDOUT: 2022-04-29 09:36:34,228 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Is a directory
16:36:34.223 [docker-java-stream-438386004] INFO  🐳 [quay.io/keycloak/keycloak:18.0.0] - STDOUT: 2022-04-29 09:36:34,230 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) For more details run the same command passing the '--verbose' option. Also you can use '--help' to see the details about the usage of the particular command.

In the 2.1.2 version, everything works fine.

Version

2.2.0

Expected behavior

I'm expecting that the container correctly imports realm files from classpath with a directory.

Actual behavior

The container crushes.

How to Reproduce?

KeycloakContainer keycloak = new KeycloakContainer().withRealmImportFile("/single-test-folder/test-realm.json");
keycloak.start();

Also, I will provide test cases in a draft PR: #74.

Relevant log output

16:36:34.212 [docker-java-stream-438386004] INFO  🐳 [quay.io/keycloak/keycloak:18.0.0] - STDOUT: 2022-04-29 09:36:34,218 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to start server in (development) mode
16:36:34.221 [docker-java-stream-438386004] INFO  🐳 [quay.io/keycloak/keycloak:18.0.0] - STDOUT: 2022-04-29 09:36:34,219 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to parse realm configuration file: /opt/keycloak/bin/../data/import/single-test-folder
16:36:34.221 [docker-java-stream-438386004] INFO  🐳 [quay.io/keycloak/keycloak:18.0.0] - STDOUT: 2022-04-29 09:36:34,228 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Is a directory
16:36:34.223 [docker-java-stream-438386004] INFO  🐳 [quay.io/keycloak/keycloak:18.0.0] - STDOUT: 2022-04-29 09:36:34,230 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) For more details run the same command passing the '--verbose' option. Also you can use '--help' to see the details about the usage of the particular command.


### Anything else?

_No response_

"Cannot remove extraneous deployment marker file" leads to strange behavior

I enabled the experimental testcontainers "withReuse" option and, after my tests completed, I went to check out the still-running container.

What I found is general flakiness. For example, after login, it would say the admin console page doesn't exist / couldn't be found. Then, after a refresh, it would work pretty well. Occasionally I would see an intermittent error on the UI, but it was still usage.

I dug into the logs to look for errors and I found the following output was repeated over and over again, basically drowning everything else out:

22:27:55,896 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-4) WFLYSRV0027: Starting deployment of "-495401560-extensions.jar" (runtime-name: "-495401560-extensions.jar")
22:27:55,971 WARN  [org.jboss.as.dependency.private] (MSC service thread 1-3) WFLYSRV0018: Deployment "deployment.-495401560-extensions.jar" is using a private module ("org.keycloak.keycloak-services") which may be changed or removed in future versions without notice.
22:27:55,976 INFO  [org.keycloak.subsystem.server.extension.KeycloakProviderDeploymentProcessor] (MSC service thread 1-3) Deploying Keycloak provider: -495401560-extensions.jar
22:27:55,990 WARN  [org.keycloak.services] (MSC service thread 1-3) KC-SERVICES0047: audience-validator (org.alvearie.keycloak.AudienceValidatorFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
22:27:55,991 WARN  [org.keycloak.services] (MSC service thread 1-3) KC-SERVICES0047: auth-select-patient (org.alvearie.keycloak.PatientSelectionFormFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
22:27:56,063 WARN  [org.keycloak.services] (MSC service thread 1-3) KC-SERVICES0047: oidc-patient-prefix-usermodel-attribute-mapper (org.alvearie.keycloak.PatientPrefixUserAttributeMapper) is implementing the internal SPI protocol-mapper. This SPI is internal and may change without notice
22:27:56,063 WARN  [org.keycloak.services] (MSC service thread 1-3) KC-SERVICES0047: oidc-usermodel-attribute-mapper-with-token-response-support (org.alvearie.keycloak.UserAttributeMapper) is implementing the internal SPI protocol-mapper. This SPI is internal and may change without notice
22:27:56,199 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 1) WFLYSRV0016: Replaced deployment "-495401560-extensions.jar" with deployment "-495401560-extensions.jar"
22:27:56,200 WARN  [org.jboss.as.server.deployment.scanner] (DeploymentScanner-threads - 2) WFLYDS0002: Cannot remove extraneous deployment marker file /opt/jboss/keycloak/standalone/deployments/-495401560-extensions.jar.dodeploy
22:28:01,225 INFO  [org.keycloak.subsystem.server.extension.KeycloakProviderDeploymentProcessor] (MSC service thread 1-6) Undeploying Keycloak provider: -495401560-extensions.jar
22:28:01,245 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-4) WFLYSRV0028: Stopped deployment -495401560-extensions.jar (runtime-name: -495401560-extensions.jar) in 23ms
22:28:01,246 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-3) WFLYSRV0027: Starting deployment of "-495401560-extensions.jar" (runtime-name: "-495401560-extensions.jar")
22:28:01,318 WARN  [org.jboss.as.dependency.private] (MSC service thread 1-6) WFLYSRV0018: Deployment "deployment.-495401560-extensions.jar" is using a private module ("org.keycloak.keycloak-services") which may be changed or removed in future versions without notice.
22:28:01,323 INFO  [org.keycloak.subsystem.server.extension.KeycloakProviderDeploymentProcessor] (MSC service thread 1-6) Deploying Keycloak provider: -495401560-extensions.jar
22:28:01,336 WARN  [org.keycloak.services] (MSC service thread 1-6) KC-SERVICES0047: audience-validator (org.alvearie.keycloak.AudienceValidatorFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
22:28:01,336 WARN  [org.keycloak.services] (MSC service thread 1-6) KC-SERVICES0047: auth-select-patient (org.alvearie.keycloak.PatientSelectionFormFactory) is implementing the internal SPI authenticator. This SPI is internal and may change without notice
22:28:01,396 WARN  [org.keycloak.services] (MSC service thread 1-6) KC-SERVICES0047: oidc-patient-prefix-usermodel-attribute-mapper (org.alvearie.keycloak.PatientPrefixUserAttributeMapper) is implementing the internal SPI protocol-mapper. This SPI is internal and may change without notice
22:28:01,397 WARN  [org.keycloak.services] (MSC service thread 1-6) KC-SERVICES0047: oidc-usermodel-attribute-mapper-with-token-response-support (org.alvearie.keycloak.UserAttributeMapper) is implementing the internal SPI protocol-mapper. This SPI is internal and may change without notice
22:28:01,488 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 1) WFLYSRV0016: Replaced deployment "-495401560-extensions.jar" with deployment "-495401560-extensions.jar"
22:28:01,491 WARN  [org.jboss.as.server.deployment.scanner] (DeploymentScanner-threads - 2) WFLYDS0002: Cannot remove extraneous deployment marker file /opt/jboss/keycloak/standalone/deployments/-495401560-extensions.jar.dodeploy
...

I'm not sure if the constantly reloading is a feature or a bug, but when I dug in I found that the reason it cannot delete the deployment marker file is that this file is a direct mount point.

When I fixed it locally, by mounting a directory instead of just the file, the container started to behave perfectly...no more wonkiness.

"endpoint with name XX already exists in network bridge" while running withReuse

I can't tell if this is something specific to testcontainers-keycloak or a more generic testcontainers issue, but figured I'd start here.

Previously, I was able to call withReuse(true) on my KeycloakContainer (before starting it) and it would let me re-use the same container from one run to the next which was very useful to reduce the cycle time on test development.

Now, when I try the same thing, everything after the first run is failing with an error like this:

13:07:40.153 [main] ERROR 🐳 [quay.io/keycloak/keycloak:13.0.1] - Could not start container
com.github.dockerjava.api.exception.DockerException: Status 403: {"message":"endpoint with name quizzical_leakey already exists in network bridge"}

I backed out to testcontainers-keycloak version 1.6.1 (where I think this was working before), but it turns out I'm seeing the same behavior there. I'm wondering if its related to some underlying Docker for Mac changes or something...

Please let me know if you have any ideas for me to try.

Full stacktrack:

13:07:34.944 [main] INFO  org.testcontainers.dockerclient.DockerClientProviderStrategy - Loaded org.testcontainers.dockerclient.UnixSocketClientProviderStrategy from ~/.testcontainers.properties, will try it first
13:07:35.717 [main] INFO  org.testcontainers.dockerclient.DockerClientProviderStrategy - Found Docker environment with local Unix socket (unix:///var/run/docker.sock)
13:07:35.719 [main] INFO  org.testcontainers.DockerClientFactory - Docker host IP address is localhost
13:07:35.772 [main] INFO  org.testcontainers.DockerClientFactory - Connected to docker: 
  Server Version: 20.10.6
  API Version: 1.41
  Operating System: Docker Desktop
  Total Memory: 7962 MB
13:07:35.776 [main] INFO  org.testcontainers.utility.ImageNameSubstitutor - Image name substitution will be performed by: DefaultImageNameSubstitutor (composite of 'ConfigurationFileImageNameSubstitutor' and 'PrefixingImageNameSubstitutor')
13:07:35.880 [main] INFO  org.testcontainers.utility.RegistryAuthLocator - Failure when attempting to lookup auth config. Please ignore if you don't have images in an authenticated registry. Details: (dockerImageName: testcontainers/ryuk:0.3.1, configFile: /Users/lmsurpre/.docker/config.json. Falling back to docker-java default behaviour. Exception message: Could not execute [docker-credential-desktop, get]. Error=2, No such file or directory
13:07:37.512 [main] INFO  org.testcontainers.DockerClientFactory - Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
13:07:37.512 [main] INFO  org.testcontainers.DockerClientFactory - Checking the system...
13:07:37.513 [main] INFO  org.testcontainers.DockerClientFactory - ✔︎ Docker server version should be at least 1.6.0
13:07:37.632 [main] INFO  org.testcontainers.DockerClientFactory - ✔︎ Docker environment should have more than 2GB free disk space
13:07:37.679 [main] INFO  🐳 [testcontainers/sshd:1.0.0] - Creating container for image: testcontainers/sshd:1.0.0
13:07:37.733 [main] INFO  🐳 [testcontainers/sshd:1.0.0] - Starting container with ID: 301ba689ac86b1b8281ca9816afbe17feadf5bf2b3ad8b93b6a16084902a23f9
13:07:39.102 [main] INFO  🐳 [testcontainers/sshd:1.0.0] - Container testcontainers/sshd:1.0.0 is starting: 301ba689ac86b1b8281ca9816afbe17feadf5bf2b3ad8b93b6a16084902a23f9
13:07:39.246 [main] INFO  🐳 [testcontainers/sshd:1.0.0] - Container testcontainers/sshd:1.0.0 started in PT1.61S
13:07:39.454 [main] INFO  🐳 [quay.io/keycloak/keycloak:13.0.1] - Creating container for image: quay.io/keycloak/keycloak:13.0.1
13:07:39.463 [main] INFO  org.testcontainers.utility.RegistryAuthLocator - Failure when attempting to lookup auth config. Please ignore if you don't have images in an authenticated registry. Details: (dockerImageName: quay.io/keycloak/keycloak:13.0.1, configFile: /Users/lmsurpre/.docker/config.json. Falling back to docker-java default behaviour. Exception message: Could not execute [docker-credential-desktop, get]. Error=2, No such file or directory
13:07:40.138 [main] INFO  🐳 [quay.io/keycloak/keycloak:13.0.1] - Reusing container with ID: de1c46323de3f5b4ddbdbf995ddfc82760a0260c0bca2bdbe7d86a981f730579 and hash: 0949650de30d970c3118393ac7a77c67b722284b
13:07:40.153 [main] ERROR 🐳 [quay.io/keycloak/keycloak:13.0.1] - Could not start container
com.github.dockerjava.api.exception.DockerException: Status 403: {"message":"endpoint with name quizzical_leakey already exists in network bridge"}

	at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.execute(DefaultInvocationBuilder.java:249)
	at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.post(DefaultInvocationBuilder.java:102)
	at org.testcontainers.shaded.com.github.dockerjava.core.exec.ConnectToNetworkCmdExec.execute(ConnectToNetworkCmdExec.java:27)
	at org.testcontainers.shaded.com.github.dockerjava.core.exec.ConnectToNetworkCmdExec.execute(ConnectToNetworkCmdExec.java:11)
	at org.testcontainers.shaded.com.github.dockerjava.core.exec.AbstrSyncDockerCmdExec.exec(AbstrSyncDockerCmdExec.java:21)
	at org.testcontainers.shaded.com.github.dockerjava.core.command.AbstrDockerCmd.exec(AbstrDockerCmd.java:35)
	at org.testcontainers.containers.GenericContainer.lambda$connectToPortForwardingNetwork$5(GenericContainer.java:576)
	at org.testcontainers.containers.GenericContainer$$Lambda$119.00000000C638D020.accept(Unknown Source)
	at java.util.Optional.ifPresent(Optional.java:159)
	at org.testcontainers.containers.GenericContainer.connectToPortForwardingNetwork(GenericContainer.java:574)
	at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:413)
	at org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:325)
	at org.testcontainers.containers.GenericContainer$$Lambda$97.00000000C38ED420.call(Unknown Source)
	at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:81)
	at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:323)
	at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:311)
	at org.alvearie.keycloak.KeycloakContainerTest.<clinit>(KeycloakContainerTest.java:74)

PS. It works just fine if I manually delete the container after each run, but I was hoping it would let me continue to use the same container over and over (until I decide not to)

Not able to reach newly added endpoint after deploy withExtensionClassesFrom

ive created extension that extends rest-api of keycloak. but after deploy classes like
.withExtensionClassesFrom("target/classes") Im not able to reach endpoints developed in that ext

is this correct that providers are not register well withing withExtensionClassesFrom?
what's I potentially can do to fix this?

Please rev the major version instead of the minor version for new major versions of keycloak

Description

Please rev the major version instead of the minor version for new major versions of keycloak.

Teams that rely on automated dependency management tools (dependabot, etc) most often set these tools to update by minor version since the majority of projects follow Semver versioning schemes.

The current versioning scheme is incompatible with Semver leading teams to perform workarounds for testcontainers-keycloak.

Motivation

No response

Details

No response

Continuous testing issue

Hi,

Nice project. I'm using it with Quarkus and it works great except for continuous testing. Not sure what Quarkus is doing behind the scene with the classpath, but this line causes issues: https://github.com/dasniko/testcontainers-keycloak/blob/main/src/main/java/dasniko/testcontainers/keycloak/KeycloakContainer.java#L185

I replaced it with:

new ObjectMapper().readValue(Thread.currentThread().getContextClassLoader().getResource(importFile), RealmRepresentation.class)

And it seems to work, but then I have another issue. I work on the first execution, but starting from the second one I got something really weird:

Caused by: java.lang.RuntimeException: Unable to start Quarkus test resource ch.koalasense.resource.KeycloakResource@4e20583b
	at io.quarkus.test.common.TestResourceManager$TestResourceEntryRunnable.run(TestResourceManager.java:457)
	at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804)
	... 3 more
Caused by: org.testcontainers.containers.ContainerLaunchException: Container startup failed
	at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:336)
	at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:317)
	at ch.koalasense.resource.KeycloakResource.start(KeycloakResource.java:21)
	at io.quarkus.test.common.TestResourceManager$TestResourceEntryRunnable.run(TestResourceManager.java:452)
	... 4 more
Caused by: org.rnorth.ducttape.RetryCountExceededException: Retry limit hit with exception
	at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:88)
	at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:329)
	... 7 more
Caused by: org.testcontainers.containers.ContainerLaunchException: Could not create/start container
	at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:525)
	at org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:331)
	at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:81)
	... 8 more
Caused by: java.lang.RuntimeException: RESTEASY003940: Unable to instantiate MessageBodyReader
	at org.jboss.resteasy.core.providerfactory.CommonProviders.processProviderContracts(CommonProviders.java:93)
	at org.jboss.resteasy.core.providerfactory.ClientHelper.processProviderContracts(ClientHelper.java:104)
	at org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl.processProviderContracts(ResteasyProviderFactoryImpl.java:841)
	at org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl.registerProvider(ResteasyProviderFactoryImpl.java:829)
	at org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl.register(ResteasyProviderFactoryImpl.java:1506)
	at org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl.register(ResteasyProviderFactoryImpl.java:105)
	at org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl.register(ResteasyClientBuilderImpl.java:479)
	at org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl.register(ResteasyClientBuilderImpl.java:47)
	at org.keycloak.admin.client.Keycloak.newRestEasyClient(Keycloak.java:71)
	at org.keycloak.admin.client.Keycloak.getInstance(Keycloak.java:78)
	at org.keycloak.admin.client.Keycloak.getInstance(Keycloak.java:94)
	at dasniko.testcontainers.keycloak.KeycloakContainer.getKeycloakAdminClient(KeycloakContainer.java:323)
	at dasniko.testcontainers.keycloak.KeycloakContainer.containerIsStarted(KeycloakContainer.java:180)
	at org.testcontainers.containers.GenericContainer.containerIsStarted(GenericContainer.java:688)
	at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:504)
	... 10 more
Caused by: java.lang.NullPointerException: Cannot invoke "io.quarkus.arc.ArcContainer.instanceSupplier(java.lang.Class, java.lang.annotation.Annotation[])" because the return value of "io.quarkus.arc.Arc.container()" is null
	at io.quarkus.resteasy.common.runtime.QuarkusConstructorInjector.construct(QuarkusConstructorInjector.java:35)
	at org.jboss.resteasy.core.providerfactory.Utils.createProviderInstance(Utils.java:102)
	at org.jboss.resteasy.core.providerfactory.CommonProviders.processProviderContracts(CommonProviders.java:87)
	... 24 more

It seems like the Arc container is null and not initialized for some reason.

I didn't see any mention of continuous testing in this repo nor in your presentation video. I'm wondering if you were able to make it work ?

Unable to import realm

Hi,

I was wondering if you are having troubles importing a previously exported realm?

I use the withRealmImportFile("elpmid-realm.json"); method and get the following warning and the realm is not imported.

KC-SERVICES0005: Unable to import realm elpmid from file /tmp/superloop-realm.json.: java.lang.RuntimeException: Script upload is disabled.

To fix the problem I had to add the following to the Class.Method: KeycloakContainer.configure()

withCommand("-Dkeycloak.profile.feature.upload_scripts=enabled");

Does this work for you?

PS - nice library you have written!

thanks

The container does not start when trying to use extension/provider of an autheticator plugin

Hi!

I'm trying to write some tests for a code similar to your keycloak-2fa-sms-authenticator.

I'm trying to start the container with

@Testcontainers
class EmailOTPAuthenticationModelTest {
//...
    companion object {
        @Container
        @JvmStatic
        val KEYCLOAK = KeycloakContainer()
            .withRealmImportFile("/quickstart-realm.json")
            .withProviderClassesFrom("target/classes")
            .withReuse(true)

        @BeforeAll
        @JvmStatic
        fun beforeAll() {
           KEYCLOAK.start()
        }
//...

    }
}

where "target/classes" contains the classes that implement AuthenticatorFactory and Authenticator classes.

What I get is an error saying that the container could not start. If I remove .withProviderClassesFrom("target/classes"), it starts with no problem.

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
SLF4J: Failed to load class "org.slf4j.impl.StaticMDCBinder".
SLF4J: Defaulting to no-operation MDCAdapter implementation.
SLF4J: See http://www.slf4j.org/codes.html#no_static_mdc_binder for further details.

Test ignored.

Test ignored.

org.testcontainers.containers.ContainerLaunchException: Container startup failed

	at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:336)
	at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:317)
	at org.testcontainers.junit.jupiter.TestcontainersExtension$StoreAdapter.start(TestcontainersExtension.java:242)
	at org.testcontainers.junit.jupiter.TestcontainersExtension$StoreAdapter.access$200(TestcontainersExtension.java:229)
	at org.testcontainers.junit.jupiter.TestcontainersExtension.lambda$null$1(TestcontainersExtension.java:59)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore.lambda$getOrComputeIfAbsent$4(ExtensionValuesStore.java:86)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.computeValue(ExtensionValuesStore.java:223)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.get(ExtensionValuesStore.java:211)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore$StoredValue.evaluate(ExtensionValuesStore.java:191)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore$StoredValue.access$100(ExtensionValuesStore.java:171)
	at org.junit.jupiter.engine.execution.ExtensionValuesStore.getOrComputeIfAbsent(ExtensionValuesStore.java:89)
	at org.junit.jupiter.engine.execution.NamespaceAwareStore.getOrComputeIfAbsent(NamespaceAwareStore.java:53)
	at org.testcontainers.junit.jupiter.TestcontainersExtension.lambda$beforeAll$2(TestcontainersExtension.java:59)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
	at org.testcontainers.junit.jupiter.TestcontainersExtension.beforeAll(TestcontainersExtension.java:59)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeBeforeAllCallbacks$10(ClassBasedTestDescriptor.java:381)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeBeforeAllCallbacks(ClassBasedTestDescriptor.java:381)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:205)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:80)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:148)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
	at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
	at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: org.rnorth.ducttape.RetryCountExceededException: Retry limit hit with exception
	at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:88)
	at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:329)
	... 55 more
Caused by: org.testcontainers.containers.ContainerLaunchException: Could not create/start container
	at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:525)
	at org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:331)
	at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:81)
	... 56 more
Caused by: java.lang.IllegalStateException: Container exited with code 1
	at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:497)
	... 58 more

My dependencies:

        <java.version>11</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <keycloak.version>14.0.0</keycloak.version>
        <maven.compiler.version>3.8.1</maven.compiler.version>
        <maven.shade.version>3.2.4</maven.shade.version>
        <kotlin.version>1.6.10</kotlin.version>
        <testcontainers.version>1.16.3</testcontainers.version>

The same error occurs with the version 1.10.0 and 2.0.0. My authenticator works correctly when deploying to a Keycloak docker.

HTTP 401 Unauthorized response when getting a token

I'm trying to run a test using the exported from Keycloack server JSON configuration file as follows:

package com.example.controllers;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@AutoConfigureMockMvc
class TestControllerTest extends BaseKeycloakTest {

    @Autowired
    protected MockMvc mockMvc;

    @Test
    public void shouldRespondOKForAdminIfTokenPresent() throws Exception {
        this.mockMvc.perform(get("/test/admin")
                .header("Authorization", "Bearer "
                        + getAccessToken(
                                "employee2",
                                "mypassword",
                                  "springboot-microservice",
                                   "demo")))
                .andExpect(status().isOk());
    }
}

The BaseKeycloakTest class is defined as follows:

@Testcontainers
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class BaseKeycloakTest {
    @Container
    protected static final KeycloakContainer keycloak = new KeycloakContainer()
            .withRealmImportFile("realm-export.json");

    @BeforeAll
    public static void setUp() {
        keycloak.start();
    }
    @AfterAll
    public static void tearDown() {
        keycloak.stop();
    }
...

I'm getting the token in BaseKeycloakTest as follows:

protected static String getAccessToken(String username, String password, String clientId, String realm) {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        LinkedMultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("grant_type", "password");
        map.add("client_id", clientId);
        map.add("username", username);
        map.add("password", password);
        map.add("client_secret", "85a58c55-dd32-4205-a568-f82ae710edd1");

        KeyCloakToken token = restTemplate.postForObject(
                tokenUrlFor(realm),
                new HttpEntity<>(map, headers), KeyCloakToken.class);

        assert token != null;
        return token.getAccessToken();
    }

    private static String tokenUrlFor(String realm) {
        String url = keycloak.getAuthServerUrl()
                + "/realms/"
                + realm
                + "/protocol/openid-connect/token";
        return url;
    }

    private static class KeyCloakToken {

        private String accessToken;

        @JsonCreator
        KeyCloakToken(@JsonProperty("access_token") final String accessToken) {
            this.accessToken = accessToken;
        }

        public String getAccessToken() {
            return accessToken;
        }
    }

When running the test, it seems like realm-export.json file is not taken in consideration, - the generated token URL looks like that:

http://localhost:32791/auth/realms/demo/protocol/openid-connect/token

instead of:

http://localhost:8080/auth/realms/demo/protocol/openid-connect/token

what raises the error:

org.springframework.web.client.HttpClientErrorException$Unauthorized: 401 Unauthorized: [no body]

	at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:105)
	at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:184)

...

The KeucloakConfig class looks like that:

package com.example.config;

import org.keycloak.adapters.KeycloakConfigResolver;
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class KeycloakConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.authorizeRequests()
                .antMatchers("/test/anonymous").permitAll()
                .antMatchers("/test/user").hasAnyRole("user")
                .antMatchers("/test/admin").hasAnyRole("admin")
                .antMatchers("/test/all-user").hasAnyRole("user","admin")
                .anyRequest()
                .permitAll();
        http.csrf().disable();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

    @Bean
    public KeycloakConfigResolver KeycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }
}

And application.yml for tests looks like that:

spring:
  application:
    name: spring-demo

server:
  port: 8000

keycloak:
  realm: demo
  auth-server-url: http://localhost:8080/auth
  ssl-required: external
  resource: springboot-microservice
  credentials:
    secret: 85a58c55-dd32-4205-a568-f82ae710edd1
  use-resource-role-mappings: true
  bearer-only: true

What is wrong with that?

Realm import: file is not handled

Describe the bug

In my test extension I have:

public KeycloakExtension(String importFile) {
    _importFile = importFile;
    _keycloakContainer = new KeycloakContainer("quay.io/keycloak/keycloak:19.0.1");
    if (_importFile != null) {
      _keycloakContainer.withRealmImportFile(_importFile);
    }
    _keycloakContainer.withCreateContainerCmdModifier(
        cmd -> cmd.withName(KEYCLOAK_TEST_CONTAINER_NAME_SUFFIX + FriendlyId.createFriendlyId()));
  }

And when I give the correct file, I can also see in the terminal for that container that the file is correctly copied:

sh-4.4$ ls opt/keycloak/data/import/
realm.json

But looking into the admin of that keycloak docker container, the realm is completely missing.

Is this a known problem?

Version

2.3.0

Expected behavior

The realm in the realm.json in the directory /opt/keycloak/data/import is successfully imported to the Keycloak.

Actual behavior

The expected realm from the JSON file is missing.

How to Reproduce?

No response

Relevant log output

No response

Anything else?

No response

"Script upload is disabled" when using realm import file

Describe the bug

Hi,
I am currently trying to write some integration tests for our system, but stumbled upon a problem when starting the docker container with Keycloak. The import of the realm file does not work and fails with a RuntimeException:

2022-08-18T10:27:48,745 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:48,743 WARN  [org.keycloak.services] (main) KC-SERVICES0005: Unable to import realm smartlabel-sso from file /opt/keycloak/bin/../data/import/test-realm.json.: java.lang.RuntimeException: Script upload is disabled

The configuration is quite simple at the moment - I just create a container with

	@Container
	private static final KeycloakContainer keycloak = new KeycloakContainer("quay.io/keycloak/keycloak:19.0.1")
			.withRealmImportFile("test-realm.json");

I will also attach the full startup log (without our spring boot startup) to this bug report.

Since you already set the "keycloak.profile.feature.upload_scripts=enabled" this error message should not occur, so any idea what happens here is highly appreciated.

Version

2.3.0

Expected behavior

The Keycloak docker instance is started and the realm configuration is imported without an exception.

Actual behavior

The realm import fails with a "Script upload is disabled" RuntimeException.

How to Reproduce?

No response

Relevant log output

"C:\Program Files\Eclipse Adoptium\jdk-17.0.3.7-hotspot\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.2\lib\idea_rt.jar=54076:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.2\bin" -Dfile.encoding=UTF-8 @C:\Users\tim.riemann\AppData\Local\Temp\idea_arg_file1906327938 com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit5 de.silab.smartlabel.server.backend.rest.internal.TagDbRestControllerTest,getEmptyListOverRestTest
2022-08-18T10:26:58,900 INFO  [main] o.t.u.ImageNameSubstitutor: Image name substitution will be performed by: DefaultImageNameSubstitutor (composite of 'ConfigurationFileImageNameSubstitutor' and 'PrefixingImageNameSubstitutor')
2022-08-18T10:26:58,929 INFO  [main] o.t.d.DockerClientProviderStrategy: Loaded org.testcontainers.dockerclient.NpipeSocketClientProviderStrategy from ~/.testcontainers.properties, will try it first
2022-08-18T10:26:59,304 INFO  [main] o.t.d.DockerClientProviderStrategy: Found Docker environment with local Npipe socket (npipe:////./pipe/docker_engine)
2022-08-18T10:26:59,307 INFO  [main] o.t.DockerClientFactory: Docker host IP address is localhost
2022-08-18T10:26:59,320 INFO  [main] o.t.DockerClientFactory: Connected to docker: 
  Server Version: 20.10.17
  API Version: 1.41
  Operating System: Docker Desktop
  Total Memory: 25429 MB
2022-08-18T10:26:59,341 INFO  [main] o.t.c.GenericContainer: Creating container for image: testcontainers/ryuk:0.3.3
2022-08-18T10:26:59,601 INFO  [main] o.t.u.RegistryAuthLocator: Credential helper/store (docker-credential-desktop) does not have credentials for https://index.docker.io/v1/
2022-08-18T10:26:59,709 INFO  [main] o.t.c.GenericContainer: Container testcontainers/ryuk:0.3.3 is starting: d9e709b636afa5aefd65cb28e8f9110b6c17a11c9f0e99f42c06822aede56e72
2022-08-18T10:27:00,178 INFO  [main] o.t.c.GenericContainer: Container testcontainers/ryuk:0.3.3 started in PT0.8508062S
2022-08-18T10:27:00,182 INFO  [main] o.t.u.RyukResourceReaper: Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
2022-08-18T10:27:00,182 INFO  [main] o.t.DockerClientFactory: Checking the system...
2022-08-18T10:27:00,183 INFO  [main] o.t.DockerClientFactory: ✔︎ Docker server version should be at least 1.6.0
2022-08-18T10:27:00,189 INFO  [main] o.t.i.RemoteDockerImage: Pulling docker image: quay.io/keycloak/keycloak:19.0.1. Please be patient; this may take some time but only needs to be done once.
2022-08-18T10:27:00,316 INFO  [main] o.t.u.RegistryAuthLocator: Credential helper/store (docker-credential-desktop) does not have credentials for quay.io
2022-08-18T10:27:02,341 INFO  [docker-java-stream--300441755] o.t.i.LoggedPullImageResultCallback: Starting to pull image
2022-08-18T10:27:02,353 INFO  [docker-java-stream--300441755] o.t.i.LoggedPullImageResultCallback: Pulling image layers:  0 pending,  0 downloaded,  0 extracted, (0 bytes/0 bytes)
2022-08-18T10:27:19,222 INFO  [docker-java-stream--300441755] o.t.i.LoggedPullImageResultCallback: Pulling image layers:  3 pending,  1 downloaded,  0 extracted, (164 MB/? MB)
2022-08-18T10:27:28,002 INFO  [docker-java-stream--300441755] o.t.i.LoggedPullImageResultCallback: Pulling image layers:  2 pending,  2 downloaded,  0 extracted, (245 MB/? MB)
2022-08-18T10:27:29,821 INFO  [docker-java-stream--300441755] o.t.i.LoggedPullImageResultCallback: Pulling image layers:  2 pending,  2 downloaded,  1 extracted, (246 MB/? MB)
2022-08-18T10:27:32,382 INFO  [docker-java-stream--300441755] o.t.i.LoggedPullImageResultCallback: Pulling image layers:  2 pending,  2 downloaded,  2 extracted, (246 MB/? MB)
2022-08-18T10:27:32,429 INFO  [docker-java-stream--300441755] o.t.i.LoggedPullImageResultCallback: Pull complete. 4 layers, pulled in 30s (downloaded 246 MB at 8 MB/s)
2022-08-18T10:27:32,610 INFO  [main] o.s.t.c.s.AbstractContextLoader: Could not detect default resource locations for test class [de.silab.smartlabel.server.backend.rest.internal.TagDbRestControllerTest]: no resource found for suffixes {-context.xml, Context.groovy}.
2022-08-18T10:27:32,729 INFO  [main] o.s.t.c.s.AbstractTestContextBootstrapper: Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener, org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.event.ApplicationEventsTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener, org.springframework.test.context.event.EventPublishingTestExecutionListener]
2022-08-18T10:27:32,742 INFO  [main] o.s.t.c.s.AbstractTestContextBootstrapper: Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@5f2de715, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@5922d3e9, org.springframework.test.context.event.ApplicationEventsTestExecutionListener@7d57dbb5, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@630b6190, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@532e27ab, org.springframework.test.context.support.DirtiesContextTestExecutionListener@1cdc1bbc, org.springframework.test.context.transaction.TransactionalTestExecutionListener@5f95f1e1, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@672a1c62, org.springframework.test.context.event.EventPublishingTestExecutionListener@459b6c53, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@39e69ea7, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener@490c7a83, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener@7e72a6cc, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@6015a4a5, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener@6d0b0da6, org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener@4779aae6]
2022-08-18T10:27:32,749 INFO  [main] o.t.c.GenericContainer: Creating container for image: quay.io/keycloak/keycloak:19.0.1
2022-08-18T10:27:33,194 INFO  [main] o.t.c.GenericContainer: Container quay.io/keycloak/keycloak:19.0.1 is starting: 56e99ba1ad27b545db821d9f2b9739e3b946de34105b3e4374c2300198870ae0
2022-08-18T10:27:33,626 INFO  [main] o.t.c.w.s.HttpWaitStrategy: /pensive_black: Waiting for 120 seconds for URL: http://localhost:54098/ (where port 54098 maps to container port 8080)
2022-08-18T10:27:33,893 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: Updating the configuration and installing your custom providers, if any. Please wait.
2022-08-18T10:27:41,089 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:41,087 INFO  [io.quarkus.deployment.QuarkusAugmentor] (main) Quarkus augmentation completed in 6327ms
2022-08-18T10:27:42,867 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:41,966 INFO  [org.keycloak.quarkus.runtime.hostname.DefaultHostnameProvider] (main) Hostname settings: FrontEnd: <request>, Strict HTTPS: false, Path: <request>, Strict BackChannel: false, Admin: <request>, Port: -1, Proxied: false
2022-08-18T10:27:42,878 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:42,547 INFO  [org.keycloak.common.crypto.CryptoIntegration] (main) Detected crypto provider: org.keycloak.crypto.def.DefaultCryptoProvider
2022-08-18T10:27:43,363 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:43,361 WARN  [org.infinispan.PERSISTENCE] (keycloak-cache-init) ISPN000554: jboss-marshalling is deprecated and planned for removal
2022-08-18T10:27:43,426 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:43,425 WARN  [org.infinispan.CONFIG] (keycloak-cache-init) ISPN000569: Unable to persist Infinispan internal caches as no global state enabled
2022-08-18T10:27:43,448 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:43,447 INFO  [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000556: Starting user marshaller 'org.infinispan.jboss.marshalling.core.JBossUserMarshaller'
2022-08-18T10:27:43,625 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:43,623 INFO  [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000128: Infinispan version: Infinispan 'Triskaidekaphobia' 13.0.9.Final
2022-08-18T10:27:44,418 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:44,416 INFO  [org.keycloak.quarkus.runtime.storage.legacy.liquibase.QuarkusJpaUpdaterProvider] (main) Initializing database schema. Using changelog META-INF/jpa-changelog-master.xml
2022-08-18T10:27:45,892 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:45,891 INFO  [org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory] (main) Node name: node_666023, Site name: null
2022-08-18T10:27:45,958 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:45,957 INFO  [org.keycloak.services] (main) KC-SERVICES0050: Initializing master realm
2022-08-18T10:27:48,745 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:48,743 WARN  [org.keycloak.services] (main) KC-SERVICES0005: Unable to import realm smartlabel-sso from file /opt/keycloak/bin/../data/import/test-realm.json.: java.lang.RuntimeException: Script upload is disabled
2022-08-18T10:27:48,745 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.authorization.policy.provider.js.JSPolicyProviderFactory.throwCanNotUpdatePolicy(JSPolicyProviderFactory.java:130)
2022-08-18T10:27:48,746 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.authorization.policy.provider.js.JSPolicyProviderFactory.onImport(JSPolicyProviderFactory.java:72)
2022-08-18T10:27:48,746 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.models.utils.RepresentationToModel.toModel(RepresentationToModel.java:1216)
2022-08-18T10:27:48,746 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.authorization.AuthorizationProvider$3.create(AuthorizationProvider.java:350)
2022-08-18T10:27:48,746 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.models.utils.RepresentationToModel.importPolicies(RepresentationToModel.java:1138)
2022-08-18T10:27:48,746 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.models.utils.RepresentationToModel.toModel(RepresentationToModel.java:1084)
2022-08-18T10:27:48,746 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.models.utils.RepresentationToModel.importAuthorizationSettings(RepresentationToModel.java:1031)
2022-08-18T10:27:48,747 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.storage.datastore.LegacyExportImportManager.lambda$importRealmAuthorizationSettings$7(LegacyExportImportManager.java:1399)
2022-08-18T10:27:48,747 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
2022-08-18T10:27:48,747 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.storage.datastore.LegacyExportImportManager.importRealmAuthorizationSettings(LegacyExportImportManager.java:1397)
2022-08-18T10:27:48,747 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.storage.datastore.LegacyExportImportManager.importRealm(LegacyExportImportManager.java:393)
2022-08-18T10:27:48,748 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.models.utils.RepresentationToModel.importRealm(RepresentationToModel.java:127)
2022-08-18T10:27:48,748 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.services.managers.RealmManager.importRealm(RealmManager.java:558)
2022-08-18T10:27:48,748 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.services.managers.RealmManager.importRealm(RealmManager.java:496)
2022-08-18T10:27:48,748 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.services.resources.KeycloakApplication.importRealm(KeycloakApplication.java:299)
2022-08-18T10:27:48,748 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.services.resources.KeycloakApplication.importRealms(KeycloakApplication.java:275)
2022-08-18T10:27:48,748 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.services.resources.KeycloakApplication.bootstrap(KeycloakApplication.java:208)
2022-08-18T10:27:48,748 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.quarkus.runtime.integration.jaxrs.QuarkusKeycloakApplication.startup(QuarkusKeycloakApplication.java:43)
2022-08-18T10:27:48,749 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.quarkus.runtime.integration.QuarkusLifecycleObserver.onStartupEvent(QuarkusLifecycleObserver.java:37)
2022-08-18T10:27:48,749 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.quarkus.runtime.integration.QuarkusLifecycleObserver_Observer_onStartupEvent_b0e82415b143738dc1f986a5fa4668e83d0a5dea.notify(Unknown Source)
2022-08-18T10:27:48,749 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at io.quarkus.arc.impl.EventImpl$Notifier.notifyObservers(EventImpl.java:320)
2022-08-18T10:27:48,749 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at io.quarkus.arc.impl.EventImpl$Notifier.notify(EventImpl.java:302)
2022-08-18T10:27:48,749 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at io.quarkus.arc.impl.EventImpl.fire(EventImpl.java:73)
2022-08-18T10:27:48,749 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at io.quarkus.arc.runtime.ArcRecorder.fireLifecycleEvent(ArcRecorder.java:128)
2022-08-18T10:27:48,749 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at io.quarkus.arc.runtime.ArcRecorder.handleLifecycleEvents(ArcRecorder.java:97)
2022-08-18T10:27:48,749 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at io.quarkus.deployment.steps.LifecycleEventsBuildStep$startupEvent1144526294.deploy_0(Unknown Source)
2022-08-18T10:27:48,750 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at io.quarkus.deployment.steps.LifecycleEventsBuildStep$startupEvent1144526294.deploy(Unknown Source)
2022-08-18T10:27:48,750 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at io.quarkus.runner.ApplicationImpl.doStart(Unknown Source)
2022-08-18T10:27:48,750 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at io.quarkus.runtime.Application.start(Application.java:101)
2022-08-18T10:27:48,750 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:103)
2022-08-18T10:27:48,750 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at io.quarkus.runtime.Quarkus.run(Quarkus.java:67)
2022-08-18T10:27:48,750 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.quarkus.runtime.KeycloakMain.start(KeycloakMain.java:103)
2022-08-18T10:27:48,750 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.quarkus.runtime.cli.command.AbstractStartCommand.run(AbstractStartCommand.java:37)
2022-08-18T10:27:48,750 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at picocli.CommandLine.executeUserObject(CommandLine.java:1939)
2022-08-18T10:27:48,751 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at picocli.CommandLine.access$1300(CommandLine.java:145)
2022-08-18T10:27:48,751 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2358)
2022-08-18T10:27:48,751 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at picocli.CommandLine$RunLast.handle(CommandLine.java:2352)
2022-08-18T10:27:48,751 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at picocli.CommandLine$RunLast.handle(CommandLine.java:2314)
2022-08-18T10:27:48,751 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2179)
2022-08-18T10:27:48,751 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at picocli.CommandLine$RunLast.execute(CommandLine.java:2316)
2022-08-18T10:27:48,751 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at picocli.CommandLine.execute(CommandLine.java:2078)
2022-08-18T10:27:48,752 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.quarkus.runtime.cli.Picocli.parseAndRun(Picocli.java:91)
2022-08-18T10:27:48,752 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at org.keycloak.quarkus.runtime.KeycloakMain.main(KeycloakMain.java:89)
2022-08-18T10:27:48,752 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2022-08-18T10:27:48,752 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
2022-08-18T10:27:48,752 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
2022-08-18T10:27:48,752 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
2022-08-18T10:27:48,752 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at io.quarkus.bootstrap.runner.QuarkusEntryPoint.doRun(QuarkusEntryPoint.java:60)
2022-08-18T10:27:48,753 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 	at io.quarkus.bootstrap.runner.QuarkusEntryPoint.main(QuarkusEntryPoint.java:31)
2022-08-18T10:27:48,753 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 
2022-08-18T10:27:48,838 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:48,836 INFO  [io.quarkus] (main) Keycloak 19.0.1 on JVM (powered by Quarkus 2.7.6.Final) started in 7.673s. Listening on: http://0.0.0.0:8080
2022-08-18T10:27:48,838 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:48,837 INFO  [io.quarkus] (main) Profile dev activated. 
2022-08-18T10:27:48,838 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:48,837 INFO  [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-h2, jdbc-mariadb, jdbc-mssql, jdbc-mysql, jdbc-oracle, jdbc-postgresql, keycloak, logging-gelf, narayana-jta, reactive-routes, resteasy, resteasy-jackson, smallrye-context-propagation, smallrye-health, smallrye-metrics, vault, vertx]
2022-08-18T10:27:48,984 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:48,983 INFO  [org.keycloak.services] (main) KC-SERVICES0009: Added user 'admin' to realm 'master'
2022-08-18T10:27:48,986 INFO  [docker-java-stream-563505127] o.t.c.o.Slf4jLogConsumer: STDOUT: 2022-08-18 08:27:48,985 WARN  [org.keycloak.quarkus.runtime.KeycloakMain] (main) Running the server in development mode. DO NOT use this configuration in production.
2022-08-18T10:27:50,022 INFO  [main] o.t.c.GenericContainer: Container quay.io/keycloak/keycloak:19.0.1 started in PT17.2730603S

Anything else?

No response

Keycloak Container never starts

Hello,

I have a strange issue with the container. It never starts on time, where previously and on another machine it works nicely. I get the error:

11:40:03.236 [main] INFO org.testcontainers.containers.wait.strategy.HttpWaitStrategy - /funny_mcnulty: Waiting for 120 seconds for URL: http://localhost:32773/auth
11:40:05.021 [tc-okhttp-stream-1189259123] INFO 🐳 [jboss/keycloak:7.0.0] - STDOUT: Added 'admin' to '/opt/jboss/keycloak/standalone/configuration/keycloak-add-user.json', restart server to load user
11:42:03.240 [main] DEBUG 🐳 [jboss/keycloak:7.0.0] - Wait strategy threw an exception
org.testcontainers.containers.ContainerLaunchException: Timed out waiting for URL to be accessible (http://localhost:32773/auth should return HTTP 200)

I pruned everything (network, volumes, containers) uninstalled and installed docker a new. Same thing. I am able to start other test containers successfully, actually any I tried...mysql, redis and so on...
The keycloak was previously accessible and the same code does work on another machine. Increasing the timeout to 5 minutes solves the problem but it seems like keycloak just hangs for a long time not starting and then it suddenly starts. Any ideas?

Provide methods to add users programmatically

I would love it if there was a way to add a user programmatically.

I realize I could probably do so using the admin endpoints, but that seems hefty to do by hand.

My particular use-case is that I would like to create new, random users for use in testing rather than rely on users already existing. This helps keep tests threadsafe and (ideally) less brittle.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.