terragrunt icon indicating copy to clipboard operation
terragrunt copied to clipboard

Terragrunt needs to support the same relative paths terraform supports in modules

Open queglay opened this issue 2 years ago • 5 comments

In Terraform if I reference any module where that module may have a defined source with something like:

module "iam_policies_s3_read_write" {
  source = "../../modules/aws-iam-policies-s3-read-write"

...Its fine. But in terragrunt, if I have a second reference to the module defined above elsewhere, suddenly that relative path is no longer a valid way of writing Terraform code. The current workaround suggests to instead change the way you would normally write your module to...

module "iam_policies_s3_read_write" {
  source = "github.com/firehawkvfx/firehawk-main.git//modules/aws-iam-policies-s3-read-write"

and then you can use in the args to run Terragrunt with something like:

--terragrunt-source-map github.com/firehawkvfx/firehawk-main.git=$TF_VAR_firehawk_path

This might achieve similar behaviour to a relative path, but it is not good because:

  • It means the module now solely relies on terragrunt to get the relative ref to work, and the user must remember to use the right arg. Terraform usage alone will be inefficient, downloading the source, and its not garunteed to be exactly the same data that we would have in a relative ref.
  • And if we start using version tags in the original module, then we have to maintain these. In Terraform alone this is not required. The relative refs simply work.
  • Terragrunt is forcing us to change the way we write a terraform module and it breaks the possibility of that module working with a relative ref.

I hope there's another solution to this!

queglay avatar Jun 04 '22 12:06 queglay

Relative paths in Terraform modules should still work with Terragrunt, but it requires you to have the // in the terraform.source property of the terragrunt.hcl file.

You might be running into an edge case though, since I am not 100% sure what you mean by:

if I have a second reference to the module defined above elsewhere, suddenly that relative path is no longer a valid way of writing Terraform code.

Do you have a minimum reproducible open source snippet we can use to investigate this?

yorinasub17 avatar Jun 06 '22 14:06 yorinasub17

I'll try and layout something equivalent to my scenario.

Where "modules", and "usage" are seperate git submodules in the repo "main", this project layout should reproduce the issue:

main/modules/module_a main/modules/module_b

main/modules/module_b.tf:

resource "module" "module_a" {
    source = "../module_a"
}

main/usage/usage_a/terragrunt.tf

terraform {
  source = "../../modules/module_b"
}

If executing terragrunt from the path main/usage, usage_a will not succeed in finding a relative ref to module_a from module_b. module_b if running in main alone, will have no problem. The current workaround is to replace all relative refs with git references in all modules and use --terragrunt-source-map to redirect the git repos to paths on disk.

This problem doesn't exist if the depth of the reference is deeper.

queglay avatar Jun 07 '22 07:06 queglay

Hi, I was wondering if will be possible to use path relative from root of git repository, through function get_repo_root, like:

terraform {
  source = "${get_repo_root()}/modules/module_b"
}

denis256 avatar Jun 07 '22 13:06 denis256

Ill try this and get back to you.

queglay avatar Jun 20 '22 03:06 queglay

Oh actually this cannot work because the problem is with terraform relative refs

resource "module" "module_a" {
    source = "../module_a"
}

...And such functions are not allowed.

main/usage/usage_a/terragrunt.tf can find the top level of the module, but the contents of that module refering to another module (module_b -> module_a) with relative refs outside are no longer an option/functional in terragrunt, but they are fine with pure terraform.

queglay avatar Jun 20 '22 03:06 queglay

Just tested the TERRAGRUNT_SOURCE_MAP behavior:

  • it is only applied by terragrunt to determine which folder tree to copy terraform configuration from towards its cache. It is not applied to any module reference inside your terraform configuration

In order to get full relative path support in your terraform configuration:

  • you could fake the stack by introducing a symbolic name like "local_repo" and then specify your target like source = "local_repo//myentrypoint" inside terragrunt hcl
  • Provide TERRAGRUNT_SOURCE_MAP with local_repo=/path/to/your/repo
  • terragrunt then copies the full local repo to its cache
  • terraform will be able to resolve all relative paths as terraform is run in the cache dir where the full repo was copied to

Would be great if this behavior could be opted in by default. As now people have to pass TERRAGRUNT_SOURCE_MAP to terragrunt plan. Or is there a way to specify this behavior in terragrunt hcl?

cveld avatar Dec 05 '23 04:12 cveld