Terraform: Get the module name to inject it to other module from the path

I need to get the terraform parent module name from the path and then pass it as a variable to other module. Is it possible?. Example: From the module child1, it can access to the directory src/yaml in the module child2

Parent module:

module "parent" {
  source = "s3::https://s3.amazonaws.com/tf-modules-zip/child1.zip"
  some_variable = "foo"
}

Child1 module:

variable "some_variable" {
  type        = string
  description = "Any value"
}

locals {
  os_module_name = this.module.name
  path_to_yamls  = "${local.os_module_name}.child2/src/yaml"
}

module "child1" {
  source = "s3::https://s3.amazonaws.com/tf-modules-zip/child2.zip"
  some_variable = var.some_variable
  path_to_yaml_files = local.path_to_yamls
}

Child2 module:

variable "some_variable" {
  type        = string
  description = "Any value"
}

variable "path_to_yaml_files" {
  type        = string
  description = "Path to retrieve the yaml files"
}

locals {
  path_to_configs = var.path_to_yaml_files
  exclusions    = yamldecode(file("${local.path_to_configs}/exclusions.yaml"))
}

resource "null_resource" "child2" {
  local-exec { 
    interpreter = ["/bin/bash" ,"-c"],
    command = <<-EOT
      exec "command1 -yaml ${local.exclusions}"
      exec "command2 -var ${var.some_variable}"
    EOT
  }
}

Upvotes: 0

Views: 2281

Answers (1)

Yes, It's possible!. Just using the module path to extract the parent portion and then concatenate it to the child1 path.

ANSWER

Parent module:

main.tf

module "parent" {
  source = "s3::https://s3.amazonaws.com/tf-modules-zip/child1.zip" # <-- Calling the child1 module
  some_variable = "foo"                                             # <-- Assigning the foo value to some_variable
}

Child1 module:

child1.tf

variable "some_variable" {                                          # <-- Input variable
  type        = string
  description = "Any value"
}

locals {
  parent_module_name    = path.module != "." ? regex(".*/([^/]+)?", path.module)[0] : "."   ### <-- Extracting the parent module name from the current module path
  path_to_yamls         = "${path.module}/../${local.parent_module_name}.child1/src/yaml"   ### <-- Concatenating the parent module name with the child2 module path
}

module "child1" {
  source = "s3::https://s3.amazonaws.com/tf-modules-zip/child2.zip" # <-- Calling the child2 module
  some_variable = var.some_variable                                 # <-- Injecting the value of var.some_variable to the child2 module
  path_to_yaml_files = local.path_to_yamls                          # <-- Injecting the value of local.path_to_yamls to the child2 module
}

Child2 module:

child2.tf

variable "some_variable" {                                          # <-- Input variable
  type        = string
  description = "Any value"
}

variable "path_to_yaml_files" {                                     # <-- Input variable
  type        = string
  description = "Path to retrieve the yaml files"
}

locals {
  path_to_configs = var.path_to_yaml_files                                      # <-- Using the injected value in var.path_to_yaml_files from the child1 module
  exclusions    = yamldecode(file("${local.path_to_configs}/exclusions.yaml"))  # <-- Using the injected value in var.path_to_yaml_files from the child1 module
}

resource "null_resource" "child2" {
  local-exec { 
    interpreter = ["/bin/bash" ,"-c"],
    command = <<-EOT
      exec "command1 -yaml ${local.exclusions}"                     # <-- Using the injected value in var.path_to_yaml_files from the child1 module
      exec "command2 -var ${var.some_variable}"                     # <-- Using the injected value in var.path_to_yaml_files from the child1 module
    EOT
  }
}

Explanation:

When we do a "terraform init", the modules are downloaded in the parent path under this structure:

-[example]
   main.tf
 |--[.terraform]
    |--[modules]
       |--[parent]
            child1.tf
       |--[parent.child1]
            child2.tf
          |--[src]
             |--[yaml]
                  file1.yaml
                  file2.yaml
                  file3.yaml

Usig the "path.module" do the trick. It gets the module path from it's called. In this example, it's being called from child1 which has the name "parent". Then, the expression: "${path.module}/../${local.parent_module_name}.child1/src/yaml" tells to terraform that it has to go up a level and then go to the "parent.child1/src/yaml" directory after the interpolation of the "${local.parent_module_name}" variable which has the value "parent".

The advantage of this method is that the parent module name can be changed in the main.tf file and afer to do a "terraform init -upgrade", the directory structure takes the new value.

I hope this helps a lot!.

Upvotes: 2

Related Questions