この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
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.