#terragrunt (2020-08)

terragrunt

Terragrunt discussions

Archive: https://archive.sweetops.com/terragrunt/

2020-08-02

barak avatar

Howdy! is there a way to migrate terrgrunt into “raw” terraform code?

loren avatar

Go look in the terragrunt cache directory. That has the terraform code you reference in the terragrunt config, and you can run terraform directly from that cache

loren avatar

Also, follow this pr for the release of the debug feature, which will simplify this further… https://github.com/gruntwork-io/terragrunt/pull/1263

Implement minimal debug feature by yorinasub17 · Pull Request #1263 · gruntwork-io/terragrunt

This takes #1137 and reduces the scope to just outputting a workable tfvars file. This should be the minimal increment for a usable debug command that should significantly improve status quo.

barak avatar

Thanks! is the cache directory created on the plan phase or apply phase?

loren avatar

init

joshmyers avatar
joshmyers

Yeah, re write it in not as DRY code.

1
barak avatar

any way to do so automatically?

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

For context, @barak is with bridgecrew. Guessing they are seeking ways to audit terragrunt code.

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

So HCL is all converts me to JSON. I would look at the go modules from HashiCorp for that. Terragrunt uses HCL configurations so those are also convertible to JSON.

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

Once it’s in JSON you can operate on it.

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

So Helmfile/helm support flags to show the rendered configs. I think you can do something similar too by looking in the gruntcache folder

1
loren avatar

Also, follow this pr for the release of the debug feature, which will simplify this further… https://github.com/gruntwork-io/terragrunt/pull/1263

loren avatar

Maybe also consider some creative use of the new terraform cdk?

joshmyers avatar
joshmyers

It would totally depend on the features of Terragrunt you are using

joshmyers avatar
joshmyers

e.g. did you buy into the sops functionality? the depedencies blocks between modules? using env vars?

2020-08-03

2020-08-18

Joe Presley avatar
Joe Presley

I’m new to terragrunt and have taken over a code base created by someone else. I have a terragrunt.hcl file with a terraform source block like this

terraform {
  source = "${get_terragrunt_dir()}/../../modules/datapipelines-infra"
}
Joe Presley avatar
Joe Presley

I’d like to create another module and call it in the same terragrunt.hcl file. Can I create another terraform block with a different source?

Joe Presley avatar
Joe Presley

I’ve tried googling and looking at the documentation but haven’t had any luck finding an answer.

David avatar

In terragrunt, you only use one module per terragrunt.hcl file.

Theres an Issue tracking an idea that would allow having multiple modules per file, but it is not a current feature: https://github.com/gruntwork-io/terragrunt/issues/759

RFC: single terragrunt.hcl per environment? · Issue #759 · gruntwork-io/terragrunt

Current state The current practice for using Terragrunt is to create one folder for each module and put a terragrunt.hcl file in it. You also have one terragrunt.hcl at the root of each environment…

Joe Presley avatar
Joe Presley

Cool. Thanks for the link and also the info that what I was looking for isn’t possible now.

2020-08-19

jdtobe avatar
jdtobe
05:40:28 PM

@jdtobe has joined the channel

2020-08-25

Callum Robertson avatar
Callum Robertson

hey terragrunt people

Callum Robertson avatar
Callum Robertson

is there any way to include a common templates in the live-infrastructure to modules?

Callum Robertson avatar
Callum Robertson
├── functions
│   ├── function1
│   │   └── terragrunt.hcl
│   ├── function2
│   │   └── terragrunt.hcl
├── project.tfvars
├── resolvers
│   ├── resolver1
│   │   └── terragrunt.hcl
│   └── resolver2
│       └── terragrunt.hcl
└── templates
Callum Robertson avatar
Callum Robertson

e.g. can I copy all the contents of the templates dir into the module dir when I call the module?

loren avatar

if your module is already assuming a path to the templates dir, why not just pass it in as a variable?

Callum Robertson avatar
Callum Robertson

sorry I don’t follow mate - can you give me an example?

loren avatar

your module must be hardcoding/expecting the path templates or it doesn’t make sense to copy the directory to the module dir

loren avatar

so, instead of hardcoding, just expose the path as a variable (with a default of templates if you like)

Callum Robertson avatar
Callum Robertson

yeah I understand, unfortunately the way we designed the module won’t allow for this and we don’t want to update our appsync templates in each module

loren avatar

then, pass the value for the path using terragrunt. then you do not need to copy the templates anywhere

Callum Robertson avatar
Callum Robertson

I fixed it using the following:

Callum Robertson avatar
Callum Robertson
terraform {
  source = "[email protected]:Callumccr/tf-mod-aws-appsync-resolver?ref=master"

  before_hook "copy_templates" {
    commands     = get_terraform_commands_that_need_vars()
    execute      = ["cp", "-a", "${get_parent_terragrunt_dir()}/humn-core/eu-west-1/dev/appsync/templates/.", "${get_terragrunt_dir()}/templates/"]
    run_on_error = true
  }
}
Callum Robertson avatar
Callum Robertson

that seems to work well!

Callum Robertson avatar
Callum Robertson

I can’t pass the value of the template either due to variable interpolation

loren avatar

yes, a before_hook is the other way. you’ll need to update your .gitignore also, of course, otherwise you’ll accidentally commit them

Callum Robertson avatar
Callum Robertson

@loren I had to have the templates in the module dir because the module has the following logic:

Callum Robertson avatar
Callum Robertson
  request_template  = file("${path.module}/templates/${each.value.request_template}")
  response_template = file("${path.module}/templates/${each.value.response_template}")
Callum Robertson avatar
Callum Robertson

if I use the file() in the terragrunt.hcl and pass it as a variable, the interpolation of the content causes the resource to fail

Callum Robertson avatar
Callum Robertson

loren avatar

i’m not saying to use file() in terragrunt.hcl

loren avatar
  request_template  = file("${var.template_dir}/${each.value.request_template}")
  response_template = file("${var.template_dir}}/${each.value.response_template}")
Callum Robertson avatar
Callum Robertson

ah…

loren avatar

the modules are making a bad assumption that the templates directory is local to the module

Callum Robertson avatar
Callum Robertson

I didn’t think to try that

loren avatar

but the module is not itself actually providing the templates

Callum Robertson avatar
Callum Robertson

yeah I didn’t think I could use relative paths outside what was local to the module

loren avatar

with terragrunt, you would provide the full path, not a relative path…

loren avatar

but you can get most of the same behavior in the module (when using the module directly as a root config), by setting the default value of the variable to templates

loren avatar

you would just override the default value with terragrunt to pass the directory that actually contains your templates

Callum Robertson avatar
Callum Robertson

worked very well!

1
Callum Robertson avatar
Callum Robertson
template_location = "${get_parent_terragrunt_dir()}/humn-core/eu-west-1/dev/appsync/templates"
Callum Robertson avatar
Callum Robertson

as part of my terragrunt.hcl

loren avatar

nice

Callum Robertson avatar
Callum Robertson

thanks @loren - that’s much cleaner that doing a cp -a

loren avatar

trust me, i’ve been there, done exactly that

2020-08-26

natalie avatar
natalie
05:12:45 PM

@natalie has joined the channel

2020-08-27

Makeshift (Connor Bell) avatar
Makeshift (Connor Bell)

I think I’m really misunderstanding how --terragrunt-source is meant to work. In my case I have a format like this:

terragrunt/
  ├── terragrunt.hcl
modules/
  ├── module_1/
  └── child_module/

module_1 references child_module via source = ../child_module. How do I make that relative pathing work?

2020-08-31

moos3 avatar

so I have the following as a env.yaml

subnets: [  {
    subnet_name: "us-east1-dev-compute",
    subnet_region: "us-east1",
    cidr: 10.66.0.0/16,
    subnet_private_access: true,
    subnet_flow_logs: "true",
    subnet_flow_logs_interval: "INTERVAL_15_MIN",
    subnet_flow_logs_sampling: 0.5,
    subnet_flow_logs_metadata: "INCLUDE_ALL_METADATA",
    subnet_secondary_ranges: {
       pods: [{
          range_name: "us-east1-dev-pods",
          ip_cidr_range: "10.67.0.0/17"
        }],
        services: [{
          range_name: "us-east1-dev-services",
          ip_cidr_range: "10.67.128.0/17"
        }],
    },
  },]

in my module i’m doing this

locals {
  subnets = {
    for x in var.subnets :
    "${x.subnet_region}/${x.subnet_name}" => x
  }
}


/******************************************
	Subnet configuration
 *****************************************/
resource "google_compute_subnetwork" "subnetwork" {
  for_each                 = local.subnets
  name                     = each.value.subnet_name
  ip_cidr_range            = each.value.cidr
  region                   = each.value.subnet_region
  private_ip_google_access = lookup(each.value, "subnet_private_access", "false")
  dynamic "log_config" {
    for_each = lookup(each.value, "subnet_flow_logs", false) ? [{
      aggregation_interval = lookup(each.value, "subnet_flow_logs_interval", "INTERVAL_5_SEC")
      flow_sampling        = lookup(each.value, "subnet_flow_logs_sampling", "0.5")
      metadata             = lookup(each.value, "subnet_flow_logs_metadata", "INCLUDE_ALL_METADATA")
    }] : []
    content {
      aggregation_interval = log_config.value.aggregation_interval
      flow_sampling        = log_config.value.flow_sampling
      metadata             = log_config.value.metadata
    }
  }
  network     = var.network_self_link
  project     = var.host_project_id
  description = lookup(each.value, "description", null)
  secondary_ip_range = [
    for i in range(
      length(
        contains(
        keys(var.secondary_ranges), each.value.subnet_name) == true
        ? var.secondary_ranges[each.value.subnet_name]
        : []
    )) :
    var.secondary_ranges[each.value.subnet_name][i]
  ]
}

Trying for the life me to figure out why its saying this

Error: Invalid value for input variable

The environment variable TF_VAR_subnets does not contain a valid value for
variable "subnets": element 0: element "subnet_secondary_ranges": string
required.
loren avatar

what’s your variable definition of var.subnets? looks vaguely like the object type definition might be off?

    keyboard_arrow_up