@Library('shared-lib') _ import tech.avroid.scm.Git import tech.avroid.terraform.Terraform import tech.avroid.kube.PodTemplates import groovy.text.SimpleTemplateEngine import tech.avroid.jenkins.Notifications Map statuses = [ 0: 'Ok', 1: 'Terraform plan error', 2: 'Infrastructure has been changed', 3: 'Terraform init problem', 4: 'Terraform init script problem', 5: 'Unknow error!' ] String repository = 'devops/terraform' String branch = 'master' String terraformInitScript = 'terraform_init.sh' String maintainer = 'devops@avroid.team' List excludeDirs = [ '__tf_template__.*', '__example__.*', '^dc-adlinux/', '^dc-cluster/', '^cloud-ext/', '^kvm-server/', '^pve-cluster/', '.*__tf_template__/$' ] Map tfStatuses = [:] Map stagesMap = [:] String mirrorsProvider = ''' provider_installation { network_mirror { url = "https://terraform-mirror.yandexcloud.net/" include = ["registry.terraform.io/*/*"] } direct { exclude = ["registry.terraform.io/*/*"] } } ''' Boolean skipStep(Integer statusCode){ Boolean skip = statusCode != 0 ? true : false return skip } List splitQueue(Object filesList, Integer step){ List result = [] Integer start = 0 for (i=0; i< filesList.size() / step ; i++){ if (step + start > filesList.size()){ result.add(filesList[start..filesList.size() -1]) return result } result.add(filesList[start..step+start -1]) start = start + step } return result } String generateReport(Map states){ SimpleTemplateEngine engine = new SimpleTemplateEngine() String report = ''' <% states.each { key, value -> %>\ ${value} <% } %>\
Terraform report
PathStatus
${key}
''' def result = engine.createTemplate(report).make([states: states]).toString() return result } timeout(time: 8, unit: 'HOURS') { properties([ disableConcurrentBuilds(), buildDiscarder(logRotator(numToKeepStr: '10')), pipelineTriggers([cron('H 2 * * *')]) ]) PodTemplates slaveTemplates = new PodTemplates(this, env.JENKINS_DOCKER_REGISTRY, [env.JENKINS_K8S_HARBOR_SECRET]) Terraform terraform = new Terraform(script: this) try { ansiColor('xterm'){ slaveTemplates.jnlp { slaveTemplates.terraform { slaveTemplates.vault { node(POD_LABEL){ stage('Get repository') { Git git = new Git(this, env.JENKINS_GIT_CREDENTIALS_SSH) git.clone([urlRepo: "${env.JENKINS_GIT_REPOSITORY_SSH_URL}/${repository}.git", branch: branch]) } List tfFiles = splitQueue(findFiles(glob: "**/${terraformInitScript}"),50) tfFiles.each { filesList -> filesList.each { file -> String terraformWorkDir = file.path.replace(terraformInitScript, '') Integer returnСode = 0 if (excludeDirs.any { terraformWorkDir ==~ it }) {return} stagesMap[terraformWorkDir] = { dir(terraformWorkDir){ withCredentials([[$class: 'VaultTokenCredentialBinding', credentialsId: 'vault-role', vaultAddr: env.JENKINS_VAULT_URL]]) { container('vault') { returnСode = sh( script: "set +x && sh ./${terraformInitScript}", returnStatus: true ) tfStatuses[terraformWorkDir] = returnСode != 0 ? statuses[4] : statuses[0] if (skipStep(returnСode)) { return } } withEnv(['TF_CLI_CONFIG_FILE=.terraformrc']){ container(name: 'terraform') { writeFile(file: '.terraformrc', text: mirrorsProvider) returnСode = terraform.init() tfStatuses[terraformWorkDir] = returnСode != 0 ? statuses[3] : statuses[0] if (skipStep(returnСode)) { return } tfStatuses[terraformWorkDir] = statuses[terraform.checkStatusPlan()] == null ? statuses[5] : statuses[terraform.checkStatusPlan()] } } } } } } parallel(stagesMap) stagesMap.clear() } stage('Send report'){ Notifications.email( script: this, subject: 'Terraform report', to: maintainer, body: generateReport(tfStatuses) ) } } } } } } } catch(err) { errorMessage = err.getMessage() println 'ERROR: ' + errorMessage currentBuild.result = 'FAILURE' String emailSubject = "${currentBuild.currentResult}. Pipeline task: ${currentBuild.fullDisplayName}" Notifications.email( script: this, subject: emailSubject, errorString: errorMessage, recipientProviders: [], to: maintainer ) } }