TERRAFORM_VERSION = "0.11.9"

job_name_parts = env.JOB_NAME.split("/")
TEAM = job_name_parts[0]
APP_NAME = job_name_parts[1]

AWS_REGION = "us-west-2"

STAGING_ENV = "staging"
STAGING_BRANCH = "staging"
STAGING_ACCOUNT = "twitch-rbac-dev"

PRODUCTION_ENV = "production"
PRODUCTION_BRANCH = "master"
PRODUCTION_ACCOUNT = "twitch-rbac-prod"

pipeline {
  agent any
  options {
      disableConcurrentBuilds()
      timeout(time: 30, unit: 'MINUTES')
      ansiColor('xterm')
      timestamps()
  }
  environment {
    CODECOV_TOKEN = credentials('devrel-vienna-codecov')
  }

  stages {
    stage("Test") {
      steps {
        sh "env"
        sh "make build_development"
      }
    }
    stage("Deploy to staging") {
      when {
        branch STAGING_BRANCH
      }
      steps {
        script {
          sh "make build_staging"
          deployViaTerraform(STAGING_ACCOUNT, STAGING_ENV, AWS_REGION)
        }
      }
    }
    stage("Deploy to production") {
      when {
        branch PRODUCTION_BRANCH
      }
      steps {
        sh "make build_production"
        deployViaTerraform(PRODUCTION_ACCOUNT, PRODUCTION_ENV, AWS_REGION)
      }
    }
  }
}

def deployViaTerraform(awsCredentials, environment, region) {
  def accountID = getAccountID(awsCredentials, region)

  withEnv([
    "TF_VAR_vienna_image=${accountID}.dkr.ecr.us-west-2.amazonaws.com/vienna:${GIT_COMMIT}",
  ]) {
    echo "Pushing to ECR: ${env.TF_VAR_vienna_image}"
    withAWS(credentials: awsCredentials, region: region) {
      sh 'make push'
    }
    echo "Starting deploy by terraforming new taskdefs in ${environment}/${region}"
    terraform('git-aws-read-key', awsCredentials, environment, 'service/app', region)
  }
  docker.image('mikesir87/aws-cli').inside {
    withAWS(credentials: awsCredentials, region: region) {
      // Unconfigurable: polls 15s intervals 40 times = 600s total
      // TODO (rbacPLAT-358): this command is an opaque success/fail that we could improve on
      sh "aws ecs wait services-stable --cluster vienna-${environment} --services hubsights-vienna"
    }
  }
}

def getAccountID(awsCredentials, region) {
  docker.image('mikesir87/aws-cli').inside {
    withAWS(credentials: awsCredentials, region: region) {
      accountID = sh(script: 'aws sts get-caller-identity | jq -r ".Account"', returnStdout: true).trim()
      echo "Found account ID ${accountID} for credentials ${awsCredentials}"
      return accountID
    }
  }
}


// Starts an ssh-agent and load the keys from the given credential in Jenkins' credential store.
// We will volume mount a unix socket into the terraform docker container that lets git in the container
// communicate with the ssh-agent outside the container.
def terraform(sshCredentials, awsCredentials, environment, module, region) {
  sshagent (credentials: [sshCredentials]) {

    terraformPlan(awsCredentials, environment, module, region)
    def planPath = "terraform/${module}/${environment}.tf_plan"

    if (!fileExists(planPath)) {
      echo 'No terraform plan file found, nothing to apply'
      return
    }

    terraformLandscape(planPath)

    echo "Terraform apply on ${environment}"
    terraformApply(awsCredentials, environment, module, region)
  }
}

def terraformPlan(awsCredentials, environment, module, region) {
  docker.image("hashicorp/terraform:${TERRAFORM_VERSION}").inside("--entrypoint '' -v ${env.SSH_AUTH_SOCK}:${env.SSH_AUTH_SOCK} -e SSH_AUTH_SOCK -e AWS_PROFILE=${awsCredentials} -u root") {
    sh 'mkdir -p ~/.ssh/; ssh-keyscan -t rsa git-aws.internal.justin.tv >> ~/.ssh/known_hosts'
    withAWS(credentials: awsCredentials, region: region) {
      echo "terraform planning ${environment} ${module} in account: ${awsCredentials}"
      // TODO: use dir('terraform') when supported inside a docker container.
      // https://issues.jenkins-ci.org/browse/JENKINS-33510
      sh "TF_FOLDER=${module} terraform/plan.sh"
    }
  }
}

def terraformLandscape(planFile) {
  sh "docker run --rm -t -v ${WORKSPACE}/${planFile}:${WORKSPACE}/${planFile} hashicorp/terraform:${TERRAFORM_VERSION} show ${WORKSPACE}/${planFile} | docker run --rm -i airhelp/terraform-landscape"
}

def terraformApply(awsCredentials, environment, module, region) {
  docker.image("hashicorp/terraform:${TERRAFORM_VERSION}").inside("--entrypoint '' -v ${env.SSH_AUTH_SOCK}:${env.SSH_AUTH_SOCK} -e SSH_AUTH_SOCK -e AWS_PROFILE=${awsCredentials} -u root") {
    withAWS(credentials: awsCredentials, region: region) {
      sh """
        cd terraform/${module}
        terraform apply -input=false -auto-approve=true ${environment}.tf_plan
      """
    }
  }
}
