Esta es la segunda versión de la Guía para desarrolladores de AWS CDK. La primera versión del CDK pasó a la etapa de mantenimiento el 1.° de junio de 2022 y no cuenta con soporte desde el 1.° de junio de 2023.
Constructos AWS CDK
Los constructos son los componentes básicos de las aplicaciones AWS Cloud Development Kit (AWS CDK). Un constructo es un componente dentro de la aplicación que representa uno o más recursos AWS CloudFormation y su configuración. Para crear la aplicación, pieza por pieza, se importan y configuran constructos.
Importación y uso de constructos
Los constructos son clases que se importan a las aplicaciones de CDK desde la Biblioteca de constructos de AWS. También puede crear y distribuir sus propios constructos o utilizar constructos creados por desarrolladores externos.
Los constructos forman parte del modelo de programación de constructos (CPM). Están disponibles para su uso con otras herramientas, como CDK para Terraform (CDKtf), CDK para (CDK8s) Kubernetes y Projen.
Muchos terceros también han publicado constructos compatibles con AWS CDK. Visite Hub de constructos para explorar el ecosistema de socios de constructos de AWS CDK.
Niveles de constructos
Los constructos de la Biblioteca de constructos de AWS se clasifican en tres niveles. Cada nivel ofrece un nivel de abstracción cada vez mayor. Cuanto mayor sea la abstracción, más fácil será la configuración y se requerirá menos experiencia. Cuanto menor sea la abstracción, mayor será la personalización disponible, lo que requerirá más experiencia.
- Constructos de nivel 1 (L1)
-
Los constructos L1, también conocidos como recursos CFN, son los constructos de nivel más bajo y no ofrecen abstracción. Cada constructo L1 se asigna directamente a un único recurso AWS CloudFormation. Con los constructos L1, se importa un constructo que representa un recurso AWS CloudFormation específico. A continuación, usted define las propiedades del recurso en la instancia del constructo.
Los constructos L1 son ideales para utilizarlos cuando conoce AWS CloudFormation y necesita un control total sobre la definición de las propiedades de los recursos de AWS.
En la Biblioteca de constructos de AWS, los constructos L1 se nombran empezando por Cfn
, seguido de un identificador para el recurso AWS CloudFormation que representan. Por ejemplo, el constructo CfnBucket
es un constructo L1 que representa un recurso AWS::S3::Bucket
de AWS CloudFormation.
Los constructos L1 se generan a partir de la especificación del recurso AWS CloudFormation. Si existe un recurso en AWS CloudFormation, estará disponible en el AWS CDK como un constructo L1. Los nuevos recursos o propiedades pueden tardar hasta una semana en estar disponibles en la Biblioteca de constructos de AWS. Para obtener más información, consulte Referencia de tipos de propiedades de recursos de AWS en la Guía del usuario de AWS CloudFormation.
- Constructos de nivel 2 (L2)
-
Los constructos L2, también conocidos como constructos seleccionados, son desarrollados cuidadosamente por el equipo de CDK y, por lo general, son el tipo de constructo más utilizado. Los constructos L2 se asignan directamente a recursos AWS CloudFormation individuales, de forma similar a los constructos L1. En comparación con los constructos L1, los constructos L2 proporcionan una abstracción de alto nivel a través de una API intuitiva basada en la intención. Los constructos de nivel 2 incluyen configuraciones de propiedades predeterminadas y sensatas, políticas de seguridad recomendadas y generan gran parte del código reutilizable y de la lógica necesaria para el usuario.
Los constructos de nivel 2 también proporcionan métodos auxiliares para la mayoría de los recursos, que facilitan y agilizan la definición de propiedades, permisos, interacciones entre recursos basadas en eventos, etc.
La clase s3.Bucket
es un ejemplo de constructo L2 para un recurso de bucket de Amazon Simple Storage Service (Amazon S3).
La Biblioteca de constructos de AWS contiene constructos L2 designados como estables y listos para su uso en producción. En el caso de los constructos de nivel 2 en fase de desarrollo, se denominan experimentales y se ofrecen en un módulo independiente.
- Constructos de nivel 3 (L3)
-
Los constructos L3, también conocidos como patrones, son el nivel más alto de abstracción. Cada constructo L3 puede contener un conjunto de recursos que están configurados para trabajar juntos a fin de realizar una tarea o un servicio específicos dentro de la aplicación. Los constructos L3 se utilizan para crear arquitecturas de AWS completas para casos de uso particulares de la aplicación.
Para proporcionar diseños de sistemas completos, o partes sustanciales de un sistema más grande, los constructos L3 ofrecen configuraciones de propiedades predeterminadas y fundamentadas. Se basan en un enfoque particular para resolver un problema y proporcionar una solución. Con los constructos L3, puede crear y configurar varios recursos rápidamente, con la menor cantidad de entrada y código.
La clase ecsPatterns.ApplicationLoadBalancedFargateService
es un ejemplo de un constructo de nivel 3 que representa un servicio AWS Fargate que se ejecuta en un clúster de Amazon Elastic Container Service (Amazon ECS) y está dirigido por un equilibrador de carga de aplicación.
Al igual que los constructos L2, los constructos L3 que están listos para su uso en producción se incluyen en la Biblioteca de constructos de AWS. Los que están en desarrollo se ofrecen en módulos separados.
Definición de constructos
Composición
La composición es el patrón clave para definir abstracciones de alto nivel a través de constructos. Un constructo de alto nivel puede estar compuesto por cualquier número de constructos de nivel inferior. Desde una perspectiva ascendente, se utilizan constructos para organizar los recursos de AWS individuales que se desean implementar. Usted usa las abstracciones que sean convenientes para su propósito, con tantos niveles como necesite.
Con la composición, define componentes reutilizables y los comparte como cualquier otro código. Por ejemplo, un equipo puede definir un constructo que implemente las prácticas recomendadas de la empresa para una tabla de Amazon DynamoDB, incluidas las copias de seguridad, la replicación global, el escalado automático y la supervisión. El equipo puede compartir el constructo internamente con otros equipos o públicamente.
Los equipos pueden usar constructos como cualquier otro paquete de biblioteca. Cuando se actualiza la biblioteca, los desarrolladores tienen acceso a las mejoras y correcciones de errores de la nueva versión, de forma similar a cualquier otra biblioteca de códigos.
Inicialización
Los constructos se implementan en clases que amplían la clase base Construct
. Para definir un constructo, se crea una instancia de la clase. Todos los constructos toman tres parámetros cuando se inicializan:
-
ámbito: el principal o el propietario del constructo. Puede ser una pila u otro constructo. El ámbito determina el lugar que ocupa el constructo en el árbol de constructos. Por lo general, debería pasar this
(self
en Python), que representa el objeto actual, para el ámbito.
-
identificador: un identificador que debe ser único en este ámbito. El identificador sirve como un espacio de nombres para todo lo que se define en el constructo. Se utiliza para generar identificadores únicos, como nombres de recursos e identificadores AWS CloudFormation lógicos.
Los identificadores solo deben ser únicos dentro de un ámbito. Esto le permite crear instancias de los constructos y reutilizarlas sin preocuparse por los constructo e identificadores que puedan contener, y permite componer los constructos en abstracciones de nivel superior. Además, los ámbitos permiten hacer referencia a grupos de constructos de una sola vez. Algunos ejemplos son el etiquetado o la especificación de dónde se implementarán los constructos.
-
props: un conjunto de propiedades o argumentos de palabras clave, según el idioma, que definen la configuración inicial del constructo. Los constructos de nivel superior proporcionan más valores predeterminados y, si todos los elementos prop son opcionales, puede omitir el parámetro props por completo.
Configuración
La mayoría de los constructos aceptan props
como tercer argumento (o en Python, argumentos de palabras clave), una colección de nombre/valor que define la configuración del constructo. El siguiente ejemplo define un bucket con el cifrado AWS Key Management Service (AWS KMS) y el alojamiento de sitios web estáticos habilitados. Como no especifica explícitamente una clave de cifrado, el constructo Bucket
define un nuevo kms.Key
y lo asocia al bucket.
- 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"),
})
Interacción con constructos
Los constructos son clases que amplían la clase base constructo base. Tras crear una instancia de un constructo, el objeto del constructo expone un conjunto de métodos y propiedades que le permiten interactuar con el constructo y transmitirlo como referencia a otras partes del sistema.
El marco AWS CDK no impone ninguna restricción a las API de los constructos. Los autores pueden definir cualquier API que deseen. Sin embargo, los constructos de AWS que se incluyen en la Biblioteca de constructos de AWS, por ejemplos3.Bucket
, siguen pautas y patrones comunes. Esto proporciona una experiencia coherente en todos los recursos de AWS.
La mayoría de los constructos de AWS tienen un conjunto de métodos de concesión que puede usar para conceder permisos AWS Identity and Access Management (de IAM) sobre ese constructo a una entidad principal. En el siguiente ejemplo se concede al grupo de IAM el permiso data-science
para leer del bucket raw-data
de Amazon S3.
- 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)
Otro patrón común es que los constructos de AWS establecen uno de los atributos del recurso a partir de datos suministrados en otros lugares. Los atributos pueden incluir nombres de recursos de Amazon (ARN), nombres o URL.
El siguiente código define una función de AWS Lambda y la asocia a una cola de Amazon Simple Queue Service (Amazon SQS) a través de la URL de la cola en una variable de entorno.
- 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()),
},
})
Para obtener información sobre los patrones de API más comunes de la Biblioteca de constructos de AWS, consulte Recursos y el AWS CDK.
El constructo de la aplicación y la pila
Las clases App
y Stack
de la Biblioteca de constructos de AWS son constructos únicos. En comparación con otros constructos, no configuran los recursos de AWS por sí mismas. En cambio, se utilizan para proporcionar contexto para los otros constructos. Debe definirse todos los constructos que representan recursos de AWS deben definirse directa o indirectamente en el ámbito de un constructo Stack
. Los constructos Stack
se definen en el ámbito de un constructo App
.
Para obtener más información sobre las aplicaciones de CDK, consulte Aplicaciones de AWS CDK. Para obtener más información sobre las pilas de CDK, consulte Introducción a las pilas de AWS CDK.
En el siguiente ejemplo se define una aplicación con una sola pila. Dentro de la pila, se utiliza un constructo L2 para configurar un recurso de bucket de 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
-
Pila definida en el archivo 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();
}
}
Aplicación definida en el archivo 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
}
Trabajo con constructos
Trabajo con constructos L1
Los constructos L1 asignan directamente a los recursos AWS CloudFormation individuales. Usted debe brindar la configuración solicitada del recurso.
En este ejemplo, creamos un objeto bucket
utilizando el constructo L1 CfnBucket
:
- 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"),
})
Las propiedades del constructo que no sean simples booleanos, cadenas, números o contenedores se gestionan de forma diferente en los lenguajes compatibles.
- 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
-
En Python, estas propiedades se representan mediante tipos definidos como clases internas del constructo L1. Por ejemplo, la propiedad opcional cors_configuration
de un CfnBucket
requiere un contenedor de tipo CfnBucket.CorsConfigurationProperty
. Aquí estamos definiendo cors_configuration
en una instancia CfnBucket
.
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
-
En Java, estas propiedades se representan mediante tipos definidos como clases internas del constructo L1. Por ejemplo, la propiedad opcional corsConfiguration
de un CfnBucket
requiere un contenedor de tipo CfnBucket.CorsConfigurationProperty
. Aquí estamos definiendo corsConfiguration
en una instancia CfnBucket
.
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#
-
En C#, estas propiedades se representan mediante tipos definidos como clases internas del constructo L1. Por ejemplo, la propiedad opcional CorsConfiguration
de un CfnBucket
requiere un contenedor de tipo CfnBucket.CorsConfigurationProperty
. Aquí estamos definiendo CorsConfiguration
en una instancia CfnBucket
.
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
-
En Go, estos tipos se nombran con el nombre del constructo L1, un guion bajo y el nombre de la propiedad. Por ejemplo, la propiedad opcional CorsConfiguration
de un CfnBucket
requiere un contenedor de tipo CfnBucket_CorsConfigurationProperty
. Aquí estamos definiendo CorsConfiguration
en una instancia CfnBucket
.
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"},
},
},
},
})
No puede usar tipos de propiedades L2 con constructos L1, o viceversa. Cuando trabaje con constructos L1, utilice siempre los tipos definidos para el constructo L1 que utilice. No utilice tipos de otros constructos L1 (algunos pueden tener el mismo nombre, pero no son del mismo tipo).
Actualmente, algunas de nuestras referencias a la API específicas del idioma contienen errores en las rutas de los tipos de propiedades del nivel 1 o no documentan estas clases en absoluto. Esperamos solucionar este problema pronto. Mientras tanto, recuerde que estos tipos son siempre clases internas del constructo L1 con el que se utilizan.
Trabajo con constructos L2
En el siguiente ejemplo, definimos un bucket de Amazon S3 mediante la creación de un objeto a partir del constructo L2 Bucket
:
- 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
no es el nombre del bucket que AWS CloudFormation crea. Es un identificador lógico que se asigna al nuevo constructo en el contexto de la aplicación CDK. El valor physicalName se utilizará para asignar un nombre al recurso AWS CloudFormation.
Trabajo con constructos de terceros
El Hub de constructos es un recurso que lo ayuda a descubrir otros constructos de AWS, de terceros y de la comunidad de CDK de código abierto.
Escritura de sus propios constructos
Además de usar los constructos existentes, también puede escribir los suyos propios y permitir que cualquiera los use en sus aplicaciones. Todos los constructos son iguales en el AWS CDK. Los constructos de la Biblioteca de constructos de AWS se tratan de la misma manera que un constructo de una biblioteca de terceros publicada mediante NPM, Maven, o PyPI. Los constructos publicados en el repositorio de paquetes interno de su empresa también se tratan del mismo modo.
Para declarar un nuevo constructo, cree una clase que amplíe la clase base de Constructo en el paquete constructs
y, a continuación, siga el patrón de los argumentos del inicializador.
En el siguiente ejemplo se muestra cómo indicar un constructo que representa un bucket de Amazon S3. El bucket S3 envía una notificación de Amazon Simple Notification Service (Amazon SNS) cada vez que alguien carga un archivo en él.
- 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
}
Nuestro constructo NotifyingBucket
no hereda de Bucket
sino de Construct
. Utilizamos la composición, no la herencia, con el fin de agrupar un bucket de Amazon S3 y un tema de Amazon SNS. En general, se prefiere la composición a la herencia a la hora de desarrollar construcciones de AWS CDK.
El constructo NotifyingBucket
tiene una firma de constructo típica: scope
, id
y props
. El último argumento, props
, es opcional (obtiene el valor predeterminado {}
) porque todos los accesorios son opcionales. (La clase base Construct
no acepta ningún argumento props
). Podría definir una instancia de este constructo en su aplicación sin props
, por ejemplo:
- 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)
O puede usar props
(en Java, un parámetro adicional) para especificar el prefijo de ruta por el que desea filtrar, por ejemplo:
- 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/"),
})
Por lo general, también querrá exponer algunas propiedades o métodos en sus constructos. No es muy útil tener un tema oculto detrás del constructo, ya que los usuarios del constructo no pueden suscribirse a ella. Agregar una propiedad topic
permite a los consumidores acceder al tema interno, tal y como se muestra en el siguiente ejemplo:
- 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
-
Para hacer esto en Go, necesitaremos más operaciones. Nuestra función NewNotifyingBucket
original devolvió un awss3.Bucket
. Tendremos que ampliar Bucket
para incluir un miembro topic
mediante la creación de una estructura NotifyingBucket
. Nuestra función devolverá entonces este tipo.
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
}
Ahora, los consumidores pueden suscribirse al tema, por ejemplo:
- 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))
Más información
El siguiente video ofrece una visión general completa de los constructos de CDK y explica cómo utilizarlas en sus aplicaciones de CDK.