Skip to content

STATE

What is this terraform.tfstate file

When you have run a terraform apply a state file is created terraform.tfstate.

A simple one looks like this:

{
  "version": 4,
  "terraform_version": "0.12.10",
  "serial": 1,
  "lineage": "c00de4dd-b230-5181-5799-847ec00a257a",
  "outputs": {
    "account_id": {
      "value": "999999999999",
      "type": "string"
    }
  },
  "resources": [
    {
      "mode": "data",
      "type": "aws_caller_identity",
      "name": "current",
      "provider": "provider.aws",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "account_id": "999999999999",
            "arn": "arn:aws:iam::999999999999:user/jameswoolfenden",
            "id": "2019-10-12 10:24:39.2137408 +0000 UTC",
            "user_id": "AAAAAAAAAAAAAAAAA"
          }
        }
      ]
    }
  ]
}

The state file holds a record of inputs, outputs and resources created. A state file is a record of what infrastructure was made or that existed at the last run.

A typical setup is to create an S3 bucket and configure that to store state, this is called a remote backend. With-in that bucket multiple state files from many different project would exist from One AWS/GCP account/project. Each projects' remote backend would look similar to remote_state.tf below:

terraform {
  backend "s3" {
    encrypt        = true
    bucket         = "121334234343-terraform-state"
    key            = "aws-lambda-wilbur/lambda/terraform.tfstate"
    dynamodb_table = "dynamodb-state-lock"
    region         = "eu-west-1"
  }
}

Where we have an S3 bucket s3://121334234343-terraform-state with a folder aws-lambda-wilbur/lambda/ as this is a environment called lambda for the template aws-lambda-wilbur.

Importance of setting version

The state file is written with the version number - see the line above

"terraform_version": "0.12.10",

The Golden Laws of State

Don't ever delete your terraform.tfstate

Don't check-in terraform.tfstate

Add a terraform.state to your .gitignore to ensure this doesn't happen.

Don't try to edit state files

You'll mess it up. Yes you will. It's like editing a SQL DB by hand. That is also a sub-optimal idea.

Do use a locking backend

More than one person trying to modify the same infrastructure at the same time? That doesn't work. In the long term you'll be controlling terraform and your infrastructure via a CI/CD process, but locking state is essential. If your state is in S3 use Dynamo.

DONT PANIC

At times like these cooler head prevail, your second idea is probably wiser than your first. Don't compound your mistakes.

Fix your Terraform version as Team in your Terraform Block

Add a File to your templates (terraform.tf) with content like:

terraform {
   required_version="12.10"
}

You'll probably forget this at some point and one of you will make the state file incompatible for the team.

If you are adding this code to git. You are? no you are. Then add a .gitignore to the root of your repo based from https://github.com/github/gitignore/blob/master/Terraform.gitignore. Also copy the pre-commit file and install it.

State recovery/import

Ok so you broke your state file? Or you have a tonne of existing estate?

  • Logging on S3 buckets

  • to find out who broke it.

  • Import existing infra basics Most (BUT NOT ALL) resources have support for the import keyword, this can create a lot of work. If your doing a load it will be better to look at Terraforming.

This gives you the terraform, this gives you the state:

$ terraforming s3 --tfstate
{
  "version": 1,
  "serial": 1,
  "modules": [
    {
      "path": [
        "root"
      ],
      "outputs": {
      },
      "resources": {
        "aws_s3_bucket.whosebucketisitanyway": {
          "type": "aws_s3_bucket",
          "primary": {
            "id": "whosebucketisitanyway",
            "attributes": {
              "acl": "private",
              "bucket": "whosebucketisitanyway",
              "force_destroy": "false",
              "id": "whosebucketisitanyway",
              "policy": ""
            }
          }
        }
      }
    }
  ]
}