Continuous Delivery for Terraform with Drone.io
Tags: terraform, continuousdelivery, systemadministratio, continuousintegrati
Published: 2019-02-20 21:46:49

---
title: Continuous Delivery for Terraform with Drone.io
published: true
tags: terraform,continuous-delivery,system-administratio,continuous-integrati
canonical_url: https://medium.com/@jmarhee/continuous-delivery-for-terraform-with-drone-io-6a4f6550dc29
---

![](https://cdn-images-1.medium.com/max/640/1*y2aYyXq908Agavu47uSeqg.jpeg)<figcaption>source: <a href="https://www.wocintechchat.com/">https://www.wocintechchat.com/</a></figcaption>

Continuous Delivery (or the combination Continuous Integration and CD) is one pattern for keeping your project well tested (as far as delivering to production in concerned — other testing on changes themselves not withstanding)- [eminently deployable](https://codeship.com/continuous-integration-essentials). For projects like infrastructure provisioning and state management tooling like Terraform repositories, that typically means, upon a change to the release branch, running these changes and ensuring the manifests can still cleanly apply.

I recently created this project to deploy a multi-architecture Kubernetes cluster on [Packet](http://packet.com):

[jmarhee/packet-multiarch-k8s-terraform](https://github.com/jmarhee/packet-multiarch-k8s-terraform)

and having selected [Drone.io’s cloud CD tooling,](http://cloud.drone.io) all I needed to do once I activated my project:

![](https://cdn-images-1.medium.com/max/1024/1*H9c44XNKrw3_ibEvvTyzYw.png)

was push a manifest, .drone.yml , with my build steps, and referencing some configuration options I’d need for Terraform to run successfully.

Before I lay out my manifest, in the project, I needed to store secrets in order to expose them to Drone when they go to run Terraform, so things like provider credentials, and other variable values that you might normally put into terraform.tfvars when you run it locally:

![](https://cdn-images-1.medium.com/max/1024/1*uJStvXp7uukzy-H_gxOxEQ.png)

With those values stored, in your manifest, you can reference these values and put them into environment variables (i.e. for a variable called count_x86, rather than declaring in tfvars , you could export a variable like TF_VAR_count_x86 ):

```
kind: pipeline

name: default

steps:

- name: Deploy

  image: alpine

  environment:

      TF_VAR_auth_token:

          from_secret: TF_VAR_auth_token

      TF_VAR_count_x86:

          from_secret: TF_VAR_count_x86

      TF_VAR_count_arm:

          from_secret: TF_VAR_count_arm
```

and then to do things like install and run Terraform, validate, and then apply the changes to your repository’s Terraform manifests, you can provide commands in a list like the following:

```
  commands:

  - apk --update add curl

  - curl --silent --output terraform.zip "https://releases.hashicorp.com/terraform/0.11.11/terraform_0.11.11_linux_amd64.zip"

  - unzip terraform.zip ; rm -f terraform.zip; chmod +x terraform

  - mkdir -p ${HOME}/bin ; export PATH=${PATH}:${HOME}/bin; mv terraform ${HOME}/bin/

  - terraform -v

  - terraform init

  - terraform validate

  - terraform apply -auto-approve

  - terraform destroy -auto-approve
```

and then, upon pushes to your target branch (in my case, master ), a new test run will begin:

![](https://cdn-images-1.medium.com/max/1024/1*gkM5pSPjO9InQnfesl71Vw.png)

with the output from your build steps, in our case a single stage called Deploy (you might repeat this, for example, to test different server types in different facilities — TF_VAR_facilityin our case- or just if a change requires multiple types of validation), written out to the console.

Further Reading

[https://hackernoon.com/build-your-own-ci-cd-pipeline-with-drone-e43d7190989b](https://hackernoon.com/build-your-own-ci-cd-pipeline-with-drone-e43d7190989b)

[https://codeship.com/continuous-integration-essentials](https://codeship.com/continuous-integration-essentials)

[https://github.com/jmarhee/packet-multiarch-k8s-terraform](https://github.com/jmarhee/packet-multiarch-k8s-terraform)