terragrunt icon indicating copy to clipboard operation
terragrunt copied to clipboard

Add function for getting Terraform working directory

Open GergelyKalmar opened this issue 3 years ago • 11 comments

It would be great to have a get_terraform_dir() function which returns the path to the directory in which the Terraform commands are run (it is usually something like ./.terragrunt-cache/xxx/yyy).

I would need this value in a locals block for constructing relative paths. I tried run_cmd("pwd") but that actually seems to be equivalent to get_terragrunt_dir(). Is there perhaps another way of obtaining this already?

GergelyKalmar avatar Sep 20 '22 09:09 GergelyKalmar

It seems that the WorkingDir entry in terragrunt-info does return what I would need, however, I can't really seem to find a way to get this value in a terragrunt.hcl file.

GergelyKalmar avatar Sep 20 '22 09:09 GergelyKalmar

What's the specific use case here? I believe path_relative_to_include() is what you need, as that should get you what WorkingDir gives you (the counterpart being path_relative_from_include(). Although that does not line up with the .terragrunt-cache/ dir you mentioned, so not sure this is what you want?

pconstantine avatar Sep 30 '22 18:09 pconstantine

I don't think that would work because my setup is roughly as follows:

~/.terragrunt/commons.hcl

locals {
  ...
  working_dir = ".terragrunt-cache/config_hash/module_hash"
}
...

~/Projects/some-project/terragrunt.hcl

include "commons" {
  path = pathexpand("~/.terragrunt/commons.hcl")
}

The commons.hcl file essentially contains my common provider and remote state configuration (and a few other things) which I then simply include in all of my projects. What I need is the relative path from terragrunt_dir() to the WorkingDir or an absolute path to WorkingDir (and not the path between ~/.terragrunt/commons.hcl and ~/Projects/some-project/terragrunt.hcl).

The specific use case is that I want to modify module sources in Terraform files before running Terraform (I do that via a before_hook) so that instead of pointing to a remote source they point to a local path, for which I need to find out the relative path between the local checkout of a module source and the WorkingDir. I know the paths to the local module sources but I can't really get the WorkingDir via any of the existing functions in Terragrunt, I think.

As said, if I run terragrunt terragrunt-info then I get something similar to this:

{
  "ConfigPath": "/home/user/Projects/some-project/terragrunt.hcl",
  "DownloadDir": "/home/user/Projects/some-project/.terragrunt-cache",
  "IamRole": "",
  "TerraformBinary": "terraform",
  "TerraformCommand": "terragrunt-info",
  "WorkingDir": "/home/user/Projects/some-project/.terragrunt-cache/EmQr60XXXCYgt9Qfni-4fHZU/F62jYYYnH_hVGDEN2pTYiMsg"
}

where WorkingDir is exactly what I would need, just inside ~/.terragrunt/commons.hcl.

GergelyKalmar avatar Oct 01 '22 10:10 GergelyKalmar

I just noticed that the working directory is sometimes the same as get_terragrunt_dir() (in particular when there are no remote configurations specified, see https://terragrunt.gruntwork.io/docs/features/caching), which makes this feature even more important.

GergelyKalmar avatar Oct 04 '22 09:10 GergelyKalmar

my usecase would be to access an image file to use in the gitlab_group resource as avatar with a relative path so that the path stays the same for all developers. the file is located in the project root directory in an assets folder.

file structure reduced to the relevant files/directories:

├── .terraform.d
│   └── .terragrunt-cache
│       └── accounts
│           └── production
│               └── gitlab
│                   └── SgKLvr5BkpwOBF27O_KMq4ZY5O0
│                       └── JFRlN212e_19ZPmP_aI4z1wvWck
│                           ├── .terragrunt-source-manifest
│                           ├── .terragrunt-source-version
│                           ├── gitlab
│                           │   ├── .terraform
│                           │   ├── .terraform.lock.hcl
│                           │   ├── .terragrunt-module-manifest
│                           │   ├── .terragrunt-source-manifest
│                           │   ├── README.md
│                           │   ├── _backend.tf
│                           │   ├── main.tf
│                           │   ├── terragrunt.hcl
│                           │   └── variables.tf
├── accounts
│   └── production
│       └── gitlab
│           └── terragrunt.hcl
├── assets
│   └── gitlab
│       └── logo.png
└── modules
    └── gitlab
        ├── main.tf
        └── variables.tf

it would be possible to access the file with an absolute path with the get_repo_root() function but this stores the absolute file from a specific developer in the states file. so if the next developer checks out the project in a different folder and runs the terraform command we get a new directory.

the paths i get from all the available functions don't help

debug_paths = {
      + get_original_terragrunt_dir = "/project/accounts/production/gitlab"
      + get_parent_terragrunt_dir   = "/project/accounts"
      + get_path_from_repo_root     = "accounts/production/gitlab"
      + get_path_to_repo_root       = "../../../"
      + get_repo_root               = "/project"
      + get_terragrunt_dir          = "/project/accounts/production/gitlab"
      + path_relative_from_include  = "../.."
      + path_relative_to_include    = "production/gitlab"
    }

get_path_to_repo_root()/assets/gitlab/logo.png and path_relative_from_include()/assets/gitlab/logo.png result in a file not found as the real working directory is the cache directory which i moved to plugin_cache_dir = "$GIT_REPO_ROOT/.terraform.d/plugin-cache" for the sake of a single location and not polluting all my source directories. this results in the path .terraform.d/.terragrunt-cache/accounts/production/gitlab/SgKLvr5BkpwOBF27O_KMq4ZY5O0/JFRlN212e_19ZPmP_aI4z1wvWck/gitlab. to access the logo from main.tf in the resoucre gitlab_group i would need 8 levels of "up" ../../../../../../../../ which is not provided by a function. so the request for a function relative_from/to_working_dir() looks valid and quite important to me.

i tried to use the path functions without and partly with the double slash //.

locals {
  config_defaults = {
    debug_paths = {
      path_relative_to_include = "${path_relative_to_include()}//"
      path_relative_from_include = "${path_relative_from_include()}//"
      get_repo_root = "${get_repo_root()}//assets/gitlab"
      get_path_from_repo_root = "${get_path_from_repo_root()}//"
      get_path_to_repo_root = "${get_path_to_repo_root()}//assets/gitlab"
      get_terragrunt_dir = "${get_terragrunt_dir()}//"
      get_parent_terragrunt_dir = "${get_parent_terragrunt_dir()}//assets/gitlab"
      get_original_terragrunt_dir = "${get_original_terragrunt_dir()}//"
    }
  }
  config_gitlab = yamldecode(file("${get_repo_root()}/config/gitlab.yaml"))
}

workarounds:

  • use absolut path and ignore that there is a change output all the time for different developers
  • hardcode a variable containing the required "directory-ups"

c33s avatar Apr 11 '23 17:04 c33s

I have tried to use the new get_working_dir function, however, it seems to cause some sort of recursive error:

/home/redacted/.terragrunt/commons.hcl:43,44-60: Error in function call; Call to function "get_working_dir" failed:
/home/redacted/.terragrunt/commons.hcl:43,44-60: Error in function call; Call to function "get_working_dir" failed:
...

Note that the get_working_dir function is used in a file that is referred via the include mechanism (see https://github.com/gruntwork-io/terragrunt/issues/2283#issuecomment-1264322620, simply replace working_dir = get_working_dir() in locals).

GergelyKalmar avatar Nov 27 '23 19:11 GergelyKalmar