Reece
Reece

Reputation: 8108

Can a map be used for values in a resource configuration block?

Can maps be used directly as resource configurations in terraform?

I have a map of repositories in yaml, like this:

repo_defaults:
  auto_init: true
  delete_branch_on_merge: true
  has_discussions: true
  has_downloads: true
  has_issues: true
  has_projects: false
  has_wiki: true
  visibility: "public"
  vulnerability_alerts: true

repos:
  anyvar:
    homepage_url: "https://github.com/biocommons/anyvar"
    description: |
      [in development] Proof-of-Concept variation translation, validation, and registration service
    topics:
      - bioinformatics
      - genome-analysis
      - variant-analysis
      - variation

My goal is to merge repo_defaults and the individual repo entries, roughly like this:

# Doesn't work
resource "github_repository" "repo" {
  for_each = local.config.repos
  merge([repo_defaults, each.value])
}

That is, I specifically want to avoid having to write lines like

name = each.key
description = each.value.description
⋮

Is it possible to merge maps and to avoid specifying each configuration item explicitly?

Upvotes: 2

Views: 623

Answers (1)

Martin Atkins
Martin Atkins

Reputation: 74574

The arguments directly inside a resource block and inside nested blocks inside a resource block are all individual language elements and there isn't a single value covering the entire content of the block.

Therefore there is no way to dynamically define resource attributes as a whole from a single mapping value. The only way to define resource attributes is to write them out explicitly.

However, you can still construct a flat map of objects to use to define your repositories, so that your argument definitions will just be simple references to attributes of the objects and you won't need to write a separate conditional expression for each argument:

locals {
  repos = tomap({
    for k, obj in local.config.repos :
    k => merge(local.config.repo_defaults, obj)
  })
}

resource "github_repository" "repo" {
  for_each = local.repos

  name                   = each.key
  description            = each.value.description
  auto_init              = each.value.auto_init
  delete_branch_on_merge = each.value.delete_branch_on_merge
  has_discussions        = each.value.has_discussions
  has_downloads          = each.value.has_downloads
  has_issues             = each.value.has_issues
  has_projects           = each.value.has_projects
  has_wiki               = each.value.has_wiki
  visibility             = each.value.visibility
  vulnerability_alerts   = each.value.vulnerability_alerts
  homepage_url           = each.value.homepage_url
}

There is no way to avoid actually defining the configuration arguments for your resources. The above is the least possible configuration to write to define this.

Upvotes: 2

Related Questions