■ はじめに
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