TerraformのChecksとTestsの使い分け

2024.01.04

「ChecksとTestsはどう違うのか?」

Terraformのコード検証やテストの方法として、ChecksとTestsがあります。

どう違ってどう使い分ければ良いのか疑問に思ったため、まとめてみます。

結論

結論からです。TestsとChecksの概要から知りたい方は、「ChecksとTestsの概要」から読んでもらえればと思います。

TestsとChecksの大きな違いは以下かと思います。

  1. テスト用の一時的なリソース作成の有無
  2. ライフサイクルの外側でのチェックの有無

以下の使い分けをお勧めします。

  • Terraformのライフサイクル管理外のテストは、Checks
  • モジュールに対するテストは、Tests
- Tests Checks
テスト用の一時的なリソース作成 -
ライフサイクルの外側でのチェック
実行のタイミング terraform test terraform plan/apply時
記述方法 test.hclファイル tfファイル内

1. テスト用の一時的なリソース作成の有無

Testsはテスト実行時に、テスト用のリソースを一時的に作成することができます。

上記の何が嬉しいかというと、直接リソースを作成しない(※)モジュールでテストが行いやすいです。

tfファイルを直接みる静的解析に比べて、ApplyやPlanを伴うテストの方が得られる情報は多いため踏み込んだテストができます。

呼び出し側でテストをする場合、関連するリソースの数が多く1回あたりの実行に時間がかかります。

全体に比べて作成するリソース数が少ないため、Testsはモジュール単位でテストを行うことに適しています。

※ディレクトリで直接terraform applyを行わない。他tfファイルから呼び出して、リソースを作成する。

2. ライフサイクルの外側でのチェックの有無

Terraformの設定ファイルだけでは、ステータスがわからない項目もあります。

例えば、

  • AWS Budgetsの予算を超過していないか
  • ACMでインポートした証明書の有効期限は切れていないか

上記の項目のチェックには、Checksを利用できます。

逆にTestsで上記を確認しようとすると、コマンドを別で叩く必要がある・Stateファイルも別になるため手間やテストの実行時間が伸びます。

ChecksとTestsの概要

Checks

terraform 1.5で追加された機能です。

Terraformで作成したインフラストラクチャ全体に対して、ライフサイクル範囲外に対してもチェックが可能です。

例えば、以下のようにACMで証明書をインポートするとします。

main.tf

resource "aws_acm_certificate" "cert" {
  private_key      = tls_private_key.example.private_key_pem
  certificate_body = tls_self_signed_cert.terramino.cert_pem
}

証明書のステータスを確認して、意図せずアプリへのHTTPSでの接続ができなくなる事態を防ぎたいです。

ステータスの部分は証明書の有効期限が切れる等、Terraformのライフサイクル範囲外で決まります。

aws_acm_certificate.cert.statusでステータスが取れるため、手動でやる場合はOutputに出して確認すれば良さそうです。

Checksを利用することで、terraform plan/apply時に自動でチェックできます。

Checksは通常のtfファイル内に記述可能で、Check失敗時もPlanやApplyの実行できます。

main.tf

check "certificate" {
  assert {
    condition     = aws_acm_certificate.cert.status == "ISSUED"
    error_message = "Certificate status is ${aws_acm_certificate.cert.status}"
  }
}

具体的な使い方の例としては、以下があります。

  • AWS Budgetsで目標金額を超えていないか
  • GuardDutyで脅威が検出されていないか
  • IAMロールがX日以上が未使用な状態になっていないか

Checks - Configuration Language | Terraform | HashiCorp Developer

Using Terraform Cloud's Continuous Validation feature with the AWS Provider | Guides | hashicorp/aws | Terraform | Terraform Registry

Tests

terraform 1.6で追加された機能です。

terratestやkitchen-terraformのように、統合テストやユニットテストが可能です。

terraform testコマンドでテストを実行します。(planやapply時には実行されない)

一時的なリソースを作成し(※)、そのリソースに対してテストを行うため、既存のリソースやStateファイルに影響はありません。

例えば、S3バケットを作成するモジュールに対して、以下のようなテストが可能です。

  • S3バケットの名前が正しいか
  • ローカルのファイルとTerraformでアップロードしたファイル(S3オブジェクト)が同一か

テストはHCLで記述可能で、.tftest.hclという拡張子にする必要があります。

tests/website.tftest.hcl

# Call the setup module to create a random bucket prefix
run "setup_tests" {
  module {
    source = "./tests/setup"
  }
}

# Apply run block to create the bucket
run "create_bucket" {
  variables {
    bucket_name = "${run.setup_tests.bucket_prefix}-aws-s3-website-test"
  }

  # Check that the bucket name is correct
  assert {
    condition     = aws_s3_bucket.s3_bucket.bucket == "${run.setup_tests.bucket_prefix}-aws-s3-website-test"
    error_message = "Invalid bucket name"
  }

  # Check index.html hash matches
  assert {
    condition     = aws_s3_object.index.etag == filemd5("./www/index.html")
    error_message = "Invalid eTag for index.html"
  }

  # Check error.html hash matches
  assert {
    condition     = aws_s3_object.error.etag == filemd5("./www/error.html")
    error_message = "Invalid eTag for error.html"
  }
}

hashicorp-education/learn-terraform-testから引用

※ ブロック内でcommand= planを設定しておけば、一時的にリソース作成せずにテストすることも可能

Write Terraform Tests | Terraform | HashiCorp Developer

Terraform Cloudの関連機能

Terraform Cloudの関連機能もみてみましょう。

Checks: Continuous validation

Checksは、PlanとApply時に評価されます。

証明書の有効期限やAWS Budgetsの金額は日々変わるため、Checkが失敗したらすぐ気づきたいです。

そんな時に便利なのが、「Continuous validation」です。

名前の通り、継続的にChecks等のバリデーションを評価してくれる機能です。

Terraform Cloudから通知を送ることも可能で、Check失敗時にSlack等にメッセージを送ることができます。

Health - Terraform Cloud | Terraform | HashiCorp Developer

Tests: Generated module tests

Testsは便利な機能ですが、Test自体の作成やワークフローを整備するのが面倒だったりします。

Terraform Cloudの「Generated module tests」を使えば、簡単です。

Terraform CloudのPrivate Registryに登録したモジュールに対して、テストを自動生成することが可能です。

Terraform Cloud側で、自動生成したテストを使って新しいバージョン公開時にテストを実行します。

Testing Private Modules - Private Registry - Terraform Cloud | Terraform | HashiCorp Developer

Terraform Cloudのプライベートモジュールのテスト機能とテスト自動生成を試してみた | DevelopersIO

おわりに

TestsとChecksについてでした。

それぞれの機能の概要と、使い分けのイメージがついたら幸いです。

「参考」にそれぞれのチュートリアルのリンクを貼っています。興味があったら、ぜひ試してみてください。

以上、AWS事業本部の佐藤(@chari7311)でした。

参考