AWS AmplifyでAuroraServerlessV2の連携API環境を構築する
2024/04/26
Table of Contents
1.はじめに
2023年末にAWS AmplifyにてAuroraServerlessV2との連携が できるようになったことを踏まえて連携API環境構築手順について記述します。
関連参考記事
- (AWS公式)Amplify Dev Center: Connect API to existing MySQL or PostgreSQL database
- 既存の MySQL と PostgreSQL データベース用の GraphQL API の作成
- AWS Amplify の新機能 – AWS CDK 用に MySQL および PostgreSQL データベースをクエリする
今回実施した各種バージョン情報:
- OS:macOS Sonoma 14.4
- next.js:14.1.4
- react:18.2.70
- typescripts:5.3.3
- postgresSQL:15.4
- awscli:2.11.27
- aws-amplify-cli:12.10.1
- AWS cdk:2.133.0
- node:20.10.0
2.事前準備
AWS CLIユーザーの設定
AWS CLIユーザーを作成して、ターミナルでAWS CLIを使用できる状態にしておきます。
❯ amplify configure
aws-amplify cliインストール
aws-amplify cliをインストールしておきます。 Amplify CLI がインストールされているかは、以下のコマンドで確認できます。
❯ amplify --version
aws-amplify-cli 12.10.1
インストールされていない場合は、以下のコマンでインストールします。
❯ npm install -g @aws-amplify/cli
.tool-versions の設定
上記コマンドツールのバージョンを指定しておくために作業フォルダに.tool-versions
を作成しておきます。
今回はパッケージ管理ツール:asdf
を利用しており、任意作業ディレクトリで以下のコマンドを実行することで
ツール名とバージョン情報が.tool-versions
に書き込まれます。
> asdf local aws-amplify-cli 12.10.1
DB構築
RDS AuroraServerless V2 を構築しておきます。 ここでのポイントは、DBクラスターの「DataAPI」を有効にすることで、この後に作成するAPI連携を可能にします。 以下、それぞれの構築別による設定方法です。
- コンソールでのGUI構築時:DataAPIを有効化
- CloudFormation構築時:Type: AWS::RDS::DBCluster >
EnableHttpEndpoint: true
- CDK構築時:DatabaseClusterクラスにて、
enableDataApi: true
また「DataAPI」を有効にすることで、Amazon RDSコンソール画面の左ペインメニューにある「クエリエディタ」を使ってデータベースへの接続やSQL文を発行することができるようになります(現状PostgreSQLのみ)。
3.Amplify GraphQLを用いたAurora Serverless V2(PostgreSQL) のAPI構築
Aurora ServerlessV2 へアクセスするためのAmplify GraphQLを用いたAPI(AWS AppSync)を作成します。
現時点(2024.04.04)では、AWS公式サイトの説明にある通り
amplify CLIの amplify add api
には、まだ対応していないためAWS CDKで作成していく必要があります。
事前準備
AWS CDK インストール AWS CDKがインストールされているかは、以下のコマンドで確認できます。
❯ cdk --version
2.133.0 (build dcc1e75)
インストールされていない場合は、以下のコマンでインストールします。
❯ npm install -g aws-cdk
PostgreSQL DB への接続パラメタ設定
AWS Systems Manager コンソール の [パラメータストア>マイパラメタ] にDBへの接続情報を設定します。
設定するデータベースの接続のパラメータ (hostname、database name、port、username、password)それぞれの項目を、SecureString
タイプで設定します。
名前 | 値 | 備考 |
---|---|---|
/amplify-api-cdk/hostname | aurora-cluster.cluster-XXXXXXXXXXmg.ap-northeast-1.rds.amazonaws.com | ※1 |
/amplify-api-cdk/username | postgres | DBユーザー名 |
/amplify-api-cdk/password | postgres | DBパスワード |
/amplify-api-cdk/port | 5432 | DBポート番号 |
/amplify-api-cdk/database | auroradb | DB名 |
・(※1) DBクラスタののライターインスタンスのエンドポイントを設定します。 エンドポイントは、RDSの該当DBのコンソール画面から取得できます。
上記、パラメータストアへのキー設定はAWS CLIにて以下のコマンドで設定することができます。
▼設定例:
# 任意API名を設定
apiName="amplify-api-cdk"
aws ssm put-parameter \
--name "/$apiName/hostname" \
--value "aurora-cluster.cluster-XXXXXXXXXXmg.ap-northeast-1.rds.amazonaws.com" \
--type "SecureString"
aws ssm put-parameter \
--name "/$apiName/username" \
--value "postgres" \
--type "SecureString"
aws ssm put-parameter \
--name "/$apiName/password" \
--value "postgres" \
--type "SecureString"
aws ssm put-parameter \
--name "/$apiName/port" \
--value "5432" \
--type "SecureString"
aws ssm put-parameter \
--name "/$apiName/database" \
--value "auroradb" \
--type "SecureString"
作成開始
アプリケーション用の新しいディレクトリを作成し移動します。
❯ mkdir amplify-api-cdk
❯ cd amplify-api-cdk
cdk init
コマンドで CDK アプリケーションを初期化します。(今回はtypescriptを利用するためオプション指定)
❯ cdk init app --language typescript
AmplifyのGraphQL API コンストラクトを新しい CDK プロジェクトにインストールします。
❯ npm install @aws-amplify/graphql-api-construct
「graphql-api-construct」モジュールがインストールされます。
CDK プロジェクトのメインスタックファイル (lib/<your-project-name>-stack.ts
)を開いて編集します。
ファイルの先頭に下記の必要なコンストラクトをインポートします。
▼lib/<your-project-name>-stack.ts
import {
AmplifyGraphqlApi,
AmplifyGraphqlDefinition
} from '@aws-amplify/graphql-api-construct';
import * as path from "path";
データベース API の GraphQL スキーマファイルの生成
新たなスキーマファイルschema.sql.graphql
を以下の操作により生成します。
ここではAPIを作成したいサンプルテーブルを作成し、AWSが用意しているツールを用いてgraphqlファイルを出力します。
AWSのコンソール画面から、「クエリエディタ」を選択し、DBへの接続情報を入力し接続します。
クエリエディタにて、下記SQLを実行しサンプルテーブルを作成、ついでにサンプルデータも挿入しておきます。
-- Mealsテーブルの作成
CREATE TABLE Meals (
id INT PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
-- サンプルデータの挿入
INSERT INTO Meals (id, name) VALUES (1, 'rice');
INSERT INTO Meals (id, name) VALUES (2, 'soup');
INSERT INTO Meals (id, name) VALUES (3, 'salad');
次に、下記のSQLを実行し結果をCSVファイルに出力します。
<database-name>
の部分をが該当のデータベース名に置き換えて下さい。
※下記のSQLはPostgreSQL版となります。(MySQL版は公式サイトを参照)
SELECT DISTINCT
INFORMATION_SCHEMA.COLUMNS.table_name,
enum_name,enum_values,column_name,column_default,ordinal_position,data_type,udt_name,is_nullable,character_maximum_length,indexname,constraint_type,
REPLACE(SUBSTRING(indexdef from '\((.*)\)'), '"', '') as index_columns
FROM INFORMATION_SCHEMA.COLUMNS
LEFT JOIN pg_indexes
ON
INFORMATION_SCHEMA.COLUMNS.table_name = pg_indexes.tablename
AND INFORMATION_SCHEMA.COLUMNS.column_name = ANY(STRING_TO_ARRAY(REPLACE(SUBSTRING(indexdef from '\((.*)\)'), '"', ''), ', '))
LEFT JOIN (
SELECT
t.typname AS enum_name,
ARRAY_AGG(e.enumlabel) as enum_values
FROM pg_type t JOIN
pg_enum e ON t.oid = e.enumtypid JOIN
pg_catalog.pg_namespace n ON n.oid = t.typnamespace
WHERE n.nspname = 'public'
GROUP BY enum_name
) enums
ON enums.enum_name = INFORMATION_SCHEMA.COLUMNS.udt_name
LEFT JOIN information_schema.table_constraints
ON INFORMATION_SCHEMA.table_constraints.constraint_name = indexname
AND INFORMATION_SCHEMA.COLUMNS.table_name = INFORMATION_SCHEMA.table_constraints.table_name
WHERE INFORMATION_SCHEMA.COLUMNS.table_schema = 'public'
AND INFORMATION_SCHEMA.COLUMNS.TABLE_CATALOG = '<database-name>';
-- Replace database name here ^^^^^^^^^^^^^^^
上記SQLをクエリエディタで実行し、結果をcsvに出力します。
(クエリエディタ画面上の「Export csv」ボタンを押下すると「`output.txt`」という名で下記内容のcsvファイルが出力されます)。
table_name,enum_name,enum_values,column_name,column_default,ordinal_position,data_type,udt_name,is_nullable,character_maximum_length,indexname,constraint_type,index_columns
meals,NULL,NULL,id,NULL,1,integer,int4,NO,NULL,meals_pkey,PRIMARY KEY,id
meals,NULL,NULL,name,NULL,2,character varying,varchar,NO,255,NULL,NULL,NULL
次のコマンドを実行します。その際、<path-schema.csv>
を、前のステップで作成したcsvファイルへのパスに置き換えます。
npx @aws-amplify/cli api generate-schema \
--sql-schema <path-to-schema.csv> \
--engine-type postgres --out lib/schema.sql.graphql
結果、lib/schema.sql.graphq
ファイルが出力されます。中身は以下の通りです。
input AMPLIFY {
engine: String = "postgres"
}
type Meal @refersTo(name: "meals") @model {
id: Int! @primaryKey
name: String!
}
@model
ディレクティブが付与されていることで、抽出、作成、更新、削除のメソッドが作成されることになります。
権限ルールの適用
上記のままではそれらのメソッドを呼び出そうとすると権限エラーとなってしまいます。
テストの段階では、パブリックな権限を付与します。
すべてのテーブルにパブリックな権限を付与する場合は、
globalAuthRule: AuthRule = { allow: public }
を設定します。
input AMPLIFY {
engine: String = "postgres"
globalAuthRule: AuthRule = { allow: public }
}
@model
ディレクティブにより生成するメソッドに対してのみ権限を与える場合は、以下のように記述します。
@auth(rules: [{ allow: public }]
を設定します。
type Meal @refersTo(name: "meals") @model @auth(rules: [{ allow: public }]){
id: Int! @primaryKey
name: String!
}
PostgreSQL DB への接続設定
メインスタックファイル「lib/<your-project-name>-stack.ts
」に、次のコードを追加して、新しい GraphQL API を定義します。
- 「vpcConfiguration」にPostgreSQL DBが属しているネットワーク情報を指定設定します。 ・vpcId: ・subnetId:とavailabilityZone:のセットを(2つ以上) ・securityGroupIds:
- 「dbConnectionConfg」に 前のステップで作成したDB接続情報のパラメータパスを設定します。
▼lib/<your-project-name>-stack.ts
export class AmplifyApiCdkStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
new AmplifyGraphqlApi(this, "AuroraPgDBApi", {
apiName: "AuroraPgDBApi",
definition: AmplifyGraphqlDefinition.fromFilesAndStrategy(
[path.join(__dirname, "schema.sql.graphql")],
{
name: "PostgresSchemaDefinition",
dbType: "POSTGRES",
vpcConfiguration: {
vpcId: "vpc-0e2d02d2283a78677",
securityGroupIds: ["sg-04e55700d0ba495b7"],
subnetAvailabilityZoneConfig: [
{
subnetId: "subnet-0c8ea8e8b4a525eb2",
availabilityZone: "ap-northeast-1a",
},
{
subnetId: "subnet-064011961200fa9fe",
availabilityZone: "ap-northeast-1c",
},
],
},
dbConnectionConfig: {
hostnameSsmPath: "/amplify-api-cdk/hostname",
portSsmPath: "/amplify-api-cdk/port",
usernameSsmPath: "/amplify-api-cdk/username",
passwordSsmPath: "/amplify-api-cdk/password",
databaseNameSsmPath: "/amplify-api-cdk/database",
},
}
),
authorizationModes: { apiKeyConfig: { expires: cdk.Duration.days(30) } },
});
}
}
GraphQL API を AWS クラウドにデプロイ
cdk bootstrap 実行
GraphQL API を AWS クラウドにデプロイする前に一度だけ実行します。 デプロイとのための準備がAWS CloudFormationスタックに格納されます。
❯ cdk bootstrap
cdk deploy 実行
cdk deploy
コマンドにより、lib/schema.sql.graphq
ファイルで定義したGraphQLのAPIが作成されます。
❯ cdk deploy
4. AWS AppSync コンソールでのAPI確認
▼作成した GraphQL API が作成されていることが確認できます。
▼「クエリ」項目では新たに定義したGraphQL に対応した APIが確認でき、ここで疎通確認やテストを行うことができます。
▼「スキーマ」項目では、各種メソッドが確認できます。
▼「データソース」の項目には以下の通りデータタイプ「NONE」と「AWS_LAMBDA」の2種類が作成されていることが確認できます。
▼「設定」の項目で作成したAPIのAPIキーを確認することができます。 2回目以降、GraphQL スキーマファイル:lib/schema.sql.graphqを変更するたびに cdk deploy コマンドを実行してAPIへ変更を反映させます。
API Helperソースの生成
実際のAPIをソースコードで使用するには「amplify codegen 」により、APIエンドポイントにアクセスできるライブラリーを作成します。
公式参考サイト:(AWS CDKの方を参照下さい) https://docs.amplify.aws/javascript/build-a-backend/graphqlapi/set-up-graphql-api/
> npx @aws-amplify/cli codegen add --apiId <YOUR_API_ID> --region <YOUR_API_REGION>
を実行することでクライアント環境にソースコードを生成します。
ルートディレクトリでコマンド実行、ソース出力先を聞かれます。
❯ npx @aws-amplify/cli codegen add --apiId XXXXXXXX --region XXXXXXXXX
? Choose the type of app that you're building javascript
? What javascript framework are you using react
✔ Getting API details
? Choose the code generation language target typescript
? Enter the file name pattern of graphql queries, mutations and subscriptions src/graphql/**/*.ts
? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions Yes
? Enter maximum statement depth [increase from default if your schema is deeply nested] 2
? Enter the file name for the generated code src/API.ts
? Do you want to generate code for your newly created GraphQL API (Y/n) Y
ソースコードが指定した場所に出力されます。
2回目以降の更新時は、下記コマンドを実行することなります。
> npx @aws-amplify/cli codegen
API呼び出し利用方法
▼例としてsrc/app/page.tsx
に以下を記述
// graphql API 呼び出しサンプル追記
import { generateClient } from "aws-amplify/api";
import { getMeal } from "../graphql/queries";
const client = generateClient();
function getMealData() {
const retMeal = client.graphql({ query: getMeal, variables: { id: 1 } });
console.log(retMeal);
}
上記、retMeal にDBデータ情報を含んだ結果が返ってきます。
詳細は、公式参考サイト を参照下さい。
5. まとめ
Aurora ServerlessV2 へアクセスするためのAmplify GraphQLを用いたAPI(AWS AppSync)を作成することができました。
今後はAmplify CLIの amplify add api
コマンドでのAPI作成ができるようになることを期待したいです。
Tatsuji Kimura