From 431920538bd95ddaede97facd8ba5a5531589bdf Mon Sep 17 00:00:00 2001 From: Dmytro Nochevnov Date: Thu, 3 Jan 2019 21:01:23 +0100 Subject: [PATCH] Make Keycloak CLI client for E2E test as extendable (#12325) Signed-off-by: Dmytro Nochevnov --- .../TestUserHttpJsonRequestFactory.java | 2 +- .../selenium/core/CheSeleniumSuiteModule.java | 19 +----- .../selenium/core/TestExecutionModule.java | 35 +++++++++++ .../KeycloakTestAuthServiceClient.java | 2 + .../keycloak/cli/KeycloakCliClient.java | 60 ++++++++++--------- .../OpenShiftKeycloakCliCommandExecutor.java | 38 ++++++++---- .../executor/hotupdate/HotUpdateUtil.java | 4 +- 7 files changed, 100 insertions(+), 60 deletions(-) create mode 100644 selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/TestExecutionModule.java diff --git a/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/requestfactory/TestUserHttpJsonRequestFactory.java b/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/requestfactory/TestUserHttpJsonRequestFactory.java index 303addb7b0..98482a1550 100644 --- a/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/requestfactory/TestUserHttpJsonRequestFactory.java +++ b/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/requestfactory/TestUserHttpJsonRequestFactory.java @@ -37,7 +37,7 @@ public class TestUserHttpJsonRequestFactory extends TestHttpJsonRequestFactory { return authServiceClient.login(testUser.getName(), testUser.getPassword()); } catch (Exception ex) { throw new RuntimeException( - format("Failed to get access token for user '%s'", testUser.getName())); + format("Failed to get access token for user '%s'", testUser.getName()), ex); } } } diff --git a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/CheSeleniumSuiteModule.java b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/CheSeleniumSuiteModule.java index 76cbfba33d..4f406a0b57 100644 --- a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/CheSeleniumSuiteModule.java +++ b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/CheSeleniumSuiteModule.java @@ -55,12 +55,6 @@ import org.eclipse.che.selenium.core.requestfactory.TestUserHttpJsonRequestFacto import org.eclipse.che.selenium.core.requestfactory.TestUserHttpJsonRequestFactoryCreator; import org.eclipse.che.selenium.core.user.DefaultTestUser; import org.eclipse.che.selenium.core.user.TestUserFactory; -import org.eclipse.che.selenium.core.webdriver.DownloadedFileUtil; -import org.eclipse.che.selenium.core.webdriver.DownloadedIntoGridFileUtil; -import org.eclipse.che.selenium.core.webdriver.DownloadedLocallyFileUtil; -import org.eclipse.che.selenium.core.webdriver.UploadIntoGridUtil; -import org.eclipse.che.selenium.core.webdriver.UploadLocallyUtil; -import org.eclipse.che.selenium.core.webdriver.UploadUtil; import org.eclipse.che.selenium.core.webdriver.log.WebDriverLogsReaderFactory; import org.eclipse.che.selenium.core.workspace.CheTestWorkspaceProvider; import org.eclipse.che.selenium.core.workspace.CheTestWorkspaceUrlResolver; @@ -127,7 +121,7 @@ public class CheSeleniumSuiteModule extends AbstractModule { install(new CheSeleniumSingleUserModule()); } - configureTestExecutionModeRelatedDependencies(); + install(new TestExecutionModule()); } private void configureInfrastructureRelatedDependencies(TestConfiguration config) { @@ -165,17 +159,6 @@ public class CheSeleniumSuiteModule extends AbstractModule { } } - private void configureTestExecutionModeRelatedDependencies() { - boolean gridMode = Boolean.valueOf(System.getProperty("grid.mode")); - if (gridMode) { - bind(DownloadedFileUtil.class).to(DownloadedIntoGridFileUtil.class); - bind(UploadUtil.class).to(UploadIntoGridUtil.class); - } else { - bind(DownloadedFileUtil.class).to(DownloadedLocallyFileUtil.class); - bind(UploadUtil.class).to(UploadLocallyUtil.class); - } - } - @Provides public TestWorkspace getWorkspace( TestWorkspaceProvider workspaceProvider, diff --git a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/TestExecutionModule.java b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/TestExecutionModule.java new file mode 100644 index 0000000000..f351ca3de2 --- /dev/null +++ b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/TestExecutionModule.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.selenium.core; + +import com.google.inject.AbstractModule; +import org.eclipse.che.selenium.core.webdriver.DownloadedFileUtil; +import org.eclipse.che.selenium.core.webdriver.DownloadedIntoGridFileUtil; +import org.eclipse.che.selenium.core.webdriver.DownloadedLocallyFileUtil; +import org.eclipse.che.selenium.core.webdriver.UploadIntoGridUtil; +import org.eclipse.che.selenium.core.webdriver.UploadLocallyUtil; +import org.eclipse.che.selenium.core.webdriver.UploadUtil; + +public class TestExecutionModule extends AbstractModule { + + @Override + protected void configure() { + boolean gridMode = Boolean.valueOf(System.getProperty("grid.mode")); + if (gridMode) { + bind(DownloadedFileUtil.class).to(DownloadedIntoGridFileUtil.class); + bind(UploadUtil.class).to(UploadIntoGridUtil.class); + } else { + bind(DownloadedFileUtil.class).to(DownloadedLocallyFileUtil.class); + bind(UploadUtil.class).to(UploadLocallyUtil.class); + } + } +} diff --git a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/client/keycloak/KeycloakTestAuthServiceClient.java b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/client/keycloak/KeycloakTestAuthServiceClient.java index 936f3adf3d..6f65465c4d 100644 --- a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/client/keycloak/KeycloakTestAuthServiceClient.java +++ b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/client/keycloak/KeycloakTestAuthServiceClient.java @@ -70,11 +70,13 @@ public class KeycloakTestAuthServiceClient extends AbstractKeycloakTestAuthServi } } + @Override protected KeycloakToken loginRequest(String username, String password) { return requestToken( PASSWORD, ImmutableList.of(Pair.of("username", username), Pair.of("password", password))); } + @Override protected KeycloakToken refreshRequest(KeycloakToken prevToken) { return requestToken( REFRESH_TOKEN, ImmutableList.of(Pair.of("refresh_token", prevToken.getRefreshToken()))); diff --git a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/client/keycloak/cli/KeycloakCliClient.java b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/client/keycloak/cli/KeycloakCliClient.java index 8e221f3cb7..1e97ccec26 100644 --- a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/client/keycloak/cli/KeycloakCliClient.java +++ b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/client/keycloak/cli/KeycloakCliClient.java @@ -18,6 +18,8 @@ import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.inject.Singleton; +import org.eclipse.che.selenium.core.client.keycloak.KeycloakSettings; +import org.eclipse.che.selenium.core.client.keycloak.TestKeycloakSettingsServiceClient; import org.eclipse.che.selenium.core.provider.AdminTestUserProvider; import org.eclipse.che.selenium.core.provider.RemovableUserProvider; import org.eclipse.che.selenium.core.user.AdminTestUser; @@ -44,15 +46,18 @@ public class KeycloakCliClient { private final TestUserFactory defaultTestUserFactory; private final TestUserFactory testUserFactory; + private final KeycloakSettings keycloakSettings; @Inject private KeycloakCliCommandExecutor executor; @Inject public KeycloakCliClient( TestUserFactory testUserFactory, - TestUserFactory defaultTestUserFactory) { + TestUserFactory defaultTestUserFactory, + TestKeycloakSettingsServiceClient testKeycloakSettingsServiceClient) { this.testUserFactory = testUserFactory; this.defaultTestUserFactory = defaultTestUserFactory; + this.keycloakSettings = testKeycloakSettingsServiceClient.read(); } public TestUserImpl createUser(RemovableUserProvider testUserProvider) throws IOException { @@ -85,13 +90,13 @@ public class KeycloakCliClient { private String doCreateUser(String username, String email, String password) throws IOException { String authPartOfCommand = format( - "--no-config --server http://localhost:8080/auth --user %s --password %s --realm master", + "--no-config --server http://0.0.0.0:8080/auth --user %s --password %s --realm master", adminTestUserProvider.get().getName(), adminTestUserProvider.get().getPassword()); String createUserCommand = format( - "create users -r che -s username=%s -s enabled=true %s 2>&1", - username, authPartOfCommand); + "create users -r %s -s username=%s -s enabled=true %s 2>&1", + getCheKeycloakRealm(), username, authPartOfCommand); String response = executor.execute(createUserCommand); if (!response.contains("Created new user with id ")) { throw new IOException("Test user creation error: " + response); @@ -99,27 +104,23 @@ public class KeycloakCliClient { String userId = extractUserId(response); - try { - String setTestUsersPermanentPasswordCommand = - format( - "set-password -r che --username %s --new-password %s %s 2>&1", - username, password, authPartOfCommand); - executor.execute(setTestUsersPermanentPasswordCommand); + String setTestUsersPermanentPasswordCommand = + format( + "set-password -r %s --username %s --new-password %s %s 2>&1", + getCheKeycloakRealm(), username, password, authPartOfCommand); + executor.execute(setTestUsersPermanentPasswordCommand); - String setEmailCommand = - format("update users/%s -r che --set email=%s %s 2>&1", userId, email, authPartOfCommand); - executor.execute(setEmailCommand); + String setEmailCommand = + format( + "update users/%s -r %s --set email=%s %s 2>&1", + userId, getCheKeycloakRealm(), email, authPartOfCommand); + executor.execute(setEmailCommand); - String addReadTokenRoleToUserCommand = - format( - "add-roles -r che --uusername %s --cclientid broker --rolename read-token %s 2>&1", - username, authPartOfCommand); - executor.execute(addReadTokenRoleToUserCommand); - } catch (IOException e) { - // clean up user - delete(userId, username); - throw e; - } + String addReadTokenRoleToUserCommand = + format( + "add-roles -r %s --uusername %s --cclientid broker --rolename read-token %s 2>&1", + getCheKeycloakRealm(), username, authPartOfCommand); + executor.execute(addReadTokenRoleToUserCommand); return userId; } @@ -128,13 +129,13 @@ public class KeycloakCliClient { public void setupAdmin(AdminTestUser adminTestUser) { String authPartOfCommand = format( - "--no-config --server http://localhost:8080/auth --user %s --password %s --realm master", + "--no-config --server http://0.0.0.0:8080/auth --user %s --password %s --realm master", adminTestUser.getName(), adminTestUser.getPassword()); String addReadTokenRoleToUserCommand = format( - "add-roles -r che --uusername %s --cclientid broker --rolename read-token %s 2>&1", - adminTestUser.getName(), authPartOfCommand); + "add-roles -r %s --uusername %s --cclientid broker --rolename read-token %s 2>&1", + getCheKeycloakRealm(), adminTestUser.getName(), authPartOfCommand); try { executor.execute(addReadTokenRoleToUserCommand); @@ -161,8 +162,9 @@ public class KeycloakCliClient { private void delete(String userId, String username) throws IOException { String commandToDeleteUser = format( - "delete users/%s -r che -s username=%s --no-config --server http://localhost:8080/auth --user %s --password %s --realm master 2>&1", + "delete users/%s -r %s -s username=%s --no-config --server http://0.0.0.0:8080/auth --user %s --password %s --realm master 2>&1", userId, + getCheKeycloakRealm(), username, adminTestUserProvider.get().getName(), adminTestUserProvider.get().getPassword()); @@ -171,4 +173,8 @@ public class KeycloakCliClient { LOG.info("Test user with name='{}' has been removed.", username); } + + private String getCheKeycloakRealm() { + return keycloakSettings.getKeycloakRealm(); + } } diff --git a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/client/keycloak/cli/OpenShiftKeycloakCliCommandExecutor.java b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/client/keycloak/cli/OpenShiftKeycloakCliCommandExecutor.java index b586a777d1..4fb56a6058 100644 --- a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/client/keycloak/cli/OpenShiftKeycloakCliCommandExecutor.java +++ b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/client/keycloak/cli/OpenShiftKeycloakCliCommandExecutor.java @@ -26,15 +26,26 @@ import org.eclipse.che.selenium.core.executor.OpenShiftCliCommandExecutor; */ @Singleton public class OpenShiftKeycloakCliCommandExecutor implements KeycloakCliCommandExecutor { - private static final String DEFAULT_OPENSHIFT_CHE_NAMESPACE = "eclipse-che"; + private static final String DEFAULT_CHE_OPENSHIFT_PROJECT = "eclipse-che"; + private static final String DEFAULT_KEYCLOAK_APP = "keycloak"; + private static final String DEFAULT_INTERNAL_PATH_TO_KEYCLOAK_CLI = + "/opt/jboss/keycloak/bin/kcadm.sh"; private String keycloakPodName; @Inject private OpenShiftCliCommandExecutor openShiftCliCommandExecutor; @Inject(optional = true) - @Named("env.openshift.che.namespace") - private String openShiftCheNamespace; + @Named("che.openshift.project") + private String cheOpenshiftProject; + + @Inject(optional = true) + @Named("env.keycloak.openshift.app") + private String keycloakApp; + + @Inject(optional = true) + @Named("env.keycloak.cli.internal.path") + private String internalPathToKeycloakCli; @Override public String execute(String command) throws IOException { @@ -43,7 +54,13 @@ public class OpenShiftKeycloakCliCommandExecutor implements KeycloakCliCommandEx } String openShiftKeycloakCliCommand = - format("exec %s -- /opt/jboss/keycloak/bin/kcadm.sh %s", keycloakPodName, command); + format( + "exec %s -- %s %s", + keycloakPodName, + internalPathToKeycloakCli != null + ? internalPathToKeycloakCli + : DEFAULT_INTERNAL_PATH_TO_KEYCLOAK_CLI, + command); return openShiftCliCommandExecutor.execute(openShiftKeycloakCliCommand); } @@ -52,20 +69,17 @@ public class OpenShiftKeycloakCliCommandExecutor implements KeycloakCliCommandEx // obtain name of keycloak pod String getKeycloakPodNameCommand = format( - "get pod --namespace=%s -l app=keycloak --no-headers | awk '{print $1}'", - openShiftCheNamespace != null - ? openShiftCheNamespace - : DEFAULT_OPENSHIFT_CHE_NAMESPACE); + "get pod --namespace=%s -l app=%s --no-headers | awk '{print $1}'", + cheOpenshiftProject != null ? cheOpenshiftProject : DEFAULT_CHE_OPENSHIFT_PROJECT, + keycloakApp != null ? keycloakApp : DEFAULT_KEYCLOAK_APP); keycloakPodName = openShiftCliCommandExecutor.execute(getKeycloakPodNameCommand); if (keycloakPodName.trim().isEmpty()) { String errorMessage = format( - "Keycloak pod is not found at namespace %s at OpenShift instance.", - openShiftCheNamespace != null - ? openShiftCheNamespace - : DEFAULT_OPENSHIFT_CHE_NAMESPACE); + "Keycloak pod is not found at project %s at OpenShift instance.", + cheOpenshiftProject != null ? cheOpenshiftProject : DEFAULT_CHE_OPENSHIFT_PROJECT); throw new RuntimeException(errorMessage); } diff --git a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/executor/hotupdate/HotUpdateUtil.java b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/executor/hotupdate/HotUpdateUtil.java index db90df529a..0d29d89876 100644 --- a/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/executor/hotupdate/HotUpdateUtil.java +++ b/selenium/che-selenium-test/src/main/java/org/eclipse/che/selenium/core/executor/hotupdate/HotUpdateUtil.java @@ -41,8 +41,8 @@ public class HotUpdateUtil { "get dc | grep che | awk '{print $1}'"; private static final String UPDATE_COMMAND_TEMPLATE = "rollout latest %s"; - private final OpenShiftCliCommandExecutor openShiftCliCommandExecutor; - private final TestUserPreferencesServiceClient testUserPreferencesServiceClient; + protected final OpenShiftCliCommandExecutor openShiftCliCommandExecutor; + protected final TestUserPreferencesServiceClient testUserPreferencesServiceClient; @Inject public HotUpdateUtil(