Delete container providers from the base testsuite (#25168)
Closes #24097 Signed-off-by: vramik <vramik@redhat.com>
This commit is contained in:
parent
8b5ebb6597
commit
6f37fefd8d
12 changed files with 1 additions and 1027 deletions
|
@ -957,136 +957,6 @@ when running these tests on your local machine. This happens when something on y
|
|||
In order to avoid using external services for DNS resolution, the tests are executed using a local host file by setting the `-Djdk.net.hosts.file=${project.build.testOutputDirectory}/hosts_file`
|
||||
system property.
|
||||
|
||||
## Running base testsuite with Map storage
|
||||
|
||||
To run base testsuite with new storage run the following command (this will execute testsuite with ConcurrentHashMap storage):
|
||||
```shell
|
||||
mvn clean install -f testsuite/integration-arquillian/tests/base \
|
||||
-Pauth-server-quarkus -Pmap-storage-chm
|
||||
```
|
||||
|
||||
### Running tests with JPA Map storage
|
||||
|
||||
By default, testing with the profile `map-storage-jpa-postgres` spawns a new Postgres container
|
||||
with each test execution. The default image used is `postgres:alpine`. To spawn a different
|
||||
version, use the system property `keycloak.map.storage.postgres.docker.image`.
|
||||
|
||||
In a similar way the profile `map-storage-jpa-cockroach` spawns a new CockroachDB container
|
||||
with each test execution. It uses the official CockroachDB image in the version stated in the
|
||||
class `CockroachdbContainerTestEnricher`. To spawn a different
|
||||
version, use the system property `keycloak.map.storage.cockroachdb.docker.image`.
|
||||
|
||||
Execute tests:
|
||||
```shell
|
||||
mvn clean install -f testsuite/integration-arquillian/tests/base \
|
||||
-Pmap-storage-jpa-postgres
|
||||
```
|
||||
|
||||
It's also possible to configure tests to connect to an external database, it might be useful
|
||||
for debugging purposes as the database is not removed after the testsuite run. On the other hand
|
||||
it'll require manual cleaning between two runs.
|
||||
|
||||
PostgreSQL database can be started e.g. by following command:
|
||||
```shell
|
||||
podman run --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=pass -e POSTGRES_USER=keycloak -e POSTGRES_DB=keycloak -d postgres:alpine
|
||||
```
|
||||
|
||||
To run the tests without spawning the container for you, execute tests with the following command:
|
||||
```shell
|
||||
mvn clean install -f testsuite/integration-arquillian/tests/base \
|
||||
-Pmap-storage-jpa-postgres \
|
||||
-Dpostgres.start-container=false \
|
||||
-Dkeycloak.map.storage.connectionsJpa.url=<jdbc_url> \
|
||||
-Dkeycloak.map.storage.connectionsJpa.user=<user> \
|
||||
-Dkeycloak.map.storage.connectionsJpa.password=<password>
|
||||
```
|
||||
|
||||
### Running tests with HotRod Map storage
|
||||
|
||||
By default, Base testsuite with `map-storage-hotrod` profile spawn a new Infinispan container
|
||||
with each test execution. To run the tests execute:
|
||||
```shell
|
||||
mvn clean install -f testsuite/integration-arquillian/tests/base \
|
||||
-Pmap-storage-hotrod
|
||||
```
|
||||
Note: For running Infinispan server we are using Testcontainer, see section
|
||||
_Usage of Testcontainers_ for details on how to set up your container engine.
|
||||
|
||||
It is also possible, to configure Base testsuite to
|
||||
connect to an external instance of Infinispan. To do so, execute tests with
|
||||
the following command:
|
||||
```shell
|
||||
mvn clean install -f testsuite/integration-arquillian/tests/base \
|
||||
-Pmap-storage-hotrod
|
||||
-Dkeycloak.testsuite.start-hotrod-container=false \
|
||||
-Dkeycloak.connectionsHotRod.host=<host> \
|
||||
-Dkeycloak.connectionsHotRod.port=<port> \
|
||||
-Dkeycloak.connectionsHotRod.username=<username> \
|
||||
-Dkeycloak.connectionsHotRod.password=<password>
|
||||
```
|
||||
|
||||
### Usage of Testcontainers
|
||||
|
||||
Some profiles within model tests require running 3rd party software, for
|
||||
example, database or Infinispan. For running these we are using
|
||||
[Testcontainers](https://www.testcontainers.org/). This may require some
|
||||
additional configuration of your container engine.
|
||||
|
||||
#### Podman settings
|
||||
|
||||
For more details see the following [Podman guide from Quarkus webpage](https://quarkus.io/guides/podman).
|
||||
|
||||
Specifically, these steps are required:
|
||||
```shell
|
||||
# Enable the podman socket with Docker REST API (only needs to be done once)
|
||||
systemctl --user enable podman.socket --now
|
||||
|
||||
# Set the required environment variables (need to be run everytime or added to profile)
|
||||
export DOCKER_HOST=unix:///run/user/${UID}/podman/podman.sock
|
||||
```
|
||||
|
||||
Testcontainers are using [ryuk](https://hub.docker.com/r/testcontainers/ryuk)
|
||||
to cleanup containers after tests. To make this work with Podman add the
|
||||
following line to `~/.testcontainers.properties`
|
||||
```shell
|
||||
ryuk.container.privileged=true
|
||||
```
|
||||
Alternatively, disable usage of ryuk (using this may result in stale containers
|
||||
still running after tests finish. This is not recommended especially if you are
|
||||
executing tests from Intellij IDE as it [may not stop](https://youtrack.jetbrains.com/issue/IDEA-190385)
|
||||
the containers created during test run).
|
||||
```shell
|
||||
export TESTCONTAINERS_RYUK_DISABLED=true #not recommended - see above!
|
||||
```
|
||||
|
||||
#### Docker settings
|
||||
|
||||
To use Testcontainers with Docker it is necessary to
|
||||
[make Docker available for non-root users](https://docs.docker.com/engine/install/linux-postinstall/).
|
||||
|
||||
### Zero downtime tests
|
||||
|
||||
By default tests are enabled and runs when `map-storage-hotrod`, `map-storage-postgres` or `map-storage-jpa-cockroach` profile is enabled.
|
||||
Other may be added in future. It supports both `auth-server-undertow` and `auth-server-quarkus`.
|
||||
|
||||
#### Default behavior
|
||||
1. Before test current `auth-server` is stopped as well as ( postgres/crdb/hotrod ) container.
|
||||
2. New ( postgres/crdb/hotrod ) container is spawned using testcontainers.
|
||||
3. Legacy keycloak (latest from https://quay.io/) is started.
|
||||
4. Test realm is imported into legacy keycloak.
|
||||
5. Current `auth-server` is started.
|
||||
|
||||
#### Notes
|
||||
- version of legacy keycloak could be specified by `keycloak.legacy.version.zero.downtime` property
|
||||
- legacy keycloak is by default listening on http://localhost:8091
|
||||
- when running only zero downtime tests, e.g. locally, it could be speeded up by skipping start of suite
|
||||
( postgres/crdb/hotrod ) container by `-Dcockroachdb.start-container=false`, `-Dpostgres.start-container=false`
|
||||
or `-Dkeycloak.testsuite.start-hotrod-container=false` and also suite `auth-server` by `-Dkeycloak.testsuite.skip.start.auth.server=true`
|
||||
- to run tests with an external instance of ( postgres/crdb/hotrod ) container
|
||||
`-Dpostgres.start-container-for-zero-downtime=false`; `-Dcockroachdb.start-container-for-zero-downtime`; `-Dstart-hotrod-container-for-zero-downtime`
|
||||
together with appropriate properties (see sections above).
|
||||
|
||||
|
||||
## FIPS 140-2 testing
|
||||
|
||||
### Unit tests
|
||||
|
|
|
@ -112,16 +112,6 @@
|
|||
<artifactId>testcontainers</artifactId>
|
||||
<version>${testcontainers.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>${testcontainers.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>cockroachdb</artifactId>
|
||||
<version>${testcontainers.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* Copyright 2023 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.testsuite.arquillian;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import org.jboss.arquillian.container.spi.event.StartSuiteContainers;
|
||||
import org.jboss.arquillian.core.api.annotation.Observes;
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.jboss.arquillian.test.spi.enricher.resource.ResourceProvider;
|
||||
import org.jboss.arquillian.test.spi.event.suite.AfterSuite;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.testcontainers.containers.CockroachContainer;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
|
||||
public class CockroachdbContainerProvider implements ResourceProvider {
|
||||
|
||||
private static final Logger log = Logger.getLogger(CockroachdbContainerProvider.class);
|
||||
|
||||
private static final Boolean START_CONTAINER = Boolean.valueOf(System.getProperty("cockroachdb.start-container", "false"));
|
||||
private static final String COCKROACHDB_DOCKER_IMAGE_NAME = System.getProperty("keycloak.map.storage.cockroachdb.docker.image", "cockroachdb/cockroach:v22.1.0");
|
||||
|
||||
public static final String COCKROACHDB_DB_USER = System.getProperty("keycloak.map.storage.connectionsJpa.user", "keycloak");
|
||||
public static final String COCKROACHDB_DB_PASSWORD = System.getProperty("keycloak.map.storage.connectionsJpa.password", "pass");
|
||||
|
||||
private static CockroachContainer cockroachDbContainer;
|
||||
|
||||
public void beforeContainerStarted(@Observes(precedence = 1) StartSuiteContainers event) {
|
||||
if (START_CONTAINER) {
|
||||
cockroachDbContainer = createContainer();
|
||||
cockroachDbContainer.start();
|
||||
|
||||
System.setProperty("keycloak.map.storage.connectionsJpa.url", cockroachDbContainer.getJdbcUrl());
|
||||
|
||||
log.infof("DatabaseInfo: %s, user=%s, pass=%s", cockroachDbContainer.getJdbcUrl(), COCKROACHDB_DB_USER, COCKROACHDB_DB_PASSWORD);
|
||||
}
|
||||
}
|
||||
|
||||
public void afterSuite(@Observes(precedence = 4) AfterSuite event) {
|
||||
if (START_CONTAINER) {
|
||||
cockroachDbContainer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
public CockroachContainer createContainer() {
|
||||
return new CockroachContainer(DockerImageName.parse(COCKROACHDB_DOCKER_IMAGE_NAME).asCompatibleSubstituteFor("cockroachdb"))
|
||||
// Using the environment variables for now where using the withXXX() method is not supported, yet.
|
||||
// https://github.com/testcontainers/testcontainers-java/issues/6299
|
||||
.withEnv("COCKROACH_DATABASE", "keycloak")
|
||||
.withEnv("COCKROACH_USER", COCKROACHDB_DB_USER)
|
||||
// password is not used/supported in insecure mode
|
||||
.withCommand("start-single-node", "--insecure");
|
||||
}
|
||||
|
||||
public CockroachContainer getContainer() {
|
||||
return cockroachDbContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProvide(Class<?> type) {
|
||||
return type.equals(CockroachdbContainerProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object lookup(ArquillianResource ar, Annotation... antns) {
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Copyright 2023 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.testsuite.arquillian;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import org.jboss.arquillian.container.spi.event.StartSuiteContainers;
|
||||
import org.jboss.arquillian.core.api.annotation.Observes;
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.jboss.arquillian.test.spi.enricher.resource.ResourceProvider;
|
||||
import org.jboss.arquillian.test.spi.event.suite.AfterSuite;
|
||||
import org.keycloak.testsuite.util.InfinispanContainer;
|
||||
|
||||
|
||||
public class HotRodContainerProvider implements ResourceProvider {
|
||||
|
||||
public static final String HOT_ROD_STORE_HOST_PROPERTY = "keycloak.connectionsHotRod.host";
|
||||
|
||||
public static final boolean HOT_ROD_START_CONTAINER = Boolean.parseBoolean(System.getProperty("keycloak.testsuite.start-hotrod-container", "false"));
|
||||
|
||||
private static InfinispanContainer infinispanContainer;
|
||||
|
||||
public void beforeContainerStarted(@Observes(precedence = 1) StartSuiteContainers event) {
|
||||
if (!HOT_ROD_START_CONTAINER) return;
|
||||
infinispanContainer = new InfinispanContainer();
|
||||
infinispanContainer.start();
|
||||
|
||||
// Add env variable, so it can be picked up by Keycloak
|
||||
System.setProperty(HOT_ROD_STORE_HOST_PROPERTY, infinispanContainer.getHost());
|
||||
}
|
||||
|
||||
public void afterSuite(@Observes(precedence = 4) AfterSuite event) {
|
||||
if (!HOT_ROD_START_CONTAINER) return;
|
||||
if (infinispanContainer != null) infinispanContainer.stop();
|
||||
}
|
||||
|
||||
public InfinispanContainer getContainer() {
|
||||
return infinispanContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProvide(Class<?> type) {
|
||||
return type.equals(HotRodContainerProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object lookup(ArquillianResource ar, Annotation... antns) {
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -58,11 +58,7 @@ public class KeycloakArquillianExtension implements LoadableExtension {
|
|||
.service(ResourceProvider.class, TestContextProvider.class)
|
||||
.service(ResourceProvider.class, AdminClientProvider.class)
|
||||
.service(ResourceProvider.class, OAuthClientProvider.class)
|
||||
.service(ResourceProvider.class, LoadBalancerControllerProvider.class)
|
||||
.service(ResourceProvider.class, PostgresContainerProvider.class)
|
||||
.service(ResourceProvider.class, CockroachdbContainerProvider.class)
|
||||
.service(ResourceProvider.class, HotRodContainerProvider.class)
|
||||
.service(ResourceProvider.class, LegacyKeycloakContainerProvider.class);
|
||||
.service(ResourceProvider.class, LoadBalancerControllerProvider.class);
|
||||
|
||||
builder
|
||||
.service(DeploymentScenarioGenerator.class, DeploymentTargetModifier.class)
|
||||
|
@ -72,9 +68,6 @@ public class KeycloakArquillianExtension implements LoadableExtension {
|
|||
.observer(AuthServerTestEnricher.class)
|
||||
.observer(AppServerTestEnricher.class)
|
||||
.observer(CrossDCTestEnricher.class)
|
||||
.observer(HotRodContainerProvider.class)
|
||||
.observer(PostgresContainerProvider.class)
|
||||
.observer(CockroachdbContainerProvider.class)
|
||||
.observer(H2TestEnricher.class);
|
||||
builder
|
||||
.service(TestExecutionDecider.class, MigrationTestExecutionDecider.class)
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
* Copyright 2023 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.testsuite.arquillian;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.jboss.arquillian.test.spi.enricher.resource.ResourceProvider;
|
||||
import org.keycloak.testsuite.util.InfinispanContainer;
|
||||
import org.keycloak.testsuite.util.LegacyKeycloakContainer;
|
||||
|
||||
public class LegacyKeycloakContainerProvider implements ResourceProvider {
|
||||
|
||||
public static final ZeroDowntimeContainer CONTAINER = processSystemProperties();
|
||||
public enum ZeroDowntimeContainer {
|
||||
POSTGRES,
|
||||
COCKROACH,
|
||||
HOTROD,
|
||||
NONE;
|
||||
}
|
||||
|
||||
private final String legacyKeycloakPort = System.getProperty("keycloak.legacy.port", "8091");
|
||||
|
||||
@Override
|
||||
public boolean canProvide(Class<?> type) {
|
||||
return type.equals(LegacyKeycloakContainerProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object lookup(ArquillianResource ar, Annotation... antns) {
|
||||
return this;
|
||||
}
|
||||
|
||||
private static ZeroDowntimeContainer processSystemProperties() {
|
||||
String mapStorageProfileconfig = System.getProperty("auth.server.quarkus.mapStorage.profile.config");
|
||||
if (mapStorageProfileconfig == null) return ZeroDowntimeContainer.NONE;
|
||||
|
||||
switch (mapStorageProfileconfig) {
|
||||
|
||||
case "jpa":
|
||||
String storageConnectionsVendor = System.getProperty("keycloak.storage.connections.vendor");
|
||||
if (storageConnectionsVendor == null) return ZeroDowntimeContainer.NONE;
|
||||
|
||||
switch (storageConnectionsVendor) {
|
||||
|
||||
case "postgres":
|
||||
return ZeroDowntimeContainer.POSTGRES;
|
||||
case "cockroach":
|
||||
return ZeroDowntimeContainer.COCKROACH;
|
||||
default:
|
||||
return ZeroDowntimeContainer.NONE;
|
||||
}
|
||||
|
||||
case "hotrod":
|
||||
return ZeroDowntimeContainer.HOTROD;
|
||||
|
||||
default:
|
||||
return ZeroDowntimeContainer.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
private LegacyKeycloakContainer createLegacyKeycloakContainer() {
|
||||
return new LegacyKeycloakContainer(System.getProperty("keycloak.legacy.version.zero.downtime", "latest"));
|
||||
}
|
||||
|
||||
public LegacyKeycloakContainer get() {
|
||||
switch (CONTAINER) {
|
||||
|
||||
case POSTGRES:
|
||||
return createLegacyKeycloakContainer().withCommand("start-dev",
|
||||
"--storage=jpa",
|
||||
"--http-port=" + legacyKeycloakPort,
|
||||
"--db-url=" + System.getProperty("keycloak.map.storage.connectionsJpa.url"),
|
||||
"--db-username=" + PostgresContainerProvider.POSTGRES_DB_USER,
|
||||
"--db-password=" + PostgresContainerProvider.POSTGRES_DB_PASSWORD);
|
||||
|
||||
case COCKROACH:
|
||||
return createLegacyKeycloakContainer().withCommand("start-dev",
|
||||
"--storage=jpa",
|
||||
"--http-port=" + legacyKeycloakPort,
|
||||
"--db-url=" + System.getProperty("keycloak.map.storage.connectionsJpa.url"),
|
||||
"--db-username=" + CockroachdbContainerProvider.COCKROACHDB_DB_USER,
|
||||
"--db-password=" + CockroachdbContainerProvider.COCKROACHDB_DB_PASSWORD);
|
||||
|
||||
case HOTROD:
|
||||
return createLegacyKeycloakContainer().withCommand("start-dev",
|
||||
"--storage=hotrod",
|
||||
"--http-port=" + legacyKeycloakPort,
|
||||
"--storage-hotrod-host=" + System.getProperty(HotRodContainerProvider.HOT_ROD_STORE_HOST_PROPERTY),
|
||||
"--storage-hotrod-port=" + InfinispanContainer.PORT,
|
||||
"--storage-hotrod-username=" + InfinispanContainer.USERNAME,
|
||||
"--storage-hotrod-password=" + InfinispanContainer.PASSWORD);
|
||||
case NONE:
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* Copyright 2023 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.testsuite.arquillian;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import org.jboss.arquillian.container.spi.event.StartSuiteContainers;
|
||||
import org.jboss.arquillian.core.api.annotation.Observes;
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.jboss.arquillian.test.spi.enricher.resource.ResourceProvider;
|
||||
import org.jboss.arquillian.test.spi.event.suite.AfterSuite;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
|
||||
public class PostgresContainerProvider implements ResourceProvider {
|
||||
|
||||
private final Logger log = Logger.getLogger(PostgresContainerProvider.class);
|
||||
|
||||
private static final Boolean START_CONTAINER = Boolean.valueOf(System.getProperty("postgres.start-container", "false"));
|
||||
private static final String POSTGRES_DOCKER_IMAGE_NAME = System.getProperty("keycloak.map.storage.postgres.docker.image", "postgres:alpine");
|
||||
|
||||
public static final String POSTGRES_DB_USER = System.getProperty("keycloak.map.storage.connectionsJpa.user", "keycloak");
|
||||
public static final String POSTGRES_DB_PASSWORD = System.getProperty("keycloak.map.storage.connectionsJpa.password", "pass");
|
||||
|
||||
private static PostgreSQLContainer postgresContainer;
|
||||
|
||||
public void beforeContainerStarted(@Observes(precedence = 1) StartSuiteContainers event) {
|
||||
if (START_CONTAINER) {
|
||||
postgresContainer = createContainer();
|
||||
postgresContainer.start();
|
||||
|
||||
System.setProperty("keycloak.map.storage.connectionsJpa.url", postgresContainer.getJdbcUrl());
|
||||
|
||||
log.infof("DatabaseInfo: %s, user=%s, pass=%s", postgresContainer.getJdbcUrl(), POSTGRES_DB_USER, POSTGRES_DB_PASSWORD);
|
||||
}
|
||||
}
|
||||
|
||||
public void afterSuite(@Observes(precedence = 4) AfterSuite event) {
|
||||
if (START_CONTAINER) {
|
||||
postgresContainer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
public PostgreSQLContainer createContainer() {
|
||||
return new PostgreSQLContainer(DockerImageName.parse(POSTGRES_DOCKER_IMAGE_NAME).asCompatibleSubstituteFor("postgres"))
|
||||
.withDatabaseName("keycloak")
|
||||
.withUsername(POSTGRES_DB_USER)
|
||||
.withPassword(POSTGRES_DB_PASSWORD);
|
||||
}
|
||||
|
||||
public PostgreSQLContainer getContainer() {
|
||||
return postgresContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProvide(Class<?> type) {
|
||||
return type.equals(PostgresContainerProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object lookup(ArquillianResource ar, Annotation... antns) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
* Copyright 2022 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.util;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.testsuite.arquillian.HotRodContainerProvider;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.containers.wait.strategy.Wait;
|
||||
import org.testcontainers.images.PullPolicy;
|
||||
import org.testcontainers.utility.MountableFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class InfinispanContainer extends GenericContainer<InfinispanContainer> {
|
||||
|
||||
private final Logger LOG = Logger.getLogger(getClass());
|
||||
public static final String PORT = System.getProperty("keycloak.connectionsHotRod.port", "11222");
|
||||
private static String HOST = System.getProperty(HotRodContainerProvider.HOT_ROD_STORE_HOST_PROPERTY);
|
||||
public static final String USERNAME = System.getProperty("keycloak.connectionsHotRod.username", "admin");
|
||||
public static final String PASSWORD = System.getProperty("keycloak.connectionsHotRod.password", "admin");
|
||||
|
||||
private static final String ZERO_TO_255
|
||||
= "(\\d{1,2}|(0|1)\\"
|
||||
+ "d{2}|2[0-4]\\d|25[0-5])";
|
||||
private static final String IP_ADDRESS_REGEX
|
||||
= ZERO_TO_255 + "\\."
|
||||
+ ZERO_TO_255 + "\\."
|
||||
+ ZERO_TO_255 + "\\."
|
||||
+ ZERO_TO_255;
|
||||
|
||||
private static final Pattern IP_ADDRESS_PATTERN = Pattern.compile("listening on (" + IP_ADDRESS_REGEX + "):" + PORT);
|
||||
|
||||
public InfinispanContainer() {
|
||||
super(getImageName());
|
||||
withEnv("USER", USERNAME);
|
||||
withEnv("PASS", PASSWORD);
|
||||
withNetworkMode("host");
|
||||
|
||||
// the images in the 'infinispan-test' repository point to tags that are frequently refreshed, therefore, always pull them
|
||||
if (getImageName().startsWith("quay.io/infinispan-test")) {
|
||||
withImagePullPolicy(PullPolicy.alwaysPull());
|
||||
}
|
||||
|
||||
Path dir = Path.of(Path.of("").toAbsolutePath() + "/target/lib");
|
||||
String projectVersion = System.getProperty("project.version");
|
||||
Path timeTaskPath;
|
||||
try {
|
||||
timeTaskPath = Files.find(dir, 1, (path, attr) -> path.toString()
|
||||
.endsWith("integration-arquillian-testsuite-providers-" + projectVersion + ".jar")).findFirst().orElse(null);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
MountableFile mountableFile = MountableFile.forHostPath(timeTaskPath, 0666);
|
||||
withCopyFileToContainer(mountableFile, "/opt/infinispan/server/lib/integration-arquillian-testsuite-providers.jar");
|
||||
|
||||
//order of waitingFor and withStartupTimeout matters as the latter sets the timeout for WaitStrategy set by waitingFor
|
||||
waitingFor(Wait.forLogMessage(".*Infinispan Server.*started in.*", 1));
|
||||
withStartupTimeout(Duration.ofMinutes(5));
|
||||
}
|
||||
|
||||
private static String getImageName() {
|
||||
String version = System.getProperty("infinispan.version");
|
||||
if (version.endsWith("-SNAPSHOT")) {
|
||||
// for snapshot versions, '14.0.13-SNAPSHOT' translates to '14.0.x'
|
||||
version = version.replaceAll("[0-9]*-SNAPSHOT$", "x");
|
||||
return "quay.io/infinispan-test/server:" + version;
|
||||
} else {
|
||||
return "quay.io/infinispan/server:" + version;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHost() {
|
||||
if (HOST == null && this.isRunning()) {
|
||||
Matcher matcher = IP_ADDRESS_PATTERN.matcher(getLogs());
|
||||
if (!matcher.find()) {
|
||||
LOG.errorf("Cannot find IP address of the infinispan server in log:\\n%s ", getLogs());
|
||||
throw new IllegalStateException("Cannot find IP address of the Infinispan server. See test log for Infinispan container log.");
|
||||
}
|
||||
HOST = matcher.group(1);
|
||||
|
||||
if ("0.0.0.0".equals(HOST)) {
|
||||
HOST = "127.0.0.1";
|
||||
}
|
||||
}
|
||||
|
||||
return HOST;
|
||||
}
|
||||
|
||||
public String getPort() {
|
||||
return PORT;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return USERNAME;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return PASSWORD;
|
||||
}
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* Copyright 2023 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.util;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.time.Duration;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.containers.wait.strategy.Wait;
|
||||
|
||||
public class LegacyKeycloakContainer extends GenericContainer<LegacyKeycloakContainer> {
|
||||
|
||||
private static final String USERNAME = "admin";
|
||||
private static final String PASSWORD = "admin";
|
||||
|
||||
public LegacyKeycloakContainer(String tagName) {
|
||||
super("quay.io/keycloak/keycloak" + getManifestDigestOfImageByName(tagName));
|
||||
|
||||
withEnv("KEYCLOAK_ADMIN", USERNAME);
|
||||
withEnv("KEYCLOAK_ADMIN_PASSWORD", PASSWORD);
|
||||
withNetworkMode("host");
|
||||
|
||||
//order of waitingFor and withStartupTimeout matters as the latter sets the timeout for WaitStrategy set by waitingFor
|
||||
waitingFor(Wait.forLogMessage(".*Running the server in development mode..*", 1));
|
||||
withStartupTimeout(Duration.ofMinutes(5));
|
||||
}
|
||||
|
||||
/**
|
||||
* For tag names as "latest" or "nightly" it may happen that some older version keycloak could be cached.
|
||||
* Therefore fetching container by its name wouldn't be reliable.
|
||||
*
|
||||
* This method obtains image "manifest_digest" by the name from quay.io and returns it with prefix "@".
|
||||
* It can be then used to fetch the container with:
|
||||
*
|
||||
* <p>quay.io/keycloak/keycloak@sha256:...</p>
|
||||
*
|
||||
* @param tagName Name of the image tag.
|
||||
* @return "manifest_digest" of the image if "latest" or "nightly" with prefix "@", {@code tagName} with ":" prefix otherwise
|
||||
*/
|
||||
private static String getManifestDigestOfImageByName(String tagName) {
|
||||
if ("latest".equals(tagName) || "nightly".equals(tagName)) {
|
||||
|
||||
try {
|
||||
URI uri = new URI("https://quay.io/api/v1/repository/keycloak/keycloak/tag/?specificTag=" + tagName);
|
||||
HttpResponse<String> response = HttpClient.newBuilder()
|
||||
.followRedirects(HttpClient.Redirect.ALWAYS)
|
||||
.build()
|
||||
.send(HttpRequest.newBuilder(uri).GET().build(), HttpResponse.BodyHandlers.ofString());
|
||||
if (response.statusCode() == HttpURLConnection.HTTP_OK) {
|
||||
JsonNode manifestDigest = JsonSerialization.mapper.readTree(response.body()).findValue("manifest_digest");
|
||||
if (manifestDigest != null) {
|
||||
return "@" + manifestDigest.asText();
|
||||
}
|
||||
}
|
||||
throw new RuntimeException(String.format("Unable to get manifest_digest for image with tag %s from quay.io. Response: %d, %s. ", tagName, response.statusCode(), response.body()));
|
||||
} catch (URISyntaxException | IOException | InterruptedException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
} else {
|
||||
return ":" + tagName;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,335 +0,0 @@
|
|||
/*
|
||||
* Copyright 2023 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.testsuite.zerodowntime;
|
||||
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import org.jboss.arquillian.container.test.api.ContainerController;
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.admin.client.KeycloakBuilder;
|
||||
import org.keycloak.common.util.Retry;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.ClientScopeRepresentation;
|
||||
import org.keycloak.representations.idm.GroupRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||
import org.keycloak.testsuite.arquillian.CockroachdbContainerProvider;
|
||||
import org.keycloak.testsuite.arquillian.HotRodContainerProvider;
|
||||
import org.keycloak.testsuite.arquillian.LegacyKeycloakContainerProvider;
|
||||
import org.keycloak.testsuite.arquillian.LegacyKeycloakContainerProvider.ZeroDowntimeContainer;
|
||||
import static org.keycloak.testsuite.arquillian.LegacyKeycloakContainerProvider.ZeroDowntimeContainer.COCKROACH;
|
||||
import static org.keycloak.testsuite.arquillian.LegacyKeycloakContainerProvider.ZeroDowntimeContainer.HOTROD;
|
||||
import static org.keycloak.testsuite.arquillian.LegacyKeycloakContainerProvider.ZeroDowntimeContainer.NONE;
|
||||
import static org.keycloak.testsuite.arquillian.LegacyKeycloakContainerProvider.ZeroDowntimeContainer.POSTGRES;
|
||||
import org.keycloak.testsuite.arquillian.PostgresContainerProvider;
|
||||
import org.keycloak.testsuite.auth.page.AuthRealm;
|
||||
import org.keycloak.testsuite.updaters.SetSystemProperty;
|
||||
import org.keycloak.testsuite.util.AdminClientUtil;
|
||||
import org.keycloak.testsuite.util.ClientBuilder;
|
||||
import org.keycloak.testsuite.util.ClientScopeBuilder;
|
||||
import org.keycloak.testsuite.util.GroupBuilder;
|
||||
import org.keycloak.testsuite.util.InfinispanContainer;
|
||||
import org.keycloak.testsuite.util.LegacyKeycloakContainer;
|
||||
import org.keycloak.testsuite.util.RealmBuilder;
|
||||
import org.keycloak.testsuite.util.RoleBuilder;
|
||||
import org.keycloak.testsuite.util.RolesBuilder;
|
||||
import org.keycloak.testsuite.util.UserBuilder;
|
||||
import org.testcontainers.containers.CockroachContainer;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
|
||||
/**
|
||||
* It tests that object stored by legacy version of keycloak could be read by
|
||||
* current one, then object is modified, therefore stored in current version and
|
||||
* then it's verified it could be read by legacy keycloak.
|
||||
*
|
||||
* See HOW-TO-RUN.md for some additional notes.
|
||||
*
|
||||
* @author vramik
|
||||
*/
|
||||
@Ignore
|
||||
public class ZeroDowntimeTest extends AbstractKeycloakTest {
|
||||
|
||||
@ArquillianResource private ContainerController controller;
|
||||
@ArquillianResource private LegacyKeycloakContainerProvider legacyKeycloakServerProvider;
|
||||
@ArquillianResource private PostgresContainerProvider postgresProvider;
|
||||
@ArquillianResource private CockroachdbContainerProvider cockroachdbProvider;
|
||||
@ArquillianResource private HotRodContainerProvider hotrodProvider;
|
||||
|
||||
private final String legacyKeycloakHost = System.getProperty("keycloak.legacy.host", "localhost");
|
||||
private final String legacyKeycloakPort = System.getProperty("keycloak.legacy.port", "8091");
|
||||
private final String legacyKeycloakUrl = "http://" + legacyKeycloakHost + ":" + legacyKeycloakPort;
|
||||
|
||||
private String currentAuthServer;
|
||||
private SetSystemProperty sysProp;
|
||||
private static boolean initialized;
|
||||
private static Keycloak legacyAdminClient;
|
||||
|
||||
// junit4 enforces to use static method when using @BeforeClass or @ClassRule
|
||||
// TODO: after upgrade to junit5: replace @Before with @BeforeAll and get rid of the "initialized" flag
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
Assume.assumeFalse(LegacyKeycloakContainerProvider.CONTAINER.equals(ZeroDowntimeContainer.NONE));
|
||||
|
||||
if (initialized) return;
|
||||
|
||||
currentAuthServer = suiteContext.getAuthServerInfo().getArquillianContainer().getName();
|
||||
|
||||
// stop current auth-server
|
||||
if (controller.isStarted(currentAuthServer)) {
|
||||
log.debug("Stopping auth server");
|
||||
controller.stop(currentAuthServer);
|
||||
}
|
||||
|
||||
// stop and create new container
|
||||
handleContainer();
|
||||
|
||||
//start legacy container
|
||||
LegacyKeycloakContainer legacyKeycloakServer = legacyKeycloakServerProvider.get();
|
||||
legacyKeycloakServer.start();
|
||||
legacyAdminClient = KeycloakBuilder.builder()
|
||||
.serverUrl(legacyKeycloakUrl)
|
||||
.realm(AuthRealm.MASTER)
|
||||
.username(AuthRealm.ADMIN)
|
||||
.password(AuthRealm.ADMIN)
|
||||
.clientId(Constants.ADMIN_CLI_CLIENT_ID)
|
||||
.resteasyClient(AdminClientUtil.createResteasyClient())
|
||||
.build();
|
||||
|
||||
// import test realm
|
||||
legacyAdminClient.realms().create(RealmBuilder.create()
|
||||
.name(AuthRealm.TEST)
|
||||
.attribute("attr", "val")
|
||||
.client(ClientBuilder.create()
|
||||
.clientId("client"))
|
||||
.clientScope(ClientScopeBuilder.create().name("client_scope"))
|
||||
.roles(RolesBuilder.create()
|
||||
.clientRole("client", RoleBuilder.create().name("client_role").singleAttribute("attr", "val").build())
|
||||
.realmRole(RoleBuilder.create().name("realm_role").singleAttribute("attr", "val").build()))
|
||||
.group(GroupBuilder.create().name("group").build())
|
||||
.user(UserBuilder.create().username("user").addAttribute("attr", "val"))
|
||||
.build());
|
||||
|
||||
// start current auth-server
|
||||
controller.start(currentAuthServer);
|
||||
reconnectAdminClient();
|
||||
|
||||
testContext.registerAfterClassAction(() -> {
|
||||
legacyKeycloakServer.stop();
|
||||
if (sysProp != null) sysProp.revert();
|
||||
});
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
private void handleContainer() {
|
||||
switch (LegacyKeycloakContainerProvider.CONTAINER) {
|
||||
case POSTGRES:
|
||||
handlePostgres();
|
||||
break;
|
||||
case COCKROACH:
|
||||
handleCockroach();
|
||||
break;
|
||||
case HOTROD:
|
||||
handleHotRod();
|
||||
break;
|
||||
case NONE:
|
||||
default:
|
||||
throw new IllegalStateException("Unknown container!");
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePostgres() {
|
||||
PostgreSQLContainer postgres = postgresProvider.getContainer();
|
||||
//if suite container is running stop it
|
||||
if (postgres != null && postgres.isRunning()) {
|
||||
postgres.stop();
|
||||
}
|
||||
if (Boolean.parseBoolean(System.getProperty("postgres.start-container-for-zero-downtime", "true"))) {
|
||||
postgres = postgresProvider.createContainer();
|
||||
postgres.start();
|
||||
|
||||
log.infof("DatabaseInfo: %s, user=%s, pass=%s", postgres.getJdbcUrl(), PostgresContainerProvider.POSTGRES_DB_USER, PostgresContainerProvider.POSTGRES_DB_PASSWORD);
|
||||
|
||||
sysProp = new SetSystemProperty("keycloak.map.storage.connectionsJpa.url", postgres.getJdbcUrl());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCockroach() {
|
||||
final CockroachContainer cockroach = cockroachdbProvider.getContainer();
|
||||
//if suite container is running stop it
|
||||
if (cockroach != null && cockroach.isRunning()) {
|
||||
cockroach.stop();
|
||||
|
||||
//it needs some time to stop
|
||||
Retry.executeWithBackoff(i -> {
|
||||
if (cockroach.isRunning()) {
|
||||
throw new AssertionError(String.format("Stopping CockroachDB container was not successful. Number of attempts: %d", i));
|
||||
}
|
||||
}, Duration.ofMinutes(1), 50);
|
||||
}
|
||||
|
||||
// spawn new container
|
||||
if (Boolean.parseBoolean(System.getProperty("cockroachdb.start-container-for-zero-downtime", "true"))) {
|
||||
CockroachContainer newCockroach = cockroachdbProvider.createContainer();
|
||||
newCockroach.withStartupAttempts(3); // with podman it sometimes fails with com.sun.jna.LastErrorException: https://github.com/testcontainers/testcontainers-java/issues/6640
|
||||
newCockroach.start();
|
||||
|
||||
log.infof("DatabaseInfo: %s, user=%s, pass=%s", newCockroach.getJdbcUrl(), CockroachdbContainerProvider.COCKROACHDB_DB_USER, CockroachdbContainerProvider.COCKROACHDB_DB_PASSWORD);
|
||||
|
||||
sysProp = new SetSystemProperty("keycloak.map.storage.connectionsJpa.url", newCockroach.getJdbcUrl());
|
||||
|
||||
/*
|
||||
* CRDB container fails to connect intermitently with:
|
||||
* org.postgresql.util.PSQLException: FATAL: password authentication failed for user "keycloak"
|
||||
*
|
||||
* It seems it needs some time to set correct permission for a user after fresh start
|
||||
* Waiting for successful connection.
|
||||
*/
|
||||
Retry.executeWithBackoff(i -> {
|
||||
try {
|
||||
DriverManager.getConnection(newCockroach.getJdbcUrl(), CockroachdbContainerProvider.COCKROACHDB_DB_USER, CockroachdbContainerProvider.COCKROACHDB_DB_PASSWORD);
|
||||
} catch (SQLException e) {
|
||||
throw new AssertionError(String.format("Establishing connection was not successful. Number of attempts: %d", i));
|
||||
}
|
||||
}, Duration.ofMinutes(1), 500);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleHotRod() {
|
||||
InfinispanContainer hotRodContainer = hotrodProvider.getContainer();
|
||||
//if suite container is running stop it
|
||||
if (hotRodContainer != null && hotRodContainer.isRunning()) {
|
||||
hotRodContainer.stop();
|
||||
}
|
||||
// spawn new container
|
||||
if (Boolean.parseBoolean(System.getProperty("start-hotrod-container-for-zero-downtime", "true"))) {
|
||||
hotRodContainer = new InfinispanContainer();
|
||||
hotRodContainer.start();
|
||||
|
||||
sysProp = new SetSystemProperty(HotRodContainerProvider.HOT_ROD_STORE_HOST_PROPERTY, hotRodContainer.getHost());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void realmSmokeTest() throws Exception {
|
||||
//realm
|
||||
RealmRepresentation testRealmRep = adminClient.realm(AuthRealm.TEST).toRepresentation();
|
||||
String realmAttribute = testRealmRep.getAttributes().get("attr");
|
||||
assertThat(realmAttribute, equalTo("val"));
|
||||
adminClient.realm(AuthRealm.TEST).update(RealmBuilder.edit(testRealmRep).displayName("displayName").build());
|
||||
|
||||
//verify objects can be read by legacy server
|
||||
RealmRepresentation returnedRealmRep = legacyAdminClient.realm(AuthRealm.TEST).toRepresentation();
|
||||
assertThat(returnedRealmRep.getDisplayName(), is("displayName"));
|
||||
assertThat(returnedRealmRep.getAttributes().get("attr"), is("val"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clientSmokeTest () throws Exception {
|
||||
//client
|
||||
List<ClientRepresentation> clients = adminClient.realm(AuthRealm.TEST).clients().findByClientId("client");
|
||||
assertThat(clients, hasSize(1));
|
||||
ClientRepresentation clientRep = clients.get(0);
|
||||
adminClient.realm(AuthRealm.TEST).clients().get(clientRep.getId()).update(ClientBuilder.edit(clientRep).addRedirectUri("*").build());
|
||||
|
||||
//client role
|
||||
List<RoleRepresentation> clientRoles = adminClient.realm(AuthRealm.TEST).clients().get(clientRep.getId()).roles().list();
|
||||
assertThat(clientRoles, hasSize(1));
|
||||
RoleRepresentation clientRoleRep = clientRoles.get(0);
|
||||
assertThat(clientRoleRep.getName(), is("client_role"));
|
||||
adminClient.realm(AuthRealm.TEST).clients().get(clientRep.getId()).roles().get(clientRoleRep.getName()).update(RoleBuilder.edit(clientRoleRep).description("desc").build());
|
||||
|
||||
//verify objects can be read by legacy server
|
||||
ClientRepresentation returnedClientRep = legacyAdminClient.realm(AuthRealm.TEST).clients().get(clientRep.getId()).toRepresentation();
|
||||
assertThat(returnedClientRep.getRedirectUris(), hasItem("*"));
|
||||
|
||||
RoleRepresentation returnedClientRoleRep = legacyAdminClient.realm(AuthRealm.TEST).clients().get(clientRep.getId()).roles().get(clientRoleRep.getName()).toRepresentation();
|
||||
assertThat(returnedClientRoleRep.getDescription(), is("desc"));
|
||||
assertThat(returnedClientRoleRep.getAttributes().get("attr"), hasItem("val"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clientScopeSmokeTest () throws Exception {
|
||||
//client scope
|
||||
ClientScopeRepresentation clientScopeRep = adminClient.realm(AuthRealm.TEST).clientScopes().findAll().stream().filter(scope -> scope.getName().equals("client_scope")).findFirst().orElse(null);
|
||||
assertThat(clientScopeRep, notNullValue());
|
||||
adminClient.realm(AuthRealm.TEST).clientScopes().get(clientScopeRep.getId()).update(ClientScopeBuilder.edit(clientScopeRep).description("desc").build());
|
||||
|
||||
//verify objects can be read by legacy server
|
||||
ClientScopeRepresentation returnedClientScopeRep = legacyAdminClient.realm(AuthRealm.TEST).clientScopes().get(clientScopeRep.getId()).toRepresentation();
|
||||
assertThat(returnedClientScopeRep.getDescription(), is("desc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userRoleSmokeTest() throws Exception {
|
||||
//user
|
||||
List<UserRepresentation> users = adminClient.realm(AuthRealm.TEST).users().searchByUsername("user", Boolean.TRUE);
|
||||
assertThat(users, hasSize(1));
|
||||
UserRepresentation userRep = users.get(0);
|
||||
adminClient.realm(AuthRealm.TEST).users().get(userRep.getId()).update(UserBuilder.edit(userRep).email("test@test").build());
|
||||
|
||||
//verify objects can be read by legacy server
|
||||
UserRepresentation returnedUserRep = legacyAdminClient.realm(AuthRealm.TEST).users().get(userRep.getId()).toRepresentation();
|
||||
assertThat(returnedUserRep.getEmail(), is("test@test"));
|
||||
assertThat(returnedUserRep.getAttributes().get("attr"), hasItem("val"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roleSmokeTest() throws Exception {
|
||||
//realm role
|
||||
RoleRepresentation realmRoleRep = adminClient.realm(AuthRealm.TEST).roles().get("realm_role").toRepresentation();
|
||||
adminClient.realm(AuthRealm.TEST).roles().get("realm_role").update(RoleBuilder.edit(realmRoleRep).description("desc").build());
|
||||
|
||||
//verify objects can be read by legacy server
|
||||
RoleRepresentation returnedRoleRep = legacyAdminClient.realm(AuthRealm.TEST).roles().get(realmRoleRep.getName()).toRepresentation();
|
||||
assertThat(returnedRoleRep.getDescription(), is("desc"));
|
||||
assertThat(returnedRoleRep.getAttributes().get("attr"), hasItem("val"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void groupSmokeTest() throws Exception {
|
||||
//group
|
||||
List<GroupRepresentation> groups = adminClient.realm(AuthRealm.TEST).groups().groups();
|
||||
assertThat(groups, hasSize(1));
|
||||
GroupRepresentation groupRep = groups.get(0);
|
||||
adminClient.realm(AuthRealm.TEST).groups().group(groupRep.getId()).update(GroupBuilder.edit(groupRep).singleAttribute("attr", "val").build());
|
||||
|
||||
//verify objects can be read by legacy server
|
||||
GroupRepresentation returnedGroupRep = legacyAdminClient.realm(AuthRealm.TEST).groups().group(groupRep.getId()).toRepresentation();
|
||||
assertThat(returnedGroupRep.getAttributes().get("attr"), hasItem("val"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||
}
|
||||
}
|
|
@ -45,4 +45,3 @@ validation,6
|
|||
vault,4
|
||||
welcomepage,6
|
||||
x509,4
|
||||
zerodowntime,1
|
||||
|
|
|
@ -17,4 +17,3 @@ TransactionsTest
|
|||
UserProfileTest
|
||||
org.keycloak.testsuite.admin.**
|
||||
org.keycloak.testsuite.authz.**ManagementTest
|
||||
org.keycloak.testsuite.zerodowntime.**
|
||||
|
|
Loading…
Reference in a new issue