この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
どうもこんにちは。 この前、AWS CDKのチュートリアルを意気揚々とやっていました。 これでコーディングしながらインフラ構築してるといけしゃあしゃあと言えると思っていましたが、チュートリアルでつまづきました。 何度やってもうまくいかずに、コピペしてもうまくいかない箇所がありました。 今回は何故うまくいかなったかと対処方法、そして、CDKプロジェクトの始め方について書いてみます。
何が起きたのか
始めて触るので、チュートリアル通りに進めていました。
$ mkdir cdk-101
$ cd cdk-101
$ npx cdk init --language typescript
$ npm run build
ここまでは問題なく動き、S3バケットをCDKスタックの中に追加するコーディングを行いました。 まずは、ライブラリを追加しました。
$ npm install @aws-cdk/aws-s3
そして、S3バケットの中身をこんな感じで書き換えました。
lib/cdk-101-stack.ts
import cdk = require('@aws-cdk/cdk');
import s3 = require('@aws-cdk/aws-s3');
export class Cdk101Stack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
new s3.Bucket(this, 'MyFirstBucket', {
versioned: true
});
}
}
そのあとに、変更を反映させるためにビルドコマンドをかけたところでエラーが発生しました。
$ npm run build
> cdk-101@0.1.0 build /Users/josh/Documents/github/cdk-101
> tsc
lib/cdk-101-stack.ts:8:19 - error TS2345: Argument of type 'this' is not assignable to parameter of type 'Construct'.
Property 'synthesize' is missing in type 'Cdk101Stack' but required in type 'Construct'.
8 new s3.Bucket(this, 'MyFirstBucket', {
~~~~
node_modules/@aws-cdk/core/lib/construct.d.ts:267:15
267 protected synthesize(session: ISynthesisSession): void;
~~~~~~~~~~
'synthesize' is declared here.
Found 1 error.
チュートリアル通りなはずなのに、typescriptのビルドで失敗してますね。
エラーの内容とGitHubのIssueを照らし合わせた感じでライブラリのバージョン(@aws-cdk/cdk
と@aws-cdk/aws-s3
)が同じじゃなきゃダメそうでした。
ライブラリのバージョンを確認してみます。
package.json
{
"name": "cdk-101",
"version": "0.1.0",
"bin": {
"cdk-test": "bin/cdk-test.js"
},
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"cdk": "cdk"
},
"devDependencies": {
"@types/node": "^8.9.4",
"typescript": "^3.1.2",
"aws-cdk": "^0.24.1"
},
"dependencies": {
"@aws-cdk/aws-s3": "^0.37.0",
"@aws-cdk/cdk": "^0.24.1",
"source-map-support": "^0.5.9"
}
}
確かにバージョンに大きくズレがありますね。 ベータ版なので、マイナーバージョンの変更でも破壊的変更が含まれている可能性はあるので、原因はこれでしょう。 ライブラリのバージョンを直せばうまくいきそうですね。
なぜ起きたのか
グローバルインストールしていたaws-cdkのバージョンが古かったのが一番の要因です。
なので、initコマンドは古いのをベースにプロジェクトを作成し、新たにインストールした@aws-cdk/aws-s3
はバージョンを指定していないため、最新の0.37.0をインストールしています。
結果してバージョンが合わずに問題が起きたということです。
グローバルインストールしたaws-cdkのバージョンを上げるか、インストールするライブラリのバージョンを指定するかをする必要がありました。 バージョンを指定して、入れる場合はこのようにします。
$ npm install @aws-cdk/aws-s3@0.24.1
この後再度ビルドなどを試してみると問題なく進んでいきます。
$ npm run build
$ npx cdk synth
Resources:
MyFirstBucketB8884501:
Type: AWS::S3::Bucket
Properties:
VersioningConfiguration:
Status: Enabled
DeletionPolicy: Retain
Metadata:
aws:cdk:path: CdkOldStack/MyFirstBucket/Resource
CDKMetadata:
Type: AWS::CDK::Metadata
Properties:
Modules: aws-cdk=0.24.1,jsii-runtime=node.js/v12.5.0
プロジェクトの新規作成時に古いライブラリを使うのもおかしな話なので、aws-cdkのバージョンを上げるのがベストだとは思います。
$ npm i -g aws-cdk
今回のエラーの原因がわかったところで、initで行なっていることを手でやって、プロジェクトに対する理解を深めていきたいと思います。
フルスクラッチでプロジェクトを始める
結局のところcdk init
が行なっていることは、ディレクトリ内にファイルを配置したり、ライブラリをインストールしたりしているだけです。
なので一から手で同じことも行えます。
出来上がったリポジトリはGitHubにあげているのでご確認ください。
それでは作業を始めていきましょう。何はともあれnpm init
します。
そのあとに必要なライブラリをインストールしていきます。
$ npm init
$ npm i -D @types/node typescript aws-cdk
$ npm i @aws-cdk/core
先ほどまでインストールしていた@aws-cdk/cdk
はどこに行ったのでしょうか。山に帰ったのでしょうか。
npmjsを確認すればわかりますが、@aws-cdk/core
という名前に変えられました。
出来上がったpackage.jsonの中身はこのようになりました。
package.json
{
"name": "cdk-template-ts",
"description": "template repo for AWS CDK",
"version": "0.37.0",
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"cdk": "cdk"
},
"author": "37108",
"license": "MIT",
"devDependencies": {
"@types/node": "^12.0.12",
"aws-cdk": "^0.37.0",
"typescript": "^3.5.2"
},
"dependencies": {
"@aws-cdk/core": "^0.37.0"
}
}
次にTypeScriptの設定のためにtsconfig.json
を作成します。
今回は何としてもビルドが通るように激甘な設定にしていますが、お好みの設定でお願いします。
tsconfig.json
{
"compilerOptions": {
"target": "ES2018",
"module": "commonjs",
"lib": [
"es2016",
"es2017.object",
"es2017.string"
],
"noUnusedLocals": false,
"noUnusedParameters": false
}
}
AWS CDKの設定に入っていきます。
スタック作成時の起点をindex.ts
として、src以下にインポートしたいファイル群をまとめるようにするため、このようなディレクトリ構造を目指します。
.
├── index.ts
│
├── src/
│ ├── /xxx.ts
│ ├── /yyy.ts
起点となるindex.tsの中身はこのような感じです。今回はsrc以下になにも作っていないのでインポートはしてないです。 実際はTemplateStackクラスのコンストラクタに必要なリソースについての記述を行なっていきます。
index.ts
import cdk = require('@aws-cdk/core')
class TemplateStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props: cdk.StackProps = {}) {
super(parent, name, props)
}
}
const app = new cdk.App()
new TemplateStack(app, 'TemplateStack')
app.synth()
AWS CDKの設定ファイル、cdk.json
をいじります。
だいぶスッキリしてますね。
cdk.json
{
"app": "node index"
}
最後にREADMEをちょちょっと書いてAWS CDKの準備完了です。 一応問題なくビルドができるかを確認します。
$ npm run build
$ npx cdk synth
Resources:
CDKMetadata:
Type: AWS::CDK::Metadata
Properties:
Modules: aws-cdk=0.37.0,@aws-cdk/core=0.37.0,@aws-cdk/cx-api=0.37.0,jsii-runtime=node.js/v12.5.0
中身のないスタックではありますが、問題なさそうですね。
そして、0.36.0
以降のバージョンではでAWS CDKからデプロイする方法が少し変わっています。
cdk deploy
する前に、cdk bootstrap
する必要があります。
具体的にはこんな感じです。
$ npx cdk bootstrap aws://123456789012/ap-northeast-1
$ npx cdk deploy
aws://123456789012/ap-northeast-1
これの前半部分でAWSアカウント、後半部分でリージョンを指定しています。
これが実行されると、CDK用のS3バケットが作成されて、cdk deploy
が可能になります。
さいごに
AWS CDKを使うとTypeScriptなどのコードがらCloudFormationのテンプレートを作成したり、プロジェクトを管理できたりするのでユースケースによっては今までのIaCツールより有用な場合もあります。 なので十分導入したくなるものなので今後の発展をささやかながらお祈りしています。