notebook

都内でWEB系エンジニアやってます。

DataformでAPIからパイプラインを実行する

Dataformで個人プロジェクトのデータ整形を行ってみた

そのときにAPIでパイプラインを実行したときのメモ

REST API

ドキュメントはこちら

Use the REST API | Dataform

docs.dataform.co

まだREST API自体がBetaらしく今の段階ではプロダクション導入とかは微妙かも

今回は個人活動の1つだったので使ってみる

API KEYの発行

画面から発行する

Project Settings -> API keysでAPI Keyを発行する

実行する

curlで実行できる

発行したAPI KEYを入れて次のようにするだけ、簡単

${project_id}はDataformのプロジェクトID

$ curl -H "Authorization: Bearer ${API_KEY}" -X POST -d '{"environmentName":"retake"}' https://api.dataform.co/v1/project/${project_id}/run
{
  "id":"11111111111111"
}

確認する

$ curl -H "Authorization: Bearer ${API_KEY}" https://api.dataform.co/v1/project/${project_id}/run/${run_id}
{
  "id": "11111111111111",
  "status": "SUCCESSFUL",
  "runLogUrl": "https://app.dataform.co/#/${project_id}/run/11111111111111"
}

project_idとCREATE RUN時に取得できるrun_idを使用してパイプラインの実行結果を確認する

失敗時はFAILED、実行中の場合はRUNNINGと表示される

こちらも簡単

実行時にConfigの値を書き換える

運用していくとなると特定の設定値を書き換えて実行したいみたいなパターンが出てくる(というか出てきた)

しかし、REST APIのリクエストBodyに何か入れて上書きするというのは2021-04-30時点ではできなそう

ドキュメントを読む限り渡せるデータの数が限られているのでvarsの内容を指定することはできない

Issueにも投げてみたが対応予定はないとのこと…

環境によってConfigの値を書き換える

Environments | Dataform

docs.dataform.co

Dataformにはenvironmentという概念がありこのenvironmentごとに設定を変えられる

これによりstaging,productionのように参照するブランチやdataset、schemaを変更し実行環境を分離することが可能(詳細はドキュメントを参照)

configOverride以下でdataform.jsonの設定値を上書きできる

  • dataform.json
{
    "warehouse": "bigquery",
    "defaultSchema": "dataform",
    "assertionSchema": "dataform_assertions",
    "defaultDatabase": "gcp-project-111111",
    "vars": {
        "targetMonth": "thisMonth"
    }
}
  • environments.json
{
  "environments": [
    {
      "name": "production",
      "gitRef": "master"
    },
    {
      "name": "retake",
      "configOverride": {
        "vars": {
          "targetMonth": "2021-03-01"
        }
      },
      "gitRef": "master"
    }
  ]
}

上記はvars.targetMonthの値を上書きするretakeという環境を設定している状態

設定ファイルに固定値を入れて実行すれば環境ごとに特定変数を書き換えることは可能

再実行などで動的に変数の値を変えたいパターン

今回はパイプラインの再実行などでtargetMonthの値を変えたいというパターン

想定としては次のように何度か値を変えて実行する可能性がある

  • 1回目:'2020-03-01'
  • 2回目:'2020-04-01'

手動でやるなら

  • environments.jsonを修正してpush
  • curlでAPI経由の実行を数回繰り返す

environmentsで変数の値を定義するパターンだと再実行の必要が出てきたら毎度このtargetMonthの内容を変更してpushして実行というような面倒なことをしなくてはならない

ただそれ以外に良い方法がなさそう…

CLIコマンドにはそういうオプションがありそうなのに…

ということで対応方法は上記の方法しか思い浮かばなかった

微妙なのは承知の上で再実行前にenvironments.jsonの中身を書き換えてpush+APIをたたく

再実行用のEnvironmentを用意(retake)してconfigOverride.vars.targetMonthを変更してpush+APIをたたく

こういう処理が必要なパターンはだいたいsourceのデータの更新もセットなことが多いイメージなのでそのあたりを含めて自動化はCI/CDサービスなりどこかのサーバなりで行う

通知に関して

Dataformでスケジューリングを組んだ場合はSlackへの通知がされるがAPI経由での実行は手動実行という扱いのようでenrivonment.jsonで設定をしても通知が来ない

これだと実行命令を投げっぱなしで成否がわからないので困る

CI/CDサービスの通知の方に乗っかるかーということで簡単なシェルスクリプトを書いた

  • bin/execute_dataform.sh
#!/bin/bash

environment=$1
project_id=${DATAFORM_PROJECT_ID}
api_token=${DATAFORM_API_TOKEN}
retry_count=0

polling() {
  run_id=$1

  run_status=$(curl -H "Authorization: Bearer ${api_token}" https://api.dataform.co/v1/project/${project_id}/run/${run_id})
  status=$(echo ${run_status} | jq -r '.status')

  case "$status" in
    "FAILED" )
      echo "FAILED JOB."
      exit 1
      ;;
    "SUCCESSFUL" )
      echo "SUCCESS JOB."
      ;;
    "RUNNING" )
      echo "retry wait 10 seconds..."
      sleep 10
      retry_count=$(($retry_count+1))
      polling ${run_id}
  esac
}

create_run=$(curl -X POST https://api.dataform.co/v1/project/${project_id}/run \
  -H "Authorization: Bearer ${api_token}" \
  -d @- <<EOS
{
  "environmentName":"${environment}"
}
EOS
)

run_id=$(echo $create_run | jq -r '.id')

sleep 30
polling ${run_id}
  • 実行部分
./bin/execute_dataform.sh retake

これでパイプラインの成否によって終了コードで判断可能になった

あとは実行環境で通知をさせればOK

まとめ

DataformのREST APIを用いてパイプラインの実行を行った

REST APIからのパラメータ指定に関してはissue投げてみたがサクッと閉じられてしまったので対応はされなそう…

あまりこういうパターンが想定されないのかなーと思いつつワークアラウンドでしのいでおくことにしました、個人のプロジェクトだし

いろいろスマートじゃないなーと思いつつも、DataformでSQL書いてデータ整形できる体験は結構良かったのでしばらく使いそう

Dataformはこういうかゆいところに…っていうのがまだ結構あるイメージなのでプロダクションで使えるかって言うと使える範囲が結構限定的なのかなと思ったりしている