Skip to content

Instantly share code, notes, and snippets.

@gazoakley
Last active April 16, 2024 12:00
Show Gist options
  • Star 40 You must be signed in to star a gist
  • Fork 45 You must be signed in to fork a gist
  • Save gazoakley/87dcc16d28fd05acda4ba0a4be5ac387 to your computer and use it in GitHub Desktop.
Save gazoakley/87dcc16d28fd05acda4ba0a4be5ac387 to your computer and use it in GitHub Desktop.
Jenkinsfile for running Terraform
pipeline {
agent any
parameters {
string(name: 'environment', defaultValue: 'default', description: 'Workspace/environment file to use for deployment')
string(name: 'version', defaultValue: '', description: 'Version variable to pass to Terraform')
booleanParam(name: 'autoApprove', defaultValue: false, description: 'Automatically run apply after generating plan?')
}
environment {
AWS_ACCESS_KEY_ID = credentials('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = credentials('AWS_SECRET_ACCESS_KEY')
TF_IN_AUTOMATION = '1'
}
stages {
stage('Plan') {
steps {
script {
currentBuild.displayName = params.version
}
sh 'terraform init -input=false'
sh 'terraform workspace select ${environment}'
sh "terraform plan -input=false -out tfplan -var 'version=${params.version}' --var-file=environments/${params.environment}.tfvars"
sh 'terraform show -no-color tfplan > tfplan.txt'
}
}
stage('Approval') {
when {
not {
equals expected: true, actual: params.autoApprove
}
}
steps {
script {
def plan = readFile 'tfplan.txt'
input message: "Do you want to apply the plan?",
parameters: [text(name: 'Plan', description: 'Please review the plan', defaultValue: plan)]
}
}
}
stage('Apply') {
steps {
sh "terraform apply -input=false tfplan"
}
}
}
post {
always {
archiveArtifacts artifacts: 'tfplan.txt'
}
}
}
@gazoakley
Copy link
Author

This Jenkinsfile depends on a couple of parameters:

  • environment - string, specifies the Terraform workspace to use
  • version - string, passed to terraform plan (you might want to remove/add to/swap this for other variables)
  • autoApprove - boolean, if true skips the approval process immediately runs terraform apply

You'll probably want to change the environment variables and the vars passed into terraform plan

@reubenavery
Copy link

thanks, this really helped me get off the ground quickly!

@fabianoalmeida
Copy link

@gazoakley thank you to share this simple example with us. I have a question... How to define the environment value when the JenkinsFile is running?

@gazoakley
Copy link
Author

@fabianoalmeida That needs to be set using Jenkins parameters. I've updated the Jenkinsfile above to include some parameters, but you might need to set them up manually (it's been a while since I looked at this)

@fabianoalmeida
Copy link

@gazoakley thank you so much. Or put this variable as an environment variable on Jenkins application. That's really good.

@andrejesusdasilva
Copy link

Thank you @gazoakley, it will help me a lot.

@tannguyen1525
Copy link

@gazoakley when I run the script I got an error as "/var/jenkins_home/workspace/Terraform-pipeline@tmp/durable-d9d9b19b/script.sh: 1: /var/jenkins_home/workspace/Terraform-pipeline@tmp/durable-d9d9b19b/script.sh: terraform: not found"

@andrejesusdasilva
Copy link

@tannguyen1525 is there a terraform installed in your environment? because in this example jenkins is using "agent any".

@andrejesusdasilva
Copy link

Look this example @tannguyen1525 that will help you:

...
script{
//já baixa a imagem mas não é o jeito certo de usar eu acho, mas funcionou
.image('hashicorp/terraform:0.11.14')
inside(""){}

sh 'docker run -i -v $(pwd):/workpace -w /workpace hashicorp/terraform:0.11.14 init'

}
...

@tannguyen1525
Copy link

Hi @andrejesusdasilva
The script seems to not working,
My OS is Ubuntu 18.04, I installed Jenkin by Container, but terraform is installed under OS level
Is this the root cause?

@andrejesusdasilva
Copy link

send me the complete script please.

@tannguyen1525
Copy link

Hi @andrejesusdasilva
I tried to install Jenkins and Terraform under OS level and it's working as well. Thank you.

@chrisj-au
Copy link

Maybe include a format check before init. terraform fmt --check

@Dhanabalan-pop
Copy link

what if I want to update my existing workspace, my jenkinsfile creates the workspace. how to include terraform workspace select $TFWORKSPACE here?

stage('Terraform Initialization') {
when {
expression {
params.destroy==false
}
}
steps {
sh 'terraform init'
sh 'terraform workspace new $TWORKSPACE'
}
}
stage('Check Terraform plan') {
when {
expression {
params.destroy==false
}
}
steps {
sh 'export TF_WORKSPACE=$TWORKSPACE'
sh 'terraform plan -out myplan.txt'
}
}

@andrejesusdasilva
Copy link

@Dhanabalan-pop try to use in this form:

terraform workspace new ${TF_WS} || terraform workspace select ${TF_WS}

@ramjangra-jpg
Copy link

i want to create a terraform script which will automate the jenkins . help me out . script should work that it can create project and and pipeline configuration

@arekgoral
Copy link

arekgoral commented Jun 14, 2021

Hi,

variable name "version" is reserved, it needs to be some other word here ?
After the docs:

"...These names are reserved for meta-arguments in module configuration blocks, and cannot be declared as variable names."

Cheers

@andrejesusdasilva
Copy link

@arekgoral if you continuing having problem with this variavel I recommend you to change this variable in a Jenkins parameters block and remember to change all occurrence.

@arekgoral
Copy link

arekgoral commented Jun 16, 2021

Yes, thats what I am saying basically - at first I assumed you made a typo...

👍

Replacing "version" with something like "build_version" and then declaring variable in the terraform code such as 👍

//variables.tf
.....
variable "build_version {
}
.....

should do.

Cheers

@surajn03
Copy link

surajn03 commented Aug 7, 2021

I have slightly different challenge, to read the terraform apply error strings within declarative pipeline, to execute subsequent sub task..
Have some in this thread come across handling such use case..

Thanks in advance..

Regards,
Suraj

@prachikhadke
Copy link

Thanks for sharing this script. It helped me start my terraform Jenkinsfile.

@Ravinderhub
Copy link

Getting following error. Anyone any help would be appreciated?

terraform init -input=false
�[31m�[0mThere are some problems with the configuration, described below.

The Terraform configuration must be valid before initialization so that
Terraform can determine which modules and providers need to be installed.�[0m�[0m�[0m
�[33m�[33m╷�[0m�[0m
�[33m│�[0m �[0m�[1m�[33mWarning: �[0m�[0m�[1mVersion constraints inside provider configuration blocks are deprecated�[0m
�[33m│�[0m �[0m
�[33m│�[0m �[0m�[0m on aws-instance-example.tf line 5, in provider "aws":
�[33m│�[0m �[0m 5: version = �[4m"~> 2.0"�[0m�[0m
�[33m│�[0m �[0m
�[33m│�[0m �[0mTerraform 0.13 and earlier allowed provider version constraints inside the
�[33m│�[0m �[0mprovider configuration block, but that is now deprecated and will be
�[33m│�[0m �[0mremoved in a future version of Terraform. To silence this warning, move the
�[33m│�[0m �[0mprovider version constraint into the required_providers block.
�[33m│�[0m �[0m

@andrejesusdasilva
Copy link

andrejesusdasilva commented Sep 8, 2021

Seems that you need to define de provider of terraform, example:

provider "aws" {
version = "~> 2.70"
region = "ca-central-1"
}

provider "null" {
version = "~> 2.1"
}

provider "template" {
version = "~> 2.2"
}

provider "local" {
version = "~> 1.4"
}

I don't know what's the exactly version that you need.

@mickleissa
Copy link

Hello,
I have an issue to automate TF in Jenkinsfile to Apply terraform.tfstae from the backend S3. how I can write the correct command?
////////////////////////////////////////////////////////////////////////////////////

pipeline {
// Jenkins AWS Access & Secret key
environment {
AWS_ACCESS_KEY_ID = credentials('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = credentials('AWS_SECRET_ACCESS_KEY')
}

options {
// Only keep the 5 most recent builds
buildDiscarder(logRotator(numToKeepStr:'5'))
}

agent any
tools {
terraform 'terraform'
}

stages {
   // Check out from GIT, Snippet Generato from pipeline Syntax --> Checkout: Check out from version control 
    stage ("Check from GIT") {
        steps {
           git branch: 'master', credentialsId: 'Jenkins_terraform_ssh_repo', url: 'git@github.com:mickleissa/kobai.git'
              }
       }
       // Terraform Init Stage
    stage ("Terraform init") {
        steps {
            // sh 'terraform -chdir="./v.14/test_env" init -upgrade'
             // terraform init -backend-config="bucket=kobai-s3-backend-terraform-state" -backend-config="key=stage-test-env/terraform.tfstate"
                 sh 'terraform -chdir="./v.14/test_env" init -migrate-state' 
              }
    }
    // Terraform fmt Stage
    stage ("Terraform fmt") {
        steps {
            sh 'terraform fmt'
        }
    }
    // Terraform Validate Stage
    stage ("Terraform validate") {
        steps {
            sh 'terraform validate'
        }
    }

    // Terraform Plan Stage
    stage ("Terraform plan") {
        steps {
              sh 'terraform -chdir="./v.14/test_env" plan -var-file="stage.tfvars"'
           // sh 'terraform -chdir="./v.14/test_env" plan'
            
        }
    }

    //  Terraform Apply Stage
    stage ("Terraform apply") {
        steps {
             sh 'terraform -chdir="./v.14/test_env" apply -var-file="stage.tfvars" --auto-approve'
            //   sh 'terraform -chdir="./v.14/test_env" apply --auto-approve'
           
        }
    }
   // Approvel stage 
   stage ("DEV approval Destroy") {
        steps {
           echo "Taking approval from DEV Manager for QA Deployment"
           timeout(time: 7, unit: 'DAYS') {
           input message: 'Do you want to Destroy the Infra', submitter: 'admin'
           }
        }
    }
   // Destroy stage
      stage ("Terraform Destroy") {
         steps {
            sh 'terraform -chdir="./v.14/test_env" destroy -var-file="stage.tfvars" --auto-approve'
            // sh 'terraform -chdir="./v.14/test_env" destroy --auto-approve'
        }
     }
}
post {
    always {
        echo 'This will always run'
    }
    success {
        echo 'This will run only if successful'
    }
    failure {
        echo 'This will run only if failed'
    }
    unstable {
        echo 'This will run only if the run was marked as unstable'
    }
    changed {
        echo 'This will run only if the state of the Pipeline has changed'
        echo 'For example, if the Pipeline was previously failing but is now successful'
    }
      }

}

@himavanthkj
Copy link

Thanks @gazoakley it's very helpful..I have a doubt if we can add a stage in pipeline to import existing resources into terraform code..I mean is there any chance if we can have a stage where we can import resources in Jenkins pipeline.

@amit4257
Copy link

Hey, where can I find variables.tf file and other dependencies? Please share them it will be a great help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment