■ はじめに
2018/05/29 に開催された、Tech Night @ Shiodome # 8の中で「明日からできる、st2のActionの作り方」という発表がありました。 まだActionは作ったことがなかったのですが、これを聞いて簡単なものを作ってみようと思ってやってみました。
■ つくるもの
何でもよかったのですが、Googleの DNS-over-HTTPSを利用して、パラメータ name で与えられた名前のAレコードをリストで返すActionを作ることにしました。
■ コードの準備
まずは、Actionの肝になるコードの準備です。
Packの作成方法がまだ理解不足だったため、default配下にしました。また、環境構築を単純化するため、 requests など別途インストールが必要なものは使わないようにしておきました。名前解決失敗時は空のリストを返すようにしました。
パス:/opt/stackstorm/packs/default/actions/dnsquery.py
from st2common.runners.base_action import Action import json import urllib2 class DnsQueryAction(Action): def run(self, name): url = "https://dns.google.com/resolve?name=" + name req = urllib2.Request(url) res = urllib2.urlopen(req) res_json = json.loads(res.read()) if "Answer" in res_json: # successed records = [v["data"] for v in res_json["Answer"]] return (True, records) else: # failed return (False, [])
■ metadataファイルの準備
続いて、Actionがどういうパラメータを持つかなどの情報を定義する、metadataファイルの準備です。YAML形式です。
パス:/opt/stackstorm/packs/default/actions/dnsquery.yml
--- name: "dnsquery" runner_type: "python-script" entry_point: "dnsquery.py" description: "resolve dns query" enabled: true parameters: name: type: "string" description: "dns query name for type A" required: true
■ Actionの作成
各ファイルを作っただけでは StackStorm はまだ認識しません。st2 action create コマンドで metadata ファイルを元に Action を作成します。
[ec2-user@ip-172-31-4-147 actions]$ st2 action create /opt/stackstorm/packs/default/actions/dnsquery.yml
+-------------+----------------------------------------------------+
| Property | Value |
+-------------+----------------------------------------------------+
| id | 5b10a7a96fb12304de15a1d2 |
| name | dnsquery |
| pack | default |
| description | resolve dns query |
| enabled | True |
| entry_point | dnsquery.py |
| notify | |
| parameters | { |
| | "name": { |
| | "required": true, |
| | "type": "string", |
| | "description": "dns query name for type A" |
| | } |
| | } |
| ref | default.dnsquery |
| runner_type | python-script |
| tags | |
| uid | action:default:dnsquery |
+-------------+----------------------------------------------------+
作成できたようなので、 st2 action list のリストで確認します。
[ec2-user@ip-172-31-4-147 actions]$ st2 action list --pack=default +---------------------+---------+-----------------------------------+ | ref | pack | description | +---------------------+---------+-----------------------------------+ | default.dnsquery | default | resolve dns query | +---------------------+---------+-----------------------------------+
認識されているようです。
■ 実行
はじめての実行(失敗・・)
それでは、st2 run による単発の実行で試してみます。
[ec2-user@ip-172-31-4-147 actions]$ st2 run default.dnsquery name=www.stackstorm.com
.
id: 5b10a8036fb12304de15a1d4
status: failed
parameters:
name: www.stackstorm.com
result:
error: '
The virtual environment (/opt/stackstorm/virtualenvs/default) for pack "default" does not exist. Normally this is
created when you install a pack using "st2 pack install". If you installed your pack by some other
means, you can create a new virtual environment using the command:
"st2 run packs.setup_virtualenv packs=default"
'
traceback: " File "/opt/stackstorm/st2/lib/python2.7/site-packages/st2actions/container/base.py", line 119, in _do_run
(status, result, context) = runner.run(action_params)
File "/opt/stackstorm/runners/python_runner/python_runner/python_runner.py", line 143, in run
raise Exception(msg)
"
おっと・・・、default pack向けの virtualenv が無いためエラーになってしまいました。
エラーメッセージに親切に書かれているコマンドで virtualenv を用意します。
[ec2-user@ip-172-31-4-147 actions]$ st2 run packs.setup_virtualenv packs=default
..
id: 5b10a8cf6fb12304de15a1d7
status: succeeded
parameters:
packs:
- default
result:
exit_code: 0
result: 'Successfuly set up virtualenv for the following packs: default'
stderr: 'st2.actions.python.SetupVirtualEnvironmentAction: DEBUG Setting up virtualenv for pack "default" (/opt/stackstorm/packs/default)
st2.actions.python.SetupVirtualEnvironmentAction: INFO Virtualenv path "/opt/stackstorm/virtualenvs/default" doesn''t exist
st2.actions.python.SetupVirtualEnvironmentAction: DEBUG Creating virtualenv for pack "default" in "/opt/stackstorm/virtualenvs/default"
st2.actions.python.SetupVirtualEnvironmentAction: DEBUG Creating virtualenv in "/opt/stackstorm/virtualenvs/default" 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 --no-download /opt/stackstorm/virtualenvs/default" to create virtualenv.
st2.actions.python.SetupVirtualEnvironmentAction: DEBUG Installing base requirements
st2.actions.python.SetupVirtualEnvironmentAction: DEBUG Installing requirement six>=1.9.0,<2.0 with command /opt/stackstorm/virtualenvs/default/bin/pip install six>=1.9.0,<2.0.
st2.actions.python.SetupVirtualEnvironmentAction: DEBUG No pack specific requirements found
st2.actions.python.SetupVirtualEnvironmentAction: DEBUG Virtualenv for pack "default" successfully created in "/opt/stackstorm/virtualenvs/default"
'
stdout: ''
無事に /opt/stackstorm/virtualenvs/default として virtualenvが作成されたようです。
もう一度実行(名前解決成功)
気を取り直してもう一度 Action を実行します。
[ec2-user@ip-172-31-4-147 actions]$ st2 run default.dnsquery name=www.stackstorm.com . id: 5b10b23e6fb12304de15a1f0 status: succeeded parameters: name: www.stackstorm.com result: exit_code: 0 result: - 104.28.16.123 - 104.28.17.123 stderr: '' stdout: ''
無事、status: succeeded となり、2つのIPアドレスが返ってきました。
もう一度実行(名前解決失敗)
今度は、名前解決ができないパターンで試します。
[ec2-user@ip-172-31-4-147 actions]$ st2 run default.dnsquery name=hogehogehoge.stackstorm.com . id: 5b10b3016fb12304de15a1f3 status: failed parameters: name: hogehogehoge.stackstorm.com result: exit_code: 0 result: [] stderr: '' stdout: ''
無事、status: failed となり、空のリストが返ってきました。
■ まとめ
非常に簡単な例ではありますが、初めてPythonによる Action を作成して動作を確認してみました。今のところは、そこまで覚えることも多くない印象です。 基本的には既存の Action を中心に使っていきますが、それでは実現できないものについては、カスタムのActionを作って見たいと思います。
参考資料
https://docs.stackstorm.com/actions.html#writing-custom-python-actions