diff --git a/alfa-client/apps/alfa-e2e/Jenkinsfile b/alfa-client/apps/alfa-e2e/Jenkinsfile index 25e990e99f368c3190158c99c989134c04785f86..3e2c42250d1972c8da035506c48b64a13adf0776 100644 --- a/alfa-client/apps/alfa-e2e/Jenkinsfile +++ b/alfa-client/apps/alfa-e2e/Jenkinsfile @@ -219,7 +219,7 @@ pipeline { forwardServices(generateNamespace(bezeichner), dbPort) - runTests(bezeichner, 'einheitlicher-ansprechpartner', dbPort, env.STAGE_NAME) + runTests(bezeichner, 'einheitlicher-ansprechpartner', 'user-ea', dbPort, env.STAGE_NAME) } } } @@ -246,7 +246,7 @@ pipeline { forwardServices(generateNamespace(bezeichner), dbPort) - runTests(bezeichner, 'main-tests', dbPort, env.STAGE_NAME) + runTests(bezeichner, 'main-tests', 'user-main', dbPort, env.STAGE_NAME) } } } @@ -452,7 +452,7 @@ Void generateNamespaceYaml(String bezeichner, String valuesPathSuffix, String us envValues.user_manager.put("helm", ['version': env.USER_MANAGER_HELM_CHART_VERSION, 'repoUrl': env.USER_MANAGER_HELM_REPO_URL]) envValues.alfa.sso.put("keycloak_groups", generateKeycloakGroupsForHelmChart()) - envValues.alfa.sso.put("keycloak_users", generateKeycloakUserForHelmChart(userFolder)) + envValues.alfa.sso.put("keycloak_users", generateKeycloakUserForHelmChart('alfa-client/apps/alfa-e2e/src/fixtures', userFolder)) writeYaml file: "gitops/dev/namespace/namespaces/by-${bezeichner}-dev.yaml", data: envValues, overwrite: true @@ -464,27 +464,24 @@ Void generateNamespaceYaml(String bezeichner, String valuesPathSuffix, String us } } -List generateKeycloakUserForHelmChart(String userFolder) { - def userFiles = sh (script: 'ls alfa-client/apps/alfa-e2e/src/fixtures/' + userFolder, returnStdout: true); - +List generateKeycloakUserForHelmChart(String fixturesPath, String userFolder) { def helmUsers = [] - userFiles.split("\\n").each { userFile -> - def userJson = readJSON file: "alfa-client/apps/alfa-e2e/src/fixtures/${userFolder}/${userFile}" + readUsersFixtures(fixturesPath, userFolder).each { username, userFixture -> def user = [ - "name": userJson.name, - "password": userJson.password, - "first_name": userJson.get("firstName", ""), - "last_name": userJson.get("lastName", ""), - "email": userJson.get("email", "") - ] - - if (userJson.containsKey("clientRoles")) { - user.put("client_roles", mapUserClientRoles(userJson.clientRoles)) + "name" : userFixture.name, + "password" : userFixture.password, + "first_name": userFixture.get("firstName", ""), + "last_name" : userFixture.get("lastName", ""), + "email" : userFixture.get("email", "") + ] + + if (userFixture.containsKey("clientRoles")) { + user.put("client_roles", mapUserClientRoles(userFixture.clientRoles)) } - if (userJson.containsKey("groups")) { - user.put("groups", userJson.groups) + if (userFixture.containsKey("groups")) { + user.put("groups", userFixture.groups) } helmUsers.add(user) @@ -522,7 +519,7 @@ List generateKeycloakGroupsForHelmChart() { } helmGroups.add(group) - } + } return helmGroups } @@ -618,13 +615,13 @@ Void publishE2ETestResult(String reportFolder, String reportName) { ) } -String runTests(String bezeichner, String reportFolder, Integer dbPort, String stageName) { - def config = generateCypressConfig(bezeichner, reportFolder, dbPort) +String runTests(String bezeichner, String reportFolder, String userFolder, Integer dbPort, String stageName) { + def config = generateCypressConfig(bezeichner, reportFolder, userFolder, dbPort) try { dir('alfa-client'){ - sh "npm run cypress:version" - sh "apps/alfa-e2e/run-tests.sh ${reportFolder} ${config}" + sh "npm run cypress:version" + sh "apps/alfa-e2e/run-tests.sh ${reportFolder} ${config}" } } catch (Exception e) { printNpmDebugLog() @@ -661,37 +658,37 @@ String cutBranchNameForKeycloakRealm(String branchName, String stageName) { return branchName.take(cutBranchNamePosition) } -String generateCypressConfig(String bezeichner, String testFolder, Integer dbPort) { +String generateCypressConfig(String bezeichner, String testFolder, String userFolder, Integer dbPort) { def namespace = generateNamespace(bezeichner) - def configName = "cypress-ci-"+testFolder+".json" + def configName = "cypress-ci-"+testFolder+".json" - dir('alfa-client/apps/alfa-e2e/'){ - def config = readJSON file: 'cypress-ci.json' + dir('alfa-client/apps/alfa-e2e/'){ + def config = readJSON file: 'cypress-ci.json' - def vorgangManagerDatabaseSecret = getVorgangManagerDatabaseSecret(namespace); - def decodedPassword = decodeString(vorgangManagerDatabaseSecret.password); - def parsablePassword = makePasswordUrlConform(decodedPassword); + def vorgangManagerDatabaseSecret = getVorgangManagerDatabaseSecret(namespace); + def decodedPassword = decodeString(vorgangManagerDatabaseSecret.password); + def parsablePassword = makePasswordUrlConform(decodedPassword); - config.baseUrl = "https://${bezeichner}.${env.CLUSTER_BASE_URL}" as String - config.env.dbUrl = "mongodb://${decodeString(vorgangManagerDatabaseSecret.username)}:${parsablePassword}@localhost:${dbPort}/admin?ssl=false&directConnection=true" as String - config.env.keycloakUrl = "https://${env.SSO_URL}/" as String - config.env.keycloakRealm = namespace as String - config.env += createUserIdsEnv(namespace, ["sabine", "dorothea", "emil", "peter"]) - config.videosFolder = "./reports/${testFolder}/videos" as String - config.screenshotsFolder = "./reports/${testFolder}/screenshots" as String - config.reporterOptions.reportDir = "./reports/${testFolder}/mochawesome-report" as String + config.baseUrl = "https://${bezeichner}.${env.CLUSTER_BASE_URL}" as String + config.env.dbUrl = "mongodb://${decodeString(vorgangManagerDatabaseSecret.username)}:${parsablePassword}@localhost:${dbPort}/admin?ssl=false&directConnection=true" as String + config.env.keycloakUrl = "https://${env.SSO_URL}/" as String + config.env.keycloakRealm = namespace as String + config.env += createUserIdsEnv('src/fixtures', userFolder, namespace) + config.videosFolder = "./reports/${testFolder}/videos" as String + config.screenshotsFolder = "./reports/${testFolder}/screenshots" as String + config.reporterOptions.reportDir = "./reports/${testFolder}/mochawesome-report" as String config.specPattern = "src/e2e/${testFolder}/**/*.cy.{js,jsx,ts,tsx}" as String - config.env.put("search", getElasticsearchEnv(namespace)) - config.env.put("userManager", getUserManagerEnv(namespace, dbPort)) + config.env.put("search", getElasticsearchEnv(namespace)) + config.env.put("userManager", getUserManagerEnv(namespace, dbPort)) - writeJSON file: configName, json: config + writeJSON file: configName, json: config - sh "cat ${configName}" - } + sh "cat ${configName}" + } - return "cypress-ci-"+testFolder+".config.ts" + return "cypress-ci-"+testFolder+".config.ts" } String makePasswordUrlConform(String password) { @@ -703,9 +700,9 @@ Map getVorgangManagerDatabaseSecret(String namespace) { } Map getUserManagerEnv(String namespace, dbPort){ - def userManagerDatabaseSecret = getUserManagerDatabaseSecret(namespace); + def userManagerDatabaseSecret = getUserManagerDatabaseSecret(namespace); def decodedPassword = decodeString(userManagerDatabaseSecret.password); - def parsablePassword = makePasswordUrlConform(decodedPassword); + def parsablePassword = makePasswordUrlConform(decodedPassword); return [ "dbUrl": "mongodb://${decodeString(userManagerDatabaseSecret.username)}:${parsablePassword}@localhost:${dbPort}/admin?ssl=false&directConnection=true" as String, @@ -717,51 +714,46 @@ Map getUserManagerDatabaseSecret(String namespace) { return readJSON ( text: sh (script: "kubectl get secret ozg-mongodb-admin-user-manager-user -n ${namespace} -o jsonpath={.data}", returnStdout: true)) } -Map createUserIdsEnv(realm, usernames) { - def env = [:] - def userIds = getUserIds(realm, usernames) - - echo "userIds: ${userIds}" - - for (username in usernames) { - if (userIds[username]) { - env[(username + "Uuid")] = userIds[username].id - env[(username + "InternalId")] = userIds[username].ozgCloudUserId - } else { - echo "user ${username} not found in Keycloak" - } - } - return env +Map createUserIdsEnv(String fixturesPath, String userFolder, realm) { + def keycloakUsers = getKeycloakUsers(realm) + def usersFixtures = readUsersFixtures(fixturesPath, userFolder) + return usersFixtures.collectEntries { username, user -> + [(username + "Uuid") : keycloakUsers[username].id, + (username + "InternalId"): keycloakUsers[username].attributes.ozgCloudUserId[0]] + } } -Map getUserIds(realm, usernames) { - def shScript = """curl -H 'Content-Type: application/json' \ +Map getKeycloakUsers(realm) { + def shScript = """curl -H 'Content-Type: application/json' \ -H 'Authorization: bearer ${getKeycloakAccessToken(realm)}' \ 'https://${env.SSO_URL}/admin/realms/${realm}/users' """ + def keycloakUsers = readJSON text: sh(script: shScript, returnStdout: true) - def users = readJSON text: sh(script: shScript, returnStdout: true) + echo "keycloak users: ${keycloakUsers}" - echo "users: ${users}" + return keycloakUsers.collectEntries { [it.username, it] } +} - return users - .findAll { it.username in usernames } - .collectEntries { - [ - (it.username): [ - "id" : it.id, - "ozgCloudUserId": it.attributes.ozgCloudUserId[0] - ] - ] - } +Map readUsersFixtures(String fixturesPath, String userFolder) { + def usersFixturesFiles = sh(script: "ls ${fixturesPath}/${userFolder}", returnStdout: true); + return usersFixturesFiles.split("\\n") + .collect { userFixtureFile -> + def userFixture = readJSON file: "${fixturesPath}/${userFolder}/${userFixtureFile}" + return ["name" : userFixture.name, + "password" : userFixture.password, + "first_name": userFixture.get("firstName", ""), + "last_name" : userFixture.get("lastName", ""), + "email" : userFixture.get("email", "")] + }.collectEntries { [it.name, it] } } String getKeycloakAccessToken(String realm) { def userManagerApiUserCredentials = getUserManagerApiUserCredentials(realm) - def token = readJSON text: sh (script: "set +x && curl -d \"client_id=admin-cli\" -d \"username=${userManagerApiUserCredentials.user}\" -d \"password=${userManagerApiUserCredentials.password}\" -d \"grant_type=password\" https://$SSO_URL/realms/$realm/protocol/openid-connect/token", returnStdout: true) + def token = readJSON text: sh (script: "set +x && curl -d \"client_id=admin-cli\" -d \"username=${userManagerApiUserCredentials.user}\" -d \"password=${userManagerApiUserCredentials.password}\" -d \"grant_type=password\" https://$SSO_URL/realms/$realm/protocol/openid-connect/token", returnStdout: true) - return token.access_token + return token.access_token } Map getUserManagerApiUserCredentials(String namespace) { diff --git a/alfa-client/apps/alfa-e2e/Jenkinsfile-static b/alfa-client/apps/alfa-e2e/Jenkinsfile-static index 4265d7063dc3f37916dc5082317b389fa305607a..3182e1110f15268a1f66b8ae91ed1117d3c64558 100644 --- a/alfa-client/apps/alfa-e2e/Jenkinsfile-static +++ b/alfa-client/apps/alfa-e2e/Jenkinsfile-static @@ -192,7 +192,7 @@ pipeline { forwardServices(generateNamespace(bezeichner), dbPort) - runTests(bezeichner, 'einheitlicher-ansprechpartner', dbPort, env.STAGE_NAME) + runTests(bezeichner, 'einheitlicher-ansprechpartner', 'user-ea', dbPort, env.STAGE_NAME) } } } @@ -222,7 +222,7 @@ pipeline { forwardServices(generateNamespace(bezeichner), dbPort) - runTests(bezeichner, 'main-tests', dbPort, env.STAGE_NAME) + runTests(bezeichner, 'main-tests', 'user-main', dbPort, env.STAGE_NAME) } } } @@ -327,8 +327,8 @@ Void publishE2ETestResult(String reportFolder, String reportName) { ) } -String runTests(String bezeichner, String reportFolder, Integer dbPort, String stageName) { - def config = generateCypressConfig(bezeichner, reportFolder, dbPort) +String runTests(String bezeichner, String reportFolder, String userFolder, Integer dbPort, String stageName) { + def config = generateCypressConfig(bezeichner, reportFolder, userFolder, dbPort) try { dir("alfa-client") { @@ -370,11 +370,11 @@ String cutBranchNameForKeycloakRealm(String branchName, String stageName) { return branchName.take(cutBranchNamePosition) } -String generateCypressConfig(String bezeichner, String testFolder, Integer dbPort) { +String generateCypressConfig(String bezeichner, String testFolder, String userFolder, Integer dbPort) { def namespace = generateNamespace(bezeichner) - def configName = "cypress-ci-"+testFolder+".json" + def configName = "cypress-ci-" + testFolder + ".json" - dir('alfa-client/apps/alfa-e2e/'){ + dir('alfa-client/apps/alfa-e2e/') { def config = readJSON file: 'cypress-ci.json' def vorgangManagerDatabaseSecret = getVorgangManagerDatabaseSecret(namespace); @@ -385,7 +385,7 @@ String generateCypressConfig(String bezeichner, String testFolder, Integer dbPor config.env.dbUrl = "mongodb://${decodeString(vorgangManagerDatabaseSecret.username)}:${parsablePassword}@localhost:${dbPort}/admin?ssl=false&directConnection=true" as String config.env.keycloakUrl = "https://${env.SSO_URL}/" as String config.env.keycloakRealm = namespace as String - config.env += createUserIdsEnv(namespace, ["sabine", "dorothea", "emil", "peter"]) + config.env += createUserIdsEnv('src/fixtures', userFolder, namespace) config.videosFolder = "./reports/${testFolder}/videos" as String config.screenshotsFolder = "./reports/${testFolder}/screenshots" as String config.reporterOptions.reportDir = "./reports/${testFolder}/mochawesome-report" as String @@ -400,11 +400,11 @@ String generateCypressConfig(String bezeichner, String testFolder, Integer dbPor sh "cat ${configName}" } - return "cypress-ci-"+testFolder+".config.ts" + return "cypress-ci-" + testFolder + ".config.ts" } Map getVorgangManagerDatabaseSecret(String namespace) { - return readJSON ( text: sh (script: "kubectl get secret ozg-mongodb-admin-vorgang-manager-user -n ${namespace} -o jsonpath={.data}", returnStdout: true)) + return readJSON(text: sh(script: "kubectl get secret ozg-mongodb-admin-vorgang-manager-user -n ${namespace} -o jsonpath={.data}", returnStdout: true)) } Map getUserManagerEnv(String namespace, dbPort){ @@ -419,76 +419,67 @@ Map getUserManagerEnv(String namespace, dbPort){ } Map getUserManagerDatabaseSecret(String namespace) { - return readJSON ( text: sh (script: "kubectl get secret ozg-mongodb-admin-user-manager-user -n ${namespace} -o jsonpath={.data}", returnStdout: true)) + return readJSON(text: sh(script: "kubectl get secret ozg-mongodb-admin-user-manager-user -n ${namespace} -o jsonpath={.data}", returnStdout: true)) } String makePasswordUrlConform(String password) { - return sh (script: "printf %s ${password} | jq -sRr @uri", returnStdout: true); + return sh(script: "printf %s ${password} | jq -sRr @uri", returnStdout: true); } -Map createUserIdsEnv(realm, usernames) { - def env = [:] - def userIds = getUserIds(realm, usernames) - - echo "userIds: ${userIds}" - - for (username in usernames) { - if (userIds[username]) { - env[(username + "Uuid")] = userIds[username].id - env[(username + "InternalId")] = userIds[username].ozgCloudUserId - } else { - echo "user ${username} not found in Keycloak" - } - } - return env +Map createUserIdsEnv(String fixturesPath, String userFolder, realm) { + def keycloakUsers = getKeycloakUsers(realm) + def usersFixtures = readUsersFixtures(fixturesPath, userFolder) + return usersFixtures.collectEntries { username, user -> + [(username + "Uuid") : keycloakUsers[username].id, + (username + "InternalId"): keycloakUsers[username].attributes.ozgCloudUserId[0]] + } } -Map getUserIds(realm, usernames) { - def shScript = """curl -H 'Content-Type: application/json' \ +Map getKeycloakUsers(realm) { + def shScript = """curl -H 'Content-Type: application/json' \ -H 'Authorization: bearer ${getKeycloakAccessToken(realm)}' \ 'https://${env.SSO_URL}/admin/realms/${realm}/users' """ + def keycloakUsers = readJSON text: sh(script: shScript, returnStdout: true) - def users = readJSON text: sh(script: shScript, returnStdout: true) + echo "keycloak users: ${keycloakUsers}" - echo "users: ${users}" + return keycloakUsers.collectEntries { [it.username, it] } +} - return users - .findAll { it.username in usernames } - .collectEntries { - [ - (it.username): [ - "id" : it.id, - "ozgCloudUserId": it.attributes.ozgCloudUserId[0] - ] - ] - } +Map readUsersFixtures(String fixturesPath, String userFolder) { + def usersFixturesFiles = sh(script: "ls ${fixturesPath}/${userFolder}", returnStdout: true); + return usersFixturesFiles.split("\\n") + .collect { userFixtureFile -> + def userFixture = readJSON file: "${fixturesPath}/${userFolder}/${userFixtureFile}" + return ["name" : userFixture.name, + "password" : userFixture.password, + "first_name": userFixture.get("firstName", ""), + "last_name" : userFixture.get("lastName", ""), + "email" : userFixture.get("email", "")] + }.collectEntries { [it.name, it] } } String getKeycloakAccessToken(String realm) { def userManagerApiUserCredentials = getUserManagerApiUserCredentials(realm) - def token = readJSON text: sh (script: "set +x && curl -d \"client_id=admin-cli\" -d \"username=${userManagerApiUserCredentials.user}\" -d \"password=${userManagerApiUserCredentials.password}\" -d \"grant_type=password\" https://$SSO_URL/realms/$realm/protocol/openid-connect/token", returnStdout: true) + def token = readJSON text: sh(script: "set +x && curl -d \"client_id=admin-cli\" -d \"username=${userManagerApiUserCredentials.user}\" -d \"password=${userManagerApiUserCredentials.password}\" -d \"grant_type=password\" https://$SSO_URL/realms/$realm/protocol/openid-connect/token", returnStdout: true) return token.access_token } Map getUserManagerApiUserCredentials(String namespace) { - def userManagerApiUserCredentials = readJSON ( text: sh (script: "kubectl get secret usermanagerapiuser-credentials -n ${namespace} -o jsonpath={.data}", returnStdout: true)) + def userManagerApiUserCredentials = readJSON(text: sh(script: "kubectl get secret usermanagerapiuser-credentials -n ${namespace} -o jsonpath={.data}", returnStdout: true)) - return [ - "user": decodeString(userManagerApiUserCredentials.name), - "password": decodeString(userManagerApiUserCredentials.password) - ] + return ["user" : decodeString(userManagerApiUserCredentials.name), + "password": decodeString(userManagerApiUserCredentials.password)] } Void sendFailureMessage() { - def data = [ - "msgtype": "m.text", - "body": "E2E-Tests: Failed stage: ${getFailedStage()} Build-ID: ${env.BUILD_NUMBER} Link: ${BLUE_OCEAN_URL}" as String, - "format": "org.matrix.custom.html", - "formatted_body": "E2E-Tests: Failed stage: ${getFailedStage()} Build-ID: <a href='${BLUE_OCEAN_URL}'>${env.BUILD_NUMBER}</a>" as String - ] + def data = ["msgtype" : "m.text", + "body" : "E2E-Tests: Failed stage: ${getFailedStage()} Build-ID: ${env.BUILD_NUMBER} Link: ${BLUE_OCEAN_URL}" as String, + "format" : "org.matrix.custom.html", + "formatted_body": "E2E-Tests: Failed stage: ${getFailedStage()} Build-ID: <a href='${BLUE_OCEAN_URL}'>${env.BUILD_NUMBER}</a>" as String] sh "curl -XPOST -H 'authorization: Bearer ${getElementAccessToken()}' -d '${JsonOutput.toJson(data)}' https://matrix.ozg-sh.de/_matrix/client/v3/rooms/${getElementRoomId()}/send/m.room.message" } @@ -514,27 +505,24 @@ String getElementRoomId() { String getElementAccessToken() { withCredentials([string(credentialsId: 'element-login-json', variable: 'LOGIN_JSON')]) { - return readJSON ( text: sh (script: '''curl -XPOST -d \"$LOGIN_JSON\" https://matrix.ozg-sh.de/_matrix/client/v3/login''', returnStdout: true)).access_token + return readJSON(text: sh(script: '''curl -XPOST -d \"$LOGIN_JSON\" https://matrix.ozg-sh.de/_matrix/client/v3/login''', returnStdout: true)).access_token } } Map getElasticsearchEnv(String namespace) { def elasticsearchSecret = getElasticsearchSecret(namespace) - return [ - "user": decodeString(elasticsearchSecret.username), - "password": decodeString(elasticsearchSecret.password), - "index": decodeString(elasticsearchSecret.index), - "url": "https://localhost:9200" - ] + return ["user" : decodeString(elasticsearchSecret.username), + "password": decodeString(elasticsearchSecret.password), + "index" : decodeString(elasticsearchSecret.index), + "url" : "https://localhost:9200"] } Void forwardServices(String namespace, Integer dbPort) { try { forwardDatenbank(namespace, dbPort) forwardElasticSearch() - } - catch (Exception e) { + } catch (Exception e) { echo "forwardServices Exception: ${e}" error("Error forwarding service") } @@ -547,7 +535,7 @@ Void forwardElasticSearch() { } Boolean isElasticSearchForwarded() { - return sh (script: "lsof -i -P -n | grep LISTEN | grep :9200", returnStatus: true) == env.SH_SUCCESS_STATUS_CODE as Integer + return sh(script: "lsof -i -P -n | grep LISTEN | grep :9200", returnStatus: true) == env.SH_SUCCESS_STATUS_CODE as Integer } Void forwardDatenbank(String namespace, port) { @@ -559,13 +547,13 @@ String generateNamespace(String bezeichner) { } String decodeString(String encoded) { - return sh (script: "echo -n ${encoded} | base64 --decode", returnStdout: true) + return sh(script: "echo -n ${encoded} | base64 --decode", returnStdout: true) } Map getElasticsearchSecret(String namespace) { - return readJSON ( text: sh (script: "kubectl get secret elasticsearch-credentials -n ${namespace} -o jsonpath={.data}", returnStdout: true)) + return readJSON(text: sh(script: "kubectl get secret elasticsearch-credentials -n ${namespace} -o jsonpath={.data}", returnStdout: true)) } Boolean hasNpmDebugLog() { - return sh (script: "ls -l /root/.npm/_logs/*-debug.log", returnStatus: true) == env.SH_SUCCESS_STATUS_CODE as Integer + return sh(script: "ls -l /root/.npm/_logs/*-debug.log", returnStatus: true) == env.SH_SUCCESS_STATUS_CODE as Integer } \ No newline at end of file