#!groovy

import groovy.transform.Field

@Field
def pulumiPod = '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: main
    image: pulumi/pulumi:v2.16.2
    command:
    - cat
    tty: true
    resources:
      requests:
        memory: "2000Mi"
        cpu: 1000m
      limits:
        memory: "4000Mi"
        cpu: 1000m
    env:
    - name: DOCKER_HOST
      value: tcp://localhost:2375
    - name: AWS_WEB_IDENTITY_TOKEN_FILE
      value: /identity/token
    volumeMounts:
    - mountPath: /identity
      name: identity
  - name: dind
    image: docker:18.09-dind
    securityContext:
      privileged: true
  - 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 any

    options {
        disableConcurrentBuilds()
    }
    environment {
        PULUMI_ACCESS_TOKEN = credentials("dbaas-pulumi-access-token")
        GOPATH = "/home/jenkins/agent/workspace/go"
        AWS_REGION = "us-west-2"
        GITHUB_BOT = credentials("github-sre-bot")
    }
    stages {
        stage('Delivery') {
            matrix {
                axes {
                    axis {
                        name 'STAGE'
                        values 'dev', 'staging', 'prod'
                    }
                }
                environment {
                    ENV = "${STAGE}"
                    KUBECONFIG = credentials("dbaas-${STAGE}-kubeconfig")
                    AWS_ROLE_ARN = credentials("dbaas-${STAGE}-aws-role")
                    PULUMI_CONFIG_PASSPHRASE = credentials("dbaas-${STAGE}-pulumi-pwd")
                    GIT_COMMIT_MSG = sh(returnStdout: true, script: "git log --oneline -n 1 --pretty=%B HEAD | head -n 1").trim()
                    ACTIVITY_HUB_SOURCE_KEY = credentials("activity-hub-${STAGE}-source-key")
                    CLINIC_TOKEN = credentials("clinic-${STAGE}-api-token")
                }
                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' }
                        }
                    }
                }
                agent {
                    kubernetes {
                        yaml pulumiPod
                        defaultContainer "main"
                        customWorkspace "/home/jenkins/agent/workspace/go/src/github.com/tidbcloud/config-service"
                    }
                }
                stages {
                    stage('Preview') {
                        when {
                            beforeAgent true
                            allOf {
                                changeRequest()
                            }
                        }
                        steps {
                            runPulumi("preview --diff", "config-service-${env.ENV}", "${ACTIVITY_HUB_SOURCE_KEY}", "${CLINIC_TOKEN}")
                        }
                    }
                    stage('Deploy Config Service') {
                        when {
                            beforeAgent true
                            allOf {
                                not { changeRequest() }
                            }
                        }
                        stages {
                            stage('Pulumi Up') {
                                steps {
                                    runPulumi("up --yes", "config-service-${env.ENV}", "${ACTIVITY_HUB_SOURCE_KEY}", "${CLINIC_TOKEN}")
                                }
                                post {
                                    unsuccessful {
                                        script {
                                            sendNotification("#gitops-ci", 'FAILURE')
                                        }
                                    }
                                    success {
                                        script {
                                            sendNotification("#gitops-ci", 'SUCCESS')
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

def runPulumi(SUB_COMMAND, STACK, SOURCE_KEY, CLINIC_TOKEN) {
    // unset KUBECONFIG to avoid creating resources without provider specified
    // unset HODSON_URL so that pulumi can detect the CI environment correctly
    sh """
    unset KUBECONFIG
    unset HUDSON_URL
    npm install
    npm run check
    npm run lint
    pulumi login https://api.pulumi.com
    pulumi stack select --create --secrets-provider=passphrase ${STACK}
    pulumi config set config-service:activity-hub-source-key ${SOURCE_KEY}
    pulumi config set config-service:clinic-api-token ${CLINIC_TOKEN} --plaintext
    pulumi ${SUB_COMMAND}
    """
}

def sendNotification(CHANNEL="#dbaas-infra-cd", STATUS="SUCCESS") {
    def GIT_AUTHOR_NAME = sh(returnStdout: true, script: "git log -1 --pretty=format:'%an'").trim()
    def slackmsg = "[<${env.RUN_DISPLAY_URL}|Pulumi up ${env.STAGE_NAME} to ${env.ENV}>] `${STATUS}`" + "\n" +
            "Commit: <https://github.com/tidbcloud/config-service/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}"
}
