LoginSignup
2
1

More than 1 year has passed since last update.

AppSync & Aurora Serverless の GraphQL バックエンドを CDK で構築したぞい!(2022/05/24版)

Last updated at Posted at 2022-06-01

更新
・2022/07/24 はまったこと の原因を記載

はじめに

これまで、API Gateway + Lambda + RDS(or Aurora Serverless)の REST API バックエンドしか実装したことがなかったのですが、いま参加している開発ではじめて AppSync + Aurora Serverless の GraphQL バックエンドを実装することになったので、色々調べならが実装中の、現時点の CDK のコードについて軽く紹介してみたいと思います。

本記事は、以下の記事の後続記事となります。
Aurora Serverless の CDK のコードについてご覧になりたい方は、こちらをどうぞ。

試した内容

利用したライブラリ

ライブラリ名 バージョン
aws-cdk-lib 2.25.0
@aws-cdk/aws-appsync-alpha 2.25.0-alpha.0
  • AppSync は、GraphQLスキーマとリゾルバ(VTLファイル)を分離して参照する形にしたかったので aws-appsync-alpha の方を試してみました。

実装コード例

ディレクトリ構成

. 
└ lib
│ ├ api
│ │ ├ schema.graphql
│ │ └ resolvers
│ │   └ items
│ │     ├ get-items-req.vtl
│ │     └ get-items-resp.vtl
│ ├ stack
│ │ └ xxx-stack.tsx

GraphQL スキーマ

schemas.graphql

type Item {
  id: ID!
  name: String
}

type Query {
  getItemss: [Item]
}

schema {
  query: Query
}
  • はじめてのお試しなので Model と Query だけ(Mutation はまだ未定義)

リゾルバー

get-items-req.vtl

## SQLステートメントの定義
#set ($statement = "SELECT * FROM item")

## リクエストテンプレートの定義
## @see https://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/tutorial-rds-resolvers.html
{
    "version": "2018-05-29",
    "statements": [
        $util.toJson(${statement})
    ]
}
  • SQLステートメントは複数行で整形して書くこともできる模様
    AppSync Resolver multiline string · Issue #2331 · aws-amplify/amplify-cli

  • version って何のバージョンなのか、まだ未確認

  • 入力データがある場合は、セキュリティ対策のためにサニタイズが必要ということだが、現時点では条件なしの一覧検索なので未確認

get-items-resp.vtl

## レスポンステンプレートの定義
## @see https://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/tutorial-rds-resolvers.html
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0])
  • 検索結果をそのまま返すだけなら、お作法に従うだけのよう

スタック

import * as rds from 'aws-cdk-lib/aws-rds';
import * as appsync from '@aws-cdk/aws-appsync-alpha';

/**
 * Aurora Serverless をバックエンドに持つ AppSync GraphQL API の定義
 * @see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-appsync-alpha-readme.html
 * @param scope
 * @param cluster ★前回の記事で作成した Aurora Serverless のクラスター★
 */
const graphqlApi = (scope: Construct, cluster: rds.ServerlessCluster) => {
  const api = new appsync.GraphqlApi(scope, 'GraphqlApi', {
    name: 'GraphqlApi',
    schema: appsync.Schema.fromAsset('./lib/api/schema.graphql'),
    xrayEnabled: true,
  });

  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
  const dataSource = api.addRdsDataSource('RdsDataSource', cluster, cluster.secret!, env.rdsDatabaseName());
  dataSource.createResolver({
    typeName: 'Query',
    fieldName: 'getItems',
    requestMappingTemplate: appsync.MappingTemplate.fromFile('./lib/api/resolvers/items/get-items-req.vtl'),
    responseMappingTemplate: appsync.MappingTemplate.fromFile('./lib/api/resolvers/items/get-items-resp.vtl'),
  });

  return api;
};
  • GraphqlApi
    • GraphqlApiPropsschema 属性に、schema.graphql ファイルから読み込んだスキーマ定義を指定します
    • GraphqlApiPropsauthorizationConfig 属性を省略すると、既定値は API キーによる認証モードが適用されます
  • RdsDataSource の createResolver
    • BaseResolverPropstypeName に GraphQL の操作種別(Query or Mutation)を指定します
    • BaseResolverProps のと fieldName に、schema.grapql で定義したクエリの名前を指定します
    • requestMappingTemplateresponseMappingTemplate に、リクエスト・レスポンスそれぞれのリゾルバーファイルから読み込んだテンプレート定義を指定します

スタックのコードをみると、かなりスッキリと書けているかな。と思います。

API Gateway を OpenAPI Spec ファイルから作成するのと比べると、少しだけ色々書かないといけないようですが…

はまったこと

初回デプロイ時に AWSServiceRoleForAppSync の作成に失敗したように見える

14:16:46 | CREATE_FAILED        | AWS::AppSync::GraphQLApi                    | GraphqlApiXXXXXXXX
Failed to assume service-linked role arn:aws:iam::xxxxxxxxxxxx:role/aws-service-role/appsync.amazonaws.com/AWSServiceRoleForAppSync, please retry. (Service: AWSAppSync; Status Code: 403; Error Code: AccessDeniedException; Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx; Proxy: null)

 ❌  XxxxStack failed: Error: The stack named XxxxStack failed to deploy: UPDATE_ROLLBACK_COMPLETE: Failed to assume service-linked role arn:aws:iam::xxxxxxxxxxxx:role/aws-service-role/appsync.amazonaws.com/AWSServiceRoleForAppSync, please retry. (Service: AWSAppSync; Status Code: 403; Error Code: AccessDeniedException; Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx; Proxy: null)
    at prepareAndExecuteChangeSet (/xxxx/node_modules/aws-cdk/lib/api/deploy-stack.ts:385:13)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at CdkToolkit.deploy (/xxxx/node_modules/aws-cdk/lib/cdk-toolkit.ts:209:24)
    at initCommandLine (/xxxx/node_modules/aws-cdk/lib/cli.ts:341:12)

The stack named XxxxStack failed to deploy: UPDATE_ROLLBACK_COMPLETE: Failed to assume service-linked role arn:aws:iam::xxxxxxxxxxxx:role/aws-service-role/appsync.amazonaws.com/AWSServiceRoleForAppSync, please retry. (Service: AWSAppSync; Status Code: 403; Error Code: AccessDeniedException; Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx; Proxy: null)

Issue #16598

執筆時点では未解決の不具合のようです。
再デプロイすると正常動作するため、エラーが出たら再実行すれば動作します。

最後に

AppSync & Aurora Serverless の GraphQL バックエンドがちゃんと完成したら、もう少ししっかりした内容に更新しますぞ〜。

以上。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1