Explanation of typical terragrunt usage
When using terragrunt, you will often have a single set of modules that are shared across environments with the difference between each environment being the parameters that are fed into the modules. Typically the folder structure is a reflection of the underlying infrastructure and terraform state.
Lets consider a contrived example of a typical terragrunt folder layout.
module_a and module_b can be assumed to be the same module call in each environment
- Our migration file will migrate from
module_a to module_b
├── env1
│ ├── module_a
│ │ ├── .tfmigrate
│ │ │ └── 20250117133204_example_migration.hcl
│ │ └── terragrunt.hcl
│ └── module_b
│ └── terragrunt.hcl
└── env2
├── module_a
│ ├── .tfmigrate
│ │ └── 20250117133204_example_migration.hcl
│ └── terragrunt.hcl
└── module_b
└── terragrunt.hcl
The issue
Lets assume we have the following config for tfmigrate
tfmigrate {
# Instruct tfmigrate to look for migrations in the `.tfmigrate` folder of the current dir
migration_dir = "./tfmigrate"
history {
# Configure the history bucket
storage "s3" {
bucket = "history-state-bucket"
region = "us-east-1"
key = "tfmigrate/history.json"
}
}
}
If we run the migrations in env1/module_a the history.json for migrations will contain something like this.
{
"version": 1,
"records": {
"20250117133204_example_migration.hcl": {
"type": "multi_state",
"name": "example_migration",
"applied_at": "2025-01-17T13:20:23.085857+01:00"
}
}
}
If we go to the env2/module_a folder and attempt to leverage a history based migration (where we have not yet ran migrations), it will indicate that all migrations have been run.
╰─ TFMIGRATE_EXEC_PATH=terragrunt tfmigrate plan --config ../../../../../../.tfmigrate.hcl
2025/01/17 13:24:39 [INFO] [runner] no unapplied migrations
Possible solutions
Allow arbitrary definition of additional migration keys.
I think this is a solution that could be flexible and would resolve this issue.
Assuming it is possible read the underlying Terraform variables/parameters, allow users to define via .tfmigrate.hcl or command line flags additional keys that should be included as part of the history.json keys.
Example
This isn't the best example and the exact way it's handled can be improved.
We have a variable in Terraform that indicates the current environment, var.environment.
In env1 the value will be env1 and in env2 the value will be env2.
Our .tfmigrate.hcl might contain something like
tfmigrate {
migration_dir = "./tfmigrate"
history {
additional_keys = [
"environment"
]
# Configure the history bucket
storage "s3" {
bucket = "history-state-bucket"
region = "us-east-1"
key = "tfmigrate/history.json"
}
}
}
Which might result in something like this in the history file
{
"version": 1,
"env1": {
"records": {
"20250117133204_example_migration.hcl": {
"type": "multi_state",
"name": "example_migration",
"applied_at": "2025-01-17T13:20:23.085857+01:00",
"state_path": "$PATHTOSTATEOFTHEINITIALMODULE"
}
}
}
}
If we run this same thing in env2 it would see that there is no key for env2, then run the migration as expected.
Include a fixed key
Include an additional fixed key in the migration for something like the folder_path or state_path
Example
{
"version": 1,
"records": {
"20250117133204_example_migration.hcl": {
"type": "multi_state",
"name": "example_migration",
"applied_at": "2025-01-17T13:20:23.085857+01:00",
"state_path": "$PATHTOSTATEOFTHEINITIALMODULE"
}
}
}
Explanation of typical
terragruntusageWhen using
terragrunt, you will often have a single set of modules that are shared across environments with the difference between each environment being the parameters that are fed into the modules. Typically the folder structure is a reflection of the underlying infrastructure and terraform state.Lets consider a contrived example of a typical
terragruntfolder layout.module_aandmodule_bcan be assumed to be the same module call in each environmentmodule_atomodule_bThe issue
Lets assume we have the following config for
tfmigrateIf we run the migrations in
env1/module_athehistory.jsonfor migrations will contain something like this.If we go to the
env2/module_afolder and attempt to leverage a history based migration (where we have not yet ran migrations), it will indicate that all migrations have been run.Possible solutions
Allow arbitrary definition of additional migration keys.
I think this is a solution that could be flexible and would resolve this issue.
Assuming it is possible read the underlying Terraform variables/parameters, allow users to define via
.tfmigrate.hclor command line flags additional keys that should be included as part of thehistory.jsonkeys.Example
This isn't the best example and the exact way it's handled can be improved.
We have a variable in Terraform that indicates the current environment,
var.environment.In
env1the value will beenv1and inenv2the value will beenv2.Our
.tfmigrate.hclmight contain something likeWhich might result in something like this in the history file
If we run this same thing in env2 it would see that there is no key for env2, then run the migration as expected.
Include a fixed key
Include an additional fixed key in the migration for something like the
folder_pathorstate_pathExample