[Cloud Development Kit ] LINEアプリのサンプルをCDKで書き直して見て、その凄さを実感しました
1 はじめに
CX事業本部の平内(SIN)です。
昨日、GAとなった AWS Cloud Development Kit (AWS CDK) 凄すぎます。
完全に、上の記事の真似事なんですが・・・私も、早速やってみたい!って事で、先日、作ったAWS SAM + TypeScriptで作成したLINE Bot のサンプルをAWS CDKで書き直してみました。
2 プロジェクト作成
CDKのコマンド initでプロジェクトを作成します。
$ mkdir line-sample $ cd line-sample [line-sample]$ cdk init app --language=typescript
3 Lambda
続いて、プロジェクトの階層下にsrc/lambdaを掘って、Lambdaのコードを作成します。
[line-sample]$ mkdir src; cd src [line-sample/src]$ mkdir lambda; cd lambda [line-sample/src/lambda]$ touch index.ts
コードは、前回作成したものと同じです。
src/lambda/index.ts
import * as Lambda from 'aws-lambda'; import * as Line from "@line/bot-sdk"; import * as Types from "@line/bot-sdk/lib/types"; import { WebhookEvent } from '@line/bot-sdk'; const accessToken = process.env.ACCESS_TOKEN!; const channelSecret = process.env.CHANNEL_SECRET!; const config: Line.ClientConfig = { channelAccessToken: accessToken, channelSecret: channelSecret, }; const client = new Line.Client(config); async function eventHandler(event: Types.MessageEvent): Promise<any> { if (event.type !== 'message' || event.message.type !== 'text') { return null; } const message: Types.Message = { type: "text", text: event.message.text + "ってか?" }; return client.replyMessage(event.replyToken, message); } export const handler: Lambda.APIGatewayProxyHandler = async (proxyEevent:Lambda.APIGatewayEvent, _context) => { console.log(JSON.stringify(proxyEevent)); // 署名確認 const signature = proxyEevent.headers["X-Line-Signature"]; if (!Line.validateSignature(proxyEevent.body!, channelSecret, signature)) { throw new Line.SignatureValidationFailed("signature validation failed", signature); } const body: Line.WebhookRequestBody = JSON.parse(proxyEevent.body!); await Promise .all(body.events.map( async event => eventHandler(event as Types.MessageEvent))) .catch( err => { console.error(err.Message); return { statusCode: 500, body: "Error" } }) return { statusCode: 200, body: "OK" } }
4 パッケージのインストール
npmパッケージのインストールを行います。
TypeScript用の型情報は、プロジェクトのトップに入れます。
TS 型定義用
[line-sample]$ npm install @types/aws-lambda [line-sample]$ npm install @line/bot-sdk
CDK 型定義用
[line-sample]$ npm install @aws-cdk/aws-lambda [line-sample]$ npm install @aws-cdk/aws-apigateway
そして、Lambdaで使用されるパッケージは、src/lambda/node_modulesに入れます。
Lambda用
[line-sample/src/lambda]$ npm init [line-sample/src/lambda]$ npm install @line/bot-sdk [line-sample/src/lambda]$ npm install aws-lambda
5 テンプレート
いよいよテンプレートをTSで作成します。これが、ビックリするぐらい簡単過ぎなんです。
下記は、APIGatewayでエンドポイントを作成し、POSTメソッドからLambdaをプロキシーで呼び出しているものです。
これをテンプレートで実際書いたら結構な量になると思います。これだけ簡単にできるのは、何と言ってもロールなどが、AWSのベストプラアクティスにのっとって、デフォルトで生成されるのが、一番の理由でしょう。
lib/line-sample-stack.ts
import cdk = require('@aws-cdk/core'); import * as lambda from '@aws-cdk/aws-lambda'; import * as apigateway from '@aws-cdk/aws-apigateway'; export class LineSampleStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const lineSampleLambda = new lambda.Function(this, 'LineSampleLambda', { code: lambda.Code.asset('src/lambda'), handler: 'index.handler', runtime: lambda.Runtime.NODEJS_10_X, timeout: cdk.Duration.seconds(5), environment: { ACCESS_TOKEN: "xxxxx", CHANNEL_SECRET: "xxxxx" } }); const api = new apigateway.RestApi(this, 'LineSampleApi', { restApiName: 'line-sample' }); const lambdaIntegration = new apigateway.LambdaIntegration( lineSampleLambda, { proxy: true } ); api.root.addMethod('POST', lambdaIntegration) } }
6 ビルド
ビルドは、実際にはtscが走っています。
[line-sample]$ npm run build > line-sample@0.1.0 build /Users/hirauchi.shinichi/tmp/line-sample > tsc
そして、出来上がったテンプレートです。(長いので、省略しています)
$ cdk synth Resources: LineSampleLambdaServiceRole802545FF: Type: AWS::IAM::Role ・・・略・・・ LineSampleLambda148E180F: Type: AWS::Lambda::Function ・・・略・・・ LineSampleLambdaApiPermissionPOST53C46664: Type: AWS::Lambda::Permission ・・・略・・・ LineSampleLambdaApiPermissionTestPOSTF7E1E36E: Type: AWS::Lambda::Permission ・・・略・・・ LineSampleApi562C5419: Type: AWS::ApiGateway::RestApi ・・・略・・・ LineSampleApiDeployment3578462012279476a9eab561f7edbe4db9f431ea: Type: AWS::ApiGateway::Deployment ・・・略・・・ LineSampleApiDeploymentStageprod08264243: Type: AWS::ApiGateway::Stage ・・・略・・・ LineSampleApiCloudWatchRole3AC02CBD: Type: AWS::IAM::Role ・・・略・・・ LineSampleApiAccount094622A7: Type: AWS::ApiGateway::Account ・・・略・・・ LineSampleApiPOSTF56853D2: Type: AWS::ApiGateway::Method ・・・略・・・ Parameters: ・・・略・・・ Outputs: ・・・略・・・
7 bootstrap
初めてCDKを利用する場合は、1回だけ bootstrapコマンドを実行してデプロイ用のBucketの準備が必要です。
$ cdk bootstrap --profile developer
8 デプロイ
$ cdk deploy --profile developer
作成されるリソースの一覧で y を入力するとデプロイされます。
9 スタック確認
AWSコンソールから確認した、リソースです。
CloudFormation
Lambda
API Gateway
ステージからURLをコピーして、LINEプロジェクトのエンドポイントに設定します。
10 動作確認
LINEから使用すると、元気にLambdaから返事が返ってきます。
11 最後に
いやー何度も言ってしまいますが、AWS CDK凄すぎます。
CFnや、SAMのテンプレート作成が、なんだかんだ言って、手際が悪くて辛かった私にとって、TypeScriptで書けるAWS CDKは、神です。
ちなみに、AWS CDKは、現時点で開発者プレビューみたいですが、C#とかJavaでも利用できます。間違いなく静的型付けの威力が発揮されるでしょう。
Use the AWS CDK to define your cloud resources in a familiar programming language. The AWS CDK supports TypeScript, JavaScript, and Python. The AWS CDK also provides Developer Preview support for C#/.NET, and Java.