Top View


Author Tatsuji Kimura

AWS AmplifyでAuroraServerlessV2の連携API環境を構築する

2024/04/26

1.はじめに

2023年末にAWS AmplifyにてAuroraServerlessV2との連携が できるようになったことを踏まえて連携API環境構築手順について記述します。

関連参考記事

今回実施した各種バージョン情報:

  • 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/hostnameaurora-cluster.cluster-XXXXXXXXXXmg.ap-northeast-1.rds.amazonaws.com※1
/amplify-api-cdk/usernamepostgresDBユーザー名
/amplify-api-cdk/passwordpostgresDBパスワード
/amplify-api-cdk/port5432DBポート番号
/amplify-api-cdk/databaseauroradbDB名

・(※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に出力します。 クエリエディタで実行し、結果を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 が作成されていることが確認できます。 API確認01_▼作成した GraphQL API が作成されていることが確認できます

▼「クエリ」項目では新たに定義したGraphQL に対応した APIが確認でき、ここで疎通確認やテストを行うことができます。 API確認02_▼「クエリ」項目では新たに定義したGraphQL に対応した APIが確認できます

▼「スキーマ」項目では、各種メソッドが確認できます。 API確認03_▼「スキーマ」項目では、各種メソッドが確認できます

▼「データソース」の項目には以下の通りデータタイプ「NONE」と「AWS_LAMBDA」の2種類が作成されていることが確認できます。 API確認04_▼「データソース」の項目には以下の通りデータタイプ「NONE」と「AWS_LAMBDA」の2種類のデータソースが作成されていることが確認できます

▼「設定」の項目で作成したAPIのAPIキーを確認することができます。 API確認05_▼「設定」の項目で作成した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

Tatsuji Kimura

エンジニアをやっています。