
AWS CDK で aws_s3_deployment モジュールを使うとローカルにある ZIP ファイル・ディレクトリなどを Amazon S3 にアップロードできる❗️使いどころとしては,静的ファイル・設定ファイル・データセットなどのアップロードも AWS CDK のワークフローに含めて IaC 化したいときなどにハマると思う💡さっそく試す \( 'ω')/
1. ZIP ファイルをアップロードする
まずはローカルにある ZIP ファイルを Amazon S3 にアップロードする.ZIP ファイルはサンプルとして MySQL のサンプルデータセット「sakila database」の sakila-db.zip を使う.AWS CDK の実装としては
aws_s3_deployment.BucketDeployment の sources に ZIP ファイルを指定して destinationBucket に Amazon S3 バケットを指定するだけ👌 簡単〜
import { Stack, StackProps, aws_s3, aws_s3_deployment, } from 'aws-cdk-lib'; import { Construct } from 'constructs'; export class SandboxCdkS3DeploymentStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); const bucket = new aws_s3.Bucket(this, 'SandboxCdkS3DeploymentBucket', { bucketName: 'sandbox-cdk-s3-deployment-bucket', }); new aws_s3_deployment.BucketDeployment(this, 'SandboxCdkS3Deployment', { sources: [aws_s3_deployment.Source.asset('./datasets/sakila-db.zip')], destinationBucket: bucket, }); } }
cdk deploy コマンドを実行すると,ZIP ファイルが自動的に展開されてアップロードされていた❗️

2. ZIP ファイルのままアップロードする
デフォルトでは ZIP ファイルは展開されるけど extract: false オプションを付けると ZIP のままアップロードできる.しかしファイル名が異なる点には注意する👀
import { Stack, StackProps, aws_s3, aws_s3_deployment, } from 'aws-cdk-lib'; import { Construct } from 'constructs'; export class SandboxCdkS3DeploymentStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); const bucket = new aws_s3.Bucket(this, 'SandboxCdkS3DeploymentBucket', { bucketName: 'sandbox-cdk-s3-deployment-bucket', }); new aws_s3_deployment.BucketDeployment(this, 'SandboxCdkS3Deployment', { sources: [aws_s3_deployment.Source.asset('./datasets/sakila-db.zip')], destinationBucket: bucket, extract: false, }); } }
cdk deploy コマンドを実行すると,e64c076b781d54f6210a9d9f8bfb08e40e8176ecf6f7542a5465d7b9be376574.zip という名前で ZIP ファイルのままアップロードされていた❗️

3. ディレクトリをアップロードする
ZIP ファイルではなくローカルにあるディレクトリをアップロードすることもできる.使いどころを考えると一番使うのはディレクトリのアップロードかもしれない.さらに include / exclude でフィルタもあって,不要なファイルをアップロードしないように制御できるのは助かる👌
import { Stack, StackProps, aws_s3, aws_s3_deployment, } from 'aws-cdk-lib'; import { Construct } from 'constructs'; export class SandboxCdkS3DeploymentStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); const bucket = new aws_s3.Bucket(this, 'SandboxCdkS3DeploymentBucket', { bucketName: 'sandbox-cdk-s3-deployment-bucket', }); new aws_s3_deployment.BucketDeployment(this, 'SandboxCdkS3Deployment', { sources: [aws_s3_deployment.Source.asset('./bin', { exclude: ['*.js'] })], destinationBucket: bucket, }); } }
単純に除外するなら sources に指定する AssetOptions に exclude を指定すればアップロード対象をまとめるときに除外できる.また BucketDeployment 自体に include と exclude を指定することもできて,Amazon S3 へのアップロード前に考慮される.ちなみに include と exclude の構文に関しては AWS CLI の aws s3 sync コマンドと同じ💡
今回はサンプルとして AWS CDK プロジェクトの bin ディレクトリの3ファイルを対象にしつつ *.js を除外する.
$ tree bin bin ├── sandbox-cdk-aws.d.ts ├── sandbox-cdk-aws.js └── sandbox-cdk-aws.ts
cdk deploy コマンドを実行すると,sandbox-cdk-aws.d.ts と sandbox-cdk-aws.ts のみアップロードされていた❗️

仕組み
ドキュメントにも書いてあるけど,aws_s3_deployment モジュールは内部的に AWS Lambda 関数を作って,AWS Lambda 関数の中から AWS CLI の aws s3 sync コマンドを実行して Amazon S3 にファイルをアップロードしている.AWS Lambda 関数のコード index.py は以下にある.
よって,AWS CloudFormation のリソース一覧を見るとカスタムリソース Custom::CDKBucketDeployment の中に AWS Lambda 関数が含まれていて,実際に以下のような AWS Lambda 関数が作られていた.あくまで個人的にだけどカスタムリソースなどによって勝手にリソースが作られることに少し抵抗はあって,今回だと Amazon S3 にファイルをアップロードするために AWS Lambda 関数が作られるのか〜という気持ちになったりはする💨
