Skip to content

[Feature Request] Better support usage of history when leveraging terragrunt #200

@rtizzy

Description

@rtizzy

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"
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions