diff --git a/jobs-dsl/jobs/Automation/DevOps/terraform_checker.groovy b/jobs-dsl/jobs/Automation/DevOps/terraform_checker.groovy
new file mode 100644
index 0000000..4e47215
--- /dev/null
+++ b/jobs-dsl/jobs/Automation/DevOps/terraform_checker.groovy
@@ -0,0 +1,28 @@
+pipelineJob('Automation/DevOps/terraform-checker') {
+ description("Terraform checker")
+ definition {
+ cpsScm {
+ scm {
+ git {
+ remote {
+ url("${JENKINS_GIT_REPOSITORY_URL}/DevOps/jenkins-pipelines.git")
+ credentials("${JENKINS_GIT_CREDENTIALS_HTTP}")
+ }
+ branch('master')
+ }
+ }
+ scriptPath('pipelines/Automation/DevOps/terraform_checker.groovy')
+ }
+ }
+
+ properties {
+ disableConcurrentBuilds()
+ pipelineTriggers {
+ triggers {
+ cron {
+ spec('H 2 * * *')
+ }
+ }
+ }
+ }
+}
diff --git a/pipelines/Automation/DevOps/terraform_checker.groovy b/pipelines/Automation/DevOps/terraform_checker.groovy
new file mode 100644
index 0000000..93b63ef
--- /dev/null
+++ b/pipelines/Automation/DevOps/terraform_checker.groovy
@@ -0,0 +1,189 @@
+@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 = '''
+
+ | Terraform report |
+
+ Path | Status |
+
+ <% states.each { key, value -> %>\
+ ${key} | ${value}
+
+ <% } %>\
+
+ '''
+
+ 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
+ )
+ }
+}