這是 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
介面。您很可能只會看到字符串編碼版本的令牌。
其他函數通常只接受基本型別的引數,例如string
或number
。要在這些情況下使用令牌,您可以通過使用 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
});