Databricks AppsからAWS Aurora Data APIを使用したデータベースアクセス方法

# はじめに
Databricks AppsからAWS Aurora Data APIを使用してデータベースにアクセスする方法について説明します。
この記事では、Databricksのシークレット管理機能を使用してデータベース接続情報を安全に管理し、
SQLAlchemyを使用してクエリを構築、AuroraDataAPIを使用してデータベースにアクセスする方法を紹介します。

# 前段
- [Databricks Secretsによるシークレット管理とDatabricks Appsでの利用方法](https://qiita.com/kei1-dev/items/dd79b483a769daab292f)
- [Databricks AppsからAWSリソースへのアクセス方法](https://qiita.com/kei1-dev/items/d6d43c514311d9e7e91d)

# データベース接続情報の管理

## 1. シークレットスコープの作成
前段で実施したAWSの設定に加え、データベース接続情報を管理するための専用のスコープを作成します。

```bash
databricks secrets create-scope database
```

## 2. データベース接続情報の追加
作成したスコープにデータベース接続情報を追加します。

```bash
# DB_CLUSTER_ARNの追加
databricks secrets put-secret --json '{
  "scope": "database",
  "key": "DB_CLUSTER_ARN",
  "string_value": "<DB_CLUSTER_ARN>"
}'

# DB_SECRET_ARNの追加
databricks secrets put-secret --json '{
  "scope": "database",
  "key": "DB_SECRET_ARN",
  "string_value": "<DB_SECRET_ARN>"
}'

# DATABASE_NAMEの追加
databricks secrets put-secret --json '{
  "scope": "database",
  "key": "DATABASE_NAME",
  "string_value": "<DATABASE_NAME>"
}'
```

## 3. シークレットの確認
追加したシークレットを確認します。

```bash
databricks secrets list-secrets database
```

# Databricks Appsでの設定

## 1. app.yamlの設定
アプリの設定ファイル（app.yaml）でデータベース接続情報を参照するように設定します。

```yaml
command: [
  "gunicorn",
  "main:app",
  "-k",
  "uvicorn.workers.UvicornWorker",
  "-w",
  "1",
]
env:
  - name: 'AWS_ACCESS_KEY_ID'
    valueFrom: 'AWS_ACCESS_KEY_ID'
  - name: 'AWS_SECRET_ACCESS_KEY'
    valueFrom: 'AWS_SECRET_ACCESS_KEY'
  - name: 'DB_CLUSTER_ARN'
    valueFrom: 'DB_CLUSTER_ARN'
  - name: 'DB_SECRET_ARN'
    valueFrom: 'DB_SECRET_ARN'
  - name: 'DATABASE_NAME'
    valueFrom: 'DATABASE_NAME'
```

## 2. Databricks Appsの設定
前段で実施したAWSの設定に加え、Databricks Appsの設定画面で、以下の設定を行います：

- scope: database
- secret key: DB_CLUSTER_ARN, DB_SECRET_ARN, DATABASE_NAME
- 権限: 読み取り可能
- リソースキー: DB_CLUSTER_ARN, DB_SECRET_ARN, DATABASE_NAME


# アプリケーションでのデータベースアクセス
※SQLAlchemyのモデリングとAlembicによるマイグレーションは実施している前提とします。

## 1. SQLAlchemyからクエリ文字列を生成する
SQLAlchemyを使用してクエリを構築し、クエリ文字列を生成する
例) ユーザテーブルから全権取得するクエリ文字列の生成
```python
query = select(User)
sql = str(query.compile(compile_kwargs={"literal_binds": True}))
```

## 2. クエリの実行例
SQLAlchemyで構築したクエリ文字列をAurora Data APIで実行する例を示します。

```python
client = get_rds_data_client()
response = client.execute_statement(
  resourceArn=DB_CLUSTER_ARN,
  secretArn=DB_SECRET_ARN,
  database=DATABASE_NAME,
  sql=sql,
  parameters=parameters if parameters is not None else []
)
return response
```

# まとめ

Databricks AppsからAWS AuroraにはNW経由のアクセスができないことから、Aurora Data APIを使用してデータベースにアクセスする必要があり、検証を行いました。
Aurora Data APIではクエリ文字列を利用することが必要だったため、ORMであるSQLAlchemyから一度クエリ文字列を生成し、Aurora Data APIを使用してデータベースにアクセスする方法を紹介しました。

また、一連の流れを通じて、既存のAWSを利用したアプリケーションをDatabricks Appsに移行できそうなことがわかりました。

# 参考資料
- [Databricks Secrets](https://docs.databricks.com/security/secrets/index.html)
- [Databricks Apps](https://docs.databricks.com/aws/ja/dev-tools/databricks-apps/configuration#databricks-%E3%82%B7%E3%83%BC%E3%82%AF%E3%83%AC%E3%83%83%E3%83%88%E3%82%92%E5%8F%82%E7%85%A7%E3%81%99%E3%82%8B)
- [AWS Aurora Data API](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/data-api.html)
- [SQLAlchemy](https://www.sqlalchemy.org/)