まだnull_resourceでがんばっているの?
2022-12-05
azblob://2022/12/02/eyecatch/2022-12-05-azapi-resource-000.jpg

こちらはFIXER Rookies Advent Calendar 2022の5日目の記事です。

みんな大好きAzureくん。

 そんなAzureのリソースをTerraformでコード化する業務を普段行っているのですが、最近null_resourceで書かれたコードをazapi_resourceに書き換える機会が多かったためメモ代わりに共有していきたいと思います。

そもそもnull_resourceとは?

null_resourceを用いることにより、Providerが存在しない処理をTerraformで実行することができます。

resource "null_resource" "this" {
  triggers = {
    rg_name = local.resource_group_name
  }

  provisioner "local-exec" {
    command     = <<EOT
      az group show --name ${self.triggers.rg_name}
    EOT
    interpreter = ["pwsh", "-Command"]
  }
}
{
  "mode": "managed",
  "type": "null_resource",
  "name": "this",
  "provider": "provider[\"registry.terraform.io/hashicorp/null\"]",
  "instances": [
    {
      "schema_version": 0,
      "attributes": {
        "id": "376976211",
        "triggers": {
          "rg_name": "<リソースグループ名>"
        }
      },
      "sensitive_attributes": []
    }
  ]
}

しかしnull_resourceは名前の通りリソースが存在しないプロバイダーのため、tfstateを確認するとinstancesの中に処理の結果が記録されず、null_resourceと他のProvider間の依存関係をTerraformはサポートしません。

メリット

  • Terraform上でリソースの作成 & が実現できる
  • Terraformでサポートされていない処理を実装できる

デメリット

  • コード間の依存関係を持つことが難しい
  • 内部の処理をtfstate上で確認することができず、デバッグ等が難しい

azapi_resourceで安心安全の処理を実現

そこでazapi_resourceをできる限り使いましょう。 これはAzure REST APIをTerraformで実行&管理するProviderです。 先ほどnull_resourceで挙げた例をazapi_resourceで再現した場合、

# az group show --name <リソースグループ名>   
data "azapi_resource" "this" {
  type      = "Microsoft.Resources/resourceGroups@2021-04-01"
  name      = local.resource_group_name
  parent_id = "/subscriptions/${var.subscription_id}"

  response_export_values = ["properties.loginServer", "properties.policies.quarantinePolicy.status"]
}
{
  "mode": "data",
  "type": "azapi_resource",
  "name": "this",
  "provider": "provider[\"registry.terraform.io/azure/azapi\"]",
  "instances": [
    {
      "schema_version": 0,
      "attributes": {
        "id": "/subscriptions/<サブスクリプションID>/resourceGroups/<リソースグループ名>",
        "identity": [],
        "location": "westus3",
        "name": "<リソースグループ名>",
        "output": "{}",
        "parent_id": "/subscriptions/<サブスクリプションID>",
        "resource_id": null,
        "response_export_values": [
          "properties.loginServer",
          "properties.policies.quarantinePolicy.status"
        ],
        "tags": {},
        "timeouts": null,
        "type": "Microsoft.Resources/resourceGroups@2021-04-01"
      },
      "sensitive_attributes": []
    }
  ]
}

tfstate上に処理の結果が記録されるため、azapi_resourceで実行したデータを他のProviderに反映することができ、依存関係をTerraformが保証するため、Azure RedHat OpenShiftAzure Container Appsなど作成に時間がかかるリソースはazapi_resourceを活用した方が安全安心です。

メリット

  • Azure Portalで実現可能な作業 ≒ Terraformで再現可能
  • tfstate上に実行ログが残るため、デバッグ時に重宝する
  • 他のProviderと明確な依存関係を持つことができる

デメリット

  • ignore_changesでフィールド名を個別に宣言することができず、bodyしか宣言できない。

まとめ

azapi_resourceを使うことにより、依存関係がはっきりしたコードを書くことができるため、できる限りnull_resource「えいや~~~」っとコードを書かないようにしましょう。 また筆者は最近Terraformの限界を感じ始めたので、「Azure SDK for GoでIaCを実現した方がリソースの作成+αが簡単にできて便利なのでは???」と模索しています。