📌

Terraform 1.7 の新機能

2024/01/29に公開

https://github.com/hashicorp/terraform/releases/tag/v1.7.0

同種の記事は数多あると思いますが、自分自身の理解を深める事を主目的に、調べた内容を整理して記載します。

今回の1.7は、概ね以下の2機能が注目の機能になるのかな、と思います。

  • terraform test の mock 機能追加
  • removed block の追加

terraform test の mock 機能追加

terraform test 自体は以前のバージョンから追加されていますが、1.7 では mock 機能 が提供されるようになりました。

Mock Providers

よくあるテストフレームワークと同様、特定の機能のインターフェースを擬態し、常に固定の値を返却することができる機能です。

公式サイトに記載されている、 S3 に対する設定を引用します。

# main.tf

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}

variable "bucket_name" {
  type = string
}

resource "aws_s3_bucket" "my_bucket" {
  bucket = var.bucket_name
}

# bucket_name.tftest.hcl

mock_provider "aws" {}

run "sets_correct_name" {
  variables {
    bucket_name = "my-bucket-name"
  }

  assert {
    condition     = aws_s3_bucket.my_bucket.bucket == "my-bucket-name"
    error_message = "incorrect bucket name"
  }
}

上記のような形で S3 バケットに対する Resource 定義 (main.tf) と、そのリソースに対するテストの定義 (bucket_name.tftest.hcl) があるとします。
テストではバケット名が意図したものであるかの確認を行っています。

このテストに対する mock の定義としては以下のような例が記載されています。
use_real_provider では実際の S3 のリソースを用いたテストを実施。
use_mocked_provider では Mock を用いたテストを実施。
という形になっています。

# mocked_providers.tftest.hcl

provider "aws" {}

mock_provider "aws" {
  alias = "fake"
}

run "use_real_provider" {
  providers = {
    aws = aws
  }
}

run "use_mocked_provider" {
  providers = {
    aws = aws.fake
  }
}

こちらを時刻すると、以下のように use_real_provider では使用する AWS 環境の状況によってはエラー、 use_mocked_provider は Mock を使用するため常に Pass となります。

 % terraform test -var bucket_name=my-bucket-name 
bucket_name.tftest.hcl... in progress
  run "sets_correct_name"... pass
bucket_name.tftest.hcl... tearing down
bucket_name.tftest.hcl... pass
mocked_providers.tftest.hcl... in progress
  run "use_real_provider"... fail
╷
│ Error: creating S3 Bucket (my-bucket-name): operation error S3: CreateBucket, https response error StatusCode: 409, RequestID: QJG6CPD876FF800F, HostID: teu3ODZjlai4wJvEMzGV82d1In3OEVpc2LCjvlj7AQuPG+tgWn0k+pqP5cIr3nd31NHi1+2130c=, BucketAlreadyExists: 
│ 
│   with aws_s3_bucket.my_bucket,
│   on main.tf line 13, in resource "aws_s3_bucket" "my_bucket":
│   13: resource "aws_s3_bucket" "my_bucket" {
│ 
╵
  run "use_mocked_provider"... skip
mocked_providers.tftest.hcl... tearing down
mocked_providers.tftest.hcl... fail

Failure! 1 passed, 1 failed, 1 skipped.

Mock provider data という機能を使うと、Mock 経由で返却するデータを自由に設定することも可能になっています。

1.6 までの terraform test は実際のリソースに対してテストを実施する形になっており、リソース作成前の状態ではテストが行いづらい状況でした。
mock 機能が追加されたため、ローカル環境で mock を使いながらテストが書けるようになり、機能として少しグレードアップした感はあります。

ただ、mock とリアルリソースのテストの切り替えが透過的に行えるわけでもなさそうなので、まだまだ利便性には課題がありそうです。

removed block の追加

removed block

terraform では今まで既存リソースの管理を terraform 管理下から削除する際には terraform state rm コマンドを実施する必要がありました。
コマンドでの実施は tf ファイルの定義との同期を取ることが難しく、運用管理上の難しさがありました。

removed block が追加されたことにより、宣言的に既存のリソースの定義を terraform 管理下から削除できるようになりました。

以下は公式サイトの記述されていた例です。

removed {
  from = aws_instance.example

  lifecycle {
    destroy = false
  }
}

lifecycle.destoryfales を指定すると、既存リソースはそのまま、 terraform の管理下からだけは外すことができる、という形の挙動になります。

terraform での管理があまり適切ではないリソースについて、途中で terraform 配下から外すという運用は私も何度か経験したことがあり、その際に宣言的に記述がかけるのは安全で安心できるな、とは感じます。

Discussion