1.はじめに
・複数のDataSourceからexecute_queryを利用してデータを取得してDataFrameに加工。
・add_result_rowとadd_result_columnを利用してRedash用のテーブル化。
上記2点を行うのが面倒だった為、ラッパークラスの作成する事にした。
2.環境把握
Redashは、docker上で動かしているので、
スクリプトはdocker内部に設置する必要がある。
3.ディレクトリ構成を決める
Redash側にスクリプトのパスを設定するので、予め決めておく必要があります。
今回は以下のディレクトリ構成で設定します。
home
└ redash
└ scripts
※scriptsディレクトリの中にスプリプトを配置します。
4.ロジックの作成
ラッパークラスを作成します。
最初は簡単なクラスで大丈夫ですが、Redash側に設定するのでファイル名だけは確定させておいてください。
class Test():
def __init__(self):
pass
...
5.Redashの設定
ここからRedash側の設定を変更していきます。
5-1.AdditionalModulesPathsの設定
スクリプトを配置しているパスを設定します。
[/home/redash/scripts]を記入します。
5-2.Modules to import prior to running the scriptの設定
インポートするファイル名を設定します。
wrapperを入力します。
※複数ある場合はカンマ区切りで入力。(カンマの後はスペースを空けない事)
5-3.設定を保存
Saveを押して保存します。
設定は保存されていますが、まだ動作しないので注意してください。
6.Dockerを再起動する。
コンテナ自体を一旦破棄して、再度作り直します。
docker-compose down
docker-compose up -d
※コンテナ自体を作る直す必要はないかもしれないですが、一応作り直しています。
6-1 Redash側の動作
ここは飛ばしてもらっても設定に影響はないです。
https://github.com/getredash/redash/blob/master/redash/query_runner/python.py#L103-L105
if self.configuration.get("allowedImportModules", None):
for item in self.configuration["allowedImportModules"].split(","):
self._allowed_modules[item] = None
Redashの起動時に _allowed_modules配列にwrapperキーの値がNoneとして追加されます。
https://github.com/getredash/redash/blob/master/redash/query_runner/python.py#L107-L110
if self.configuration.get("additionalModulesPaths", None):
for p in self.configuration["additionalModulesPaths"].split(","):
if p not in sys.path:
sys.path.append(p)
Redashの起動時に 環境変数にスクリプトのパス「/home/redash/scripts」が登録されます。
7.スクリプトファイルをDocker内に転送する。
まだ実体がDocker内には存在していないので、今の状態でスクリプトを実行するとファイルがないエラーが発生します。
なので、実体をDocker内へ転送します。
docker cp ./scripts/. `docker-compose ps -q server`:/home/redash/scripts/
docker cp ./scripts/. `docker-compose ps -q worker`:/home/redash/scripts/
スクリプトファイルのオーナーがrootであっても
スクリプトは実行できるのを確認しているので、この手順では権限変更を行いません。
8.実際にRedash内で実行する。
from wrapper import test
hoge = test()
hoge.fuga()
8-1.Redash側の動作
https://github.com/getredash/redash/blob/master/redash/query_runner/python.py#L248-L251
def run_query(self, query, user):
self._current_user = user
try:
....
実行した際に、run_query関数が走ります。
RestrictedPythonで設定して動かしますが、この記事では触れませんのでご了承ください。
https://github.com/getredash/redash/blob/master/redash/query_runner/python.py#L117-L126
def custom_import(self, name, globals=None, locals=None, fromlist=(), level=0):
if name in self._allowed_modules:
m = None
if self._allowed_modules[name] is None:
m = importlib.import_module(name)
self._allowed_modules[name] = m
else:
m = self._allowed_modules[name]
return m
Redashのロジック内でimportしたモジュールは、custom_import関数内で、importlibを使用してインポートされます。
10.参考サイト
https://qiita.com/tsuboyataiki/items/90dbe94553d3dea39b19
https://qiita.com/reflet/items/ad734edc87c73cbaa459
https://docs.docker.jp/engine/reference/commandline/cp.html