#!groovy

def getSlackChannel(targetHost) {
    def channelMap = [
        "qa-ows-pdp.theorchard.io": "#permissions-platform-alerts",
        "qa-ows-account.theorchard.io": "#accounts-team-alerts",
        "qa-ows-users.theorchard.io": "#accounts-team-alerts",
        "qa-graphql-account.theorchard.io": "#accounts-team-alerts",
        "qa-ows-vectororder.theorchard.io": "#distro-build-alerts",
        // Add more host-channel mappings here
    ]

    return channelMap[targetHost]
}

def getServiceName(targetHost) {
    def serviceNameMap = [
        "qa-ows-pdp.theorchard.io": "ows-pdp",
        "qa-ows-account.theorchard.io": "ows-account",
        "qa-ows-users.theorchard.io": "ows-users",
        "qa-graphql-account.theorchard.io": "graphql-account",
        "qa-ows-vectororder.theorchard.io": "ows-vectororder",
        // Add more host-service-name mappings here
    ]

    return serviceNameMap[targetHost]
}

def getLoadHost(targetHost) {
    def loadHostMap = [
        "qa-ows-pdp.theorchard.io": "qa-ows-pdp.theorchard.io",
        "qa-ows-account.theorchard.io": "qa-ows-account.theorchard.io",
        "qa-ows-users.theorchard.io": "qa-ows-users.theorchard.io",
        "qa-graphql-account.theorchard.io": "qa-graphql-router.theorchard.io",
        "qa-ows-vectororder.theorchard.io": "qa-ows-vectororder.theorchard.io",
        // Add more load host mappings here
    ]

    return loadHostMap[targetHost]
}

def getSampleFileName(targetHost, yesterdayDate) {
    // for files are not generated automatically
    def fileNameMap = [
        "qa-ows-pdp.theorchard.io": "sample-requests/pdp.csv",
        "qa-graphql-account.theorchard.io": "sample-requests/qraphql-account.csv",
        "qa-ows-vectororder.theorchard.io": "sample-requests/ows-vectororder.csv",
    ]

    sampleFileName = fileNameMap.get(targetHost)
    if (!sampleFileName) {
        sampleFileName = "samples/${targetHost}_${yesterdayDate}.csv"
    }

    return sampleFileName
}

String ECR_ACCOUNT_ID = '483193324480'
String SLACK_NOTIFICATIONS_CHANNEL = getSlackChannel(params.TARGET_HOST)
String PROD_ACCOUNT_ID = '437795906767'
String ROLE_NAME = 'qa-core-load-tester-role'

pipeline {
    agent {
        label 'aws'
    }

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

    parameters {
        string(defaultValue: "qa-ows-pdp.theorchard.io",
                name: "TARGET_HOST",
                trim: true)
        string(defaultValue: "10",
                name: "NUM_USERS",
                trim: true)
        string(defaultValue: "2",
                name: "SPAWN_RATE",
                trim: true)
        string(defaultValue: "300s",
                name: "RUN_TIME",
                trim: true)
        string(name: "SHARED_LIBRARIES_VERSION",
                defaultValue: "master",
                description: "The version of the Jenkins shared libraries to use. Can be a branch, tag or Git revision.")
    }

    stages {
        stage('Load Shared Libraries') {
            steps {
                library "jenkins-global-libraries@${params.SHARED_LIBRARIES_VERSION}"
            }
        }
        stage('Build') {
            options {
                retry(2)
            }
            steps {
                script { currentBuild.description = "Host: ${params.TARGET_HOST}" }
                sh label: 'docker login', script: "aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin https://${ECR_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com"
                sh label: 'docker build', script: "docker build -t ${ECR_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com/core-load-tester:latest ."
            }
        }
        stage('Execute') {
            environment {
                TARGET_ENVIRONMENT = "${params.TARGET_HOST}"
                AUTH0_AUDIENCE     = 'https://workstation.qaorch.com/api'
                AUTH0_HOST         = 'qa-orchard.auth0.com'
                AUTH0_USERNAME     = 'pdptest@theorchard.com'
                AUTH0_GRANT_TYPE   = 'password'
                DD_DASHBOARD_LINK  = 'https://app.datadoghq.com/dashboard/mbc-gui-2yx'
                YESTERDAY_DATE     = sh(script: 'date --date="yesterday" +"%Y-%m-%d"', returnStdout: true).trim()
                SAMPLE_FILE        = getSampleFileName(params.TARGET_HOST, env.YESTERDAY_DATE)
                DD_SERVICE_NAME    = getServiceName(params.TARGET_HOST)
            }
            steps {
                withSecrets(awsAccountId: PROD_ACCOUNT_ID, awsRole: ROLE_NAME, secrets: [
                        [id: 'qa/core-load-tester/AUTH0_CLIENT_ID', environmentVariable: 'AUTH0_CLIENT_ID'],
                        [id: 'qa/core-load-tester/AUTH0_CLIENT_SECRET', environmentVariable: 'AUTH0_CLIENT_SECRET'],
                        [id: 'qa/core-load-tester/AUTH0_TEST_USERS_CREDENTIALS', environmentVariable: 'AUTH0_TEST_USERS_CREDENTIALS'],
                        [id: 'qa/core-load-tester/DD_API_KEY', environmentVariable: 'DD_API_KEY'],
                        [id: 'qa/core-load-tester/DD_APP_KEY', environmentVariable: 'DD_APP_KEY'],
                        [id: 'qa/core-load-tester/SENTRY_DSN', environmentVariable: 'SENTRY_DSN'],
                ]) {
                    script {
                        docker.image("${ECR_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com/core-load-tester:latest").inside('--ulimit nofile=90000:90000') {
                            // core-load-tester-pdp-sample
                            sh label: 'prepare samples directory', script: 'mkdir -p samples/'
                            withCredentials([
                                    string(credentialsId: 'core-load-tester-auth0-password', variable: 'AUTH0_PASSWORD'),
                            ]) {
                                // validate datadog api key
                                sh label: 'validate DD key', script: '''
                                  curl -X GET "https://api.datadoghq.com/api/v1/validate" \
                                    -H "Accept: application/json" \
                                    -H "DD-API-KEY: $DD_API_KEY"
                                '''
                                // if the file doesn't exist create it
                                if (!fileExists(env.SAMPLE_FILE)) {
                                    def query_cmd = []
                                        query_cmd << 'python3'
                                        query_cmd << 'selectors/datadog/selector.py'
                                        query_cmd << "-o ${env.SAMPLE_FILE}"
                                        query_cmd << "-d ${env.YESTERDAY_DATE}"
                                    if (params.EXTRA_ARGS != '') {
                                        query_cmd << "${params.EXTRA_ARGS}"
                                    }
                                    sh label: 'get samples from Athena', script: query_cmd.join(' ')
                                    sh label: 'check files', script: 'ls -ashil samples/'
                                    sh label: 'check content', script: "cat ${env.SAMPLE_FILE}"
                                }

                                sh label: 'run performance tests', script: """
                                  locust \
                                    --locustfile locust/locustfile.py \
                                    --headless \
                                    -u ${params.NUM_USERS} \
                                    -r ${params.SPAWN_RATE} \
                                    -t ${params.RUN_TIME} \
                                    --csv report \
                                    --csv-full-history \
                                    --html report.html \
                                    --exit-code-on-error 0 \
                                    --host 'https://${getLoadHost(env.TARGET_ENVIRONMENT)}'
                                """
                            }
                        }
                    }
                }
            }
            post {
                always {
                    archiveArtifacts artifacts: 'report.html', followSymlinks: false
                    script {
                        def csvFile = "${env.WORKSPACE}/report_stats.csv"
                        def csvContent = readCSV(file: csvFile)

                        if (csvContent != null && csvContent.size() > 0) {
                            def lastRecord = csvContent.last()
                            def messageRequestCount = lastRecord[2]
                            def messageFailureCount = lastRecord[3]
                            def messageAvgResponseTime = lastRecord[4]

                            def slackMessage = """*Aggregated results for ${env.TARGET_HOST}:*\n\n*Request Count:* ${messageRequestCount} \n*Failure Count:* ${messageFailureCount} \n*Average Response Time:* ${messageAvgResponseTime}"""

                            slackNotify channel: SLACK_NOTIFICATIONS_CHANNEL, message: slackMessage
                        }
                    }
                }
            }
        }
    }
    post {
        always {
            slackNotify channel: SLACK_NOTIFICATIONS_CHANNEL
        }
    }
}
