Terraform destroy fails in CircleCI

Viewed 714

I am currently using CircleCI as my CI tool to build AWS infrastructure using Terraform

My flow is,

  1. Create an AWS instance using Terraform
  2. Install Docker and run Nginx image on it
  3. Destroy the infrastructure

My CircleCI config is as follows,

version: 2
jobs:
  terraform_apply:
    working_directory: ~/tmp
    docker:
            - image: hashicorp/terraform:light
            - image: ubuntu:16.04

    steps:
      - checkout
      - run:
          name: terraform apply
          command: |
            terraform init
            terraform apply -auto-approve
      - store_artifacts:
          path: terraform.tfstate

  terraform_destroy:
    working_directory: ~/tmp
    docker:
            - image: hashicorp/terraform:light
            - image: ubuntu:16.04
    steps:
      - checkout
      - run:
          name: terraform destroy
          command: |
            terraform init
            terraform destroy -auto-approve

workflows:
  version: 2
  terraform:
    jobs:
      - terraform_apply
      - click_here_to_delete:
          type: approval
          requires:
            - terraform_apply
      - terraform_destroy:
          requires:
            - click_here_to_delete

Here I am using 2 jobs, One for the creation and one for Deletion in CircleCI workflow.

My first job is running successfully but when I started second it start from scratch so I could not get previous terraform apply state hence terraform could not destroy my already created infrastructure.

I am looking for some solution where I can somehow save state file and copy it to next job where terraform can destroy my previous architecture

1 Answers

You should be using remote state.

Local state is only ever useful if you are always running from the same machine and don't care about loss of your state file if you accidentally delete something etc.

You can mix and match any of the available state backends but as you're using AWS already it probably makes most sense to use the S3 backend.

You will need to define the state configuration for each location which can be done entirely hardcoded in config, entirely by command line flags or partially with both.

As an example you should have something like this block in each of the directories you would run Terraform in:

terraform {
  backend "s3" {}
}

You could then finish configuring this during terraform init:

terraform init -backend-config="bucket=uniquely-named-terraform-state-bucket" \
               -backend-config="key=state-key/terraform.tfstate"

Once you have ran terraform init, Terraform will fetch the state from S3 for any plans. Then on a terraform apply or terraform destroy it will update the state file as necessary.

This will then allow you to share the state easily among colleagues and also CI/CD machines. You should also consider looking into state locking using DynamoDB to prevent state from being corrupted by multiple people modifying state at the same time. Equally you should also consider enabling versioning on the S3 bucket used for storing your state so you can always get back to an earlier version of the state in the event of any issues.

Related