こんにちは、CX事業本部 Delivery部の若槻です。
AWS CDK v2.85.0 で、ファイルの内容を置換しつつ Amazon S3 バケットにアップロードできるコンストラクトクラス DeployTimeSubstitutedFile
が利用可能になりました。
Features
- s3-deployment: create
DeployTimeSubstitutedFile
to allow substitutions in file (#25876) (ca2e6a2), closes #1461
DeployTimeSubstitutedFile
の仕様
ドキュメントで DeployTimeSubstitutedFile
コンストラクトクラスの仕様を確認してみます。
Construct Props は次のようになります。
Name | Type | Description |
---|---|---|
destinationBucket | IBucket | The S3 bucket to sync the contents of the zip file to. |
source | string | Path to the user's local file. |
substitutions | { [string]: string } | User-defined substitutions to make in the file. |
source
のパスにあるローカルファイルの内容を substitutions
に従って置換し、destinationBucket
にアップロードします。
Properties は次のようになります。
Name | Type | Description |
---|---|---|
bucket | IBucket | |
deployedBucket | IBucket | The bucket after the deployment. |
node | Node | The tree node. |
objectKey | string | |
objectKeys | string[] | The object keys for the sources deployed to the S3 bucket. |
試してみた
CDK コード
DeployTimeSubstitutedFile
を使用した CDK スタックのコードです。my-file.json
ファイル内の xxxx
および yyyy
というプレースホルダーを置換するようにしています。
lib/cdk-sample-stack.ts
import {
aws_s3_deployment as s3deploy,
aws_s3 as s3,
Stack,
StackProps,
} from 'aws-cdk-lib';
import { Construct } from 'constructs';
export class CdkSampleStack extends Stack {
public readonly myFileObjectKey: string;
constructor(scope: Construct, id: string, props: StackProps) {
super(scope, id, props);
// アップロード先バケット
const destinationBucket = new s3.Bucket(this, 'MyBucket', {
bucketName: `my-bucket-${this.account}-${this.region}`,
});
// `DeployTimeSubstitutedFile` によるファイルの置換およびアップロード
const myFile = new s3deploy.DeployTimeSubstitutedFile(this, 'MyFile', {
source: 'my-file.json',
destinationBucket: destinationBucket,
substitutions: {
xxxx: 'mySubstitution1',
yyyy: 'mySubstitution2',
},
});
// アップロードされたファイルのオブジェクトキー取得確認
this.myFileObjectKey = myFile.objectKey;
this.exportValue(myFile.objectKey, { name: 'MyFileObjectKey' });
}
}
置換およびアップロード対象のファイルです。プレースホルダーは {{ xxxx }}
のように指定します。
my-file.json
{
"description": "This is a sample file",
"parameter1": "{{ xxxx }}",
"parameter2": "{{ yyyy }}"
}
cdk deploy
でスタックをデプロイします。
デプロイ後に S3 バケットの中身を確認すると、オブジェクトがアップロードされています。パスは S3 バケットのルート、オブジェクト名はランダムな文字列となるようです。ローカルでのファイル名とはならないんですね。
$ aws s3 ls s3://${bucketname}
2023-06-29 03:01:50 115 b70caacf3a36a7bd6b9315a9deabbc9ae27a11b6812257017f1a89e76b4a7ca4
作成されたオブジェクトの内容を確認すると、ちゃんと置換が行われていますね。
$ aws s3 cp s3://${bucketname} ./tmp --recursive
$ cat ./tmp/b70caacf3a36a7bd6b9315a9deabbc9ae27a11b6812257017f1a89e76b4a7ca4
{
"description": "This is a sample file",
"parameter1": "mySubstitution1",
"parameter2": "mySubstitution2"
}
アップロード対象のファイルを変更してみる
DeployTimeSubstitutedFile
の source
の指定を変更して、アップロード対象のファイルを変更した時の挙動を確認してみます。
lib/cdk-sample-stack.ts
// `DeployTimeSubstitutedFile` によるファイルの置換およびアップロード
const myFile = new s3deploy.DeployTimeSubstitutedFile(this, 'MyFile', {
- source: 'my-file.json',
+ source: 'my-file.yaml',
destinationBucket: destinationBucket,
substitutions: {
xxxx: 'mySubstitution1',
yyyy: 'mySubstitution2',
},
});
変更後のアップロード対象ファイルです。
my-file.yaml
version: 1.0.0
metadata:
name: my-file
description: This is a sample file
parameter1: {{ xxxx }}
parameter2: {{ yyyy }}
cdk deploy
コマンドでスタックをデプロイします。
デプロイ完了後に S3 バケットの中身を確認すると、変更前と変更後のオブジェクトが S3 バケットに併存していますね。変更前のオブジェクトは削除され、変更後のオブジェクトが追加されるという冪等性のある挙動を期待していましたが、そうではないようです。
$ aws s3 ls s3://${bucketname}
2023-06-29 03:20:40 138 583d9aa21a5e56757e5e91c0065b4ad9a24879cb30b6c58354bce7bfd4ec56ce
2023-06-29 03:01:50 115 b70caacf3a36a7bd6b9315a9deabbc9ae27a11b6812257017f1a89e76b4a7ca4
変更後のファイルの内容を確認すると、ちゃんと置換は行われています。
$ aws s3 cp s3://${bucketname} ./tmp --recursive
$ cat ./tmp/583d9aa21a5e56757e5e91c0065b4ad9a24879cb30b6c58354bce7bfd4ec56ce
version: 1.0.0
metadata:
name: my-file
description: This is a sample file
parameter1: mySubstitution1
parameter2: mySubstitution2
DeployTimeSubstitutedFile
コンストラクトを削除してみる
作成した DeployTimeSubstitutedFile
コンストラクトを削除した時の挙動も確認してみます。
lib/cdk-sample-stack.ts
export class CdkSampleStack extends Stack {
public readonly myFileObjectKey: string;
constructor(scope: Construct, id: string, props: StackProps) {
super(scope, id, props);
// アップロード先バケット
const destinationBucket = new s3.Bucket(this, 'MyBucket', {
bucketName: `my-bucket-${this.account}-${this.region}`,
});
// // `DeployTimeSubstitutedFile` によるファイルの置換およびアップロード
// const myFile = new s3deploy.DeployTimeSubstitutedFile(this, 'MyFile', {
// source: 'my-file.yaml',
// destinationBucket: destinationBucket,
// substitutions: {
// xxxx: 'mySubstitution1',
// yyyy: 'mySubstitution2',
// },
// });
// // アップロードされたファイルのオブジェクトキー確認
// this.myFileObjectKey = myFile.objectKey;
// this.exportValue(myFile.objectKey, { name: 'MyFileObjectKey' });
}
}
cdk deploy
コマンドでスタックをデプロイします。
デプロイ完了後に S3 バケットの中身を確認すると、既存のファイルは削除されずに残っています。やはり作りっぱなしになるようですね。
aws s3 ls s3://${bucketname}
2023-06-29 03:20:40 138 583d9aa21a5e56757e5e91c0065b4ad9a24879cb30b6c58354bce7bfd4ec56ce
2023-06-29 03:01:50 115 b70caacf3a36a7bd6b9315a9deabbc9ae27a11b6812257017f1a89e76b4a7ca4
注意点
DeployTimeSubstitutedFile
を試した結果、次のような点に注意する必要がありました。
- アップロードされるオブジェクトキー(ディレクトリやオブジェクト名)の指定は出来ない
- ファイルの変更やコンストラクト削除した場合でも、既存のオブジェクトは削除されない(冪等性がない)
所感
はじめは CDK でデプロイを管理しているフロントエンドアプリの構成ファイルをデプロイ先の環境ごとに動的に作成するというユースケースで便利になると思いましたが、上記の注意点のような制約があるため今のところは難しそうです。
しかしオブジェクトキーが指定可能となったりデプロイ毎の冪等性の担保されるようになれば、かなり便利なクラスに化けると思います。もしくはこの置換機能が BucketDeployment コンストラクトクラス自体に実装されると嬉しいかも知れません。
以上