[TypeScript] AWS-CDK 備忘録

普段はserverless frameworkを使用しているので備忘録として残す
気になる所があったら随時更新していく

# AWS-CDK

https://github.com/aws/aws-cdk
 
### インストール
GAはNode.js≧10.3.0以上じゃないといけない

```
npm i -g aws-cdk
```

### cdk init

`cdk init`は空ディレクトリでないと実行出来ないので注意

```
mkdir test-cdk
cd test-cdk
cdk init app --language=typescript
npm i 
```

### cdk.tsの実装

環境変数(direnvを使用)

```
direnv edit .
```

```:.envrc
export AWS_REGION=ap-northeast-1
export STAGE=dev
```

accountは`cdk deploy --profile [aws profile]`を使用するためコメントアウト
regionはデプロイしたいリージョンを指定する(環境変数で管理してる)

```
npm i @types/node
```

```typescript:bin/test-cdk.ts
import 'source-map-support/register';
import cdk = require('@aws-cdk/core');
import {TestCdkStack} from '../lib/test-cdk-stack';

const app = new cdk.App();
new TestCdkStack(app, 'TestCdkStack', {
    env: {
        // account: '',
        region: process.env.AWS_REGION
    }
});
app.synth();
```

###Lambda Handlerの実装



```
npm i aws-lambda @types/aws-lambda
```

```typescript:src/lambda/test.ts
import {APIGatewayEvent, Handler} from 'aws-lambda';

export const handler: Handler = async (event: APIGatewayEvent) => {
    let test: string = '';

    if (event.body != null) {
        const body = JSON.parse(event.body);
        test = body.test;
    } else {
        return {
            statusCode: 400,
            body: 'invalid request'
        };
    }

    return {
        statusCode: 200,
        body: test
    };
};

```

### apigateway-lambdaの実装

```
npm i @aws-cdk/aws-lambda @aws-cdk/aws-apigateway
```

```json:cdk.json
{
  "context": {
    "serviceName": "test"
  },
  "app": "npx ts-node bin/test-cdk.ts"
}
```

envに指定したstageの情報を持ってdev/prodの環境を分ける

```typescript:lib/test-cdk-stack.ts
import * as cdk from '@aws-cdk/core';
import * as lambda from '@aws-cdk/aws-lambda';
import * as apiGateway from '@aws-cdk/aws-apigateway';

export class TestCdkStack extends cdk.Stack {
    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);

        const serviceName: string = this.node.tryGetContext("serviceName");
        const stage: string = process.env.STAGE ? process.env.STAGE : 'dev';

        const testLambda = new lambda.Function(this, 'testFunction', {
            functionName: `${serviceName}-${stage}`,
            code: new lambda.AssetCode('src/lambda'),
            handler: 'test.handler',
            runtime: lambda.Runtime.NODEJS_10_X,
            memorySize: 128,
            timeout: cdk.Duration.seconds(30),
            environment: {
                // lambda環境変数を指定する
                // STAGE: stage
            }
        });

        const api = new apiGateway.RestApi(this, 'testApi', {
            restApiName: `${serviceName}-service-${stage}`,
            // stageNameの情報を付与しないとEndpointが/prod/になってしまう
            deployOptions: {
                stageName: stage
            }
        });

        const root = api.root.addResource('tests');
        const testLambdaIntegration = new apiGateway.LambdaIntegration(testLambda);
        root.addMethod('POST', testLambdaIntegration);
    };
}
```

### デプロイ

`[aws profile]`を適宜変更して実行

```
// cdk bootstrapを実行するのは一度だけでいい
cdk bootstrap --profile [aws profile]

// ビルド&デプロイ
npm run build
cdk deploy --profile [aws profile]
```

### 削除

```
cdk destroy --profile [aws profile]
```

## 注意点

name関連にデフォルト値が設定されている箇所が多いので、作成したい環境に合わせて設定していく必要がある