AWS CDK でカスタム Construct を作って、他の CDK プロジェクトから使ってみる
はじめに
CX事業本部@札幌の佐藤です。最近はCDKが面白くてCDKのブログばかり書いています。
AWS CDKでは、CDK標準のライブラリを使用してリソースを定義する他にも、独自にライブラリを作って作成することもできます。
概要
今回は独自のConstructライブラリを作成して、それをnpmにpublishして、他のCDKプロジェクトのスタックでrequireしてAWSにデプロイするということをやっていきます。
環境
項目 | バージョン |
---|---|
macOS | Mojave 10.14.5 |
node | v10.16.0 |
npm | 6.9.0 |
cdk | 1.12.0 (build 923055e) |
事前準備
npmjsでアカウントを作成しておきます。その後、以下のコマンドで、username、password、emailを入力してユーザーを作成しておきます。
npm adduser
やってみた
CDKのプロジェクトの作成
まずはCDKのプロジェクトを作成します。
$ cdk init Available templates: * app: Template for a CDK Application └─ cdk init app --language=[csharp|fsharp|java|javascript|python|typescript] * lib: Template for a CDK Construct Library └─ cdk init lib --language=typescript * sample-app: Example CDK Application with some constructs └─ cdk init sample-app --language=[csharp|javascript|python|typescript]
cdk init
とすると、コマンド体系の一覧が表示されます。普通のCDKのプロジェクトの場合は、cdk init app
となりますが、今回はライブラリを作成するため、cdk init lib
の方を使用します。言語はTypeScript
を使用します。
$ cdk init lib --language=typescript
サンプルConstruct Libraryのソースの確認
プロジェクトを作成すると、以下のようなサンプルコードが作られています。サンプルコードでは、cdk.Construct
を継承したクラスが作成されています。独自ライブラリを作るには、cdk.Construct
クラスを継承したクラスを作成し、コンストラクタでAWSリソースを定義していきます。このサンプルコードでは、SQS
、SNSトピック
、SNSサブスクリプション
を作っています。また、インスタンス変数でSQSキューのARNを設定しているため、これを他のConstructの引数などに設定できるようになっています。
import sns = require('@aws-cdk/aws-sns'); import subs = require('@aws-cdk/aws-sns-subscriptions'); import sqs = require('@aws-cdk/aws-sqs'); import cdk = require('@aws-cdk/core'); export interface AwsCdkLibSampleProps { /** * The visibility timeout to be configured on the SQS Queue, in seconds. * * @default Duration.seconds(300) */ visibilityTimeout?: cdk.Duration; } export class AwsCdkLibSample extends cdk.Construct { /** @returns the ARN of the SQS queue */ public readonly queueArn: string; constructor(scope: cdk.Construct, id: string, props: AwsCdkLibSampleProps = {}) { super(scope, id); const queue = new sqs.Queue(this, 'AwsCdkLibSampleQueue', { visibilityTimeout: props.visibilityTimeout || cdk.Duration.seconds(300) }); const topic = new sns.Topic(this, 'AwsCdkLibSampleTopic'); topic.addSubscription(new subs.SqsSubscription(queue)); this.queueArn = queue.queueArn; } }
npmに公開する
他のCDKプロジェクトから使うためにnpmに公開してみます。他のパッケージと名前がぶつからないように、名前空間を付与します。usernameはnpmjsに登録されているusernameを使用します。
{ "name": "@username/aws-cdk-lib-sample", "version": "0.1.0", ... ... ... }
プロジェクト直下で以下のコマンドを実行するだけです。これで、@username/aws-cdk-lib-sample
パッケージとしてnpmに公開されます。
$ npm run build $ npm publish --access=public + aws-cdk-lib-sample@0.1.0
他のCDKプロジェクトから参照する
npmに公開したので、他のCDKプロジェクトでnpm install
してスタックを作成してみます。先ほどと同じように、CDKプロジェクトを作成します。こちらはCDKのAppを作成するため、cdk init app
の方を使います。
$ cdk init app --language=typescript
その後、先ほどnpmに公開したパッケージをインストールします。
$ npm install @username/aws-cdk-lib-sample
コードを修正します。以下のサンプルコードでは、先ほどnpmに公開した独自のConstruct Libraryをrequireして使用しています。
import cdk = require('@aws-cdk/core'); import sample = require('@username/aws-cdk-lib-sample') // 先ほどの独自パッケージをrequire export class AwsCdkSampleStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const sampleConstruct = new sample.AwsCdkLibSample(this, "SampleConstruct", { visibilityTimeout: cdk.Duration.seconds(10) }); // インスタンス変数から、SQSのARNを取得できる // sampleConstruct.queueArn } }
デプロイ
AWSへデプロイします。
$ cdk deploy
This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening). Please confirm you intend to make the following modifications: IAM Statement Changes ┌───┬─────────────────────────────────────────────┬────────┬─────────────────┬───────────────────────────┬─────────────────────────────────────────────────────────────────────────────┐ │ │ Resource │ Effect │ Action │ Principal │ Condition │ ├───┼─────────────────────────────────────────────┼────────┼─────────────────┼───────────────────────────┼─────────────────────────────────────────────────────────────────────────────┤ │ + │ ${SampleConstruct/AwsCdkLibSampleQueue.Arn} │ Allow │ sqs:SendMessage │ Service:sns.amazonaws.com │ "ArnEquals": { │ │ │ │ │ │ │ "aws:SourceArn": "${SampleConstruct/AwsCdkLibSampleTopic}" │ │ │ │ │ │ │ } │ └───┴─────────────────────────────────────────────┴────────┴─────────────────┴───────────────────────────┴─────────────────────────────────────────────────────────────────────────────┘ (NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299) Do you wish to deploy these changes (y/n)? y AwsCdkRequireLibrarySampleStack: deploying... AwsCdkRequireLibrarySampleStack: creating CloudFormation changeset... 0/6 | 7:10:48 PM | CREATE_IN_PROGRESS | AWS::SQS::Queue | SampleConstruct/AwsCdkLibSampleQueue (SampleConstructAwsCdkLibSampleQueue6C642B46) 0/6 | 7:10:48 PM | CREATE_IN_PROGRESS | AWS::SNS::Topic | SampleConstruct/AwsCdkLibSampleTopic (SampleConstructAwsCdkLibSampleTopicEE2D292F) 0/6 | 7:10:48 PM | CREATE_IN_PROGRESS | AWS::CDK::Metadata | CDKMetadata 0/6 | 7:10:48 PM | CREATE_IN_PROGRESS | AWS::SQS::Queue | SampleConstruct/AwsCdkLibSampleQueue (SampleConstructAwsCdkLibSampleQueue6C642B46) Resource creation Initiated 0/6 | 7:10:49 PM | CREATE_IN_PROGRESS | AWS::SNS::Topic | SampleConstruct/AwsCdkLibSampleTopic (SampleConstructAwsCdkLibSampleTopicEE2D292F) Resource creation Initiated 1/6 | 7:10:49 PM | CREATE_COMPLETE | AWS::SQS::Queue | SampleConstruct/AwsCdkLibSampleQueue (SampleConstructAwsCdkLibSampleQueue6C642B46) 1/6 | 7:10:50 PM | CREATE_IN_PROGRESS | AWS::CDK::Metadata | CDKMetadata Resource creation Initiated 2/6 | 7:10:50 PM | CREATE_COMPLETE | AWS::CDK::Metadata | CDKMetadata 3/6 | 7:10:59 PM | CREATE_COMPLETE | AWS::SNS::Topic | SampleConstruct/AwsCdkLibSampleTopic (SampleConstructAwsCdkLibSampleTopicEE2D292F) 3/6 | 7:11:01 PM | CREATE_IN_PROGRESS | AWS::SQS::QueuePolicy | SampleConstruct/AwsCdkLibSampleQueue/Policy (SampleConstructAwsCdkLibSampleQueuePolicyB26F01DD) 3/6 | 7:11:01 PM | CREATE_IN_PROGRESS | AWS::SNS::Subscription | SampleConstruct/AwsCdkLibSampleQueue/AwsCdkRequireLibrarySampleStackSampleConstructAwsCdkLibSampleTopic4BACA155 (SampleConstructAwsCdkLibSampleQueueAwsCdkRequireLibrarySampleStackSampleConstructAwsCdkLibSampleTopic4BACA15518B88C48) 3/6 | 7:11:01 PM | CREATE_IN_PROGRESS | AWS::SQS::QueuePolicy | SampleConstruct/AwsCdkLibSampleQueue/Policy (SampleConstructAwsCdkLibSampleQueuePolicyB26F01DD) Resource creation Initiated 4/6 | 7:11:01 PM | CREATE_COMPLETE | AWS::SQS::QueuePolicy | SampleConstruct/AwsCdkLibSampleQueue/Policy (SampleConstructAwsCdkLibSampleQueuePolicyB26F01DD) 4/6 | 7:11:02 PM | CREATE_IN_PROGRESS | AWS::SNS::Subscription | SampleConstruct/AwsCdkLibSampleQueue/AwsCdkRequireLibrarySampleStackSampleConstructAwsCdkLibSampleTopic4BACA155 (SampleConstructAwsCdkLibSampleQueueAwsCdkRequireLibrarySampleStackSampleConstructAwsCdkLibSampleTopic4BACA15518B88C48) Resource creation Initiated 5/6 | 7:11:02 PM | CREATE_COMPLETE | AWS::SNS::Subscription | SampleConstruct/AwsCdkLibSampleQueue/AwsCdkRequireLibrarySampleStackSampleConstructAwsCdkLibSampleTopic4BACA155 (SampleConstructAwsCdkLibSampleQueueAwsCdkRequireLibrarySampleStackSampleConstructAwsCdkLibSampleTopic4BACA15518B88C48) 6/6 | 7:11:03 PM | CREATE_COMPLETE | AWS::CloudFormation::Stack | AwsCdkRequireLibrarySampleStack ✅ AwsCdkRequireLibrarySampleStack
独自ライブラリで定義した、SQS
、SNS
が作成されています。
クリーンアップ
デプロイしたAWSリソースと、npmjsのパッケージを削除します。
$ npm unpublish @username/aws-cdk-lib-sample --force $ cdk destroy
まとめ
CDKで独自のライブラリを使う方法でした。CDKにおけるスタックの粒度やConstruct Libraryの上手な使い方などはまだまだ模索中の段階です。これからどんどん実案件などで使って知見をためていけたらなと思っています。