本記事はAP Tech Blog Week Vol.4の参加記事です。
はじめに
こんにちは、ACS事業部の吉川です。
Terraformのv1.8より、Provider-defined functions という機能が追加されました。
どんな機能なのかを見ていきましょう。
どんな機能?
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
- PROVIDERS → providers
- 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の機能の紹介でした。
まだ出たばかりなので各プロバイダーでの関数実装は数少ない印象ですが、これから実用的な関数が増えていくのではと思います。関数をうまく使って、コードの書き方をシンプルにしていきたいですね。