Conditional block inside a conditional block?

I’m using Terraform to manage a Github organization. We have a “common repository” module that we use to ensure our repositories share a common configuration. I would like to add support for configuring GitHub pages, which requires support for the pages element, which looks like this:

  pages {
    build_type = "legacy"
    cname = "example.com"
    source {
      branch = "master"
      path   = "/docs"
    }
  }

Everything is optional. In particular, source is only required if build_type == "legacy" || build_type == null, and the entire pages block can be omitted. I couldn’t figure out how to make source conditional, so I ended up splitting this into two dynamic blocks like this:

  # There are two `dynamic "pages"` blocks here to account for the fact that `source` is only required
  # if `build_type` is "legacy". The `for_each` at the top of each block will only enable the block when
  # the necessary conditions are met.
  dynamic "pages" {

    # enable this block if `pages` is not null and `build_type` is "legacy" (or null)
    for_each = var.pages == null ? [] : var.pages.build_type == "legacy" || var.pages.build_type == null ? ["enabled"] : []

    content {
      source {
        branch = var.pages.source.branch
        path   = var.pages.source.path
      }

      cname      = var.pages.cname
      build_type = var.pages.build_type
    }
  }

  dynamic "pages" {

    # enable this block if `pages` is not null and `build_type` is "workflow"
    for_each = var.pages == null ? [] : var.pages.build_type == "workflow" ? ["enabled"] : []

    content {
      cname      = var.pages.cname
      build_type = var.pages.build_type
    }
  }

Where I’ve defined the pages variable in the module like this:

variable "pages" {
  description = "Configuration for github pages"
  type = object({
    source = optional(object({
      branch = string
      path   = string
    }))
    build_type = optional(string, "legacy")
    cname      = optional(string)
  })
  default = null
}

Is there a better way to approach this?

1 Like