Slide 1

Slide 1 text

明日からできる、st2のActionの作り方 Wataru Manji

Slide 2

Slide 2 text

自己紹介 ● 名前: 萬治 渉 (マンジ ワタル) ● 所属: ○ NTTテクノクロス株式会社 IoTイノベーション事業部 ○ 日本StackStormユーザ会 ● 仕事: ○ OpenStack基盤の設計、運用、保守 ○ StackStorm関係色々 ○ その他AnsibleとかNWとか色々 ● 連絡先: ● Twitter: @_manji0 ● Mail: [email protected]

Slide 3

Slide 3 text

みなさん、Action書いてますか??? (・ω・)ノ <ハーイ 1. プロダクションでバリバリ書いてる 2. 手習い程度に書いてる 3. 公開されてるものを使ってるだけで、書いてない 4. Action? ナニソレ? Todays Target

Slide 4

Slide 4 text

Action作成のノウハウはいっぱいある ● Action入出力を定義する方法 ● ActionのPythonコードの記述方法 ● etc ○ Workflow内で扱いやすいActionの入出力とは ○ Actionの適切な粒度とは ○ Actionコードの形式別の記述方法 ○ 開発中Actionのテスト方法 ○ ... おおまかな勉強順序

Slide 5

Slide 5 text

その中で今回話すこと ● Action入出力を定義する方法 ○ 入力: ActionのMetadataについて ○ 出力: Actionの出力形式、および構造化データの扱いについて ● ActionのPythonコードの記述方法 ○ 基本的な形式と要素の解説 ● etcは話す時間が無いのでまたいつか

Slide 6

Slide 6 text

今回のゴール ● Actionの入出力を定義する方法について理解している ● Python, BashでActionコードを記述する方法を知っている = Actionの「箱」について理解しており、 明日から「自分の作りたいAction」を作り始められること

Slide 7

Slide 7 text

※全ての前提知識について話す時間は無い ピンからキリまで20分で話すのは不可能... なので、今回はAction, Workflow, Ruleなどの分類については話しません。 必要に応じて以下の情報を参考にすることで、フォローできるかと思います。 (どっちも作成に関わってるので、質問にも答えられます) ● st2の概要&特徴 ○ https://speakerdeck.com/ntttechnocross/ntt-techconference-number-2-stackstorm ● workflowやruleの書き方 ○ https://github.com/internetweek2017-st2/handson_documents

Slide 8

Slide 8 text

前提: チョット分かるActionの構造

Slide 9

Slide 9 text

チョット分かるActionの構造 metadata ・Actionコードの形式、path ・入力の定義 Actionコード ・実行内容の記述 ・return値の定義 st2 ・metadataに書かれた 情報の管理 ・実行リクエストの解釈 metadataで指定された Action-Codeを 指定された入力で起動 実行結果をst2にreturn 事前にst2へActionの 情報を渡す

Slide 10

Slide 10 text

Actionの入出力について

Slide 11

Slide 11 text

それぞれ、どこで定義しているの? ● 入力: metadata内 ○ metadata内での定義記述箇所 ○ 指定できるオプション ● 出力: Actionコード内 ○ st2の出力定義 ○ Actionコード内での出力方法 ○ 構造化データの取り扱い 順番に解説。

Slide 12

Slide 12 text

入力の定義: metadata.parameters ● metadata: ActionやWorkflowの名前、コード位置や入力を定義するファイル ● parametersセクションで入力を定義する ○ 入力の名前 ○ 入力値の型 ○ 入力値の初期値 ○ 入力の必須/任意の選択 ○ etc... ● metadataで定義していない入力は基本的に使うことができない (やり方はあるが、今回は解説しない)

Slide 13

Slide 13 text

metadata.parametersの記述方法(基本) # 前略 parameters: hostname: type: string required: true hoge: type: string ... ● YAMLの辞書形式で書いていく ● ここでは、”hostname”と”hoge”の2つの 入力を定義している ● “type”の指定は必須! ● “required”はオプション。 trueは「起動時の入力を必須とする」 という意味。 required以外のオプションについては後述。

Slide 14

Slide 14 text

個々のparameterに指定できるオプションたち ● required ○ Action起動時にその入力値が指定されていない場合、エラーを出すことができる ○ デフォルトはFalse ● description ○ その入力の役割、意味などを自由に記述することができる。あった方が親切 ● default ○ 入力の初期値を設定できる ○ requiredと組み合わせることもできるが、意味が無くなる ● enum ○ 入力値を選択式にする ● immutable ○ 入力値をユーザから入力できないようにする ○ defaultとセットで使うのが基本 ● position ○ 入力の順序を定義する

Slide 15

Slide 15 text

入力定義のポイント ● Actionの入力はmetadataのparametersで定義する ● 入力は名前付き引数として定義される ● 入力値の形式や初期値などを定義できるので、 「metadata内で定義している部分は」Action内でのvalidateが不要

Slide 16

Slide 16 text

bash(local-shell-script)でActionを作る場合 Actionコード内で引数(入力)を名前で引くことができない。 なので、以下のようにActionを実装する必要がある。 ● metadata.parametersの各要素にpositionを連続した自然数で設定する ● Actionコードとなるスクリプト内で、$で参照する

Slide 17

Slide 17 text

出力I: st2の出力形式 st2は、Actionの出力を以下のように分類している。 共通 shell-script系Action Python Action stdout result_code exit_code stderr failed result (status) succeeded 赤字が実質的な差分

Slide 18

Slide 18 text

出力I:例(shell-script系) core.localでecho helloしてみる ! failed is succeeded

Slide 19

Slide 19 text

出力I: 例(Python) 同じようなPythonのActionを実行してみる resultの役割とは? →次項

Slide 20

Slide 20 text

出力II: 構造化データの取り扱い ● Pythonで実装する場合 ○ result以下に構造化データを出力することができる ○ dictをそのまま渡せばOK ○ ネストしててもリストが混ざってても OK ○ 型も保持される ● それ以外で実装する場合 ○ stdoutにJSON or YAMLのStringで出力する ○ 別途Jinja Filterで構造化データに変換することで、後続 Actionなどで利用可能

Slide 21

Slide 21 text

出力I&II: Pythonでの出力方法 def run(self, **kwargs): sys.stdout.write(“ok”) ← stdout sys.stderr.write(“error”) ← stderr return (True, {“fuga”: “111”, “list”: [1, 2, 3]}) ↑return (status, result) True → succeeded False → failed status: succeeded exit_code: 0 result: fuga: “111” list: - 1 - 2 - 3 stdout: “ok” stderr: “error”

Slide 22

Slide 22 text

出力定義のポイント ● 基本的にテキストで出力する ● PythonでActionを作ることで、resultという表現力の高い出力形式を使える ○ hash, listを用いた構造化データの記述が可能 ○ 出力値の型の保持が可能

Slide 23

Slide 23 text

PythonでのActionコード記述方法

Slide 24

Slide 24 text

Pythonでの書き方 from st2common.runners.base_action import Action class TestAction(Action): def run(self, arg1, arg2, **kwargs): # なんらかの処理 return (True, result)

Slide 25

Slide 25 text

Pythonでの書き方 from st2common.runners.base_action import Action class TestAction(Action): def run(self, arg1, arg2, **kwargs): # なんらかの処理 return (True, result) 特別な理由が無い限り、とりあえず書く

Slide 26

Slide 26 text

Pythonでの書き方 from st2common.runners.base_action import Action class TestAction(Action): def run(self, arg1, arg2, **kwargs): # なんらかの処理 return (True, result) 名前は自由だが、Action名と対応が 取れるのが望ましい

Slide 27

Slide 27 text

Pythonでの書き方 from st2common.runners.base_action import Action class TestAction(Action): def run(self, arg1, arg2, **kwargs): # なんらかの処理 return (True, result) st2は自動的にrunメソッドを実行するので、必須。 (同クラス内に、runから呼ばれるメソッドを独自に書いても OK)

Slide 28

Slide 28 text

Pythonでの書き方 from st2common.runners.base_action import Action class TestAction(Action): def run(self, arg1, arg2, **kwargs): # なんらかの処理 return (True, result) 引数(入力)はmetadata.parametersで設定したものが名前付き で渡されるので、列挙してもいいし dictで拾ってもよい

Slide 29

Slide 29 text

Pythonでの書き方 from st2common.runners.base_action import Action class TestAction(Action): def run(self, arg1, arg2, **kwargs): # なんらかの処理 return (True, result) ● 何もreturnしない場合 ○ status = succeededになる ○ resultは空になる(None) ● Trueだけ返した場合: 同上 ● タプルを返した場合 ○ 1つ目のBoolがActionの実行成否になる ○ 2つ目のデータがそのまま resultに入る

Slide 30

Slide 30 text

応用: exit_codeを定義する from st2common.runners.base_action import Action class TestAction(Action): def run(self, arg1, arg2, **kwargs): # なんらかの処理 if hoge is None: sys.stderr.write(‘hoge err’) exit(2) exit(exit_code)で定義することが可能 status: failed --- exit_code: 2 result: None stdout: “” stderr: “hoge err” exit_code != 0の場合、 Actionは失敗する

Slide 31

Slide 31 text

returnとexitの使い分け ● 正常系、準正常系を通ったときにはreturnで返すべき ○ returnでないと、構造化データを返せない ○ statusは可変だが、exit_codeは0に固定される ● exitを使うのは特殊ケースのみにすべき ○ stdout, stderr, exit_codeしか返せない = テキストと数値だけしか返せない → Actionを異常終了させるときに使うと綺麗だと思う (stderr + errno)

Slide 32

Slide 32 text

まとめ

Slide 33

Slide 33 text

やったね!Actionが書けるよ! ● metadata内のparametersを設定できるようになったので、 ○ 入力を定義することができるようになった! ○ 簡単な入力規則を定義することができるようになった! ● Python形式のAction出力の定義方法と全体の書き方が分かったので、 ○ ナニカを実行するActionを書けるようになった! ○ 構造化データを含む自由度の高いActionを作れるようになった!

Slide 34

Slide 34 text

明日からActionを作り始める、その前に 公式ドキュメントの以下の節は読んでおこう! ● https://docs.stackstorm.com/actions.html#action-metadata ● https://docs.stackstorm.com/actions.html#writing-custom-python-actions 概要は説明したので、理解も補足もスムーズにいくはず!