はじめに
データ戦略室のaranです
今回で2回目の登場になります
月日は早いもので、入社して1年が過ぎました
私ごとですが
去年までは出社していたのですが、寒過ぎて朝起きれず
年末から座りっぱなしのリモートワークの日々を過ごし、節々の痛いと闘っています
不健康まっしぐらなので、最近は1時間弱の散歩を日課としています
今回のネタ
今回は、ゆるーいTipsです
最近、Terraformを使う機会が増えてきたこともあり
for文の2重ループを試してみました。
ググるとTerraformで2重ループは使えないとか
setproduct
を使えば、2重ループっぽいことができるよってブログを見つけましたが
for文の2重ループはできるようです
(そんなこと知っているよ!!って内容かもしれませんが、ご了承を)
お試しの構成
私は、データ基盤及びデータパイプラインの構築を担当していて
各種バッチは、主にGCP上で動かしており
IaCツールは、Terraformを使っています
ワークフローツールにCloud Workflowsを採用しており
cloud.google.com
今回の2重ループを試した部分は、Cloud Workflowsへ引数を渡す
Cloud Schedulerのパラメータの生成部分で、利用してみました
試したいと思った用途
生成したいパラメータで制御するのは、各テーブルをTransform(データ変換)するバッチの起動有無です
BigQueryにデータロードするバッチと、ロードしたデータを変換するバッチがあり
BigQueryにデータロードするバッチができたら、テーブルを作成するファイルを作成(追加)し
データ変換するバッチができたら、フラグを有効にしてパラメータに追記することをやりたいためです
ファイル構成
今回のお試しで、必要とするファイル構成は以下になります。
main.tf bg/<media>/native/table.json <media>は各媒体(google, yahoo, line等)
main.tf
にて、 bg/<media>/native/table.json
をロードします
module "xxx_gcp_workflow" { source = "./modules/gcp_workflow" ※cloud workflow作成に必要なパラメータをモジュール引数として渡す . . args = ※2重ループで各媒体 × table.jsonをロードして、パラメータを生成したい
媒体別のテーブルを定義したJSONファイル(bg/<media>/native/table.json
)の内容は以下の通りです。
今回、必要とするのは2項目(テーブル名とフラグ)になりますが
BigQueryのテーブル生成に必要なパラメータを管理しています。
[ { "name": "テーブル名", "description": "テーブル名の説明", "friendly_name": "テーブルのわかりやすい名前", "partition_field": "パーティション項目", . . . "do_transform": True(データ変換バッチの実行有無) }, { "name": "テーブル名", "description": "テーブル名の説明", "friendly_name": "テーブルのわかりやすい名前", "partition_field": "パーティション項目", . . . "do_transform": false(データ変換バッチの実行有無) }, . . . ]
サンプル
単純に for文を2つ記述すると構文エラーになるのですが、以下のように括弧を利用すると 今回の要件を満たす2重ループを実現できました
[ for media in var.medias : ([ for table in jsondecode(file("bg/${media}/native/tables.json")) : "{\"media\": \"${media}\",\"table\": \"${table["name"]}\"}" if table["do_transform"] ]) ]
実際にコマンド引数を生成したソースは、以下の通りです
2重ループで生成できた配列を1つの文字列にするため、joinとflattenを組み合わせています
locals { medias = ["media1", "media2", "media3", "media4"] } args = "[${join(", ", flatten([for media in local.medias : ([for table in jsondecode(file("bg/${media}/native/tables.json")) : "{\"param1\": \"${media}\",\"param2\": \"${table["name"]}\"}" if table["do_transform"] ]) ]))}]"
argsをデータ整形すると、以下のようになります
(実際の出力結果は1行です)
[ { "param1": "media1", "param2": "table1" }, { "param1": "media1", "param2": "table2" }, { "param1": "media1", "param2": "table3" }, { "param1": "media2", "param2": "table1" }, { "param1": "media2", "param2": "table3" }, { "param1": "media3", "param2": "table2" }, { "param1": "media4", "param2": "table1" }, { "param1": "media4", "param2": "table2" }, { "param1": "media4", "param2": "table4" } ]
if table["do_transform"]
によって
do_transform
項目が true
のテーブルのみ、出力することができました
さいごに
ググったブログの内容を鵜呑みにせず、できる手段がないかを探してみるが大切って
改めて認識できました