这是 AWS CDK v2 开发者指南。较旧的 CDK v1 于 2022 年 6 月 1 日进入维护阶段,并于 2023 年 6 月 1 日终止支持。
本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
导入现有 AWS CloudFormation 模板
使用cloudformation-include.CfnInclude
构造将资源转换为 L1 结构,将资源从 AWS CloudFormation 模板导入到您的 AWS Cloud Development Kit (AWS CDK) 应用程序中。
导入后,您可以在应用程序中使用这些资源,方法与最初在 AWS CDK 代码中定义这些资源的方式相同。你也可以在更高级别 AWS CDK 的构造中使用这些 L1 结构。例如,这可以让你将 L2 权限授予方法与它们定义的资源一起使用。
该cloudformation-include.CfnInclude
构造本质上是为 AWS CloudFormation 模板中的任何资源添加 AWS CDK API包装器。使用此功能一次将现有 AWS CloudFormation 模板导入到 AWS CDK 一个片段中。通过这样做,你可以使用 AWS CDK 构造来管理现有资源,从而利用更高级别的抽象的好处。您还可以使用此功能通过提供 AWS CDK 构造API将 AWS CloudFormation 模板出售给 AWS CDK 开发人员。
导入 AWS CloudFormation 模板
以下是示例 AWS CloudFormation 模板,我们将使用该模板在本主题中提供示例。复制并保存模板,my-template.json
以便后续操作。完成这些示例后,您可以使用任何现有已部署的 AWS CloudFormation 模板进一步探索。您可以从 AWS CloudFormation
控制台获取它们。
{
"Resources": {
"MyBucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": "MyBucket",
}
}
}
}
您可以使用JSON或YAML模板中的任意一个。JSON如果可用,我们建议使用,因为YAML解析器接受的内容可能略有不同。
以下是如何使用将示例模板导入 AWS CDK 应用程序的示例cloudformation-include
。模板是在CDK堆栈的上下文中导入的。
- TypeScript
-
import * as cdk from 'aws-cdk-lib';
import * as cfninc from 'aws-cdk-lib/cloudformation-include';
import { Construct } from 'constructs';
export class MyStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const template = new cfninc.CfnInclude(this, 'Template', {
templateFile: 'my-template.json',
});
}
}
- JavaScript
-
const cdk = require('aws-cdk-lib');
const cfninc = require('aws-cdk-lib/cloudformation-include');
class MyStack extends cdk.Stack {
constructor(scope, id, props) {
super(scope, id, props);
const template = new cfninc.CfnInclude(this, 'Template', {
templateFile: 'my-template.json',
});
}
}
module.exports = { MyStack }
- Python
-
import aws_cdk as cdk
from aws_cdk import cloudformation_include as cfn_inc
from constructs import Construct
class MyStack(cdk.Stack):
def __init__(self, scope: Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
template = cfn_inc.CfnInclude(self, "Template",
template_file="my-template.json")
- Java
-
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.cloudformation.include.CfnInclude;
import software.constructs.Construct;
public class MyStack extends Stack {
public MyStack(final Construct scope, final String id) {
this(scope, id, null);
}
public MyStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
CfnInclude template = CfnInclude.Builder.create(this, "Template")
.templateFile("my-template.json")
.build();
}
}
- C#
-
using Amazon.CDK;
using Constructs;
using cfnInc = Amazon.CDK.CloudFormation.Include;
namespace MyApp
{
public class MyStack : Stack
{
internal MyStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
{
var template = new cfnInc.CfnInclude(this, "Template", new cfnInc.CfnIncludeProps
{
TemplateFile = "my-template.json"
});
}
}
}
默认情况下,导入资源会保留模板中资源的原始逻辑 ID。此行为适用于将 AWS CloudFormation 模板导入到 AWS CDK,其中IDs必须保留逻辑。 AWS CloudFormation 需要这些信息才能将这些导入的资源识别为 AWS CloudFormation 模板中的相同资源。
如果您正在为模板开发 AWS CDK 构造封装器,以便其他 AWS CDK 开发人员可以使用,请IDs改用 AWS CDK 生成新资源。通过这样做,可以在堆栈中多次使用该构造,而不会出现名称冲突。为此,请在导入模板false
时将该preserveLogicalIds
属性设置为。以下是 示例:
- TypeScript
-
const template = new cfninc.CfnInclude(this, 'MyConstruct', {
templateFile: 'my-template.json',
preserveLogicalIds: false
});
- JavaScript
-
const template = new cfninc.CfnInclude(this, 'MyConstruct', {
templateFile: 'my-template.json',
preserveLogicalIds: false
});
- Python
-
template = cfn_inc.CfnInclude(self, "Template",
template_file="my-template.json",
preserve_logical_ids=False)
- Java
-
CfnInclude template = CfnInclude.Builder.create(this, "Template")
.templateFile("my-template.json")
.preserveLogicalIds(false)
.build();
- C#
-
var template = new cfnInc.CfnInclude(this, "Template", new cfn_inc.CfnIncludeProps
{
TemplateFile = "my-template.json",
PreserveLogicalIds = false
});
要将导入的资源置于您的 AWS CDK 应用程序的控制之下,请将堆栈添加到App
:
- TypeScript
-
import * as cdk from 'aws-cdk-lib';
import { MyStack } from '../lib/my-stack';
const app = new cdk.App();
new MyStack(app, 'MyStack');
- JavaScript
-
const cdk = require('aws-cdk-lib');
const { MyStack } = require('../lib/my-stack');
const app = new cdk.App();
new MyStack(app, 'MyStack');
- Python
-
import aws_cdk as cdk
from mystack.my_stack import MyStack
app = cdk.App()
MyStack(app, "MyStack")
- Java
-
import software.amazon.awscdk.App;
public class MyApp {
public static void main(final String[] args) {
App app = new App();
new MyStack(app, "MyStack");
}
}
- C#
-
using Amazon.CDK;
namespace CdkApp
{
sealed class Program
{
public static void Main(string[] args)
{
var app = new App();
new MyStack(app, "MyStack");
}
}
}
要验证堆栈中的 AWS 资源不会发生任何意想不到的更改,您可以执行差异。使用 AWS CDK CLIcdk diff
命令并省略任何 AWS CDK特定的元数据。以下是 示例:
cdk diff --no-version-reporting --no-path-metadata --no-asset-metadata
导入 AWS CloudFormation 模板后,该 AWS CDK 应用程序应成为您导入资源的真实来源。要对资源进行更改,请在 AWS CDK 应用程序中对其进行修改,然后使用 AWS CDK CLIcdk deploy命令进行部署。
访问导入的资源
示例代码template
中的名称代表导入的 AWS CloudFormation 模板。要从中访问资源,请使用对象getResource()
的方法。要将返回的资源作为特定类型的资源进行访问,请将结果转换为所需的类型。在 Python 中或者,这不是必需 JavaScript的。以下是 示例:
- TypeScript
-
const cfnBucket = template.getResource('MyBucket') as s3.CfnBucket;
- JavaScript
-
const cfnBucket = template.getResource('MyBucket');
- Python
-
cfn_bucket = template.get_resource("MyBucket")
- Java
-
CfnBucket cfnBucket = (CfnBucket)template.getResource("MyBucket");
- C#
-
var cfnBucket = (CfnBucket)template.GetResource("MyBucket");
从这个例子中,现在cfnBucket
是该aws-s3.CfnBucket
类的实例。这是代表相应 AWS CloudFormation 资源的 L1 结构。你可以像对待任何其他同类资源一样对待它。例如,您可以通过bucket.attrArn
属性获取其ARN值。
要改为将 L1 CfnBucket
资源封装在 L2 aws-s3.Bucket
实例中,请使用静态方法fromBucketArn()
fromBucketAttributes()
、或。fromBucketName()
通常,该fromBucketName()
方法最方便。以下是 示例:
- TypeScript
-
const bucket = s3.Bucket.fromBucketName(this, 'Bucket', cfnBucket.ref);
- JavaScript
-
const bucket = s3.Bucket.fromBucketName(this, 'Bucket', cfnBucket.ref);
- Python
-
bucket = s3.Bucket.from_bucket_name(self, "Bucket", cfn_bucket.ref)
- Java
-
Bucket bucket = (Bucket)Bucket.fromBucketName(this, "Bucket", cfnBucket.getRef());
- C#
-
var bucket = (Bucket)Bucket.FromBucketName(this, "Bucket", cfnBucket.Ref);
其他 L2 构造也有类似的方法,用于从现有资源创建构造。
当你将 L1 构造封装在 L2 构造中时,它不会创建新的资源。从我们的示例来看,我们没有创建第二个 S3; 存储桶。相反,新Bucket
实例封装了现有实例。CfnBucket
从示例中可以看出,现在bucket
是一个 L2 Bucket
构造,其行为与任何其他 L2 构造类似。例如,您可以使用存储桶的便捷grantWrite()
方法向 AWS Lambda 函数授予对该存储桶的写入权限。您不必手动定义必要的 AWS Identity and Access Management (IAM) 策略。以下是 示例:
- TypeScript
-
bucket.grantWrite(lambdaFunc);
- JavaScript
-
bucket.grantWrite(lambdaFunc);
- Python
-
bucket.grant_write(lambda_func)
- Java
-
bucket.grantWrite(lambdaFunc);
- C#
-
bucket.GrantWrite(lambdaFunc);
替换参数
如果您的 AWS CloudFormation 模板包含参数,则可以在导入时使用parameters
属性将其替换为构建时值。在以下示例中,我们将UploadBucket
参数替换为 AWS CDK 代码中其他地方定义ARN的存储桶的参数。
- TypeScript
-
const template = new cfninc.CfnInclude(this, 'Template', {
templateFile: 'my-template.json',
parameters: {
'UploadBucket': bucket.bucketArn,
},
});
- JavaScript
-
const template = new cfninc.CfnInclude(this, 'Template', {
templateFile: 'my-template.json',
parameters: {
'UploadBucket': bucket.bucketArn,
},
});
- Python
-
template = cfn_inc.CfnInclude(self, "Template",
template_file="my-template.json",
parameters=dict(UploadBucket=bucket.bucket_arn)
)
- Java
-
CfnInclude template = CfnInclude.Builder.create(this, "Template")
.templateFile("my-template.json")
.parameters(java.util.Map.of( // Map.of requires Java 9+
"UploadBucket", bucket.getBucketArn()))
.build();
- C#
-
var template = new cfnInc.CfnInclude(this, "Template", new cfnInc.CfnIncludeProps
{
TemplateFile = "my-template.json",
Parameters = new Dictionary<string, string>
{
{ "UploadBucket", bucket.BucketArn }
}
});
导入其他模板元素
您可以导入任何 AWS CloudFormation 模板元素,而不仅仅是资源。导入的元素将成为 AWS CDK
堆栈的一部分。要导入这些元素,请使用CfnInclude
对象的以下方法:
这些方法中的每一个都返回一个表示特定 AWS CloudFormation 元素类型的类的实例。这些对象是可变的。您对它们所做的更改将显示在从 AWS CDK
堆栈生成的模板中。以下是从模板导入参数并修改其默认值的示例:
- TypeScript
-
const param = template.getParameter('MyParameter');
param.default = "AWS CDK"
- JavaScript
-
const param = template.getParameter('MyParameter');
param.default = "AWS CDK"
- Python
-
param = template.get_parameter("MyParameter")
param.default = "AWS CDK"
- Java
-
CfnParameter param = template.getParameter("MyParameter");
param.setDefaultValue("AWS CDK")
- C#
-
var cfnBucket = (CfnBucket)template.GetResource("MyBucket");
var param = template.GetParameter("MyParameter");
param.Default = "AWS CDK";
导入嵌套堆栈
您可以通过在导入嵌套堆栈的主模板时或稍后指定嵌套堆栈来导入它们。嵌套模板必须存储在本地文件中,但在主模板中作为NestedStack
资源引用。此外, AWS CDK 代码中使用的资源名称必须与主模板中用于嵌套堆栈的名称相匹配。
鉴于主模板中的此资源定义,以下代码显示了如何双向导入引用的嵌套堆栈。
"NestedStack": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": "https://my-s3-template-source.s3.amazonaws.com/nested-stack.json"
}
- TypeScript
-
// include nested stack when importing main stack
const mainTemplate = new cfninc.CfnInclude(this, 'MainStack', {
templateFile: 'main-template.json',
loadNestedStacks: {
'NestedStack': {
templateFile: 'nested-template.json',
},
},
});
// or add it some time after importing the main stack
const nestedTemplate = mainTemplate.loadNestedStack('NestedTemplate', {
templateFile: 'nested-template.json',
});
- JavaScript
-
// include nested stack when importing main stack
const mainTemplate = new cfninc.CfnInclude(this, 'MainStack', {
templateFile: 'main-template.json',
loadNestedStacks: {
'NestedStack': {
templateFile: 'nested-template.json',
},
},
});
// or add it some time after importing the main stack
const nestedTemplate = mainTemplate.loadNestedStack('NestedStack', {
templateFile: 'my-nested-template.json',
});
- Python
-
# include nested stack when importing main stack
main_template = cfn_inc.CfnInclude(self, "MainStack",
template_file="main-template.json",
load_nested_stacks=dict(NestedStack=
cfn_inc.CfnIncludeProps(template_file="nested-template.json")))
# or add it some time after importing the main stack
nested_template = main_template.load_nested_stack("NestedStack",
template_file="nested-template.json")
- Java
-
CfnInclude mainTemplate = CfnInclude.Builder.create(this, "MainStack")
.templateFile("main-template.json")
.loadNestedStacks(java.util.Map.of( // Map.of requires Java 9+
"NestedStack", CfnIncludeProps.builder()
.templateFile("nested-template.json").build()))
.build();
// or add it some time after importing the main stack
IncludedNestedStack nestedTemplate = mainTemplate.loadNestedStack("NestedTemplate", CfnIncludeProps.builder()
.templateFile("nested-template.json")
.build());
- C#
-
// include nested stack when importing main stack
var mainTemplate = new cfnInc.CfnInclude(this, "MainStack", new cfnInc.CfnIncludeProps
{
TemplateFile = "main-template.json",
LoadNestedStacks = new Dictionary<string, cfnInc.ICfnIncludeProps>
{
{ "NestedStack", new cfnInc.CfnIncludeProps { TemplateFile = "nested-template.json" } }
}
});
// or add it some time after importing the main stack
var nestedTemplate = mainTemplate.LoadNestedStack("NestedTemplate", new cfnInc.CfnIncludeProps {
TemplateFile = 'nested-template.json'
});
您可以使用任一方法导入多个嵌套堆栈。导入主模板时,您需要提供每个嵌套堆栈的资源名称与其模板文件之间的映射。此映射可以包含任意数量的条目。要在初始导入后执行此操作,请为每个嵌套堆栈调用loadNestedStack()
一次。
导入嵌套堆栈后,您可以使用主模板的getNestedStack()
方法对其进行访问。
- TypeScript
-
const nestedStack = mainTemplate.getNestedStack('NestedStack').stack;
- JavaScript
-
const nestedStack = mainTemplate.getNestedStack('NestedStack').stack;
- Python
-
nested_stack = main_template.get_nested_stack("NestedStack").stack
- Java
-
NestedStack nestedStack = mainTemplate.getNestedStack("NestedStack").getStack();
- C#
-
var nestedStack = mainTemplate.GetNestedStack("NestedStack").Stack;
该getNestedStack()
方法返回一个IncludedNestedStack
实例。在此实例中,您可以通过stack
属性访问 AWS CDK NestedStack
实例,如示例所示。您也可以通过访问原始 AWS CloudFormation 模板对象includedTemplate
,从中加载资源和其他 AWS CloudFormation 元素。