terraform

Copy a list of terraform objects, replacing values in each object


I've got a Terraform local variable loaded from a bunch of json files that is a list of objects, like this:

raw_repo_data = [
  {
    "collaborators" = {
      "teams" = [
        {
          "permission" = "admin"
          "slug" = "ops"
        },
        {
          "permission" = "triage"
          "slug" = "projectmanagement"
        },
        {
          "permission" = "triage"
          "slug" = "secops"
        },
      ]
    }
    "description" = "Terraform module to create a github repo with opinionated properties"
    "name" = "terraform-github-repo"
    "visibility" = "private"
  },
]

I've generated a map of team ids from a data source, keyed on slug:

locals {
  # Get the set of github team slugs used by all repositories
  team_slugs = toset(
    flatten(
      [
        for name, repo in local.raw_repo_data : [
          for team in lookup(repo.collaborators, "teams", []) :
          team.slug
        ]
      ]
    )
  )

  team_ids = {
    for team in data.github_team.this : team.slug => team.id
  }
}

data "github_team" "this" {
  for_each = local.team_slugs
  slug     = each.value
}

The team_ids map looks like this:

team_ids = {
  "ops" = "3676156"
  "projectmanagement" = "6105717"
  "secops" = "7766525"
}

I'd like to replace all the team slugs with their equivalent team id, like this:

repo_data = [
  {
    "collaborators" = {
      "teams" = [
        {
          "permission" = "admin"
          "slug" = "3676156"
        },
        {
          "permission" = "triage"
          "slug" = "6105717"
        },
        {
          "permission" = "triage"
          "slug" = "7766525"
        },
      ]
    }
    "description" = "Terraform module to create a github repo with opinionated properties"
    "name" = "terraform-github-repo"
    "visibility" = "private"
  },
]

I realise I'll need to copy the repo_data structure to a new local variable, but I can't for the life of me figure out how to construct the necessary for loops to do this.

I've got as far as this:

locals {
  repo_data = [
    for repo in local.raw_repo_data : [
      for k, v in repo : {
        k = v
      }
    ]
  ]
}

I can't figure out how to copy all attributes without change, and only process the collaborators.teams list.

Can anyone point me in the right direction?


Solution

  • With the help of the answer here, I figured it out:

    locals {
      repo_data = [
        for repo in local.raw_repo_data : {
          for k, v in repo : k =>
          k == "collaborators" ?
          {
            for k2, v2 in v : k2 =>
            k2 == "teams" ? [
              for block in v2 : {
                for k4, v4 in block : k4 =>
                k4 == "slug" ? local.team_ids[v4] : v4
              }
            ]
            : v2
          }
          : v
        }
      ]
    }