# Move module call to config branch and specify Terraform sample into
This section introduce Cycloid stacks concept to improve the reusability of your stack.
We created a Terraform module during the last step and used it in a
main.tf file inside our
stacks branch. This step will make it more flexible and follow Cycloid stacks concept.
Keep in mind a stack can be deployed several times for different environments or projects. The standard way to do this is to create a Terraform module in the
stacks branch. A Terraform module should be generic and describe an application. This means if we want for an application to create two environments,
prod, we might want the same infrastructure but with a smaller instance size on staging. So we will describe the infrastructure in a Terraform module and call this module 2 times (one for each env) using different parameters for the instance type.
As well this concept can also be applied to other technologies like Ansible.
This is where you apply Cycloid stacks concept. To make it simple, there is no technological limitation. It's just a way to split a
template (here, the Terraform module) and a
parameters of a template (here Terraform module call).
In our use-case, we will transform the call of the Terraform module
main.tf in a sample file. Each time someone uses your stack, it will use the Terraform module from the
stacks branch and automatically push the module's parameters in a
config branch using your sample file. We will go more into detail about it in this step.
Follow those steps to apply all changes described in this step
As described above let's define our new
main.tf.sample as a sample in the Cycloid stack (similarly to the pipeline variables sample file), we will define the Terraform sample in
config: default: ... # Configuration of terraform to setup the infrastructure terraform: instance: path: 'terraform/main.tf.sample' destination: '($ project $)/terraform/($ environment $)/main.tf'
Cycloid special vars can be used in
.cycloid.yml file, in our case
'($ project $)/terraform/($ environment $)/main.tf' will be rendered by
Those lines define the path of your stack sample in the
stacks branch and the expected path for the sample after user configuration in the
After this change, the next time you create a project or a new environment with this stack, the example of Terraform file to put in the Git
config branch will be displayed, letting the user specify is own configuration:
Then it will be automatically pushed into his config repository
Unfortunately, this does not apply to an existing env, and this is why we created the config branch and manually put this file in the commands above.
Now to make your pipeline take into account, you need to apply the concept of merging
config that you will define in the pipeline with the following changes:
- Add a
gitresource for our new
- Add merge stack and config sample as describe in produce a configured stack from stack and config section.
# Branch used to store the config of the stack config_git_branch: config
We define a pipeline variable to specify the branch for our new
git resource. And as well create a new git resource for the config branch:
resources: ... # The Terraform config (will be merged with the stack) - name: git_config type: git source: uri: ((git_repository)) branch: ((config_git_branch)) private_key: ((git_ssh_key)) paths: - ((project))/terraform/((env))/*
paths section here to limit the trigger of the pipeline only if the configuration for this specific project and env change.
Then we need to merge our stack and our config inside the pipeline. We will use the same tips as the previous step based on YAML Alias indicators (opens new window).
# YAML anchors shared: - &task-merge-stack-and-config task: merge-stack-and-config config: platform: linux image_resource: type: docker-image source: repository: cycloid/cycloid-toolkit tag: latest run: path: /usr/bin/merge-stack-and-config inputs: - name: git_config path: "config" - name: git_stack path: "stack" outputs: - name: merged-stack path: "merged-stack" params: CONFIG_PATH: ((project))/terraform/((env)) STACK_PATH: stack-sample/terraform
This task calls a script provided by cycloid in our cycloid-toolkit image (opens new window) to merge our two expected inputs
config and put the result of the merge in a
This merge also takes
STACK_PATH as params related to the expected path of Terraform files defined in
Last change, add
task-merge-stack-and-config task and
git_config resource in our Terraform jobs to merge our config and stack before running the Terraform resource.
jobs: ... - name: terraform-plan plan: - do: - get: git_stack trigger: true - get: git_config trigger: true - get: git_code trigger: true passed: - unittest - *task-merge-stack-and-config - *task-get-commit - put: tfstate params: plan_only: true terraform_source: merged-stack/ var_files: - extracted-vars/terraform.tfvars - name: terraform-apply plan: - do: - get: git_stack trigger: false passed: - terraform-plan - get: git_config trigger: false passed: - terraform-plan - get: tfstate trigger: false passed: - terraform-plan - get: git_code passed: - terraform-plan - *task-merge-stack-and-config - *task-get-commit - put: tfstate params: plan_run: true terraform_source: merged-stack/ var_files: - extracted-vars/terraform.tfvars
The code above adds the
get call of our
git_config resource, then use the YAML anchor to add a merge task before.
Then we also changed the
terraform_source from terraform (
put: tfstate) to use the output of our merge
merged-stack instead of the Terraform code from the stack branch.
Add and commit those changes in Git:
git add . git commit -m "Step 5" git push origin stacks
Get back to Cycloid's dashboard, and click on the
Refresh pipeline button .
# Key points to remember
- A stack can be deployed several times for different environments or projects
- A Terraform module should be generic and describe an application (same thing with Ansible for example)
- A stack is a way to split a template (for example a Terraform module) and a parameters of a template (for example a Terraform module call or
- Most of the time, the parameters (for example
main.tf) is transformed in a sample file
- Each time someone uses your stack, it will use the Terraform module from the
stacksbranch and automatically push the module's parameters in a
configbranch using your sample file