Giter Site home page Giter Site logo

terraform-azurerm-reference's Introduction

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.