Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you pass blocks as variables in Terraform, referencing the type of a resource's nested block contents?

Tags:

terraform

hcl

I am trying to build in Terraform a Web ACL resource https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl

This resource has the nested blocks rule->action->block and rule-> action->count

I would like to have a variable which's type allows me to set the action to either count {} or block{} so that the two following configurations are possible:

With block:

resource "aws_wafv2_web_acl" "example" {
  ...

  rule {
   ...

    action {
      block {}
    }

   ...
}

With count:

resource "aws_wafv2_web_acl" "example" {
  ...

  rule {
   ...

    action {
      count {}
    }

   ...
}

I can achieve this result with a boolean variable and dynamic blocks in a very non-declarative way so far.

My question is, can the type of a variable reference the type of a nested block, so that the content of the nested block can be passed in a variable?

What I am trying to achieve is something that would look similar to this (non working syntax):

resource "aws_wafv2_web_acl" "example" {
  ...

  rule {
   ...

    action = var.action_block

   ...
  } 
}
variable "action_block" {
  description = "Action of the rule"
  type         = <whatever type is accepted by aws_wafv2_web_acl->rule->action>
}

so that it can be passed down in a similar manner to this

module "my_waf" {
  source                   = "../modules/waf"
  action_block {
    block {}
  }
}

For reference, what I am trying to avoid:

    dynamic "action" {
      for_each = var.block  ? [] : [1]
      content {
        count {}
      }
    }

    dynamic "action" {
      for_each = var.block ? [1] : []
      content {
        block {}
      }
    }

Thank you so much for your help!

like image 421
Patricio Marrone Avatar asked Jan 30 '26 02:01

Patricio Marrone


1 Answers

The only marginal improvement I can imagine is to move the dynamic blocks one level deeper, to perhaps make it clear to a reader that the action block will always be present and it's the count or block blocks inside that have dynamic behavior:

  action {
    dynamic "count" {
      for_each = var.block ? [] : [1]
      content {}
    }
    dynamic "block" {
      for_each = var.block ? [1] : []
      content {}
    }
  }

There are some other ways you could formulate those two for_each expressions so that the input could have a different shape, but you'll need to write out a suitable type constraint for that variable yourself which matches whatever conditions you want to apply to it.

like image 82
Martin Atkins Avatar answered Feb 01 '26 09:02

Martin Atkins



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!