0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Terraform】for_eachだけじゃ足りない!可変スキーマをdynamicで表現する(Lake Formation権限を題材に)

Last updated at Posted at 2025-09-29

この記事で解決する課題

Terraformでaws_lakeformation_permissionsを扱う際、制御するケースに応じて適切なオブジェクト(databasedata_locationlf_tag_policy等)を書き分ける必要があります。(参考:Resource: aws_lakeformation_permissions Argument Reference
したがって、単純にfor_eachで種類の異なる複数のリソースを作成するには工夫が必要です。

本記事では、必要なオブジェクトだけをdynamictryで生成することで、for_eachだけでは難しい可変スキーマをシンプルに管理する方法を紹介します。

結論(完成コード)

databasedata_locationlf_tag_policyのいずれか1つだけを受け取り、渡されたものだけ dynamic で生成するモジュール。

モジュール本体

# modules/lakeformation_permissions/main.tf
resource "aws_lakeformation_permissions" "main" {
  principal   = var.principal_arn
  permissions = var.permissions

  # ---- database ----
  dynamic "database" {
    for_each = try([var.policy.database], [])
    content {
      name = database.value.name
    }
  }

  # ---- data_location ----
  dynamic "data_location" {
    for_each = try([var.policy.data_location], [])
    content {
      arn = data_location.value.arn
    }
  }

  # ---- lf_tag_policy ----
  dynamic "lf_tag_policy" {
    for_each = try([var.policy.lf_tag_policy], [])
    content {
      resource_type = lf_tag_policy.value.resource_type

      dynamic "expression" {
        for_each = lf_tag_policy.value.expression
        content {
          key    = expression.value.key
          values = expression.value.values
        }
      }
    }
  }
}

変数定義

variable "principal_arn" {
  type = string
}

variable "permissions" {
  type = list(string)
}

variable "policy" {
  # database / data_location / lf_tag_policy のいずれか1つを受け取るため any を指定
  type = any
}

使い方(呼び出し例)

# localsでパラメータ定義(3パターンをまとめて管理するサンプル)
locals {
  lf_permission_parameters = {
    # S3 データロケーション用
    location_for_role = {
      principal_arn = "arn:aws:iam::123456789012:role/lake-formation-role"
      permissions   = ["DATA_LOCATION_ACCESS"]
      policy = {
        data_location = {
          arn = "arn:aws:s3:::my-data-bucket"
        }
      }
    }
    # Database 用
    database_for_role = {
      principal_arn = "arn:aws:iam::123456789012:role/lake-formation-role"
      permissions   = ["SELECT", "ALTER"]
      policy = {
        database = {
          name = "my_db"
        }
      }
    }
    # LF-Tag Policy 用
    lf_tag_policy_for_role = {
      principal_arn = "arn:aws:iam::123456789012:role/lake-formation-role"
      permissions   = ["SELECT"]
      policy = {
        lf_tag_policy = {
          resource_type = "TABLE"

          expression = [
            {
              key    = "my_tag",
              values = ["high","low"]
            }
          ]
        }
      }
    }
  }
}

# モジュール本体の呼び出し
module "lf_permission" {
  source = "./modules/lakeformation_permissions"

  for_each = local.lf_permission_parameters

  principal_arn = each.value.principal_arn
  permissions   = each.value.permissions
  policy        = each.value.policy
}

設計のポイント

  • for_eachでは足りない理由
    for_eachそのものは「同じ形の繰り返し」が前提です。
    今回はオブジェクトの種類が制御したいケースによって変わる = 可変スキーマ なのでモジュール設計に工夫が必要になります。
  • dynamic × try([...], [])
    dynamicに渡すfor_eachは「空なら生成しない、1要素なら生成する」の意味です。
    try([var.policy.database], [])によって、未指定時に空配列渡すことによりこれを実現しています。

まとめ

  • 可変スキーマが前提のリソースは、for_eachだけだとつらい。
  • dynamictryを組み合わせることで、必要なブロックだけを生成。

「あ、これ自分の案件でも使えるかも」と思ったら、ぜひ試してみてください!

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?