😋

Amplify x CDK でカスタムリソースを作る& CDK v2 に移行する

2021/12/18に公開

はじめに

これはAWS Amplify Advent Calendar 2021 18 日目の記事です。

Amplify CLI で CDK または CloudFormation を使ってカスタムリソースを作れるようになりました。この記事では Amazon IVS のプライベートチャネルを作ってみます。またどうも Amplify CLI 7.6.4 時点ではカスタムリソースを作るのに CDK v1 が使われているようなので CDK v2 に移行してみました。

なぜこの記事を書こうと思ったか

あまり言ってないのですが私は Amplify が好きです。最初は AppSync のリゾルバを簡単に作れるところが気に入って(なので Amplify CLI を AppSync SDK みたいに思っていた)、最近は Amplify Console を使って git push するだけでウェブサイトをホストできるところが気に入ってます。AWS Copilot CLI や CDK Pipelines もそうですが簡単に CI/CD を整備できるのはいいものです。

またこれはよく言っているのですが私は AWS CDK も好きです。IaC は最初 CloudFormation から入ったので YAML を書けと言われたら書くだろうけど、TypeScript を使った少ない記述量で様々な AWS サービスを柔軟に作れる CDK は触っていて楽しいです。

そして今年は Amplify で生成されたバックエンドリソースを CDK でカスタマイズできるようになったり、CDK か CloudFormation でカスタムリソースを作れるようになったりと Amplify x CDK が熱いです。

うどんが好きでカレーも好きな人はカレーうどんももちろん好きですよね?同じように Amplify が好きで CDK も好きな私のような人間にとってはこうしたアップデートはめちゃめちゃ気になる訳です。というわけで早速触ってみました。

実際に触ってみる

環境の確認

以下の環境で動作を確認しています。

$ node --version
v16.13.1
$ npm --version
8.1.2
$ amplify --version
7.6.4

React アプリの初期化

React アプリの初期化には Vite を使います。この記事では本格的に React アプリを開発するわけではないので Create React App でもいいっちゃいいんですがまぁ速く動く方が嬉しいですからね。

$ npm init vite@latest amplify-cdk-app -- --template react-ts
$ cd amplify-cdk-app
$ npm install
$ npm run dev

Amplify プロジェクトの初期化

以下のコマンドを実行します。

$ amplify configure
$ amplify init
Note: It is recommended to run this command from the root of your app directory
? Enter a name for the project amplifycdkapp
The following configuration will be applied:

Project information
| Name: amplifycdkapp
| Environment: dev
| Default editor: Visual Studio Code
| App type: javascript
| Javascript framework: react
| Source Directory Path: src
| Distribution Directory Path: build
| Build Command: npm run-script build
| Start Command: npm run-script start

? Initialize the project with the above configuration? Yes
Using default provider  awscloudformation
? Select the authentication method you want to use: AWS profile

For more information on AWS Profiles, see:
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html

? Please choose the profile you want to use default

カスタムリソースの追加

いよいよお待ちかねのカスタムリソースを作成します。リソース名は customIVSChannel とします。

$ amplify add custom
✔ How do you want to define this custom resource? · AWS CDK
✔ Provide a name for your custom resource · customIVSChannel
✅ Created skeleton CDK stack in amplify/backend/custom/customIVSChannel directory
✔ Do you want to edit the CDK stack now? (Y/n) · no

すると amplicy/backend/custom/customIVSChannel ディレクトリが作成されます。 package.json をみると CDK 1.124.0 が使われているようです。 cdk-stack.ts にスタックを定義することでカスタムリソースを作成できます。また node_modules があるのが気になりますね。

今回は IVS のチャネルを作るので package.json@aws-cdk/aws-ivs を追加し、 cdk-stack.ts で IVS チャネルを作成しましょう。 amplify/backend/custom/customIVSChannel/package.json は以下のような感じで

{
  "name": "custom-resource",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies": {
    "@aws-amplify/cli-extensibility-helper": "^2.0.0",
    "@aws-cdk/core": "~1.124.0",
    "@aws-cdk/aws-ivs": "~1.124.0"
  },
  "devDependencies": {
    "typescript": "^4.2.4"
  }
}

amplify/backend/custom/customIVSChannel/cdk-stack.ts は以下のようにします。

import * as cdk from '@aws-cdk/core';
import * as AmplifyHelpers from '@aws-amplify/cli-extensibility-helper';
import { AmplifyDependentResourcesAttributes } from '../../types/amplify-dependent-resources-ref';
import * as ivs from '@aws-cdk/aws-ivs';

export class cdkStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps, amplifyResourceProps?: AmplifyHelpers.AmplifyResourceProps) {
    super(scope, id, props);
    /* Do not remove - Amplify CLI automatically injects the current deployment environment in this input parameter */
    new cdk.CfnParameter(this, 'env', {
      type: 'String',
      description: 'Current Amplify CLI env name',
    });
    const myChannel = new ivs.Channel(this, 'Channel', {
      authorized: false
    });
  }
}

CI/CD の準備( CodeCommit 作成から git push まで)

amplify push してもいいですがせっかくなので CI/CD しちゃいましょう。簡単のため Git リポジトリは CodeCommit にしますが GitHub でもいけるはず。

$ aws codecommit create-repository --repository-name amplify-cdk
$ git init
$ git remote add origin https://git-codecommit.us-east-1.amazonaws.com/v1/repos/amplify-cdk

あとは CodeCommit にプッシュしましょう。

$ git add .
$ git commit -m 'initial commit'
$ git push origin master

CI/CD の準備( Amplify Console の設定)

ここからは AWS コンソールで Amplify Console の設定を行います。


CodeCommit を選択


リポジトリは amplify-cdk ブランチは master を選択


ビルド設定は CI/CD の有効化にチェックを入れる


ビルドスクリプトはデフォルトのままで Next をクリック


設定を確認してデプロイする

しばらく待つと CodeCommit からコードをクローンしてきてビルドが始まります。カスタムリソースも無事作成されて IVS のページに行くと以下のようにパブリックチャネルが作成されています。

CDK v2 への移行

私は CDK v2 が Developer Preview になった頃には CDK v1 から v2 に移っていたので CDK v1 を触るのは久しぶりでした。

CDK v1 は 2022 年 6 月 1 日からメンテナンスフェーズに入るので CDK v2 への移行を試してみましょう。

CDK v2 への移行はこのドキュメントに詳しく書かれています。CDK v2 だと ivs や ec2 などの各モジュールが aws-cdk-lib にまとまっているので管理がやりやすくなります。 amplify/backend/custom/customIVSChannel/package.json は以下のような感じにします。

{
  "name": "custom-resource",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies": {
    "@aws-amplify/cli-extensibility-helper": "^2.0.0",
    "aws-cdk-lib": "2.0.0",
    "constructs": "^10.0.0"
  },
  "devDependencies": {
    "typescript": "^4.2.4"
  }
}

また CDK v1 だと @aws-cdk/core に Stack や StackProps, Construct, CfnParameter があったのが CDK v2 だと Construct 以外は aws-cdk-lib に移動しています。Construct だけ constructs の中にあります。さらに IVS モジュールの話ですが CDK v2.0.0 の IVS モジュールには L2 Construct がありません。なので L1 Construct を使うことにします。 amplify/backend/custom/customIVSChannel/cdk-stack.ts はこんな感じで違いがわかるように IVS のチャネルをプライベートに変更しました。

import { Stack, StackProps, CfnParameter } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as AmplifyHelpers from '@aws-amplify/cli-extensibility-helper';
import { AmplifyDependentResourcesAttributes } from '../../types/amplify-dependent-resources-ref';
import * as ivs from 'aws-cdk-lib/aws-ivs';

export class cdkStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps, amplifyResourceProps?: AmplifyHelpers.AmplifyResourceProps) {
    super(scope, id, props);
    /* Do not remove - Amplify CLI automatically injects the current deployment environment in this input parameter */
    new CfnParameter(this, 'env', {
      type: 'String',
      description: 'Current Amplify CLI env name',
    });
    const myChannel = new ivs.CfnChannel(this, 'Channel', {
      authorized: true
    });
  }
}

あとは git push するだけで変更が反映されます。

$ git add amplify/backend/custom/customIVSChannel/cdk-stack.ts amplify/backend/custom/customIVSChannel/package.json
$ git commit -m 'migrate to CDK v2'
$ git push origin master

おわりに

Amplify プロジェクトの中で CDK も使えるようになるとバックエンドの作成がかなり柔軟になりそうです。私ならフロント側からアクセスするリソース ( AppSync とか API Gateway とか)は Amplify CLI で作成して細かい設定は CDK で override する、フロントからアクセスしないようなリソースは CDK のカスタムリソースで作成するかなぁと思いました。

Discussion