KEYCLOAK-9536 DB Allocator Plugin
This commit is contained in:
parent
ccc8e06f9a
commit
2e7f717e50
22 changed files with 1132 additions and 31 deletions
|
@ -56,13 +56,10 @@ Stop MySQl:
|
|||
Using built-in profiles to run database tests using docker containers
|
||||
-------
|
||||
|
||||
The project provides specific profiles to run database tests using containers. The supported databases and their respective profiles are:
|
||||
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`):
|
||||
|
||||
* `db-mysql`
|
||||
* `db-postgres`
|
||||
* `db-mariadb`
|
||||
* `db-mssql2017`
|
||||
* `db-oracle11g`
|
||||
|
||||
As an example, to run tests using a MySQL docker container on Undertow auth-server:
|
||||
|
||||
|
@ -94,3 +91,31 @@ name or tag for the image.
|
|||
Note that Docker containers may occupy some space even after termination, and
|
||||
especially with databases that might be easily a gigabyte. It is thus
|
||||
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 Wildfly and MSSQL 2016:
|
||||
|
||||
```
|
||||
mvn -f testsuite/integration-arquillian/pom.xml \
|
||||
-Pjpa,auth-server-wildfly,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.
|
||||
|
||||
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` - dor testing with Postgres 9.6.x
|
||||
* `db-allocator-db-mysql` - dor testing with MySQL 5.7
|
76
testsuite/db-allocator-plugin/pom.xml
Normal file
76
testsuite/db-allocator-plugin/pom.xml
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?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>6.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.6.0</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>${maven.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-core</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-client</artifactId>
|
||||
</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>${maven.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,176 @@
|
|||
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.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;
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
} 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());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
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";
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package org.keycloak.testsuite.dballocator.client;
|
||||
|
||||
import org.keycloak.testsuite.dballocator.client.exceptions.DBAllocatorUnavailableException;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface BackoffRetryPolicy {
|
||||
Response retryTillHttpOk(Callable<Response> callableSupplier) throws DBAllocatorUnavailableException;
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
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.ReleaseResult;
|
||||
import org.keycloak.testsuite.dballocator.client.exceptions.DBAllocatorException;
|
||||
import org.keycloak.testsuite.dballocator.client.retry.IncrementalBackoffRetryPolicy;
|
||||
|
||||
import javax.ws.rs.client.Client;
|
||||
import javax.ws.rs.client.Invocation;
|
||||
import javax.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;
|
||||
|
||||
public class DBAllocatorServiceClient {
|
||||
|
||||
private static final int TIMEOUT = 10_000;
|
||||
|
||||
private final Client restClient;
|
||||
private final URI allocatorServletURI;
|
||||
private final BackoffRetryPolicy retryPolicy;
|
||||
|
||||
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 = new ResteasyClientBuilder().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();
|
||||
|
||||
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 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();
|
||||
|
||||
retryPolicy.retryTillHttpOk(() -> target.get());
|
||||
|
||||
return ReleaseResult.successful(allocationResult.getUUID());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package org.keycloak.testsuite.dballocator.client.exceptions;
|
||||
|
||||
import javax.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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package org.keycloak.testsuite.dballocator.client.exceptions;
|
||||
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
public class DBAllocatorUnavailableException extends DBAllocatorException {
|
||||
|
||||
public DBAllocatorUnavailableException(Response errorResponse) {
|
||||
super(errorResponse);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package org.keycloak.testsuite.dballocator.client.retry;
|
||||
|
||||
import org.keycloak.testsuite.dballocator.client.BackoffRetryPolicy;
|
||||
import org.keycloak.testsuite.dballocator.client.exceptions.DBAllocatorUnavailableException;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public Response retryTillHttpOk(Callable<Response> callableSupplier, int totalRetries, int backoffTime, TimeUnit backoffTimeUnit) throws DBAllocatorUnavailableException {
|
||||
int retryCount = 0;
|
||||
Response response = null;
|
||||
while(true) {
|
||||
try {
|
||||
response = callableSupplier.call();
|
||||
} catch (Exception e) {
|
||||
response = null;
|
||||
}
|
||||
|
||||
if (response != null && response.getStatus() == 200) {
|
||||
return response;
|
||||
}
|
||||
|
||||
if (++retryCount > totalRetries) {
|
||||
throw new DBAllocatorUnavailableException(response);
|
||||
}
|
||||
|
||||
LockSupport.parkNanos(backoffTimeUnit.toNanos(backoffTime * retryCount));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
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.exceptions.DBAllocatorException;
|
||||
import org.keycloak.testsuite.dballocator.client.exceptions.DBAllocatorUnavailableException;
|
||||
import org.keycloak.testsuite.dballocator.client.mock.MockResponse;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
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());
|
||||
}
|
||||
|
||||
@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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
package org.keycloak.testsuite.dballocator.client.mock;
|
||||
|
||||
import javax.ws.rs.core.EntityTag;
|
||||
import javax.ws.rs.core.GenericType;
|
||||
import javax.ws.rs.core.Link;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
import javax.ws.rs.core.NewCookie;
|
||||
import javax.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() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
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 javax.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());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
#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
|
5
testsuite/db-allocator-plugin/src/test/resources/log4j.properties
Executable file
5
testsuite/db-allocator-plugin/src/test/resources/log4j.properties
Executable file
|
@ -0,0 +1,5 @@
|
|||
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
|
|
@ -717,6 +717,7 @@ The exact steps to configure Docker depend on the operating system.
|
|||
By default, the test will run against Undertow based embedded Keycloak Server, thus no distribution build is required beforehand.
|
||||
The exact command line arguments depend on the operating system.
|
||||
|
||||
|
||||
### General guidelines
|
||||
|
||||
If docker daemon doesn't run locally, or if you're not running on Linux, you may need
|
||||
|
|
|
@ -94,6 +94,8 @@
|
|||
<keycloak.connectionsJpa.password></keycloak.connectionsJpa.password>
|
||||
<keycloak.connectionsJpa.url>jdbc:h2:mem:test;MVCC=TRUE;DB_CLOSE_DELAY=-1</keycloak.connectionsJpa.url>
|
||||
<keycloak.connectionsJpa.schema>DEFAULT</keycloak.connectionsJpa.schema>
|
||||
|
||||
<dballocator.skip>true</dballocator.skip>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@ -244,6 +246,18 @@
|
|||
<build>
|
||||
<pluginManagement>
|
||||
<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>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.19.1</version>
|
||||
|
@ -272,6 +286,27 @@
|
|||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<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>
|
||||
<execution>
|
||||
<id>release-db</id>
|
||||
<goals>
|
||||
<goal>release</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<modules>
|
||||
|
@ -379,6 +414,16 @@
|
|||
<docker.database.wait-for-log-regex>(?si)Ready for start up.*ready [^\n]{0,30}connections</docker.database.wait-for-log-regex>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>db-allocator-db-mysql</id>
|
||||
<properties>
|
||||
<jdbc.mvn.groupId>mysql</jdbc.mvn.groupId>
|
||||
<jdbc.mvn.artifactId>mysql-connector-java</jdbc.mvn.artifactId>
|
||||
<jdbc.mvn.version>${mysql.version}</jdbc.mvn.version>
|
||||
<dballocator.type>mysql57</dballocator.type>
|
||||
<dballocator.skip>false</dballocator.skip>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>db-postgres</id>
|
||||
<properties>
|
||||
|
@ -396,6 +441,16 @@
|
|||
<docker.database.wait-for-log-regex>(?si)Ready for start up.*ready [^\n]{0,30}connections</docker.database.wait-for-log-regex>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>db-allocator-db-postgres</id>
|
||||
<properties>
|
||||
<jdbc.mvn.groupId>org.postgresql</jdbc.mvn.groupId>
|
||||
<jdbc.mvn.artifactId>postgresql</jdbc.mvn.artifactId>
|
||||
<jdbc.mvn.version>${postgresql.version}</jdbc.mvn.version>
|
||||
<dballocator.type>postgresql96</dballocator.type>
|
||||
<dballocator.skip>false</dballocator.skip>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>db-mariadb</id>
|
||||
<properties>
|
||||
|
@ -413,6 +468,16 @@
|
|||
<docker.database.wait-for-log-regex>(?si)Ready for start up.*ready [^\n]{0,30}connections</docker.database.wait-for-log-regex>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>db-allocator-db-mariadb</id>
|
||||
<properties>
|
||||
<jdbc.mvn.groupId>org.mariadb.jdbc</jdbc.mvn.groupId>
|
||||
<jdbc.mvn.artifactId>mariadb-java-client</jdbc.mvn.artifactId>
|
||||
<jdbc.mvn.version>${mariadb.version}</jdbc.mvn.version>
|
||||
<dballocator.type>mariadb_galera_101</dballocator.type>
|
||||
<dballocator.skip>false</dballocator.skip>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>db-mssql2017</id>
|
||||
<properties>
|
||||
|
@ -431,6 +496,16 @@
|
|||
<jdbc.mvn.version>${mssql.version}</jdbc.mvn.version>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>db-allocator-db-mssql2016</id>
|
||||
<properties>
|
||||
<jdbc.mvn.groupId>com.microsoft.sqlserver</jdbc.mvn.groupId>
|
||||
<jdbc.mvn.artifactId>mssql-jdbc</jdbc.mvn.artifactId>
|
||||
<jdbc.mvn.version>${mssql.version}</jdbc.mvn.version>
|
||||
<dballocator.type>mssql2016</dballocator.type>
|
||||
<dballocator.skip>false</dballocator.skip>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>db-oracle11g</id>
|
||||
<properties>
|
||||
|
@ -450,6 +525,16 @@
|
|||
<jdbc.mvn.version>12.1.0</jdbc.mvn.version>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>db-allocator-db-oracle11g</id>
|
||||
<properties>
|
||||
<jdbc.mvn.groupId>com.oracle</jdbc.mvn.groupId>
|
||||
<jdbc.mvn.artifactId>ojdbc7</jdbc.mvn.artifactId>
|
||||
<jdbc.mvn.version>12.1.0</jdbc.mvn.version>
|
||||
<dballocator.type>oracle11gR1</dballocator.type>
|
||||
<dballocator.skip>false</dballocator.skip>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -103,6 +103,9 @@
|
|||
</target>
|
||||
|
||||
<target name="configure-server-jpa" depends="update-jpa-schema">
|
||||
<!-- I'm intentionally leaving this here. This shows up environment variables that are used during the build.
|
||||
If anything goes wrong, this is the first place to look at -->
|
||||
<echoproperties/>
|
||||
<copy todir="${cli.tmp.dir}">
|
||||
<resources>
|
||||
<file file="${common.resources}/jboss-cli/configure-server-jpa.cli"/>
|
||||
|
|
|
@ -63,6 +63,10 @@
|
|||
|
||||
<!-- default ant scenario -->
|
||||
<ant.scenario>scenario-standalone</ant.scenario>
|
||||
|
||||
<session.cache.owners>1</session.cache.owners>
|
||||
<offline.session.cache.owners>1</offline.session.cache.owners>
|
||||
<login.failure.cache.owners>1</login.failure.cache.owners>
|
||||
</properties>
|
||||
|
||||
<profiles>
|
||||
|
@ -216,16 +220,16 @@
|
|||
</goals>
|
||||
<configuration>
|
||||
<target>
|
||||
<ant antfile="${common.resources}/ant/configure.xml" target="${ant.scenario}-generate">
|
||||
<!-- These properties become equivalent to properties defined on the command line. -->
|
||||
<!-- Without specifying those the default values would be used regardless what is -->
|
||||
<!-- defined via -Dproperty=value when executing maven command -->
|
||||
<property name="auth.server.worker.io-threads">${auth.server.worker.io-threads}</property>
|
||||
<property name="auth.server.worker.task-max-threads">${auth.server.worker.task-max-threads}</property>
|
||||
<!-- Following properties are cluster specific -->
|
||||
<property name="session.cache.owners">${session.cache.owners}</property>
|
||||
<property name="offline.session.cache.owners">${offline.session.cache.owners}</property>
|
||||
<property name="login.failure.cache.owners">${login.failure.cache.owners}</property>
|
||||
<ant antfile="${common.resources}/ant/configure.xml" target="${ant.scenario}-generate" >
|
||||
<!-- In most of the cases, Ant Plugin picks up properties automatically.
|
||||
However, in some rare cases, it will not detect if a property has been overriden
|
||||
in the command line using "-D" switch (see why here: https://technotes.khitrenovich.com/properties-resolution-maven-implications-antrun-plugin/
|
||||
There's also another case, when we have a dynamic property (like "keycloak.connectionsJpa.url")
|
||||
that can change in the runtime. In such cases, we CAN NOT put is as a property (or
|
||||
Ant will see outdated values, not the dynamic ones). -->
|
||||
<property name="session.cache.owners" value="${session.cache.owners}" />
|
||||
<property name="offline.session.cache.owners" value="${offline.session.cache.owners}" />
|
||||
<property name="login.failure.cache.owners" value="${login.failure.cache.owners}" />
|
||||
</ant>
|
||||
</target>
|
||||
</configuration>
|
||||
|
@ -415,18 +419,7 @@
|
|||
</goals>
|
||||
<configuration>
|
||||
<target>
|
||||
<ant antfile="${common.resources}/ant/configure.xml" target="configure-server-jpa">
|
||||
<!-- These properties become equivalent to properties defined on the command line. -->
|
||||
<!-- Without specifying those the default values would be used regardless what is -->
|
||||
<!-- defined via -Dproperty=value when executing maven command -->
|
||||
<property name="jdbc.driver.tmp.dir">${jdbc.driver.tmp.dir}</property>
|
||||
<property name="jdbc.mvn.artifactId">${jdbc.mvn.artifactId}</property>
|
||||
<property name="jdbc.mvn.version">${jdbc.mvn.version}</property>
|
||||
<property name="keycloak.connectionsJpa.url">${keycloak.connectionsJpa.url}</property>
|
||||
<property name="keycloak.connectionsJpa.user">${keycloak.connectionsJpa.user}</property>
|
||||
<property name="keycloak.connectionsJpa.password">${keycloak.connectionsJpa.password}</property>
|
||||
<property name="keycloak.connectionsJpa.schema">${keycloak.connectionsJpa.schema}</property>
|
||||
</ant>
|
||||
<ant antfile="${common.resources}/ant/configure.xml" target="configure-server-jpa" />
|
||||
</target>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
@ -574,11 +567,6 @@
|
|||
<id>auth-server-cluster</id>
|
||||
<properties>
|
||||
<ant.scenario>scenario-cluster</ant.scenario>
|
||||
|
||||
<session.cache.owners>1</session.cache.owners>
|
||||
<offline.session.cache.owners>1</offline.session.cache.owners>
|
||||
<login.failure.cache.owners>1</login.failure.cache.owners>
|
||||
|
||||
<load.metric>simple</load.metric>
|
||||
<!-- The default value 'simple' configures mod-cluster with simple-load-provider.
|
||||
Any other value configures it with dynamic-load-provider using the particular `load.metric`.
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
</plugins>
|
||||
</build>
|
||||
<modules>
|
||||
<module>db-allocator-plugin</module>
|
||||
<module>integration-arquillian</module>
|
||||
<module>utils</module>
|
||||
</modules>
|
||||
|
|
Loading…
Reference in a new issue