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", \