supersetの導入

# Overview
既存システムのデータベース(MySQL)にアクセスするまで

# Environment
superset : 0.20.4
OS : Ubuntu Xenial
DB : MySQL 5.7.19
Python : 2.7.12

# Installation
[公式ドキュメント](https://superset.incubator.apache.org/installation.html#os-dependencies)に従って、まずはsupersetを動かすために必要なパッケージをインストールします。
Ubuntuの場合は

```
sudo apt-get install build-essential libssl-dev libffi-dev python-dev python-pip libsasl2-dev libldap2-dev
```

ドキュメントでは[virtual env](https://superset.incubator.apache.org/installation.html#python-virtualenv)を使用していますが、今回はsuperset専用にVMインスタンスを準備しているためこの手順は省きます。

superset自体はpipで簡単にインストールできます。
https://superset.incubator.apache.org/installation.html#superset-installation-and-initialization

superset runserverコマンドを実行するとデフォルトでは8088ポートでsupersetが起動します。
http://127.0.0.1:8088

```
fabmanager create-admin --app superset
```

こちらのコマンドで作成したユーザーでログインできればひとまず完了です。

# Settings
上記の方法でsupersetのインストールは完了しましたが、実際に運用するにあたって以下の変更を加えたいと思います。

* supersetが使用するデータベースをsqliteからmysqlへ変更
* データソースに既存システムのデータベース(mysql)を追加

## supersetで使用するデータベースをsqliteからmysqlへ変更
supersetのソースコードがあるディレクトリにsuperset_config.pyを作成します

```
cd /usr/local/lib/python2.7/dist-packages/superset # 環境によって異なります
touch superset_config.py
```

superset_config.pyには[公式ドキュメント](https://superset.incubator.apache.org/installation.html#configuration)に記載されている記載例をコピペし、SQLALCHEMY_DATABASE_URIの項目を任意の接続先へ変更します。
記載の仕方は```mysql://dbuser:dbpass@hostname/dbname```となります。
接続先を変更したら改めて管理者ユーザーとDBマイグレーションを実行します。

```
fabmanager create-admin --app superset
superset db upgrade
superset init
```

__mysqlでデータベースの文字エンコーディングをutf8mb4にしている場合、superset db upgradeを実行すると下記のエラーが表示されて正常にマイグレーションが完了しません__

```
sqlalchemy.exc.OperationalError: (_mysql_exceptions.OperationalError) (1071, 'Specified key was too long; max key length is 767 bytes') [SQL: u'\nCREATE TABLE clusters (\n\tcreated_on DATETIME NOT NULL, \n\tchanged_on DATETIME NOT NULL, \n\tid INTEGER NOT NULL AUTO_INCREMENT, \n\tcluster_name VARCHAR(250), \n\tcoordinator_host VARCHAR(255), \n\tcoordinator_port INTEGER, \n\tcoordinator_endpoint VARCHAR(255), \n\tbroker_host VARCHAR(255), \n\tbroker_port INTEGER, \n\tbroker_endpoint VARCHAR(255), \n\tmetadata_last_refreshed DATETIME, \n\tcreated_by_fk INTEGER, \n\tchanged_by_fk INTEGER, \n\tPRIMARY KEY (id), \n\tUNIQUE (cluster_name), \n\tFOREIGN KEY(created_by_fk) REFERENCES ab_user (id), \n\tFOREIGN KEY(changed_by_fk) REFERENCES ab_user (id)\n)\n\n']
```

「Specified key was too long; max key length is 767 bytes」とある通り、keyは最大で767byteまでしか使えないようです。
PRIMARYやUNIQUEに設定されているカラムがvarchar(256)に設定されていた場合utf8でも同様のエラーが発生するようです。
この場合UNIQUEが設定されているcluster_nameとverbose_nameのvarchar(250)が引っかかっていると考えられるので、これをvarchar(191)などに変更すればマイグレーション自体は正常に完了しそうです。
ですが、ソフトウェアの動作に影響しそう & supersetで絵文字といった4バイト文字は使用しなさそうなので、おとなしくデータベースの文字エンコーディングをutf8に変更しましょう。

## データソースの追加
データソースの追加はweb画面上から行います。
![Superset.jpg](https://qiita-image-store.s3.amazonaws.com/0/57448/fbf56834-be6b-7602-bbc1-9ff6394323be.jpeg)
SQLAlchemy URIの項目は上述の記法と同じです。

### Test Connectionは正常に行えるが「This endpoint requires the datasource database_name, database or `all_datasource_access` permission」と表示されて内容が表示されない
ログインしているユーザーに対してadmin roleを与えていたので初めは原因がわからなかったのですが、どうやらデータベース個別のパーミッションを与えてあげないといけないようです。
なお公式ドキュメントでは[alpha](This endpoint requires the datasource database or `all_datasource_access` permission)と言うroleが全てのデータソースへのアクセス権限を持つような記載がされていますが、私の環境ではadminとpublicしかあらかじめ用意されていませんでした。
今回はsupersetの使用目的が決まっていたので実行しませんでしたが、```superset load_examples```を実行すると作成されるのかもしれません。

### デーモンとして起動したい
```superset runserver```コマンドにはデーモンで起動するためのオプションが用意されていませんが、
上記コマンドを実行すると

```
gunicorn -w 2 --timeout 60 -b  0.0.0.0:8088 --limit-request-line 0 --limit-request-field_size 0 superset:app
```

と言うコマンドが実行されているのが確認できます。
ですので、supersetのルートディレクトリで上記gunicornコマンドに「-D」のオプションを追加して実行すればデーモンとしてsupersetを起動できます。

```
cd /usr/local/lib/python2.7/dist-packages/superset # 環境によって異なります
gunicorn -w 2 --timeout 60 -b  0.0.0.0:8088 --limit-request-line 0 --limit-request-field_size 0 superset:app -D
```