StackStormのActionには、カスタムスクリプトとしてPythonが利用できます。
ここでは、StackStormでPythonスクリプトを利用するための流れと使い方を見てみます。
pythonスクリプトの構成要素
以下の2つです。
- metadata : YAML形式で、基本的な設定などを行います。
- Action名
- pythonスクリプトに与えるパラメータ(その型や必須かどうかも含めて)
- 呼び出すpythonスクリプト
- pythonスクリプト : 普通のpythonスクリプトです。
静的なconfigファイルを利用するなら、さらにもう1つconfigファイルを利用します。
動かす流れ
- スクリプトや設定を作る
- (必要に応じて)StackStorm上での実行環境を作る
- Actionを登録する
- 動かす
という流れになります。
実際にActionとしてPythonスクリプトを動かす
ここからは実際にpythonスクリプトをActionとして動かす流れを見ていきましょう。
事前に認証を済ませているものとします。
以下はst2admin
/ st2admin
で認証している例です。
$ export ST2_AUTH_TOKEN=$(st2 auth st2admin -p st2admin -t)
必要なスクリプトや設定ファイルを作る
上記の通り、2つのファイルを作る必要があります。
どちらも、 /opt/stackstorm/packs/<pack名>/actions/
配下に置かなければなりません。
ここではtest
というpack名で作成します。
metadata
こちらは、割とすんなりとみることができるのではないでしょうか。
entry_point
は、 /opt/stackstorm/packs/<pack名>/actions
からみた相対パスを書きます。
---
name: "python-test"
runner_type: "python-script"
description: "this is a sample script of python"
enabled: true
entry_point: "python-test.py"
parameters:
param1:
type: "string"
description: "parameter 1"
required: true
position: 0
param2:
type: "string"
description: "parameter 2"
required: true
position: 1
default: "default parameter 2"
pythonスクリプト
こちらのスクリプトは、StackStormから呼び出されるためお作法自体はありますが、結局は run
メソッドが呼ばれると思えば良さそうです1。
import sys
from st2actions.runners.pythonrunner import Action
class PythonTestAction(Action):
def __init__(self, config):
self.config = config
def run(self, param1, param2):
print(param1, param2)
print(self.config["test_param1"])
return (True, param1 + "," + param2)
コンストラクタでconfig
を渡していますが、これが次に紹介するconfigファイルと連動します。
configファイル
test_param1: "static_param1"
<pack名>
の直下にconfig.yaml
を置いておくと、そこの中に書かれた設定値をpythonスクリプト実行時にコンストラクタでconfig
というオブジェクトに読み込んでくれるそうです2。
StackStorm上でpythonの実行環境を作る
さて、これでStackStormに登録して実行…といきたいところですが、このまま登録して実行しても、エラーになります。
(登録は成功しますが実行はエラーになります)
まず、全てのActionを登録するには、 st2ctl reload --register-actions
コマンドを実行します。
これは、 /opt/stackstorm/<pack名>
配下にある設定を全て読みなおしてくれるというコマンドになります。
$ sudo st2ctl reload --register-actions
Registering content...[flags = --register-actions]
2016-08-27 14:23:15,107 INFO [-] Connecting to database "st2" @ "0.0.0.0:27017" as user "None".
2016-08-27 14:23:15,376 INFO [-] =========================================================
2016-08-27 14:23:15,376 INFO [-] ############## Registering actions ######################
2016-08-27 14:23:15,376 INFO [-] =========================================================
2016-08-27 14:23:17,147 INFO [-] Registered 63 actions.
##### st2 components status #####
st2actionrunner PID: 4291
st2actionrunner PID: 4293
st2actionrunner PID: 4295
st2actionrunner PID: 4297
st2actionrunner PID: 4299
st2actionrunner PID: 4301
st2actionrunner PID: 4303
st2actionrunner PID: 4305
st2actionrunner PID: 4307
st2actionrunner PID: 4309
st2api PID: 4316
st2api PID: 4810
st2stream PID: 4378
st2stream PID: 4756
st2auth PID: 4388
st2auth PID: 4748
st2garbagecollector PID: 4396
st2notifier PID: 4404
st2resultstracker PID: 4416
st2rulesengine PID: 4428
st2sensorcontainer PID: 4440
st2chatops is not running.
mistral-server PID: 4486
mistral-api PID: 4481
mistral-api PID: 4769
mistral-api PID: 4770
実際に登録されています。
$ st2 action list -p test
+----------------------+------+-----------------------------------+
| ref | pack | description |
+----------------------+------+-----------------------------------+
| test.python-test | test | this is a sample script of python |
+----------------------+------+-----------------------------------+
さて、これで実行…とすると、エラーになります。
$ st2 run test.python_test param1=p1
..
id: 57c1dbf1e368b912caaf8908
status: failed
parameters:
param1: p1
result:
error: '
Virtual environment (/opt/stackstorm/virtualenvs/test) for pack "test" doesn''t exist. If you haven''t
installed a pack using "packs.install" command, you can create a new virtual environment using
"st2 run packs.setup_virtualenv packs=test" command''
'
traceback: " File "/opt/stackstorm/st2/lib/python2.7/site-packages/st2actions/container/base.py", line 98, in _do_run
(status, result, context) = runner.run(action_params)
File "/opt/stackstorm/st2/lib/python2.7/site-packages/st2actions/runners/pythonrunner.py", line 118, in run
raise Exception(msg)
"
途中にメッセージもありますが、 test
というpackでのpythonの実行環境がないということですね。virtualenv
によって、packごとに実行環境がわけられるようです。
ですので、packを適切に分割すれば、実行環境がごちゃごちゃになるのを避けることができそうです。
さて、メッセージ通りに環境を作りましょう。丁寧に「コマンドをこう叩け」と書いてあるので、そのとおりに実行します。
$ sudo st2 run packs.setup_virtualenv packs=test
....
id: 57c1dc6ce368b912caaf890b
status: succeeded
parameters:
packs:
- test
result:
exit_code: 0
result: 'Successfuly set up virtualenv for the following packs: test'
stderr: 'st2.actions.python.SetupVirtualEnvironmentAction: DEBUG Setting up virtualenv for pack "test"
st2.actions.python.SetupVirtualEnvironmentAction: INFO Virtualenv path "/opt/stackstorm/virtualenvs/test" doesn''t exist
st2.actions.python.SetupVirtualEnvironmentAction: DEBUG Creating virtualenv for pack "test" in "/opt/stackstorm/virtualenvs/test"
st2.actions.python.SetupVirtualEnvironmentAction: DEBUG Creating virtualenv in "/opt/stackstorm/virtualenvs/test" using Python binary "/opt/stackstorm/st2/bin/python"
st2.actions.python.SetupVirtualEnvironmentAction: DEBUG Running command "/opt/stackstorm/st2/bin/virtualenv -p /opt/stackstorm/st2/bin/python /opt/stackstorm/virtualenvs/test" to create virtualenv.
st2.actions.python.SetupVirtualEnvironmentAction: DEBUG Installing base requirements
st2.actions.python.SetupVirtualEnvironmentAction: DEBUG No pack specific requirements found
st2.actions.python.SetupVirtualEnvironmentAction: DEBUG Virtualenv for pack "test" successfully created in "/opt/stackstorm/virtualenvs/test"
'
stdout: ''
全てINFOとDEBUGなので問題なさそうです。最後のメッセージの通り、/opt/stackstorm/virtualenvs/test
にpythonの環境ができています。
Actionの実行(Pythonスクリプトの実行)
さて、登録自体はできているので再度実行してみましょう。
$ st2 run test.python-test param1=p1
..
id: 57c1ed13e368b912caaf8962
status: succeeded
parameters:
param1: p1
result:
exit_code: 0
result: p1,default parameter 2
stderr: ''
stdout: '(u''p1'', u''default parameter 2'')
static_param1
'
上記の通り、print
で出力されたものはstdout
に、return
で戻すものはresult
に格納されています。
まとめ
ということで、簡単ですがpythonスクリプトを実行する流れを見てきました。
構成要素は少し多いかもしれませんが、非常に簡単にpythonをworkflowとして動かすことができそうです。
その他気になったこと
Action実行中に、そのActionを変更してreloadしたらどうなるの?
どうにもなりませんでした。中断もされないし動かされたものは動き続けます。
変更されたものは、次回実行時から反映されます。
従って、わざわざ既存で動いているものを止めずに済みそうです。
reloadが必要なときはどんなとき?
YAML(metadata)修正時です。
pythonスクリプトを修正するだけならreloadは不要です。
ファイル消してreloadしたらどうなる?
どうにもなりませんでした。
今までないものをst2ctl reload --register-actions
コマンドにより反映はできますが、
逆にファイルを消して上記コマンドを実行しても消えません。(Actionは登録されたままになります)
従って、消す場合は以下のようにして明示的に消すしかなさそうです。
st2 action delete test.python-test
引数以外にどんなパラメータが使えるの?
Pythonスクリプトに関して言うなら、基本的に明示的に引数に加えるか、環境変数から読み取るかくらいしかできなさそうです3。
引数にはどんなものが使えるの?
{{ action_context }}
という形で、その辞書の配下にいろいろと入っているらしいです4。
例えばWebHookだったらそのユーザとか、Workflowだったら親ActionのIDとか。
ただ、試していません。