terraform testにてMockプロバイダーを試してみた

以前terraform testを試しましたが、terraform test機能としてMockプロバイダーがTerraform v1.7よりサポートされております。

github.com

今回は本機能を試してみようと思います。

Mockプロバイダーとは

Mockプロバイダーとは、Terraformのテスト環境で使用される疑似プロバイダーです。

実際のリソース作成や、APIの呼び出しは行わず、応答が可能となります。

developer.hashicorp.com

前提条件

前提条件として、以下Terratermバージョンが必要となります。

  • Terraformのバージョン:v1.7 以上

事前準備

リソース作成用のTerraform定義ファイルを作成する

リソース作成用の定義ファイルを作成します。

terraform testを試してみた際と同様に、既存リソースグループにStorage AccountとLog Analyticsワークスペースを作成し、Storage Accountの診断ログをLog Analyticsワークスペースに収集を作成する定義ファイルを作成しました。

【main.tf】

# Env info
provider "azurerm" {
  features {}
  subscription_id = var.subscription_id
  tenant_id       = var.tenant_id
}

# Azure Provider
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~>4.32.0"
    }
  }

  # Store Terraform state in Azure Storage
  backend "azurerm" {
    resource_group_name  = "<Resource Group名(状態格納用ストレージアカウントが格納されているResource Group)>"
    storage_account_name = "<Storage Account名>"
    container_name       = "<Blob Container名>"
    # Statment File Name
    key = "terraform.tfstate"
  }
}

【rg.tf】

#-------------------------------
# Resource Group
#-------------------------------

# Resource Group
data "azurerm_resource_group" "rg" {
  name = var.resource_group_name
}

【st.tf】

#-------------------------------
# Storage Account
#-------------------------------

# Storage Account
resource "azurerm_storage_account" "st" {
  name                     = var.st_name
  resource_group_name      = data.azurerm_resource_group.rg.name
  location                 = data.azurerm_resource_group.rg.location
  account_tier             = var.st_tier
  account_replication_type = var.st_rep

  depends_on = [
    data.azurerm_resource_group.rg
  ]
}

resource "azurerm_monitor_diagnostic_setting" "diag" {
  name                       = var.diag_name
  target_resource_id         = "${azurerm_storage_account.st.id}/fileServices/default/"
  log_analytics_workspace_id = azurerm_log_analytics_workspace.log.id

  enabled_log {
    category = "StorageRead"
  }

  enabled_metric {
    category = "Transaction"
  }

  depends_on = [
    azurerm_log_analytics_workspace.log,
    azurerm_storage_account.st
  ]
}

【log.tf】

#-------------------------------
# Log Analytics Workspace
#-------------------------------

resource "azurerm_log_analytics_workspace" "log" {
  name                = var.log_name
  location            = data.azurerm_resource_group.rg.location
  resource_group_name = data.azurerm_resource_group.rg.name
  sku                 = var.log_sku
  retention_in_days   = var.log_day

  depends_on = [
    data.azurerm_resource_group.rg
  ]
}

【variables.tf】

#-------------------------------
# 基本変数定義
#-------------------------------
# Subscription ID
variable "subscription_id" {}
# TenantID
variable "tenant_id" {}
# Region
variable "location" {
  default = "japaneast"
}

#-------------------------------
# Resource Group
#-------------------------------
# Resource Group Name
variable "resource_group_name" {
  default = "nishiyamas-tf-rg"
}

#----------------------------------
# Storage Account
#----------------------------------
# Storage Account Name
variable "st_name" {
  default = "<Storage Account名>"
}
# Tier
variable "st_tier" {
  default = "Standard"
}
# Replication
variable "st_rep" {
  default = "LRS"
}
# Diagnostic Settings Name
variable "diag_name" {
  default = "st_diag01"
}

#----------------------------------
# Log Analytics Workspace
#----------------------------------
# Log Analytics Workspace Name
variable "log_name" {
  default = "nishiyamas-tf-log01"
}
# SKU
variable "log_sku" {
  default = "PerGB2018"
}
# Retention Days
variable "log_day" {
  default = 30
}

【terraform.tfvars】

# Tenand ID
tenant_id = "<Tenant ID>"

# SubScription ID
subscription_id = "<Subscription ID>"

テストファイル(.tftest.hcl)を作成する

テストファイルを作成します。

terraform testを試してみた際と同様に、テストファイルでは「run」ブロック内にterraform testにて実施する内容を記載します。

テストファイルはカレントディレクトリ、もしくはカレントディレクトリ配下の「tests」ディレクトリ内のファイルを参照します。

Mockプロバイダーの定義が別途必要なため、各ファイルに「mock_provider "azurerm" {}」を追記しております。

また、以下に記載がある通り、明示的なデフォルトが提供されていない属性(computed attributes)は、デフォルトのランダム値生成等の生成ルールが適用されるため、明示的に指定がない値はテスト対象から除外しています。

Computed attributes not provided an explicit default will simply fall back to the generic data generation rules.

developer.hashicorp.com

※例えば、terraform testを試してみた際に確認したStorage Account、Log AnalyticsワークスペースのLocationの確認をテストファイルに入れた状態で実行すると、それぞれ明示的に値を指定していないためランダムな値が生成され、以下のようにエラーが発生します。

エラー画面

【log_test.tftest.hcl】

mock_provider "azurerm" {}

variables {
  log_name      = "nishiyamas-tf-log01"
  log_sku       = "PerGB2018"
  log_day       = 30
}

run "log_test" {
    command = plan
    assert {
        condition = azurerm_log_analytics_workspace.log.name == var.log_name
        error_message = "${azurerm_log_analytics_workspace.log.name} の名称を ${var.log_name} に修正してください。"
    }
    assert {
        condition = azurerm_log_analytics_workspace.log.sku == var.log_sku
        error_message = "${azurerm_log_analytics_workspace.log.name} のSKUを ${var.log_sku} に修正してください。"
    }
    assert {
        condition = azurerm_log_analytics_workspace.log.retention_in_days == var.log_day
        error_message = "${azurerm_log_analytics_workspace.log.name} のログ保持期間を ${var.log_day} 日に修正してください。"
    }
}

【st_test.tftest.hcl】

mock_provider "azurerm" {}

variables {
  st_name                = "<Storage Account名>"
  diag_name              = "st_diag01"
  diag_log_category      = "StorageRead"
  diag_metric_category   = "Transaction"
}

run "st_conf_test" {
    command = plan
    assert {
        condition = azurerm_storage_account.st.name == var.st_name
        error_message = "${azurerm_storage_account.st.name} の名称を ${var.st_name} に修正してください。"
    }
}

run "st_diag_test" {
    command = plan
    assert {
        condition = azurerm_monitor_diagnostic_setting.diag.name == var.diag_name
        error_message = "${azurerm_monitor_diagnostic_setting.diag.name} の名称を ${var.diag_name} に修正してください。"
    }
    assert {
        condition = contains(
            [
                for log in azurerm_monitor_diagnostic_setting.diag.enabled_log : log.category
            ], 
            var.diag_log_category
        )
        error_message = "${azurerm_monitor_diagnostic_setting.diag.name} に ${var.diag_log_category} のカテゴリを追加してください。"
    }
    assert {
        condition = contains(
            [
                for log in azurerm_monitor_diagnostic_setting.diag.enabled_metric : log.category
            ], 
            var.diag_metric_category
        )
        error_message = "${azurerm_monitor_diagnostic_setting.diag.name} に ${var.diag_metric_category} のカテゴリを追加してください。"
    }
}

ディレクトリ構成は以下の通りです。

ディレクトリ構成

terraform testを実行する

terraform testを実行していきます。

設定値が正しい状態で実行する

設定値が正しい状態でterraform testを実行します。

terraform test実行画面

現在の状態では問題なくpassされていることが確認できます。

設定値が誤った状態で実行する

次に、設定値が誤った状態で実行していきます。

st.tfを一部設定変更する

st.tfのStorage Accountの診断設定で取得するカテゴリを「StorageRead」から「StorageWrite」に変更します。

【st.tf ※一部抜粋】

  enabled_log {
    category = "StorageWrite" # 更新
  }
terraform testを実行する

再度terraform testを実行します。

terraform test実行画面
設定値が誤った箇所にてエラーが発生することが確認できます。

おわりに

本記事を最後までお読みいただき、ありがとうございます。

TerraformのMockプロバイダーを利用することで、実環境に影響を与えることなくリソースの動作確認やテストが可能となります。これにより、インフラ構築や運用における品質向上と効率化が期待できます。

本記事がTerraformを使用する際の参考となれば幸いです。

執筆担当者プロフィール
西山 正太郎

西山 正太郎(日本ビジネスシステムズ株式会社)

クラウドソリューション事業本部に所属。近年は業務で主にMicrosoft Azureに携わっています。山登りが趣味です。

担当記事一覧