実行時に引数を渡すときにデフォルト値を設定したい
というよくあるパターンをWorkflowsで行えるか試してみた
今回は失敗したパターンも書きながら流れを追って書いていく
結論だけ知りたい方は最後の方を見てください
ランタイム引数の扱い
Workflowsでランタイム引数を扱う場合は次のドキュメントを読めば良い
実行リクエストでのランタイム引数渡し | ワークフロー | Google Cloud
以下実際に試してみたログも合わせて書いていく
dict.getでデフォルト値を指定する
ランタイム引数をargs
として扱う
Pythonの関数を使える部分があったので内部的にはPythonを使っているのだろう
argsに対してdict.get
でデフォルト値を指定すれば簡単に設定できるのでは?
とういことで試してみたがデプロイ時にパースエラーを吐かれて終了した
- arguments.workflow.yml
main: params: [args] steps: - step0: assign: - argsDict: dict(args) - step1: assign: - firstName: ${argsDict.get('firstName', "defaultFirstName")} - lastName: ${argsDict.get('lastName', "defaultLastName")} - step2: assign: - OutputVar: ${"Hello, " + firstName + " " + lastName + "!"} - step3: return: ${OutputVar}
ERROR: (gcloud.workflows.deploy) [INVALID_ARGUMENT] main.yaml:9:24: parse error: in workflow 'main', step 'step1': token recognition error at: ''' - firstName: ${argsDict.get('firstName', "defaultFirstName")} ^ main.yaml:9:24: parse error: in workflow 'main', step 'step1': token recognition error at: ''' - firstName: ${argsDict.get('firstName', "defaultFirstName")} ^ main.yaml:10:23: parse error: in workflow 'main', step 'step1': token recognition error at: ''' - lastName: ${argsDict.get('lastName', "defaultLastName")} ^ main.yaml:10:23: parse error: in workflow 'main', step 'step1': token recognition error at: ''' - lastName: ${argsDict.get('lastName', "defaultLastName")} ^
そもそもパース時にシングルクオートが使用できないよう
ダブルクオートにしても違うエラーでデプロイできず
ERROR: (gcloud.workflows.deploy) [INVALID_ARGUMENT] failed to build: error in step step1: error evaluating the value to assign: call target must be a symbolic reference to a sub-workflow
サブワークフローを使う
Syntax reference | ワークフロー | Google Cloud
サブワークフローを使うとデフォルト値がサポートされているのでそっちでよしなにやるのが良さそう
ドキュメントからサンプルを引っ張ってきて少し調整して試してみた
- arguments.workflow.yml
main: params: [args] steps: - call_subworkflow: call: build_output args: first_name: ${args.first_name} last_name: ${args.last_name} result: output - return_message: return: ${output} build_output: params: [first_name: "default_first_name", last_name: "default_last_name"] steps: - build_message: return: ${"Hello, " + first_name + " " + last_name + "!"}
$ gcloud workflows deploy argument --source=argument.workflow.yml $ gcloud workflows run argument --data='{"first_name":"hoge"}' error: context: |- KeyError: key not found: first_name in step "call_subworkflow", routine "main", line: 7 payload: '{"message":"KeyError: key not found: first_name","tags":["KeyError","LookupError"]}' stackTrace: elements: - position: column: '23' length: '18' line: '7' routine: main step: call_subworkflow state: FAILED
だめだった
そもそもサブワークフローに引数を渡すときにLookupしているのでその時点でエラーが発生する
サブワークフローを組み合わせて最終的にはdictを生成し直す(結論)
最後は若干パワープレイ感があるがこれで行けた
- arguments.workflow.yml
main: params: [args] steps: - call_subworkflow: call: build_params args: arg_params: ${args} result: params - return_message: return: ${params} build_params: params: [arg_params] steps: - fix_first_name: call: fix_value args: params: ${arg_params} key: first_name default: hoge result: fixed_first_name - fix_last_name: call: fix_value args: params: ${arg_params} key: last_name default: fuga result: fixed_last_name - build: assign: - fixed_params: first_name: ${fixed_first_name} last_name: ${fixed_last_name} - return_value: return: ${fixed_params} fix_value: params: [params, key, default] steps: - check_value: switch: - condition: ${key in params} return: ${params[key]} - condition: ${not(key in params)} return: ${default}
こんな感じでサブワークフローを2つ用意する
- fix_value
- dict、key、デフォルト値を受け取って受け取ったdictに対象キーの値があるかチェックしなければデフォルト値を返すワークフロー
- build_params
- assignでよしなにdictの形を整えて返すワークフロー
- デフォルト値とキーの値をデフォルト値を設定したい引数分すべて記述する
- assignでよしなにdictの形を整えて返すワークフロー
$ gcloud workflows run argument --data='{}' result: '{"first_name":"hoge","last_name":"fuga"}' state: SUCCEEDED $ gcloud workflows run argument --data='{"first_name":"piyo"}' result: '{"first_name":"piyo","last_name":"fuga"}' state: SUCCEEDED
引数として渡したものに対しては上書きできることが確認できた
ただこの方法だとサブワークフローの中でその後使うパラメータをすべて列挙する必要があるのでデフォルト指定が必要ないものまで書く必要があるので冗長である
欲をいえばデフォルト値が必要なものだけ記述できるようにしたい
おまけ
GUIの詳細を見に行くと可視化部分ではワークフロー単位でフロー図が出力される
なので上記のワークフローだとこんな感じ
正直これ見ただけでイメージ湧くかというと何とも言えない…
所感
- 無事引数のデフォルト値を指定できるようになった
- 引数のJSONがネストしていたりするとそれに合わせて修正する必要がある
- サブワークフローを使いこなせればわりと書きやすそうに感じた
- 前回も書いたが式の中で配列や辞書を生成できなさそうなのがつらい
- 前回も書いたがPythonのメソッドで使えるものリストが欲しい(どこにあるの)
前回の記事はこちら
GCPのCloud Workflowsを試す - notebook
また、今回のサンプルの定義ファイルは以下においた