#!groovy

node {
  def rootPath = "/src/rancher-validation/"
  def job_name = "${JOB_NAME}"
  if (job_name.contains('/')) { 
    job_names = job_name.split('/')
    job_name = job_names[job_names.size() - 1] 
  }

  def containerPrefix = "${job_name}${BUILD_NUMBER}"

  def rancherConfig = "rancher_env.config"
  def imageName = "rancher-validation-${job_name}${env.BUILD_NUMBER}"
  def testsDir = "tests/v3_api/"

  def pre_branch = PREUPGRADE_BRANCH
  def post_branch = POSTUPGRADE_BRANCH

  def buildFail = false

  wrap([$class: 'AnsiColorBuildWrapper', 'colorMapName': 'XTerm', 'defaultFg': 2, 'defaultBg':1]) {
    withFolderProperties {
      withCredentials([ string(credentialsId: 'AWS_ACCESS_KEY_ID', variable: 'AWS_ACCESS_KEY_ID'),
                        string(credentialsId: 'AWS_SECRET_ACCESS_KEY', variable: 'AWS_SECRET_ACCESS_KEY'),
                        string(credentialsId: 'AWS_ACCESS_KEY_ID', variable: 'RANCHER_EKS_ACCESS_KEY'),
                        string(credentialsId: 'AWS_SECRET_ACCESS_KEY', variable: 'RANCHER_EKS_SECRET_KEY'),
                        string(credentialsId: 'DO_ACCESSKEY', variable: 'DO_ACCESSKEY'),
                        string(credentialsId: 'AWS_SSH_PEM_KEY', variable: 'AWS_SSH_PEM_KEY'),
                        string(credentialsId: 'RANCHER_SSH_KEY', variable: 'RANCHER_SSH_KEY'),
                        string(credentialsId: 'AZURE_SUBSCRIPTION_ID', variable: 'AZURE_SUBSCRIPTION_ID'),
                        string(credentialsId: 'AZURE_TENANT_ID', variable: 'AZURE_TENANT_ID'), 
                        string(credentialsId: 'AZURE_CLIENT_ID', variable: 'AZURE_CLIENT_ID'),
                        string(credentialsId: 'AZURE_CLIENT_SECRET', variable: 'AZURE_CLIENT_SECRET'),
                        string(credentialsId: 'AZURE_AKS_SUBSCRIPTION_ID', variable: 'RANCHER_AKS_SUBSCRIPTION_ID'),
                        string(credentialsId: 'AZURE_TENANT_ID', variable: 'RANCHER_AKS_TENANT_ID'), 
                        string(credentialsId: 'AZURE_CLIENT_ID', variable: 'RANCHER_AKS_CLIENT_ID'),
                        string(credentialsId: 'AZURE_CLIENT_SECRET', variable: 'RANCHER_AKS_SECRET_KEY'),
                        string(credentialsId: 'RANCHER_REGISTRY_USER_NAME', variable: 'RANCHER_REGISTRY_USER_NAME'),
                        string(credentialsId: 'RANCHER_REGISTRY_PASSWORD', variable: 'RANCHER_REGISTRY_PASSWORD'),
                        string(credentialsId: 'ADMIN_PASSWORD', variable: 'ADMIN_PASSWORD'),
                        string(credentialsId: 'USER_PASSWORD', variable: 'USER_PASSWORD'),
                        string(credentialsId: 'RANCHER_GKE_CREDENTIAL', variable: 'RANCHER_GKE_CREDENTIAL')]) {
        stage('Prechecks & checkout preupgrade branch') {
          if (RANCHER_SERVER_VERSION == "") {
            currentBuild.result = 'ABORTED'
            error("RANCHER_SERVER_VERSION must be provided!")
          }

          if (RANCHER_SERVER_VERSION_UPGRADE == "") {
            currentBuild.result = 'ABORTED'
            error("RANCHER_SERVER_VERSION_UPGRADE must be provided!")
          }

          if (PREUPGRADE_BRANCH == "") {
            currentBuild.result = 'ABORTED'
            error("PREUPGRADE_BRANCH must be provided!")
          }

          if (POSTUPGRADE_BRANCH == "") {
            currentBuild.result = 'ABORTED'
            error("POSTUPGRADE_BRANCH must be provided!")
          }

          deleteDir()
          checkout([
                    $class: 'GitSCM',
                    branches: [[name: "*/${pre_branch}"]],
                    extensions: scm.extensions + [[$class: 'CleanCheckout']],
                    userRemoteConfigs: scm.userRemoteConfigs
                  ])
          
          if (RANCHER_EXTRA_VARS != "" && RANCHER_EXTRA_VARS != null) {
            echo "${RANCHER_EXTRA_VARS}"
            writeFile(file: "preenv.config", text: "${RANCHER_EXTRA_VARS}")
            load "preenv.config"
          } 
        }

        stage('Configure and Build') {
          if (env.AWS_SSH_PEM_KEY && env.AWS_SSH_KEY_NAME) {
            dir("./tests/validation/.ssh") {
              def decoded = new String(AWS_SSH_PEM_KEY.decodeBase64())
              writeFile file: AWS_SSH_KEY_NAME, text: decoded
            }
          }
          sh "./tests/validation/tests/v3_api/scripts/configure.sh"
          sh "./tests/validation/tests/v3_api/scripts/build.sh"
        }

        stage('Deploy Rancher server') {
          try {
            sh "docker run --name ${containerPrefix}_deploy -t --env-file .env " +
                "${imageName} /bin/bash -c \'" +
                "pytest -v -s --junit-xml=deploy.xml " +
                "-k test_deploy_rancher_server ${testsDir}\'"

                sh "docker cp ${containerPrefix}_deploy:${rootPath}${testsDir}${rancherConfig} ."
                load rancherConfig
          } catch(err) {
            buildFail = true
            echo "Error: " + err
            echo "Deploy Rancher server failed"
            currentBuild.result = 'FAILURE'
          }
        }

        stage('Provision cluster') {
          try {
            sh "docker run --name ${containerPrefix}_provision  --env-file .env " +
              "${imageName} /bin/bash -c \'" +
              "export CATTLE_TEST_URL=${CATTLE_TEST_URL} && " +
              "export ADMIN_TOKEN=${ADMIN_TOKEN} && " +
              "export USER_TOKEN=${USER_TOKEN} && " +
              "pytest -v -s --junit-xml=provision.xml -k test_rke_${RANCHER_CLUSTER_TYPE}_host_${RANCHER_CLUSTER_PROFILE} ${testsDir}\'"
          } catch(err) {
            buildFail = true
            echo "Error: " + err
            echo "Provision cluster failed."
            currentBuild.result = 'FAILURE'
          }
        }

        stage('Run preupgrade') {
          try {
            sh "docker run --name ${containerPrefix}_preupgrade  --env-file .env " +
              "${imageName} /bin/bash -c \'" +
              "export CATTLE_TEST_URL=${CATTLE_TEST_URL} && " + 
              "export ADMIN_TOKEN=${ADMIN_TOKEN} && " +
              "export USER_TOKEN=${USER_TOKEN} && " +
              "export RANCHER_VALIDATE_RESOURCES_PREFIX=autopre && " +
              "export RANCHER_CREATE_RESOURCES_PREFIX=autopre && " +
              "export RANCHER_UPGRADE_CHECK=preupgrade && " +
              "export RANCHER_INGRESS_CHECK=True && " +
              "export RANCHER_ENABLE_HOST_NODE_PORT_TESTS=True && " +
              "export RANCHER_SKIP_INGRESS=False && " +
              "export RANCHER_CHECK_FOR_LB=False && " +
              "pytest -v -s --junit-xml=preupgrade.xml -k test_upgrade ${testsDir}\'"
          } catch(err) {
            buildFail = true
            echo "Error: " + err
            echo "Preupgrade tests failed"
            currentBuild.result = 'UNSTABLE'
          }
        }
        
        stage('Checkout postupgrade branch & rebuild') {
          checkout([
                    $class: 'GitSCM',
                    branches: [[name: "*/${post_branch}"]],
                    extensions: scm.extensions,
                    userRemoteConfigs: scm.userRemoteConfigs
                  ])

            if (env.AWS_SSH_PEM_KEY && env.AWS_SSH_KEY_NAME) {
              dir("./tests/validation/.ssh") {
                def decoded = new String(AWS_SSH_PEM_KEY.decodeBase64())
                writeFile file: AWS_SSH_KEY_NAME, text: decoded
              }
            }

            sh "./tests/validation/tests/v3_api/scripts/configure.sh"
            sh "./tests/validation/tests/v3_api/scripts/build.sh"
        }

        stage('Run upgrade') {
          try {
            sh "docker run --name ${containerPrefix}_upgrade  --env-file .env " +
              "${imageName} /bin/bash -c \'" +
              "export CATTLE_TEST_URL=${CATTLE_TEST_URL} && " + 
              "export ADMIN_TOKEN=${ADMIN_TOKEN} && " +
              "export USER_TOKEN=${USER_TOKEN} && " +
              "export RANCHER_UPGRADE_CHECK=upgrade_rancher && " +
              "pytest -v -s --junit-xml=upgrade.xml -k test_rancher_upgrade ${testsDir}\'"
          } catch(err) {
            buildFail = true
            echo "Error: " + err
            echo "Upgrade Rancher failed."
            currentBuild.result = 'FAILURE'
          }
        }

        stage('Run postupgrade tests') {
          try {
            sleep(time: 5, unit: "MINUTES")
            sh "docker run --name ${containerPrefix}_postupgrade  --env-file .env " + \
              "${imageName} /bin/bash -c \'" + 
              "export CATTLE_TEST_URL=${CATTLE_TEST_URL} && " + 
              "export ADMIN_TOKEN=${ADMIN_TOKEN} && " +
              "export USER_TOKEN=${USER_TOKEN} && " +
              "export RANCHER_VALIDATE_RESOURCES_PREFIX=autopre && " +
              "export RANCHER_CREATE_RESOURCES_PREFIX=autopost && " +
              "export RANCHER_UPGRADE_CHECK=postupgrade && " +
              "export RANCHER_INGRESS_CHECK=True && " +
              "export RANCHER_ENABLE_HOST_NODE_PORT_TESTS=True && " +
              "export RANCHER_SKIP_INGRESS=False && " +
              "export RANCHER_CHECK_FOR_LB=False && " +
              "pytest -v -s --junit-xml=postupgrade.xml -k test_upgrade ${testsDir}\'"
          } catch(err) {
            buildFail = true
            currentBuild.result = 'UNSTABLE'
            echo "Error: " + err
            echo "Postupgrade tests failed"
          }
        }  

        stage('Upgrade k8s') {
          try {
            if (RANCHER_K8S_VERSION_UPGRADE != null && RANCHER_K8S_VERSION_UPGRADE != "") {
              sh "docker run --name ${containerPrefix}_k8supgrade  --env-file .env " +
                "${imageName} /bin/bash -c \'" +
                "export CATTLE_TEST_URL=${CATTLE_TEST_URL} && " + 
                "export ADMIN_TOKEN=${ADMIN_TOKEN} && " +
                "export USER_TOKEN=${USER_TOKEN} && " +
                "pytest -v -s --junit-xml=k8supgrade.xml -k test_edit_cluster_k8s_version ${testsDir}\'"
            }
          } catch(err) {
            buildFail = true
            echo "Error: " + err
            echo "Upgrade cluster k8s failed."
            currentBuild.result = 'FAILURE'
          }
        }

        stage('Run postupgrade scripts') {
          try {
            if (RANCHER_K8S_VERSION_UPGRADE != null && RANCHER_K8S_VERSION_UPGRADE != "") {
              sh "docker run --name ${containerPrefix}_k8spostupgrade  --env-file .env " +
                "${imageName} /bin/bash -c \'" + 
                "export CATTLE_TEST_URL=${CATTLE_TEST_URL} && " + 
                "export ADMIN_TOKEN=${ADMIN_TOKEN} && " +
                "export USER_TOKEN=${USER_TOKEN} && " +
                "export RANCHER_VALIDATE_RESOURCES_PREFIX=autopost && " +
                "export RANCHER_CREATE_RESOURCES_PREFIX=autopost2 && " +
                "export RANCHER_UPGRADE_CHECK=postupgrade && " +
                "export RANCHER_INGRESS_CHECK=True && " +
                "export RANCHER_ENABLE_HOST_NODE_PORT_TESTS=True && " +
                "export RANCHER_SKIP_INGRESS=False && " +
                "export RANCHER_CHECK_FOR_LB=False && " +
                "pytest -v -s --junit-xml=k8spostupgrade.xml -k test_upgrade ${testsDir}\'"
            }
          } catch(err) {
            buildFail = true
            echo "Error: " + err
            echo "k8s postupgrade scripts failed"
            currentBuild.result = 'UNSTABLE'
          }
        }

        stage('Delete Rancher Server') {
          try {
            if (RANCHER_DELETE_SERVER.toLowerCase() == "true" && buildFail == false) {
              sh "docker run --name ${containerPrefix}_delete -t --env-file .env " + 
              "${imageName} /bin/bash -c \'" +
              "export CATTLE_TEST_URL=${CATTLE_TEST_URL} && " + 
              "export USER_TOKEN=${USER_TOKEN} && " +
              "pytest -v -s --junit-xml=delete.xml " +
              "-k test_delete_rancher_server ${testsDir}\'"
            } else {
              echo "Build failed or RANCHER_DELETE_SERVER is set to false"
              echo "SERVER IS NOT DELETED"
            }
          } catch(err) {
            echo "Error: " + err
            error()
            currentBuild.result = 'FAILURE'
          }
        }

        stage('Test Reports') {
          try {
            sh "docker cp ${containerPrefix}_deploy:${rootPath}deploy.xml ."
            sh "docker cp ${containerPrefix}_provision:${rootPath}provision.xml ."
            sh "docker cp ${containerPrefix}_preupgrade:${rootPath}preupgrade.xml ."
            sh "docker cp ${containerPrefix}_upgrade:${rootPath}upgrade.xml ."
            sh "docker cp ${containerPrefix}_postupgrade:${rootPath}postupgrade.xml ."
            
            if (RANCHER_K8S_VERSION_UPGRADE != null && RANCHER_K8S_VERSION_UPGRADE != "") {
              sh "docker cp ${containerPrefix}_k8supgrade:${rootPath}k8supgrade.xml ."
              sh "docker cp ${containerPrefix}_k8spostupgrade:${rootPath}k8spostupgrade.xml ."  
            }
            
            if (RANCHER_DELETE_SERVER.toLowerCase() == "true" && buildFail == false) {
              sh "docker cp ${containerPrefix}_delete:${rootPath}delete.xml ."
            }
            
            step([$class: 'JUnitResultArchiver', testResults: "**/*.xml"])
          } catch(err) {
            echo "Error: " + err
          }
        }

        stage('Cleanup') {
          sh "docker rm ${containerPrefix}_deploy"
          sh "docker rm ${containerPrefix}_provision"
          sh "docker rm ${containerPrefix}_preupgrade"
          sh "docker rm ${containerPrefix}_upgrade"
          sh "docker rm ${containerPrefix}_postupgrade"

          if (RANCHER_K8S_VERSION_UPGRADE != null && RANCHER_K8S_VERSION_UPGRADE != "") {
            sh "docker rm ${containerPrefix}_k8supgrade"
            sh "docker rm ${containerPrefix}_k8spostupgrade"
          }

          if (RANCHER_DELETE_SERVER.toLowerCase() == "true" && buildFail == false) {
            sh "docker rm  ${containerPrefix}_delete"
          }

          sh "docker rmi ${imageName}"
        }
      }
    }
  }
}