AWS CDK 构造 - AWS Cloud Development Kit (AWS CDK) v2

这是 AWS CDK v2 开发者指南。较旧的 CDK v1 于 2022 年 6 月 1 日进入维护阶段,并于 2023 年 6 月 1 日终止支持。

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

AWS CDK 构造

构造是 AWS Cloud Development Kit (AWS CDK) 应用程序的基本组成部分。构造是应用程序中的一个组件,它代表一个或多个 AWS CloudFormation 资源及其配置。您可以通过导入和配置构造来逐步构建应用程序。

导入和使用构造

构造是您从AWS 构造库导入到CDK应用程序中的类。您也可以创建和分发自己的构造,或者使用第三方开发者创建的构造。

构造是构造编程模型 (CPM) 的一部分。它们可以与其他工具一起使用,CDK例如 Terraform (CDKtf),CDK对于 Kubernetes (CDK8s),以及 Projen.

许多第三方也发布了与... 兼容的 AWS CDK结构。访问 C onstruc t Hub 探索 AWS CDK 建筑合作伙伴生态系统。

构造关卡

构造库中的 AWS 构造分为三个级别。每个级别都提供了越来越高的抽象级别。抽象越高,配置越容易,所需的专业知识也越少。抽象越低,可用的自定义越多,需要更多的专业知识。

1 级 (L1) 构造

L1 构造,也称为CFN资源,是最低级别的构造,不提供抽象。每个 L1 构造都直接映射到单个 AWS CloudFormation 资源。使用 L1 构造,您可以导入代表特定 AWS CloudFormation 资源的构造。然后,您可以在构造实例中定义资源的属性。

当您熟悉 AWS CloudFormation 并需要完全控制 AWS 资源属性的定义时,L1 结构非常适合使用。

在 AWS 构造库中,L1 构造以开头命名Cfn,后面是它所代表的 AWS CloudFormation 资源的标识符。例如,该CfnBucket构造是代表AWS::S3::Bucket AWS CloudFormation 资源的 L1 构造。

L1 结构是根据AWS CloudFormation 资源规范生成的。如果资源存在于中 AWS CloudFormation,则该资源将 AWS CDK 作为 L1 结构在中可用。新资源或属性可能需要长达一周的时间才能在 Construct Librar AWS y 中发布。有关更多信息,请参阅《AWS CloudFormation 用户指南》中的AWS 资源和属性类型参考

2 级 (L2) 构造

L2 构造,也称为精选构造,由CDK团队精心开发,通常是使用最广泛的构造类型。L2 构造直接映射到单个 AWS CloudFormation 资源,类似于 L1 结构。与 L1 结构相比,L2 构造通过直观的基于意图的构造提供了更高级别的抽象。APIL2 结构包括合理的默认属性配置、最佳实践安全策略,并为您生成大量样板代码和粘合逻辑。

L2 构造还为大多数资源提供了辅助方法,使定义属性、权限、资源之间基于事件的交互等变得更加简单快捷。

s3.Bucket类是亚马逊简单存储服务 (Amazon S3) 存储桶资源的 L2 结构示例。

AWS 构造库包含指定为稳定且可供生产使用的 L2 构造。对于正在开发的 L2 结构,它们被指定为实验性结构,并在单独的模块中提供。

3 级 (L3) 构造

L3 构造,也称为模式,是最高级别的抽象。每个 L3 构造可以包含一组资源,这些资源配置为协同工作以完成应用程序中的特定任务或服务。L3 结构用于为应用程序中的特定用例创建整个 AWS 架构。

为了提供完整的系统设计或大型系统的重要组成部分,L3 构造提供了自以为是的默认属性配置。它们围绕解决问题和提供解决方案的特定方法而构建。使用 L3 结构,您可以用最少的输入和代码快速创建和配置多个资源。

ecsPatterns.ApplicationLoadBalancedFargateService类是 L3 结构的示例,该结构表示在亚马逊弹性容器 AWS Fargate 服务 (AmazonECS) 集群上运行并以应用程序负载均衡器为前端的服务。

与 L2 构造类似,可供生产使用的 L3 构造包含在构造库中。 AWS 正在开发的软件以单独的模块提供。

定义结构

合成

组合是通过构造定义更高级别抽象的关键模式。高级构造可以由任意数量的较低级别构造构成。从自下而上的角度来看,您可以使用构造来组织要 AWS 部署的各个资源。你可以随心所欲地使用任何适合你目的的抽象,你可以根据需要使用任意数量的级别。

通过组合,您可以定义可重复使用的组件,并像任何其他代码一样共享它们。例如,团队可以定义一种结构,用于实现公司对 Amazon DynamoDB 表的最佳实践,包括备份、全局复制、自动扩展和监控。团队可以在内部与其他团队共享构建,也可以公开共享。

团队可以像使用任何其他库包一样使用构造。库更新后,开发人员可以访问新版本的改进和错误修复,这与任何其他代码库类似。

初始化

构造是在扩展 Construct 基类的类中实现的。您可以通过实例化类来定义构造。所有构造在初始化时都有三个参数:

  • s@@ cop e — 构造的父级或所有者。这可以是堆栈,也可以是其他构造。作用域决定构造在构造树中的位置。你通常应该通过 this (selfin Python),它代表作用域的当前对象。

  • id — 在范围内必须是唯一的标识符。标识符充当构造中定义的所有内容的命名空间。它用于生成唯一标识符,例如资源名称和 AWS CloudFormation 逻辑IDs。

    标识符只需要在一个范围内是唯一的。这使您可以实例化和重用构造,而不必担心它们可能包含的构造和标识符,并且可以将构造组合成更高级别的抽象。此外,作用域可以同时引用一组构造。示例包括标记或指定构造的部署位置。

  • props — 一组属性或关键字参数,视语言而定,用于定义构造的初始配置。更高级别的构造提供了更多的默认值,如果所有 prop 元素都是可选的,则可以完全省略 props 参数。

配置

大多数构造都接受定义构造配置的名称/值集合props作为其第三个参数(或者在 Python 中为关键字参数)。以下示例定义了一个启用了 AWS Key Management Service (AWS KMS) 加密和静态网站托管的存储桶。由于它没有明确指定加密密钥,因此该Bucket构造定义了一个新的kms.Key密钥并将其与存储桶相关联。

TypeScript
new s3.Bucket(this, 'MyEncryptedBucket', { encryption: s3.BucketEncryption.KMS, websiteIndexDocument: 'index.html' });
JavaScript
new s3.Bucket(this, 'MyEncryptedBucket', { encryption: s3.BucketEncryption.KMS, websiteIndexDocument: 'index.html' });
Python
s3.Bucket(self, "MyEncryptedBucket", encryption=s3.BucketEncryption.KMS, website_index_document="index.html")
Java
Bucket.Builder.create(this, "MyEncryptedBucket") .encryption(BucketEncryption.KMS_MANAGED) .websiteIndexDocument("index.html").build();
C#
new Bucket(this, "MyEncryptedBucket", new BucketProps { Encryption = BucketEncryption.KMS_MANAGED, WebsiteIndexDocument = "index.html" });
Go
awss3.NewBucket(stack, jsii.String("MyEncryptedBucket"), &awss3.BucketProps{ Encryption: awss3.BucketEncryption_KMS, WebsiteIndexDocument: jsii.String("index.html"), })

与构造交互

构造是扩展基本构造类的类。实例化构造后,构造对象会公开一组方法和属性,这些方法和属性允许你与该构造进行交互并将其作为对系统其他部分的引用传递。

该 AWS CDK 框架对构造没有任何限制。APIs作者可以随心API所欲地定义。但是, AWS 构造库中包含的 AWS 构造(例如s3.Bucket)遵循准则和常见模式。这为所有 AWS 资源提供了一致的体验。

大多数 AWS 构造都有一组授予方法,您可以使用这些方法向委托人授予对该构造的 AWS Identity and Access Management (IAM) 权限。以下示例向IAM群组授予从 Amazon S3 存储桶读取的data-science权限raw-data

TypeScript
const rawData = new s3.Bucket(this, 'raw-data'); const dataScience = new iam.Group(this, 'data-science'); rawData.grantRead(dataScience);
JavaScript
const rawData = new s3.Bucket(this, 'raw-data'); const dataScience = new iam.Group(this, 'data-science'); rawData.grantRead(dataScience);
Python
raw_data = s3.Bucket(self, 'raw-data') data_science = iam.Group(self, 'data-science') raw_data.grant_read(data_science)
Java
Bucket rawData = new Bucket(this, "raw-data"); Group dataScience = new Group(this, "data-science"); rawData.grantRead(dataScience);
C#
var rawData = new Bucket(this, "raw-data"); var dataScience = new Group(this, "data-science"); rawData.GrantRead(dataScience);
Go
rawData := awss3.NewBucket(stack, jsii.String("raw-data"), nil) dataScience := awsiam.NewGroup(stack, jsii.String("data-science"), nil) rawData.GrantRead(dataScience, nil)

另一种常见的模式是 AWS 构造根据其他地方提供的数据设置资源的一个属性。属性可以包括 Amazon 资源名称 (ARNs)、名称或URLs。

以下代码定义了一个 AWS Lambda 函数,并通过环境变量URL中的队列将其与亚马逊简单队列服务 (AmazonSQS) 队列关联起来。

TypeScript
const jobsQueue = new sqs.Queue(this, 'jobs'); const createJobLambda = new lambda.Function(this, 'create-job', { runtime: lambda.Runtime.NODEJS_18_X, handler: 'index.handler', code: lambda.Code.fromAsset('./create-job-lambda-code'), environment: { QUEUE_URL: jobsQueue.queueUrl } });
JavaScript
const jobsQueue = new sqs.Queue(this, 'jobs'); const createJobLambda = new lambda.Function(this, 'create-job', { runtime: lambda.Runtime.NODEJS_18_X, handler: 'index.handler', code: lambda.Code.fromAsset('./create-job-lambda-code'), environment: { QUEUE_URL: jobsQueue.queueUrl } });
Python
jobs_queue = sqs.Queue(self, "jobs") create_job_lambda = lambda_.Function(self, "create-job", runtime=lambda_.Runtime.NODEJS_18_X, handler="index.handler", code=lambda_.Code.from_asset("./create-job-lambda-code"), environment=dict( QUEUE_URL=jobs_queue.queue_url ) )
Java
final Queue jobsQueue = new Queue(this, "jobs"); Function createJobLambda = Function.Builder.create(this, "create-job") .handler("index.handler") .code(Code.fromAsset("./create-job-lambda-code")) .environment(java.util.Map.of( // Map.of is Java 9 or later "QUEUE_URL", jobsQueue.getQueueUrl()) .build();
C#
var jobsQueue = new Queue(this, "jobs"); var createJobLambda = new Function(this, "create-job", new FunctionProps { Runtime = Runtime.NODEJS_18_X, Handler = "index.handler", Code = Code.FromAsset(@".\create-job-lambda-code"), Environment = new Dictionary<string, string> { ["QUEUE_URL"] = jobsQueue.QueueUrl } });
Go
createJobLambda := awslambda.NewFunction(stack, jsii.String("create-job"), &awslambda.FunctionProps{ Runtime: awslambda.Runtime_NODEJS_18_X(), Handler: jsii.String("index.handler"), Code: awslambda.Code_FromAsset(jsii.String(".\\create-job-lambda-code"), nil), Environment: &map[string]*string{ "QUEUE_URL": jsii.String(*jobsQueue.QueueUrl()), }, })

有关 AWS 构造库中最常见API模式的信息,请参阅资源和 AWS CDK

应用程序和堆栈结构

AWS 构造库中的AppStack类是独特的构造。与其他结构相比,它们不会自行配置 AWS 资源。相反,它们用于为您的其他构造提供上下文。所有代表 AWS 资源的构造都必须在Stack构造的范围内直接或间接地定义。 Stack构造是在App构造的范围内定义的。

要了解有关CDK应用程序的更多信息,请参阅AWS CDK 应用程序。要了解有关CDK堆栈的更多信息,请参阅AWS CDK 堆栈

以下示例定义了一个具有单个堆栈的应用程序。在堆栈中,使用 L2 结构来配置 Amazon S3 存储桶资源。

TypeScript
import { App, Stack, StackProps } from 'aws-cdk-lib'; import * as s3 from 'aws-cdk-lib/aws-s3'; class HelloCdkStack extends Stack { constructor(scope: App, id: string, props?: StackProps) { super(scope, id, props); new s3.Bucket(this, 'MyFirstBucket', { versioned: true }); } } const app = new App(); new HelloCdkStack(app, "HelloCdkStack");
JavaScript
const { App , Stack } = require('aws-cdk-lib'); const s3 = require('aws-cdk-lib/aws-s3'); class HelloCdkStack extends Stack { constructor(scope, id, props) { super(scope, id, props); new s3.Bucket(this, 'MyFirstBucket', { versioned: true }); } } const app = new App(); new HelloCdkStack(app, "HelloCdkStack");
Python
from aws_cdk import App, Stack import aws_cdk.aws_s3 as s3 from constructs import Construct class HelloCdkStack(Stack): def __init__(self, scope: Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) s3.Bucket(self, "MyFirstBucket", versioned=True) app = App() HelloCdkStack(app, "HelloCdkStack")
Java

HelloCdkStack.java文件中定义的堆栈:

import software.constructs.Construct; import software.amazon.awscdk.Stack; import software.amazon.awscdk.StackProps; import software.amazon.awscdk.services.s3.*; public class HelloCdkStack extends Stack { public HelloCdkStack(final Construct scope, final String id) { this(scope, id, null); } public HelloCdkStack(final Construct scope, final String id, final StackProps props) { super(scope, id, props); Bucket.Builder.create(this, "MyFirstBucket") .versioned(true).build(); } }

HelloCdkApp.java文件中定义的应用程序:

import software.amazon.awscdk.App; import software.amazon.awscdk.StackProps; public class HelloCdkApp { public static void main(final String[] args) { App app = new App(); new HelloCdkStack(app, "HelloCdkStack", StackProps.builder() .build()); app.synth(); } }
C#
using Amazon.CDK; using Amazon.CDK.AWS.S3; namespace HelloCdkApp { internal static class Program { public static void Main(string[] args) { var app = new App(); new HelloCdkStack(app, "HelloCdkStack"); app.Synth(); } } public class HelloCdkStack : Stack { public HelloCdkStack(Construct scope, string id, IStackProps props=null) : base(scope, id, props) { new Bucket(this, "MyFirstBucket", new BucketProps { Versioned = true }); } } }
Go
func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack { var sprops awscdk.StackProps if props != nil { sprops = props.StackProps } stack := awscdk.NewStack(scope, &id, &sprops) awss3.NewBucket(stack, jsii.String("MyFirstBucket"), &awss3.BucketProps{ Versioned: jsii.Bool(true), }) return stack }

使用构造

使用 L1 构造

L1 构造直接映射到各个 AWS CloudFormation 资源。您必须提供资源所需的配置。

在这个例子中,我们使用 CfnBucket L1 构造创建一个bucket对象:

TypeScript
const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", { bucketName: "amzn-s3-demo-bucket" });
JavaScript
const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", { bucketName: "amzn-s3-demo-bucket" });
Python
bucket = s3.CfnBucket(self, "amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket")
Java
CfnBucket bucket = new CfnBucket.Builder().bucketName("amzn-s3-demo-bucket").build();
C#
var bucket = new CfnBucket(this, "amzn-s3-demo-bucket", new CfnBucketProps { BucketName= "amzn-s3-demo-bucket" });
Go
awss3.NewCfnBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.CfnBucketProps{ BucketName: jsii.String("amzn-s3-demo-bucket"), })

构造不是简单布尔值、字符串、数字或容器的属性在支持的语言中的处理方式有所不同。

TypeScript
const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", { bucketName: "amzn-s3-demo-bucket", corsConfiguration: { corsRules: [{ allowedOrigins: ["*"], allowedMethods: ["GET"] }] } });
JavaScript
const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", { bucketName: "amzn-s3-demo-bucket", corsConfiguration: { corsRules: [{ allowedOrigins: ["*"], allowedMethods: ["GET"] }] } });
Python

在 Python 中,这些属性由定义为 L1 构造内部类的类型表示。例如,a 的可选属性CfnBucket需要一个cors_configuration类型的CfnBucket.CorsConfigurationProperty封装器。这里我们在一个CfnBucket实例cors_configuration上定义。

bucket = CfnBucket(self, "amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket", cors_configuration=CfnBucket.CorsConfigurationProperty( cors_rules=[CfnBucket.CorsRuleProperty( allowed_origins=["*"], allowed_methods=["GET"] )] ) )
Java

在 Java 中,这些属性由定义为 L1 构造内部类的类型表示。例如,a 的可选属性CfnBucket需要一个corsConfiguration类型的CfnBucket.CorsConfigurationProperty封装器。这里我们在一个CfnBucket实例corsConfiguration上定义。

CfnBucket bucket = CfnBucket.Builder.create(this, "amzn-s3-demo-bucket") .bucketName("amzn-s3-demo-bucket") .corsConfiguration(new CfnBucket.CorsConfigurationProperty.Builder() .corsRules(Arrays.asList(new CfnBucket.CorsRuleProperty.Builder() .allowedOrigins(Arrays.asList("*")) .allowedMethods(Arrays.asList("GET")) .build())) .build()) .build();
C#

在 C# 中,这些属性由定义为 L1 构造内部类的类型表示。例如,a 的可选属性CfnBucket需要一个CorsConfiguration类型的CfnBucket.CorsConfigurationProperty封装器。这里我们在一个CfnBucket实例CorsConfiguration上定义。

var bucket = new CfnBucket(this, "amzn-s3-demo-bucket", new CfnBucketProps { BucketName = "amzn-s3-demo-bucket", CorsConfiguration = new CfnBucket.CorsConfigurationProperty { CorsRules = new object[] { new CfnBucket.CorsRuleProperty { AllowedOrigins = new string[] { "*" }, AllowedMethods = new string[] { "GET" }, } } } });
Go

在 Go 中,这些类型是使用 L1 构造的名称、下划线和属性名称命名的。例如,a 的可选属性CfnBucket需要一个CorsConfiguration类型的CfnBucket_CorsConfigurationProperty封装器。这里我们在一个CfnBucket实例CorsConfiguration上定义。

awss3.NewCfnBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.CfnBucketProps{ BucketName: jsii.String("amzn-s3-demo-bucket"), CorsConfiguration: &awss3.CfnBucket_CorsConfigurationProperty{ CorsRules: []awss3.CorsRule{ awss3.CorsRule{ AllowedOrigins: jsii.Strings("*"), AllowedMethods: &[]awss3.HttpMethods{"GET"}, }, }, }, })
重要

您不能将 L2 属性类型与 L1 构造一起使用,反之亦然。使用 L1 构造时,请务必使用为正在使用的 L1 构造定义的类型。不要使用其他 L1 构造中的类型(有些可能具有相同的名称,但类型不同)。

目前,我们的一些特定于语言的API参考文献在 L1 属性类型的路径中存在错误,或者根本没有记录这些类。我们希望尽快解决这个问题。同时,请记住,此类类型始终是与之一起使用的 L1 构造的内部类。

使用 L2 构造

在以下示例中,我们通过从 BucketL2 构造中创建对象来定义 Amazon S3 存储桶:

TypeScript
import * as s3 from 'aws-cdk-lib/aws-s3'; // "this" is HelloCdkStack new s3.Bucket(this, 'MyFirstBucket', { versioned: true });
JavaScript
const s3 = require('aws-cdk-lib/aws-s3'); // "this" is HelloCdkStack new s3.Bucket(this, 'MyFirstBucket', { versioned: true });
Python
import aws_cdk.aws_s3 as s3 # "self" is HelloCdkStack s3.Bucket(self, "MyFirstBucket", versioned=True)
Java
import software.amazon.awscdk.services.s3.*; public class HelloCdkStack extends Stack { public HelloCdkStack(final Construct scope, final String id) { this(scope, id, null); } public HelloCdkStack(final Construct scope, final String id, final StackProps props) { super(scope, id, props); Bucket.Builder.create(this, "MyFirstBucket") .versioned(true).build(); } }
C#
using Amazon.CDK.AWS.S3; // "this" is HelloCdkStack new Bucket(this, "MyFirstBucket", new BucketProps { Versioned = true });
Go
import ( "github.com/aws/aws-cdk-go/awscdk/v2/awss3" "github.com/aws/jsii-runtime-go" ) // stack is HelloCdkStack awss3.NewBucket(stack, jsii.String("MyFirstBucket"), &awss3.BucketProps{ Versioned: jsii.Bool(true), })>

MyFirstBucket不是 AWS CloudFormation 创建的存储桶的名称。它是在您的CDK应用程序上下文中赋予新构造的逻辑标识符。该physicalName值将用于命名 AWS CloudFormation 资源。

使用第三方构造

Constr@@ uct Hub 是一种资源 AWS,可帮助您发现来自第三方和开源CDK社区的其他构造。

编写你自己的构造

除了使用现有构造之外,你还可以编写自己的构造,让任何人在自己的应用程序中使用它们。中的所有构造都是相等的。 AWS CDK构造库中的 AWS 构造与通过以下方式发布的第三方库中的构造相同 NPM, Maven,或 PyPI。 发布到公司内部软件包存储库的构造也将以同样的方式处理。

要声明新构造,请在constructs包中创建一个扩展 C on struct 基类的类,然后按照初始化器参数的模式进行操作。

以下示例说明如何声明代表 Amazon S3 存储桶的结构。每当有人向其上传文件时,S3 存储桶都会发送一条亚马逊简单通知服务 (AmazonSNS) 通知。

TypeScript
export interface NotifyingBucketProps { prefix?: string; } export class NotifyingBucket extends Construct { constructor(scope: Construct, id: string, props: NotifyingBucketProps = {}) { super(scope, id); const bucket = new s3.Bucket(this, 'bucket'); const topic = new sns.Topic(this, 'topic'); bucket.addObjectCreatedNotification(new s3notify.SnsDestination(topic), { prefix: props.prefix }); } }
JavaScript
class NotifyingBucket extends Construct { constructor(scope, id, props = {}) { super(scope, id); const bucket = new s3.Bucket(this, 'bucket'); const topic = new sns.Topic(this, 'topic'); bucket.addObjectCreatedNotification(new s3notify.SnsDestination(topic), { prefix: props.prefix }); } } module.exports = { NotifyingBucket }
Python
class NotifyingBucket(Construct): def __init__(self, scope: Construct, id: str, *, prefix=None): super().__init__(scope, id) bucket = s3.Bucket(self, "bucket") topic = sns.Topic(self, "topic") bucket.add_object_created_notification(s3notify.SnsDestination(topic), s3.NotificationKeyFilter(prefix=prefix))
Java
public class NotifyingBucket extends Construct { public NotifyingBucket(final Construct scope, final String id) { this(scope, id, null, null); } public NotifyingBucket(final Construct scope, final String id, final BucketProps props) { this(scope, id, props, null); } public NotifyingBucket(final Construct scope, final String id, final String prefix) { this(scope, id, null, prefix); } public NotifyingBucket(final Construct scope, final String id, final BucketProps props, final String prefix) { super(scope, id); Bucket bucket = new Bucket(this, "bucket"); Topic topic = new Topic(this, "topic"); if (prefix != null) bucket.addObjectCreatedNotification(new SnsDestination(topic), NotificationKeyFilter.builder().prefix(prefix).build()); } }
C#
public class NotifyingBucketProps : BucketProps { public string Prefix { get; set; } } public class NotifyingBucket : Construct { public NotifyingBucket(Construct scope, string id, NotifyingBucketProps props = null) : base(scope, id) { var bucket = new Bucket(this, "bucket"); var topic = new Topic(this, "topic"); bucket.AddObjectCreatedNotification(new SnsDestination(topic), new NotificationKeyFilter { Prefix = props?.Prefix }); } }
Go
type NotifyingBucketProps struct { awss3.BucketProps Prefix *string } func NewNotifyingBucket(scope constructs.Construct, id *string, props *NotifyingBucketProps) awss3.Bucket { var bucket awss3.Bucket if props == nil { bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), nil) } else { bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), &props.BucketProps) } topic := awssns.NewTopic(scope, jsii.String(*id+"Topic"), nil) if props == nil { bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic)) } else { bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic), &awss3.NotificationKeyFilter{ Prefix: props.Prefix, }) } return bucket }
注意

我们的NotifyingBucket构造不是继承自Bucket而是继承自Construct。我们使用组合而不是继承来将 Amazon S3 存储桶和亚马逊SNS主题捆绑在一起。通常,在开发 AWS CDK 构造时,组合优先于继承。

NotifyingBucket构造函数具有典型的构造签名:scopeid、和props。最后一个参数是可选的(获取默认值{}),因为所有道具都是可选的。props(基Construct类不带props参数。) 例如,你可以在你的应用程序中定义这个构造的实例props,而不必这样做:

TypeScript
new NotifyingBucket(this, 'MyNotifyingBucket');
JavaScript
new NotifyingBucket(this, 'MyNotifyingBucket');
Python
NotifyingBucket(self, "MyNotifyingBucket")
Java
new NotifyingBucket(this, "MyNotifyingBucket");
C#
new NotifyingBucket(this, "MyNotifyingBucket");
Go
NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), nil)

或者你可以使用props(在 Java 中,一个附加参数)来指定要筛选的路径前缀,例如:

TypeScript
new NotifyingBucket(this, 'MyNotifyingBucket', { prefix: 'images/' });
JavaScript
new NotifyingBucket(this, 'MyNotifyingBucket', { prefix: 'images/' });
Python
NotifyingBucket(self, "MyNotifyingBucket", prefix="images/")
Java
new NotifyingBucket(this, "MyNotifyingBucket", "/images");
C#
new NotifyingBucket(this, "MyNotifyingBucket", new NotifyingBucketProps { Prefix = "/images" });
Go
NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), &NotifyingBucketProps{ Prefix: jsii.String("images/"), })

通常,您还需要在构造中公开一些属性或方法。在你的构造后面隐藏一个话题并不是很有用,因为你的构造的用户无法订阅它。添加topic属性允许使用者访问内部主题,如以下示例所示:

TypeScript
export class NotifyingBucket extends Construct { public readonly topic: sns.Topic; constructor(scope: Construct, id: string, props: NotifyingBucketProps) { super(scope, id); const bucket = new s3.Bucket(this, 'bucket'); this.topic = new sns.Topic(this, 'topic'); bucket.addObjectCreatedNotification(new s3notify.SnsDestination(this.topic), { prefix: props.prefix }); } }
JavaScript
class NotifyingBucket extends Construct { constructor(scope, id, props) { super(scope, id); const bucket = new s3.Bucket(this, 'bucket'); this.topic = new sns.Topic(this, 'topic'); bucket.addObjectCreatedNotification(new s3notify.SnsDestination(this.topic), { prefix: props.prefix }); } } module.exports = { NotifyingBucket };
Python
class NotifyingBucket(Construct): def __init__(self, scope: Construct, id: str, *, prefix=None, **kwargs): super().__init__(scope, id) bucket = s3.Bucket(self, "bucket") self.topic = sns.Topic(self, "topic") bucket.add_object_created_notification(s3notify.SnsDestination(self.topic), s3.NotificationKeyFilter(prefix=prefix))
Java
public class NotifyingBucket extends Construct { public Topic topic = null; public NotifyingBucket(final Construct scope, final String id) { this(scope, id, null, null); } public NotifyingBucket(final Construct scope, final String id, final BucketProps props) { this(scope, id, props, null); } public NotifyingBucket(final Construct scope, final String id, final String prefix) { this(scope, id, null, prefix); } public NotifyingBucket(final Construct scope, final String id, final BucketProps props, final String prefix) { super(scope, id); Bucket bucket = new Bucket(this, "bucket"); topic = new Topic(this, "topic"); if (prefix != null) bucket.addObjectCreatedNotification(new SnsDestination(topic), NotificationKeyFilter.builder().prefix(prefix).build()); } }
C#
public class NotifyingBucket : Construct { public readonly Topic topic; public NotifyingBucket(Construct scope, string id, NotifyingBucketProps props = null) : base(scope, id) { var bucket = new Bucket(this, "bucket"); topic = new Topic(this, "topic"); bucket.AddObjectCreatedNotification(new SnsDestination(topic), new NotificationKeyFilter { Prefix = props?.Prefix }); } }
Go

要在 Go 中做到这一点,我们需要一点额外的管道。我们的原始NewNotifyingBucket函数返回了一个awss3.Bucket. 我们需要通过创建NotifyingBucket结构Bucket来扩展以包含topic成员。然后,我们的函数将返回此类型。

type NotifyingBucket struct { awss3.Bucket topic awssns.Topic } func NewNotifyingBucket(scope constructs.Construct, id *string, props *NotifyingBucketProps) NotifyingBucket { var bucket awss3.Bucket if props == nil { bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), nil) } else { bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), &props.BucketProps) } topic := awssns.NewTopic(scope, jsii.String(*id+"Topic"), nil) if props == nil { bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic)) } else { bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic), &awss3.NotificationKeyFilter{ Prefix: props.Prefix, }) } var nbucket NotifyingBucket nbucket.Bucket = bucket nbucket.topic = topic return nbucket }

现在,消费者可以订阅该主题,例如:

TypeScript
const queue = new sqs.Queue(this, 'NewImagesQueue'); const images = new NotifyingBucket(this, '/images'); images.topic.addSubscription(new sns_sub.SqsSubscription(queue));
JavaScript
const queue = new sqs.Queue(this, 'NewImagesQueue'); const images = new NotifyingBucket(this, '/images'); images.topic.addSubscription(new sns_sub.SqsSubscription(queue));
Python
queue = sqs.Queue(self, "NewImagesQueue") images = NotifyingBucket(self, prefix="Images") images.topic.add_subscription(sns_sub.SqsSubscription(queue))
Java
NotifyingBucket images = new NotifyingBucket(this, "MyNotifyingBucket", "/images"); images.topic.addSubscription(new SqsSubscription(queue));
C#
var queue = new Queue(this, "NewImagesQueue"); var images = new NotifyingBucket(this, "MyNotifyingBucket", new NotifyingBucketProps { Prefix = "/images" }); images.topic.AddSubscription(new SqsSubscription(queue));
Go
queue := awssqs.NewQueue(stack, jsii.String("NewImagesQueue"), nil) images := NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), &NotifyingBucketProps{ Prefix: jsii.String("/images"), }) images.topic.AddSubscription(awssnssubscriptions.NewSqsSubscription(queue, nil))

了解更多

以下视频全面概述了CDK构造,并说明了如何在CDK应用程序中使用它们。