Terraform version 1.7の新機能モックテストを使ってみた

2024.01.31

2024/01/17にTerraformのversion 1.7がGA(一般提供開始)になりました。本versionよりterrraform testにてモックが利用できるようになりました。

どういう機能?

version 1.6で導入されたterraform testですが、version 1.6では実際のproviderの設定を使い、実際のリソースをプロビジョニングし(あるいはcommand = planにした場合はplan結果を作成し)、data sourceも実際にデータを取得してきて、その結果について conditionに書いた条件式でテストする、というものでした。

テスト用にAWSなどのproviderの設定を上書きする(例えばテストのときだけAWSリージョンを変えるなど)ことや、変数を上書きあるいは新規追加などすることでプロビジョニングされるリソースの設定値を変えることは出来ましたが、それでもproviderのクレデンシャルが必要になり、providerのAPIにアクセスすることは同じでした。

新機能のモックにより、指定したprovider配下のresource/data source全般をモック化したり、一部の resource / data source / moduleをモック化する事ができるようになりました。これによりterrafrom test実行時にproviderのクレデンシャルを用意したり、APIにアクセスする必要がなくなりました。またRDSインスタンスなど作成に時間がかかるリソースをモックにすることでテスト実行時間の大幅短縮も狙えます。総じて、もっと手軽にテストできるようになりました。

  • テスト実行するCIジョブ(もしくはローカルから実行する場合は開発者)にprovider(AWSなど)の強権限を持たせたくない
  • providerのAPIにアクセスできない環境からでもテストを実行したい
  • テストの実行時間が長すぎて待ってられない

などといった状況でもterraform testするという選択肢が増えました。

一部のresource / data source をモック化する

override_resource {
  target = aws_s3_bucket.main
}

override_data {
  target = data.http.index
}

targetで上書きするresource / data source を指定します。

任意のattribute valuesによって、resource / data source のattributesを指定することもできます。

status_codeを指定した例

override_data {
  target = data.http.index
  values = {
    status_code = 404
  }
}

valuesで指定しなかった、かつ computed attributesであった場合は、その値はデータタイプ毎に以下になります。

  • Numbers → 0
  • Boolean (true or false) → false
  • Strings → ランダムな英数字8文字
  • Collections(sets, lists, maps) → 空
  • Objects → 配下のattributesに上記ルールが適用される

moduleをモック化する

override_resourceoverride_dataと同様 targetで上書き対象のアドレスを指定する点は同じです。

異なる点は任意の任意のattribute valuesは無く、代わりにoutputs があり、その mock moduleのoutputsを指定することができます。

override_module {
  target = module.eks
  outputs = {
    cluster_endpoint = "https://hogehoge.gr7.ap-northeast-1.eks.amazonaws.com"
  }
}

Providerのモック

mock_provider "aws" {}

テストファイル(xxx.tftest.hcl)にこれだけを書いておけば、そのファイル内でAWS providerのresourceとData Sourceはモック化されます。

以下のようにaliasを使って、そのaliasだけモック化することも出来ます。

mock_provider "aws" {
  alias = "mock"
}

run "mock_test" {
  providers = {
    aws = aws.mock	
  }
}

また、以下のようにmock_providerの内部にmock_resource mock_dataを書いて特定のresorce / data sourceのattribute値を指定することもできます。

mock_provider "aws" {
  mock_resource "aws_s3_bucket" {
    defaults = {
      arn = "arn:aws:s3:::name"
    }
  }

  mock_data "aws_s3_bucket" {
    defaults = {
      arn = "arn:aws:s3:::name"
    }
  }
}

感想

Terraform version 1.7の新機能モックをご紹介しました。1.6時点ではあんまりテストコードを書く気にならなかったのですが、本機能により今後は書いていきたいなと思いました。とはいえ当然ですが非モックのテストが不要になるわけでは全く無く、モックテストで細かく確認しつつ、applyまでには非モックのテストも通してみるといった使い分けが大事になってくるかなと思います。

参考情報