困っていること、やりたいこと
digdag + embulk の環境において、embulk の設定ファイルで共通部分を include で共有している。 → 参考
ディレクトリの構造上、複数のプロジェクトにまたがって同じ設定を利用したいが、
仕様上、include する設定ファイルより上の階層からは include できないため、
現状は、まったく同じ設定ファイルを各プロジェクトの中に配置しているため気持ちが悪い。
具体的には、embulk-input-bigquery, emublk-output-bigquery の設定が記載されている。
設定が変更になったときに、すべてのファイルを変えなければならないため管理上問題がある。
これをなんとかする方法を知りたい。
サービスDBから生データを BigQuery に入れ、そのデータを集計した結果を BigQuery にいれるというようなことをしている
ファイル構成
commons 配下の _in_bigquery.yml.liquid と _out_bigquery.yml.liquid がまったく同じファイル
parent.dig
project1/
├ project1_child.dig
├ project1_conf1.yml.liquid
├ project1_conf2.yml.liquid
├ commons/
│ ├ _in_mongodb.yml.liquid
│ ├ _in_bigquery.yml.liquid
│ ├ _out_bigquery.yml.liquid
project2/
├ project2_child.dig
├ project2_conf1.yml.liquid
├ project2_conf2.yml.liquid
├ commons/
│ ├ _in_mysql.yml.liquid
│ ├ _in_bigquery.yml.liquid
│ ├ _out_bigquery.yml.liquid
+daily:
+project1:
!include : 'project1/project1_child.dig'
+project2:
!include : 'project2/project2_child.dig'
+daily:
_export:
OUTPUT_DATASET_NAME: xxx
+task1:
_export:
INPUT_TABLE_NAME: xxx
OUTPUT_TABLE_NAME: xxx
+embulk:
sh>: embulk run project1_conf1.yml.liquid
+task2:
_export:
INPUT_TABLE_NAME: xxx
OUTPUT_TABLE_NAME: xxx
+embulk:
sh>: embulk run project1_conf2.yml.liquid
{% include 'commons/in_bigquery' %}
# 実際には何らかの集計クエリ
sql: SELECT * FROM {{ env.INPUT_TABLE_NAME }}
{% include 'commons/out_bigquery' %}
dataset: {{ env.OUTPUT_DATASET_NAME }}
table: {{ env.OUTPUT_TABLE_NAME }}
auto_create_table: true
mode: replace
prevent_duplicate_insert: true
in:
type: bigquery
keyfile: xxx.json
project: xxx
out:
type: bigquery
auth_method: json_key
json_keyfile: xxx.json
project: xxx
gcs_bucket: xxx
auto_create_gcs_bucket: true
compression: GZIP
試したこと
仕組み上プロジェクト外のファイルは参照できないので、yaml_masterとか使って複数プロジェクトに共通の設定ファイルを出力するとかの方がよいかもしれませんね。https://t.co/GuS56DRHjt
— hiroyuki sato (@hiroysato) August 23, 2018
@hiroysato さんにアドバイスを頂き、yaml_master を使い、
_in_bigquery.yml.liquid と _out_bigquery.yml.liquid をそれぞれのプロジェクト内に出力するようにしました。
yaml_master の仕様上、先頭に --- がつくので、実際に出来上がる project1_conf1.yml.liquid は以下のようになり、複数の yaml ファイルとみなされてしまい動きません。
というところで今、詰まっているところです。
yaml_master:
project1_in_bigquery: project1/commons/_in_bigquery.yml.liquid
project2_in_bigquery: project2/commons/_in_bigquery.yml.liquid
project1_out_bigquery: project1/commons/_out_bigquery.yml.liquid
project2_out_bigquery: project2/commons/_out_bigquery.yml.liquid
data:
project1_in_bigquery: !include _in_bigquery.yml.liquid
project2_in_bigquery: !include _in_bigquery.yml.liquid
project1_out_bigquery: !include _out_bigquery.yml.liquid
project2_out_bigquery: !include _out_bigquery.yml.liquid
include している _in_bigquery.yml.liquid、_out_bigquery.yml.liquid は、少し上のものとまったく同じです。
$ yaml_master -m master.yml --all
実行した結果できあがったものが以下
---
in:
type: bigquery
keyfile: xxx.json
project: xxx
---
out:
type: bigquery
auth_method: json_key
json_keyfile: xxx.json
project: xxx
gcs_bucket: xxx
auto_create_gcs_bucket: true
compression: GZIP
それによって出来上がった project1_conf1.yml.liquid は以下
---
in:
type: bigquery
keyfile: xxx.json
project: xxx
# 実際には何らかの集計クエリ
sql: SELECT * FROM {{ env.INPUT_TABLE_NAME }}
---
out:
type: bigquery
auth_method: json_key
json_keyfile: xxx.json
project: xxx
gcs_bucket: xxx
auto_create_gcs_bucket: true
compression: GZIP
dataset: {{ env.OUTPUT_DATASET_NAME }}
table: {{ env.OUTPUT_TABLE_NAME }}
auto_create_table: true
mode: replace
prevent_duplicate_insert: true
本当に欲しいのはこれ
in:
type: bigquery
keyfile: xxx.json
project: xxx
# 実際には何らかの集計クエリ
sql: SELECT * FROM {{ env.INPUT_TABLE_NAME }}
out:
type: bigquery
auth_method: json_key
json_keyfile: xxx.json
project: xxx
gcs_bucket: xxx
auto_create_gcs_bucket: true
compression: GZIP
dataset: {{ env.OUTPUT_DATASET_NAME }}
table: {{ env.OUTPUT_TABLE_NAME }}
auto_create_table: true
mode: replace
prevent_duplicate_insert: true
よくよく考えると、実質的に _in_bigquery.yml.liquid と _out_bigquery.yml.liquid を各プロジェクトにコピーしているだけなので
そういうシェルを書いて、変更があったときに修正して実行するだけか…?
そもそもプロジェクトまたがって1つで実行しようとしていることが間違っているのか
プロジェクトごとにディレクトリ分けずに1つに突っ込めとなるのか
こういうケースのベストプラクティスを知りたい。
結局どうしたか
Twitterで @hiroysato さん @joker1007 さんにアドバイスをいただき
今回のケースでは、共通部分の設定ファイルを上位におき、変更があったときにそこから各所にコピーするシェルを実行する、としました。
もし project1_conf1.yml.liquid をある程度共通化できるようなケースであれば yaml_master が最適かもしれません。
commons/
├ _in_bigquery.yml.liquid
├ _out_bigquery.yml.liquid
copy.sh
parent.dig
project1/
├ project1_child.dig
├ project1_conf1.yml.liquid
├ project1_conf2.yml.liquid
├ commons/
│ ├ _in_mongodb.yml.liquid
│ ├ _in_bigquery.yml.liquid
│ ├ _out_bigquery.yml.liquid
project2/
├ project2_child.dig
├ project2_conf1.yml.liquid
├ project2_conf2.yml.liquid
├ commons/
│ ├ _in_mysql.yml.liquid
│ ├ _in_bigquery.yml.liquid
│ ├ _out_bigquery.yml.liquid