05. November 2022
How to setup a Gitlab as a remote state backend for Terraform with Reusable Templates
Lets create a new repo in gitlab that is called pipelines and create a folder called terraform.
Lets create Reusable Jobs that are configured from environment variables
We are going to make a tf.yml that contains the full template that can be pulled into an applications .gitlab-ci.yml
1include:
2 - local: 'tf/main/plan.yml'
3 - local: 'tf/main/apply.yml'
All the primary scripts will go in main/
Create a reusable terraform init script to run at the beginning of each terraform stage
We will create a variable check that runs at the very beginning to catch any configuration errors form the Environment variables
You can store the username and password in the gitlab ci variables or in vault.
Field | Desc |
---|---|
username | gitlab username |
password | Either a gitlab token or actual password |
1tf_init_var_check:
2 stage: .pre
3 script:
4 - if [ -z "${TF_ADDRESS}"]; then echo "ERROR - TF_ADDRESS does not exist, add to .gitlab-ci.yml"; exit 1; fi
5 - if [ -z "${TF_USERNAME}"]; then echo "ERROR - TF_USERNAME does not exist, add to .gitlab-ci.yml"; exit 1; fi
6 - if [ -z "${TF_PASSWORD}"]; then echo "ERROR - TF_PASSWORD does not exist, add to .gitlab-ci.yml"; exit 1; fi
7
8.terraform_init:
9 script:
10 - echo $GITLAB_USER_NAME
11 - rm -rf .terraform
12 - terraform --version
13 - |
14 terraform init \
15 -backend-config=address=${TF_ADDRESS} \
16 -backend-config=lock_address=${TF_ADDRESS}/lock \
17 -backend-config=unlock_address=${TF_ADDRESS}/lock \
18 -backend-config=username=${TF_USERNAME} \
19 -backend-config=password=${TF_PASSWORD} \
20 -backend-config=lock_method=POST \
21 -backend-config=unlock_method=DELETE \
22 -backend-config=retry_wait_min=5
This sets the Image for all jobs and creates a cache for .terraform
1tf_base_config_var_check:
2 stage: .pre
3 script:
4 - if [ -z "${TF_IMAGE}"]; then echo "ERROR - TF_IMAGE does not exist, add to .gitlab-ci.yml"; exit 1; fi
5 - if [ -z "${TF_ROOT}"]; then echo "ERROR - TF_ROOT does not exist, add to .gitlab-ci.yml"; exit 1; fi
6
7.tf_base_config:
8 image: ${TF_IMAGE}
9 cache:
10 key: "${TF_ROOT}"
11 paths:
12 - ${TF_ROOT}/.terraform/
This uses the config and init script to plan and save a plan artifact named "plans"
1include:
2 - local: 'tf/main/init.yml'
3 - local: 'tf/main/config.yml'
4
5plan:
6 stage: build
7 extends:
8 - .tf_base_config
9 script:
10 - !reference [.terraform_init, script]
11 - terraform plan -out "plans"
12 artifacts:
13 paths:
14 - plans
15 expire_in: 20m
This uses the config and init script to apply the artifact named "plans" only on the master branch
1include:
2 - local: 'tf/main/init.yml'
3 - local: 'tf/main/config.yml'
4
5
6deploy:
7 stage: deploy
8 extends:
9 - .tf_base_config
10 script:
11 - !reference [.terraform_init, script]
12 - terraform apply -input=false "plans"
13 only:
14 - master
Add this to your gitlab-ci.yml
1include:
2 - project: 'groupName/pipelines'
3 file:
4 - tf/tf.yml
5
6
7variables:
8 TF_ROOT: $CI_PROJECT_DIR # The relative path to the root directory of the Terraform project
9 TF_STATE_NAME: STATE_NAME # The name of the state file used by the GitLab Managed Terraform state backend
10 TF_IMAGE: registry.gitlab.com/gitlab-org/terraform-images/releases/terraform:1.1.9
11 ARTIFACT_VERSION: "1.0.0"
12 REALEASE_VERSION: $ARTIFACT_VERSION
13 TF_ADDRESS: "https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/terraform/state/${TF_STATE_NAME}"
14
15
16default:
17 tags:
18 - your
19 - runner
20 - tags
Enjoy Quickly Adding Gitlab as your Remote state backend
To use add this to main.tf
1terraform{
2
3 backend "http" {
4
5 }
6}