APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

【AP Tech Blog Week】TerraformのProvider-defined functionsを使ってみよう

本記事はAP Tech Blog Week Vol.4の参加記事です。

はじめに

こんにちは、ACS事業部の吉川です。
Terraformのv1.8より、Provider-defined functions という機能が追加されました。

www.hashicorp.com

どんな機能なのかを見ていきましょう。

どんな機能?

Terraformには関数が実装されており、文字列操作などの基本的な機能が実装されています。この関数機能をプロバイダー側で実装できる機能がProvider-defined functionsです。
標準の関数では実行できない機能を独自に実装したり、クラウドごとに固有の機能としてプロバイダーに実装された関数を利用できるという利点があります。

プロバイダーごとの関数

現在提供されているプロバイダーの関数を紹介します。
私は業務でAzure・Kubernetesを利用するケースが多いので、それぞれのプロバイダーを例に挙げて紹介します。

Azure Provider (azurerm)

normalise_resource_id

AzureのリソースIDの文字列について、大文字小文字を正しく整形します。
公式ドキュメント内の例を挙げると、

/Subscriptions/12345678-1234-9876-4563-123456789012/ResourceGroups/resGroup1/PROVIDERS/microsoft.apimanagement/service/service1/gateWays/gateway1/hostnameconfigurations/config1

という文字列を

/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/gateways/gateway1/hostnameConfigurations/config1

というように修正して出力します。

  • Subscriptions → subscriptions
  • ResourceGroups → resourceGroups
  • PROVIDERSproviders
  • microsoft.apimanagement → Microsoft.ApiManagement
  • gateWays → gateways
  • hostnameconfigurations → hostnameConfigurations

上記のように修正されていることが確認できます。

parse_resource_id

AzureリソースIDの文字列から、要素を分解してMap型に変換します。

/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/gateways/gateway1/hostnameConfigurations/config1

というリソースID文字列を、以下のように変換します。

{
  "full_resource_type" = "Microsoft.ApiManagement/service/gateways/hostnameConfigurations"
  "parent_resources" = tomap({
    "gateways" = "gateway1"
    "service" = "service1"
  })
  "resource_group_name" = "resGroup1"
  "resource_name" = "config1"
  "resource_provider" = "Microsoft.ApiManagement"
  "resource_scope" = tostring(null)
  "resource_type" = "hostnameConfigurations"
  "subscription_id" = "12345678-1234-9876-4563-123456789012"
}

リソースグループ名を取り出して別リソース作成時の入力値に使ったり、便利に使える機能かと思います。

Kubernetes Provider (kubernetes)

manifest_decode / manifest_encode

Kubernetesマニフェストファイルを読み込んでMap型に変換します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

というファイルを読み込んで、

{
  "apiVersion" = "apps/v1"
  "kind" = "Deployment"
  "metadata" = {
    "labels" = {
      "app" = "nginx"
    }
    "name" = "my-nginx"
  }
  "spec" = {
    "replicas" = 3
    "selector" = {
      "matchLabels" = {
        "app" = "nginx"
      }
    }
    "template" = {
      "metadata" = {
        "labels" = {
          "app" = "nginx"
        }
      }
      "spec" = {
        "containers" = [
          {
            "image" = "nginx:1.14.2"
            "name" = "nginx"
            "ports" = [
              {
                "containerPort" = 80
              },
            ]
          },
        ]
      }
    }
  }
}

という形に変換します。

1つのマニフェストファイル内に複数の定義が入っている場合に利用する manifest_decode_multi という関数もあります。

manifest_encodeはこの逆で、Map型の変数からYAMLに変換できます。

おわりに

比較的新しいTerraformの機能の紹介でした。
まだ出たばかりなので各プロバイダーでの関数実装は数少ない印象ですが、これから実用的な関数が増えていくのではと思います。関数をうまく使って、コードの書き方をシンプルにしていきたいですね。

本記事の投稿者: 吉川 俊甫
夏休みの宿題は最後まで残す派でした。Microsoft MVP (Microsoft Azure)
Shunsuke Yoshikawa - Credly