KEYCLOAK-1678 Reorganized containers handling. (WIP: adapter-libs installation via CLI doesn't work)
This commit is contained in:
parent
eae52a563c
commit
3a51b3530d
37 changed files with 892 additions and 581 deletions
|
@ -0,0 +1,187 @@
|
|||
package org.keycloak.testsuite.arquillian;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import org.jboss.arquillian.container.spi.Container;
|
||||
import org.jboss.arquillian.container.test.api.ContainerController;
|
||||
import org.jboss.arquillian.core.api.Instance;
|
||||
import org.jboss.arquillian.core.api.InstanceProducer;
|
||||
import org.jboss.arquillian.core.api.annotation.Inject;
|
||||
import org.jboss.arquillian.core.api.annotation.Observes;
|
||||
import org.jboss.arquillian.test.spi.annotation.ClassScoped;
|
||||
import org.jboss.arquillian.test.spi.event.suite.BeforeClass;
|
||||
import org.jboss.logging.Logger;
|
||||
import static org.keycloak.testsuite.arquillian.AuthServerTestEnricher.getAuthServerContextRoot;
|
||||
import static org.keycloak.testsuite.arquillian.AuthServerTestEnricher.getAuthServerQualifier;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AdapterLibsLocationProperty;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import static org.keycloak.testsuite.util.IOUtil.execCommand;
|
||||
import org.keycloak.testsuite.util.LogChecker;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.pause;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tkyjovsk
|
||||
*/
|
||||
public class AppServerTestEnricher {
|
||||
|
||||
protected final Logger log = Logger.getLogger(this.getClass());
|
||||
|
||||
@Inject
|
||||
@ClassScoped
|
||||
private InstanceProducer<TestContext> testContextProducer;
|
||||
private TestContext testContext;
|
||||
|
||||
@Inject
|
||||
private Instance<ContainerController> containerController;
|
||||
|
||||
public static String getAppServerQualifier(Class testClass) {
|
||||
Class<? extends AuthServerTestEnricher> annotatedClass = getNearestSuperclassWithAnnotation(testClass, AppServerContainer.class);
|
||||
|
||||
String appServerQ = (annotatedClass == null ? null
|
||||
: annotatedClass.getAnnotation(AppServerContainer.class).value());
|
||||
|
||||
return appServerQ;
|
||||
}
|
||||
|
||||
public static String getAppServerContextRoot() {
|
||||
return getAppServerContextRoot(0);
|
||||
}
|
||||
|
||||
public static String getAppServerContextRoot(int clusterPortOffset) {
|
||||
int httpPort = Integer.parseInt(System.getProperty("app.server.http.port")); // property must be set
|
||||
int httpsPort = Integer.parseInt(System.getProperty("app.server.https.port")); // property must be set
|
||||
boolean sslRequired = Boolean.parseBoolean(System.getProperty("app.server.ssl.required"));
|
||||
|
||||
return sslRequired
|
||||
? "https://localhost:" + (httpsPort + clusterPortOffset)
|
||||
: "http://localhost:" + (httpPort + clusterPortOffset);
|
||||
}
|
||||
|
||||
private ContainerInfo initializeAppServerInfo(Container appServerContainer) {
|
||||
return initializeAppServerInfo(appServerContainer, 0);
|
||||
}
|
||||
|
||||
private ContainerInfo initializeAppServerInfo(Container appServerContainer, int clusterPortOffset) {
|
||||
ContainerInfo appServerInfo = new ContainerInfo(appServerContainer);
|
||||
try {
|
||||
|
||||
String appServerContextRootStr = isRelative(testContext.getTestClass())
|
||||
? getAuthServerContextRoot(clusterPortOffset)
|
||||
: getAppServerContextRoot(clusterPortOffset);
|
||||
|
||||
appServerInfo.setContextRoot(new URL(appServerContextRootStr));
|
||||
|
||||
} catch (MalformedURLException ex) {
|
||||
throw new IllegalArgumentException(ex);
|
||||
}
|
||||
return appServerInfo;
|
||||
}
|
||||
|
||||
public void updateTestContextWithAppServerInfo(@Observes BeforeClass event) {
|
||||
testContext = testContextProducer.get();
|
||||
String appServerQualifier = getAppServerQualifier(testContext.getTestClass());
|
||||
for (Container container : testContext.getSuiteContext().getArquillianContainers()) {
|
||||
if (container.getContainerConfiguration().getContainerName().equals(appServerQualifier)) {
|
||||
testContext.setAppServerInfo(initializeAppServerInfo(container));
|
||||
}
|
||||
}
|
||||
// validate app server
|
||||
if (appServerQualifier != null && testContext.getAppServerInfo() == null) {
|
||||
throw new RuntimeException(String.format("No app server container matching '%s' was activated. Check if defined and enabled in arquillian.xml.", appServerQualifier));
|
||||
}
|
||||
log.info("\n\n" + testContext);
|
||||
}
|
||||
|
||||
public void startAppServer(@Observes(precedence = -1) BeforeClass event) throws MalformedURLException, InterruptedException, IOException {
|
||||
ContainerController controller = containerController.get();
|
||||
if (testContext.isAdapterTest()) {
|
||||
String appServerQualifier = testContext.getAppServerInfo().getQualifier();
|
||||
if (!controller.isStarted(appServerQualifier)) {
|
||||
controller.start(appServerQualifier);
|
||||
}
|
||||
log.info("\n\n\nAPP SERVER STARTED\n\n\n");
|
||||
// install adapter libs on JBoss-based container via CLI
|
||||
// if (testContext.getAppServerInfo().isJBossBased()) {
|
||||
installAdapterLibsUsingJBossCLIClient(testContext.getAppServerInfo());
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
private void installAdapterLibsUsingJBossCLIClient(ContainerInfo appServerInfo) throws InterruptedException, IOException {
|
||||
|
||||
log.info("Installing adapter via CLI client");
|
||||
|
||||
if (!appServerInfo.isJBossBased()) {
|
||||
throw new IllegalArgumentException("App server must be JBoss-based to run jboss-cli-client.");
|
||||
}
|
||||
|
||||
String jbossHomePath = appServerInfo.getProperties().get("jbossHome");
|
||||
|
||||
File bin = new File(jbossHomePath + "/bin");
|
||||
String command = "java -jar " + jbossHomePath + "/bin/client/jboss-cli-client.jar";
|
||||
String adapterScript = "adapter-install.cli";
|
||||
String samlAdapterScript = "adapter-install-saml.cli";
|
||||
String managementPort = appServerInfo.getProperties().get("managementPort");
|
||||
|
||||
String controllerArg = " --controller=localhost:" + managementPort;
|
||||
if (new File(bin, adapterScript).exists()) {
|
||||
log.info("Installing adapter to app server via cli script");
|
||||
execCommand(command + " --connect --file=" + adapterScript + controllerArg, bin);
|
||||
}
|
||||
if (new File(bin, samlAdapterScript).exists()) {
|
||||
log.info("Installing saml adapter to app server via cli script");
|
||||
execCommand(command + " --connect --file=" + samlAdapterScript + controllerArg, bin);
|
||||
}
|
||||
if (new File(bin, adapterScript).exists() || new File(bin, samlAdapterScript).exists()) {
|
||||
log.info("Restarting container");
|
||||
execCommand(command + " --connect --command=reload" + controllerArg, bin);
|
||||
log.info("Container restarted");
|
||||
pause(5000);
|
||||
LogChecker.checkJBossServerLog(jbossHomePath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param testClass
|
||||
* @param annotationClass
|
||||
* @return testClass or the nearest superclass of testClass annotated with
|
||||
* annotationClass
|
||||
*/
|
||||
public static Class getNearestSuperclassWithAnnotation(Class testClass, Class annotationClass) {
|
||||
return testClass.isAnnotationPresent(annotationClass) ? testClass
|
||||
: (testClass.getSuperclass().equals(Object.class) ? null // stop recursion
|
||||
: getNearestSuperclassWithAnnotation(testClass.getSuperclass(), annotationClass)); // continue recursion
|
||||
}
|
||||
|
||||
public static boolean hasAppServerContainerAnnotation(Class testClass) {
|
||||
return getNearestSuperclassWithAnnotation(testClass, AppServerContainer.class) != null;
|
||||
}
|
||||
|
||||
public static boolean isRelative(Class testClass) {
|
||||
return getAppServerQualifier(testClass).equals(getAuthServerQualifier());
|
||||
}
|
||||
|
||||
public static String getAdapterLibsLocationProperty(Class testClass) {
|
||||
Class<? extends AuthServerTestEnricher> annotatedClass = getNearestSuperclassWithAnnotation(testClass, AdapterLibsLocationProperty.class);
|
||||
return (annotatedClass == null ? null
|
||||
: annotatedClass.getAnnotation(AdapterLibsLocationProperty.class).value());
|
||||
}
|
||||
|
||||
public static boolean isWildflyAppServer(Class testClass) {
|
||||
return getAppServerQualifier(testClass).contains("wildfly");
|
||||
}
|
||||
|
||||
public static boolean isTomcatAppServer(Class testClass) {
|
||||
return getAppServerQualifier(testClass).contains("tomcat");
|
||||
}
|
||||
|
||||
public static boolean isOSGiAppServer(Class testClass) {
|
||||
String q = getAppServerQualifier(testClass);
|
||||
return q.contains("karaf") || q.contains("fuse");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.testsuite.arquillian;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.jboss.arquillian.container.spi.Container;
|
||||
import org.jboss.arquillian.container.spi.ContainerRegistry;
|
||||
import org.jboss.arquillian.container.spi.event.StartContainer;
|
||||
import org.jboss.arquillian.container.spi.event.StartSuiteContainers;
|
||||
import org.jboss.arquillian.container.test.api.ContainerController;
|
||||
import org.jboss.arquillian.core.api.Event;
|
||||
import org.jboss.arquillian.core.api.Instance;
|
||||
import org.jboss.arquillian.core.api.InstanceProducer;
|
||||
import org.jboss.arquillian.core.api.annotation.Inject;
|
||||
import org.jboss.arquillian.core.api.annotation.Observes;
|
||||
import org.jboss.arquillian.test.spi.annotation.ClassScoped;
|
||||
import org.jboss.arquillian.test.spi.annotation.SuiteScoped;
|
||||
import org.jboss.arquillian.test.spi.event.suite.BeforeClass;
|
||||
import org.jboss.arquillian.test.spi.event.suite.BeforeSuite;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.testsuite.util.LogChecker;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tkyjovsk
|
||||
* @author vramik
|
||||
*/
|
||||
public class AuthServerTestEnricher {
|
||||
|
||||
protected final Logger log = Logger.getLogger(this.getClass());
|
||||
|
||||
@Inject
|
||||
private Instance<ContainerRegistry> containerRegistry;
|
||||
|
||||
@Inject
|
||||
private Instance<ContainerController> containerController;
|
||||
|
||||
@Inject
|
||||
private Event<StartContainer> startContainerEvent;
|
||||
|
||||
private static final String AUTH_SERVER_CONTAINER_PROPERTY = "auth.server.container";
|
||||
private static final String AUTH_SERVER_CONTAINER_DEFAULT = "auth-server-undertow";
|
||||
|
||||
private static final String MIGRATED_AUTH_SERVER_CONTAINER_PROPERTY = "migrated.auth.server.container";
|
||||
|
||||
@Inject
|
||||
@SuiteScoped
|
||||
private InstanceProducer<SuiteContext> suiteContextProducer;
|
||||
private SuiteContext suiteContext;
|
||||
|
||||
@Inject
|
||||
@ClassScoped
|
||||
private InstanceProducer<TestContext> testContextProducer;
|
||||
|
||||
public static String getAuthServerQualifier() {
|
||||
return System.getProperty(AUTH_SERVER_CONTAINER_PROPERTY, AUTH_SERVER_CONTAINER_DEFAULT);
|
||||
}
|
||||
|
||||
public static String getMigratedAuthServerQualifier() {
|
||||
return System.getProperty(MIGRATED_AUTH_SERVER_CONTAINER_PROPERTY); // == null if migration not enabled
|
||||
}
|
||||
|
||||
public static String getAuthServerContextRoot() {
|
||||
return getAuthServerContextRoot(0);
|
||||
}
|
||||
|
||||
public static String getAuthServerContextRoot(int clusterPortOffset) {
|
||||
int httpPort = Integer.parseInt(System.getProperty("auth.server.http.port")); // property must be set
|
||||
int httpsPort = Integer.parseInt(System.getProperty("auth.server.https.port")); // property must be set
|
||||
boolean sslRequired = Boolean.parseBoolean(System.getProperty("auth.server.ssl.required"));
|
||||
|
||||
return sslRequired
|
||||
? "https://localhost:" + (httpsPort + clusterPortOffset)
|
||||
: "http://localhost:" + (httpPort + clusterPortOffset);
|
||||
}
|
||||
|
||||
public void initializeSuiteContext(@Observes(precedence = 2) BeforeSuite event) {
|
||||
suiteContext = new SuiteContext(new ArrayList<>(containerRegistry.get().getContainers()));
|
||||
|
||||
String authServerQualifier = getAuthServerQualifier();
|
||||
String migratedAuthServerQualifier = getMigratedAuthServerQualifier();
|
||||
|
||||
// init authServerInfo and authServerBackendsInfo
|
||||
if (authServerQualifier.startsWith("auth-server-")) {
|
||||
|
||||
boolean authServerCluster = authServerQualifier.endsWith("-cluster");
|
||||
|
||||
String authServerType = authServerQualifier.replaceAll("^auth-server-", "").replaceAll("-cluster$", "");
|
||||
String authServerFrontend = authServerCluster
|
||||
? "auth-server-" + authServerType + "-balancer" // in cluster mode the load-balancer container serves as auth server frontend
|
||||
: authServerQualifier; // single-node mode
|
||||
String authServerBackend = "auth-server-" + authServerType + "-backend";
|
||||
int backends = 0;
|
||||
for (Container container : suiteContext.getArquillianContainers()) {
|
||||
// frontend
|
||||
if (container.getContainerConfiguration().getContainerName().equals(authServerFrontend)) {
|
||||
suiteContext.setAuthServerInfo(initializeAuthServerInfo(container));
|
||||
}
|
||||
// backends
|
||||
if (container.getContainerConfiguration().getContainerName().startsWith(authServerBackend)) {
|
||||
suiteContext.getAuthServerBackendsInfo().add(initializeAuthServerInfo(container, ++backends));
|
||||
}
|
||||
}
|
||||
|
||||
// validate auth server setup
|
||||
if (suiteContext.getAuthServerInfo() == null) {
|
||||
throw new RuntimeException(String.format("No auth server activated. A container matching '%s' needs to be enabled in arquillian.xml.", authServerFrontend));
|
||||
}
|
||||
if (authServerCluster && !suiteContext.getAuthServerBackendsInfo().isEmpty()) {
|
||||
throw new RuntimeException(String.format("No cluster backend nodes activated. Containers matching '%sN' need to be enabled in arquillian.xml.", authServerBackend));
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new IllegalArgumentException(String.format("Value of %s should start with 'auth-server-' prefix.", AUTH_SERVER_CONTAINER_PROPERTY));
|
||||
}
|
||||
|
||||
if (migratedAuthServerQualifier != null) {
|
||||
// init migratedAuthServerInfo
|
||||
if (migratedAuthServerQualifier.startsWith("migrated-auth-server-")) {
|
||||
for (Container container : suiteContext.getArquillianContainers()) {
|
||||
// migrated auth server
|
||||
if (container.getContainerConfiguration().getContainerName().equals(migratedAuthServerQualifier)) {
|
||||
suiteContext.setMigratedAuthServerInfo(initializeAuthServerInfo(container));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException(String.format("Value of %s should start with 'migrated-auth-server-' prefix.", MIGRATED_AUTH_SERVER_CONTAINER_PROPERTY));
|
||||
}
|
||||
// validate setup
|
||||
if (suiteContext.getMigratedAuthServerInfo() == null) {
|
||||
throw new RuntimeException(String.format("Migration test was enabled but no auth server from which to migrate was activated. "
|
||||
+ "A container matching '%s' needs to be enabled in arquillian.xml.", migratedAuthServerQualifier));
|
||||
}
|
||||
}
|
||||
|
||||
suiteContextProducer.set(suiteContext);
|
||||
log.info("\n\n" + suiteContext);
|
||||
}
|
||||
|
||||
public void initializeTestContext(@Observes(precedence = 1) BeforeClass event) {
|
||||
TestContext testContext = new TestContext(suiteContext, event.getTestClass().getJavaClass());
|
||||
testContextProducer.set(testContext);
|
||||
}
|
||||
|
||||
private ContainerInfo initializeAuthServerInfo(Container authServerContainer) {
|
||||
return initializeAuthServerInfo(authServerContainer, 0);
|
||||
}
|
||||
|
||||
private ContainerInfo initializeAuthServerInfo(Container authServerContainer, int clusterPortOffset) {
|
||||
ContainerInfo authServerInfo = new ContainerInfo(authServerContainer);
|
||||
try {
|
||||
authServerInfo.setContextRoot(new URL(getAuthServerContextRoot(clusterPortOffset)));
|
||||
} catch (MalformedURLException ex) {
|
||||
throw new IllegalArgumentException(ex);
|
||||
}
|
||||
return authServerInfo;
|
||||
}
|
||||
|
||||
public void startMigratedContainer(@Observes(precedence = 2) StartSuiteContainers event) {
|
||||
if (suiteContext.isAuthServerMigrationEnabled()) {
|
||||
log.info("\n\n### Starting keycloak " + System.getProperty("version", "- previous") + " ###\n");
|
||||
startContainerEvent.fire(new StartContainer(suiteContext.getMigratedAuthServerInfo().getArquillianContainer()));
|
||||
}
|
||||
}
|
||||
|
||||
public void stopMigratedContainer(@Observes(precedence = 1) StartSuiteContainers event) {
|
||||
if (suiteContext.isAuthServerMigrationEnabled()) {
|
||||
containerController.get().stop(suiteContext.getAuthServerInfo().getQualifier());
|
||||
}
|
||||
}
|
||||
|
||||
public void checkServerLogs(@Observes(precedence = -1) BeforeSuite event) throws IOException, InterruptedException {
|
||||
boolean checkLog = System.getProperty("auth.server.log.check", "true").equals("true");
|
||||
if (checkLog && suiteContext.getAuthServerInfo().isJBossBased()) {
|
||||
String jbossHomePath = suiteContext.getAuthServerInfo().getProperties().get("jbossHome");
|
||||
LogChecker.checkJBossServerLog(jbossHomePath);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package org.keycloak.testsuite.arquillian;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import org.jboss.arquillian.container.spi.Container;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tkyjovsk
|
||||
*/
|
||||
public class ContainerInfo {
|
||||
|
||||
private URL contextRoot;
|
||||
private Container arquillianContainer;
|
||||
|
||||
public ContainerInfo(Container arquillianContainer) {
|
||||
if (arquillianContainer == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.arquillianContainer = arquillianContainer;
|
||||
}
|
||||
|
||||
public Container getArquillianContainer() {
|
||||
return arquillianContainer;
|
||||
}
|
||||
|
||||
public Map<String, String> getProperties() {
|
||||
return getArquillianContainer().getContainerConfiguration().getContainerProperties();
|
||||
}
|
||||
|
||||
public String getQualifier() {
|
||||
return getArquillianContainer().getName();
|
||||
}
|
||||
|
||||
public URL getContextRoot() {
|
||||
return contextRoot;
|
||||
}
|
||||
|
||||
public void setContextRoot(URL contextRoot) {
|
||||
this.contextRoot = contextRoot;
|
||||
}
|
||||
|
||||
public boolean isAS7() {
|
||||
return getQualifier().contains("as7");
|
||||
}
|
||||
|
||||
public boolean isWildfly() {
|
||||
return getQualifier().contains("Wildfly");
|
||||
}
|
||||
|
||||
public boolean isEAP() {
|
||||
return getQualifier().contains("eap");
|
||||
}
|
||||
|
||||
public boolean isJBossBased() {
|
||||
return isAS7() || isWildfly() || isEAP();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getQualifier();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,362 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.arquillian;
|
||||
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.ADMIN;
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.pause;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.jboss.arquillian.container.spi.Container;
|
||||
import org.jboss.arquillian.container.spi.ContainerRegistry;
|
||||
import org.jboss.arquillian.container.spi.event.StartSuiteContainers;
|
||||
import org.jboss.arquillian.container.spi.event.StopSuiteContainers;
|
||||
import org.jboss.arquillian.container.spi.event.container.AfterStart;
|
||||
import org.jboss.arquillian.container.test.api.ContainerController;
|
||||
import org.jboss.arquillian.core.api.Event;
|
||||
import org.jboss.arquillian.core.api.Instance;
|
||||
import org.jboss.arquillian.core.api.InstanceProducer;
|
||||
import org.jboss.arquillian.core.api.annotation.Inject;
|
||||
import org.jboss.arquillian.core.api.annotation.Observes;
|
||||
import org.jboss.arquillian.test.spi.annotation.ClassScoped;
|
||||
import org.jboss.arquillian.test.spi.annotation.SuiteScoped;
|
||||
import org.jboss.arquillian.test.spi.event.suite.BeforeClass;
|
||||
import org.jboss.arquillian.test.spi.event.suite.BeforeSuite;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AdapterLibsLocationProperty;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.util.OAuthClient;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tkyjovsk
|
||||
* @author vramik
|
||||
*/
|
||||
public class ContainersTestEnricher {
|
||||
|
||||
protected final Logger log = Logger.getLogger(this.getClass());
|
||||
|
||||
@Inject
|
||||
private Instance<ContainerController> containerController;
|
||||
|
||||
@Inject
|
||||
private Instance<ContainerRegistry> containerRegistry;
|
||||
|
||||
@Inject
|
||||
private Event<StopSuiteContainers> stopSuiteContainers;
|
||||
|
||||
private String appServerQualifier;
|
||||
|
||||
private static final String AUTH_SERVER_CONTAINER_PROPERTY = "auth.server.container";
|
||||
private static final String AUTH_SERVER_CONTAINER_DEFAULT = "auth-server-undertow";
|
||||
|
||||
@Inject
|
||||
@SuiteScoped
|
||||
private InstanceProducer<SuiteContext> suiteContext;
|
||||
|
||||
@Inject
|
||||
@ClassScoped
|
||||
private InstanceProducer<TestContext> testContext;
|
||||
|
||||
@Inject
|
||||
@ClassScoped
|
||||
private InstanceProducer<Keycloak> adminClient;
|
||||
|
||||
@Inject
|
||||
@ClassScoped
|
||||
private InstanceProducer<OAuthClient> oauthClient;
|
||||
|
||||
private ContainerController controller;
|
||||
private LinkedList<Container> containers;
|
||||
|
||||
private String jbossHomePath;
|
||||
private final boolean migrationTests = System.getProperty("migration", "false").equals("true");
|
||||
private final boolean skipInstallAdapters = System.getProperty("skip.install.adapters", "false").equals("true");
|
||||
private boolean alreadyInstalled = false;
|
||||
private boolean alreadyStopped = false;
|
||||
private boolean init = false;
|
||||
|
||||
private void init() {
|
||||
if (!init) {
|
||||
containers = new LinkedList<>(containerRegistry.get().getContainers());
|
||||
}
|
||||
init = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* non-javadoc
|
||||
*
|
||||
* Before starting suite containers. Initialization of containers is done
|
||||
* (only once during class life cycle)
|
||||
*/
|
||||
public void startSuiteContainers(@Observes(precedence = 1) StartSuiteContainers event) {
|
||||
init();
|
||||
if (migrationTests) {
|
||||
log.info("\n\n### Starting keycloak " + System.getProperty("version", "- previous") + " ###\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* non-javadoc
|
||||
*
|
||||
* After start container. Server logs are checked (in case jboss based container).
|
||||
* In case of migration scenario: previous container is stopped.
|
||||
*/
|
||||
public void afterStart(@Observes AfterStart event) throws IOException, InterruptedException {
|
||||
Container container = containers.pollFirst();
|
||||
|
||||
if (isJBossBased(container)) {
|
||||
jbossHomePath = container.getContainerConfiguration().getContainerProperties().get("jbossHome");
|
||||
log.debug("jbossHome: " + jbossHomePath + "\n");
|
||||
}
|
||||
checkServerLog(jbossHomePath);
|
||||
|
||||
if (migrationTests && !alreadyStopped) {
|
||||
log.info("\n\n### Stopping keycloak " + System.getProperty("version", "- previous") + " ###\n");
|
||||
stopSuiteContainers.fire(new StopSuiteContainers());
|
||||
log.info("\n\n### Starting keycloak current version ###\n");
|
||||
alreadyStopped = true;
|
||||
}
|
||||
installAdapters(container);
|
||||
}
|
||||
|
||||
/*
|
||||
* non-javadoc
|
||||
*
|
||||
* check server logs whether there are no ERRORs or SEVEREs
|
||||
*/
|
||||
private void checkServerLog(String jbossHomePath) throws IOException {
|
||||
if (jbossHomePath != null && System.getProperty("check.server.log", "true").equals("true")) {
|
||||
File serverLog = new File(jbossHomePath + "/standalone/log/server.log");
|
||||
String serverLogContent = FileUtils.readFileToString(serverLog);
|
||||
|
||||
boolean containsError
|
||||
= serverLogContent.contains("ERROR")
|
||||
|| serverLogContent.contains("SEVERE")
|
||||
|| serverLogContent.contains("Exception ");
|
||||
//There is expected string "Exception" in server log: Adding provider
|
||||
//singleton org.keycloak.services.resources.ModelExceptionMapper
|
||||
|
||||
if (containsError) {
|
||||
throw new RuntimeException(serverLog.getPath() + " contains ERROR.");
|
||||
}
|
||||
log.info(serverLog.getPath() + " doesn't contain Error");
|
||||
}
|
||||
}
|
||||
|
||||
public void beforeSuite(@Observes BeforeSuite event) {
|
||||
suiteContext.set(new SuiteContext());
|
||||
}
|
||||
|
||||
public void startContainers(@Observes(precedence = -1) BeforeClass event) {
|
||||
controller = containerController.get();
|
||||
|
||||
Class testClass = event.getTestClass().getJavaClass();
|
||||
appServerQualifier = getAppServerQualifier(testClass);
|
||||
|
||||
if (!controller.isStarted(appServerQualifier)) {
|
||||
controller.start(appServerQualifier);
|
||||
}
|
||||
|
||||
initializeTestContext(testClass);
|
||||
initializeAdminClient();
|
||||
initializeOAuthClient();
|
||||
}
|
||||
|
||||
private void initializeTestContext(Class testClass) {
|
||||
String authServerContextRootStr = getAuthServerContextRootFromSystemProperty();
|
||||
String appServerContextRootStr = isRelative(testClass)
|
||||
? authServerContextRootStr
|
||||
: getAppServerContextRootFromSystemProperty();
|
||||
try {
|
||||
URL authServerContextRoot = new URL(authServerContextRootStr);
|
||||
URL appServerContextRoot = new URL(appServerContextRootStr);
|
||||
|
||||
testContext.set(new TestContext(authServerContextRoot, appServerContextRoot));
|
||||
|
||||
} catch (MalformedURLException ex) {
|
||||
throw new IllegalStateException("Malformed url.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeAdminClient() {
|
||||
adminClient.set(Keycloak.getInstance(
|
||||
getAuthServerContextRootFromSystemProperty() + "/auth",
|
||||
MASTER, ADMIN, ADMIN, Constants.ADMIN_CLI_CLIENT_ID));
|
||||
}
|
||||
|
||||
private void initializeOAuthClient() {
|
||||
oauthClient.set(new OAuthClient(getAuthServerContextRootFromSystemProperty() + "/auth"));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param testClass
|
||||
* @param annotationClass
|
||||
* @return testClass or the nearest superclass of testClass annotated with
|
||||
* annotationClass
|
||||
*/
|
||||
public static Class getNearestSuperclassWithAnnotation(Class testClass, Class annotationClass) {
|
||||
return testClass.isAnnotationPresent(annotationClass) ? testClass
|
||||
: (testClass.getSuperclass().equals(Object.class) ? null // stop recursion
|
||||
: getNearestSuperclassWithAnnotation(testClass.getSuperclass(), annotationClass)); // continue recursion
|
||||
}
|
||||
|
||||
public static String getAuthServerQualifier() {
|
||||
return System.getProperty(
|
||||
AUTH_SERVER_CONTAINER_PROPERTY,
|
||||
AUTH_SERVER_CONTAINER_DEFAULT);
|
||||
}
|
||||
|
||||
public static String getAppServerQualifier(Class testClass) {
|
||||
Class<? extends ContainersTestEnricher> annotatedClass = getNearestSuperclassWithAnnotation(testClass, AppServerContainer.class);
|
||||
|
||||
String appServerQ = (annotatedClass == null ? null
|
||||
: annotatedClass.getAnnotation(AppServerContainer.class).value());
|
||||
|
||||
return appServerQ == null || appServerQ.isEmpty()
|
||||
? getAuthServerQualifier() // app server == auth server
|
||||
: appServerQ;
|
||||
}
|
||||
|
||||
public static boolean hasAppServerContainerAnnotation(Class testClass) {
|
||||
return getNearestSuperclassWithAnnotation(testClass, AppServerContainer.class) != null;
|
||||
}
|
||||
|
||||
public static boolean isRelative(Class testClass) {
|
||||
return getAppServerQualifier(testClass).equals(getAuthServerQualifier());
|
||||
}
|
||||
|
||||
public static String getAdapterLibsLocationProperty(Class testClass) {
|
||||
Class<? extends ContainersTestEnricher> annotatedClass = getNearestSuperclassWithAnnotation(testClass, AdapterLibsLocationProperty.class);
|
||||
return (annotatedClass == null ? null
|
||||
: annotatedClass.getAnnotation(AdapterLibsLocationProperty.class).value());
|
||||
}
|
||||
|
||||
public static boolean isWildflyAppServer(Class testClass) {
|
||||
return getAppServerQualifier(testClass).contains("wildfly");
|
||||
}
|
||||
|
||||
public static boolean isTomcatAppServer(Class testClass) {
|
||||
return getAppServerQualifier(testClass).contains("tomcat");
|
||||
}
|
||||
|
||||
public static boolean isOSGiAppServer(Class testClass) {
|
||||
String q = getAppServerQualifier(testClass);
|
||||
return q.contains("karaf") || q.contains("fuse");
|
||||
}
|
||||
|
||||
public static String getAuthServerContextRootFromSystemProperty() {
|
||||
// TODO find if this can be extracted from ARQ metadata instead of System properties
|
||||
boolean sslRequired = Boolean.parseBoolean(System.getProperty("auth.server.ssl.required"));
|
||||
if (sslRequired) {
|
||||
return "https://localhost:" + Integer.parseInt(System.getProperty("auth.server.https.port", "8543"));
|
||||
}
|
||||
return "http://localhost:" + Integer.parseInt(System.getProperty("auth.server.http.port", "8180"));
|
||||
}
|
||||
|
||||
public static String getAppServerContextRootFromSystemProperty() {
|
||||
boolean sslRequired = Boolean.parseBoolean(System.getProperty("app.server.ssl.required"));
|
||||
if (sslRequired) {
|
||||
return "https://localhost:" + Integer.parseInt(System.getProperty("app.server.https.port", "8643"));
|
||||
}
|
||||
return "http://localhost:" + Integer.parseInt(System.getProperty("app.server.http.port", "8280"));
|
||||
}
|
||||
|
||||
private void installAdapters(Container container) throws InterruptedException, IOException {
|
||||
if (!alreadyInstalled && !skipInstallAdapters && isJBossBased(container)) {
|
||||
File bin = new File(jbossHomePath + "/bin");
|
||||
String command = "java -jar " + jbossHomePath + "/bin/client/jboss-cli-client.jar";
|
||||
String adapterScript = "adapter-install.cli";
|
||||
String samlAdapterScript = "adapter-install-saml.cli";
|
||||
String managementPort = container.getContainerConfiguration().getContainerProperties().get("managementPort");
|
||||
|
||||
String controllerArg = " --controller=localhost:" + managementPort;
|
||||
if (new File(bin, adapterScript).exists()) {
|
||||
log.info("Installing adapter to app server via cli script");
|
||||
execCommand(command + " --connect --file=" + adapterScript + controllerArg, bin);
|
||||
}
|
||||
if (new File(bin, samlAdapterScript).exists()) {
|
||||
log.info("Installing saml adapter to app server via cli script");
|
||||
execCommand(command + " --connect --file=" + samlAdapterScript + controllerArg, bin);
|
||||
}
|
||||
if (new File(bin, adapterScript).exists() || new File(bin, samlAdapterScript).exists()) {
|
||||
log.info("Restarting container");
|
||||
execCommand(command + " --connect --command=reload" + controllerArg, bin);
|
||||
log.info("Container restarted");
|
||||
pause(5000);
|
||||
checkServerLog(jbossHomePath);
|
||||
}
|
||||
if (container.getName().startsWith("app-server")) {
|
||||
alreadyInstalled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void execCommand(String command, File dir) throws IOException, InterruptedException {
|
||||
Process process = Runtime.getRuntime().exec(command, null, dir);
|
||||
if (process.waitFor(10, TimeUnit.SECONDS)) {
|
||||
if (process.exitValue() != 0) {
|
||||
getOutput("ERROR", process.getErrorStream());
|
||||
throw new RuntimeException("Adapter installation failed. Process exitValue: "
|
||||
+ process.exitValue());
|
||||
}
|
||||
getOutput("OUTPUT", process.getInputStream());
|
||||
log.debug("process.isAlive(): " + process.isAlive());
|
||||
} else {
|
||||
if (process.isAlive()) {
|
||||
process.destroyForcibly();
|
||||
}
|
||||
throw new RuntimeException("Timeout after 10 seconds.");
|
||||
}
|
||||
}
|
||||
|
||||
private void getOutput(String type, InputStream is) throws IOException {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("<").append(type).append(">");
|
||||
System.out.println(builder);
|
||||
builder = new StringBuilder();
|
||||
while (reader.ready()) {
|
||||
System.out.println(reader.readLine());
|
||||
}
|
||||
builder.append("</").append(type).append(">");
|
||||
System.out.println(builder);
|
||||
}
|
||||
|
||||
private boolean isJBossBased(Container container) {
|
||||
if (container == null) {
|
||||
return false;
|
||||
}
|
||||
return container.getName().matches("a.*-server-wildfly")
|
||||
|| container.getName().matches("a.*-server-eap.")
|
||||
|| container.getName().equals("app-server-as7");
|
||||
}
|
||||
}
|
|
@ -37,8 +37,12 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import static org.keycloak.testsuite.arquillian.AppServerTestEnricher.getAdapterLibsLocationProperty;
|
||||
import static org.keycloak.testsuite.arquillian.AppServerTestEnricher.hasAppServerContainerAnnotation;
|
||||
import static org.keycloak.testsuite.arquillian.AppServerTestEnricher.isRelative;
|
||||
import static org.keycloak.testsuite.arquillian.AppServerTestEnricher.isTomcatAppServer;
|
||||
|
||||
import static org.keycloak.testsuite.arquillian.ContainersTestEnricher.*;
|
||||
import static org.keycloak.testsuite.arquillian.AuthServerTestEnricher.*;
|
||||
import static org.keycloak.testsuite.util.IOUtil.*;
|
||||
|
||||
;
|
||||
|
@ -122,7 +126,7 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
|
|||
adapterConfig.setAuthServerUrl("/auth");
|
||||
// ac.setRealmKey(null); // TODO verify if realm key is required for relative scneario
|
||||
} else {
|
||||
adapterConfig.setAuthServerUrl(getAuthServerContextRootFromSystemProperty() + "/auth");
|
||||
adapterConfig.setAuthServerUrl(getAuthServerContextRoot() + "/auth");
|
||||
adapterConfig.setRealmKey(REALM_KEY);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.jboss.arquillian.container.spi.client.deployment.TargetDescription;
|
|||
import org.jboss.arquillian.container.test.impl.client.deployment.AnnotationDeploymentScenarioGenerator;
|
||||
import org.jboss.arquillian.test.spi.TestClass;
|
||||
import org.jboss.logging.Logger;
|
||||
import static org.keycloak.testsuite.arquillian.ContainersTestEnricher.*;
|
||||
import static org.keycloak.testsuite.arquillian.AppServerTestEnricher.getAppServerQualifier;
|
||||
|
||||
/**
|
||||
* Changes target container for all Arquillian deployments based on value of
|
||||
|
|
|
@ -47,7 +47,8 @@ public class KeycloakArquillianExtension implements LoadableExtension {
|
|||
builder
|
||||
.service(DeploymentScenarioGenerator.class, DeploymentTargetModifier.class)
|
||||
.service(ApplicationArchiveProcessor.class, DeploymentArchiveProcessor.class)
|
||||
.observer(ContainersTestEnricher.class);
|
||||
.observer(AuthServerTestEnricher.class)
|
||||
.observer(AppServerTestEnricher.class);
|
||||
|
||||
builder
|
||||
.service(DeployableContainer.class, CustomUndertowContainer.class);
|
||||
|
|
|
@ -14,11 +14,13 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.arquillian;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.jboss.arquillian.container.spi.Container;
|
||||
import static org.keycloak.testsuite.util.MailServerConfiguration.*;
|
||||
|
||||
/**
|
||||
|
@ -27,10 +29,18 @@ import static org.keycloak.testsuite.util.MailServerConfiguration.*;
|
|||
*/
|
||||
public final class SuiteContext {
|
||||
|
||||
private final List<Container> arquillianContainers;
|
||||
|
||||
private ContainerInfo authServerInfo;
|
||||
private final List<ContainerInfo> authServerBackendsInfo = new ArrayList<>();
|
||||
|
||||
private ContainerInfo migratedAuthServerInfo;
|
||||
|
||||
private boolean adminPasswordUpdated;
|
||||
private final Map<String, String> smtpServer = new HashMap<>();
|
||||
|
||||
public SuiteContext() {
|
||||
|
||||
public SuiteContext(List<Container> arquillianContainers) {
|
||||
this.arquillianContainers = arquillianContainers;
|
||||
this.adminPasswordUpdated = false;
|
||||
smtpServer.put("from", FROM);
|
||||
smtpServer.put("host", HOST);
|
||||
|
@ -48,4 +58,44 @@ public final class SuiteContext {
|
|||
public Map<String, String> getSmtpServer() {
|
||||
return smtpServer;
|
||||
}
|
||||
|
||||
public ContainerInfo getAuthServerInfo() {
|
||||
return authServerInfo;
|
||||
}
|
||||
|
||||
public void setAuthServerInfo(ContainerInfo authServerInfo) {
|
||||
this.authServerInfo = authServerInfo;
|
||||
}
|
||||
|
||||
public List<ContainerInfo> getAuthServerBackendsInfo() {
|
||||
return authServerBackendsInfo;
|
||||
}
|
||||
|
||||
public ContainerInfo getMigratedAuthServerInfo() {
|
||||
return migratedAuthServerInfo;
|
||||
}
|
||||
|
||||
public void setMigratedAuthServerInfo(ContainerInfo migratedAuthServerInfo) {
|
||||
this.migratedAuthServerInfo = migratedAuthServerInfo;
|
||||
}
|
||||
|
||||
public boolean isAuthServerCluster() {
|
||||
return !authServerBackendsInfo.isEmpty();
|
||||
}
|
||||
|
||||
public boolean isAuthServerMigrationEnabled() {
|
||||
return migratedAuthServerInfo != null;
|
||||
}
|
||||
|
||||
public List<Container> getArquillianContainers() {
|
||||
return arquillianContainers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SUITE CONTEXT:\n"
|
||||
+ "Auth server: " + authServerInfo.getQualifier() + "\n"
|
||||
+(isAuthServerCluster() ? "Auth server cluster: " + getAuthServerBackendsInfo().size() + " nodes+\n" : "");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.arquillian;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -25,29 +25,21 @@ import java.net.URL;
|
|||
*/
|
||||
public final class TestContext {
|
||||
|
||||
private URL authServerContextRoot;
|
||||
private URL appServerContextRoot;
|
||||
private final SuiteContext suiteContext;
|
||||
|
||||
private final Class testClass;
|
||||
|
||||
private ContainerInfo appServerInfo;
|
||||
private final List<ContainerInfo> appServerBackendsInfo = new ArrayList<>();
|
||||
|
||||
private boolean adminLoggedIn;
|
||||
|
||||
public TestContext() {
|
||||
public TestContext(SuiteContext suiteContext, Class testClass) {
|
||||
this.suiteContext = suiteContext;
|
||||
this.testClass = testClass;
|
||||
this.adminLoggedIn = false;
|
||||
}
|
||||
|
||||
public TestContext(URL authServerContextRoot, URL appServerContextRoot) {
|
||||
this();
|
||||
this.authServerContextRoot = authServerContextRoot;
|
||||
this.appServerContextRoot = appServerContextRoot;
|
||||
}
|
||||
|
||||
public URL getAuthServerContextRoot() {
|
||||
return authServerContextRoot;
|
||||
}
|
||||
|
||||
public URL getAppServerContextRoot() {
|
||||
return appServerContextRoot;
|
||||
}
|
||||
|
||||
public boolean isAdminLoggedIn() {
|
||||
return adminLoggedIn;
|
||||
}
|
||||
|
@ -56,12 +48,44 @@ public final class TestContext {
|
|||
this.adminLoggedIn = adminLoggedIn;
|
||||
}
|
||||
|
||||
public void setAuthServerContextRoot(URL authServerContextRoot) {
|
||||
this.authServerContextRoot = authServerContextRoot;
|
||||
public ContainerInfo getAppServerInfo() {
|
||||
return appServerInfo;
|
||||
}
|
||||
|
||||
public void setAppServerContextRoot(URL appServerContextRoot) {
|
||||
this.appServerContextRoot = appServerContextRoot;
|
||||
public void setAppServerInfo(ContainerInfo appServerInfo) {
|
||||
this.appServerInfo = appServerInfo;
|
||||
}
|
||||
|
||||
public List<ContainerInfo> getAppServerBackendsInfo() {
|
||||
return appServerBackendsInfo;
|
||||
}
|
||||
|
||||
public Class getTestClass() {
|
||||
return testClass;
|
||||
}
|
||||
|
||||
public boolean isAdapterTest() {
|
||||
return appServerInfo != null;
|
||||
}
|
||||
|
||||
public boolean isRelativeAdapterTest() {
|
||||
return isAdapterTest()
|
||||
&& appServerInfo.getQualifier().equals(
|
||||
suiteContext.getAuthServerInfo().getQualifier()); // app server == auth server
|
||||
}
|
||||
|
||||
public boolean isClusteredAdapterTest() {
|
||||
return isAdapterTest() && !appServerBackendsInfo.isEmpty();
|
||||
}
|
||||
|
||||
public SuiteContext getSuiteContext() {
|
||||
return suiteContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TEST CONTEXT: " + getTestClass().getCanonicalName() + "\n"
|
||||
+ (isAdapterTest() ? "App server container: " + getAppServerInfo() + "\n" : "");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import java.net.MalformedURLException;
|
|||
import java.net.URL;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.keycloak.testsuite.arquillian.SuiteContext;
|
||||
|
||||
public class URLProvider extends URLResourceProvider {
|
||||
|
||||
|
@ -43,6 +44,8 @@ public class URLProvider extends URLResourceProvider {
|
|||
|
||||
private final boolean appServerSslRequired = Boolean.parseBoolean(System.getProperty("app.server.ssl.required"));
|
||||
|
||||
@Inject
|
||||
Instance<SuiteContext> suiteContext;
|
||||
@Inject
|
||||
Instance<TestContext> testContext;
|
||||
|
||||
|
@ -97,10 +100,10 @@ public class URLProvider extends URLResourceProvider {
|
|||
// inject context roots if annotation present
|
||||
for (Annotation a : qualifiers) {
|
||||
if (AuthServerContext.class.isAssignableFrom(a.annotationType())) {
|
||||
return testContext.get().getAuthServerContextRoot();
|
||||
return suiteContext.get().getAuthServerInfo().getContextRoot();
|
||||
}
|
||||
if (AppServerContext.class.isAssignableFrom(a.annotationType())) {
|
||||
return testContext.get().getAppServerContextRoot();
|
||||
return testContext.get().getAppServerInfo().getContextRoot();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,11 +41,11 @@ public class AuthServer extends AuthServerContextRoot {
|
|||
return uri.getScheme() + "://" + uri.getAuthority() + "/auth";
|
||||
}
|
||||
|
||||
@ArquillianResource
|
||||
protected Keycloak keycloak;
|
||||
|
||||
public Keycloak keycloak() {
|
||||
return keycloak;
|
||||
}
|
||||
// @ArquillianResource
|
||||
// protected Keycloak keycloak;
|
||||
//
|
||||
// public Keycloak keycloak() {
|
||||
// return keycloak;
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -101,9 +101,9 @@ public class AccountManagement extends AuthRealm {
|
|||
save.click();
|
||||
}
|
||||
|
||||
public RealmResource realmResource() {
|
||||
return keycloak().realm(getAuthRealm());
|
||||
}
|
||||
// public RealmResource realmResource() {
|
||||
// return keycloak().realm(getAuthRealm());
|
||||
// }
|
||||
|
||||
public void waitForAccountLinkPresent() {
|
||||
waitUntilElement(accountLink, "account link should be present").is().present();
|
||||
|
|
|
@ -59,9 +59,9 @@ public class AdminConsoleRealm extends AdminConsoleRealmsRoot {
|
|||
return configureMenu;
|
||||
}
|
||||
|
||||
public RealmResource realmResource() {
|
||||
return realmsResource().realm(getConsoleRealm());
|
||||
}
|
||||
// public RealmResource realmResource() {
|
||||
// return realmsResource().realm(getConsoleRealm());
|
||||
// }
|
||||
|
||||
public class ConfigureMenu {
|
||||
|
||||
|
|
|
@ -59,8 +59,8 @@ public class AdminConsoleRealmsRoot extends AdminConsole {
|
|||
@FindBy(css = "realm-selector")
|
||||
protected RealmSelector realmSelector;
|
||||
|
||||
public RealmsResource realmsResource() {
|
||||
return keycloak.realms();
|
||||
}
|
||||
// public RealmsResource realmsResource() {
|
||||
// return keycloak.realms();
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.util;
|
||||
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
|
@ -33,6 +32,8 @@ import javax.xml.transform.TransformerFactory;
|
|||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -40,6 +41,8 @@ import java.io.*;
|
|||
*/
|
||||
public class IOUtil {
|
||||
|
||||
private static final Logger log = Logger.getLogger(IOUtil.class);
|
||||
|
||||
public static <T> T loadJson(InputStream is, Class<T> type) {
|
||||
try {
|
||||
return JsonSerialization.readValue(is, type);
|
||||
|
@ -71,7 +74,7 @@ public class IOUtil {
|
|||
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
|
||||
return dBuilder.parse(is);
|
||||
} catch (ParserConfigurationException|SAXException|IOException e) {
|
||||
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
@ -99,4 +102,36 @@ public class IOUtil {
|
|||
}
|
||||
node.setTextContent(node.getTextContent().replace(regex, replacement));
|
||||
}
|
||||
|
||||
public static void execCommand(String command, File dir) throws IOException, InterruptedException {
|
||||
Process process = Runtime.getRuntime().exec(command, null, dir);
|
||||
if (process.waitFor(10, TimeUnit.SECONDS)) {
|
||||
if (process.exitValue() != 0) {
|
||||
getOutput("ERROR", process.getErrorStream());
|
||||
throw new RuntimeException("Adapter installation failed. Process exitValue: "
|
||||
+ process.exitValue());
|
||||
}
|
||||
getOutput("OUTPUT", process.getInputStream());
|
||||
log.debug("process.isAlive(): " + process.isAlive());
|
||||
} else {
|
||||
if (process.isAlive()) {
|
||||
process.destroyForcibly();
|
||||
}
|
||||
throw new RuntimeException("Timeout after 10 seconds.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void getOutput(String type, InputStream is) throws IOException {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("<").append(type).append(">");
|
||||
System.out.println(builder);
|
||||
builder = new StringBuilder();
|
||||
while (reader.ready()) {
|
||||
System.out.println(reader.readLine());
|
||||
}
|
||||
builder.append("</").append(type).append(">");
|
||||
System.out.println(builder);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package org.keycloak.testsuite.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author vramik
|
||||
* @author tkyjovsk
|
||||
*/
|
||||
public class LogChecker {
|
||||
|
||||
private static final Logger log = Logger.getLogger(LogChecker.class);
|
||||
|
||||
public static void checkServerLog(File logFile) throws IOException {
|
||||
log.info(String.format("Checking server log: '%s'", logFile.getAbsolutePath()));
|
||||
String logContent = FileUtils.readFileToString(logFile);
|
||||
|
||||
boolean containsError
|
||||
= logContent.contains("ERROR")
|
||||
|| logContent.contains("SEVERE")
|
||||
|| logContent.contains("Exception ");
|
||||
|
||||
//There is expected string "Exception" in server log: Adding provider
|
||||
//singleton org.keycloak.services.resources.ModelExceptionMapper
|
||||
if (containsError) {
|
||||
throw new RuntimeException(String.format("Server log file contains ERROR: '%s'", logFile.getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkJBossServerLog(String jbossHome) throws IOException {
|
||||
checkServerLog(new File(jbossHome + "/standalone/log/server.log"));
|
||||
}
|
||||
|
||||
}
|
|
@ -14,7 +14,6 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite;
|
||||
|
||||
import org.keycloak.testsuite.arquillian.TestContext;
|
||||
|
@ -33,9 +32,12 @@ import org.junit.Before;
|
|||
import org.junit.runner.RunWith;
|
||||
import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.admin.client.resource.RealmsResource;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import static org.keycloak.testsuite.admin.Users.setPasswordFor;
|
||||
import org.keycloak.testsuite.arquillian.AuthServerTestEnricher;
|
||||
import org.keycloak.testsuite.arquillian.SuiteContext;
|
||||
import org.keycloak.testsuite.auth.page.WelcomePage;
|
||||
import org.keycloak.testsuite.util.OAuthClient;
|
||||
|
@ -66,11 +68,9 @@ public abstract class AbstractKeycloakTest {
|
|||
|
||||
@ArquillianResource
|
||||
protected TestContext testContext;
|
||||
|
||||
@ArquillianResource
|
||||
|
||||
protected Keycloak adminClient;
|
||||
|
||||
@ArquillianResource
|
||||
protected OAuthClient oauthClient;
|
||||
|
||||
protected List<RealmRepresentation> testRealmReps;
|
||||
|
@ -100,6 +100,11 @@ public abstract class AbstractKeycloakTest {
|
|||
|
||||
@Before
|
||||
public void beforeAbstractKeycloakTest() {
|
||||
adminClient = Keycloak.getInstance(AuthServerTestEnricher.getAuthServerContextRoot() + "/auth",
|
||||
MASTER, ADMIN, ADMIN, Constants.ADMIN_CLI_CLIENT_ID);
|
||||
oauthClient = new OAuthClient(AuthServerTestEnricher.getAuthServerContextRoot() + "/auth");
|
||||
|
||||
|
||||
adminUser = createAdminUserRepresentation();
|
||||
|
||||
setDefaultPageUriParameters();
|
||||
|
@ -195,5 +200,9 @@ public abstract class AbstractKeycloakTest {
|
|||
public void removeRealm(RealmRepresentation realm) {
|
||||
adminClient.realms().realm(realm.getRealm()).remove();
|
||||
}
|
||||
|
||||
public RealmsResource realmsResouce() {
|
||||
return adminClient.realms();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package org.keycloak.testsuite;
|
||||
|
||||
import java.util.List;
|
||||
import org.jboss.arquillian.container.test.api.ContainerController;
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.arquillian.AuthServerTestEnricher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tkyjovsk
|
||||
*/
|
||||
public class ContainersTest extends AbstractKeycloakTest {
|
||||
|
||||
@ArquillianResource
|
||||
ContainerController controller;
|
||||
|
||||
@Override
|
||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAuthServer() {
|
||||
|
||||
log.info("AUTH SERVER should be started.");
|
||||
assertTrue(controller.isStarted(AuthServerTestEnricher.getAuthServerQualifier()));
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -25,7 +25,7 @@ import org.keycloak.representations.idm.ClientRepresentation;
|
|||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.AbstractAuthTest;
|
||||
import org.keycloak.testsuite.adapter.page.AppServerContextRoot;
|
||||
import org.keycloak.testsuite.arquillian.ContainersTestEnricher;
|
||||
import org.keycloak.testsuite.arquillian.AuthServerTestEnricher;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -78,7 +78,7 @@ public abstract class AbstractAdapterTest extends AbstractAuthTest {
|
|||
public abstract void addAdapterTestRealms(List<RealmRepresentation> testRealms);
|
||||
|
||||
public boolean isRelative() {
|
||||
return ContainersTestEnricher.isRelative(this.getClass());
|
||||
return testContext.isRelativeAdapterTest();
|
||||
}
|
||||
|
||||
protected void modifyClientRedirectUris(RealmRepresentation realm, String regex, String replacement) {
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.client;
|
||||
|
||||
import org.junit.After;
|
||||
|
@ -46,7 +45,7 @@ public abstract class AbstractClientRegistrationTest extends AbstractKeycloakTes
|
|||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
reg = ClientRegistration.create().url(testContext.getAuthServerContextRoot() + "/auth", "test").build();
|
||||
reg = ClientRegistration.create().url(suiteContext.getAuthServerInfo().getContextRoot() + "/auth", "test").build();
|
||||
}
|
||||
|
||||
@After
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.client;
|
||||
|
||||
import org.junit.Before;
|
||||
|
@ -87,7 +86,7 @@ public class AdapterInstallationConfigTest extends AbstractClientRegistrationTes
|
|||
AdapterConfig config = reg.getAdapterConfig(client.getClientId());
|
||||
assertNotNull(config);
|
||||
|
||||
assertEquals(testContext.getAuthServerContextRoot() + "/auth", config.getAuthServerUrl());
|
||||
assertEquals(suiteContext.getAuthServerInfo().getContextRoot() + "/auth", config.getAuthServerUrl());
|
||||
assertEquals("test", config.getRealm());
|
||||
|
||||
assertEquals(1, config.getCredentials().size());
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
<!--
|
||||
~ Copyright 2016 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.
|
||||
-->
|
||||
~ Copyright 2016 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.
|
||||
-->
|
||||
|
||||
<arquillian xmlns="http://jboss.org/schema/arquillian"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
|
@ -44,80 +44,6 @@
|
|||
<property name="deploymentExportPath">target/deployments</property>
|
||||
</engine>
|
||||
|
||||
<!-- PREVIOUS VERSIONS KEYCLOAK FOR MIGRATION TESTS -->
|
||||
<!-- IT HAS TO BE LISTED ABOWE KEYCLOAK AUTH SERVERS -->
|
||||
|
||||
<container qualifier="keycloak-1.6.1.Final" mode="suite" >
|
||||
<configuration>
|
||||
<property name="enabled">${migration.kc16}</property>
|
||||
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
|
||||
<property name="jbossHome">${keycloak.migration.home}</property>
|
||||
<property name="javaVmArguments">
|
||||
-Dkeycloak.migration.action=import
|
||||
-Dkeycloak.migration.provider=singleFile
|
||||
-Dkeycloak.migration.file=${keycloak.migration.file}
|
||||
-Dkeycloak.migration.strategy=OVERWRITE_EXISTING
|
||||
-Dkeycloak.migration.realmName=Migration
|
||||
-Djboss.socket.binding.port-offset=${auth.server.port.offset}
|
||||
-Xms64m -Xmx512m -XX:MaxPermSize=256m
|
||||
</property>
|
||||
<property name="managementPort">${auth.server.management.port}</property>
|
||||
<property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
|
||||
</configuration>
|
||||
</container>
|
||||
|
||||
<container qualifier="keycloak-1.5.1.Final" mode="suite" >
|
||||
<configuration>
|
||||
<property name="enabled">${migration.kc15}</property>
|
||||
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
|
||||
<property name="jbossHome">${keycloak.migration.home}</property>
|
||||
<property name="javaVmArguments">
|
||||
-Dkeycloak.migration.action=import
|
||||
-Dkeycloak.migration.provider=singleFile
|
||||
-Dkeycloak.migration.file=${keycloak.migration.file}
|
||||
-Dkeycloak.migration.strategy=OVERWRITE_EXISTING
|
||||
-Dkeycloak.migration.realmName=Migration
|
||||
-Djboss.socket.binding.port-offset=${auth.server.port.offset}
|
||||
-Xms64m -Xmx512m -XX:MaxPermSize=256m
|
||||
</property>
|
||||
<property name="managementPort">${auth.server.management.port}</property>
|
||||
<property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
|
||||
</configuration>
|
||||
</container>
|
||||
|
||||
<container qualifier="keycloak-1.4.0.Final" mode="suite" >
|
||||
<configuration>
|
||||
<property name="enabled">${migration.kc14}</property>
|
||||
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
|
||||
<property name="jbossHome">${keycloak.migration.home}</property>
|
||||
<property name="javaVmArguments">-Djboss.socket.binding.port-offset=${auth.server.port.offset} -Xms64m -Xmx512m -XX:MaxPermSize=256m</property>
|
||||
<property name="managementPort">${auth.server.management.port}</property>
|
||||
<property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
|
||||
</configuration>
|
||||
</container>
|
||||
|
||||
<container qualifier="keycloak-1.3.1.Final" mode="suite" >
|
||||
<configuration>
|
||||
<property name="enabled">${migration.kc13}</property>
|
||||
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
|
||||
<property name="jbossHome">${keycloak.migration.home}</property>
|
||||
<property name="javaVmArguments">-Djboss.socket.binding.port-offset=${auth.server.port.offset} -Xms64m -Xmx512m -XX:MaxPermSize=256m</property>
|
||||
<property name="managementPort">${auth.server.management.port}</property>
|
||||
<property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
|
||||
</configuration>
|
||||
</container>
|
||||
|
||||
<container qualifier="keycloak-1.2.0.Final" mode="suite" >
|
||||
<configuration>
|
||||
<property name="enabled">${migration.kc12}</property>
|
||||
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
|
||||
<property name="jbossHome">${keycloak.migration.home}</property>
|
||||
<property name="javaVmArguments">-Djboss.socket.binding.port-offset=${auth.server.port.offset} -Xms64m -Xmx512m -XX:MaxPermSize=256m</property>
|
||||
<property name="managementPort">${auth.server.management.port}</property>
|
||||
<property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
|
||||
</configuration>
|
||||
</container>
|
||||
|
||||
<!-- KEYCLOAK AUTH SERVERS -->
|
||||
|
||||
<container qualifier="auth-server-undertow" mode="suite" >
|
||||
|
@ -140,6 +66,37 @@
|
|||
</configuration>
|
||||
</container>
|
||||
|
||||
<group qualifier="auth-server-wildfly-cluster">
|
||||
<container qualifier="auth-server-wildfly-balancer" mode="suite" >
|
||||
<configuration>
|
||||
<property name="enabled">${auth.server.wildfly.cluster}</property>
|
||||
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
|
||||
<property name="jbossHome">${wildfly.home}</property>
|
||||
<property name="javaVmArguments">
|
||||
-Djboss.socket.binding.port-offset=${auth.server.port.offset}
|
||||
-Xms64m -Xmx512m -XX:MaxPermSize=256m
|
||||
${adapter.test.props}
|
||||
</property>
|
||||
<property name="managementPort">${auth.server.management.port}</property>
|
||||
<property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
|
||||
</configuration>
|
||||
</container>
|
||||
<container qualifier="auth-server-wildfly-backend1" mode="manual" >
|
||||
<configuration>
|
||||
<property name="enabled">${auth.server.wildfly.cluster}</property>
|
||||
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
|
||||
<property name="jbossHome">${keycloak.backend1.home}</property>
|
||||
<property name="javaVmArguments">
|
||||
-Djboss.socket.binding.port-offset=${auth.server.backend1.port.offset}
|
||||
-Xms64m -Xmx512m -XX:MaxPermSize=256m
|
||||
${adapter.test.props}
|
||||
</property>
|
||||
<property name="managementPort">${auth.server.backend1.management.port}</property>
|
||||
<property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
|
||||
</configuration>
|
||||
</container>
|
||||
</group>
|
||||
|
||||
<container qualifier="auth-server-eap7" mode="suite" >
|
||||
<configuration>
|
||||
<property name="enabled">${auth.server.eap7}</property>
|
||||
|
@ -150,5 +107,79 @@
|
|||
<property name="managementPort">${auth.server.management.port}</property>
|
||||
</configuration>
|
||||
</container>
|
||||
|
||||
<!-- PREVIOUS VERSIONS OF KEYCLOAK FOR MIGRATION TESTS -->
|
||||
|
||||
<container qualifier="migrated-auth-server-wildfly_kc16" mode="manual" >
|
||||
<configuration>
|
||||
<property name="enabled">${migration.kc16}</property>
|
||||
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
|
||||
<property name="jbossHome">${keycloak.migration.home}</property>
|
||||
<property name="javaVmArguments">
|
||||
-Dkeycloak.migration.action=import
|
||||
-Dkeycloak.migration.provider=singleFile
|
||||
-Dkeycloak.migration.file=${keycloak.migration.file}
|
||||
-Dkeycloak.migration.strategy=OVERWRITE_EXISTING
|
||||
-Dkeycloak.migration.realmName=Migration
|
||||
-Djboss.socket.binding.port-offset=${auth.server.port.offset}
|
||||
-Xms64m -Xmx512m -XX:MaxPermSize=256m
|
||||
</property>
|
||||
<property name="managementPort">${auth.server.management.port}</property>
|
||||
<property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
|
||||
</configuration>
|
||||
</container>
|
||||
|
||||
<container qualifier="migrated-auth-server-wildfly_kc15" mode="manual" >
|
||||
<configuration>
|
||||
<property name="enabled">${migration.kc15}</property>
|
||||
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
|
||||
<property name="jbossHome">${keycloak.migration.home}</property>
|
||||
<property name="javaVmArguments">
|
||||
-Dkeycloak.migration.action=import
|
||||
-Dkeycloak.migration.provider=singleFile
|
||||
-Dkeycloak.migration.file=${keycloak.migration.file}
|
||||
-Dkeycloak.migration.strategy=OVERWRITE_EXISTING
|
||||
-Dkeycloak.migration.realmName=Migration
|
||||
-Djboss.socket.binding.port-offset=${auth.server.port.offset}
|
||||
-Xms64m -Xmx512m -XX:MaxPermSize=256m
|
||||
</property>
|
||||
<property name="managementPort">${auth.server.management.port}</property>
|
||||
<property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
|
||||
</configuration>
|
||||
</container>
|
||||
|
||||
<container qualifier="migrated-auth-server-wildfly_kc14" mode="manual" >
|
||||
<configuration>
|
||||
<property name="enabled">${migration.kc14}</property>
|
||||
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
|
||||
<property name="jbossHome">${keycloak.migration.home}</property>
|
||||
<property name="javaVmArguments">-Djboss.socket.binding.port-offset=${auth.server.port.offset} -Xms64m -Xmx512m -XX:MaxPermSize=256m</property>
|
||||
<property name="managementPort">${auth.server.management.port}</property>
|
||||
<property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
|
||||
</configuration>
|
||||
</container>
|
||||
|
||||
<container qualifier="migrated-auth-server-wildfly_kc13" mode="manual" >
|
||||
<configuration>
|
||||
<property name="enabled">${migration.kc13}</property>
|
||||
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
|
||||
<property name="jbossHome">${keycloak.migration.home}</property>
|
||||
<property name="javaVmArguments">-Djboss.socket.binding.port-offset=${auth.server.port.offset} -Xms64m -Xmx512m -XX:MaxPermSize=256m</property>
|
||||
<property name="managementPort">${auth.server.management.port}</property>
|
||||
<property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
|
||||
</configuration>
|
||||
</container>
|
||||
|
||||
<container qualifier="migrated-auth-server-wildfly_kc12" mode="manual" >
|
||||
<configuration>
|
||||
<property name="enabled">${migration.kc12}</property>
|
||||
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
|
||||
<property name="jbossHome">${keycloak.migration.home}</property>
|
||||
<property name="javaVmArguments">-Djboss.socket.binding.port-offset=${auth.server.port.offset} -Xms64m -Xmx512m -XX:MaxPermSize=256m</property>
|
||||
<property name="managementPort">${auth.server.management.port}</property>
|
||||
<property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
|
||||
</configuration>
|
||||
</container>
|
||||
|
||||
|
||||
</arquillian>
|
||||
|
|
|
@ -108,8 +108,6 @@ public class Client extends Clients {
|
|||
|
||||
}
|
||||
|
||||
public ClientResource clientResource() {
|
||||
return clientsResource().get(getId());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -126,8 +126,4 @@ public class Clients extends AdminConsoleRealm {
|
|||
}
|
||||
}
|
||||
|
||||
public ClientsResource clientsResource() {
|
||||
return realmResource().clients();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,9 +22,5 @@ public class ClientRoles extends Client {
|
|||
public RolesTable roles() {
|
||||
return table;
|
||||
}
|
||||
|
||||
public RolesResource rolesResource() {
|
||||
return clientResource().roles();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -92,8 +92,4 @@ public class IdentityProviderSettings extends AdminConsoleRealm {
|
|||
return rows;
|
||||
}
|
||||
|
||||
public IdentityProvidersResource identityProviders() {
|
||||
return realmResource().identityProviders();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,8 +35,4 @@ public class Roles extends AdminConsoleRealm {
|
|||
|
||||
}
|
||||
|
||||
public RolesResource rolesResource() {
|
||||
return realmResource().roles();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.keycloak.testsuite.console.page.users;
|
||||
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.testsuite.console.page.fragment.Breadcrumb;
|
||||
import static org.keycloak.testsuite.console.page.fragment.Breadcrumb.BREADCRUMB_XPATH;
|
||||
import org.openqa.selenium.WebElement;
|
||||
|
@ -76,8 +75,4 @@ public class User extends Users {
|
|||
|
||||
}
|
||||
|
||||
public UserResource userResource() {
|
||||
return usersResource().get(getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,9 +20,5 @@ public class UserRoleMappings extends User {
|
|||
public UserRoleMappingsForm form() {
|
||||
return form;
|
||||
}
|
||||
|
||||
public RoleMappingResource roleMappingResource() {
|
||||
return userResource().roles();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import org.openqa.selenium.support.FindBy;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.keycloak.admin.client.resource.UsersResource;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
|
||||
import org.keycloak.testsuite.console.page.AdminConsoleRealm;
|
||||
|
@ -135,8 +134,4 @@ public class Users extends AdminConsoleRealm {
|
|||
|
||||
}
|
||||
|
||||
public UsersResource usersResource() {
|
||||
return realmResource().users();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
*/
|
||||
package org.keycloak.testsuite.console;
|
||||
|
||||
import org.jboss.arquillian.graphene.findby.FindByJQuery;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Before;
|
||||
|
|
|
@ -8,6 +8,8 @@ import java.util.Map;
|
|||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.junit.Before;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.admin.client.resource.ClientsResource;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||
import static org.keycloak.testsuite.auth.page.login.OIDCLogin.OIDC;
|
||||
|
@ -50,7 +52,7 @@ public abstract class AbstractClientTest extends AbstractConsoleTest {
|
|||
|
||||
public final String TEST_CLIENT_ID = "test-client";
|
||||
public final String TEST_REDIRECT_URIS = "http://example.test/app/*";
|
||||
|
||||
|
||||
@Page
|
||||
protected Clients clientsPage;
|
||||
@Page
|
||||
|
@ -87,12 +89,12 @@ public abstract class AbstractClientTest extends AbstractConsoleTest {
|
|||
client.setConsentRequired(false);
|
||||
return client;
|
||||
}
|
||||
|
||||
|
||||
public static ClientRepresentation createOidcClientRep(OidcAccessType accessType, String clientId, String... redirectUris) {
|
||||
ClientRepresentation client = createClientRep(clientId);
|
||||
|
||||
|
||||
client.setProtocol(OIDC);
|
||||
|
||||
|
||||
switch (accessType) {
|
||||
case BEARER_ONLY:
|
||||
client.setBearerOnly(true);
|
||||
|
@ -116,24 +118,24 @@ public abstract class AbstractClientTest extends AbstractConsoleTest {
|
|||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
|
||||
public static ClientRepresentation createSamlClientRep(String clinetId) {
|
||||
ClientRepresentation client = createClientRep(clinetId);
|
||||
|
||||
|
||||
client.setProtocol(SAML);
|
||||
|
||||
|
||||
client.setFrontchannelLogout(true);
|
||||
client.setAttributes(getSAMLAttributes());
|
||||
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
|
||||
private static void setRedirectUris(ClientRepresentation client, String... redirectUris) {
|
||||
List<String> redirectUrisList = new ArrayList<>();
|
||||
redirectUrisList.addAll(Arrays.asList(redirectUris));
|
||||
client.setRedirectUris(redirectUrisList);
|
||||
}
|
||||
|
||||
|
||||
protected static void setExpectedWebOrigins(ClientRepresentation client) {
|
||||
List<String> webOrigins = new ArrayList<>();
|
||||
for (String redirectUri : client.getRedirectUris()) {
|
||||
|
@ -143,7 +145,7 @@ public abstract class AbstractClientTest extends AbstractConsoleTest {
|
|||
}
|
||||
client.setWebOrigins(webOrigins);
|
||||
}
|
||||
|
||||
|
||||
public ClientRepresentation findClientByClientId(String clientId) {
|
||||
ClientRepresentation found = null;
|
||||
for (ClientRepresentation clientRepresentation : testRealmResource().clients().findAll()) {
|
||||
|
@ -154,7 +156,7 @@ public abstract class AbstractClientTest extends AbstractConsoleTest {
|
|||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
public void assertClientSettingsEqual(ClientRepresentation c1, ClientRepresentation c2) {
|
||||
assertEqualsStringAttributes(c1.getClientId(), c2.getClientId());
|
||||
assertEqualsStringAttributes(c1.getName(), c2.getName());
|
||||
|
@ -174,38 +176,37 @@ public abstract class AbstractClientTest extends AbstractConsoleTest {
|
|||
}
|
||||
assertEqualsBooleanAttributes(c1.isSurrogateAuthRequired(), c2.isSurrogateAuthRequired());
|
||||
assertEqualsBooleanAttributes(c1.isServiceAccountsEnabled(), c2.isServiceAccountsEnabled());
|
||||
}
|
||||
else if (c1.getProtocol().equals(SAML)) {
|
||||
} else if (c1.getProtocol().equals(SAML)) {
|
||||
assertEqualsBooleanAttributes(c1.isFrontchannelLogout(), c2.isFrontchannelLogout());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void assertClientSamlAttributes(Map<String, String> expected, Map<String, String> actual) {
|
||||
for (String key : expected.keySet()) {
|
||||
assertEquals("Expected attribute " + key, expected.get(key), actual.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected static Map<String, String> getSAMLAttributes() {
|
||||
Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put(SAML_ASSERTION_SIGNATURE, "true");
|
||||
attributes.put(SAML_AUTHNSTATEMENT, "false");
|
||||
attributes.put(SAML_CLIENT_SIGNATURE, "true");
|
||||
attributes.put(SAML_ENCRYPT, "true");
|
||||
attributes.put(SAML_FORCE_POST_BINDING, "true");
|
||||
attributes.put(SAML_MULTIVALUED_ROLES, "false");
|
||||
attributes.put(SAML_SERVER_SIGNATURE, "true");
|
||||
attributes.put(SAML_SIGNATURE_ALGORITHM, "RSA_SHA512");
|
||||
attributes.put(SAML_ASSERTION_CONSUMER_URL_POST, "http://example0.test");
|
||||
attributes.put(SAML_ASSERTION_CONSUMER_URL_REDIRECT, "http://example1.test");
|
||||
attributes.put(SAML_FORCE_NAME_ID_FORMAT, "true");
|
||||
attributes.put(SAML_NAME_ID_FORMAT, "email");
|
||||
attributes.put(SAML_SIGNATURE_CANONICALIZATION_METHOD, "http://www.w3.org/2001/10/xml-exc-c14n#WithComments");
|
||||
attributes.put(SAML_SINGLE_LOGOUT_SERVICE_URL_POST, "http://example2.test");
|
||||
attributes.put(SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT, "http://example3.test");
|
||||
attributes.put(SAML_CLIENT_SIGNATURE, "true");
|
||||
attributes.put(SAML_ENCRYPT, "true");
|
||||
attributes.put(SAML_FORCE_POST_BINDING, "true");
|
||||
attributes.put(SAML_MULTIVALUED_ROLES, "false");
|
||||
attributes.put(SAML_SERVER_SIGNATURE, "true");
|
||||
attributes.put(SAML_SIGNATURE_ALGORITHM, "RSA_SHA512");
|
||||
attributes.put(SAML_ASSERTION_CONSUMER_URL_POST, "http://example0.test");
|
||||
attributes.put(SAML_ASSERTION_CONSUMER_URL_REDIRECT, "http://example1.test");
|
||||
attributes.put(SAML_FORCE_NAME_ID_FORMAT, "true");
|
||||
attributes.put(SAML_NAME_ID_FORMAT, "email");
|
||||
attributes.put(SAML_SIGNATURE_CANONICALIZATION_METHOD, "http://www.w3.org/2001/10/xml-exc-c14n#WithComments");
|
||||
attributes.put(SAML_SINGLE_LOGOUT_SERVICE_URL_POST, "http://example2.test");
|
||||
attributes.put(SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT, "http://example3.test");
|
||||
return attributes;
|
||||
}
|
||||
|
||||
|
||||
public ProtocolMapperRepresentation findClientMapperByName(String clientId, String mapperName) {
|
||||
ProtocolMapperRepresentation found = null;
|
||||
for (ProtocolMapperRepresentation mapper : testRealmResource().clients().get(clientId).getProtocolMappers().getMappers()) {
|
||||
|
@ -215,4 +216,13 @@ public abstract class AbstractClientTest extends AbstractConsoleTest {
|
|||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
public ClientsResource clientsResource() {
|
||||
return testRealmResource().clients();
|
||||
}
|
||||
|
||||
public ClientResource clientResource(String id) {
|
||||
return clientsResource().get(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -153,11 +153,11 @@ public class ClientSettingsTest extends AbstractClientTest {
|
|||
c.setPublicClient(true);
|
||||
c.setBearerOnly(true);
|
||||
|
||||
Response r = clientsPage.clientsResource().create(c);
|
||||
Response r = clientsResource().create(c);
|
||||
r.close();
|
||||
clientSettingsPage.setId(getCreatedId(r));
|
||||
|
||||
c = clientSettingsPage.clientResource().toRepresentation();
|
||||
c = clientResource(clientSettingsPage.getId()).toRepresentation();
|
||||
assertTrue(c.isBearerOnly());
|
||||
assertTrue(c.isPublicClient());
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import javax.ws.rs.core.Response;
|
|||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.keycloak.admin.client.resource.ClientsResource;
|
||||
import static org.keycloak.testsuite.console.page.clients.CreateClientForm.OidcAccessType.CONFIDENTIAL;
|
||||
|
||||
|
||||
|
@ -50,12 +51,12 @@ public class AdminEventsTest extends AbstractConsoleTest {
|
|||
@Test
|
||||
public void clientsAdminEventsTest() {
|
||||
newClient = AbstractClientTest.createOidcClientRep(CONFIDENTIAL, "test_client", "http://example.test/test_client/*");
|
||||
Response response = clientsPage.clientsResource().create(newClient);
|
||||
Response response = clientsResource().create(newClient);
|
||||
String id = ApiUtil.getCreatedId(response);
|
||||
response.close();
|
||||
newClient.setClientId("test_client2");
|
||||
clientsPage.clientsResource().get(id).update(newClient);
|
||||
clientsPage.clientsResource().get(id).remove();
|
||||
clientsResource().get(id).update(newClient);
|
||||
clientsResource().get(id).remove();
|
||||
|
||||
adminEventsPage.navigateTo();
|
||||
adminEventsPage.table().filter();
|
||||
|
@ -85,4 +86,8 @@ public class AdminEventsTest extends AbstractConsoleTest {
|
|||
resultList.get(0).findElement(By.xpath("//td[text()='DELETE']"));
|
||||
resultList.get(0).findElement(By.xpath("//td[text()='clients/" + id + "']"));
|
||||
}
|
||||
|
||||
public ClientsResource clientsResource() {
|
||||
return testRealmResource().clients();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.keycloak.testsuite.console.roles;
|
|||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Before;
|
||||
import org.keycloak.admin.client.resource.RoleMappingResource;
|
||||
import org.keycloak.testsuite.console.AbstractConsoleTest;
|
||||
import org.keycloak.testsuite.console.page.roles.Roles;
|
||||
import org.keycloak.testsuite.console.page.users.User;
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.jboss.arquillian.graphene.page.Page;
|
|||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.RolesResource;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import static org.keycloak.testsuite.admin.ApiUtil.createUserWithAdminClient;
|
||||
|
@ -31,7 +32,7 @@ public class DefaultRolesTest extends AbstractRolesTest {
|
|||
public void beforeDefaultRolesTest() {
|
||||
// create a role via admin client
|
||||
defaultRoleRep = new RoleRepresentation("default-role", "", false);
|
||||
rolesPage.rolesResource().create(defaultRoleRep);
|
||||
rolesResource().create(defaultRoleRep);
|
||||
|
||||
defaultRolesPage.navigateTo();
|
||||
// navigate to default roles page
|
||||
|
@ -58,4 +59,8 @@ public class DefaultRolesTest extends AbstractRolesTest {
|
|||
assertTrue(userRolesPage.form().isAssignedRole(defaultRoleName));
|
||||
}
|
||||
|
||||
public RolesResource rolesResource() {
|
||||
return testRealmResource().roles();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package org.keycloak.testsuite.console.users;
|
|||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Before;
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.admin.client.resource.UsersResource;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.testsuite.console.AbstractConsoleTest;
|
||||
import org.keycloak.testsuite.console.page.users.CreateUser;
|
||||
|
@ -35,5 +37,13 @@ public abstract class AbstractUserTest extends AbstractConsoleTest {
|
|||
createUserPage.form().setValues(user);
|
||||
createUserPage.form().save();
|
||||
}
|
||||
|
||||
|
||||
public UsersResource usersResource() {
|
||||
return testRealmResource().users();
|
||||
}
|
||||
|
||||
public UserResource userResource(String id) {
|
||||
return usersResource().get(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue