# Create a Terraform module and add Terraform apply job in the pipeline
Terraform plan job is now configured and working, it's time to push some real Terraform codes to describe a cloud instance using terraform module format.
Follow those steps to apply all changes described in this step
The previous lines create a Terraform module which contains the description of a cloud instance and an its init bash script to run at startup. To know more about Terraform module, feel free to read the Terraform module documentation
Our Terraform now have the following files:
- A module under the
terraform/module-<provider_name>
directory - A main Terraform file to simply call the module
terraform/main.tf
- An output file
terraform/outputs.tf
to forward module outputs to the pipeline. We will use it later. - Several files inside the module
- Module output file
terraform/module-<provider_name>/outputs.tf
to specify which information the module will return. - Variables file
terraform/module-<provider_name>/variables.tf
to define what are the parameters we can pass to the module. - A
terraform/module-<provider_name>/vm.tf
file containing the definition of the cloud instance. - The template of the startup script
terraform/module-<provider_name>/userdata.sh.tpl
run in the instance
- Module output file
tips
You can notice how tags are usually used
tags {
"cycloid.io" = "true"
env = var.env
project = var.project
customer = var.customer
}
}
2
3
4
5
6
7
Notice how usually customer use our defined variables as tag special tags env
, project
, customer
and cycloid.io
which are used by some of our features like billing to filter components.
The userdata.sh.tpl
startup script will use our two previously defined variables to know the url and the version (commit id) we want to deploy on it.
stack-sample/terraform/provider.tf
variable "git_code_commit" {
default = "origin/code"
}
variable "git_code_repo" {
default = "https://github.com/cycloid-community-catalog/docs-step-by-step-stack.git"
}
2
3
4
5
6
note
We use a startup bash script to deploy the website source code on our instance to make this guide easier. On production you might want to go using dedicated tools like Ansible
Our new Terraform code now requires 2 variables to be run git_code_commit
and git_code_repo
. To get the commit id we will need a little bash script.
As we will need it into the Terraform plan and apply job, we will introduce a standard YAML tip, allowing us to reuse YAML code as a template YAML Alias indicators.
To summarize it will allow us to define a YAML code that we will put under shared
section, and name &task-get-commit
. That we will be able to reuse using *task-get-commit
.
shared:
- &task-get-commit
task: get-commit
config:
platform: linux
image_resource:
type: docker-image
source:
repository: cycloid/cycloid-toolkit
tag: latest
run:
path: /bin/bash
args:
- -c
- |
DIR=${PWD}
echo "git_code_commit = \"$(cat git_code/.git/ref)\"" | tee -a extracted-vars/terraform.tfvars
echo "git_code_repo = \"${GIT_CODE_REPO}\"" | tee -a extracted-vars/terraform.tfvars
params:
ENV: ((env))
GIT_CODE_REPO: ((code_git_public_repository))
inputs:
- name: git_code
outputs:
- name: extracted-vars
path: "extracted-vars"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
This code above defines a pipeline task that we will use in our terraform plan
an terraform apply
jobs.
The task expect our website source code (git_code
) as input. Then run a bash script to generate a terraform variables file terraform.tfvars
in the defined output extracted-vars
.
The Terraform code is now ready to be tested and applied. To follow best practices, we will implement a "manual validation" in the pipeline to run terraform apply
after a terraform plan
.
Let's define now the Terraform apply job using our previously defined task.
stack-sample/pipeline/pipeline.yml
groups:
- name: overview
jobs:
- unittest
- terraform-plan
- terraform-apply
jobs:
- name: terraform-plan
...
plan:
- do:
- get: git_code
trigger: true
passed:
- unittest
- *task-get-commit
- put: tfstate
params:
plan_only: true
terraform_source: git_stack/stack-sample/terraform
var_files:
- extracted-vars/terraform.tfvars
- name: terraform-apply
build_logs_to_retain: 10
plan:
- do:
- get: git_stack
trigger: false
passed:
- terraform-plan
- get: tfstate
trigger: false
passed:
- terraform-plan
- get: git_code
passed:
- terraform-plan
- *task-get-commit
- put: tfstate
params:
plan_run: true
terraform_source: git_stack/stack-sample/terraform
var_files:
- extracted-vars/terraform.tfvars
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
This sample implements a manual approval by adding the terraform-apply
without any trigger: true
configured on the get
resources. That means the terraform-apply
will never be triggered automatically.
The usual workflow is to trigger terraform-plan
, let a user reads the output of the plan and if it's ok, manually triggers the terraform-apply
job by clicking on it and press the +
button
We also added our special task defined earlier *task-get-commit
in both jobs. As saw above this task create a variable file extracted-vars/terraform.tfvars
that we specify during the call of the Terraform resource using var_files
option.
Add and commit those changes in Git:
git add .
git commit -m "Step 4"
git push origin stacks
2
3
Get back to Cycloid's dashboard, click on the Refresh pipeline
button .
It's time to create our instance, run the terraform-plan
job, the output should inform that Terraform is about to create our new cloud instance:
If everything is ok for you, as described earlier, go on the terraform-apply
job and trigger it:
After the apply, a new cloud instance should be present on your cloud provider console.