Terraform で Amazon ECR リポジトリのライフサイクルポリシーを設定するときに aws_ecr_lifecycle_policy
リソースのドキュメントを読むとヒアドキュメントを使った例が載っている📝
個人的にはヒアドキュメントを使いたくなく,他の実装案を考えながら試してみた❗️
- aws_ecr_repository | Resources | hashicorp/aws | Terraform Registry
- aws_ecr_lifecycle_policy | Resources | hashicorp/aws | Terraform Registry
1. ヒアドキュメントで直接書く
まずはドキュメントに載っているヒアドキュメントの例を試す.今回はサンプルとして Policy on tagged image のライフサイクルポリシーを使っている.ヒアドキュメントで EOF
を書く部分や閉じる EOF
のインデントが気になる💨
ちなみに <<-EOF
とすればインデントはキレイに書けるようになるけどまだ微妙さは残る...
main.tf
resource "aws_ecr_repository" "playground" { name = "playground" } resource "aws_ecr_lifecycle_policy" "playground" { repository = aws_ecr_repository.playground.name policy = <<EOF { "rules": [ { "rulePriority": 1, "description": "Keep last 30 images", "selection": { "tagStatus": "tagged", "tagPrefixList": ["v"], "countType": "imageCountMoreThan", "countNumber": 30 }, "action": { "type": "expire" } } ] } EOF }
2. jsonencode
関数に JSON をそのまま指定する
jsonencode
関数を使えば指定した値を JSON に変換できる.JSON を文字列のまま指定できるため,結果的にヒアドキュメントを jsonencode
関数に置き換えられる.JSON を指定すると区切り文字を :
にした Map 型になるため,terraform fmt
コマンドで整形できるというメリットもある👌
main.tf
resource "aws_ecr_repository" "playground" { name = "playground" } resource "aws_ecr_lifecycle_policy" "playground" { repository = aws_ecr_repository.playground.name policy = jsonencode( { "rules" : [ { "rulePriority" : 1, "description" : "Keep last 30 images", "selection" : { "tagStatus" : "tagged", "tagPrefixList" : ["v"], "countType" : "imageCountMoreThan", "countNumber" : 30 }, "action" : { "type" : "expire" } } ] } ) }
3. file
関数で JSON ファイルを読み込む
file
関数を使うと JSON ファイルを直接読み込める.固定の JSON を読み込めれば Terraform コードをシンプルに保てる👌
lifecycle.json
{ "rules": [ { "rulePriority": 1, "description": "Keep last 30 images", "selection": { "tagStatus": "tagged", "tagPrefixList": ["v"], "countType": "imageCountMoreThan", "countNumber": 30 }, "action": { "type": "expire" } } ] }
main.tf
resource "aws_ecr_repository" "playground" { name = "playground" } resource "aws_ecr_lifecycle_policy" "playground" { repository = aws_ecr_repository.playground.name policy = file("lifecycle.json") }
4. jsonencode
関数に Map 型を指定する
案2 と似てるけど jsonencode
関数に区切り文字を =
にした Map 型を指定する.rulePriority
や description
などキー名に "
を書く必要がなく,個人的には JSON をそのまま指定するよりも可読性が高くて良いと思う👌
main.tf
resource "aws_ecr_repository" "playground" { name = "playground" } resource "aws_ecr_lifecycle_policy" "playground" { repository = aws_ecr_repository.playground.name policy = jsonencode( { rules = [ { rulePriority = 1, description = "Keep last 30 images", selection = { tagStatus = "tagged", tagPrefixList = ["v"], countType = "imageCountMoreThan", countNumber = 30 }, action = { type = "expire" } } ] } ) }
5. templatefile
関数と jsonencode
関数を組み合わせてテンプレート化する
templatefile
関数と jsonencode
関数を組み合わせるとテンプレートファイルから JSON を作れる❗️${description}
や ${countNumber}
など変数を埋め込めるのは便利〜 \( 'ω')/
例えば「アプリケーションごとに Amazon ECR リポジトリは複数あるけどライフサイクルポリシーはほとんど同じだからできる限り共通化したい」という場面にピッタリ👌
テンプレートファイルの拡張子はドキュメントで推奨されている .tftpl
にしてある📝
lifecycle.tftpl
${jsonencode( { rules = [ { rulePriority = 1, description = "${description}", selection = { tagStatus = "tagged", tagPrefixList = ["v"], countType = "imageCountMoreThan", countNumber = "${countNumber}" }, action = { type = "expire" } } ] } )}
main.tf
resource "aws_ecr_repository" "playground" { name = "playground" } resource "aws_ecr_lifecycle_policy" "playground" { repository = aws_ecr_repository.playground.name policy = templatefile("lifecycle.tftpl", { description = "Keep last 30 images" countNumber = 30 }) }