Migrating from terragrunt - Root modules?

Just became aware of terraspace and reading up on it. Looks very compelling and maybe addresses some of the non DRY struggles we are running into with terragrunt. Thanks for creating and sharing this.

I was going to try a little POC and see what it would take to migrate one of our terragrunt projects to terraspace – given they are both terraform under the covers, if I could wire things up correctly and point terraspace to our existing s3 tfstate buckets, then in theory I should be able to evaluate a project and see if terrform shows no changes when applying a plan.

There is at least one thing I can’t quite figure out though reading the documentation.

With terragrunt, we have terragrunt hcl files that basically look like this:


terraform {
  source = "git@github.com:path/to/project//modules/my/module"
  ...
}

In the terraform stanza, we point to a remote module which terragrunt then retrieves and it becomes our “root” terraform module.

Is it possible in terraspace to point to a remote module as a projects root module? I see that that I can define a terraform.tf file and then reference modules in it, but they then act as child modules. This will then conflict with the original terraform state in s3 created via terragrunt.

I’m hoping to validate that a migration to terraspace from terragrunt would not involve a big in managing our projects terraform remote state.

Any ideas on how to manage this in terraspace?

Thanks in advance.

Sure. To make it so that terrraform/terraspace does not create the extra hierarchical resource name structure, don’t use the terraform module keyword. This is a terraform, not a terraspace thing. The module keyword always creates a hierarchical namespace in the resource name.

Existing Terragrunt Project

Let’s say your current terraform project is something like this:

dev/mysql/terragrunt.hcl

terraform {
  source = "git@github.com:org/repo//modules/my/module"
}

And in the github repo source

main.tf

resource "aws_db_instance" "default" {
  allocated_storage    = 10
  engine               = "mysql"
  engine_version       = "5.7"
  instance_class       = "db.t3.micro"
  # ...
}

With terragrunt, like you mentioned, it creates a flattened resource name. Running:

$ terragrunt apply
...
# aws_db_instance.default will be created
...

The resource name is aws_db_instance.default

This is because the terragrunt terraform keyword is a custom HCL syntax added by terragrunt. It works differently from the terraform module native keyword.

Instead, the native keyword always produces extra hierarchy in the resource name. Something like:

module.default.aws_db_instance.default

Hence, as you see, the terraform state “changes” since the resource names are different.

New Terraspace Project

To keep the same flattened resource names, you cannot use the terraform module keyword.

Instead, your current reusable github repo modules become terraspace stacks. It can look something like this:

app/stacks/db/main.tf

resource "aws_db_instance" "default" {
  allocated_storage    = 10
  engine               = "mysql"
  engine_version       = "5.7"
  instance_class       = "db.t3.micro"
  # ...
}

Terrafile

mod "db", source: "git@github.com:org/repo", export_to: "app/stacks", subfolder: "modules/my/module"

seed/tfvars/stacks/db/dev.tfvars

length = 1

Running the command:

terraspace bundle
terraspace up db

As long as the statefile is configured to match your existing terragrunt backend.tf, terraform produces a plan with no changes. Starter example:

config/terraform/backend.tf

terraform {
  backend "s3" {
    bucket         = "REPLACE_WITH_YOUR_BUCKET"
    key            = "<%= expansion(':ENV/:MOD_NAME/terraform.tfstate') %>"
    region         = "<%= expansion(':REGION') %>"
    encrypt        = true
    dynamodb_table = "REPLACE_WITH_YOUR_TABLE"
  }
}

The key is that terraform module will always add hierarchical info, so we cannot use it to keep the terragrunt flattened resource name.

For an even more detailed explanation with example projects, see this repo: boltops-tools/terragrunt-vs-terraform-reusable-module

Thanks. It sound like what I’m looking for is to reference the remote repo exporting it as a stack in terraspaces’ terrafile. This is likely something I missed from the terraspace doc taking it all in at once the first time. I will try to experiment with in the next day or so.

Cheers.

Thanks for this post. It inspired these videos :tada: