Terraform の Optional 属性で処理をスキップしたいときの対処方法

Terraform の Optional 属性値に null を設定するといい感じに処理をスキップしてくれます。
2022.08.26

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

アノテーション構築チームの荒川です。

Terraform のリソースを作成する際に Optional 属性(attributes)に値を代入しつつ、設定の組み合わせ次第では処理をスキップ・省略したいケースがありました。

このような場合、モジュールなどで汎用的な作りにするにはどうしたら良いか迷いましたので、ブログに残します。

環境情報

$ terraform -v
Terraform v1.2.8
on darwin_arm64
+ provider registry.terraform.io/hashicorp/aws v4.22.0

InvalidParameterCombination

私が遭遇したのは RDS DB インスタンスである aws_db_instance のリソースを作成するケースでした。

modules/rds.tf

resource "aws_db_instance" "mysql" {
  // ...
  availability_zone = "ap-northeast-1a"
  multi_az          = true
  // ...
}

このままでは下記エラーが発生します。

Error creating DB Instance: InvalidParameterCombination: Requesting a specific availability zone is not valid for Multi-AZ instances.

マルチ AZ を有効にすれば AZ の指定は無効になります。
CloudFormation のドキュメントでは、このことが明記されています。

AWS::RDS::DBInstance - AWS CloudFormation

MultiAZ Specifies whether the database instance is a Multi-AZ DB instance deployment. You can't set the AvailabilityZone parameter if the MultiAZ parameter is set to true.

multi_aztrue の時は availability_zone の指定を無視したいです。

対処方法

Terraform では Optional 属性の値に null を代入すると省略できます。

defaults - Functions - Configuration Language | Terraform by HashiCorp

When you define an attribute as optional and the caller doesn't provide an explicit value for it, Terraform will set the attribute to null to represent that it was omitted. If you want to use a placeholder value other than null when an attribute isn't set, you can use the defaults function to concisely assign default values only where an attribute value was set to null.

マルチ AZ 配置にしない場合

modules/rds.tf

resource "aws_db_instance" "mysql" {
  // ...
  availability_zone = "ap-northeast-1a"
  multi_az          = false
  // ...
}

マルチ AZ 配置にする場合

modules/rds.tf

resource "aws_db_instance" "mysql" {
  // ...
  availability_zone = null
  multi_az          = true
  // ...
}

汎用的に書きたい場合

modules/rds.tf

resource "aws_db_instance" "mysql" {
  // ...
  availability_zone = var.multi_az ? null : var.availability_zone
  multi_az          = var.multi_az
  // ...
}

これでシングル AZ の場合は DB インスタンスの配置 AZ を指定しつつ、マルチ AZ が有効な場合もエラーを回避できます。

おわりに

今回紹介した例を使うことで Optional 変数のデフォルト値を null にして、処理が必要なければ代入不要な変数も作れそうです。

Terraform の null とは仲良くできそうと感じました。Terraform は期待する動作をコードで書きやすいので、楽しめています。

参考

アノテーション株式会社について

アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、さまざまな背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。