@Library('infraLib') _

def common_env_projects = [
  "Devops/Terraform/apollo/common-dev",
  "Devops/Terraform/apollo_new/common-dev",
  "Devops/Terraform/core/common-dev",
  "Devops/Terraform/datascience/common-dev",
  "Devops/Terraform/delphi/common-dev",
  "Devops/Terraform/delphi/common-prod",
  "Devops/Terraform/ecommerce/common-dev",
  "Devops/Terraform/mct/common-dev",
  "Devops/Terraform/smu/common-dev",
  "Devops/Terraform/whitelist/common-dev",
]
def dev_env_projects = [
  "Devops/Terraform/apollo/dev-deploy",
  "Devops/Terraform/apollo/dev-main",
  "Devops/Terraform/apollo_new/dev-deploy",
  "Devops/Terraform/apollo_new/dev-main",
  "Devops/Terraform/artistapp/dev-deploy",
  "Devops/Terraform/artistapp/dev-main",
  "Devops/Terraform/core/dev-deploy",
  "Devops/Terraform/core/dev-images-api",
  "Devops/Terraform/core/dev-main",
  "Devops/Terraform/databricks/dev-main",
  "Devops/Terraform/datascience/dev-deploy",
  "Devops/Terraform/datascience/dev-main",
  "Devops/Terraform/delphi/dev-api",
  "Devops/Terraform/delphi/dev-deploy",
  "Devops/Terraform/delphi/dev-main",
  "Devops/Terraform/ecommerce/dev-deploy",
  "Devops/Terraform/ecommerce/dev-main",
  "Devops/Terraform/infra/dev",
  "Devops/Terraform/infrastructure/dev",
  "Devops/Terraform/mct/dev-deploy",
  "Devops/Terraform/mct/dev-main",
  "Devops/Terraform/smu/dev-deploy",
  "Devops/Terraform/smu/dev-main",
  "Devops/Terraform/whitelist/dev-deploy",
  "Devops/Terraform/whitelist/dev-main",
  "Devops/Terraform/security/dev-apollo",
  "Devops/Terraform/security/dev-artistapp",
  "Devops/Terraform/security/dev-core",
  "Devops/Terraform/security/dev-databricks",
  "Devops/Terraform/security/dev-datascience",
  "Devops/Terraform/security/dev-delphi",
  "Devops/Terraform/security/dev-infra",
  "Devops/Terraform/security/dev-mct",
  "Devops/Terraform/security/dev-prodhub",
  "Devops/Terraform/security/dev-smu",
  "Devops/Terraform/security/dev-whitelist",
  "Devops/Terraform/bootstrap/dev-apollo",
  "Devops/Terraform/bootstrap/dev-artistapp",
  "Devops/Terraform/bootstrap/dev-core",
  "Devops/Terraform/bootstrap/dev-databricks",
  "Devops/Terraform/bootstrap/dev-datascience",
  "Devops/Terraform/bootstrap/dev-delphi",
  "Devops/Terraform/bootstrap/dev-infra",
  "Devops/Terraform/bootstrap/dev-mct",
  "Devops/Terraform/bootstrap/dev-prodhub",
  "Devops/Terraform/bootstrap/dev-smu",
  "Devops/Terraform/bootstrap/dev-whitelist",
]
def qa_env_projects = [
  "Devops/Terraform/apollo_new/qa-deploy",
  "Devops/Terraform/apollo_new/qa-main",
  //"Devops/Terraform/artistapp/qa-deploy",
  //"Devops/Terraform/artistapp/qa-main",
  "Devops/Terraform/core/qa-deploy",
  "Devops/Terraform/core/qa-images-api",
  "Devops/Terraform/core/qa-main",
  "Devops/Terraform/delphi/qa-api",
  "Devops/Terraform/delphi/qa-deploy",
  "Devops/Terraform/delphi/qa-main",
  "Devops/Terraform/mct/qa-deploy",
  "Devops/Terraform/mct/qa-main",
  "Devops/Terraform/prodhub/qa-deploy",
  "Devops/Terraform/prodhub/qa-main",
  "Devops/Terraform/whitelist/qa-deploy",
  "Devops/Terraform/whitelist/qa-main",
]
def stage_env_projects = [
  "Devops/Terraform/apollo_new/stage-deploy",
  "Devops/Terraform/apollo_new/stage-main",
  "Devops/Terraform/artistapp/stage-deploy",
  "Devops/Terraform/artistapp/stage-main",
  "Devops/Terraform/delphi/stage-api-mobile",
  "Devops/Terraform/delphi/stage-api",
  "Devops/Terraform/delphi/stage-deploy",
  "Devops/Terraform/delphi/stage-main",
  "Devops/Terraform/mct/stage-deploy",
  "Devops/Terraform/mct/stage-main",
]
def uat_env_projects = [
  "Devops/Terraform/apollo_new/uat-deploy",
  "Devops/Terraform/apollo_new/uat-main",
  "Devops/Terraform/core/uat-deploy",
  "Devops/Terraform/core/uat-images-api",
  "Devops/Terraform/core/uat-main",
  "Devops/Terraform/whitelist/uat-deploy",
  "Devops/Terraform/whitelist/uat-main",
]
def prod_env_projects = [
  "Devops/Terraform/apollo/prod-deploy",
  "Devops/Terraform/apollo/prod-main",
  "Devops/Terraform/apollo/prod-eu-west-main",
  "Devops/Terraform/apollo_new/prod-deploy",
  "Devops/Terraform/apollo_new/prod-main",
  "Devops/Terraform/artistapp/prod-deploy",
  "Devops/Terraform/artistapp/prod-main",
  "Devops/Terraform/core/prod-deploy",
  "Devops/Terraform/core/prod-images-api",
  "Devops/Terraform/core/prod-main",
  "Devops/Terraform/databricks/prod-main",
  "Devops/Terraform/delphi/prod-api",
  "Devops/Terraform/delphi/prod-deploy",
  "Devops/Terraform/delphi/prod-main",
  "Devops/Terraform/ecommerce/prod-deploy",
  "Devops/Terraform/ecommerce/prod-main",
  "Devops/Terraform/infra/prod",
  "Devops/Terraform/infrastructure/prod",
  "Devops/Terraform/mct/prod-deploy",
  "Devops/Terraform/mct/prod-main",
  "Devops/Terraform/prodhub/prod-deploy",
  "Devops/Terraform/prodhub/prod-main",
  "Devops/Terraform/smu/prod-deploy",
  "Devops/Terraform/smu/prod-main",
  "Devops/Terraform/whitelist/prod-deploy",
  "Devops/Terraform/whitelist/prod-main",
  "Devops/Terraform/whitelist/legacy-main",
  "Devops/Terraform/security/prod-apollo",
  "Devops/Terraform/security/prod-artistapp",
  "Devops/Terraform/security/prod-core",
  "Devops/Terraform/security/prod-databricks",
  "Devops/Terraform/security/prod-delphi",
  "Devops/Terraform/security/prod-infra",
  "Devops/Terraform/security/prod-mct",
  "Devops/Terraform/security/prod-smu",
  "Devops/Terraform/security/prod-whitelist",
  "Devops/Terraform/security/prod-whitelist-legacy",
  "Devops/Terraform/bootstrap/prod-apollo",
  "Devops/Terraform/bootstrap/prod-artistapp",
  "Devops/Terraform/bootstrap/prod-core",
  "Devops/Terraform/bootstrap/prod-databricks",
  "Devops/Terraform/bootstrap/prod-delphi",
  "Devops/Terraform/bootstrap/prod-infra",
  "Devops/Terraform/bootstrap/prod-mct",
  "Devops/Terraform/bootstrap/prod-smu",
  "Devops/Terraform/bootstrap/prod-whitelist",
  "Devops/Terraform/bootstrap/prod-whitelist-legacy",
]
def globalBuildStages = [
  common_env_projects,
  dev_env_projects,
  qa_env_projects,
  stage_env_projects,
  uat_env_projects,
  prod_env_projects,
]

def buildJobsFullList = []
globalBuildStages.each { buildJobsFullList += it}
buildJobsFullList = buildJobsFullList.sort()

def checkBoxParamProjects = utility.checkBox(
  "PROJECTS", // name
  buildJobsFullList.join(','), // values
  "", //default value
)

def buildJobList = []
def branchId = env.JOB_NAME.split('/')[-1]

properties(
  [parameters([
    choice(
      choices: [
        'Build latest changes',
        'Select manually',
        'Build all'
      ],
      description: 'Choose what module to build',
      name: 'PROJECT_CHOICE'
    ),
    checkBoxParamProjects,
    choice(
      choices: [
        'default',
        'yes',
        'no',
      ],
      description: 'Whether to run prompt for apply and than apply itself. By default only enabled for master branch',
      name: 'TERRAFORM_APPLY'
    ),
    booleanParam(
      name: 'SKIP_APPROVAL',
      defaultValue: false,
      description: 'Skip approval step and do the changes right away. SUPER GIGA DANGEROUS'
    )
  ])]
)


pipeline {
  agent {
    label 'terraform-agent'
  }
  options { disableConcurrentBuilds() }
  environment {
    NOTIFICATIONS_CHANNEL = "terraform-cicd-alerts"
  }
  stages {
    stage('Github notify') {
      steps {githubNotify description: "Build manager has started",  status: 'PENDING', context: "Terraform/Global_build"}
    }
    //get parameters map
    stage('Define build elements') {
      steps {
        script {
          switch(params.PROJECT_CHOICE) {
            case 'Select manually':
              buildJobList = (params.PROJECTS != null ? params.PROJECTS.split(',') : []).collect{it}.toSet()
              break
            case 'Build all':
              buildJobList = buildJobsFullList
              break
            case 'Build latest changes':
              def changeset = terraform.getChangesLastOrPR()
              println "Changeset:\n${changeset}"
              tfProjectPaths = terraform.getChangedTfProjectPaths(changeset, "Terraform")
              println "Project paths:\n${tfProjectPaths}"
              buildJobList = tfProjectPaths.collect{ terraform.convertConfigPathToJobName(it) }
              break
            default:
              def changeset = terraform.getChangesLastOrPR()
              println "Changeset:\n${changeset}"
              tfProjectPaths = terraform.getChangedTfProjectPaths(changeset, "Terraform")
              println "Project paths:\n${tfProjectPaths}"
              buildJobList = tfProjectPaths.collect{ terraform.convertConfigPathToJobName(it) }
              break
          }
          println "Build job list:\n${buildJobList}"
        }
      }
    }
    stage("Plan mode") {
      steps {
        script {
          if (!terraform.checkBranchConditions(params.TERRAFORM_APPLY)) {
            terraform.runEnvironmentStages(
            "All", buildJobsFullList,
            buildJobList, params, branchId)
          }
        }
      }
    }
    stage("Apply mode") {
      when {
        expression { return terraform.checkBranchConditions(params.TERRAFORM_APPLY) }
      }
      stages {
        stage("Build Common") {
          steps {
            script {
              // Run Main states first
              terraform.runEnvironmentStages(
                "Common", common_env_projects.findAll {it.contains('main')},
                buildJobList, params, branchId)
              // Run all other states
              terraform.runEnvironmentStages(
                "Common", common_env_projects.findAll {!it.contains('main')},
                buildJobList, params, branchId)
            }
          }
        }
        stage("Build Development") {
          steps {
            script {
              // Run Main states first
              terraform.runEnvironmentStages(
                "Dev", dev_env_projects.findAll {it.contains('main')},
                buildJobList, params, branchId)
              // Run all other states
              terraform.runEnvironmentStages(
                "Dev", dev_env_projects.findAll {!it.contains('main')},
                buildJobList, params, branchId)
            }
          }
        }
        stage("Build QA") {
          steps {
            script {
              // Run Main states first
              terraform.runEnvironmentStages(
                "QA", qa_env_projects.findAll {it.contains('main')},
                buildJobList, params, branchId)
              // Run all other states
              terraform.runEnvironmentStages(
                "QA", qa_env_projects.findAll {!it.contains('main')},
                buildJobList, params, branchId)
            }
          }
        }
        stage("Build Staging") {
          steps {
            script {
              // Run Main states first
              terraform.runEnvironmentStages(
                "Staging", stage_env_projects.findAll {it.contains('main')},
                buildJobList, params, branchId)
              // Run all other states
              terraform.runEnvironmentStages(
                "Staging", stage_env_projects.findAll {!it.contains('main')},
                buildJobList, params, branchId)
            }
          }
        }
        stage("Build UAT") {
          steps {
            script {
              // Run Main states first
              terraform.runEnvironmentStages(
                "UAT", uat_env_projects.findAll {it.contains('main')},
                buildJobList, params, branchId)
              // Run all other states
              terraform.runEnvironmentStages(
                "UAT", uat_env_projects.findAll {!it.contains('main')},
                buildJobList, params, branchId)
            }
          }
        }
        stage("Build Production") {
          steps {
            script {
              // Run Main states first
              terraform.runEnvironmentStages(
                "Prod", prod_env_projects.findAll {it.contains('main')},
                buildJobList, params, branchId)
              // Run all other states
              terraform.runEnvironmentStages(
                "Prod", prod_env_projects.findAll {!it.contains('main')},
                buildJobList, params, branchId)
            }
          }
        }
      }
    }
  }
  post {
    always {
      sh "sudo chown -R ec2-user:ec2-user ${env.WORKSPACE}"
    }
    success {
      script {
        if (currentBuild.getPreviousBuild() &&
            currentBuild.getPreviousBuild().getResult().toString() != "SUCCESS") {
          utility.slackNotify(currentBuild.currentResult, env.NOTIFICATIONS_CHANNEL)
        }
        githubNotify description: "Build manager status - ${currentBuild.currentResult}",  status: 'SUCCESS', context: "Terraform/Global_build"
      }
    }
    failure {
      script {
        utility.slackNotify(currentBuild.currentResult, env.NOTIFICATIONS_CHANNEL)
        githubNotify description: "Build manager status - ${currentBuild.currentResult}",  status: 'FAILURE', context: "Terraform/Global_build"
      }
    }
    cleanup {
        deleteDir()
    }
  }
}
