diff --git a/Jenkinsfile b/Jenkinsfile index 255c2298b48fb9187ee82f3cb2036b5b4775f5ee..6987f95b2b2e310760ed6401c6e871e6e6b2047e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -141,6 +141,7 @@ pipeline { sh 'helm version' } + setAnsibleKubeConfig() } } stage('Deploy Maven Artifacts to Nexus') { @@ -227,13 +228,12 @@ pipeline { script { def stageName = env.STAGE_NAME def bezeichner = generateBezeichner(stageName) - def namespace = generateNamespaceName(bezeichner) - startEnvironment(namespace, 'ea-values.yaml', 'ea-values.yaml', IMAGE_TAG, bezeichner) + startEnvironment(bezeichner, stageName, IMAGE_TAG, true) - def testResult = runTests(stageName, 'einheitlicher-ansprechpartner') + def testResult = runTests(stageName, bezeichner, 'einheitlicher-ansprechpartner') - shutdownEnvironment(namespace) + deleteKopStack(bezeichner, stageName) if(!testResult) { E2E_FAILED += "${stageName}, " @@ -254,13 +254,12 @@ pipeline { script { def stageName = env.STAGE_NAME def bezeichner = generateBezeichner(stageName) - def namespace = generateNamespaceName(bezeichner) - startEnvironment(namespace, 'values.yaml', 'values.yaml', IMAGE_TAG, bezeichner) + startEnvironment(bezeichner, stageName, IMAGE_TAG, false) - def testResult = runTests(stageName, 'main-tests') + def testResult = runTests(stageName, bezeichner, 'main-tests') - shutdownEnvironment(namespace) + deleteKopStack(bezeichner, stageName) if(!testResult) { E2E_FAILED += "${stageName}, " @@ -300,93 +299,188 @@ pipeline { } } -Void startEnvironment(String namespace, String goofyValues, String plutoValues, String imageTag, String bezeichner){ - checkIfNamespaceExists(namespace) +Void startEnvironment(String bezeichner, String stage, String imageTag, Boolean isEa) { + setupAnsible(imageTag, stage, isEa) - setupAnsible(imageTag) + try { + deleteKopStack(bezeichner, stage) + } catch (Exception e) { + echo "deleteKopStack Exception" + } - rolloutKopStack(bezeichner) - addKeycloakGroups(bezeichner) - addKeycloakUser(bezeichner) + rolloutKopStack(bezeichner, stage) + addKeycloakGroups(bezeichner, stage) + addKeycloakUser(bezeichner, stage) } -Void setupAnsible(String goofyImageTag) { - checkoutProvisioningRepo() +Void setupAnsible(String imageTag, String stage, Boolean isEa) { + checkoutProvisioningRepo(stage) + + if (env.BRANCH_NAME == 'release') { + copyTestEnvironmentToDev(stage) + } + + editEnvironemntVersion(stage, imageTag, isEa) + + if (isEa) { + setupEaEnvironment(stage) + } + + setPlutoDatabasePassword(stage) +} - setGoofyImageVersion(goofyImageTag) +Void setAnsibleKubeConfig() { + container("ansible") { + configFileProvider([configFile(fileId: 'jenkins-kuby-kubeconfig', variable: 'KUBE_CONFIG')]) { + sh 'mkdir ~/.kube' + sh 'cp ${KUBE_CONFIG} ~/.kube/config' + } + } } -Void checkoutProvisioningRepo() { +Void checkoutProvisioningRepo(String stage) { withCredentials([usernamePassword(credentialsId: 'jenkins-gitea-access-token', passwordVariable: 'TOKEN', usernameVariable: 'USER')]) { + dir(stage) { sh 'git clone https://${USER}:${TOKEN}@git.ozg-sh.de/mgm/provisioning.git' - sh 'git checkout ozg-2552' + + // todo remove git checkout + dir('provisioning') { + sh 'git checkout ozg-2552-jenkins-e2e' + } + } } } -Void setGoofyImageVersion(String goofyImageTag) { - dir('provisioning') { - def devVersions = readYaml file: "playbook/versions/dev.yaml" +Void copyTestEnvironmentToDev(stage) { + dir("${stage}/provisioning") { + def devEnvFile = "playbook/inventory/versions/dev.yml" + def testEnvFile = "playbook/inventory/versions/test.yml" - devVersions.versions.goofy.image.tag = goofyImageTag + def devVersions = readYaml file: devEnvFile + def testVersions = readYaml file: testEnvFile - writeYaml file: "playbook/versions/dev.yaml", data: devVersions + devVersions.charts = testVersions.charts + devVersions.versions = testVersions.versions - sh "cat playbook/versions/dev.yaml" + writeYaml file: devEnvFile, data: devVersions, overwrite: true } } -Void rolloutKopStack(String bezeichner) { +Void editEnvironemntVersion(String stage, String imageTag, Boolean isEa) { + dir("${stage}/provisioning") { + def editFile = "playbook/inventory/versions/dev.yml" + + def devVersions = readYaml file: editFile + + overrideSpringProfiles = getSpringProfile(isEa) + + devVersions.values.goofy.put('env', ['overrideSpringProfiles': overrideSpringProfiles]) + devVersions.values.pluto.put('env', ['overrideSpringProfiles': overrideSpringProfiles]) + + devVersions.versions.goofy.image.tag = imageTag + + writeYaml file: editFile, data: devVersions, overwrite: true + + sh "cat ${editFile}" + } +} + +String getSpringProfile(Boolean isEa) { + if (isEa) { + return "oc,ea,e2e,dev" + } + + return "oc,e2e,dev" +} + +Void setupEaEnvironment(String stage) { + dir("${stage}/provisioning") { + def editFile = "playbook/inventory/group_vars/all.yml" + def groupVars = readYaml file: editFile + + groupVars.kop_einheitlicher_ansprechpartner = true + + writeYaml file: editFile, data: groupVars, overwrite: true + } +} + +Void setPlutoDatabasePassword(String stage) { + dir("${stage}/provisioning") { + def editFile = "playbook/inventory/versions/dev.yml" + def devVars = readYaml file: editFile + + devVars.values.pluto.database.password = "XnHhfznNWg65NNd" + + writeYaml file: editFile, data: devVars, overwrite: true + } +} + +Void rolloutKopStack(String bezeichner, String stage) { container("ansible") { - dir('provisioning') { - def ansibleVars = """{ - "k8s_context": "ozg-dev", - "kop_env": "dev", - "kop_bezeichner": ${bezeichner}, - "kop_displayname": ${bezeichner}, - "kop_postfach_api_key": "", - "install_afm_adapter": false, - "install_fs_adapter": false, - "external_db_enabled": false - }""" - - sh "ansible-playbook playbook/rollout.yml --extra-vars ${ansibleVars}" + dir("${stage}/provisioning") { + def ansibleVars = """{"k8s_context":"ozg-dev", \ + "kop_env":"dev", \ + "kop_bezeichner":${bezeichner}, \ + "kop_displayname":${bezeichner}, \ + "kop_postfach_api_key":"", \ + "install_afm_adapter":false, \ + "install_fs_adapter":false, \ + "external_db_enabled":false}""" + + sh "ansible-playbook playbook/rollout.yml --extra-vars '${ansibleVars}'" } } } -Void addKeycloakGroups(bezeichner) { +Void addKeycloakGroups(String bezeichner, String stage) { container("ansible") { def groupFiles = sh (script: 'ls goofy-client/apps/goofy-e2e/src/fixtures/group', returnStdout: true) groupFiles.split("\\n").each { group -> def groupJson = sh (script: "cat goofy-client/apps/goofy-e2e/src/fixtures/group/${group}", returnStdout: true) - def ansibleVars = """{ - "k8s_context": "ozg-dev", - "kop_env": "dev", - "keycloak_realm": "sh-${bezeichner}-dev", - "group": ${groupJson} + def ansibleVars = """{"k8s_context":"ozg-dev", \ + "kop_env":"dev", \ + "keycloak_realm":"sh-${bezeichner}-dev", \ + "group":${groupJson} }""" - sh "ansible-playbook playbook/rollout.yml --extra-vars ${ansibleVars}" + dir("${stage}/provisioning") { + sh "ansible-playbook playbook/add-keycloak-group.yml --extra-vars '${ansibleVars}'" + } } } } -Void addKeycloakUser(String bezeichner) { - def userFiles = sh (script: 'ls goofy-client/apps/goofy-e2e/src/fixtures/user', returnStdout: true) +Void addKeycloakUser(String bezeichner, String stage) { + container("ansible") { + def userFiles = sh (script: 'ls goofy-client/apps/goofy-e2e/src/fixtures/user', returnStdout: true) - userFiles.split("\\n").each { user -> - def userJson = readJSON file: 'goofy-client/apps/goofy-e2e/src/fixtures/user/'+user + userFiles.split("\\n").each { user -> + def userJson = sh (script: "cat goofy-client/apps/goofy-e2e/src/fixtures/user/${user}", returnStdout: true) + + def ansibleVars = """{"k8s_context":"ozg-dev", \ + "kop_env":"dev", \ + "keycloak_realm":"sh-${bezeichner}-dev", \ + "user":${userJson} + }""" + + dir("${stage}/provisioning") { + sh "ansible-playbook playbook/add-keycloak-user.yml --extra-vars '${ansibleVars}'" + } + } + } +} - def ansibleVars = """{ - "k8s_context": "ozg-dev", - "kop_env": "dev", - "keycloak_realm": "sh-${bezeichner}-dev", - "user": ${userJson} - }""" +Void deleteKopStack(String bezeichner, String stage) { + container("ansible") { + dir("${stage}/provisioning") { + def ansibleVars = """{"k8s_context":"ozg-dev", \ + "kop_env":"dev", \ + "kop_bezeichner":${bezeichner}}""" - sh "ansible-playbook playbook/rollout.yml --extra-vars ${ansibleVars}" + sh "ansible-playbook playbook/delete-commune.yml --extra-vars '${ansibleVars}'" + } } } @@ -403,79 +497,11 @@ Void publishE2ETestResult(String reportFolder, String reportName) { ) } -Void checkIfNamespaceExists(String namespace) { - container("k8s") { - def namespaceList = sh (script: 'kubectl get namespaces', returnStdout: true) - - if(namespaceList.contains(namespace)) { - deleteNamespace(namespace) - } - } -} - -Void deleteNamespace(String namespace) { - sh "kubectl delete namespace ${namespace}" -} - -Void startPluto(String namespace, String values, String bezeichner) { - container("k8s") { - dir('goofy-client/apps/goofy-e2e/deployment-values/pluto') { - if(env.BRANCH_NAME == 'release') { - startPlutoForReleaseTests(namespace, values, bezeichner) - } - else { - startPlutoForSnapshotTests(namespace, values, bezeichner) - } - } - - sh "kubectl rollout status statefulset/pluto-database -n ${namespace}" - } -} +String runTests(String stageName, String bezeichner, String reportFolder) { + def configFile = generateCypressConfig(stageName, bezeichner, reportFolder) -Void startPlutoForReleaseTests(String namespace, String values, String bezeichner) { - sh "helm upgrade --install --create-namespace pluto ozg-base-apps/pluto -f ${values} --set kop.bezeichner=${bezeichner} --namespace ${namespace} --wait --wait-for-jobs" -} - -Void startPlutoForSnapshotTests(String namespace, String values, String bezeichner) { - sh "helm upgrade --install --create-namespace pluto ozg-base-apps-snapshot/pluto -f ${values} --set kop.bezeichner=${bezeichner} --namespace ${namespace} --version ${getLatestChartVersion('pluto').trim()} --wait --wait-for-jobs" -} - -Void startGoofy(String namespace, String values, String imageTag, String bezeichner) { - container("k8s") { - dir('goofy-client/apps/goofy-e2e/deployment-values/goofy') { - if(env.BRANCH_NAME == 'release') { - startGoofyForReleaseTests(namespace, values, bezeichner, imageTag) - } - else { - startGoofyForSnapshotTests(namespace, values, bezeichner, imageTag) - } - } - - waitForKeycloakClientCreation(namespace) - createKeycloakGroups(namespace) - generateKeycloakUserYaml(namespace) - applyKeycloakUser(namespace) - } -} - -Void startGoofyForReleaseTests(String namespace, String values, String bezeichner, String imageTag) { - sh "helm upgrade --install --create-namespace goofy ozg-base-apps/goofy -f ${values} --set image.tag=${imageTag} --set kop.bezeichner=${bezeichner} --namespace ${namespace} --wait --wait-for-jobs" -} - -Void startGoofyForSnapshotTests(String namespace, String values, String bezeichner, String imageTag) { - sh "helm upgrade --install --create-namespace goofy ozg-base-apps-snapshot/goofy -f ${values} --set image.tag=${imageTag} --set kop.bezeichner=${bezeichner} --namespace ${namespace} --version ${getLatestChartVersion('goofy').trim()} --wait --wait-for-jobs" -} - -String getLatestChartVersion(String chart) { - container("k8s") { - return sh (script: "helm search repo ozg-base-apps-snapshot --devel -l -o json | jq -r 'first(.[] | select((.name==\"ozg-base-apps-snapshot/${chart}\") and (.version|match(\"SNAPSHOT\$\"))) | .version)'", returnStdout: true) - } -} - -String runTests(String stageName, String reportFolder) { container("cypress") { try { - def configFile = generateCypressConfig(stageName, reportFolder) dir("goofy-client") { sh "npm run cypress:version" sh "npm run cypress:ci-run --CONFIG_FILE=${configFile} --REPORT_FOLDER=${reportFolder}" @@ -490,16 +516,6 @@ String runTests(String stageName, String reportFolder) { } } -Void shutdownEnvironment(String namespace) { - container("k8s") { - sh "helm uninstall goofy --namespace ${namespace} --wait" - sh "helm uninstall pluto --namespace ${namespace} --wait" - - removeKeycloakUser(namespace) - - sh "kubectl delete namespace ${namespace}" - } -} String makeUrlConform(String input) { return input.replaceAll(/[^a-zA-Z0-9]+/, "").toLowerCase() @@ -524,89 +540,15 @@ String cutBranchNameForKeycloakRealm(String branchName, String stageName) { return branchName } -String generateNamespaceName(String bezeichner) { - return "e2e-${bezeichner}-dev" -} - -Void generateKeycloakUserYaml(String namespace) { - def e2eUserFiles = sh (script: 'ls goofy-client/apps/goofy-e2e/src/fixtures/user', returnStdout: true) - - e2eUserFiles.split("\\n").each { user -> - def newUserYaml = readYaml file: "goofy-client/apps/goofy-e2e/deployment-values/goofy/user/user.yaml" - def userJson = readJSON file: 'goofy-client/apps/goofy-e2e/src/fixtures/user/'+user - - newUserYaml.metadata.name = namespace + "-" + userJson.name - newUserYaml.metadata.namespace = namespace - newUserYaml.metadata.labels.realm = namespace - newUserYaml.spec.realmSelector.matchLabels.realm = namespace - newUserYaml.spec.user.username = userJson.name - newUserYaml.spec.user.credentials = [[type: 'password', value: userJson.password]] - - if(userJson.firstName) { - newUserYaml.spec.user.firstName = userJson.firstName - } - - if(userJson.lastName) { - newUserYaml.spec.user.lastName = userJson.lastName - } - - if(userJson.clientRoles) { - newUserYaml.spec.user.clientRoles = [(namespace+"-goofy"): userJson.clientRoles] - } - - if(userJson.groups) { - newUserYaml.spec.user.groups = userJson.groups - } - - dir (namespace) { - writeYaml file: userJson.name+".yaml", data: newUserYaml - } - } -} - -Void createKeycloakGroups(String realm) { - def groupFiles = sh (script: 'ls goofy-client/apps/goofy-e2e/src/fixtures/group', returnStdout: true) - - groupFiles.split("\\n").each { group -> - def groupJson = sh (script: "cat goofy-client/apps/goofy-e2e/src/fixtures/group/${group}", returnStdout: true) - - sh """curl -X POST 'https://sso.dev.ozg-sh.de/auth/admin/realms/${realm}/groups' \ - -H 'Content-Type: application/json' \ - -H 'Authorization: bearer ${getKeycloakAccessToken()}' \ - --data-raw '${groupJson}' - """ - } -} - -Void applyKeycloakUser(String namespace) { - dir(namespace){ - def kcUserFiles = sh (script: "ls", returnStdout: true) - - kcUserFiles.split("\\n").each { user -> - sh "kubectl apply -f ${user}" - } - } -} - -Void removeKeycloakUser(String namespace) { - dir(namespace){ - def kcUserFiles = sh (script: "ls", returnStdout: true) - - kcUserFiles.split("\\n").each { user -> - sh "kubectl delete -f ${user}" - } - } -} -String generateCypressConfig(String stage, String testFolder) { - def bezeichner = generateBezeichner(stage) - def namespace = generateNamespaceName(bezeichner) +String generateCypressConfig(String stage, String bezeichner, String testFolder) { + def namespace = "sh-${bezeichner}-dev" def configName = "cypress-ci-"+testFolder+".json" dir('goofy-client/apps/goofy-e2e/'){ def config = readJSON file: 'cypress-ci.json' - config.baseUrl = "https://${makeUrlConform(env.BRANCH_NAME)}${makeUrlConform(stage)}.dev.ozg-sh.de" as String + config.baseUrl = "https://${bezeichner}.dev.ozg-sh.de" as String config.env.dbUrl = "mongodb+srv://pluto-database-user:XnHhfznNWg65NNd@pluto-database-svc.${namespace}.svc.cluster.local/admin?ssl=false" as String config.env.keycloakRealm = namespace as String config.env.keycloakClient = namespace + "-goofy" as String @@ -645,18 +587,6 @@ String getKeycloakAccessToken() { } } -Void waitForKeycloakClientCreation(realm) { - def shScript = """curl -H 'Content-Type: application/json' \ - -H 'Authorization: bearer ${getKeycloakAccessToken()}' \ - 'https://sso.dev.ozg-sh.de/auth/admin/realms/${realm}/clients' \ - | grep -q ${realm}-goofy - """ - - while(sh(script: shScript, returnStatus: true)) { - sh 'sleep 5' - } -} - Void sendFailureMessage() { def room = '' def data = """{"msgtype":"m.text", \