Signed-off-by: Lukas Hanusovsky <lhanusov@redhat.com>
This commit is contained in:
parent
8031703228
commit
ca0833b2e4
21 changed files with 3 additions and 1230 deletions
|
@ -56,7 +56,7 @@ Stop MySQl:
|
||||||
Using built-in profiles to run database tests using docker containers
|
Using built-in profiles to run database tests using docker containers
|
||||||
-------
|
-------
|
||||||
|
|
||||||
The project provides specific profiles to run database tests using containers. Below is a just a sample of implemented profiles. In order to get a full list, please invoke (`mvn help:all-profiles -pl testsuite/integration-arquillian | grep -- db- | grep -v allocator`):
|
The project provides specific profiles to run database tests using containers. Below is a just a sample of implemented profiles. In order to get a full list, please invoke (`mvn help:all-profiles -pl testsuite/integration-arquillian | grep -- db-`):
|
||||||
|
|
||||||
* `db-mysql`
|
* `db-mysql`
|
||||||
* `db-postgres`
|
* `db-postgres`
|
||||||
|
@ -84,35 +84,3 @@ name or tag for the image.
|
||||||
Note that Docker containers may occupy some space even after termination, and
|
Note that Docker containers may occupy some space even after termination, and
|
||||||
especially with databases that might be easily a gigabyte. It is thus
|
especially with databases that might be easily a gigabyte. It is thus
|
||||||
advisable to run `docker system prune` occasionally to reclaim that space.
|
advisable to run `docker system prune` occasionally to reclaim that space.
|
||||||
|
|
||||||
|
|
||||||
Using DB Allocator Service
|
|
||||||
-------
|
|
||||||
|
|
||||||
The testsuite can use the DB Allocator Service to allocate and release desired database automatically.
|
|
||||||
Since some of the database properties (such as JDBC URL, Username or Password) need to be used when building the Auth Server,
|
|
||||||
the allocation and deallocation need to happen when building the `integration-arquillian` project (instead of `tests/base` as
|
|
||||||
it happens in other cases).
|
|
||||||
|
|
||||||
In order to use the DB Allocator Service, you must use the `jpa` profile with one of the `db-allocator-*`. Here's a full example to
|
|
||||||
run JPA with Auth Server Quarkus and MSSQL 2016:
|
|
||||||
|
|
||||||
```
|
|
||||||
mvn -f testsuite/integration-arquillian/pom.xml clean verify \
|
|
||||||
-Pjpa,auth-server-quarkus,db-allocator-db-mssql2016 \
|
|
||||||
-Ddballocator.uri=<<db-allocator-servlet-url>> \
|
|
||||||
-Ddballocator.user=<<db-allocator-user>> \
|
|
||||||
-Dmaven.test.failure.ignore=true
|
|
||||||
```
|
|
||||||
|
|
||||||
Using `-Dmaven.test.failure.ignore=true` is not strictly required but highly recommended. After running the tests,
|
|
||||||
the DB Allocator Plugin should release the allocated database.
|
|
||||||
|
|
||||||
**NOTE**: If you killed the maven surefire test preliminary (for example with CTRL-C or `kill -9` command), it will be
|
|
||||||
good to manually release the allocated database. Please check `dballocator.uri` and add `?operation=report` to the end of the URL.
|
|
||||||
Find your DB in the GUI and release it manually.
|
|
||||||
|
|
||||||
Below is a just a sample of implemented profiles. In order to get a full list, please invoke (`mvn help:all-profiles -pl testsuite/integration-arquillian | grep -- db-allocator-db-`):
|
|
||||||
|
|
||||||
* `db-allocator-db-postgres` - for testing with Postgres 9.6.x
|
|
||||||
* `db-allocator-db-mysql` - for testing with MySQL 5.7
|
|
|
@ -1,81 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright 2019 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
|
||||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<parent>
|
|
||||||
<artifactId>keycloak-testsuite-pom</artifactId>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<version>999.0.0-SNAPSHOT</version>
|
|
||||||
</parent>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<artifactId>db-allocator-plugin</artifactId>
|
|
||||||
<packaging>maven-plugin</packaging>
|
|
||||||
<name>DB Allocator Plugin</name>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<maven.version>3.3.9</maven.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.maven</groupId>
|
|
||||||
<artifactId>maven-plugin-api</artifactId>
|
|
||||||
<version>${maven.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.maven.plugin-tools</groupId>
|
|
||||||
<artifactId>maven-plugin-annotations</artifactId>
|
|
||||||
<version>3.4</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.maven</groupId>
|
|
||||||
<artifactId>maven-core</artifactId>
|
|
||||||
<version>${maven.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.resteasy</groupId>
|
|
||||||
<artifactId>resteasy-client</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-io</groupId>
|
|
||||||
<artifactId>commons-io</artifactId>
|
|
||||||
<version>2.11.0</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-plugin-plugin</artifactId>
|
|
||||||
<version>3.6.0</version>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
|
|
@ -1,184 +0,0 @@
|
||||||
package org.keycloak.testsuite.dballocator;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.maven.plugin.AbstractMojo;
|
|
||||||
import org.apache.maven.plugin.MojoFailureException;
|
|
||||||
import org.apache.maven.plugin.logging.Log;
|
|
||||||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
|
||||||
import org.apache.maven.plugins.annotations.Mojo;
|
|
||||||
import org.apache.maven.plugins.annotations.Parameter;
|
|
||||||
import org.apache.maven.project.MavenProject;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.data.AllocationResult;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.DBAllocatorServiceClient;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.data.EraseResult;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.exceptions.DBAllocatorException;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.retry.IncrementalBackoffRetryPolicy;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocated a DB from DB Allocator Service.
|
|
||||||
*/
|
|
||||||
@Mojo(name = "allocate", defaultPhase = LifecyclePhase.PROCESS_TEST_RESOURCES)
|
|
||||||
public class AllocateDBMojo extends AbstractMojo {
|
|
||||||
|
|
||||||
|
|
||||||
private final Log logger = getLog();
|
|
||||||
|
|
||||||
@Parameter(defaultValue = "${project}", required = true, readonly = true)
|
|
||||||
protected MavenProject project;
|
|
||||||
|
|
||||||
@Parameter(defaultValue = "${reactorProjects}", readonly = true)
|
|
||||||
List<MavenProject> reactorProjects;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables printing out a summary after execution.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_PRINT_SUMMARY, defaultValue = "true")
|
|
||||||
private boolean printSummary;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Skips the execution of this Mojo.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_SKIP, defaultValue = "false")
|
|
||||||
private boolean skip;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The number of retries for reaching the DB Allocator Service
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_RETRY_TOTAL_RETRIES, defaultValue = "3")
|
|
||||||
private int totalRetries;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Backoff time for reaching out the DB Allocator Service.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_RETRY_BACKOFF_SECONDS, defaultValue = "10")
|
|
||||||
private int backoffTimeSeconds;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* URI to the DB Allocator Service.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_DB_ALLOCATOR_URI)
|
|
||||||
private String dbAllocatorURI;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Username used for allocating DBs.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_DB_ALLOCATOR_USER)
|
|
||||||
private String user;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fallback username used for allocating DBs.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_DB_ALLOCATOR_USER_FALLBACK)
|
|
||||||
private String fallbackUser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type of the database to be used.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_DB_ALLOCATOR_DATABASE_TYPE)
|
|
||||||
private String type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expiration in minutes.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_DB_ALLOCATOR_EXPIRATION_MIN, defaultValue = "1440")
|
|
||||||
private int expirationInMinutes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Preferred DB location.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_DB_ALLOCATOR_LOCATION, defaultValue = "geo_RDU")
|
|
||||||
private String location;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A property set as an output of this Mojo for JDBC Driver.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_TO_BE_SET_DRIVER, defaultValue = "keycloak.connectionsJpa.driver")
|
|
||||||
private String propertyDriver;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A property set as an output of this Mojo for Database Schema.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_TO_BE_SET_DATABASE, defaultValue = "keycloak.connectionsJpa.database")
|
|
||||||
private String propertyDatabase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A property set as an output of this Mojo for DB Username.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_TO_BE_SET_USER, defaultValue = "keycloak.connectionsJpa.user")
|
|
||||||
private String propertyUser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A property set as an output of this Mojo for DB Password.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_TO_BE_SET_PASSWORD, defaultValue = "keycloak.connectionsJpa.password")
|
|
||||||
private String propertyPassword;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A property set as an output of this Mojo for JDBC Connection URI.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_TO_BE_SET_JDBC_URL, defaultValue = "keycloak.connectionsJpa.url")
|
|
||||||
private String propertyURL;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() throws MojoFailureException {
|
|
||||||
if (skip) {
|
|
||||||
logger.info("Skipping");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("Total retries: " + totalRetries + "; backOffTime: " + backoffTimeSeconds);
|
|
||||||
try {
|
|
||||||
IncrementalBackoffRetryPolicy retryPolicy = new IncrementalBackoffRetryPolicy(totalRetries, backoffTimeSeconds, TimeUnit.SECONDS);
|
|
||||||
DBAllocatorServiceClient client = new DBAllocatorServiceClient(dbAllocatorURI, retryPolicy);
|
|
||||||
|
|
||||||
setFallbackUserIfNecessary();
|
|
||||||
AllocationResult allocate = client.allocate(user, type, expirationInMinutes, TimeUnit.MINUTES, location);
|
|
||||||
|
|
||||||
reactorProjects.forEach((project) -> setPropertiesToProject(project, allocate));
|
|
||||||
|
|
||||||
if (printSummary) {
|
|
||||||
logger.info("Allocated database:");
|
|
||||||
logger.info("-- UUID: " + allocate.getUUID());
|
|
||||||
logger.info("-- Driver: " + allocate.getDriver());
|
|
||||||
logger.info("-- Database: " + allocate.getDatabase());
|
|
||||||
logger.info("-- User: " + allocate.getUser());
|
|
||||||
logger.info("-- Password: " + allocate.getPassword());
|
|
||||||
logger.info("-- URL: " + allocate.getURL());
|
|
||||||
}
|
|
||||||
|
|
||||||
EraseResult eraseResult = client.erase(allocate);
|
|
||||||
if (printSummary) {
|
|
||||||
logger.info("Erased database:");
|
|
||||||
logger.info("-- UUID: " + eraseResult.getUUID());
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (DBAllocatorException e) {
|
|
||||||
String error = e.getMessage();
|
|
||||||
if (e.getErrorResponse() != null) {
|
|
||||||
error = String.format("[%s](%s)", e.getErrorResponse().getStatus(), e.getErrorResponse().readEntity(String.class));
|
|
||||||
}
|
|
||||||
throw new MojoFailureException("An error occurred while communicating with DBAllocator (" + error + ")", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setFallbackUserIfNecessary() {
|
|
||||||
if (StringUtils.isBlank(user)) {
|
|
||||||
if (StringUtils.isBlank(fallbackUser)) {
|
|
||||||
throw new IllegalArgumentException("Both " + Constants.PROPERTY_DB_ALLOCATOR_USER + " and " + Constants.PROPERTY_DB_ALLOCATOR_USER_FALLBACK + " are empty");
|
|
||||||
}
|
|
||||||
user = fallbackUser;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setPropertiesToProject(MavenProject project, AllocationResult allocate) {
|
|
||||||
project.getProperties().setProperty(propertyDriver, allocate.getDriver());
|
|
||||||
project.getProperties().setProperty(propertyDatabase, allocate.getDatabase());
|
|
||||||
project.getProperties().setProperty(propertyUser, allocate.getUser());
|
|
||||||
project.getProperties().setProperty(propertyPassword, allocate.getPassword());
|
|
||||||
project.getProperties().setProperty(propertyURL, allocate.getURL());
|
|
||||||
project.getProperties().setProperty(Constants.PROPERTY_ALLOCATED_DB, allocate.getUUID());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
package org.keycloak.testsuite.dballocator;
|
|
||||||
|
|
||||||
public interface Constants {
|
|
||||||
String PROPERTY_ALLOCATED_DB = "dballocator.allocated.uuid";
|
|
||||||
String PROPERTY_DB_ALLOCATOR_URI = "dballocator.uri";
|
|
||||||
String PROPERTY_DB_ALLOCATOR_USER = "dballocator.user";
|
|
||||||
String PROPERTY_DB_ALLOCATOR_USER_FALLBACK = "user.name";
|
|
||||||
String PROPERTY_DB_ALLOCATOR_DATABASE_TYPE = "dballocator.type";
|
|
||||||
String PROPERTY_DB_ALLOCATOR_EXPIRATION_MIN = "dballocator.expirationMin";
|
|
||||||
String PROPERTY_DB_ALLOCATOR_LOCATION = "dballocator.location";
|
|
||||||
String PROPERTY_TO_BE_SET_DRIVER = "dballocator.properties.driver";
|
|
||||||
String PROPERTY_TO_BE_SET_DATABASE = "dballocator.properties.database";
|
|
||||||
String PROPERTY_TO_BE_SET_USER = "dballocator.properties.user";
|
|
||||||
String PROPERTY_TO_BE_SET_PASSWORD = "dballocator.properties.password";
|
|
||||||
String PROPERTY_TO_BE_SET_JDBC_URL = "dballocator.properties.url";
|
|
||||||
String PROPERTY_PRINT_SUMMARY = "dballocator.summary";
|
|
||||||
String PROPERTY_SKIP = "dballocator.skip";
|
|
||||||
String PROPERTY_RETRY_TOTAL_RETRIES = "dballocator.retry.totalRetries";
|
|
||||||
String PROPERTY_RETRY_BACKOFF_SECONDS = "dballocator.retry.backoffSeconds";
|
|
||||||
}
|
|
|
@ -1,93 +0,0 @@
|
||||||
package org.keycloak.testsuite.dballocator;
|
|
||||||
|
|
||||||
import org.apache.maven.plugin.AbstractMojo;
|
|
||||||
import org.apache.maven.plugin.MojoFailureException;
|
|
||||||
import org.apache.maven.plugin.logging.Log;
|
|
||||||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
|
||||||
import org.apache.maven.plugins.annotations.Mojo;
|
|
||||||
import org.apache.maven.plugins.annotations.Parameter;
|
|
||||||
import org.apache.maven.project.MavenProject;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.data.AllocationResult;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.DBAllocatorServiceClient;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.exceptions.DBAllocatorException;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.retry.IncrementalBackoffRetryPolicy;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.data.ReleaseResult;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Releases a DB from DB Allocator Service.
|
|
||||||
*/
|
|
||||||
@Mojo(name = "release", defaultPhase = LifecyclePhase.TEST)
|
|
||||||
public class ReleaseDBMojo extends AbstractMojo {
|
|
||||||
|
|
||||||
private final Log logger = getLog();
|
|
||||||
|
|
||||||
@Parameter(defaultValue = "${project}", required = true)
|
|
||||||
protected MavenProject project;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables printing out a summary after execution.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_PRINT_SUMMARY, defaultValue = "true")
|
|
||||||
private boolean printSummary;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Skips the execution of this Mojo.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_SKIP, defaultValue = "false")
|
|
||||||
private boolean skip;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The number of retries for reaching the DB Allocator Service
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_RETRY_TOTAL_RETRIES, defaultValue = "3")
|
|
||||||
private int totalRetries;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Backoff time for reaching out the DB Allocator Service.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_RETRY_BACKOFF_SECONDS, defaultValue = "10")
|
|
||||||
private int backoffTimeSeconds;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* URI to the DB Allocator Service.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_DB_ALLOCATOR_URI)
|
|
||||||
private String dbAllocatorURI;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* UUID for releasing the allocated DB.
|
|
||||||
*/
|
|
||||||
@Parameter(property = Constants.PROPERTY_ALLOCATED_DB)
|
|
||||||
private String allocatedUUID;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() throws MojoFailureException {
|
|
||||||
if (skip) {
|
|
||||||
logger.info("Skipping");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("Total retries: " + totalRetries + "; backOffTime: " + backoffTimeSeconds);
|
|
||||||
try {
|
|
||||||
IncrementalBackoffRetryPolicy retryPolicy = new IncrementalBackoffRetryPolicy(totalRetries, backoffTimeSeconds, TimeUnit.SECONDS);
|
|
||||||
DBAllocatorServiceClient client = new DBAllocatorServiceClient(dbAllocatorURI, retryPolicy);
|
|
||||||
|
|
||||||
ReleaseResult release = client.release(AllocationResult.forRelease(allocatedUUID));
|
|
||||||
|
|
||||||
if (printSummary) {
|
|
||||||
logger.info("Released database:");
|
|
||||||
logger.info("-- UUID: " + release.getUUID());
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (DBAllocatorException e) {
|
|
||||||
String error = e.getMessage();
|
|
||||||
if (e.getErrorResponse() != null) {
|
|
||||||
error = String.format("[%s](%s)", e.getErrorResponse().getStatus(), e.getErrorResponse().readEntity(String.class));
|
|
||||||
}
|
|
||||||
throw new MojoFailureException("An error occurred while communicating with DBAllocator (" + error + ")", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package org.keycloak.testsuite.dballocator.client;
|
|
||||||
|
|
||||||
import org.keycloak.testsuite.dballocator.client.exceptions.DBAllocatorUnavailableException;
|
|
||||||
|
|
||||||
import jakarta.ws.rs.core.Response;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface BackoffRetryPolicy {
|
|
||||||
Response retryTillHttpOk(Callable<Response> callableSupplier) throws DBAllocatorUnavailableException;
|
|
||||||
}
|
|
|
@ -1,119 +0,0 @@
|
||||||
package org.keycloak.testsuite.dballocator.client;
|
|
||||||
|
|
||||||
import org.apache.http.client.config.RequestConfig;
|
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
|
||||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
|
||||||
import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient43Engine;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.data.AllocationResult;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.data.EraseResult;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.data.ReleaseResult;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.exceptions.DBAllocatorException;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.retry.IncrementalBackoffRetryPolicy;
|
|
||||||
|
|
||||||
import jakarta.ws.rs.client.Client;
|
|
||||||
import jakarta.ws.rs.client.Invocation;
|
|
||||||
import jakarta.ws.rs.core.Response;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
|
|
||||||
public class DBAllocatorServiceClient {
|
|
||||||
|
|
||||||
private static final int TIMEOUT = 10_000;
|
|
||||||
|
|
||||||
private final Client restClient;
|
|
||||||
private final URI allocatorServletURI;
|
|
||||||
private final BackoffRetryPolicy retryPolicy;
|
|
||||||
private final Logger logger = Logger.getLogger(DBAllocatorServiceClient.class);
|
|
||||||
|
|
||||||
public DBAllocatorServiceClient(String allocatorServletURI, BackoffRetryPolicy retryPolicy) {
|
|
||||||
Objects.requireNonNull(allocatorServletURI, "DB Allocator URI must not be null");
|
|
||||||
|
|
||||||
this.allocatorServletURI = URI.create(allocatorServletURI);
|
|
||||||
this.retryPolicy = retryPolicy != null ? retryPolicy : new IncrementalBackoffRetryPolicy();
|
|
||||||
this.restClient = ((ResteasyClientBuilder) ResteasyClientBuilder.newBuilder()).httpEngine(createEngine()).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private final ApacheHttpClient43Engine createEngine() {
|
|
||||||
RequestConfig reqConfig = RequestConfig.custom()
|
|
||||||
.setConnectTimeout(TIMEOUT)
|
|
||||||
.setSocketTimeout(TIMEOUT)
|
|
||||||
.setConnectionRequestTimeout(TIMEOUT)
|
|
||||||
.build();
|
|
||||||
CloseableHttpClient httpClient = HttpClientBuilder.create()
|
|
||||||
.setDefaultRequestConfig(reqConfig)
|
|
||||||
.setMaxConnTotal(1)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
ApacheHttpClient43Engine engine = new ApacheHttpClient43Engine(httpClient);
|
|
||||||
engine.setFollowRedirects(true);
|
|
||||||
return engine;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AllocationResult allocate(String user, String type, int expiration, TimeUnit expirationTimeUnit, String location) throws DBAllocatorException {
|
|
||||||
Objects.requireNonNull(user, "User can not be null");
|
|
||||||
Objects.requireNonNull(type, "DB Type must not be null");
|
|
||||||
|
|
||||||
try {
|
|
||||||
String typeWithLocation = location != null ? type + "&&" + location : type;
|
|
||||||
Invocation.Builder target = restClient
|
|
||||||
.target(allocatorServletURI)
|
|
||||||
.queryParam("operation", "allocate")
|
|
||||||
.queryParam("requestee", user)
|
|
||||||
.queryParam("expression", typeWithLocation)
|
|
||||||
.queryParam("expiry", expirationTimeUnit.toMinutes(expiration))
|
|
||||||
.request();
|
|
||||||
|
|
||||||
logger.info("Calling " + allocatorServletURI);
|
|
||||||
Response response = retryPolicy.retryTillHttpOk(() -> target.get());
|
|
||||||
Properties properties = new Properties();
|
|
||||||
String content = response.readEntity(String.class);
|
|
||||||
|
|
||||||
if (content != null) {
|
|
||||||
try(InputStream is = new ByteArrayInputStream(content.getBytes())) {
|
|
||||||
properties.load(is);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return AllocationResult.successful(properties);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new DBAllocatorException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public EraseResult erase(AllocationResult allocationResult) throws DBAllocatorException {
|
|
||||||
Objects.requireNonNull(allocationResult, "Previous allocation result must not be null");
|
|
||||||
Objects.requireNonNull(allocationResult.getUUID(), "UUID must not be null");
|
|
||||||
|
|
||||||
Invocation.Builder target = restClient
|
|
||||||
.target(allocatorServletURI)
|
|
||||||
.queryParam("operation", "erase")
|
|
||||||
.queryParam("uuid", allocationResult.getUUID())
|
|
||||||
.request();
|
|
||||||
|
|
||||||
try (Response response = retryPolicy.retryTillHttpOk(() -> target.get())) {
|
|
||||||
return EraseResult.successful(allocationResult.getUUID());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReleaseResult release(AllocationResult allocationResult) throws DBAllocatorException {
|
|
||||||
Objects.requireNonNull(allocationResult, "Previous allocation result must not be null");
|
|
||||||
Objects.requireNonNull(allocationResult.getUUID(), "UUID must not be null");
|
|
||||||
|
|
||||||
Invocation.Builder target = restClient
|
|
||||||
.target(allocatorServletURI)
|
|
||||||
.queryParam("operation", "dealloc")
|
|
||||||
.queryParam("uuid", allocationResult.getUUID())
|
|
||||||
.request();
|
|
||||||
|
|
||||||
try (Response response = retryPolicy.retryTillHttpOk(() -> target.get())) {
|
|
||||||
return ReleaseResult.successful(allocationResult.getUUID());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
package org.keycloak.testsuite.dballocator.client.data;
|
|
||||||
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
public class AllocationResult {
|
|
||||||
|
|
||||||
private final String uuid;
|
|
||||||
private final String driver;
|
|
||||||
private final String database;
|
|
||||||
private final String user;
|
|
||||||
private final String password;
|
|
||||||
private final String url;
|
|
||||||
|
|
||||||
private AllocationResult(String uuid) {
|
|
||||||
this.uuid = uuid;
|
|
||||||
this.driver = null;
|
|
||||||
this.database = null;
|
|
||||||
this.user = null;
|
|
||||||
this.password = null;
|
|
||||||
this.url = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private AllocationResult(String uuid, String driver, String database, String user, String password, String url) {
|
|
||||||
this.uuid = uuid;
|
|
||||||
this.driver = driver;
|
|
||||||
this.database = database;
|
|
||||||
this.user = user;
|
|
||||||
this.password = password;
|
|
||||||
this.url = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AllocationResult forRelease(String uuid) {
|
|
||||||
return new AllocationResult(uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AllocationResult successful(Properties properties) {
|
|
||||||
return new AllocationResult(
|
|
||||||
properties.getProperty("uuid"),
|
|
||||||
properties.getProperty("db.jdbc_class"),
|
|
||||||
properties.getProperty("db.name"),
|
|
||||||
properties.getProperty("db.username"),
|
|
||||||
properties.getProperty("db.password"),
|
|
||||||
properties.getProperty("db.jdbc_url"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDriver() {
|
|
||||||
return driver;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDatabase() {
|
|
||||||
return database;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUser() {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPassword() {
|
|
||||||
return password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getURL() {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUUID() {
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "AllocationResult{" +
|
|
||||||
"uuid='" + uuid + '\'' +
|
|
||||||
", driver='" + driver + '\'' +
|
|
||||||
", database='" + database + '\'' +
|
|
||||||
", user='" + user + '\'' +
|
|
||||||
", password='" + password + '\'' +
|
|
||||||
", url='" + url + '\'' +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2017 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.dballocator.client.data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
|
||||||
*/
|
|
||||||
public class EraseResult {
|
|
||||||
|
|
||||||
private final String uuid;
|
|
||||||
|
|
||||||
private EraseResult(String uuid) {
|
|
||||||
this.uuid = uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static EraseResult successful(String uuid) {
|
|
||||||
return new EraseResult(uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUUID() {
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "EraseResult{" +
|
|
||||||
"uuid='" + uuid + '\'' +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
package org.keycloak.testsuite.dballocator.client.data;
|
|
||||||
|
|
||||||
public class ReleaseResult {
|
|
||||||
|
|
||||||
private final String uuid;
|
|
||||||
|
|
||||||
private ReleaseResult(String uuid) {
|
|
||||||
this.uuid = uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ReleaseResult successful(String uuid) {
|
|
||||||
return new ReleaseResult(uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUUID() {
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ReleaseResult{" +
|
|
||||||
"uuid='" + uuid + '\'' +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
package org.keycloak.testsuite.dballocator.client.exceptions;
|
|
||||||
|
|
||||||
import jakarta.ws.rs.core.Response;
|
|
||||||
|
|
||||||
public class DBAllocatorException extends Exception {
|
|
||||||
|
|
||||||
private Response errorResponse;
|
|
||||||
|
|
||||||
public DBAllocatorException(Response errorResponse) {
|
|
||||||
this.errorResponse = errorResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DBAllocatorException(Response errorResponse, Throwable throwable) {
|
|
||||||
super(throwable);
|
|
||||||
this.errorResponse = errorResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DBAllocatorException(Throwable throwable) {
|
|
||||||
super(throwable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Response getErrorResponse() {
|
|
||||||
return errorResponse;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package org.keycloak.testsuite.dballocator.client.exceptions;
|
|
||||||
|
|
||||||
|
|
||||||
import jakarta.ws.rs.core.Response;
|
|
||||||
|
|
||||||
public class DBAllocatorUnavailableException extends DBAllocatorException {
|
|
||||||
|
|
||||||
public DBAllocatorUnavailableException(Response errorResponse) {
|
|
||||||
super(errorResponse);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
package org.keycloak.testsuite.dballocator.client.retry;
|
|
||||||
|
|
||||||
import org.keycloak.testsuite.dballocator.client.BackoffRetryPolicy;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.exceptions.DBAllocatorUnavailableException;
|
|
||||||
|
|
||||||
import jakarta.ws.rs.core.Response;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.locks.LockSupport;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
|
|
||||||
public class IncrementalBackoffRetryPolicy implements BackoffRetryPolicy {
|
|
||||||
|
|
||||||
public static final int DEFAULT_TOTAL_RETRIES = 3;
|
|
||||||
public static final int DEFAULT_BACKOFF_TIME = 10;
|
|
||||||
public static final TimeUnit DEFAULT_BACKOFF_TIME_UNIT = TimeUnit.SECONDS;
|
|
||||||
|
|
||||||
private final int totalRetries;
|
|
||||||
private final int backoffTime;
|
|
||||||
private final TimeUnit backoffTimeUnit;
|
|
||||||
private final Logger logger = Logger.getLogger(IncrementalBackoffRetryPolicy.class);
|
|
||||||
|
|
||||||
public IncrementalBackoffRetryPolicy() {
|
|
||||||
this(DEFAULT_TOTAL_RETRIES, DEFAULT_BACKOFF_TIME, DEFAULT_BACKOFF_TIME_UNIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IncrementalBackoffRetryPolicy(int totalRetries, int backoffTime, TimeUnit backoffTimeUnit) {
|
|
||||||
this.backoffTime = backoffTime;
|
|
||||||
this.backoffTimeUnit = backoffTimeUnit;
|
|
||||||
this.totalRetries = totalRetries;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Response retryTillHttpOk(Callable<Response> callableSupplier) throws DBAllocatorUnavailableException {
|
|
||||||
return retryTillHttpOk(callableSupplier, totalRetries, backoffTime, backoffTimeUnit);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Response retryTillHttpOk(Callable<Response> callableSupplier, int totalRetries, int backoffTime, TimeUnit backoffTimeUnit) throws DBAllocatorUnavailableException {
|
|
||||||
int retryCount = 0;
|
|
||||||
Response response;
|
|
||||||
while(true) {
|
|
||||||
try {
|
|
||||||
response = callableSupplier.call();
|
|
||||||
} catch (Exception e) {
|
|
||||||
response = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response != null) {
|
|
||||||
logger.info("Response status: " + response.getStatus());
|
|
||||||
if (response.getStatus() == 200) {
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("retryCount: " + (retryCount + 1) + ", totalRetries: " + totalRetries);
|
|
||||||
if (++retryCount > totalRetries) {
|
|
||||||
logger.info("retryCount exceeded: " + retryCount);
|
|
||||||
throw new DBAllocatorUnavailableException(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("backoffTime * retryCount: " + backoffTime * retryCount);
|
|
||||||
LockSupport.parkNanos(backoffTimeUnit.toNanos(backoffTime * retryCount));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,71 +0,0 @@
|
||||||
package org.keycloak.testsuite.dballocator.client;
|
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.data.AllocationResult;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.data.EraseResult;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.data.ReleaseResult;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.exceptions.DBAllocatorException;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.exceptions.DBAllocatorUnavailableException;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.mock.MockResponse;
|
|
||||||
|
|
||||||
import jakarta.ws.rs.core.Response;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
|
|
||||||
public class DBAllocatorServiceClientTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuccessfulAllocation() throws Exception {
|
|
||||||
//given
|
|
||||||
String mockURI = "http://localhost:8080/test";
|
|
||||||
|
|
||||||
String testProperties = null;
|
|
||||||
try(InputStream is = DBAllocatorServiceClientTest.class.getResourceAsStream("/db-allocator-response.properties")) {
|
|
||||||
testProperties = IOUtils.toString(is, Charset.defaultCharset());
|
|
||||||
}
|
|
||||||
|
|
||||||
Response successfulResponse = new MockResponse(200, testProperties);
|
|
||||||
BackoffRetryPolicy retryPolicyMock = callableSupplier -> successfulResponse;
|
|
||||||
|
|
||||||
DBAllocatorServiceClient client = new DBAllocatorServiceClient(mockURI, retryPolicyMock);
|
|
||||||
|
|
||||||
//when
|
|
||||||
AllocationResult allocationResult = client.allocate("user", "mariadb_galera_101", 1440, TimeUnit.SECONDS, "geo_RDU");
|
|
||||||
|
|
||||||
//then
|
|
||||||
Assert.assertEquals("d328bb0e-3dcc-42da-8ce1-83738a8dfede", allocationResult.getUUID());
|
|
||||||
Assert.assertEquals("org.mariadb.jdbc.Driver", allocationResult.getDriver());
|
|
||||||
Assert.assertEquals("dbname", allocationResult.getDatabase());
|
|
||||||
Assert.assertEquals("username", allocationResult.getUser());
|
|
||||||
Assert.assertEquals("password", allocationResult.getPassword());
|
|
||||||
Assert.assertEquals("jdbc:mariadb://mariadb-101-galera.keycloak.org:3306", allocationResult.getURL());
|
|
||||||
|
|
||||||
EraseResult erase = client.erase(allocationResult);
|
|
||||||
ReleaseResult result = client.release(allocationResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFailureAllocation() throws Exception {
|
|
||||||
//given
|
|
||||||
String mockURI = "http://localhost:8080/test";
|
|
||||||
|
|
||||||
Response serverErrorResponse = new MockResponse(500, null);
|
|
||||||
BackoffRetryPolicy retryPolicyMock = callableSupplier -> {
|
|
||||||
throw new DBAllocatorUnavailableException(serverErrorResponse);
|
|
||||||
};
|
|
||||||
|
|
||||||
DBAllocatorServiceClient client = new DBAllocatorServiceClient(mockURI, retryPolicyMock);
|
|
||||||
|
|
||||||
//when
|
|
||||||
try {
|
|
||||||
client.allocate("user", "mariadb_galera_101", 1440, TimeUnit.SECONDS, "geo_RDU");
|
|
||||||
Assert.fail();
|
|
||||||
} catch (DBAllocatorException e) {
|
|
||||||
Assert.assertEquals(500, e.getErrorResponse().getStatus());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,158 +0,0 @@
|
||||||
package org.keycloak.testsuite.dballocator.client.mock;
|
|
||||||
|
|
||||||
import jakarta.ws.rs.core.EntityTag;
|
|
||||||
import jakarta.ws.rs.core.GenericType;
|
|
||||||
import jakarta.ws.rs.core.Link;
|
|
||||||
import jakarta.ws.rs.core.MediaType;
|
|
||||||
import jakarta.ws.rs.core.MultivaluedMap;
|
|
||||||
import jakarta.ws.rs.core.NewCookie;
|
|
||||||
import jakarta.ws.rs.core.Response;
|
|
||||||
import java.lang.annotation.Annotation;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class MockResponse extends Response {
|
|
||||||
|
|
||||||
private final int status;
|
|
||||||
private final String entity;
|
|
||||||
|
|
||||||
public MockResponse(int status, String entity) {
|
|
||||||
this.status = status;
|
|
||||||
this.entity = entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StatusType getStatusInfo() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getEntity() {
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T readEntity(Class<T> aClass) {
|
|
||||||
if (aClass.isAssignableFrom(String.class)) {
|
|
||||||
return (T) entity;
|
|
||||||
}
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T readEntity(GenericType<T> genericType) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T readEntity(Class<T> aClass, Annotation[] annotations) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T readEntity(GenericType<T> genericType, Annotation[] annotations) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasEntity() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean bufferEntity() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MediaType getMediaType() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Locale getLanguage() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLength() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getAllowedMethods() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, NewCookie> getCookies() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EntityTag getEntityTag() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Date getDate() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Date getLastModified() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public URI getLocation() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<Link> getLinks() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasLink(String s) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Link getLink(String s) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Link.Builder getLinkBuilder(String s) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MultivaluedMap<String, Object> getMetadata() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MultivaluedMap<String, String> getStringHeaders() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getHeaderString(String s) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
package org.keycloak.testsuite.dballocator.client.retry;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.exceptions.DBAllocatorUnavailableException;
|
|
||||||
import org.keycloak.testsuite.dballocator.client.retry.IncrementalBackoffRetryPolicy;
|
|
||||||
|
|
||||||
import jakarta.ws.rs.core.Response;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.LongAdder;
|
|
||||||
|
|
||||||
|
|
||||||
public class IncrementalBackoffRetryPolicyTest {
|
|
||||||
|
|
||||||
static class BackoffCounter implements Callable<Response> {
|
|
||||||
|
|
||||||
LongAdder adder = new LongAdder();
|
|
||||||
Response responseToReport;
|
|
||||||
|
|
||||||
public BackoffCounter(Response responseToReport) {
|
|
||||||
this.responseToReport = responseToReport;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Response call() throws Exception {
|
|
||||||
adder.add(1);
|
|
||||||
return responseToReport;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getCounter() {
|
|
||||||
return adder.longValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testBackoffLoop() {
|
|
||||||
//given
|
|
||||||
long expectedNumberOfRetries = 2;
|
|
||||||
long expectedNumberOfInvocations = expectedNumberOfRetries + 1;
|
|
||||||
BackoffCounter counter = new BackoffCounter(Response.serverError().build());
|
|
||||||
IncrementalBackoffRetryPolicy backoffRetryPolicy = new IncrementalBackoffRetryPolicy((int) expectedNumberOfRetries, 0, TimeUnit.NANOSECONDS);
|
|
||||||
|
|
||||||
//when
|
|
||||||
try {
|
|
||||||
backoffRetryPolicy.retryTillHttpOk(counter);
|
|
||||||
Assert.fail();
|
|
||||||
} catch (DBAllocatorUnavailableException e) {
|
|
||||||
//then
|
|
||||||
Assert.assertEquals(expectedNumberOfInvocations, counter.getCounter().longValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIgnoringBackoffWhenGettingSuccessfulResponse() throws Exception {
|
|
||||||
//given
|
|
||||||
BackoffCounter counter = new BackoffCounter(Response.ok().build());
|
|
||||||
IncrementalBackoffRetryPolicy backoffRetryPolicy = new IncrementalBackoffRetryPolicy(3, 0, TimeUnit.NANOSECONDS);
|
|
||||||
|
|
||||||
//when
|
|
||||||
Response response = backoffRetryPolicy.retryTillHttpOk(counter);
|
|
||||||
|
|
||||||
//then
|
|
||||||
Assert.assertEquals(1, counter.getCounter().longValue());
|
|
||||||
Assert.assertEquals(200, response.getStatus());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
#Generated by DBAllocator
|
|
||||||
#Mon Mar 18 12:49:24 UTC 2019
|
|
||||||
db.password=password
|
|
||||||
hibernate.connection.password=password
|
|
||||||
hibernate41.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
|
|
||||||
broken=false
|
|
||||||
db.username=username
|
|
||||||
server_geo=RDU
|
|
||||||
dballoc.db_type=clustered
|
|
||||||
db.name=dbname
|
|
||||||
db.jdbc_url=jdbc\:mariadb\://mariadb-101-galera.keycloak.org\:3306
|
|
||||||
datasource.class.xa=org.mariadb.jdbc.MySQLDataSource
|
|
||||||
server_uid=RDU_mariadb_galera_101
|
|
||||||
hibernate33.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
|
|
||||||
hibernate.connection.username=username
|
|
||||||
server_labels=mariadb_galera_101
|
|
||||||
db.jdbc_class=org.mariadb.jdbc.Driver
|
|
||||||
db.schema=dballo01
|
|
||||||
hibernate.connection.driver_class=org.mariadb.jdbc.Driver
|
|
||||||
uuid=d328bb0e-3dcc-42da-8ce1-83738a8dfede
|
|
||||||
db.primary_label=mariadb_galera_101
|
|
||||||
server_label_primary=mariadb_galera_101
|
|
||||||
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
|
|
||||||
hibernate.connection.url=jdbc\:mariadb\://mariadb-101-galera-01.keycloak.org\:3306
|
|
||||||
hibernate.connection.schema=dballo01
|
|
|
@ -1,5 +0,0 @@
|
||||||
log4j.rootLogger=info, stdout
|
|
||||||
|
|
||||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
|
||||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
|
||||||
log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p %t [%c] %m%n
|
|
|
@ -77,8 +77,6 @@
|
||||||
<jdbc.mvn.version>${h2.version}</jdbc.mvn.version>
|
<jdbc.mvn.version>${h2.version}</jdbc.mvn.version>
|
||||||
|
|
||||||
<keycloak.connectionsJpa.schema>DEFAULT</keycloak.connectionsJpa.schema>
|
<keycloak.connectionsJpa.schema>DEFAULT</keycloak.connectionsJpa.schema>
|
||||||
|
|
||||||
<dballocator.skip>true</dballocator.skip>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
|
@ -235,18 +233,6 @@
|
||||||
<build>
|
<build>
|
||||||
<pluginManagement>
|
<pluginManagement>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>db-allocator-plugin</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<configuration>
|
|
||||||
<propertyDatabase>keycloak.connectionsJpa.database</propertyDatabase>
|
|
||||||
<propertyDriver>keycloak.connectionsJpa.driver</propertyDriver>
|
|
||||||
<propertyURL>keycloak.connectionsJpa.url</propertyURL>
|
|
||||||
<propertyUser>keycloak.connectionsJpa.user</propertyUser>
|
|
||||||
<propertyPassword>keycloak.connectionsJpa.password</propertyPassword>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
|
@ -326,28 +312,6 @@
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
|
||||||
<id>jpa</id>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<!-- Just allocate the DB now. It will be released after the tests, so the "release" is declared in the base-tests module -->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>db-allocator-plugin</artifactId>
|
|
||||||
<inherited>false</inherited>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>allocate-db</id>
|
|
||||||
<goals>
|
|
||||||
<goal>allocate</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
|
|
||||||
<profile>
|
<profile>
|
||||||
<id>test-70-migration</id>
|
<id>test-70-migration</id>
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -429,13 +393,11 @@
|
||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
<!-- Specifies default DB properties, which are used for test with embedded H2. Those are overriden when testing with any docker container
|
<!-- Specifies default DB properties, which are used for test with embedded H2. Those are overriden when testing with any docker container
|
||||||
profile like "db-mysql" or any dballocator profile. Also those can be manually overriden when running the test from CMD -->
|
profile like "db-mysql". Also those can be manually overriden when running the test from CMD -->
|
||||||
<profile>
|
<profile>
|
||||||
<id>db-default-properties</id>
|
<id>db-default-properties</id>
|
||||||
<activation>
|
<activation>
|
||||||
<property>
|
<activeByDefault>true</activeByDefault>
|
||||||
<name>!dballocator.uri</name>
|
|
||||||
</property>
|
|
||||||
</activation>
|
</activation>
|
||||||
<properties>
|
<properties>
|
||||||
<keycloak.connectionsJpa.driver>org.h2.Driver</keycloak.connectionsJpa.driver>
|
<keycloak.connectionsJpa.driver>org.h2.Driver</keycloak.connectionsJpa.driver>
|
||||||
|
@ -468,14 +430,6 @@
|
||||||
<docker.database.wait-for-log-regex>(?si)Ready for start up.*ready [^\n]{0,30}connections</docker.database.wait-for-log-regex>
|
<docker.database.wait-for-log-regex>(?si)Ready for start up.*ready [^\n]{0,30}connections</docker.database.wait-for-log-regex>
|
||||||
</properties>
|
</properties>
|
||||||
</profile>
|
</profile>
|
||||||
<profile>
|
|
||||||
<id>db-allocator-db-mysql</id>
|
|
||||||
<properties>
|
|
||||||
<keycloak.storage.connections.vendor>mysql</keycloak.storage.connections.vendor>
|
|
||||||
<dballocator.type>mysql80</dballocator.type>
|
|
||||||
<dballocator.skip>false</dballocator.skip>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
<profile>
|
<profile>
|
||||||
<id>db-postgres</id>
|
<id>db-postgres</id>
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -516,22 +470,6 @@
|
||||||
<jdbc.mvn.version>${aws-jdbc-wrapper.version}</jdbc.mvn.version>
|
<jdbc.mvn.version>${aws-jdbc-wrapper.version}</jdbc.mvn.version>
|
||||||
</properties>
|
</properties>
|
||||||
</profile>
|
</profile>
|
||||||
<profile>
|
|
||||||
<id>db-allocator-db-postgres</id>
|
|
||||||
<properties>
|
|
||||||
<keycloak.storage.connections.vendor>postgres</keycloak.storage.connections.vendor>
|
|
||||||
<dballocator.type>postgresql132</dballocator.type>
|
|
||||||
<dballocator.skip>false</dballocator.skip>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
<profile>
|
|
||||||
<id>db-allocator-db-postgresplus</id>
|
|
||||||
<properties>
|
|
||||||
<keycloak.storage.connections.vendor>postgres</keycloak.storage.connections.vendor>
|
|
||||||
<dballocator.type>postgresplus131</dballocator.type>
|
|
||||||
<dballocator.skip>false</dballocator.skip>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
<profile>
|
<profile>
|
||||||
<id>db-mariadb</id>
|
<id>db-mariadb</id>
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -555,14 +493,6 @@
|
||||||
<docker.database.wait-for-log-regex>(?si)Ready for start up.*ready [^\n]{0,30}connections</docker.database.wait-for-log-regex>
|
<docker.database.wait-for-log-regex>(?si)Ready for start up.*ready [^\n]{0,30}connections</docker.database.wait-for-log-regex>
|
||||||
</properties>
|
</properties>
|
||||||
</profile>
|
</profile>
|
||||||
<profile>
|
|
||||||
<id>db-allocator-db-mariadb</id>
|
|
||||||
<properties>
|
|
||||||
<keycloak.storage.connections.vendor>mariadb</keycloak.storage.connections.vendor>
|
|
||||||
<dballocator.type>mariadb_galera_103</dballocator.type>
|
|
||||||
<dballocator.skip>false</dballocator.skip>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
<profile>
|
<profile>
|
||||||
<id>db-mssql</id>
|
<id>db-mssql</id>
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -586,14 +516,6 @@
|
||||||
<jdbc.mvn.version>${mssql-jdbc.version}</jdbc.mvn.version>
|
<jdbc.mvn.version>${mssql-jdbc.version}</jdbc.mvn.version>
|
||||||
</properties>
|
</properties>
|
||||||
</profile>
|
</profile>
|
||||||
<profile>
|
|
||||||
<id>db-allocator-db-mssql2019</id>
|
|
||||||
<properties>
|
|
||||||
<keycloak.storage.connections.vendor>mssql</keycloak.storage.connections.vendor>
|
|
||||||
<dballocator.type>mssql2019</dballocator.type>
|
|
||||||
<dballocator.skip>false</dballocator.skip>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
<profile>
|
<profile>
|
||||||
<id>db-oracle</id>
|
<id>db-oracle</id>
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -619,14 +541,6 @@
|
||||||
<jdbc.mvn.version>${oracle-jdbc.version}</jdbc.mvn.version>
|
<jdbc.mvn.version>${oracle-jdbc.version}</jdbc.mvn.version>
|
||||||
</properties>
|
</properties>
|
||||||
</profile>
|
</profile>
|
||||||
<profile>
|
|
||||||
<id>db-allocator-db-oracleRAC</id>
|
|
||||||
<properties>
|
|
||||||
<keycloak.storage.connections.vendor>oracle</keycloak.storage.connections.vendor>
|
|
||||||
<dballocator.type>oracle19cRAC</dballocator.type>
|
|
||||||
<dballocator.skip>false</dballocator.skip>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -454,27 +454,6 @@
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
|
||||||
<id>jpa</id>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<!-- DB will be released after the test -->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>db-allocator-plugin</artifactId>
|
|
||||||
<inherited>false</inherited>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>release-db</id>
|
|
||||||
<goals>
|
|
||||||
<goal>release</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
|
|
||||||
<profile>
|
<profile>
|
||||||
<id>app-server-wildfly</id>
|
<id>app-server-wildfly</id>
|
||||||
|
|
|
@ -50,7 +50,6 @@
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
<modules>
|
<modules>
|
||||||
<module>db-allocator-plugin</module>
|
|
||||||
<module>integration-arquillian</module>
|
<module>integration-arquillian</module>
|
||||||
<module>model</module>
|
<module>model</module>
|
||||||
<module>utils</module>
|
<module>utils</module>
|
||||||
|
|
Loading…
Reference in a new issue