はじめに
この記事では StackStorm (st2) で Workflow を作る際のポイントをまとめます。
ただしタイミングとして、StackStorm の難しいところを見つけたときに、その時点でのベスト・ベターな対応方法をポイントとしてまとめる形で、徐々に追記しながら充実させていこうと思っています。
StackStorm とは
StackStorm は Workflow Engine です。
HTTP アクセス、SSH ログインしてリモートサーバでコマンド実行、Slack 通知、、、などの Action/Workflow をパズルのピースのように組み合わせて、柔軟にオペレーションの自動化を行うことが出来ます。
StackStorm の難しいところ
Action や Workflow は YAML ファイルに定義を記述するのですが、ここに YAQL (Query Language) や jinja (template engine) が使うことが出来ます。
便利ではある一方で Action や Workflow を作っていく中で理解が難しく躓くこともしばしばあります。
[POINT] YAML ファイルがパース・評価される順序
YAML が StackStorm により読み込まれ、Action/Workflow として実行される際に考慮すべきポイントです。
※ 想像です。ソースコードを読んで裏付けが出来たら追記します。もし詳しくご存じの方がいればコメントください。
- YAML が解釈される
- データ型は Python の対応するデータ型へ変換される
- Action/Workflow が読み込まれるときに YAML による Syntax check が行われる
- つまり、YAQL / jinja を使う場合も使わない場合も YAML として正しい記法に則る必要があります
- YAML の文字列の中に書かれた YAQL / jinja 式が解釈される
- 評価が終わった文字列は適切な Python データ型へ解釈される
- String の "True" は boolean の True として解釈される
- String の "[]" は空 Array として解釈される
- ... etc
- YAQL/jinja の実行結果と StackStorm の Action/Workflow 定義との Syntax check が行われる
- YAQL/jinja は Action/Workflow が実行される際に評価される
- つまり、実行時に Syntax error が発生する可能性があります
- 評価が終わった文字列は適切な Python データ型へ解釈される
[POINT] Action の default 値を設定するポイント
- YAML だけで定義する場合は、基本型(String、Array、Boolean、Object)が Workflow で定義する type と一致するようにする
- Key-Value(st2kv) が定義されていた場合のみ default 値を上書きできるようにする場合は
st2kv.system.XXX | trim | d(XXX, true)
の形式にする
YAML だけで定義する場合
String
parameters:
param1:
type: string
default: DEFAULT_STRING
Array
parameters:
param1:
type: array
default:
- item1
- item2
Boolean
parameters:
param1:
type: boolean
default: false
Object
parameters:
param1:
type: object
default:
key1: value1
key2: value2
Key-Value(st2kv) が定義されていた場合のみ default 値を上書きできるようにする場合
st2kv.system.XXX
は st2kv に定義されているかどうかによらず、 <st2common.services.keyvalues.KeyValueLookup object>
として評価されます。
そのため、定義された値であるかどうかは jinja でも評価できるように文字列へ変換する必要があります。
ここで、trim
filter を使います。
すると、定義されていれば何らかの文字列となり、未定義の場合は空文字列("")となります。
続いて、default(省略形はd) filter へ渡すことで未定義の場合に default 値を設定することが出来ます。
ここで default filter の第 2 引数に false を設定した場合は undefined の値に対してのみ default 値を設定することになり空文字列が渡ってきても default 値を設定できません。
そこで第 2 引数に true を設定し、空文字列のような false として評価される値の場合に default 値を設定するようにしています。(参考)
This will output the value of my_variable if the variable was defined, otherwise 'my_variable is not defined'. If you want to use default with variables that evaluate to false you have to set the second parameter to true:
String
parameters:
param1:
type: string
default: "{{ st2kv.system.some_value | trim | d('DEFAULT_STRING', true) }}"
-
st2kv.system.some_value
が設定されているとその文字列が default 値となる -
st2kv.system.some_value
が設定されていいないと"DEFAULT_STRING"
が default 値となる
+------------------+--------------+
| Property | Value |
+------------------+--------------+
| name | some_value |
| value | HOGE |
| scope | st2kv.system |
| expire_timestamp | |
+------------------+--------------+
Array
parameters:
param1:
type: array
default: "{{ st2kv.system.some_value | trim | d([], true) }}"
-
st2kv.system.some_value
が設定されているとその値が default 値となる -
st2kv.system.some_value
が設定されていいないと[]
が default 値となる
+------------------+--------------+
| Property | Value |
+------------------+--------------+
| name | some_value |
| value | [100,200] |
| scope | st2kv.system |
| expire_timestamp | |
+------------------+--------------+
Boolean
parameters:
param1:
type: boolean
default: "{{ st2kv.system.some_value | trim | d('True', true) }}"
-
st2kv.system.some_value
が設定されているとその値が default 値となる -
st2kv.system.some_value
が設定されていいないと"True"
が default 値となる
ここで、st2kv.system.some_value
に "False" を設定した場合、default filter により "False" != false として判定されるため default filter は値を上書きしないという動作になります。
+------------------+--------------+
| Property | Value |
+------------------+--------------+
| name | some_value |
| value | False |
| scope | st2kv.system |
| expire_timestamp | |
+------------------+--------------+
Object
parameters:
param1:
type: object
default: "{{ st2kv.system.some_value | trim | d('{\"k1\":\"v1\",\"k2\":\"v2\"}', true) }}"
+------------------+-----------------+
| Property | Value |
+------------------+-----------------+
| name | some_value |
| value | {"key":"value"} |
| scope | st2kv.system |
| expire_timestamp | |
+------------------+-----------------+