@Library('infraLib') _

def get30FromBuildLog(){
    def logs = currentBuild.rawBuild.getLog(30).join('\n')
    return "${logs}"
}

def getRuntimeTag(){
    switch (env.BRANCH_NAME) {
        case 'master':
            return 'AP,AGO'
        case 'develop':
            return 'AP,AGO'
        case 'TAG_VENDOR_UAT':
            return 'VENDOR'
        case ~/TAG_(.*)/:
            BRANCH_SUBSTRINGS=env.BRANCH_NAME.split('_')
            return BRANCH_SUBSTRINGS[1..-1].join('_')
        default:
            return ''
    }
}

def getBztFileTemplate(){
    switch(env.BRANCH_NAME) {
        case 'TAG_VENDOR':
            return 'bztfile-high-workload.yml.tmpl'
        case 'TAG_AGO':
        case 'TAG_AP':
        case 'master':
            return 'bztfile.yml.tmpl'
        default:
            return 'bztfile-qa.yml.tmpl'
    }
}

def getBseURI(){
    switch (BRANCH_NAME) {
        case 'master':
            return 'https://stage-proxy.apollo.stream/'
        case 'TAG_AP':
            return 'https://stage-proxy.apollo.stream/'
        case 'TAG_AGO':
            return 'https://stage-proxy.apollo.stream/'
        case 'TAG_VENDOR':
            return 'https://qa-proxy.apollo.stream/'
        case 'TAG_VENDOR_UAT':
            return 'https://uat-proxy.filtr.com/'
        case 'TAG_IMAGES':
            return 'https://qa-images-api.atlas.stream/'
        default:
            return 'https://qa-proxy.apollo.stream/'
    }
}

String[] URI_METRICS = "throughput concurrency succ fail avg_rt stdev_rt avg_lt avg_ct bytes".split()

pipeline {
  agent {
    label 'linux-agents-xlarge'
  }

  environment {
    AWS_PROFILE    = 'gdb-infra-dev'
    AWS_ACCOUNT_ID = '483193324480'
    AWS_REGION     = 'us-east-1'

    ECR_REGISTRY        = "${env.AWS_ACCOUNT_ID}.dkr.ecr.${env.AWS_REGION}.amazonaws.com"
    ECR_REPOSITORY_NAME = "infra/locust-runner"
    ECR_REGISTRY_URI    = "${env.ECR_REGISTRY}/${ECR_REPOSITORY_NAME}"

    CLIENT_ID         = utility.getSecretValueById("infra/jenkins/apollo/dev/perormance/CLIENT_ID${BRANCH_NAME ==~/TAG_VENDOR_UAT$/ ? '_PROD' : ''}", 'gdb-delphi-dev')
    CLIENT_SECRET     = utility.getSecretValueById("infra/jenkins/apollo/dev/perormance/CLIENT_SECRET${BRANCH_NAME ==~/TAG_VENDOR_UAT$/ ? '_PROD' : ''}", 'gdb-delphi-dev')
    USERNAME          = utility.getSecretValueById("infra/jenkins/apollo/dev/perormance/USERNAME${BRANCH_NAME ==~/TAG_VENDOR_UAT$/ ? '_PROD' : ''}", 'gdb-delphi-dev')
    PASSWORD          = utility.getSecretValueById("infra/jenkins/apollo/dev/perormance/PASSWORD${BRANCH_NAME ==~/TAG_VENDOR_UAT$/ ? '_PROD' : ''}", 'gdb-delphi-dev')
    DD_CLIENT_API_KEY = utility.getSecretValueById("infra/jenkins/apollo/common/datadog/DEVELOPMENT_API_KEY", "gdb-delphi-dev")
    AUDIENCE          = "${BRANCH_NAME ==~/TAG_VENDOR_UAT$/ ? 'https://apollo-private-api/' : ''}"
    GRANT_TYPE        = "${BRANCH_NAME ==~/TAG_VENDOR_UAT$/ ? 'http://auth0.com/oauth/grant-type/password-realm' : '' }"
    REPORT_XML_FILE   = "aggregate-results.xml"
    BASE_URI          = "${getBseURI()}"
    TAG               = "${getRuntimeTag()}"
    REALM             = "${BRANCH_NAME ==~/TAG_VENDOR_UAT$/ ? 'MergedUsersDB' : 'LevelDB'}"
    AUTH0_HOST        = "${BRANCH_NAME ==~/TAG_VENDOR_UAT$/ ? 'prod-dna-apps.auth0.com' : 'sme-dna.auth0.com' }"
    DD_DASHBOARD_LINK = "https://app.datadoghq.com/dashboard/ibi-aam-q6f/apollo-performance-load-testing"
    BZT_FILE_TEMPLATE = "${getBztFileTemplate()}"

    NOTIFICATIONS_CHANNEL = '#apollo-load-testing'
  }

  options {
    timeout(time: 180, unit: 'MINUTES')
    buildDiscarder logRotator(
      artifactDaysToKeepStr: '',
      artifactNumToKeepStr: '',
      daysToKeepStr: '',
      numToKeepStr: '30'
    )
    disableResume()
    disableConcurrentBuilds()
    ansiColor('xterm')
  }

  stages {
    stage('Build') {
      steps {
        sh label: 'docker login', script: """
          aws ecr get-login --no-include-email --region us-east-1 \
          | awk '{print \$6}' \
          | docker login -u AWS --password-stdin https://${ECR_REGISTRY} \
          || aws ecr get-login-password --region us-east-1 \
          | docker login -u AWS --password-stdin https://${ECR_REGISTRY}
        """
        sh label: 'docker build', script: """
          docker build \
            --cache-from ${env.ECR_REGISTRY_URI}:apollo \
            -t ${env.ECR_REGISTRY_URI}:apollo .
        """
      }
    }
    stage('Push') {
      steps {
        sh label: 'docker login', script: """
          aws ecr get-login --no-include-email --region us-east-1 \
          | awk '{print \$6}' \
          | docker login -u AWS --password-stdin https://${ECR_REGISTRY} \
          || aws ecr get-login-password --region us-east-1 \
          | docker login -u AWS --password-stdin https://${ECR_REGISTRY}
        """
        sh label: 'docker build', script: """
          docker push ${env.ECR_REGISTRY_URI}:apollo
        """
      }
    }
    stage('Test') {
      steps {
        script {
          docker.image("${env.ECR_REGISTRY_URI}:apollo").inside("--ulimit nofile=90000:90000") {
            sh label: 'replace target URL', script: """
              envsubst < ${env.BZT_FILE_TEMPLATE} > bztfile.yml
              cat bztfile.yml
            """
            bzt '-report bztfile.yml'
          }
          if (fileExists(env.REPORT_XML_FILE) && (env.BRANCH_NAME == "master" || env.BRANCH_NAME == "develop" || env.BRANCH_NAME ==~ /TAG_.*$/)) {
            dd_timestamp = sh(returnStdout: true, script: "date +%s").trim()
            xml = readFile(env.REPORT_XML_FILE)
            labels = utility.getBztReportGroupLabels(xml)
            for (label in labels) {
              for (metric_name in URI_METRICS){
                metric_val=utility.getBztReportGroupMetricValue(xml,label,metric_name)
                ddResponse=utility.dataDogMetricPut(
                  "apollo_load_test.all_test.${metric_name}",
                  "${metric_val}",
                  "${dd_timestamp}",
                  "${env.DD_CLIENT_API_KEY}",
                  "${label.replace('-', '_').replace(' ', '_')}",
                  "[ \"environment:Jenkins\", \"branch:${env.BRANCH_NAME}\", \"metric_name:${metric_name}\", \"label:${label.replace('-', '_').replace(' ', '_')}\", \"BASE_URI:${env.BASE_URI}\" ]"
                )
                println 'LABEL: '+label.replace('-', '_').replace(' ', '_') +' metric: ' + metric_name + ' val: '+ metric_val +' DD:'+ddResponse
              }
            }
          }
        }
      }
    }
  }
  post {
    success {
      script {
        external_report_link = utility.getBztReportURL(readFile(env.REPORT_XML_FILE))
        utility.slackNotifyMainBranches(
          "SUCCESS",
          env.NOTIFICATIONS_CHANNEL,
          "Performance test done, please see results <${external_report_link}|Last Build Report> and <${env.BUILD_URL}/performance/|Last Build Performance Trend>, <${env.DD_DASHBOARD_LINK}|DataDog Dashboard>"
        )
      }
    }
    unstable {
      script {
        errorLog = get30FromBuildLog()
        external_report_link = utility.getBztReportURL(readFile(env.REPORT_XML_FILE))
        println "ReportLink:" +external_report_link
        slackResponse = utility.slackNotifyMainBranches(
          "UNSTABLE",
          env.NOTIFICATIONS_CHANNEL,
          "Performance test is unstable, please see results <${external_report_link}|Last Build Report> and  <${env.BUILD_URL}/performance/|Last Build Performance Trend>. Most likely pass/fail criteria triggered this build UNSTABLE"
        )
        if (!slackResponse.toString().isInteger()) {
          blocks = [
            [
              "type": "section",
              "text": [
                "type": "mrkdwn",
                "text": "```${errorLog}```"
              ]
            ]
          ]
          slackSend(channel: slackResponse.threadId,
                    iconEmoji: ":hammer_and_wrench:",
                    blocks: blocks)
        }
      }
    }
    aborted {
      script {
        external_report_link = utility.getBztReportURL(readFile(REPORT_XML_FILE))
        utility.slackNotifyMainBranches(
          "ABORTED",
          env.NOTIFICATIONS_CHANNEL,
          "Performance test ABORTED, <${env.BUILD_URL}|Please delete aborted build> to keep statistic clean"
        )
      }
    }
    failure {
      script {
        errorLog = get30FromBuildLog()
        slackResponse = utility.slackNotifyMainBranches(
          "FAILURE",
          env.NOTIFICATIONS_CHANNEL,
          "Performance test FAIL, <${env.BUILD_URL}|Please fix it> and delete failed build to keep statistic clean."
        )
        if (!slackResponse.toString().isInteger()) {
          blocks = [
            [
              "type": "section",
              "text": [
                "type": "mrkdwn",
                "text": "```${errorLog}```"
              ]
            ]
          ]
          slackSend(channel: slackResponse.threadId,
                    iconEmoji: ":hammer_and_wrench:",
                    blocks: blocks)
        }
      }
    }
  }
}
