Skip to content

MarcBuch/terraform-azurerm-reference

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

terraform-azurerm-reference

"Infrastructure as Code should be fully treated as code." - Some guy on reddit

This repo is intended to display a approach to Terraform project design with the recommendations given in the 12factor App.

Goals of this project

The 12 factor app recommends that configuration has to be separated from the application code. To externalize this, I decided to wrap the module with a YAML wrapper. This allows me to use a YAML file for the configuration.

  • YAML is easier to read.
  • Typed variables offer input validation.
  • YAML can be generated by other tools.

You can also use JSON for input, but this helps more on the automation side. For example, REST requests could be made to deploy Terraform.

Why implement a YAML wrapper?

There are multiple ways to provide values to Terraform:

  1. Hardcode them.
  2. Using variables and default values.
  3. Using variables and passing a .tfvars file.
  4. On the command line using -var.
  5. Through environment variables TF_VAR_.

Each of these different ways can override the others. This can result in configuration living in various locations and makes code reviews painful.

One step further with an immutable artifact

Why on earth would you wrap Terraform into a container?

  • Provide a single way to set variables for Terraform.
  • Can be promoted through the stages (dev, qa, prod).
  • Everything needed for the deployment is inside the container. Only docker is required.
  • The artifact can be used in other pipelines. For example, the pipeline in the application repo can pull this artifact and create a new deployment.

My implementation also includes a provider mirror Terraform Docs - Provider Installation meaning the providers are baked into the docker image.

Integrating tests

I've included a compiled version of the Terratest file in the container image. Configuration for this test is read from the same YAML file as the deployment uses.

How to build a new image

# Build the docker image
docker build -t terraform-azurerm-reference .

How to run a Terratest tests

  • YAML config can be passed into /config/input.yaml location.
docker run -it -e "ARM_SUBSCRIPTION_ID=${ARM_SUBSCRIPTION_ID}" -e "ARM_TENANT_ID=${ARM_TENANT_ID}" \
    -e "ARM_CLIENT_ID=${ARM_CLIENT_ID}" -e "ARM_CLIENT_SECRET=${ARM_CLIENT_SECRET}" \
    -e "STORAGE_ACCOUNT_NAME=${storage_account_name}" -e "STORAGE_ACCOUNT_KEY=${storage_account_key}" \
    -e "CONTAINER_NAME=${container_name}" -e "STATE_FILE_NAME=${state_file_name}" \
    -v $PWD/input.yaml:/config/input.yaml:ro \
    terraform-azurerm-reference /tests/integration_test

How to run a Terraform deployment

  • A docker volume will be used to hold the initialized Terraform as well as the plan file.

Terraform init

docker run -it -e "ARM_SUBSCRIPTION_ID=${ARM_SUBSCRIPTION_ID}" -e "ARM_TENANT_ID=${ARM_TENANT_ID}" \
    -e "ARM_CLIENT_ID=${ARM_CLIENT_ID}" -e "ARM_CLIENT_SECRET=${ARM_CLIENT_SECRET}" \
    -v tf-wd:/working_dir \
    terraform-azurerm-reference terraform init -from-module=/tf \
    -backend-config="storage_account_name=${storage_account_name}" -backend-config="container_name=${container_name}" \
    -backend-config="access_key=${storage_account_key}" -backend-config="key=${state_file_name}"

Terraform plan

docker run -it -e "ARM_SUBSCRIPTION_ID=${ARM_SUBSCRIPTION_ID}" -e "ARM_TENANT_ID=${ARM_TENANT_ID}" \
    -e "ARM_CLIENT_ID=${ARM_CLIENT_ID}" -e "ARM_CLIENT_SECRET=${ARM_CLIENT_SECRET}" \
    -v tf-wd:/working_dir -v $PWD/input.yaml:/config/input.yaml:ro \
    terraform-azurerm-reference terraform plan -out /working_dir/plan

Terraform apply

docker run -it -e "ARM_SUBSCRIPTION_ID=${ARM_SUBSCRIPTION_ID}" -e "ARM_TENANT_ID=${ARM_TENANT_ID}" \
    -e "ARM_CLIENT_ID=${ARM_CLIENT_ID}" -e "ARM_CLIENT_SECRET=${ARM_CLIENT_SECRET}" \
    -v tf-wd:/working_dir -v $PWD/input.yaml:/config/input.yaml:ro \
    terraform-azurerm-reference terraform apply /working_dir/plan

Terraform destroy

docker run -it -e "ARM_SUBSCRIPTION_ID=${ARM_SUBSCRIPTION_ID}" -e "ARM_TENANT_ID=${ARM_TENANT_ID}" \
    -e "ARM_CLIENT_ID=${ARM_CLIENT_ID}" -e "ARM_CLIENT_SECRET=${ARM_CLIENT_SECRET}" \
    -v tf-wd:/working_dir -v $PWD/input.yaml:/config/input.yaml:ro \
    terraform-azurerm-reference terraform destroy

References

Based on the YT Video Series by Antonio Masucci

About

This repo can be used for refence to design Terraform projects

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published