#!groovy

import groovy.transform.Field

@Field
def agentPod = '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: main
    image: gcr.io/pingcap-public/overlay:0522cf2733c7d5
    command:
    - cat
    tty: true
    resources:
      requests:
        memory: "2000Mi"
        cpu: 1000m
      limits:
        memory: "2000Mi"
        cpu: 1000m
    env:
    - name: AWS_WEB_IDENTITY_TOKEN_FILE
      value: /identity/token
    volumeMounts:
    - mountPath: /identity
      name: identity
  - name: auth
    image: gcr.io/pingcap-gardener/jenkins/gcp-web-identity:20201201
    env:
    - name: AWS_WEB_IDENTITY_TOKEN_FILE
      value: /identity/token
    volumeMounts:
    - mountPath: /identity
      name: identity
  volumes:
  - emptyDir: {}
    name: identity
  restartPolicy: Never
'''

pipeline {
    agent{
        kubernetes {
            yaml agentPod
            defaultContainer "main"
            customWorkspace "/home/jenkins/agent/workspace/go/src/github.com/tidbcloud/tidb-configuration"
        }
    }

    options {
        disableConcurrentBuilds()
    }
    environment {
        GOPATH = "/home/jenkins/agent/workspace/go"
    }
    stages {
        stage('Check') {
            when {
                beforeAgent true
                changeRequest()
            }
            matrix {
                axes {
                    axis {
                        name 'STAGE'
                        values 'dev', 'staging', 'prod'
                    }
                }
                environment {
                    KUBECONFIG = credentials("dbaas-${STAGE}-kubeconfig")
                    AWS_ROLE_ARN = credentials("dbaas-${STAGE}-aws-role")
                    GIT_COMMIT_MSG = sh(returnStdout: true, script: "git log --oneline -n 1 --pretty=%B HEAD | head -n 1").trim()
                }
                when {
                    beforeAgent true
                    // BRANCH to ENV mapping
                    anyOf {
                        allOf {
                            anyOf {
                                environment name: 'GIT_BRANCH', value: 'master' // delivery
                                environment name: 'CHANGE_TARGET', value: 'master' // preview
                            }
                            expression { env.STAGE == 'dev' }
                        }
                        allOf {
                            anyOf {
                                environment name: 'GIT_BRANCH', value: 'staging' // delivery
                                environment name: 'CHANGE_TARGET', value: 'staging' // preview
                            }
                            expression { env.STAGE == 'staging' }
                        }
                        allOf {
                            anyOf {
                                environment name: 'GIT_BRANCH', value: 'prod' // delivery
                                environment name: 'CHANGE_TARGET', value: 'prod' // preview
                            }
                            expression { env.STAGE == 'prod' }
                        }
                    }
                }
                stages {
                    stage('Diff') {
                        steps {
                            script {
                                def url = ""
                                if (env.STAGE == 'dev') {
                                    url = "http://clinic-dev-1923272735.us-west-2.elb.amazonaws.com:8085/grafana/d/90I1Tiqnk/gitops-dryrun?orgId=1"
                                } else if(env.STAGE == 'staging'){
                                    url = "https://staging-clinic.pingcap.com/grafana/d/90I1Tiqnk/gitops-dryrun?orgId=1"
                                }else if (env.STAGE == 'prod'){
                                    url = "https://clinic.pingcap.com/grafana/d/90I1Tiqnk/gitops-dryrun?orgId=1"
                                }
                                def result = sh(script: "./hack/diff.sh '${url}'", returnStdout: true)
                                for (comment in pullRequest.comments) {
                                    if (comment.user == "tidbcloud-bot") {
                                        pullRequest.deleteComment(comment.id)
                                    }
                                }
                                len = result.length()
                                if (len > 65536) {
                                    println("result.length(): ${len}")
                                    println("result: ${result}")
                                    pullRequest.comment("PR comment fail on length too long, please check the diff in jenkins console output")
                                } else {
                                    pullRequest.comment(result)
                                }
                            }
                        }
                    }
                }
            }
        }
        stage('Delivery') {
            when {
                beforeAgent true
                not { changeRequest() }
            }
            matrix {
                axes {
                    axis {
                        name 'STAGE'
                        values 'dev', 'staging', 'prod'
                    }
                }
                environment {
                    KUBECONFIG = credentials("dbaas-${STAGE}-kubeconfig")
                    AWS_ROLE_ARN = credentials("dbaas-${STAGE}-aws-role")
                    GIT_COMMIT_MSG = sh(returnStdout: true, script: "git log --oneline -n 1 --pretty=%B HEAD | head -n 1").trim().replace(" ","%20")
                    GIT_COMMIT_FILES = sh(returnStdout:true, script:"git --no-pager log --name-only --oneline -n 1 --pretty='' HEAD | tr -s '\n' ','").trim()
                    ACTIVITY_HUB_SOURCE_KEY = credentials("activity-hub-${STAGE}-source-key")
                }
                when {
                    beforeAgent true
                    // BRANCH to ENV mapping
                    anyOf {
                        allOf {
                            anyOf {
                                environment name: 'GIT_BRANCH', value: 'master' // delivery
                                environment name: 'CHANGE_TARGET', value: 'master' // preview
                            }
                            expression { env.STAGE == 'dev' }
                        }
                        allOf {
                            anyOf {
                                environment name: 'GIT_BRANCH', value: 'staging' // delivery
                                environment name: 'CHANGE_TARGET', value: 'staging' // preview
                            }
                            expression { env.STAGE == 'staging' }
                        }
                        allOf {
                            anyOf {
                                environment name: 'GIT_BRANCH', value: 'prod' // delivery
                                environment name: 'CHANGE_TARGET', value: 'prod' // preview
                            }
                            expression { env.STAGE == 'prod' }
                        }
                    }
                }
                stages {
                    stage('Apply') {
                        steps {
                            script {
                                if (env.STAGE == 'dev') {
                                    activity_hub = "https://b9u12esjuf.execute-api.us-west-2.amazonaws.com"
                                } else if(env.STAGE == 'staging'){
                                    activity_hub = "https://b9u12esjuf.execute-api.us-west-2.amazonaws.com"
                                } else if (env.STAGE == 'prod'){
                                    activity_hub = "https://e4hr1v4oqh.execute-api.us-west-2.amazonaws.com"
                                }
                                env.ACTIVITY_HUB = activity_hub
                            }

                            sh '''
                            ./overlay.sh --meta --git-pr-num ${CHANGE_ID} --git-pr-created-by ${CHANGE_AUTHOR} --git-commit ${GIT_COMMIT} --git-commit-msg ${GIT_COMMIT_MSG} --version $(date +%s) --activity --activity-hub ${ACTIVITY_HUB} --source-key ${ACTIVITY_HUB_SOURCE_KEY}  --git-commit-files ${GIT_COMMIT_FILES}
                            ./hack/apply.sh

                            # Apply ClusterConfig to infra-api
                            # Get infra-api kubeconfig
                            kubectl get secret -n gitops config-service-infra-kubeconfig --template={{.data.config}} | base64 -d > infra-api-kubeconfig
                            apiserverAddress=$(kubectl get dnsentry api-server -n infra -o=jsonpath='{.spec.dnsName}')
                            KUBECONFIG=infra-api-kubeconfig kubectl config set-cluster infra --server=https://${apiserverAddress}
                            # Generate ClusterConfig Custom Resources
                            ./overlay.sh --meta --git-pr-num ${CHANGE_ID} --git-pr-created-by ${CHANGE_AUTHOR} --git-commit ${GIT_COMMIT} --git-commit-msg ${GIT_COMMIT_MSG} --version $(date +%s) --overlay=false --output=output_origin  --activity --activity-hub ${ACTIVITY_HUB} --source-key ${ACTIVITY_HUB_SOURCE_KEY}  --git-commit-files ${GIT_COMMIT_FILES}
                            # Trying Create it for preview
                            DRY_RUN=false GVK=cloud.pingcap.com/v1/ClusterConfig KUBECONFIG=infra-api-kubeconfig OUTPUT=output_origin ./hack/apply.sh
                            '''
                        }
                        post {
                            unsuccessful {
                                script {
                                    sendNotification("#dbaas-gitops", 'FAILURE')
                                }
                            }
                            success {
                                script {
                                    sendNotification("#dbaas-gitops", 'SUCCESS')
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

def sendNotification(CHANNEL="#dbaas-gitops", STATUS="SUCCESS") {
    def GIT_AUTHOR_NAME = sh(returnStdout: true, script: "git log -1 --pretty=format:'%an'").trim()
    def slackmsg = "[<${env.RUN_DISPLAY_URL}|Update config in ${STAGE}>] `${STATUS}`" + "\n" +
            "Commit: <https://github.com/tidbcloud/tidb-configuration/commit/${env.GIT_COMMIT}|${env.GIT_COMMIT_MSG}>" + "\n" +
            "Branch: `${env.GIT_BRANCH}`, Authored by: `${GIT_AUTHOR_NAME}`"
    def COLOR = 'good'
    if (STATUS != "SUCCESS") {
        COLOR = 'danger'
    }
    slackSend channel: CHANNEL, color: COLOR, teamDomain: 'pingcap', tokenCredentialId: 'slack-pingcap-token', message: "${slackmsg}"
}
