Terragrunt was originally created to support two features that were not available in Terraform: defining remote state configuration in a file (rather than via CLI commands) and locking. As of version 0.9.0, Terraform now supports both of these features natively, so we have made some changes to Terragrunt:
- Terragrunt still supports remote state configuration, so you can take advantage of Terragrunt's interpolation functions.
- Terragrunt no longer supports locking.
The following sections outlines the steps you may need to take in order to migrate from Terragrunt <= v0.11.x to Terragrunt 0.12.x. If you are using Terraform <= 0.8.x, see the upgrade guide on the Terraform website Upgrading to Terraform v0.9.
Migration steps include:
- Define a backend in your Terraform files
- Switch from Terragrunt locking to Terraform locking
- Migrate from .terragrunt to terraform.tfvars
As of Terraform 0.9.0, you must define a backend
in your Terraform code (the .tf
files). The Terraform guides
Upgrading to Terraform v0.9 and
Backends: Migrating From 0.8.x and Earlier
may be useful to understand backends.
For example, to use S3 as a remote state backend, you will need to add the following to your Terraform code:
# main.tf
terraform {
# The configuration for this backend will be filled in by Terragrunt
backend "s3" {}
}
Note that you can leave the configuration of the backend
empty and allow Terragrunt to provide that configuration
instead. This allows you to keep your remote state configuration more DRY by taking advantage of Terragrunt's
interpolation functions:
# terraform.tfvars
terragrunt = {
remote_state {
backend = "s3"
config {
bucket = "my-terraform-state"
key = "${path_relative_to_include()}/terraform.tfstate"
region = "us-east-1"
encrypt = true
}
}
}
Note: when switching from Terragrunt v0.11.x to v0.12.x, you also need to change the encrypt
setting from a string (e.g. "true"
) to a boolean (e.g. true
without the quotes).
Remove any lock { ... }
blocks from your Terragrunt configurations, as these are no longer supported.
If you were storing remote state in S3 and relying on DynamoDB as a locking mechanism, Terraform now supports that
natively. To enable it, simply add the lock_table
parameter to your S3 backend configuration. If you configure
your S3 backend using Terragrunt, then Terragrunt will automatically create the lock_table
for you if that table
doesn't already exist:
# terraform.tfvars
terragrunt = {
remote_state {
backend = "s3"
config {
bucket = "my-terraform-state"
key = "${path_relative_to_include()}/terraform.tfstate"
region = "us-east-1"
encrypt = true
# Tell Terraform to do locking using DynamoDB. Terragrunt will automatically
# create this table for you if it doesn't already exist.
lock_table = "my-lock-table"
}
}
}
NOTE: We recommend using a completely new lock table name and NOT reusing the lock table from older versions of Terragrunt, as that older table had a different structure than what Terraform expects, and Terragrunt will not automatically recreate it.
If you would like Terraform to automatically retry locks like Terragrunt did (this is particularly useful when
running Terraform as part of an automated script, such as a CI build), you use an extra_arguments
block:
# terraform.tfvars
terragrunt = {
remote_state {
backend = "s3"
config {
bucket = "my-terraform-state"
key = "${path_relative_to_include()}/terraform.tfstate"
region = "us-east-1"
encrypt = true
# Tell Terraform to do locking using DynamoDB. Terragrunt will automatically
# create this table for you if it doesn't already exist.
lock_table = "my-lock-table"
}
}
terraform {
# Force Terraform to keep trying to acquire a lock for up to 20 minutes
# if someone else already has the lock.
extra_arguments "retry_lock" {
commands = [
"init",
"apply",
"refresh",
"import",
"plan",
"taint",
"untaint"
]
arguments = [
"-lock-timeout=20m"
]
}
}
}
The configuration in a .terragrunt
file is identical to that of the terraform.tfvars
file, except the
terraform.tfvars
file requires you to wrap that configuration in a terragrunt = { ... }
block.
For example, if this is your .terragrunt
file:
include {
path = "${find_in_parent_folders()}"
}
dependencies {
paths = ["../vpc", "../mysql", "../redis"]
}
The equivalent terraform.tfvars
file is:
terragrunt = {
include {
path = "${find_in_parent_folders()}"
}
dependencies {
paths = ["../vpc", "../mysql", "../redis"]
}
}
To migrate, all you need to do is:
- Copy all the contents of the
.terragrunt
file. - Paste those contents into a
terragrunt = { ... }
block in aterraform.tfvars
file. - Delete the
.terragrunt
file.