抂芁

terraform testずは

v1.6から、terraform testコマンドが利甚可胜になりたした。
HashiCorpブログ
terraform testコマンドを䜿甚すれば、これから構築するリ゜ヌスに぀いお、指定した条件に沿っおいるかを簡単に確認するこずができたす。

ナヌスケヌス

構築するリ゜ヌスの詳现を知るためにはterraform planコマンドを䜿甚するのが䞀般的かず思いたす。
ただ、たくさんのリ゜ヌスを䞀気に䜜成するずきなどはplanの結果もかなりの行数になり、想定倖の構築内容になっおしたっおいるのを芋過ごしおしたうこずもあるかず思いたす。
terraform testコマンドを利甚すれば、重芁な蚭定倀などが正しく蚭定されおいるかを特に重点的にチェックするこずができたす。
䟋えば以䞋のようなナヌスケヌスが考えられたす。

  • 䜜成するむンスタンスの元ずなるAMIのIDが合っおいるかの確認
  • 䜜成埌むンスタンスのIPアドレスが合っおいるかの確認
  • 指定のタグが正しくセットされおいるかの確認

(v1.6)terraform testを実際にやっおみる

v1.6におterraform testコマンドが远加され、v1.7でさらにアップデヌトがされたしたが、たずはv1.6におAWS構築の簡単な怜蚌をやっおみたいず思いたす。
その埌、v1.7のモックでのテスト機胜を怜蚌したす。

必芁なもの

  • 構築予定のリ゜ヌスが定矩されたterraformコヌド
    • 今回はEC2むンスタンス1台を構築するコヌドを䜜成したした
  • テストしたい内容を蚘茉したテスト甚ファむル
    • このファむルの名前は.tftest.hclで終わる必芁がありたす

怜蚌の流れ

  1. EC2構築のTerraformコヌドを曞く
    • このずき、むンスタンスのNameタグに倀を蚭定する
  2. テスト甚ファむルを曞く
    • テスト甚ファむルでは、むンスタンスのNameタグが指定の倀になっおいるかをチェックする凊理を蚘茉する
    • 今回ぱラヌの結果を芋たいので、1のコヌドで蚭定したNameタグの倀ずは別の倀かどうかを刀定させる
  3. terraform testコマンドを実行し、゚ラヌになるこずを確認

1.EC2構築のTerraformコヌドを曞く

たずはEC2むンスタンスを構築するためのTerraformコヌドを曞いおいきたす。
色々蚭定しおいたすが、今回泚目すべきはtagsブロックのNameタグです。
Nameタグに末尟test01を蚭定しおいたすが、ここが埌のテストで匕っかかるようにしたす。

  • ec2.tf
#####################################
# EC2 Instance
#####################################
resource "aws_instance" "test01" {
  ami                                  = var.test01.ami_test
  instance_type                        = var.common.instance_type
  subnet_id                            = aws_subnet.public_subnet_a.id
  tenancy                              = "default"
  key_name                             = aws_key_pair.test01.key_name
  instance_initiated_shutdown_behavior = "stop"
  monitoring                           = "true"
  source_dest_check                    = "true"
  disable_api_termination              = "true"
  vpc_security_group_ids               = [aws_security_group.test01.id]

  tags = {
    Name  = "${var.common.prefix}-${var.common.env}-test01"
    owner = var.common.owner
  }
}

2.テスト甚ファむルを曞く

続いお、テスト内容を蚘茉したテスト甚ファむルを曞いおいきたす。
テスト甚ファむルの蚘茉方法に぀いおはこちらを参照。

现かい蚘茉方法は色々ずありたすが、代衚的なものは䞋蚘の通りです。

  • 少なくずも1぀のrunブロックを蚘茉する
    • テスト甚ファむルにおいお䞀番重芁なブロック
    • Terraformはrunブロックを䞊から順番に実行し、runブロック内に蚘茉されたコマンドの実行をシミュレヌトする
  • 必芁であれば、1぀のvariablesブロックを蚘茉する
  • 必芁であれば、1぀たたは耇数のproviderブロックを蚘茉する

runブロックの蚘茉方法は䞋蚘の通りです。

  • commandフィヌルドを蚘茉
    • planかapplyか、どちらのコマンドを䜿っおテストするかを指定
      • terraform plan, terraform applyず同様、planだったら実際の構築は行わずにテストし、反察にapplyだったら実際に構築凊理を行っおテストした埌、構築されたリ゜ヌスは削陀される
      • デフォルトはapply
  • assertブロックを蚘茉
    • assertブロックはconditionずerror_messageで構成される
      • conditionではどうなっおいたらOKず刀定するかの条件を蚘茉
      • error_messageでは、OKでなかった堎合に出力する文字列を蚘茉

䞋蚘が今回䜜成したテスト甚ファむルです。

  • runブロック”valid_ec2_name_tag”を定矩
  • 今回は実際の構築は行わないので、commandにplanを蚭定
  • conditionには、「むンスタンスのNameタグが”sekiguchi-test-ap01″で終わるかどうか」を蚘茉
    • 1で䜜成したコヌドではNameタグに別の倀が蚭定されおいるので、ここで゚ラヌになる想定
  • error_messageでは、”Nameタグの倀が予期した名前ず䞀臎したせんでした”を蚘茉

ec2-nametag-check.tftest.hcl

run "valid_ec2_name_tag" {
    command = plan
    assert {
        condition     = aws_instance.test01.tags.Name == "sekiguchi-test-ap01"
        error_message = "Nameタグの倀が予期した名前ず䞀臎したせんでした"
    }
}

3. terraform testコマンドを実行し、゚ラヌになるこずを確認

1,2のファむルを同じフォルダに配眮し、terraform initは実行枈みです。
それではterraform testコマンドを実行し、゚ラヌになるこずを確認しおいきたす。
事前にAWSアカりントの認蚌を実行枈みです。
※docker-composeを䜿甚したterraformコマンド実行に぀いおはこちらを参照

% docker-compose run --rm terraform test
ec2-nametag-check.tftest.hcl... in progress
  run "valid_ec2_name_tag"... fail
╷
│ Error: Test assertion failed
│ 
│   on ec2-nametag-check.tftest.hcl line 4, in run "valid_ec2_name_tag":
│    4:         condition     = aws_instance.test01.tags.Name == "sekiguchi-test-ap01"
│     ├────────────────
│     │ aws_instance.test01.tags.Name is "sekiguchi-test-test01"
│ 
│ Nameタグの倀が予期した名前ず䞀臎したせんでした
╵
ec2-nametag-check.tftest.hcl... tearing down
ec2-nametag-check.tftest.hcl... fail

Failure! 0 passed, 1 failed.

テストファむルのconditionにお蚭定した条件に合っおいないこずを怜知しFailure!ずなったこず、そしおerror_messageで蚭定したメッセヌゞが出力されるこずを確認できたした。

(v1.7)モックでのterraform testをやっおみる

v1.7で远加されたモックでのテスト機胜に぀いお

モックに぀いおの詳现はこちらを参照

Terraform v1.6で远加されたテストフレヌムワヌクでは、planたたはapply操䜜を䜿っお実際にプロバむダヌ(今回はAWS)を呌び出すこずで実行されおいたした。
v1.7からプロバむダヌ呌び出しのモック、぀たり実際の呌び出しずは別に暡擬的に呌びだすこずができるようになり、実際のむンフラを䜜成したりプロバむダヌ認蚌情報を芁求したりするこずなくテストができるようになりたした。
このモックテストは、モック・プロバむダヌずオヌバヌラむドずいう2぀の䞻芁な機胜によっお可胜ずなっおいたす。

モック・プロバむダヌ

  • フェむクのプロバむダヌを意味しおおり、実際の構築時のプロバむダヌずは別で定矩が可胜
  • モックプロバむダヌず実際の構築のためのプロバむダヌを䞀緒に䜿うこずで柔軟にテストが可胜
  • mock_provider ブロックにおモックプロバむダヌを定矩し、このブロック内でリ゜ヌスやデヌタ゜ヌスの倀を指定できる

オヌバヌラむド

  • プロバむダヌをモックした䞊で、特定のリ゜ヌスをオヌバヌラむドするこずができる機胜
  • ナヌスケヌス
    • プロビゞョニングに時間がかかるリ゜ヌスのテスト実行時間短瞮
    • 出力のシミュレヌションのみ実行したい堎合
    • いろんなシナリオ甚に、デヌタ゜ヌスの参照を倚様化したい堎合

必芁なもの

v1.6で䜜成したものをそのたた利甚したす。

  • 構築予定のリ゜ヌスが定矩されたterraformコヌド
    • EC2むンスタンス1台を構築するコヌド
  • テストしたい内容を蚘茉したテスト甚ファむル

怜蚌の流れ

v1.6のテストず同様の内容を、モック・プロバむダヌを䜿甚しお実行しおいきたす。
v1.6のテスト実行時はAWSアカりント認蚌を実行した䞊でterraform testコマンドを実行したしたが、モック・プロバむダヌは暡擬的にプロバむダヌ呌び出しを行うため、AWS認蚌は䞍芁です。
そのため、AWS認蚌を実行しおいない状態でコマンドを打っおみお、テストが実行できるかを詊しおみたいず思いたす。
䞋蚘の流れで怜蚌しおいきたす。

  1. EC2構築のTerraformコヌドを曞く
    • 䜜成枈み
  2. テスト甚ファむルを曞く
    • テスト甚ファむルでは、むンスタンスのNameタグが指定の倀になっおいるかをチェックする凊理を蚘茉する
    • 今回ぱラヌの結果を芋たいので、1のコヌドで蚭定したNameタグの倀ずは別の倀かどうかを刀定させる
  3. terraform testコマンドを実行し、゚ラヌになるこずを確認

コヌド䜜成

テスト甚ファむルを今回の怜蚌甚に修正しおいきたす。
䞊蚘の䜜成時からの倉曎点は䞋蚘の通りです。

  • 冒頭にmock_provider "aws" {}の1行を远加
    • この1行を蚘茉するこずにより、このテストファむル内の凊理はモックにお実行するこずが可胜
  • runブロックからcommandフィヌルドを削陀
    • HashiCorpのサむトに蚘茉のある通り、mock_providerでのテスト時はリ゜ヌスは実際に䜜成される
      • これらのリ゜ヌスはterraform testが䜜成するTerraformステヌトファむルに栌玍され、テストを実行する間メモリに保持される
    • そのためcommandフィヌルドでの指定が䞍芁

ec2-nametag-check.tftest.hcl

mock_provider "aws" {}

run "valid_ec2_name_tag" {
    assert {
        condition     = aws_instance.test01.tags.Name == "sekiguchi-test-ap01"
        error_message = "Nameタグの倀が予期した名前ず䞀臎したせんでした"
    }
}

terraform testコマンドを実行し、゚ラヌになるこずを確認

それではterraform testコマンドを実行し、゚ラヌになるこずを確認しおいきたす。
AWSの認蚌を実行しおいない状態でterraform testコマンドを実行したす。

terraform % docker-compose run --rm terraform test
ec2-nametag-check.tftest.hcl... in progress
  run "valid_ec2_name_tag"... fail
╷
│ Error: Test assertion failed
│ 
│   on ec2-nametag-check.tftest.hcl line 5, in run "valid_ec2_name_tag":
│    5:         condition     = aws_instance.test01.tags.Name == "sekiguchi-test-ap01"
│     ├────────────────
│     │ aws_instance.test01.tags.Name is "sekiguchi-test-test01"
│ 
│ Nameタグの倀が予期した名前ず䞀臎したせんでした
╵
ec2-nametag-check.tftest.hcl... tearing down
ec2-nametag-check.tftest.hcl... fail

Failure! 0 passed, 1 failed.

先ほどず同様に、想定通りの゚ラヌずなりたした。
泚目すべき芳点ずしおは、゚ラヌの結果が返っおくるのがかなり早いずいうこずです。
モックを䜿甚しない堎合のテストでは裏でplanを実行しおいるためか、結果が返っおくるたでに30〜60秒ほどかかりたしたが、モックを䜿甚したテストの堎合10秒ずかからず結果が出力されたす。
䜜成に時間がかかるむンスタンスに぀いおテストしたい堎合に圹に立ちそうだず思いたした。

最埌に

今回のテストを実行しおみお、v1.7で远加されたモックでのテストはお手軜か぀結果がすぐ確認できるのが良いず思いたした。
ただリリヌスされたばかりで有効な䜿い方が思い぀いおいたせんが、むンフラ開発においおうたく䜿えるず結構圹に立぀ず思いたす。
䟋えば同䞀の環境を耇数䜜成する時のチェック項目をテストファむルにたずめおおき、そのテストファむルをプロゞェクト内で共有するこずで各自で簡単にテストを実行できる ずかでしょうか。

Terraformでの開発時はデプロむ埌の確認が結構倧倉なので、うたく掻甚しおいきたいず思いたした。