This is the homepage of the TACO project obviously... TACO is a thin ansible wrapper for Terraform that provides extra features and conventions for keeping your Terraform configurations DRY.
TACO brings you key features to gain time in your every day work around Terraform:
- a smart way of managing variables in a DRY way
- an awesome way of managing dynamic backend configurations
- the fantabulous capacity of deploying remote Terraform stack from their git repository url
- Install Ansible (tested with Ansible 2.9.x)
- Install Terraform (tested on 0.12.x)
- Have a
terraform
directory, in which you will group several directories containing Terraform code. These sub-directoriesterraform/*
will be our layers directories.
- Get the project code, either by:
- Downloading it
- or
git clone
the project
- Export a
TACO_HOME
environment variable to point to the root of the TACO project on your machine
Run ansible-playbook ${TACO_HOME}/taco.yml
from the root of a compliant Terraform project.
- You will have to supply some variables to the ansible run :
tflayer
: the name of the Terraform layer you want to target. Can be any subdirectory of theterraform/
directorydeploy_env
: a label that should be used to differenciate you several tfstatesdeploy_region
: the region you intend to apply your Terraform layer.tfaction
: the desired Terraform workflow phase you want. Can be one of[ init | plan | apply | refresh | import | output | destroy ]
- For some Terraform workflow phases, you will need to supply additionally variables to the ansible run
- Mandatory variables when running
import
terraform workflow phase :tf_addr
: specify the address to import the resource totf_id
: specify the resource-specific ID to identify that resource being imported
- Optional variables when running
output
terraform workflow phase :tf_name
: specify the name of the resource to outputtf_output_file
: specify the name of the output file where theoutput
result command will be redirect (file will be available on taco layer target directory)
- Mandatory variables when running
The main feature of TACO is to deport variables in YAML files and rely on Ansible variable and templating
feature instead of passing tfvars
files by hand to Terraform.
If multiple variables of the same name are defined in different places, they get overwritten in a certain order. In the list below, the {{ tflayer }}
, {{ deploy_env }}
and {{ deploy_region }}
placeholders refers to the value passed to the taco.yml
playbook. Here is the order of precedence from least to greatest (the last listed variables winning prioritization):
terraform/all-layers.taco.yml
terraform/{{ tflayer }}/all-env.all-region.taco.yml
terraform/{{ tflayer }}/all-env.{{ deploy_region }}.taco.yml
terraform/{{ tflayer }}/{{ deploy_env }}.all-region.taco.yml
terraform/{{ tflayer }}/{{ deploy_env }}.{{ deploy_region }}.taco.yml
Avoid defining the variable x
in many places and then ask the question "which x gets used". There is only one Empire State Building. One Mona Lisa, etc. Figure out where to define a variable, and don’t make it complicated.
When running Terraform CLI, TACO will:
- read all these files and gather every variable defined there
- scan Terraform code and find every
variable "xxx"
definition - generate a JSON file with every values needed by the Terraform code
- pass it to the Terraform CLI via a
-var-file=...
option
Among the several ways of defining Terraform backend configuration, we chose to pass them via CLI options
supplied to terraform init -backend-config=...
.
It is based on the presence of a special variable named tflayer_backend_config
in the YAML variables files. It should be a map and every key-value in it will become option for the init phase.
For example, if you have this in your YAML variable files:
tflayer_backend_config:
bucket: "project-tfstates"
region: "eu-west-1"
encrypt: "true"
kms_key_id: "arn:aws:kms:eu-west-1:000666000666:key/0dd666ee-25aa-a2a2-8888-042042042fff"
key: "tflayers/{{ tflayer }}/{{ deploy_env }}.{{ deploy_region }}.tfstate"
dynamodb_table: "project-tfstates-lock"
And you run this from the root of your Terraform project:
ansible-playbook ${TACO_HOME}/taco.yml \
-e tflayer=network \
-e tfaction=init \
-e deploy_env=dev \
-e deploy_region=eu-west-3
Then this will add init option like:
terraform init [...]
-backend-config="bucket=project-tfstates"
-backend-config="region=eu-west-1"
-backend-config="encrypt=true"
-backend-config="kms_key_id=arn:aws:kms:eu-west-1:000666000666:key/0dd666ee-25aa-a2a2-8888-042042042fff"
-backend-config="key=tflayers/network/dev.eu-west-3.tfstate"
-backend-config="dynamodb_table=project-tfstates-lock"
For three simple reasons:
- Ansible makes it easy to open and hack the project if you want/need to.
- Ansible is great at mixing variables files and templating.
- On the project founder's workstation:
[ "$MY_PREFERED_TOOL" = "ansible" ]
returns0