こんにちは、CX事業本部 IoT事業部の若槻です。
AWS CDKでは、CloudFromation Resourceの実装を直接表現したLow Level Construct(L1 Construct)と、実装のインターフェース(プロパティ)が抽象化されたHigh Level Construct(L2 Construct)があります。
全ての種類のAWS Resourceに対してL2 Constructが提供されているわけではありませんが、一般的にはL2 Constructを使った方がより少ないコードの記述で実装が可能となります。(今回は触れませんが、さらに上位のL3 Constructなんてのもあります。)
しかしこのL2 Constructは抽象化されているゆえに、L1で設定可能なプロパティがL2では設定できないパターンがあります。
今回は、AWS CDK(TypeScript)のL2 Constructで設定できないプロパティを設定する方法を確認してみました。
確認してみた
次のAWS CDK(TypeScript)の実装があります。
lib/aws-app-stack.ts
import { Construct } from 'constructs';
import {
aws_s3,
aws_glue,
Stack,
StackProps,
RemovalPolicy,
} from 'aws-cdk-lib';
import * as glue_alpha from '@aws-cdk/aws-glue-alpha';
export class AwsAppStack extends Stack {
constructor(scope: Construct, id: string, props: StackProps) {
super(scope, id, props);
// データ格納バケット
const dataBucket = new aws_s3.Bucket(this, 'dataBucket', {
bucketName: `data-${this.account}-${this.region}`,
removalPolicy: RemovalPolicy.DESTROY,
});
// データカタログ
const dataCatalog = new glue_alpha.Database(this, 'dataCatalog', {
databaseName: 'data_catalog',
});
// データカタログテーブル
const dataGlueTable = new glue_alpha.Table(this, 'dataGlueTable', {
tableName: 'data_glue_table',
database: dataCatalog,
bucket: dataBucket,
s3Prefix: 'data/',
partitionKeys: [
{
name: 'device_id',
type: glue_alpha.Schema.STRING,
},
],
dataFormat: glue_alpha.DataFormat.JSON,
columns: [
{
name: 'userId',
type: glue_alpha.Schema.STRING,
},
{
name: 'count',
type: glue_alpha.Schema.FLOAT,
},
],
});
}
}
AWS GlueのTableを@aws-cdk/aws-glue-alphaのL2 Constructで実装しています。このConstructに対してPartition Projectionの設定をしたいのですが、このL2 Constructではそのためのプロパティへはアクセスできません。
そこで、次の2つの方法により設定を行ってみます。
方法その1:addPropertyOverrideで設定
まず、addPropertyOverride
を使う方法です。大まかに言うと、L2で実装したConstructのL1 Constructを取得し、設定したいプロパティをオーバーライドしています。
lib/aws-app-stack.ts
// データカタログテーブルへのPartition Projectionの設定
const cfnTable = dataGlueTable.node.defaultChild as aws_glue.CfnTable;
cfnTable.addPropertyOverride('TableInput.Parameters', {
'projection.enabled': true,
'projection.device_id.type': 'injected',
'storage.location.template':
`s3://${dataBucket.bucketName}/data/` + '${device_id}',
});
詳細を説明します。
始めにdataGlueTable.node.defaultChild
によりL2 ConstructのdataGlueTable
からDefault ChildとなるNodeを取得しています。L2 Constructでは複数のConstruct nodeが作成される場合があるため、デフォルトの子要素(ここではGlue Table)がこれにより取得できます。
そして取得したConstruct nodeをas aws_glue.CfnTable
と型アサーションし、L1 Constructとして扱えるようにしています。これによりこのConstructでaddPropertyOverride
メソッドが利用可能となります。
addPropertyOverride
は、すべてのL1 Constructのクラスで利用可能なクラスです。設定したいプロパティのパスと値を引数として指定します。
public addPropertyOverride(propertyPath: string, value: any): void
方法その2:直接設定
次に直接Parameterを設定する方法です。
lib/aws-app-stack.ts
// データカタログテーブルへのPartition Projectionの設定
(dataGlueTable.node.defaultChild as any).tableInput.parameters = {
'projection.enabled': true,
'projection.device_id.type': 'injected',
'storage.location.template':
`s3://${dataBucket.bucketName}/data/` + '${device_id}',
};
dataGlueTable.node.defaultChild
によりL2 Constructのデフォルトの子要素のConstruct nodeを取得するところまでは方法1と同じです。異なるのは、取得したConstruct nodeに対してnode.<parameter path> = <value>
のように設定したいプロパティのパスと値を引数として直接指定しているところです。これにより方法1のaddPropertyOverride
によるものと同様の設定が可能です。
しかしany
による型付けをしているため、ESLintなどを使用している環境ではビルドエラーになる場合があるので注意が必要です。特段の理由がなければaddPropertyOverride
を使う方法1で良いかと思います。
参考
- AWS CDK の3種類の Construct を使ってデプロイしてみた | DevelopersIO
- Constructs - AWS Cloud Development Kit (AWS CDK) v2
以上