令牌和 AWS CDK - AWS Cloud Development Kit (AWS CDK) V2

這是 AWS CDK v2 開發人員指南。較舊的 CDK V1 已於 2022 年 6 月 1 日進入維護,並於 2023 年 6 月 1 日結束支援。

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

令牌和 AWS CDK

令牌表示只能在應用程序生命週期中稍後解析的值。例如,您在CDK應用程式中定義的 Amazon 簡易儲存服務 (Amazon S3) 儲存貯體的名稱只會在合成 AWS CloudFormation 範本時分配。如果你打印bucket.bucketName屬性,這是一個字符串,你會看到它包含如下內容:

${TOKEN[Bucket.Name.1234]}

這就是 AWS CDK 編碼令牌的方式,其值在施工時尚未知道,但稍後將可用。 AWS CDK 調用這些佔位符令牌。在這種情況下,它是編碼為字符串的令牌。

您可以傳遞此字符串,就好像它是存儲桶的名稱一樣。在下列範例中,值區名稱會指定為 AWS Lambda 函數的環境變數。

TypeScript
const bucket = new s3.Bucket(this, 'MyBucket'); const fn = new lambda.Function(stack, 'MyLambda', { // ... environment: { BUCKET_NAME: bucket.bucketName, } });
JavaScript
const bucket = new s3.Bucket(this, 'MyBucket'); const fn = new lambda.Function(stack, 'MyLambda', { // ... environment: { BUCKET_NAME: bucket.bucketName } });
Python
bucket = s3.Bucket(self, "MyBucket") fn = lambda_.Function(stack, "MyLambda", environment=dict(BUCKET_NAME=bucket.bucket_name))
Java
final Bucket bucket = new Bucket(this, "MyBucket"); Function fn = Function.Builder.create(this, "MyLambda") .environment(java.util.Map.of( // Map.of requires Java 9+ "BUCKET_NAME", bucket.getBucketName())) .build();
C#
var bucket = new s3.Bucket(this, "MyBucket"); var fn = new Function(this, "MyLambda", new FunctionProps { Environment = new Dictionary<string, string> { ["BUCKET_NAME"] = bucket.BucketName } });

當 AWS CloudFormation 模板最終合成時,令牌被渲染為 AWS CloudFormation 內{ "Ref": "MyBucket" }在。在部署階段, AWS CloudFormation 會以建立的值區的實際名稱取代此內建項目。

令牌和令牌編碼

令牌是實現IResolvable接口的對象,其中包含一個單一的resolve方法。在合成過程中 AWS CDK 調用此方法以產生 AWS CloudFormation 模板的最終值。令牌參與合成過程以產生任何類型的任意值。

注意

您很少會直接使用IResolvable介面。您很可能只會看到字符串編碼版本的令牌。

其他函數通常只接受基本型別的引數,例如stringnumber。要在這些情況下使用令牌,您可以通過使用 CDK.Token 類上的靜態方法將它們編碼為三種類型之一。

這些需要一個任意值,它可以是一個IResolvable,並將它們編碼為指示類型的原始值。

重要

由於先前的任何一種類型都可能是編碼的 Token,因此在剖析或嘗試讀取其內容時請小心。例如,如果您嘗試剖析字串以從中擷取值,而該字串是編碼的 Token,則剖析會失敗。同樣地,如果您嘗試查詢陣列的長度或使用數字執行數學運算,您必須先驗證它們是否未編碼 Token。

若要檢查值中是否有未解析的權杖,請呼叫 Token.isUnresolved (Python:is_unresolved) 方法。

下列範例會驗證字串值 (可能是 Token) 的長度不超過 10 個字元。

TypeScript
if (!Token.isUnresolved(name) && name.length > 10) { throw new Error(`Maximum length for name is 10 characters`); }
JavaScript
if ( !Token.isUnresolved(name) && name.length > 10) { throw ( new Error(`Maximum length for name is 10 characters`)); }
Python
if not Token.is_unresolved(name) and len(name) > 10: raise ValueError("Maximum length for name is 10 characters")
Java
if (!Token.isUnresolved(name) && name.length() > 10) throw new IllegalArgumentException("Maximum length for name is 10 characters");
C#
if (!Token.IsUnresolved(name) && name.Length > 10) throw new ArgumentException("Maximum length for name is 10 characters");

如果 name 是 Token,則不會執行驗證,並且在生命週期的稍後階段(例如部署期間)仍可能發生錯誤。

注意

您可以使用令牌編碼來轉義類型系統。例如,您可以對在合成時產生數字值的令牌進行字符串編碼。如果您使用這些函數,您有責任確保您的模板在合成後解析為可用狀態。

字符串編碼令牌

字符串編碼令牌看起來如下所示。

${TOKEN[Bucket.Name.1234]}

它們可以像常規字符串一樣傳遞,並且可以連接起來,如以下示例所示。

TypeScript
const functionName = bucket.bucketName + 'Function';
JavaScript
const functionName = bucket.bucketName + 'Function';
Python
function_name = bucket.bucket_name + "Function"
Java
String functionName = bucket.getBucketName().concat("Function");
C#
string functionName = bucket.BucketName + "Function";

如果您的語言支援,您也可以使用字串內插補點,如下列範例所示。

TypeScript
const functionName = `${bucket.bucketName}Function`;
JavaScript
const functionName = `${bucket.bucketName}Function`;
Python
function_name = f"{bucket.bucket_name}Function"
Java
String functionName = String.format("%sFunction". bucket.getBucketName());
C#
string functionName = $"${bucket.bucketName}Function";

避免以其他方式操作字符串。例如,取得字串的子字串很可能會中斷字串 Token。

列表編碼令牌

列表編碼的令牌如下所示:

["#{TOKEN[Stack.NotificationArns.1234]}"]

這些列表唯一安全的事情就是將它們直接傳遞給其他構造。字符串列表形式的令牌不能連接,也不能從令牌中獲取元素。操作它們的唯一安全方法是使用 Fn.select 等 AWS CloudFormation 內在函數。

数字编码令牌

數字編碼的令牌是一組微小的負浮點數,如下所示。

-1.8881545897087626e+289

與列表令牌一樣,您無法修改數字值,因為這樣做可能會破壞數字令牌。唯一允許的操作是將值傳遞給另一個構造。

懶惰值

除了表示部署時間值 (例如 AWS CloudFormation 參數) 之外,Token 也常用來表示合成時間延遲值。這些是最終值將在合成完成之前確定的值,但不是在構建該值的時間點。使用令牌將文字字符串或數字值傳遞給另一個構造,而合成時的實際值可能取決於尚未發生的某些計算。

您可以使用Lazy類別上的靜態方法 (例如 lazy.String 和 lazy .Number) 來建構代表合成時間延遲值的記號。這些方法接受一個對象,其produce屬性是接受上下文參數的函數,並在調用時返回最終值。

下列範例會建立 Auto Scaling 群組,其容量是在建立之後決定的。

TypeScript
let actualValue: number; new AutoScalingGroup(this, 'Group', { desiredCapacity: Lazy.numberValue({ produce(context) { return actualValue; } }) }); // At some later point actualValue = 10;
JavaScript
let actualValue; new AutoScalingGroup(this, 'Group', { desiredCapacity: Lazy.numberValue({ produce(context) { return (actualValue); } }) }); // At some later point actualValue = 10;
Python
class Producer: def __init__(self, func): self.produce = func actual_value = None AutoScalingGroup(self, "Group", desired_capacity=Lazy.number_value(Producer(lambda context: actual_value)) ) # At some later point actual_value = 10
Java
double actualValue = 0; class ProduceActualValue implements INumberProducer { @Override public Number produce(IResolveContext context) { return actualValue; } } AutoScalingGroup.Builder.create(this, "Group") .desiredCapacity(Lazy.numberValue(new ProduceActualValue())).build(); // At some later point actualValue = 10;
C#
public class NumberProducer : INumberProducer { Func<Double> function; public NumberProducer(Func<Double> function) { this.function = function; } public Double Produce(IResolveContext context) { return function(); } } double actualValue = 0; new AutoScalingGroup(this, "Group", new AutoScalingGroupProps { DesiredCapacity = Lazy.NumberValue(new NumberProducer(() => actualValue)) }); // At some later point actualValue = 10;

轉換為 JSON

有時你想產生一JSON串任意數據,你可能不知道數據是否包含令牌。要正確JSON編碼任何數據結構,無論它是否包含令牌,請使用該方法堆棧。 toJsonString,如下列範例所示。

TypeScript
const stack = Stack.of(this); const str = stack.toJsonString({ value: bucket.bucketName });
JavaScript
const stack = Stack.of(this); const str = stack.toJsonString({ value: bucket.bucketName });
Python
stack = Stack.of(self) string = stack.to_json_string(dict(value=bucket.bucket_name))
Java
Stack stack = Stack.of(this); String stringVal = stack.toJsonString(java.util.Map.of( // Map.of requires Java 9+ put("value", bucket.getBucketName())));
C#
var stack = Stack.Of(this); var stringVal = stack.ToJsonString(new Dictionary<string, string> { ["value"] = bucket.BucketName });