terragrunt icon indicating copy to clipboard operation
terragrunt copied to clipboard

Consider a builtin generator for single resource terraform modules

Open yorinasub17 opened this issue 2 years ago • 6 comments

Currently, if you want to deploy just a single resource, terragrunt is fairly overkill since you need to wrap the resource in a terraform module, with all the vars and outputs flowing through. This is a feature request for a special terragrunt block that can autogenerate a single resource module that flows through just the inputs that are specified, and outputs as well.

A crude snippet for this might be:

terraform {
  resource {
    source = "null_resource"
    name = "foo"
    outputs = ["id", "triggers", ... etc]
  }
}

inputs = {
  triggers = "hello-world"
}

which would generate the terraform module:

variable "triggers" {}

resource "null_resource" "foo" {
  triggers = var.triggers
}

output "id" {
  value = null_resource.foo.id
}

output "triggers" {
  value = null_resource.foo.triggers
}

However, there are a few open questions that make this difficult to jump on:

  • How to handle the type field for input variables?
  • How to handle sub blocks?

yorinasub17 avatar Jun 14 '22 18:06 yorinasub17

One workaround I just came up with is to use generate blocks to dynamically create the single resource module. The following should work on any modern terragrunt version that supports generate:

locals {
  foo_str = "hello world"
}

generate "resource" {
  path      = "main.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF
resource "null_resource" "foo" {
  triggers = {
    foo = "${local.foo_str}"
  }
}

output "id" {
  value = null_resource.foo.id
}
EOF

}

This approach is a bit more verbose, but has the flexibility of being able to handle sub block inputs since you can generate them in the template. You can also take advantage of for/if directives to do some complex logic as well.

yorinasub17 avatar Jun 15 '22 02:06 yorinasub17

@yorinasub17 can't we just have in a folder:

terragrunt.hcl:

include "root" {
  path   = find_in_parent_folders()
  expose = true
}

inputs = {
  foo_str = "bar"
}

null.tf

variable "foo_str" {
  type = string
}

resource "null_resource" "foo" {
  triggers = {
    foo = var.foo_str
  }

I noticed if you don't add source to terragrunt.hcl it just reads *.tf files from directory. Is it expected behaviour?

okgolove avatar Aug 18 '22 12:08 okgolove

One workaround I just came up with is to use generate blocks to dynamically create the single resource module. The following should work on any modern terragrunt version that supports generate:

locals {
  foo_str = "hello world"
}

generate "resource" {
  path      = "main.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF
resource "null_resource" "foo" {
  triggers = {
    foo = "${local.foo_str}"
  }
}

output "id" {
  value = null_resource.foo.id
}
EOF

}

This approach is a bit more verbose, but has the flexibility of being able to handle sub block inputs since you can generate them in the template. You can also take advantage of for/if directives to do some complex logic as well.

I know this is an older issue, but I am trying to get my feet wet with Terragrunt finally. This works decently well, but I'm a little confused on how to then use attributes/outputs from this later on in my terragrunt.hcl inputs. In other words, how would I use output.id later on in terragrunt.hcl?

bigjew92 avatar Jan 13 '23 20:01 bigjew92

I know this is an older issue, but I am trying to get my feet wet with Terragrunt finally. This works decently well, but I'm a little confused on how to then use attributes/outputs from this later on in my terragrunt.hcl inputs. In other words, how would I use output.id later on in terragrunt.hcl?

I have the same question :)

stdmje avatar Mar 13 '23 08:03 stdmje