📗

【Terraform】Error: Unsupported attributeの解消(outputブロックの理解を深める)

2024/09/08に公開

Unsupported attribute

terraform plan実行時に、Unsupported attributeというエラーが発生しました。

$ terraform plan
╷
│ Error: Unsupported attribute
│ 
│   on outputs.tf line 2, in output "storage_account_name":2:   value = module.storage_account.storage_account_name
│     ├────────────────
│     │ module.storage_account is a object
│ 
│ This object does not have an attribute named "storage_account_name".
╵
╷
│ Error: Unsupported attribute
│ 
│   on outputs.tf line 6, in output "container_name":6:   value = module.storage_account.container_name
│     ├────────────────
│     │ module.storage_account is a object
│ 
│ This object does not have an attribute named "container_name".

module.storage_accountというオブジェクトがstorage_account_namecontainer_nameという属性を持っていないよというエラーです。

ディレクトリ構成とファイル内容

terraform-sample
  |--modules
      |--storage_account
          |-- main.tf
          |-- variables.tf
  |--envs
      |--development
          |-- main.tf
          |-- outputs.tf
          |-- provider.tf
          |-- backend.tf
          |-- terraform.tfvars
          |-- variables.tf
modules/storage_account/main.tf
# モジュール:AzureストレージアカウントとBlobコンテナを定義
resource "azurerm_storage_account" "sample_storage_account" {
  name                     = var.storage_account_name
  resource_group_name      = var.resource_group_name
  location                 = var.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

resource "azurerm_storage_container" "sample_blob_container" {
  name                  = var.container_name
  storage_account_name  = azurerm_storage_account.sample_storage_account.name
  container_access_type = "private"
}
# モジュールを使いAzureストレージアカウントを宣言
resource "azurerm_resource_group" "rg" {
  name     = var.resource_group_name
  location = var.location
}

module "storage_account" {
  source = "../../modules/storage_account"

  storage_account_name = var.storage_account_name
  resource_group_name  = azurerm_resource_group.rg.name
  location             = var.location
  container_name       = var.container_name
}
envs/development/outputs.tf
# メインディレクトリ側のoutput定義
output "storage_account_name" {
  value = module.storage_account.storage_account_name
}

output "container_name" {
  value = module.storage_account.container_name
}

結論: outputブロックについて

結論としては、以下のように、module側でもoutputを定義する必要があります。

modules/storage_account/outputs.tf
output "storage_account_name" {
  value = azurerm_storage_account.sample_storage_account.name
}

output "container_name" {
  value = azurerm_storage_container.sample_blob_container.name
}

モジュール内でoutputを定義するのは、モジュール内部のリソースや変数を外部(メイン構成ファイル)に公開するためです。モジュールは、内部の詳細が外部から見えないようにカプセル化されています。そのため、モジュール内で定義した情報(ここではストレージアカウント名やBlobコンテナ名)をメイン側のoutputで利用する場合、モジュール側でoutputを定義し、公開しておく必要があります。

一方、メイン構成ファイル側でoutputを定義する理由は、terraform apply実行時にコマンドラインに値を出力したり、その値を他のリソースや外部システムで利用するためです。

この辺りは、Output Valuesドキュメントに記載の通りでした。

Output values have several uses:
・A child module can use outputs to expose a subset of its resource attributes to a parent module.
・A root module can use outputs to print certain values in the CLI output after running terraform apply.

https://developer.hashicorp.com/terraform/language/values/outputs

以上です。

Discussion