Terraform 1.6+ `test` フレームワーク:インフラの「真のユニットテスト」を構築する極意
Terraform 1.6でついに公式化された `terraform test`。これまで我々は、`terratest` のような外部ツールに依存し、巨大なGoバイナリをコンパイルし、数十分かかる統合テストに耐えてきた。だが、時代は変わった。
「インフラをコードで記述する」とは、単にリソースを定義することではない。「リソースの整合性を数学的に証明し、破壊的な変更をパイプラインの入り口で遮断する」ことだ。本稿では、Terraformネイティブテストを活用し、インフラコードの品質を極限まで引き上げる手法を伝授する。
—
1. なぜ今、ネイティブテストなのか?
従来の `terratest` 等による外部テストは、実際にリソースを作成(`terraform apply`)してから検証を行うため、フィードバックループが遅く、コストが嵩む。
一方、`terraform test` は Plan-as-a-Test を基本思想としている。`terraform plan` の出力結果(JSON)に対してテストを実行するため、APIコールを発生させずにリソースの期待値検証が可能だ。これは、大規模なTerraformモジュールを運用する我々にとって、CI/CDのレイテンシを劇的に改善する転換点となる。
2. モックを利用した「境界」の制御
現実のクラウド環境には「外部依存」が付き物だ。既存のVPC IDや、他チームが管理するIAMロールなど。これらをテストのたびに参照すると、テストは不安定(Flaky)になる。
`terraform test` の真髄は、`mock_provider` を駆使して「外部依存を遮断」することにある。
tests/vpc.tftest.hcl
実際のProvider設定を上書きし、API疎通を不要にする
mock_provider “aws” {
alias = “main”
# モックデータで外部参照をスタブ化
mock_resource “aws_vpc” {
defaults = {
id = “vpc-0123456789abcdef0”
}
}
}
run “validate_vpc_tags” {
command = plan
# 期待値の検証:タグ設計の強制
assert {
condition = aws_vpc.main.tags[“Environment”] == “production”
error_message = “VPCには必ずEnvironmentタグが必要です”
}
}
この手法を使えば、ネットワーク構成やセキュリティグループのルールを、クラウドプロバイダーのAPI制限を気にすることなく、ローカルのCI環境でミリ秒単位で検証可能になる。
3. 高度なテスト設計:状態遷移と冪等性の検証
単にタグを見るだけでは、SREとは呼べない。私が現場で実践しているのは、「設計不変量(Invariant)」の自動検査である。
例えば、`public_access_block` が無効化されるような破壊的変更は、CIで即座に検知しなければならない。
モジュール入力値を動的に変更してテストする
run “check_public_access_block” {
command = plan
variables {
block_public_access = true
}
assert {
condition = aws_s3_bucket_public_access_block.this.block_public_policy == true
error_message = “S3のパブリックアクセスブロックが無効化されています。セキュリティポリシー違反です。”
}
}
4. 伝説的エンジニアのハック:パイプライン完全自動化の極意
単にコマンドを叩くだけでは不十分だ。大規模環境では、以下のスクリプトをCIパイプラインのフックとして組み込むことを推奨する。
高速化ハック:並列テスト実行とキャッシュ戦略
`terraform test` はデフォルトでシングルスレッドだが、テストケースが数千に及ぶ場合、CIの実行時間は無視できない。以下のラッパースクリプトで並列化する。
!/bin/bash
修正箇所のみテストを実行し、テスト効率を最大化する戦略
CHANGED_FILES=$(git diff –name-only origin/main…HEAD | grep ‘\.tf$’)
if [ -n “$CHANGED_FILES” ]; then
# 変更されたモジュールに関連するテストのみを抽出して実行
terraform test -filter=$(dirname $CHANGED_FILES) -parallelism=10
else
echo “No infra changes detected.”
fi
内部アーキテクチャへの理解:メモリ消費の最適化
TerraformのPlanファイルは、巨大な構成になるとメモリを大量に消費する。テスト実行時のヒープサイズ制限に抵触する場合、`TF_PLAN_FORMAT` や `TF_LOG` の出力をパイプラインから分離し、アーティファクトとして保存する設計にせよ。`/tmp` をRAMディスク(`tmpfs`)としてマウントし、そこに `.terraform` ディレクトリを配置するだけで、I/O性能は物理限界まで向上する。
—
結びに:コードは「意思」である
Terraformのテストを書くということは、「このインフラがどうあるべきか」という設計者の意志を、マシンが理解できる言語に翻訳する行為だ。
単に `terraform apply` を成功させるだけのエンジニアは、いつかシステムに裏切られる。だが、テストによって「定義された状態」を数学的に保証するエンジニアは、システムの複雑性を完全にコントロール下におくことができる。
さあ、モックを書き、アサーションを積み上げ、君のインフラを「壊れない鉄壁」へと昇華させよ。これこそが、IaCを極めた者が辿り着く、静かなるエンジニアリングの極致である。