Files
jenkins-pipelines/pipelines/Automation/DevOps/terraform_checker.groovy
Rustam Tagaev 1be646943e [DO-1617] add_terraform_checker (!85)
Co-authored-by: Rustam Tagaev <rustam.tagaev@avroid.tech>
Reviewed-on: https://git.avroid.tech/DevOps/jenkins-pipelines/pulls/85
Reviewed-by: Vasiliy Chipizhin <vasiliy.chipizhin@avroid.team>
Reviewed-by: Aleksandr Vodyanov <aleksandr.vodyanov@avroid.team>
Reviewed-by: Denis Patrakeev <denis.patrakeev@avroid.team>
2025-02-27 12:33:53 +03:00

190 lines
6.8 KiB
Groovy
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@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: '<td style="color:rgb(0, 255, 68)">Ok</td>',
1: '<td style="color:rgb(255, 5, 5)">Terraform plan error</td>',
2: '<td style="color:rgb(247, 255, 20)">Infrastructure has been changed</td>',
3: '<td style="color:rgb(255, 5, 5)">Terraform init problem</td>',
4: '<td style="color:rgb(255, 5, 5)">Terraform init script problem</td>',
5: '<td style="color:rgb(255, 5, 5)">Unknow error!</td>'
]
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 = '''
<table border="1" style="background: rgb(109, 109, 109);">
<th colspan="2">Terraform report</th>
<tr></tr>
<th>Path</th><th>Status</th>
<tr></tr>
<% states.each { key, value -> %>\
<td>${key}</td>${value}
<tr></tr>
<% } %>\
</table>
'''
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
)
}
}