これは v2 AWS CDK デベロッパーガイドです。旧版の CDK v1 は 2022 年 6 月 1 日にメンテナンスを開始し、2023 年 6 月 1 日にサポートを終了しました。
翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
では AWS Cloud Development Kit (AWS CDK)、トークンは、コンストラクトの定義時またはスタックの合成時にわからない値のプレースホルダーです。実際のインフラストラクチャが作成されると、これらの値はデプロイ時に完全に解決されます。 AWS CDK アプリケーションを開発するときは、トークンを使用してアプリケーション全体でこれらの値を管理します。
トークンの例
次の内容は、Amazon Simple Storage Service (Amazon S3) バケットのコンストラクトを定義する CDK スタックの例です。バケットの名前はまだ不明なため、bucketName
の値はトークンとして保存されます。
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';
export class CdkDemoAppStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Define an S3 bucket
const myBucket = new s3.Bucket(this, 'myBucket');
// Store value of the S3 bucket name
const myBucketName = myBucket.bucketName;
// Print the current value for the S3 bucket name at synthesis
console.log("myBucketName: " + bucketName);
}
}
スタックを合成するために cdk synth
を実行するとき、myBucketName
の値は ${Token[TOKEN.
のトークン形式で表示されます。このトークン形式は、 AWS CDK がトークンをエンコードする方法の結果です。この例では、トークンは文字列としてエンコードされます。1234
]}
$
cdk synth --quiet
myBucketName: ${Token[TOKEN.21
]}
バケット名の値は合成時にわからないため、トークンは myBucket
としてレンダリングされます。 AWS CloudFormation テンプレートは、 <unique-hash>
Ref
組み込み関数を使用してその値を参照します。これはデプロイ時に認識されます。
Resources:
myBucket5AF9C99B
:
# ...
Outputs:
bucketNameOutput:
Description: The name of the S3 bucket
Value:
Ref: myBucket5AF9C99B
一意のハッシュの生成方法の詳細については、「AWS CloudFormation テンプレートで生成された論理 IDs 」を参照してください。
トークンを渡す
トークンが表す実際の値であるかのように、渡すことができます。以下は、バケット名のトークンを AWS Lambda 関数のコンストラクトに渡す例です。
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as lambda from 'aws-cdk-lib/aws-lambda';
export class CdkDemoAppStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Define an S3 bucket
const myBucket = new s3.Bucket(this, 'myBucket');
// ...
// Define a Lambda function
const myFunction = new lambda.Function(this, "myFunction", {
runtime: lambda.Runtime.NODEJS_20_X,
handler: "index.handler",
code: lambda.Code.fromInline(`
exports.handler = async function(event) {
return {
statusCode: 200,
body: JSON.stringify('Hello World!'),
};
};
`),
functionName: myBucketName + "Function", // Pass token for the S3 bucket name
environment: {
BUCKET_NAME: myBucketName, // Pass token for the S3 bucket name
}
});
}
}
テンプレートを合成するときに Ref
および Fn::Join
の組み込み関数を使用して値を指定し、デプロイ時に判明されます。
Resources:
myBucket5AF9C99B
:
Type: AWS::S3::Bucket
# ...
myFunction884E1557
:
Type: AWS::Lambda::Function
Properties:
# ...
Environment:
Variables:
BUCKET_NAME:
Ref: myBucket5AF9C99B
FunctionName:
Fn::Join:
- ""
- - Ref: myBucket5AF9C99B
- Function
# ...
トークンエンコーディングの仕組み
トークンは、IResolvable
インターフェイスを実装するオブジェクトであり、1 つの resolve
メソッドが含まれています。合成中、 はこのメソッドを AWS CDK 呼び出して CloudFormation テンプレート内のトークンの最終値を生成します。
注記
IResolvable
インターフェイスを直接操作することはめったにありません。ほとんどの場合、トークンの文字列エンコードされたバージョンのみが表示されます。
トークンエンコードのタイプ
トークンは合成プロセスに関与し、すべてのタイプにおける任意の値を生成します。通常、他の関数は string
や number
などの基本的なタイプの引数のみを受け入れます。このような場合にトークンを使用するには、cdk.Token
クラスの静的メソッドを使用して 3 つのタイプのいずれかにトークンをエンコードできます。
-
Token.asString
で文字列エンコーディング (またはトークンオブジェクトで.toString()
を呼び出す) を生成します。 -
Token.asList
でリストエンコーディングを生成します。 -
Token.asNumber
で数値エンコーディングを生成します。
IResolvable
の可能性がある任意の値を取得し、指定されたタイプのプリミティブ値にエンコードします。
重要
前のタイプのいずれかがエンコードされたトークンである可能性があるため、内容を解析または読み取ろうとするときは注意してください。例えば、文字列を解析してそこから値を抽出しようとし、文字列がエンコードされたトークンである場合、解析は失敗します。同様に、配列の長さをクエリしたり、数値で数学演算を実行したりした場合は、最初にエンコードされたトークンではないことを確認する必要があります。
アプリでトークンを確認する方法
値に未解決のトークンが含まれているかどうかを確認するには、Token.isUnresolved
(Python: is_unresolved
) メソッドを呼び出します。次の内容は、Amazon S3 バケット名の値がトークンであるかどうかをチェックする例です。トークンではない場合、バケット名の長さを検証します。
// ...
export class CdkDemoAppStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Define an S3 bucket
const myBucket = new s3.Bucket(this, 'myBucket');
// ...
// Check if bucket name is a token. If not, check if length is less than 10 characters
if (cdk.Token.isUnresolved(myBucketName)) {
console.log("Token identified.");
} else if (!cdk.Token.isUnresolved(myBucketName) && myBucketName.length > 10) {
throw new Error('Maximum length for name is 10 characters.');
};
// ...
cdk synth
を実行するとき、myBucketName
はトークンとして識別されます。
$
cdk synth --quiet
Token identified.
注記
トークンエンコーディングを使用し、タイプシステムからエスケープできます。例えば、合成時に数値を生成するトークンを文字列エンコードできます。これらの関数を使用する場合、合成後にテンプレートが使用可能な状態に解決されていることを確認するのがユーザーの責任です。
文字列エンコードされたトークンの使用
文字列エンコードされたトークンは次のようになります。
${TOKEN[Bucket.Name.1234]}
次の例で示すように、通常の文字列のように渡して連結できます。
const functionName = bucket.bucketName + 'Function';
次の例で示すように、言語が文字列補間をサポートしている場合、文字列補間も使用できます。
const functionName = `${bucket.bucketName}Function`;
他の方法で文字列を操作しないでください。例えば、文字列の部分文字列を取ると、文字列トークンが壊れる可能性があります。
リストエンコードされたトークンの使用
リストエンコードされたトークンは次のようになります。
["#{TOKEN[Stack.NotificationArns.1234]}"]
これらのリストにする唯一の安全なことは、他のコンストラクトに直接渡すことです。文字列リスト形式のトークンは連結することも、トークンから要素を取得することもできません。安全に操作する唯一の方法は、Fn.select などの AWS CloudFormation 組み込み関数を使用することです。
番号エンコードされたトークンの使用
数値エンコードされたトークンは、次のような小さな負の浮動小数点数のセットです。
-1.8881545897087626e+289
リストトークンと同様に、数値トークンが壊れる可能性があるため、数値は変更できません。
次の内容は、数値としてエンコードされたトークンを含むコンストラクトの例です。
import { Stack, Duration, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as rds from 'aws-cdk-lib/aws-rds';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
export class CdkDemoAppStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// Define a new VPC
const vpc = new ec2.Vpc(this, 'MyVpc', {
maxAzs: 3, // Maximum number of availability zones to use
});
// Define an RDS database cluster
const dbCluster = new rds.DatabaseCluster(this, 'MyRDSCluster', {
engine: rds.DatabaseClusterEngine.AURORA,
instanceProps: {
vpc,
},
});
// Get the port token (this is a token encoded as a number)
const portToken = dbCluster.clusterEndpoint.port;
// Print the value for our token at synthesis
console.log("portToken: " + portToken);
}
}
cdk synth
を実行するとき、portToken
の値が数値エンコードされたトークンとして表示されます。
$
cdk synth --quiet
portToken: -1.8881545897087968e+289
数値エンコードされたトークンを渡す
数値エンコードされたトークンを他のコンストラクトに渡すとき、最初に文字列に変換するのが理にかなっている場合があります。例えば、数値エンコードされた文字列の値を連結文字列の一部として使用する場合、変換すると読みやすくなります。
次の例では、portToken
は connectionString
の一部として Lambda 関数に渡す数値エンコードされたトークンです。
import { Stack, Duration, CfnOutput, StackProps } from 'aws-cdk-lib';
// ...
import * as lambda from 'aws-cdk-lib/aws-lambda';
export class CdkDemoAppStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// Define a new VPC
// ...
// Define an RDS database cluster
// ...
// Get the port token (this is a token encoded as a number)
const portToken = dbCluster.clusterEndpoint.port;
// ...
// Example connection string with the port token as a number
const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portToken}/mydatabase`;
// Use the connection string as an environment variable in a Lambda function
const myFunction = new lambda.Function(this, 'MyLambdaFunction', {
runtime: lambda.Runtime.NODEJS_20_X,
handler: 'index.handler',
code: lambda.Code.fromInline(`
exports.handler = async function(event) {
return {
statusCode: 200,
body: JSON.stringify('Hello World!'),
};
};
`),
environment: {
DATABASE_CONNECTION_STRING: connectionString, // Using the port token as part of the string
},
});
// Output the value of our connection string at synthesis
console.log("connectionString: " + connectionString);
// Output the connection string
new CfnOutput(this, 'ConnectionString', {
value: connectionString,
});
}
}
この値を connectionString
に渡す場合、数値エンコードされた文字列により、cdk synth
の実行時の出力値が混乱を招く場合があります。
$
cdk synth --quiet
connectionString: jdbc:mysql://mydb.cluster.amazonaws.com:-1.888154589708796e+289/mydatabase
数値エンコードされたトークンを文字列に変換するには、cdk.Tokenization.stringifyNumber(
を使用します。次の例では、接続文字列を定義する前に、数値エンコードされたトークンを文字列に変換します。token
)
import { Stack, Duration, Tokenization, CfnOutput, StackProps } from 'aws-cdk-lib';
// ...
export class CdkDemoAppStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// Define a new VPC
// ...
// Define an RDS database cluster
// ...
// Get the port token (this is a token encoded as a number)
const portToken = dbCluster.clusterEndpoint.port;
// ...
// Convert the encoded number to an encoded string for use in the connection string
const portAsString = Tokenization.stringifyNumber(portToken);
// Example connection string with the port token as a string
const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portAsString}/mydatabase`;
// Use the connection string as an environment variable in a Lambda function
const myFunction = new lambda.Function(this, 'MyLambdaFunction', {
// ...
environment: {
DATABASE_CONNECTION_STRING: connectionString, // Using the port token as part of the string
},
});
// Output the value of our connection string at synthesis
console.log("connectionString: " + connectionString);
// Output the connection string
new CfnOutput(this, 'ConnectionString', {
value: connectionString,
});
}
}
cdk synth
を実行するとき、接続文字列の値はより簡潔で明確な形式で表されます。
$
cdk synth --quiet
connectionString: jdbc:mysql://mydb.cluster.amazonaws.com:${Token[TOKEN.242]}/mydatabase
遅延値
AWS CloudFormation パラメータなどのデプロイ時の値を表すだけでなく、トークンは合成時の遅延値を表すためにもよく使用されます。合成が完了する前に最終値が決定される値ですが、値が構築された時点では決定されません。トークンを使用してリテラル文字列または数値を別のコンストラクトに渡しますが、合成時の実際の値はまだ発生していない計算に依存する場合があります。
Lazy.string
や Lazy.number
などの Lazy
クラスの静的メソッドを使用して、合成時間の遅延値を表すトークンを構成できます。これらのメソッドは、produce
プロパティがコンテキスト引数を受け入れる関数であるオブジェクトを受け入れ、呼び出されたときに最終値を返します。
次の例では Auto Scaling グループを作成し、作成後に容量が決定されます。
let actualValue: number;
new AutoScalingGroup(this, 'Group', {
desiredCapacity: Lazy.numberValue({
produce(context) {
return actualValue;
}
})
});
// At some later point
actualValue = 10;
JSON への変換
任意のデータの JSON 文字列を生成し、データにトークンが含まれているかどうかわからない場合があります。次の例で示すように、トークンが含まれているかどうかを問わず、データ構造を適切に JSON エンコードするには、stack.toJsonString
メソッドを使用します。
const stack = Stack.of(this);
const str = stack.toJsonString({
value: bucket.bucketName
});