#!groovy

// RANCHER_VERSION resolution is first via Jenkins Build Parameter RANCHER_VERSION fed in from console,
// then from $DOCKER_TRIGGER_TAG which is sourced from the Docker Hub Jenkins plugin webhook.

def rancher_version() {
  try { if ('' != RANCHER_VERSION) { return RANCHER_VERSION } }
  catch (MissingPropertyException e) {}

  try { return DOCKER_TRIGGER_TAG }
  catch (MissingPropertyException e) {}

  echo  'Neither RANCHER_VERSION nor DOCKER_TRIGGER_TAG have been specified!'
  error()
}

def lastBuildResult() {
 def previous_build = currentBuild.getPreviousBuild()
  if ( null != previous_build ) { return previous_build.result } else { return 'UNKNOWN' }
}

def via_webhook() {
  try {
    def foo = DOCKER_TRIGGER_TAG
    return true
  } catch(MissingPropertyException) {
    return false
  }
}

// Filter out Docker Hub tags like 'latest', 'master', 'enterprise'.
// Just want things like v1.2*
def branch = "v2.1"
def rancher_version = rancher_version()
def String rancher_version_regex = "^v[\\d]\\.[\\d]\\.[\\d][\\-rc\\d]+\$"

if ( true == via_webhook() && (!(rancher_version ==~ rancher_version_regex)) ) {
  println("Received RANCHER_VERSION \'${rancher_version}\' via webhook which does not match regex \'${rancher_version_regex}\'.")
  println("** This will **not** result in a pipeline run.")
  currentBuild.result = lastBuildResult()
} else {
  if (rancher_version.startsWith("v2.2") || rancher_version.startsWith("v2.3") || rancher_version == "master-head") {
    branch = "master"
  }
  if (env.BRANCH) {
    branch = "${BRANCH}"
  }
  try {
    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 setupContainer = "${job_name}${env.BUILD_NUMBER}_setup"
      def setupContainer2 = "${job_name}${env.BUILD_NUMBER}_setup2"
      def deleteContainer = "${job_name}${env.BUILD_NUMBER}_delete"
      def deleteContainer2 = "${job_name}${env.BUILD_NUMBER}_delete2"

      def deployPytestOptions = "-k test_deploy_rancher_server"

      def deletePytestOptions = "-k test_delete_rancher_server"

      def setupResultsOut = "setup-results.xml"
      def setupResultsOut2 = "setup-results-2.xml"
      def deleteResultsOut = "delete-results.xml"
      def deleteResultsOut2 = "delete-results-2.xml"

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

      def envFile = ".env"
      def rancherConfig = "rancher_env.config"

      def CATTLE_TEST_URL_2 = ""
      def ADMIN_TOKEN_2 = ""
      def USER_TOKEN_2 = ""

      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_SSH_PEM_KEY', variable: 'AWS_SSH_PEM_KEY'),
                            string(credentialsId: 'ADMIN_PASSWORD', variable: 'ADMIN_PASSWORD'),
                            string(credentialsId: 'USER_PASSWORD', variable: 'USER_PASSWORD')]) {

            println "Branch: ${branch}"
            stage('Checkout') {
                deleteDir()
                checkout([
                          $class: 'GitSCM',
                          branches: [[name: "*/${branch}"]],
                          extensions: scm.extensions + [[$class: 'CleanCheckout']],
                          userRemoteConfigs: scm.userRemoteConfigs
                        ])
            }

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

              try {
                stage('Deploy Rancher server 1') {
                  try {
                    // deploy rancher server
                    sh "docker run --name ${setupContainer} -t --env-file ${envFile} " +
                      "${imageName} /bin/bash -c \'export RANCHER_SERVER_VERSION=${rancher_version} && " +
                      "pytest -v -s --junit-xml=${setupResultsOut} " +
                      "${deployPytestOptions} ${testsDir}\'"

                    // copy file containing CATTLE_TEST_URL, ADMIN_TOKEN, USER_TOKEN and load into environment variables
                    sh "docker cp ${setupContainer}:${rootPath}${testsDir}${rancherConfig} ."
                    load rancherConfig

                    CATTLE_TEST_URL_2 = "${CATTLE_TEST_URL}"
                    ADMIN_TOKEN_2 = "${ADMIN_TOKEN}"
                    USER_TOKEN_2 = "${USER_TOKEN}"
                  } catch(err) {
                    echo "Error: " + err
                    echo 'Test run had failures. Collecting results...'
                    currentBuild.result = 'FAILURE'
                  }
                }

                stage('Deploy Rancher server 2') {
                  try {
                    // deploy rancher server
                    sh "docker run --name ${setupContainer2} -t --env-file ${envFile} " +
                      "${imageName} /bin/bash -c \'export RANCHER_SERVER_VERSION=${rancher_version} && " +
                      "pytest -v -s --junit-xml=${setupResultsOut2} " +
                      "${deployPytestOptions} ${testsDir}\'"

                    // copy file containing CATTLE_TEST_URL & ADMIN_TOKEN and load into environment variables
                    sh "docker cp ${setupContainer2}:${rootPath}${testsDir}${rancherConfig} ."
                    load rancherConfig
                  } catch(err) {
                    echo "Error: " + err
                    echo 'Test run had failures. Collecting results...'
                    currentBuild.result = 'FAILURE'
                  }
                }

                stage('Execute subjobs') {
                  try {
                      jobs = [:]
                      println "Branch: ${branch}"
                      params = [ string(name: 'CATTLE_TEST_URL', value: "${CATTLE_TEST_URL}"),
                                string(name: 'ADMIN_TOKEN', value: "${ADMIN_TOKEN}"),
                                string(name: 'USER_TOKEN', value: "${USER_TOKEN}"),
                                string(name: 'RANCHER_SERVER_VERSION', value: "${rancher_version}"), 
                                string(name: 'BRANCH', value: branch) ]

                      params2 = [ string(name: 'CATTLE_TEST_URL', value: "${CATTLE_TEST_URL_2}"),
                                  string(name: 'ADMIN_TOKEN', value: "${ADMIN_TOKEN_2}"),
                                  string(name: 'USER_TOKEN', value: "${USER_TOKEN_2}"),
                                  string(name: 'RANCHER_SERVER_VERSION', value: "${rancher_version}"),
                                  string(name: 'BRANCH', value: branch) ]

                      // Rancher server 1 is used to test RKE clusters
                      jobs["do"] = { build job: 'rancher-v3_ontag_do_certification', parameters: params }
                      jobs["ec2"] = { build job: 'rancher-v3_ontag_ec2_certification', parameters: params }
                      jobs["az"] = { build job: 'rancher-v3_ontag_az_certification', parameters: params }
                      jobs["custom"] = { build job: 'rancher-v3_ontag_custom_certification', parameters: params}
                      jobs["windows"] = { build job: 'rancher-v3_ontag_windows_certification', parameters: params}

                      // Rancher server 2 is used to test GKE, EKS, AKS and Imported clusters
                      jobs["gke"] = { build job: 'rancher-v3_ontag_gke_certification', parameters: params2 }
                      jobs["eks"] = { build job: 'rancher-v3_ontag_eks_certification', parameters: params2 }
                      jobs["aks"] = { build job: 'rancher-v3_ontag_aks_certification', parameters: params2 }
                      jobs["import"] = { build job: 'rancher-v3_ontag_import_certification', parameters: params2}
                      jobs["importk3s"] = { build job: 'rancher-v3_ontag_import_k3s_certification', parameters: params2}

                      parallel jobs
                    } catch(err) {
                      echo "Error: " + err
                    }
                }

                stage('Delete Rancher Server') {
                  if (env.RANCHER_DELETE_SERVER.toLowerCase() == "true") {
                    try {
                      sh "docker run --name ${deleteContainer} -t --env-file ${envFile} " +
                      "${imageName} /bin/bash -c \'export CATTLE_TEST_URL=${env.CATTLE_TEST_URL} && " +
                      "export ADMIN_TOKEN=${env.ADMIN_TOKEN} && export USER_TOKEN=${env.USER_TOKEN} &&"+
                      "pytest -v -s --junit-xml=${deleteResultsOut} " +
                      "${deletePytestOptions} ${testsDir}\'"
                    } catch(err) {
                      echo "Error: " + err
                    }

                    try {
                      sh "docker run --name ${deleteContainer2} -t --env-file ${envFile} " +
                      "${imageName} /bin/bash -c \'export CATTLE_TEST_URL=${CATTLE_TEST_URL_2} && " +
                      "export ADMIN_TOKEN=${ADMIN_TOKEN_2} && export USER_TOKEN=${USER_TOKEN_2} &&" +
                      "pytest -v -s --junit-xml=${deleteResultsOut2} " +
                      "${deletePytestOptions} ${testsDir}\'"
                    } catch(err) {
                      echo "Error: " + err
                    }
                  }
                }

                stage('Test Report') {
                  // copy and archive test results
                  sh "docker cp ${setupContainer}:${rootPath}${setupResultsOut} ."
                  sh "docker cp ${setupContainer2}:${rootPath}${setupResultsOut2} ."
                  sh "docker cp ${deleteContainer}:${rootPath}${deleteResultsOut} ."
                  sh "docker cp ${deleteContainer2}:${rootPath}${deleteResultsOut2} ."
                  step([$class: 'JUnitResultArchiver', testResults: "**/${setupResultsOut}"])
                  step([$class: 'JUnitResultArchiver', testResults: "**/${setupResultsOut2}"])
                  step([$class: 'JUnitResultArchiver', testResults: "**/${deleteResultsOut}"])
                  step([$class: 'JUnitResultArchiver', testResults: "**/${deleteResultsOut2}"])
                  sh "docker stop ${setupContainer}"
                  sh "docker rm -v ${setupContainer}"
                  sh "docker stop ${setupContainer2}"
                  sh "docker rm -v ${setupContainer2}"
                  sh "docker stop ${deleteContainer}"
                  sh "docker rm -v ${deleteContainer}"
                  sh "docker stop ${deleteContainer2}"
                  sh "docker rm -v ${deleteContainer2}"
                  sh "docker rmi ${imageName}"
                }
              } catch(err){
                sh "docker stop ${setupContainer}"
                sh "docker rm -v ${setupContainer}"
                sh "docker stop ${setupContainer2}"
                sh "docker rm -v ${setupContainer2}"
                sh "docker stop ${deleteContainer}"
                sh "docker rm -v ${deleteContainer}"
                sh "docker stop ${deleteContainer2}"
                sh "docker rm -v ${deleteContainer2}"
                sh "docker rmi ${imageName}"
              }
            }
          }
        }
      }
    }
  } catch(err) {
    echo "Error: " + err
  }
}
