Terraformモジュール間でのAccess Level連携:よくあるエラーと解決法

TerraformでVPC Service Controlsを管理する際、モジュール間でのAccess Level連携でエラーに遭遇することがよくあります。本記事では、実際の開発で遭遇した「Reference to undeclared input variable」エラーの原因と解決方法を詳しく解説します。

発生したエラー

VPC-SC設定を他環境に合わせて修正した際、以下のエラーが発生しました:

1
2
3
4
5
6
 Error: Reference to undeclared input variable
 
   on ../../us_modules/service_perimeter/locals.tf line 6, in locals:
    6:         var.access_level_service_accounts["analysis_project"].id,
 
 An input variable with the name "access_level_service_accounts" has not been declared.

エラーの原因分析

このエラーの根本原因は、モジュール間の変数連携が不完全だったことです。

正常に動作している環境Aの構成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# env_a_modules/access_level/outputs.tf
output "access_level_service_accounts" {
  value = google_access_context_manager_access_level.service_accounts
}

# env_a_modules/service_perimeter/variables.tf  
variable "access_level_service_accounts" {}

# jp_main.tf
module "service_perimeter" {
  source                        = "../../jp_modules/service_perimeter"
  access_level_service_accounts = module.access_level.access_level_service_accounts
  # 他の変数...
}

問題があったUS環境の構成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# env_b_modules/access_level/outputs.tf (不足していた)
output "access_level_office_and_vpn_ips" {
  value = google_access_context_manager_access_level.office_and_vpn_ips_us
}
# access_level_service_accountsのoutputが無い!

# env_b_modules/service_perimeter/variables.tf (不足していた)
variable "access_level_office_and_vpn_ips" {}
# access_level_service_accountsの変数宣言が無い!

# us_main.tf (不足していた)
module "service_perimeter" {
  source                              = "../../us_modules/service_perimeter"
  access_level_office_and_vpn_ips = module.access_level.access_level_office_and_vpn_ips
  # access_level_service_accountsの受け渡しが無い!
}

解決手順

ステップ1: access_levelモジュールにOutputを追加

1
2
3
4
5
6
7
8
# env_b_modules/access_level/outputs.tf
output "access_level_office_and_vpn_ips" {
  value = google_access_context_manager_access_level.office_and_vpn_ips_us
}

+ output "access_level_service_accounts" {
+   value = google_access_context_manager_access_level.service_accounts
+ }

ステップ2: service_perimeterモジュールに変数を追加

1
2
3
4
5
6
7
8
9
# env_b_modules/service_perimeter/variables.tf
variable "env" {}
variable "env_type" {}
variable "region" {}
variable "google_projects" {}
variable "scoped_policy" {}
variable "supported_services" {}
variable "access_level_office_and_vpn_ips" {}
+ variable "access_level_service_accounts" {}

ステップ3: メインファイルで変数を受け渡し

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# us_main.tf
module "service_perimeter" {
  source                              = "../../us_modules/service_perimeter"
  env                                 = var.env
  env_type                            = var.env_type
  region                              = var.region
  google_projects                     = data.google_project._
  scoped_policy                       = data.google_access_context_manager_access_policy._[var.env].name
  access_level_office_and_vpn_ips     = module.access_level.access_level_office_and_vpn_ips
+ access_level_service_accounts       = module.access_level.access_level_service_accounts
  supported_services                  = var.supported_services
}

Terraformモジュール間連携のベストプラクティス

1. 段階的なモジュール設計

1
2
3
access_level  service_perimeter  ingress_policy
                                     
   outputs      variables          variables

2. 変数命名の一貫性

  • Output名とVariable名を一致させる
  • モジュール間で統一した命名規則を使用
1
2
3
4
5
6
7
# Good: 一貫した命名
output "access_level_service_accounts" { ... }
variable "access_level_service_accounts" { ... }

# Bad: 不一致な命名  
output "service_account_access_levels" { ... }
variable "access_level_service_accounts" { ... }

3. 段階的な実装とテスト

1
2
3
4
5
6
7
# 各ステップでvalidationを実行
terraform validate
terraform plan

# モジュールごとの変更を確認
terraform plan -target=module.access_level
terraform plan -target=module.service_perimeter

デバッグのコツ

エラーメッセージの読み方

1
2
3
Error: Reference to undeclared input variable
   on ../../us_modules/service_perimeter/locals.tf line 6
   variable "access_level_service_accounts" has not been declared

この場合のチェック順序:

  1. variables.tf: 該当変数が宣言されているか
  2. メインファイル: モジュール呼び出し時に変数を渡しているか
  3. outputs.tf: 参照元モジュールでoutputが定義されているか

terraform graphを活用

1
terraform graph | dot -Tsvg > graph.svg

モジュール間の依存関係を視覚的に確認できます。

まとめ

Terraformモジュール間でのAccess Level連携では、以下の3つの要素が正しく設定されている必要があります:

  1. Output: 提供側モジュールでの値の公開
  2. Variable: 受け取り側モジュールでの変数宣言
  3. パススルー: メインファイルでのモジュール間連携

一つでも欠けると「Reference to undeclared input variable」エラーが発生します。エラーが発生した場合は、この3要素を順番に確認することで、効率的に問題を特定・解決できます。

複雑なインフラをTerraformで管理する際は、モジュール設計の初期段階でこれらの連携パターンを統一しておくことが、長期的な保守性向上の鍵となります。

技術ネタ、趣味や備忘録などを書いているブログです
Hugo で構築されています。
テーマ StackJimmy によって設計されています。