

Esta es la guía para desarrolladores de AWS CDK v2. 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.

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# Conozca los AWS conceptos básicos de CDK
<a name="core-concepts"></a>

Conozca los conceptos básicos del AWS Cloud Development Kit (AWS CDK).

## AWS CDK y IaC
<a name="concepts-iac"></a>

El AWS CDK es un marco de código abierto que puede usar para administrar su AWS infraestructura mediante código. Este enfoque se conoce como *infraestructura como código (IaC)*. Cuando administra y aprovisiona su infraestructura como código, trata su infraestructura del mismo modo que los desarrolladores tratan el código. Esto ofrece muchos beneficios, como el control de versiones y la escalabilidad. Para obtener más información acerca de la IaC, consulte [¿Qué es la infraestructura como código?](https://aws.amazon.com/what-is/iac/) 

## AWS CDK y AWS CloudFormation
<a name="concepts-cfn"></a>

El AWS CDK está estrechamente integrado con. AWS CloudFormation AWS CloudFormation es un servicio totalmente gestionado que puede utilizar para gestionar y aprovisionar su infraestructura. AWS Con AWS CloudFormation él, puede definir su infraestructura en plantillas y desplegarlas en ellas AWS CloudFormation. A continuación, el AWS CloudFormation servicio aprovisiona la infraestructura de acuerdo con la configuración definida en las plantillas.

 AWS CloudFormation las plantillas son *declarativas*, lo que significa que declaran el estado o resultado deseado de su infraestructura. *Con JSON o YAML, declaras tu AWS infraestructura definiendo AWS *los recursos* y las propiedades.* Los recursos representan los numerosos servicios AWS y las propiedades representan la configuración deseada de dichos servicios. Al implementar la plantilla en AWS CloudFormation, los recursos y sus propiedades configuradas se aprovisionan tal y como se describe en la plantilla.

Con el AWS CDK, puede administrar su infraestructura de *forma imperativa* mediante lenguajes de programación de uso general. En lugar de solo definir el estado deseado de forma declarativa, puede definir la lógica o la secuencia necesarias para alcanzar el estado deseado. Por ejemplo, puede utilizar instrucciones `if` o bucles condicionales que determinen cómo alcanzar un estado final deseado para su infraestructura.

La infraestructura creada con el AWS CDK finalmente se traduce o se *sintetiza* en AWS CloudFormation plantillas y se implementa mediante el servicio. AWS CloudFormation Por lo tanto, si bien la AWS CDK ofrece un enfoque diferente para crear su infraestructura, usted seguirá beneficiándose de ello AWS CloudFormation, como un amplio soporte para la configuración de los AWS recursos y unos procesos de implementación sólidos.

Para obtener más información AWS CloudFormation, consulte [¿Qué es? AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html) en la *Guía AWS CloudFormation del usuario*.

## AWS CDK y abstracciones
<a name="concepts-abstractions"></a>

Con AWS CloudFormation, debe definir cada detalle de cómo se configuran sus recursos. Esto le brinda la ventaja de tener un control total sobre su infraestructura. Sin embargo, esto requiere que aprenda, comprenda y cree plantillas sólidas que contengan los detalles de configuración de los recursos y las relaciones entre los recursos, como los permisos y las interacciones basadas en eventos.

Con la AWS CDK, puede tener el mismo control sobre las configuraciones de sus recursos. Sin embargo, el AWS CDK también ofrece potentes abstracciones, que pueden acelerar y simplificar el proceso de desarrollo de la infraestructura. Por ejemplo, el AWS CDK incluye construcciones que proporcionan configuraciones predeterminadas razonables y métodos auxiliares que generan código repetitivo para usted. La AWS CDK también ofrece herramientas, como la interfaz de línea de comandos AWS CDK (AWS CDK CLI), que realizan acciones de administración de la infraestructura por usted.

## Obtenga más información sobre los conceptos básicos de la CDK AWS
<a name="concepts-learn"></a><a name="concepts-learn-interact"></a>

 **Interactuar con el CDK AWS **   
Cuando lo utilice con la AWS CDK, interactuará principalmente con la biblioteca AWS Construct y la AWS CLI de la CDK.<a name="concepts-learn-develop"></a>

 **Desarrollando con la CDK AWS **   
El AWS CDK se puede escribir en cualquier lenguaje de [programación compatible](languages.md). Comienza con un [proyecto de CDK](projects.md), que contiene una estructura de carpetas y archivos, incluidos los [activos](assets.md). Dentro del proyecto, crea una [aplicación de CDK](apps.md). Dentro de la aplicación, se define una [pila](stacks.md), que representa directamente una CloudFormation pila. Dentro de la pila, se definen AWS los recursos y las propiedades mediante [componentes fijos.](constructs.md)<a name="concepts-learn-deploy"></a>

 **Implementación con el CDK AWS **   
Las aplicaciones de CDK se implementan en un [entorno](environments.md) de AWS . Antes de la implementación, debe llevar a cabo un [arranque](bootstrapping.md) único para preparar el entorno.<a name="concepts-learn-more"></a>

 **Más información**   
Para obtener más información sobre los conceptos básicos del AWS CDK, consulte los temas de esta sección.

# Lenguajes de programación admitidos para AWS CDK
<a name="languages"></a>

AWS Cloud Development Kit (AWS CDK) tiene una compatibilidad de primera clase para los siguientes lenguajes de programación y de uso general:
+ TypeScript
+ JavaScript
+ Python
+ Java
+ C\$1
+  Go 

En teoría, también se pueden utilizar otros lenguajes JVM, .NET y CLR, pero no ofrecemos compatibilidad oficial en este momento.

AWS CDK está desarrollado en un idioma, TypeScript. Para admitir los otros lenguajes, AWS CDK utiliza una herramienta llamada [JSII](https://github.com/aws/jsii) para generar enlaces lingüísticos.

Intentamos ofrecer las convenciones habituales de cada idioma para que el desarrollo de AWS CDK sea lo más natural e intuitivo posible. Por ejemplo, distribuimos los módulos de la Biblioteca de constructos de AWS utilizando el repositorio estándar de su idioma preferido y usted los instala utilizando el administrador de paquetes estándar del idioma. Los métodos y las propiedades también se nombran según los patrones de nomenclatura recomendados en su idioma.

A continuación, se muestran algunos ejemplos de códigos:

**Example**  

```
const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', {
  bucketName: 'amzn-s3-demo-bucket',
  versioned: true,
  websiteRedirect: {hostName: 'aws.amazon.com'}});
```

```
const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', {
  bucketName: 'amzn-s3-demo-bucket',
  versioned: true,
  websiteRedirect: {hostName: 'aws.amazon.com'}});
```

```
bucket = s3.Bucket("amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket", versioned=True,
            website_redirect=s3.RedirectTarget(host_name="aws.amazon.com"))
```

```
Bucket bucket = Bucket.Builder.create(self, "amzn-s3-demo-bucket")
                      .bucketName("amzn-s3-demo-bucket")
                      .versioned(true)
                      .websiteRedirect(new RedirectTarget.Builder()
                          .hostName("aws.amazon.com").build())
                      .build();
```

```
var bucket = new Bucket(this, "amzn-s3-demo-bucket", new BucketProps {
                      BucketName = "amzn-s3-demo-bucket",
                      Versioned  = true,
                      WebsiteRedirect = new RedirectTarget {
                              HostName = "aws.amazon.com"
                      }});
```

```
bucket := awss3.NewBucket(scope, jsii.String("amzn-s3-demo-bucket"), &awss3.BucketProps {
	BucketName: jsii.String("amzn-s3-demo-bucket"),
	Versioned: jsii.Bool(true),
	WebsiteRedirect: &awss3.RedirectTarget {
		HostName: jsii.String("aws.amazon.com"),
	},
})
```

**nota**  
Estos fragmentos de código están destinados únicamente a fines ilustrativos. Están incompletos y no se ejecutarán tal como están.

La Biblioteca de constructos de AWS se distribuye utilizando las herramientas de administración de paquetes estándar de cada idioma, lo que incluye NPM, PyPi, Maven y NuGet. También ofrecemos una versión de la [referencia de la API de AWS CDK](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html) para cada idioma.

Para ayudarlo a usar AWS CDK en su idioma preferido, esta guía incluye los siguientes temas sobre los idiomas compatibles:
+  [Utilización del AWS CDK en TypeScript](work-with-cdk-typescript.md) 
+  [Utilización del AWS CDK en JavaScript](work-with-cdk-javascript.md) 
+  [Utilización del AWS CDK en Python](work-with-cdk-python.md) 
+  [Utilización del AWS CDK en Java](work-with-cdk-java.md) 
+  [Utilización del CDK AWS en C\$1](work-with-cdk-csharp.md) 
+  [Utilización del AWS CDK en Go](work-with-cdk-go.md) 

TypeScript fue el primer idioma admitido por AWS CDK y gran parte del código de ejemplo de AWS CDK está escrito en TypeScript. Esta guía incluye un tema específico para mostrar cómo adaptar el código AWS CDK de TypeScript para su uso con los demás lenguajes compatibles. Consulte [Comparación de AWS CDK en TypeScript](work-with.md#work-with-cdk-compare) con otros lenguajes para obtener más información.

# Las bibliotecas de AWS CDK
<a name="libraries"></a>

Obtenga información sobre las bibliotecas principales que utilizará con AWS Cloud Development Kit (AWS CDK).

## La biblioteca de AWS CDK
<a name="libraries-cdk"></a>

La Biblioteca de AWS CDK, también conocida como `aws-cdk-lib`, es la biblioteca principal que utilizará para desarrollar aplicaciones con AWS CDK. AWS está a cargo de su desarrollo y mantenimiento. Esta biblioteca contiene clases básicas, como [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html) y [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html). También contiene las bibliotecas que utilizará para definir su infraestructura mediante constructos.

## La Biblioteca de constructos de AWS
<a name="libraries-construct"></a>

La Biblioteca de constructos de AWS forma parte de la biblioteca de AWS CDK. Contiene una recopilación de [constructos](constructs.md) desarrollados y mantenidos por AWS. Está organizado en varios módulos para cada servicio de AWS. Cada módulo incluye componentes fijos que puede utilizar para definir sus propiedades y recursos de AWS.

## La Biblioteca de constructos
<a name="libraries-constructs"></a>

La Biblioteca de constructos, conocida comúnmente como `constructs`, es una biblioteca para definir y componer los componentes de la infraestructura en la nube. Contiene la clase principal de [https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html), que representa el componente básico del constructo. Esta clase es la clase básica fundamental de todos los constructos de la Biblioteca de constructos de AWS. La Biblioteca de constructos es una biblioteca independiente de uso general que utilizan otras herramientas basadas en constructos, como *CDK para Terraform* y *CDK para Kubernetes*.

## Referencia de la API de AWS CDK
<a name="libraries-reference"></a>

La [referencia de la API de AWS CDK](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html) contiene la documentación de referencia oficial de la Biblioteca de AWS CDK, incluidas la Biblioteca de constructos de AWS y la Biblioteca de constructos. Se proporciona una versión de la referencia de la API para cada lenguaje de programación compatible.
+ Para ver la documentación de la Biblioteca de AWS CDK (`aws-cdk-lib`), consulte el [módulo aws-cdk-lib](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html).
+ La documentación de los constructos de la Biblioteca de constructos de AWS está organizada por el servicio de AWS en el siguiente formato: `aws-cdk-lib.<service>`. Por ejemplo, la documentación de constructos para Amazon Simple Storage Service (Amazon S3) se encuentra en el [módulo aws-cdk-lib.aws\$1s3](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3-readme.html).
+ Para ver la documentación de la Biblioteca de constructos, consulte el [módulo de constructos](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs-readme.html).

### Contribuya con la referencia de la API de AWS CDK
<a name="libraries-reference-contribute"></a>

El AWS CDK tiene código abierto y lo invitamos a que haga su aporte. Las contribuciones de la comunidad impactan positivamente en el AWS CDK y lo mejoran. Para obtener instrucciones sobre cómo contribuir específicamente con la documentación de referencia de la API de AWS CDK, consulte la [documentación](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md#documentation) en el *repositorio aws-cdk de GitHub*.

## Más información
<a name="libraries-learn"></a>

Para obtener instrucciones sobre la importación y el uso de la Biblioteca del CDK, consulte [Trabajar con la biblioteca de CDK](work-with.md).

# Proyectos de AWS CDK
<a name="projects"></a>

Un proyecto de AWS Cloud Development Kit (AWS CDK) representa los archivos y las carpetas que contienen el código del CDK. El contenido variará en función del lenguaje de programación.

Puede crear su proyecto de AWS CDK manualmente o con el comando de la interfaz de línea de comando `cdk init` de AWS (CLI de AWS CDK). En este tema, haremos referencia a la estructura del proyecto y a las convenciones de nomenclatura de los archivos y las carpetas que crea la CLI de AWS CDK. Puede personalizar y organizar sus proyectos de CDK para adaptarlos a sus necesidades.

**nota**  
La estructura del proyecto que crea la CLI de AWS CDK puede variar a lo largo del tiempo entre versiones.

## Archivos y carpetas universales
<a name="projects-universal"></a><a name="projects-universal-git"></a>

 `.git`   
Si tiene `git` instalado, la CLI del AWS CDK inicializa automáticamente un repositorio de Git para su proyecto. El directorio `.git` contiene información sobre el repositorio.<a name="projects-universal-gitignore"></a>

 `.gitignore`   
Archivo de texto que utiliza Git para especificar los archivos y las carpetas que se deben ignorar.<a name="projects-universal-readme"></a>

 `README.md`   
Archivo de texto que proporciona orientación básica e información importante para administrar el proyecto del AWS CDK. Modifique este archivo según sea necesario para documentar la información importante relacionada con el proyecto del CDK.<a name="projects-universal-cdk"></a>

 `cdk.json`   
Archivo de configuración para el AWS CDK. Este archivo proporciona instrucciones a la CLI del AWS CDK sobre cómo ejecutar la aplicación.

## Archivos y carpetas específicos del lenguaje
<a name="projects-specific"></a>

Los siguientes archivos y las carpetas son exclusivos de cada lenguaje de programación compatible.

**Example**  
El siguiente es un ejemplo de proyecto creado en el directorio `my-cdk-ts-project` mediante el comando `cdk init --language typescript`:  

```
my-cdk-ts-project
├── .git
├── .gitignore
├── .npmignore
├── README.md
├── bin
│   └── my-cdk-ts-project.ts
├── cdk.json
├── jest.config.js
├── lib
│   └── my-cdk-ts-project-stack.ts
├── node_modules
├── package-lock.json
├── package.json
├── test
│   └── my-cdk-ts-project.test.ts
└── tsconfig.json
```  
 `.npmignore`   
Archivo que especifica qué archivos y carpetas se deben ignorar cuando se publica un paquete en el registro `npm`. Este archivo es similar a los `.gitignore`, pero es específico de los paquetes `npm`.  
 `bin/my-cdk-ts-project.ts`   
El *archivo de la aplicación* define la aplicación de CDK. Los proyectos de CDK pueden contener uno o más archivos de aplicación. Los archivos de aplicación se almacenan en la carpeta `bin`.  
A continuación, se muestra un ejemplo de un archivo de aplicación básico que define una aplicación CDK:  

```
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { MyCdkTsProjectStack } from '../lib/my-cdk-ts-project-stack';

const app = new cdk.App();
new MyCdkTsProjectStack(app, 'MyCdkTsProjectStack');
```  
 `jest.config.js`   
Archivo de configuración para Jest. * Jest* es un marco de pruebas popular de JavaScript.  
 `lib/my-cdk-ts-project-stack.ts`   
El *archivo de pila* define la pila de CDK. Dentro de la pila, usted define los recursos y las propiedades de AWS mediante constructos.  
A continuación, se muestra un ejemplo de un archivo de pila básico que define una pila de CDK:  

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class MyCdkTsProjectStack extends cdk.Stack {
 constructor(scope: Construct, id: string, props?: cdk.StackProps) {
  super(scope, id, props);

  // code that defines your resources and properties go here
 }
}
```  
 `node_modules`   
Carpeta común en los proyectos Node.js que contienen dependencias para su proyecto.  
 `package-lock.json`   
Archivo de metadatos que funciona con el archivo `package.json` para administrar las versiones de las dependencias.  
 `package.json`   
Archivo de metadatos que se utiliza habitualmente en los proyectos Node.js. Este archivo contiene información sobre su proyecto de CDK, como el nombre del proyecto, las definiciones de los scripts, las dependencias y otra información de importación del proyecto.  
 `test/my-cdk-ts-project.test.ts`   
Se crea una carpeta de pruebas para organizar las pruebas del proyecto de CDK. También se crea un archivo de prueba de muestra.  
Puede escribir pruebas en TypeScript y utilizar Jest para compilar el código de TypeScript antes de ejecutarlas.  
 `tsconfig.json`   
Archivo de configuración que se utiliza en proyectos de TypeScript que especifica las opciones del compilador y la configuración del proyecto.
El siguiente es un ejemplo de proyecto creado en el directorio `my-cdk-js-project` mediante el comando `cdk init --language javascript`:  

```
my-cdk-js-project
├── .git
├── .gitignore
├── .npmignore
├── README.md
├── bin
│   └── my-cdk-js-project.js
├── cdk.json
├── jest.config.js
├── lib
│   └── my-cdk-js-project-stack.js
├── node_modules
├── package-lock.json
├── package.json
└── test
    └── my-cdk-js-project.test.js
```  
 `.npmignore`   
Archivo que especifica qué archivos y carpetas se deben ignorar cuando se publica un paquete en el registro `npm`. Este archivo es similar a los `.gitignore`, pero es específico de los paquetes `npm`.  
 `bin/my-cdk-js-project.js`   
El *archivo de la aplicación* define la aplicación del CDK. Los proyectos de CDK pueden contener uno o más archivos de aplicación. Los archivos de aplicación se almacenan en la carpeta `bin`.  
A continuación, se muestra un ejemplo de un archivo de aplicación básico que define una aplicación CDK:  

```
#!/usr/bin/env node

const cdk = require('aws-cdk-lib');
const { MyCdkJsProjectStack } = require('../lib/my-cdk-js-project-stack');

const app = new cdk.App();
new MyCdkJsProjectStack(app, 'MyCdkJsProjectStack');
```  
 `jest.config.js`   
Archivo de configuración para Jest. * Jest* es un marco de pruebas popular de JavaScript.  
 `lib/my-cdk-js-project-stack.js`   
El *archivo de pila* define la pila de CDK. Dentro de la pila, usted define los recursos y las propiedades de AWS mediante constructos.  
A continuación, se muestra un ejemplo de un archivo de pila básico que define una pila de CDK:  

```
const { Stack, Duration } = require('aws-cdk-lib');

class MyCdkJsProjectStack extends Stack {
 constructor(scope, id, props) {
  super(scope, id, props);

  // code that defines your resources and properties go here
 }
}

module.exports = { MyCdkJsProjectStack }
```  
 `node_modules`   
Carpeta común en los proyectos Node.js que contienen dependencias para su proyecto.  
 `package-lock.json`   
Archivo de metadatos que funciona con el archivo `package.json` para administrar las versiones de las dependencias.  
 `package.json`   
Archivo de metadatos que se utiliza habitualmente en los proyectos Node.js. Este archivo contiene información sobre su proyecto de CDK, como el nombre del proyecto, las definiciones de los scripts, las dependencias y otra información de importación del proyecto.  
 `test/my-cdk-js-project.test.js`   
Se crea una carpeta de pruebas para organizar las pruebas del proyecto de CDK. También se crea un archivo de prueba de muestra.  
Puede escribir pruebas en JavaScript y utilizar Jest para compilar el código de JavaScript antes de ejecutarlas.
El siguiente es un ejemplo de proyecto creado en el directorio `my-cdk-py-project` mediante el comando `cdk init --language python`:  

```
my-cdk-py-project
├── .git
├── .gitignore
├── .venv
├── README.md
├── app.py
├── cdk.json
├── my_cdk_py_project
│   ├── __init__.py
│   └── my_cdk_py_project_stack.py
├── requirements-dev.txt
├── requirements.txt
├── source.bat
└── tests
    ├── __init__.py
    └── unit
```  
 `.venv`   
La CLI de CDK crea automáticamente un entorno virtual para el proyecto. El directorio `.venv` hace referencia a este entorno virtual.  
 `app.py`   
El *archivo de la aplicación* define la aplicación del CDK. Los proyectos de CDK pueden contener uno o más archivos de aplicación.  
A continuación, se muestra un ejemplo de un archivo de aplicación básico que define una aplicación CDK:  

```
#!/usr/bin/env python3
import os

import aws_cdk as cdk

from my_cdk_py_project.my_cdk_py_project_stack import MyCdkPyProjectStack

app = cdk.App()
MyCdkPyProjectStack(app, "MyCdkPyProjectStack")

app.synth()
```  
 `my_cdk_py_project`   
Directorio que contiene los *archivos de pila*. La CLI de CDK crea lo siguiente aquí:  
+ \$1\$1init\$1\$1.py: es un fichero de definición de paquete de Python vacío.
+  `my_cdk_py_project`: es un archivo que define la pila del CDK. A continuación, defina los recursos de AWS y las propiedades de la pila mediante constructos.
A continuación, se muestra un ejemplo de un archivo de pila:  

```
from aws_cdk import Stack

from constructs import Construct

class MyCdkPyProjectStack(Stack):
 def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
  super().__init__(scope, construct_id, **kwargs)

  # code that defines your resources and properties go here
```  
 `requirements-dev.txt`   
Archivo similar a `requirements.txt`, pero se utiliza para administrar las dependencias específicamente con fines de desarrollo y no de producción.  
 `requirements.txt`   
Archivo común que se utiliza en los proyectos de Python para especificar y administrar las dependencias del proyecto.  
 `source.bat`   
El archivo Batch para Windows se usa para configurar el entorno virtual de Python.  
 `tests`   
Directorio que contiene pruebas de unidades para el proyecto de CDK.  
A continuación, se muestra un ejemplo de una prueba unitaria:  

```
import aws_cdk as core
import aws_cdk.assertions as assertions

from my_cdk_py_project.my_cdk_py_project_stack import MyCdkPyProjectStack

def test_sqs_queue_created():
 app = core.App()
 stack = MyCdkPyProjectStack(app, "my-cdk-py-project")
 template = assertions.Template.from_stack(stack)

 template.has_resource_properties("AWS::SQS::Queue", {
  "VisibilityTimeout": 300
 })
```
El siguiente es un ejemplo de proyecto creado en el directorio `my-cdk-java-project` mediante el comando `cdk init --language java`:  

```
my-cdk-java-project
├── .git
├── .gitignore
├── README.md
├── cdk.json
├── pom.xml
└── src
    ├── main
    └── test
```  
 `pom.xml`   
Archivo que contiene información de configuración y metadatos sobre el proyecto de CDK. Este archivo forma parte de Maven.  
 `src/main`   
Directorio que contiene los archivos de *la aplicación* y de la *pila*.  
A continuación, se muestra un ejemplo de un archivo de aplicación:  

```
package com.myorg;

import software.amazon.awscdk.App;
import software.amazon.awscdk.Environment;
import software.amazon.awscdk.StackProps;

import java.util.Arrays;

public class MyCdkJavaProjectApp {
 public static void main(final String[] args) {
  App app = new App();

  new MyCdkJavaProjectStack(app, "MyCdkJavaProjectStack", StackProps.builder()
   .build());

  app.synth();
 }
}
```
A continuación, se muestra un ejemplo de un archivo de pila:  

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;

public class MyCdkJavaProjectStack extends Stack {
 public MyCdkJavaProjectStack(final Construct scope, final String id) {
  this(scope, id, null);
 }

 public MyCdkJavaProjectStack(final Construct scope, final String id, final StackProps props) {
  super(scope, id, props);

  // code that defines your resources and properties go here
 }
}
```  
 `src/test`   
Directorio que contiene los archivos de prueba. A continuación, se muestra un ejemplo:  

```
package com.myorg;

import software.amazon.awscdk.App;
import software.amazon.awscdk.assertions.Template;
import java.io.IOException;

import java.util.HashMap;

import org.junit.jupiter.api.Test;

public class MyCdkJavaProjectTest {

 @Test
 public void testStack() throws IOException {
  App app = new App();
  MyCdkJavaProjectStack stack = new MyCdkJavaProjectStack(app, "test");

  Template template = Template.fromStack(stack);

  template.hasResourceProperties("AWS::SQS::Queue", new HashMap<String, Number>() {{
   put("VisibilityTimeout", 300);
  }});
 }
}
```
El siguiente es un ejemplo de proyecto creado en el directorio `my-cdk-csharp-project` mediante el comando `cdk init --language csharp`:  

```
my-cdk-csharp-project
├── .git
├── .gitignore
├── README.md
├── cdk.json
└── src
    ├── MyCdkCsharpProject
    └── MyCdkCsharpProject.sln
```  
 `src/MyCdkCsharpProject`   
Directorio que contiene los archivos de *la aplicación* y de la *pila*.  
A continuación, se muestra un ejemplo de un archivo de aplicación:  

```
using Amazon.CDK;
using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCdkCsharpProject
{
 sealed class Program
 {
  public static void Main(string[] args)
  {
   var app = new App();
   new MyCdkCsharpProjectStack(app, "MyCdkCsharpProjectStack", new StackProps{});
   app.Synth();
  }
 }
}
```
A continuación, se muestra un ejemplo de un archivo de pila:  

```
using Amazon.CDK;
using Constructs;

namespace MyCdkCsharpProject
{
 public class MyCdkCsharpProjectStack : Stack
 {
  internal MyCdkCsharpProjectStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
  {
   // code that defines your resources and properties go here
  }
 }
}
```
Este directorio también contiene lo siguiente:  
  
+  `GlobalSuppressions.cs`: archivo utilizado para suprimir advertencias o errores específicos del compilador en todo el proyecto.
+  `.csproj`: archivo basado en XML que se utiliza para definir los ajustes, las dependencias y las configuraciones de compilación del proyecto. ---  
 `src/MyCdkCsharpProject.sln`   
 Microsoft Visual Studio Solution File se utiliza para organizar y administrar proyectos relacionados.
El siguiente es un ejemplo de proyecto creado en el directorio `my-cdk-go-project` mediante el comando `cdk init --language go`:  

```
my-cdk-go-project
├── .git
├── .gitignore
├── README.md
├── cdk.json
├── go.mod
├── my-cdk-go-project.go
└── my-cdk-go-project_test.go
```  
 `go.mod`   
Archivo que contiene información del módulo y que se utiliza para administrar las dependencias y el control de versiones del proyecto Go.  
 `my-cdk-go-project.go`   
Archivo que define la aplicación y las pilas de CDK.  
A continuación, se muestra un ejemplo:  

```
package main
import (
 "github.com/aws/aws-cdk-go/awscdk/v2"
 "github.com/aws/constructs-go/constructs/v10"
 "github.com/aws/jsii-runtime-go"
)

type MyCdkGoProjectStackProps struct {
 awscdk.StackProps
}

func NewMyCdkGoProjectStack(scope constructs.Construct, id string, props *MyCdkGoProjectStackProps) awscdk.Stack {
 var sprops awscdk.StackProps
 if props != nil {
  sprops = props.StackProps
 }
 stack := awscdk.NewStack(scope, &id, &sprops)
 // The code that defines your resources and properties go here

  return stack
}

func main() {
 defer jsii.Close()
 app := awscdk.NewApp(nil)
 NewMyCdkGoProjectStack(app, "MyCdkGoProjectStack", &MyCdkGoProjectStackProps{
  awscdk.StackProps{
   Env: env(),
  },
 })
 app.Synth(nil)
}

func env() *awscdk.Environment {

 return nil
}
```  
 `my-cdk-go-project_test.go`   
Archivo que define un ejemplo de prueba.  
A continuación, se muestra un ejemplo:  

```
package main

import (
 "testing"

 "github.com/aws/aws-cdk-go/awscdk/v2"
 "github.com/aws/aws-cdk-go/awscdk/v2/assertions"
 "github.com/aws/jsii-runtime-go"
)

func TestMyCdkGoProjectStack(t *testing.T) {

 // GIVEN
 app := awscdk.NewApp(nil)

 // WHEN
 stack := NewMyCdkGoProjectStack(app, "MyStack", nil)

 // THEN
 template := assertions.Template_FromStack(stack, nil)
 template.HasResourceProperties(jsii.String("AWS::SQS::Queue"), map[string]interface{}{
  "VisibilityTimeout": 300,
 })
}
```

# AWS Aplicaciones de CDK
<a name="apps"></a>

La aplicación o *app* de AWS Cloud Development Kit (AWS CDK) es una colección de una o más [pilas](stacks.md) de CDK. Las pilas son colecciones de uno o más [constructos](constructs.md) que definen los recursos y las propiedades de AWS. Por lo tanto, la agrupación general de sus pilas y constructos se conoce como una aplicación de CDK.

## Cómo crear una aplicación de CDK
<a name="apps-define"></a>

Para crear una aplicación, define una instancia de aplicación en el archivo de aplicación de su [proyecto](projects.md). Para ello, importe y utilice el constructo de la [App](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html) de la biblioteca de constructos de AWS. El constructo `App` no requiere ningún argumento para la inicialización. Es el único constructo que se puede utilizar como raíz.

Las clases ` [App](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html) ` y ` [Stack](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html) ` 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`.

Luego, las aplicaciones se sintetizan para crear plantillas de AWS CloudFormation para sus pilas. A continuación, se muestra un ejemplo:

**Example**  

```
const app = new App();
new MyFirstStack(app, 'hello-cdk');
app.synth();
```

```
const app = new App();
new MyFirstStack(app, 'hello-cdk');
app.synth();
```

```
app = App()
MyFirstStack(app, "hello-cdk")
app.synth()
```

```
App app = new App();
new MyFirstStack(app, "hello-cdk");
app.synth();
```

```
var app = new App();
new MyFirstStack(app, "hello-cdk");
app.Synth();
```

```
app := awscdk.NewApp(nil)

MyFirstStack(app, "MyFirstStack", &MyFirstStackProps{
  awscdk.StackProps{
    Env: env(),
  },
})

app.Synth(nil)
```

Las pilas de una sola aplicación pueden hacer referencia a los recursos y las propiedades de las demás con facilidad. CDK AWS deduce las dependencias entre las pilas para poder implementarlas en el orden correcto. Puede implementar cualquiera de las pilas de una aplicación o todas ellas con un solo comando `cdk deploy`.

## El árbol de constructos
<a name="apps-tree"></a>

Los constructos se definen dentro de otros constructos mediante el argumento `scope` que se pasa a cada constructo, con la clase `App` como raíz. De esta forma, una aplicación de CDK AWS define una jerarquía de constructos conocida como *árbol de constructos*.

La raíz de este árbol es su aplicación, que es una instancia de la clase `App`. Dentro de la aplicación, se crean instancias de una o más pilas. Dentro de las pilas, se crean instancias de los constructos, que, a su vez, pueden crear instancias de recursos u otros constructos, y así sucesivamente en el resto del árbol.

Los constructos *siempre* se definen de forma explícita en el ámbito de otro constructo, lo cual crea relaciones entre los constructos. Casi siempre, debe pasar `this` (en Python, `self`) como el ámbito, lo que indica que el nuevo constructo es un elemento secundario del constructo actual. El patrón previsto consiste en derivar su constructo a partir de [https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html) y, luego, crear una instancia de los constructos que utiliza en su constructor.

Pasar el ámbito de forma explícita permite que cada constructo se agregue a sí mismo al árbol. Este comportamiento se limita exclusivamente a la [clase base `Construct`](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html). Funciona de la misma manera en todos los lenguajes que admite el AWS CDK y no requiere más personalización.

**importante**  
Técnicamente, es posible pasar un ámbito distinto a `this` cuando se genere un constructo. Puede agregar constructos en cualquier parte del árbol, incluso en otra pila de la misma aplicación. Por ejemplo, puede escribir una función de estilo mixto que agregue constructos a un ámbito que se pasó como argumento. La dificultad práctica en este caso es que no es fácil garantizar que los ID que elija para sus constructos sean únicos en el ámbito de otra persona. Esta práctica también hace que sea más difícil entender, mantener y reutilizar el código. Por lo tanto, se recomienda utilizar la estructura general del árbol de constructos.

CDK AWS utiliza los ID de todos los constructos en la ruta desde la raíz del árbol hasta cada constructo secundario para generar los ID únicos que necesita AWS. Este enfoque significa que los ID de los constructos solo deben ser únicos en su ámbito, y no dentro de toda la pila, como en el caso de AWS CloudFormation original. Sin embargo, si mueve un constructo a un ámbito diferente, se cambia el ID exclusivo de la pila que se generó, y AWS CloudFormation no lo considerará el mismo recurso.

El árbol de constructos es independiente de los constructos que defina en el código de CDK AWS. Sin embargo, se puede acceder a él con el atributo `node` de cualquier constructo, que es una referencia al nodo que representa ese constructo en el árbol. Cada nodo es una instancia [https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Node.html](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Node.html), cuyos atributos proporcionan acceso a la raíz del árbol y a los ámbitos principales y secundarios del nodo.

1.  `node.children`: los elementos secundarios del constructo.

1.  `node.id`: el identificador del constructo dentro de su ámbito.

1.  `node.path`: la ruta completa del constructo, incluidos los ID de todos los elementos principales.

1.  `node.root`: la raíz del árbol de constructos (la aplicación).

1.  `node.scope`: el ámbito (principal) del constructo o indefinido si el nodo es la raíz.

1.  `node.scopes`: todos los elementos principales del constructo, hasta la raíz.

1.  `node.uniqueId`: el identificador alfanumérico único de este constructo dentro del árbol (se genera de forma predeterminada a partir de `node.path` y un hash).

El árbol de constructos establece un orden implícito en el que los constructos se sintetizan en recursos de la plantilla final de AWS CloudFormation. Cuando se debe crear un recurso antes que otro, AWS o la Biblioteca de constructos de AWS CloudFormation generalmente deducen la dependencia. Luego, se aseguran de que los recursos se creen en el orden correcto.

También puede agregar una dependencia explícita entre dos nodos mediante `node.addDependency()`. Para obtener más información, consulte [Dependencias](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html#dependencies) en la *Referencia de la API de AWS CDK*.

El AWS CDK proporciona una forma sencilla de visitar todos los nodos del árbol de constructos y realizar una operación en cada uno de ellos. Para obtener más información, consulte [Aspectos y AWS CDK](aspects.md).

# Introducción a las pilas de AWS CDK
<a name="stacks"></a>

Una pila de AWS CDK es la unidad de implementación más pequeña. Representa un conjunto de AWS recursos que se definen mediante estructuras de CDK. Al implementar aplicaciones de CDK, los recursos de una pila de CDK se implementan juntos como una pila. AWS CloudFormation *Para obtener más información sobre las AWS CloudFormation pilas, consulte [Administrar AWS los recursos como una sola unidad con AWS CloudFormation pilas](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacks.html) en la Guía del usuario. AWS CloudFormation *

Una pila se define mediante la extensión o la herencia del constructo [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html). El siguiente ejemplo es un patrón común para definir una pila de CDK en un archivo independiente, conocido como *archivo de pila*. Aquí, extendemos o heredamos la clase `Stack` y definimos un constructor que acepte `scope`, `id` y `props`. Luego, invocamos el constructor de clase `Stack` de base mediante `super` con el `scope`, el `id` y los `props` recibidos:

**Example**  

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class MyCdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Define your constructs here

  }
}
```

```
const { Stack } = require('aws-cdk-lib');

class MyCdkStack extends Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    // Define your constructs here

  }
}

module.exports = { MyCdkStack }
```

```
from aws_cdk import (
  Stack,
)
from constructs import Construct

class MyCdkStack(Stack):

  def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
    super().__init__(scope, construct_id, **kwargs)

    # Define your constructs here
```

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;

public class MyCdkStack extends Stack {
  public MyCdkStack(final Construct scope, final String id) {
    this(scope, id, null);
  }

  public MyCdkStack(final Construct scope, final String id, final StackProps props) {
    super(scope, id, props);

    // Define your constructs here
  }
}
```

```
using Amazon.CDK;
using Constructs;

namespace MyCdk
{
  public class MyCdkStack : Stack
  {
    internal MyCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
    {
      // Define your constructs here
    }
  }
}
```

```
package main

import (
	"github.com/aws/aws-cdk-go/awscdk/v2"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
)

type CdkDemoAppStackProps struct {
	awscdk.StackProps
}

func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	stack := awscdk.NewStack(scope, &id, &sprops)

	// The code that defines your stack goes here

	return stack
}

func main() {
	defer jsii.Close()

	app := awscdk.NewApp(nil)

	NewCdkDemoAppStack(app, "CdkDemoAppStack", &CdkDemoAppStackProps{
		awscdk.StackProps{
			Env: env(),
		},
	})

	app.Synth(nil)
}

//...
```

En el ejemplo anterior solo se definió una pila. Para crear la pila, se debe crear una instancia de ella en el contexto de la aplicación de CDK. Un patrón común consiste en definir la aplicación de CDK e iniciar la pila en un archivo independiente, conocido como *archivo de aplicación*.

A continuación, se muestra un ejemplo donde se crea una pila de CDK llamada `MyCdkStack`. Aquí, se crea la aplicación de CDK y se crea una instancia de `MyCdkStack` en el contexto de la aplicación:

**Example**  

```
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { MyCdkStack } from '../lib/my-cdk-stack';

const app = new cdk.App();
new MyCdkStack(app, 'MyCdkStack', {
});
```

```
#!/usr/bin/env node

const cdk = require('aws-cdk-lib');
const { MyCdkStack } = require('../lib/my-cdk-stack');

const app = new cdk.App();
new MyCdkStack(app, 'MyCdkStack', {
});
```
Se encuentra en `app.py`:  

```
#!/usr/bin/env python3
import os

import aws_cdk as cdk

from my_cdk.my_cdk_stack import MyCdkStack


app = cdk.App()
MyCdkStack(app, "MyCdkStack",)

app.synth()
```

```
package com.myorg;

import software.amazon.awscdk.App;
import software.amazon.awscdk.Environment;
import software.amazon.awscdk.StackProps;

import java.util.Arrays;

public class MyCdkApp {
  public static void main(final String[] args) {
    App app = new App();

    new MyCdkStack(app, "MyCdkStack", StackProps.builder()
      .build());

    app.synth();
  }
}
```

```
using Amazon.CDK;
using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCdk
{
  sealed class Program
  {
    public static void Main(string[] args)
    {
      var app = new App();
      new MyCdkStack(app, "MyCdkStack", new StackProps
      {});
      app.Synth();
    }
  }
}
```

```
package main

import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/constructs-go/constructs/v10"
  "github.com/aws/jsii-runtime-go"
)

// ...

func main() {
  defer jsii.Close()

  app := awscdk.NewApp(nil)

  NewMyCdkStack(app, "MyCdkStack", &MyCdkStackProps{
    awscdk.StackProps{
      Env: env(),
    },
  })

  app.Synth(nil)
}

// ...
```

En el siguiente ejemplo, se crea una aplicación de CDK que contiene dos pilas:

**Example**  

```
const app = new App();

new MyFirstStack(app, 'stack1');
new MySecondStack(app, 'stack2');

app.synth();
```

```
const app = new App();

new MyFirstStack(app, 'stack1');
new MySecondStack(app, 'stack2');

app.synth();
```

```
app = App()

MyFirstStack(app, 'stack1')
MySecondStack(app, 'stack2')

app.synth()
```

```
App app = new App();

new MyFirstStack(app, "stack1");
new MySecondStack(app, "stack2");

app.synth();
```

```
var app = new App();

new MyFirstStack(app, "stack1");
new MySecondStack(app, "stack2");

app.Synth();
```

```
package main

import (
	"github.com/aws/aws-cdk-go/awscdk/v2"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
)

type MyFirstStackProps struct {
	awscdk.StackProps
}

func NewMyFirstStack(scope constructs.Construct, id string, props *MyFirstStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	myFirstStack := awscdk.NewStack(scope, &id, &sprops)

	// The code that defines your stack goes here

	return myFirstStack
}

type MySecondStackProps struct {
	awscdk.StackProps
}

func NewMySecondStack(scope constructs.Construct, id string, props *MySecondStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	mySecondStack := awscdk.NewStack(scope, &id, &sprops)

	// The code that defines your stack goes here

	return mySecondStack
}

func main() {
	defer jsii.Close()

	app := awscdk.NewApp(nil)

	NewMyFirstStack(app, "MyFirstStack", &MyFirstStackProps{
		awscdk.StackProps{
			Env: env(),
		},
	})

	NewMySecondStack(app, "MySecondStack", &MySecondStackProps{
		awscdk.StackProps{
			Env: env(),
		},
	})

	app.Synth(nil)
}

// ...
```

## Acerca de la pila de API
<a name="stack-api"></a>

El objeto [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html) proporciona una API completa que incluye lo siguiente:
+  `Stack.of(construct)`: un método estático que devuelve la **pila** en la que se define un constructo. Es útil si necesita interactuar con una pila desde un constructo reutilizable. La llamada falla si no se encuentra una pila en el ámbito.
+  `stack.stackName` (Python: `stack_name`): devuelve el nombre físico de la pila. Como se mencionó anteriormente, todas las pilas de AWS CDK tienen un nombre físico que la AWS CDK puede resolver durante la síntesis.
+  `stack.region`y `stack.account` — Devuelve la AWS región y la cuenta, respectivamente, en las que se desplegará esta pila. Estas propiedades devuelven uno de los siguientes valores:
  + La cuenta o la región que se especificó de forma explícita cuando se definió la pila
  + Un token codificado en cadenas que se resuelve con los AWS CloudFormation pseudoparámetros de la cuenta y la región para indicar que esta pila es independiente del entorno

    [Para obtener información sobre cómo se determinan los entornos de las pilas, consulte Entornos del CDK. AWS](environments.md)
+  `stack.addDependency(stack)` (Python: `stack.add_dependency(stack)`): se puede utilizar para definir de manera explícita el orden de dependencia entre dos pilas. El comando `cdk deploy` respeta este orden cuando se implementan varias pilas a la vez.
+  `stack.tags`— Devuelve un elemento [TagManager](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagManager.html)que puede utilizar para añadir o eliminar etiquetas a nivel de pila. Este administrador de etiquetas etiqueta todos los recursos de la pila y también etiqueta la propia pila cuando se crea mediante ella. AWS CloudFormation
+  `stack.partition`, `stack.urlSuffix` (Python:`url_suffix`), `stack.stackId` (Python:`stack_id`) y `stack.notificationArn` (Python:`notification_arn`): devuelven los tokens que se resuelven en los AWS CloudFormation pseudoparámetros respectivos, como`{ "Ref": "AWS::Partition" }`. Estos tokens están asociados al objeto de pila específico para que el marco AWS CDK pueda identificar las referencias entre pilas.
+  `stack.availabilityZones` (Python: `availability_zones`): devuelve el conjunto de zonas de disponibilidad disponibles en el entorno en el que se implementa esta pila. En el caso de las pilas independientes del entorno, este siempre devuelve una matriz con dos zonas de disponibilidad. En el caso de las pilas específicas del entorno, la AWS CDK consulta el entorno y devuelve el conjunto exacto de zonas de disponibilidad disponibles en la región que especificó.
+  `stack.parseArn(arn)`and `stack.formatArn(comps)` (Python:`parse_arn`,`format_arn`): se puede usar para trabajar con Amazon Resource Names (ARNs).
+  `stack.toJsonString(obj)`(Python:`to_json_string`): se puede usar para formatear un objeto arbitrario como una cadena JSON que se puede incrustar en una AWS CloudFormation plantilla. El objeto puede incluir tókenes, atributos y referencias, que solo se resuelven durante la implementación.
+  `stack.templateOptions`(Python:`template_options`): se usa para especificar opciones de AWS CloudFormation plantilla, como transformación, descripción y metadatos, para la pila.

## Trabajo con pilas
<a name="stacks-work"></a>

Las pilas se implementan como una AWS CloudFormation pila en un AWS [entorno.](environments.md) El entorno cubre una AWS cuenta y una AWS región específicas.

Cuando se ejecuta el comando `cdk synth` para una aplicación con varias pilas, el ensamblaje de la nube incluye una plantilla independiente para cada instancia de pila. Incluso si las dos pilas son instancias de la misma clase, la AWS CDK las emite como dos plantillas individuales.

Puede sintetizar cada plantilla si especifica el nombre de la pila en el comando `cdk synth`. El siguiente ejemplo sintetiza la plantilla para `stack1`:

```
$ cdk synth <stack1>
```

[Este enfoque es conceptualmente diferente de la forma en que se utilizan normalmente las AWS CloudFormation plantillas, ya que una plantilla se puede implementar varias veces y parametrizar mediante parámetros.AWS CloudFormation ](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html) Si bien AWS CloudFormation los parámetros se pueden definir en la AWS CDK, por lo general no se recomienda utilizarlos porque los AWS CloudFormation parámetros solo se resuelven durante el despliegue. Esto significa que no se puede determinar su valor en el código.

Por ejemplo, para incluir de manera condicional un recurso en su aplicación en función del valor de un parámetro, debe configurar una [condición de AWS CloudFormation ](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html) y etiquetar el recurso con ella. El AWS CDK adopta un enfoque en el que las plantillas concretas se resuelven en el momento de la síntesis. Por lo tanto, puede utilizar una instrucción `if` para verificar el valor y determinar si se debe definir un recurso o si se debe aplicar algún comportamiento.

**nota**  
El AWS CDK proporciona la mayor resolución posible durante el tiempo de síntesis para permitir un uso idiomático y natural del lenguaje de programación.

Como cualquier otro constructo, las pilas pueden componerse en grupos. El siguiente código muestra un ejemplo de un servicio que consta de tres pilas: un plano de control, un plano de datos y pilas de supervisión. El constructo de servicio se define dos veces: una para el entorno beta y otra para el entorno de producción.

**Example**  

```
import { App, Stack } from 'aws-cdk-lib';
import { Construct } from 'constructs';

interface EnvProps {
  prod: boolean;
}

// imagine these stacks declare a bunch of related resources
class ControlPlane extends Stack {}
class DataPlane extends Stack {}
class Monitoring extends Stack {}

class MyService extends Construct {

  constructor(scope: Construct, id: string, props?: EnvProps) {

    super(scope, id);

    // we might use the prod argument to change how the service is configured
    new ControlPlane(this, "cp");
    new DataPlane(this, "data");
    new Monitoring(this, "mon");  }
}

const app = new App();
new MyService(app, "beta");
new MyService(app, "prod", { prod: true });

app.synth();
```

```
const { App, Stack } = require('aws-cdk-lib');
const { Construct } = require('constructs');

// imagine these stacks declare a bunch of related resources
class ControlPlane extends Stack {}
class DataPlane extends Stack {}
class Monitoring extends Stack {}

class MyService extends Construct {

  constructor(scope, id, props) {

    super(scope, id);

    // we might use the prod argument to change how the service is configured
    new ControlPlane(this, "cp");
    new DataPlane(this, "data");
    new Monitoring(this, "mon");
  }
}

const app = new App();
new MyService(app, "beta");
new MyService(app, "prod", { prod: true });

app.synth();
```

```
from aws_cdk import App, Stack
from constructs import Construct

# imagine these stacks declare a bunch of related resources
class ControlPlane(Stack): pass
class DataPlane(Stack): pass
class Monitoring(Stack): pass

class MyService(Construct):

  def __init__(self, scope: Construct, id: str, *, prod=False):

    super().__init__(scope, id)

    # we might use the prod argument to change how the service is configured
    ControlPlane(self, "cp")
    DataPlane(self, "data")
    Monitoring(self, "mon")

app = App();
MyService(app, "beta")
MyService(app, "prod", prod=True)

app.synth()
```

```
package com.myorg;

import software.amazon.awscdk.App;
import software.amazon.awscdk.Stack;
import software.constructs.Construct;

public class MyApp {

    // imagine these stacks declare a bunch of related resources
    static class ControlPlane extends Stack {
        ControlPlane(Construct scope, String id) {
            super(scope, id);
        }
    }

    static class DataPlane extends Stack {
        DataPlane(Construct scope, String id) {
            super(scope, id);
        }
    }

    static class Monitoring extends Stack {
        Monitoring(Construct scope, String id) {
            super(scope, id);
        }
    }

    static class MyService extends Construct {
        MyService(Construct scope, String id) {
            this(scope, id, false);
        }

        MyService(Construct scope, String id, boolean prod) {
            super(scope, id);

            // we might use the prod argument to change how the service is configured
            new ControlPlane(this, "cp");
            new DataPlane(this, "data");
            new Monitoring(this, "mon");
        }
    }

    public static void main(final String argv[]) {
        App app = new App();

        new MyService(app, "beta");
        new MyService(app, "prod", true);

        app.synth();
    }
}
```

```
using Amazon.CDK;
using Constructs;

// imagine these stacks declare a bunch of related resources
public class ControlPlane : Stack {
    public ControlPlane(Construct scope, string id=null) : base(scope, id) { }
}

public class DataPlane : Stack {
    public DataPlane(Construct scope, string id=null) : base(scope, id) { }
}

public class Monitoring : Stack
{
    public Monitoring(Construct scope, string id=null) : base(scope, id) { }
}

public class MyService : Construct
{
    public MyService(Construct scope, string id, Boolean prod=false) : base(scope, id)
    {
        // we might use the prod argument to change how the service is configured
        new ControlPlane(this, "cp");
        new DataPlane(this, "data");
        new Monitoring(this, "mon");
    }
}

class Program
{
    static void Main(string[] args)
    {

        var app = new App();
        new MyService(app, "beta");
        new MyService(app, "prod", prod: true);
        app.Synth();
    }
}
```

```
package main

import (
	"github.com/aws/aws-cdk-go/awscdk/v2"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
)

type ControlPlaneStackProps struct {
	awscdk.StackProps
}

func NewControlPlaneStack(scope constructs.Construct, id string, props *ControlPlaneStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	ControlPlaneStack := awscdk.NewStack(scope, jsii.String(id), &sprops)

	// The code that defines your stack goes here

	return ControlPlaneStack
}

type DataPlaneStackProps struct {
	awscdk.StackProps
}

func NewDataPlaneStack(scope constructs.Construct, id string, props *DataPlaneStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	DataPlaneStack := awscdk.NewStack(scope, jsii.String(id), &sprops)

	// The code that defines your stack goes here

	return DataPlaneStack
}

type MonitoringStackProps struct {
	awscdk.StackProps
}

func NewMonitoringStack(scope constructs.Construct, id string, props *MonitoringStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	MonitoringStack := awscdk.NewStack(scope, jsii.String(id), &sprops)

	// The code that defines your stack goes here

	return MonitoringStack
}

type MyServiceStackProps struct {
	awscdk.StackProps
	Prod bool
}

func NewMyServiceStack(scope constructs.Construct, id string, props *MyServiceStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	MyServiceStack := awscdk.NewStack(scope, jsii.String(id), &sprops)

	NewControlPlaneStack(MyServiceStack, "cp", &ControlPlaneStackProps{
		StackProps: sprops,
	})
	NewDataPlaneStack(MyServiceStack, "data", &DataPlaneStackProps{
		StackProps: sprops,
	})
	NewMonitoringStack(MyServiceStack, "mon", &MonitoringStackProps{
		StackProps: sprops,
	})

	return MyServiceStack
}

func main() {
	defer jsii.Close()

	app := awscdk.NewApp(nil)

	betaProps := MyServiceStackProps{
		StackProps: awscdk.StackProps{
			Env: env(),
		},
		Prod: false,
	}

	NewMyServiceStack(app, "beta", &betaProps)

	prodProps := MyServiceStackProps{
		StackProps: awscdk.StackProps{
			Env: env(),
		},
		Prod: true,
	}

	NewMyServiceStack(app, "prod", &prodProps)

	app.Synth(nil)
}

// ...
```
Esta aplicación de AWS CDK finalmente consta de seis pilas, tres para cada entorno:  

```
$ cdk ls

betacpDA8372D3
betadataE23DB2BA
betamon632BD457
prodcp187264CE
proddataF7378CE5
prodmon631A1083
```

El AWS CDK determina automáticamente los nombres físicos de las AWS CloudFormation pilas en función de la ruta de construcción de la pila en el árbol. De manera predeterminada, el nombre de una pila deriva del ID de constructo del objeto `Stack`. Sin embargo, se puede especificar un nombre explícito mediante el uso de la propiedad `stackName` (en Python, `stack_name`), como se indica a continuación.

**Example**  

```
new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' });
```

```
new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' });
```

```
MyStack(self, "not:a:stack:name", stack_name="this-is-stack-name")
```

```
new MyStack(this, "not:a:stack:name", StackProps.builder()
    .StackName("this-is-stack-name").build());
```

```
new MyStack(this, "not:a:stack:name", new StackProps
{
    StackName = "this-is-stack-name"
});
```

### Uso de pilas anidadas
<a name="stack-nesting"></a>

Una *pila anidada* es una pila de CDK que se crea dentro de otra pila, conocida como pila principal. Las pilas anidadas se crean mediante el constructo [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html).

Cuando se utilizan pilas anidadas, se pueden organizar los recursos en varias pilas. Las pilas anidadas también ofrecen una forma de evitar el límite de AWS CloudFormation 500 recursos de las pilas. Una pila anidada cuenta solo como un recurso en la pila que la contiene. Sin embargo, puede contener hasta 500 recursos, incluidas pilas anidadas adicionales.

El ámbito de una pila anidada debe ser una `Stack` o un constructo `NestedStack`. La pila anidada no necesita declararse léxicamente dentro de la pila principal. Solo es necesario pasar la pila principal como el primer parámetro (`scope`) cuando se crea una instancia de la pila anidada. Además de esta restricción, la definición de constructos en una pila anidada funciona exactamente igual que en una pila normal.

En el momento de la síntesis, la pila anidada se sintetiza en su propia AWS CloudFormation plantilla, que se carga en el depósito provisional del CDK en el momento de la AWS implementación. Las pilas anidadas están vinculadas a su pila principal y no se tratan como artefactos de implementación independientes. No aparecen en la lista `cdk list` ni pueden implementarse mediante `cdk deploy`.

[Las referencias entre las pilas principales y las pilas anidadas se traducen automáticamente en parámetros y resultados de la pila en las AWS CloudFormation plantillas generadas, como ocurre con cualquier referencia entre pilas.](resources.md#resource-stack)

**aviso**  
En el caso de las pilas anidadas, los cambios en la posición de seguridad no se muestran antes de la implementación. Esta información solo se muestra en el caso de las pilas de nivel superior.

# Introducción a las etapas de AWS CDK
<a name="stages"></a>

Una *etapa* de AWS Cloud Development Kit (AWS CDK) representa un grupo de una o más pilas de CDK que están configuradas para implementarse juntas. Utilice las etapas para implementar la misma agrupación de pilas en varios entornos, por ejemplo, desarrollo, pruebas y producción.

Para configurar una etapa de CDK, importe y utilice el constructo [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html).

A continuación, se muestra un ejemplo básico que define una etapa de CDK denominada `MyAppStage`. Agregamos dos pilas de CDK, denominadas `AppStack` y `DatabaseStack` a nuestra etapa. Para este ejemplo, `AppStack` contiene los recursos de la aplicación y `DatabaseStack` contiene los recursos de la base de datos. A continuación, creamos dos instancias de `MyAppStage` para los entornos de desarrollo y producción:

**Example**  
En `cdk-demo-app/lib/app-stack.ts`:  

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';

// Define the app stack
export class AppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    // The code that defines your application goes here
  }
}
```
En `cdk-demo-app/lib/database-stack.ts`:  

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';

// Define the database stack
export class DatabaseStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    // The code that defines your database goes here
  }
}
```
En `cdk-demo-app/lib/my-stage.ts`:  

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { Stage } from 'aws-cdk-lib';
import { AppStack } from './app-stack';
import { DatabaseStack } from './database-stack';

// Define the stage
export class MyAppStage extends Stage {
  constructor(scope: Construct, id: string, props?: cdk.StageProps) {
    super(scope, id, props);

    // Add both stacks to the stage
    new AppStack(this, 'AppStack');
    new DatabaseStack(this, 'DatabaseStack');
  }
}
```
En `cdk-demo-app/bin/cdk-demo-app.ts`:  

```
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { MyAppStage } from '../lib/my-stage';

// Create a CDK app
const app = new cdk.App();

// Create the development stage
new MyAppStage(app, 'Dev', {
  env: {
    account: '123456789012',
    region: 'us-east-1'
  }
});

// Create the production stage
new MyAppStage(app, 'Prod', {
  env: {
    account: '098765432109',
    region: 'us-east-1'
  }
});
```
En `cdk-demo-app/lib/app-stack.js`:  

```
const { Stack } = require('aws-cdk-lib');

class AppStack extends Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    // The code that defines your application goes here
  }
}

module.exports = { AppStack }
```
En `cdk-demo-app/lib/database-stack.js`:  

```
const { Stack } = require('aws-cdk-lib');

class DatabaseStack extends Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    // The code that defines your database goes here
  }
}

module.exports = { DatabaseStack }
```
En `cdk-demo-app/lib/my-stage.js`:  

```
const { Stage } = require('aws-cdk-lib');
const { AppStack } = require('./app-stack');
const { DatabaseStack } = require('./database-stack');

// Define the stage
class MyAppStage extends Stage {
  constructor(scope, id, props) {
    super(scope, id, props);

    // Add both stacks to the stage
    new AppStack(this, 'AppStack');
    new DatabaseStack(this, 'DatabaseStack');
  }
}

module.exports = { MyAppStage };
```
En `cdk-demo-app/bin/cdk-demo-app.js`:  

```
#!/usr/bin/env node

const cdk = require('aws-cdk-lib');
const { MyAppStage } = require('../lib/my-stage');

// Create the CDK app
const app = new cdk.App();

// Create the development stage
new MyAppStage(app, 'Dev', {
  env: {
    account: '123456789012',
    region: 'us-east-1',
  },
});

// Create the production stage
new MyAppStage(app, 'Prod', {
  env: {
    account: '098765432109',
    region: 'us-east-1',
  },
});
```
En `cdk-demo-app/cdk_demo_app/app_stack.py`:  

```
from aws_cdk import Stack
from constructs import Construct

# Define the app stack
class AppStack(Stack):
    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # The code that defines your application goes here
```
En `cdk-demo-app/cdk_demo_app/database_stack.py`:  

```
from aws_cdk import Stack
from constructs import Construct

# Define the database stack
class DatabaseStack(Stack):
    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # The code that defines your database goes here
```
En `cdk-demo-app/cdk_demo_app/my_stage.py`:  

```
from aws_cdk import Stage
from constructs import Construct
from .app_stack import AppStack
from .database_stack import DatabaseStack

# Define the stage
class MyAppStage(Stage):
    def __init__(self, scope: Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # Add both stacks to the stage
        AppStack(self, "AppStack")
        DatabaseStack(self, "DatabaseStack")
```
En `cdk-demo-app/app.py`:  

```
#!/usr/bin/env python3
import os

import aws_cdk as cdk

from cdk_demo_app.my_stage import MyAppStage

#  Create a CDK app
app = cdk.App()

# Create the development stage
MyAppStage(app, 'Dev',
           env=cdk.Environment(account='123456789012', region='us-east-1'),
           )

# Create the production stage
MyAppStage(app, 'Prod',
           env=cdk.Environment(account='098765432109', region='us-east-1'),
           )

app.synth()
```
En `cdk-demo-app/src/main/java/com/myorg/AppStack.java`:  

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;

public class AppStack extends Stack {
    public AppStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public AppStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        // The code that defines your application goes here
    }
}
```
En `cdk-demo-app/src/main/java/com/myorg/DatabaseStack.java`:  

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;

public class DatabaseStack extends Stack {
    public DatabaseStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public DatabaseStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        // The code that defines your database goes here
    }
}
```
En `cdk-demo-app/src/main/java/com/myorg/MyAppStage.java`:  

```
package com.myorg;

import software.amazon.awscdk.Stage;
import software.amazon.awscdk.StageProps;
import software.constructs.Construct;

// Define the stage
public class MyAppStage extends Stage {
    public MyAppStage(final Construct scope, final String id, final software.amazon.awscdk.Environment env) {
        super(scope, id, StageProps.builder().env(env).build());

        // Add both stacks to the stage
        new AppStack(this, "AppStack");
        new DatabaseStack(this, "DatabaseStack");
    }
}
```
En `cdk-demo-app/src/main/java/com/myorg/CdkDemoAppApp.java`:  

```
package com.myorg;

import software.amazon.awscdk.App;
import software.amazon.awscdk.Environment;
import software.amazon.awscdk.StackProps;

import java.util.Arrays;

public class CdkDemoAppApp {
    public static void main(final String[] args) {

        // Create a CDK app
        App app = new App();

        // Create the development stage
        new MyAppStage(app, "Dev", Environment.builder()
                .account("123456789012")
                .region("us-east-1")
                .build());

        // Create the production stage
        new MyAppStage(app, "Prod", Environment.builder()
        .account("098765432109")
        .region("us-east-1")
        .build());

        app.synth();
    }
}
```
En `cdk-demo-app/src/CdkDemoApp/AppStack.cs`:  

```
using Amazon.CDK;
using Constructs;

namespace CdkDemoApp
{
    public class AppStack : Stack
    {
        internal AppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // The code that defines your application goes here
        }
    }
}
```
En `cdk-demo-app/src/CdkDemoApp/DatabaseStack.cs`:  

```
using Amazon.CDK;
using Constructs;

namespace CdkDemoApp
{
    public class DatabaseStack : Stack
    {
        internal DatabaseStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // The code that defines your database goes here
        }
    }
}
```
En `cdk-demo-app/src/CdkDemoApp/MyAppStage.cs`:  

```
using Amazon.CDK;
using Constructs;

namespace CdkDemoApp
{
    // Define the stage
    public class MyAppStage : Stage
    {
        internal MyAppStage(Construct scope, string id, Environment env) : base(scope, id, new StageProps { Env = env })
        {
            // Add both stacks to the stage
            new AppStack(this, "AppStack");
            new DatabaseStack(this, "DatabaseStack");
        }
    }
}
```
En `cdk-demo-app/src/CdkDemoApp/program.cs`:  

```
using Amazon.CDK;
using System;
using System.Collections.Generic;
using System.Linq;

namespace CdkDemoApp
{
    sealed class Program
    {
        public static void Main(string[] args)
        {
            // Create a CDK app
            var app = new App();

            // Create the development stage
            new MyAppStage(app, "Dev", new Amazon.CDK.Environment
            {
                Account = "123456789012",
                Region = "us-east-1"
            });

            // Create the production stage
            new MyAppStage(app, "Prod", new Amazon.CDK.Environment
            {
                Account = "098765432109",
                Region = "us-east-1"
            });

            app.Synth();
        }
    }
}
```
En `cdk-demo-app/cdk-demo-app.go`:  

```
package main

import (
	"github.com/aws/aws-cdk-go/awscdk/v2"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
)

// Define the app stack
type AppStackProps struct {
	awscdk.StackProps
}

func NewAppStack(scope constructs.Construct, id string, props *AppStackProps) awscdk.Stack {
	stack := awscdk.NewStack(scope, &id, &props.StackProps)

	// The code that defines your application goes here

	return stack
}

// Define the database stack
type DatabaseStackProps struct {
	awscdk.StackProps
}

func NewDatabaseStack(scope constructs.Construct, id string, props *DatabaseStackProps) awscdk.Stack {
	stack := awscdk.NewStack(scope, &id, &props.StackProps)

	// The code that defines your database goes here

	return stack
}

// Define the stage
type MyAppStageProps struct {
	awscdk.StageProps
}

func NewMyAppStage(scope constructs.Construct, id string, props *MyAppStageProps) awscdk.Stage {
	stage := awscdk.NewStage(scope, &id, &props.StageProps)

	// Add both stacks to the stage
	NewAppStack(stage, "AppStack", &AppStackProps{
		StackProps: awscdk.StackProps{
			Env: props.Env,
		},
	})

	NewDatabaseStack(stage, "DatabaseStack", &DatabaseStackProps{
		StackProps: awscdk.StackProps{
			Env: props.Env,
		},
	})

	return stage
}

func main() {
	defer jsii.Close()

	// Create a CDK app
	app := awscdk.NewApp(nil)

	// Create the development stage
	NewMyAppStage(app, "Dev", &MyAppStageProps{
		StageProps: awscdk.StageProps{
			Env: &awscdk.Environment{
				Account: jsii.String("123456789012"),
				Region:  jsii.String("us-east-1"),
			},
		},
	})

	// Create the production stage
	NewMyAppStage(app, "Prod", &MyAppStageProps{
		StageProps: awscdk.StageProps{
			Env: &awscdk.Environment{
				Account: jsii.String("098765432109"),
				Region:  jsii.String("us-east-1"),
			},
		},
	})

	app.Synth(nil)
}

func env() *awscdk.Environment {
	return nil
}
```

Cuando ejecutamos `cdk synth`, se crean dos ensamblajes de nubes en `cdk.out`. Estos dos ensamblajes de nubes contienen la plantilla de AWS CloudFormation sintetizada y los recursos para cada etapa. El siguiente es un fragmento de nuestro directorio del proyecto:

**Example**  

```
cdk-demo-app
├── bin
│   └── cdk-demo-app.ts
├── cdk.out
│   ├── assembly-Dev
│   │   ├── DevAppStack<unique-hash>.assets.json
│   │   ├── DevAppStack<unique-hash>.template.json
│   │   ├── DevDatabaseStack<unique-hash>.assets.json
│   │   ├── DevDatabaseStack<unique-hash>.template.json
│   │   ├── cdk.out
│   │   └── manifest.json
│   ├── assembly-Prod
│   │   ├── ProdAppStack<unique-hash>.assets.json
│   │   ├── ProdAppStack<unique-hash>.template.json
│   │   ├── ProdDatabaseStack<unique-hash>.assets.json
│   │   ├── ProdDatabaseStack<unique-hash>.template.json
│   │   ├── cdk.out
│   │   └── manifest.json
└── lib
    ├── app-stack.ts
    ├── database-stack.ts
    └── my-stage.ts
```

```
cdk-demo-app
├── bin
│   └── cdk-demo-app.js
├── cdk.out
│   ├── assembly-Dev
│   │   ├── DevAppStack<unique-hash>.assets.json
│   │   ├── DevAppStack<unique-hash>.template.json
│   │   ├── DevDatabaseStack<unique-hash>.assets.json
│   │   ├── DevDatabaseStack<unique-hash>.template.json
│   │   ├── cdk.out
│   │   └── manifest.json
│   ├── assembly-Prod
│   │   ├── ProdAppStack<unique-hash>.assets.json
│   │   ├── ProdAppStack<unique-hash>.template.json
│   │   ├── ProdDatabaseStack<unique-hash>.assets.json
│   │   ├── ProdDatabaseStack<unique-hash>.template.json
│   │   ├── cdk.out
│   │   └── manifest.json
└── lib
    ├── app-stack.js
    ├── database-stack.js
    └── my-stage.js
```

```
cdk-demo-app
├── app.py
├── cdk.out
│   ├── assembly-Dev
│   │   ├── DevAppStack<unique-hash>.assets.json
│   │   ├── DevAppStack<unique-hash>.template.json
│   │   ├── DevDatabaseStack<unique-hash>.assets.json
│   │   ├── DevDatabaseStack<unique-hash>.template.json
│   │   ├── cdk.out
│   │   └── manifest.json
│   ├── assembly-Prod
│   │   ├── ProdAppStack<unique-hash>.assets.json
│   │   ├── ProdAppStack<unique-hash>.template.json
│   │   ├── ProdDatabaseStack<unique-hash>.assets.json
│   │   ├── ProdDatabaseStack<unique-hash>.template.json
│   │   ├── cdk.out
│   │   └── manifest.json
│   ├── cdk.out
│   ├── manifest.json
│   └── tree.json
└── cdk_demo_app
    ├── __init__.py
    ├── app_stack.py
    ├── database_stack.py
    └── my_stage.py
```

```
cdk-demo-app
├── cdk.out
│   ├── assembly-Dev
│   │   ├── DevAppStack<unique-hash>.assets.json
│   │   ├── DevAppStack<unique-hash>.template.json
│   │   ├── DevDatabaseStack<unique-hash>.assets.json
│   │   ├── DevDatabaseStack<unique-hash>.template.json
│   │   ├── cdk.out
│   │   └── manifest.json
│   ├── assembly-Prod
│   │   ├── ProdAppStack<unique-hash>.assets.json
│   │   ├── ProdAppStack<unique-hash>.template.json
│   │   ├── ProdDatabaseStack<unique-hash>.assets.json
│   │   ├── ProdDatabaseStack<unique-hash>.template.json
│   │   ├── cdk.out
│   │   └── manifest.json
│   ├── cdk.out
│   ├── manifest.json
│   └── tree.json
└── src
    └── main
        └── java
            └── com
                └── myorg
                    ├── AppStack.java
                    ├── CdkDemoAppApp.java
                    ├── DatabaseStack.java
                    └── MyAppStage.java
```

```
cdk-demo-app
├── cdk.out
│   ├── assembly-Dev
│   │   ├── DevAppStack<unique-hash>.assets.json
│   │   ├── DevAppStack<unique-hash>.template.json
│   │   ├── DevDatabaseStack<unique-hash>.assets.json
│   │   ├── DevDatabaseStack<unique-hash>.template.json
│   │   ├── cdk.out
│   │   └── manifest.json
│   ├── assembly-Prod
│   │   ├── ProdAppStack<unique-hash>.assets.json
│   │   ├── ProdAppStack<unique-hash>.template.json
│   │   ├── ProdDatabaseStack<unique-hash>.assets.json
│   │   ├── ProdDatabaseStack<unique-hash>.template.json
│   │   ├── cdk.out
│   │   └── manifest.json
│   ├── cdk.out
│   ├── manifest.json
│   └── tree.json
└── src
    └── CdkDemoApp
        ├── AppStack.cs
        ├── DatabaseStack.cs
        ├── MyAppStage.cs
        └── Program.cs
```

```
cdk-demo-app
├── cdk-demo-app.go
└── cdk.out
    ├── assembly-Dev
    │   ├── DevAppStack<unique-hash>.assets.json
    │   ├── DevAppStack<unique-hash>.template.json
    │   ├── DevDatabaseStack<unique-hash>.assets.json
    │   ├── DevDatabaseStack<unique-hash>.template.json
    │   ├── cdk.out
    │   └── manifest.json
    ├── assembly-Prod
    │   ├── ProdAppStack<unique-hash>.assets.json
    │   ├── ProdAppStack<unique-hash>.template.json
    │   ├── ProdDatabaseStack<unique-hash>.assets.json
    │   ├── ProdDatabaseStack<unique-hash>.template.json
    │   ├── cdk.out
    │   └── manifest.json
    ├── cdk.out
    ├── manifest.json
    └── tree.json
```
Cuando enumeramos nuestras pilas con `cdk list`, vemos un total de cuatro pilas:  

```
$ cdk list
Dev/AppStack (Dev-AppStack)
Dev/DatabaseStack (Dev-DatabaseStack)
Prod/AppStack (Prod-AppStack)
Prod/DatabaseStack (Prod-DatabaseStack)
```
Para implementar una etapa específica, ejecutamos `cdk deploy` y proporcionamos las pilas que se van a implementar. A continuación, se muestra un ejemplo en el que se utiliza el comodín `/*` para implementar ambas pilas en nuestra etapa `Dev`:  

```
$ cdk deploy <"Dev/*">

✨  Synthesis time: 3.18s

Dev/AppStack (Dev-AppStack)
Dev/AppStack (Dev-AppStack): deploying... [1/2]

 ✅  Dev/AppStack (Dev-AppStack)

✨  Deployment time: 1.11s

Stack ARN:
...

✨  Total time: 4.29s

Dev/DatabaseStack (Dev-DatabaseStack)
Dev/DatabaseStack (Dev-DatabaseStack): deploying... [2/2]

 ✅  Dev/DatabaseStack (Dev-DatabaseStack)

✨  Deployment time: 1.09s

Stack ARN:
...

✨  Total time: 4.27s
```

# AWS Construcciones CDK
<a name="constructs"></a>

Las construcciones son los componentes básicos de las aplicaciones del AWS Cloud Development Kit (AWS CDK). Una construcción es un componente de la aplicación que representa uno o más AWS CloudFormation recursos y su configuración. Para crear la aplicación, pieza por pieza, se importan y configuran constructos.

## Importación y uso de constructos
<a name="constructs-import"></a>

Los constructos son clases que se importan a las aplicaciones de CDK desde la [Biblioteca de constructos de AWS](libraries.md#libraries-construct). 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 for Terraform (CDKtf), CDK for Kubernetes (CDK8s) y. Projen

Numerosos terceros también han publicado construcciones compatibles con la CDK. AWS Visite [Construct Hub](https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&offset=0) para explorar el ecosistema de socios de AWS CDK Construct.

## Niveles de constructos
<a name="constructs-lib-levels"></a>

Las construcciones de la biblioteca AWS Construct 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.<a name="constructs-lib-levels-one"></a>

 **Construcciones 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 construcción de L1 se asigna directamente a un único recurso. AWS CloudFormation Con las construcciones de L1, se importa una construcción que representa un recurso específico. AWS CloudFormation A continuación, usted define las propiedades del recurso en la instancia del constructo.  
Las construcciones L1 son ideales para utilizarlas cuando se conoce AWS CloudFormation y se necesita un control total sobre la definición de las propiedades de los recursos. AWS   
En la biblioteca de AWS construcciones, las construcciones de L1 se nombran empezando por`Cfn`, seguido de un identificador para el AWS CloudFormation recurso que representan. Por ejemplo, la [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.CfnBucket.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.CfnBucket.html)construcción es una construcción L1 que representa un recurso. [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) AWS CloudFormation   
Los constructos L1 se generan a partir de la [especificación del recurso AWS CloudFormation .](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html) Si existe un recurso en AWS CloudFormation, estará disponible en la AWS CDK como una construcción L1. Es posible que los nuevos recursos o propiedades tarden hasta una semana en estar disponibles en la biblioteca de AWS Construct. Para obtener más información, consulte la [referencia sobre los tipos de AWS recursos y propiedades](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html) en la *Guía del AWS CloudFormation usuario*.<a name="constructs-lib-levels-two"></a>

 **Construcciones 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. Las construcciones de L2 se asignan directamente a AWS CloudFormation recursos individuales, de forma similar a las construcciones de 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. Muchas de estas funciones también están disponibles como bloques de construcción independientes denominados [Mixins](mixins.md), que se pueden aplicar a las construcciones L1 y L2 mediante este método. `.with()`  
La clase [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) es un ejemplo de constructo L2 para un recurso de bucket de Amazon Simple Storage Service (Amazon S3).  
La biblioteca de AWS construcciones contiene construcciones de nivel 2 que se denominan estables y listas 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.<a name="constructs-lib-levels-three"></a>

 **Construcciones 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. Las construcciones L3 se utilizan para crear AWS arquitecturas 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 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs_patterns.ApplicationLoadBalancedFargateService.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs_patterns.ApplicationLoadBalancedFargateService.html)clase es un ejemplo de una construcción de nivel 3 que representa un servicio de AWS Fargate que se ejecuta en un clúster de Amazon Elastic Container Service (Amazon ECS) y que está encabezado por un balanceador de carga de aplicaciones.  
Al igual que las construcciones L2, las construcciones L3 que están listas para su uso en producción se incluyen en la biblioteca Construct. AWS Los que están en desarrollo se ofrecen en módulos separados.

## Definición de constructos
<a name="constructs-define"></a>

### Composición
<a name="constructs-composition"></a>

 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, las construcciones se utilizan para organizar los AWS recursos 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
<a name="constructs-init"></a>

Los constructos se implementan en clases que amplían la clase base [https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html). 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](apps.md#apps-tree). Por lo general, debería pasar `this` (`self` en Python), que representa el objeto actual, para el ámbito.
+  **identificador**: un [identificador](identifiers.md) 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 los [nombres de los recursos](resources.md#resources-physical-names) y los lógicos. AWS CloudFormation IDs

  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](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tag.html) 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
<a name="constructs-config"></a>

La mayoría de las construcciones aceptan `props` como tercer argumento (o en Python, argumentos de palabras clave), una name/value colección que define la configuración de la construcción. En el siguiente ejemplo, se define un depósito con el cifrado del Servicio de administración de AWS claves (AWS KMS) y el alojamiento de sitios web estáticos activados. Como no especifica explícitamente una clave de cifrado, el constructo `Bucket` define un nuevo `kms.Key` y lo asocia al bucket.

**Example**  

```
new s3.Bucket(this, 'MyEncryptedBucket', {
  encryption: s3.BucketEncryption.KMS,
  websiteIndexDocument: 'index.html'
});
```

```
new s3.Bucket(this, 'MyEncryptedBucket', {
  encryption: s3.BucketEncryption.KMS,
  websiteIndexDocument: 'index.html'
});
```

```
s3.Bucket(self, "MyEncryptedBucket", encryption=s3.BucketEncryption.KMS,
    website_index_document="index.html")
```

```
Bucket.Builder.create(this, "MyEncryptedBucket")
        .encryption(BucketEncryption.KMS_MANAGED)
        .websiteIndexDocument("index.html").build();
```

```
new Bucket(this, "MyEncryptedBucket", new BucketProps
{
    Encryption = BucketEncryption.KMS_MANAGED,
    WebsiteIndexDocument = "index.html"
});
```

```
	awss3.NewBucket(stack, jsii.String("MyEncryptedBucket"), &awss3.BucketProps{
		Encryption: awss3.BucketEncryption_KMS,
		WebsiteIndexDocument: jsii.String("index.html"),
	})
```

### Interacción con constructos
<a name="constructs-interact"></a>

Los constructos son clases que amplían la clase base [constructo](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html) 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 APIs las construcciones. Los autores pueden definir cualquier API que deseen. Sin embargo, las AWS construcciones que se incluyen en la biblioteca AWS Construct, por ejemplo`s3.Bucket`, siguen pautas y patrones comunes. Esto proporciona una experiencia coherente en todos los AWS recursos.

La mayoría de AWS las construcciones tienen un conjunto de métodos de [concesión](permissions.md#permissions-grants) que puede utilizar para conceder permisos de AWS Identity and Access Management (IAM) sobre esa construcción a un principal. En el siguiente ejemplo se concede al grupo de IAM el permiso `data-science` para leer del bucket `raw-data` de Amazon S3.

**Example**  

```
const rawData = new s3.Bucket(this, 'raw-data');
const dataScience = new iam.Group(this, 'data-science');
rawData.grants.read(dataScience);
```

```
const rawData = new s3.Bucket(this, 'raw-data');
const dataScience = new iam.Group(this, 'data-science');
rawData.grants.read(dataScience);
```

```
raw_data = s3.Bucket(self, 'raw-data')
data_science = iam.Group(self, 'data-science')
raw_data.grants.read(data_science)
```

```
Bucket rawData = new Bucket(this, "raw-data");
Group dataScience = new Group(this, "data-science");
rawData.getGrants().read(dataScience);
```

```
var rawData = new Bucket(this, "raw-data");
var dataScience = new Group(this, "data-science");
rawData.Grants.Read(dataScience);
```

```
	rawData := awss3.NewBucket(stack, jsii.String("raw-data"), nil)
	dataScience := awsiam.NewGroup(stack, jsii.String("data-science"), nil)
	rawData.Grants().Read(dataScience, nil)
```

Otro patrón común es que AWS las construcciones establezcan uno de los atributos del recurso a partir de datos suministrados en otros lugares. Los atributos pueden incluir nombres de recursos de Amazon (ARNs), nombres o URLs.

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.

**Example**  

```
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
  }
});
```

```
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
  }
});
```

```
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
    )
)
```

```
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();
```

```
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
    }
});
```

```
	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 AWS Construct, consulte Resources and the CDK. AWS](resources.md)

### Añada funciones con Mixins
<a name="constructs-mixins"></a>

Los mixins son funciones componibles que se pueden aplicar a cualquier construcción mediante el método. `.with()` Los mixins te permiten añadir funcionalidad a las construcciones L1 y L2 sin tener que usar una construcción diferente ni escribir código de bajo nivel.

Por ejemplo, puede habilitar el control de versiones y bloquear el acceso público en un bucket de Amazon S3, ya sea un L1 `CfnBucket` o un L2: `Bucket`

**Example**  

```
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';

// Apply mixins to an L1 construct
new s3.CfnBucket(this, 'MyBucket')
  .with(new s3.mixins.BucketVersioning())
  .with(new s3.mixins.BucketBlockPublicAccess());

// Apply mixins to an L2 construct
new s3.Bucket(this, 'MyL2Bucket', { removalPolicy: cdk.RemovalPolicy.DESTROY })
  .with(new s3.mixins.BucketAutoDeleteObjects());
```

```
const cdk = require('aws-cdk-lib');
const s3 = require('aws-cdk-lib/aws-s3');

// Apply mixins to an L1 construct
new s3.CfnBucket(this, 'MyBucket')
  .with(new s3.mixins.BucketVersioning())
  .with(new s3.mixins.BucketBlockPublicAccess());

// Apply mixins to an L2 construct
new s3.Bucket(this, 'MyL2Bucket', { removalPolicy: cdk.RemovalPolicy.DESTROY })
  .with(new s3.mixins.BucketAutoDeleteObjects());
```

```
import aws_cdk as cdk
import aws_cdk.aws_s3 as s3

# Apply mixins to an L1 construct
s3.CfnBucket(self, "MyBucket") \
    .with_(s3.mixins.BucketVersioning()) \
    .with_(s3.mixins.BucketBlockPublicAccess())

# Apply mixins to an L2 construct
s3.Bucket(self, "MyL2Bucket", removal_policy=cdk.RemovalPolicy.DESTROY) \
    .with_(s3.mixins.BucketAutoDeleteObjects())
```

```
import software.amazon.awscdk.*;
import software.amazon.awscdk.services.s3.*;

// Apply mixins to an L1 construct
CfnBucket bucket = new CfnBucket(this, "MyBucket");
bucket.with(new BucketVersioning());
bucket.with(new BucketBlockPublicAccess());

// Apply mixins to an L2 construct
Bucket l2Bucket = Bucket.Builder.create(this, "MyL2Bucket")
        .removalPolicy(RemovalPolicy.DESTROY)
        .build();
l2Bucket.with(new BucketAutoDeleteObjects());
```

```
using Amazon.CDK;
using Amazon.CDK.AWS.S3;

// Apply mixins to an L1 construct
var bucket = new CfnBucket(this, "MyBucket");
bucket.With(new BucketVersioning());
bucket.With(new BucketBlockPublicAccess());

// Apply mixins to an L2 construct
var l2Bucket = new Bucket(this, "MyL2Bucket", new BucketProps
{
    RemovalPolicy = RemovalPolicy.DESTROY
});
l2Bucket.With(new BucketAutoDeleteObjects());
```

```
bucket := awss3.NewCfnBucket(stack, jsii.String("MyBucket"), nil)
bucket.With(awss3.NewBucketVersioning())
bucket.With(awss3.NewBucketBlockPublicAccess())

l2Bucket := awss3.NewBucket(stack, jsii.String("MyL2Bucket"), &awss3.BucketProps{
    RemovalPolicy: awscdk.RemovalPolicy_DESTROY,
})
l2Bucket.With(awss3.NewBucketAutoDeleteObjects())
```

Los mixins están disponibles en el espacio de `mixins` nombres de cada módulo de servicio (por ejemplo,). `s3.mixins` Cada mixin se dirige a un tipo de recurso específico y lleva el nombre de ese recurso. Al aplicar un mixin a una construcción de L2, se aplica automáticamente al recurso de L1 subyacente.

[Para obtener más información sobre las mezclas, consulte las mezclas.](mixins.md)

### El constructo de la aplicación y la pila
<a name="constructs-apps-stacks"></a>

[https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html)Las clases [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html)y de la biblioteca AWS Construct son construcciones únicas. En comparación con otras construcciones, no configuran AWS los recursos por sí mismas. En cambio, se utilizan para proporcionar contexto para los otros constructos. Todos los constructos que representan AWS recursos deben definirse, directa o indirectamente, dentro del ámbito de un `Stack` constructo. `Stack`los constructos se definen dentro del ámbito de un `App` constructo.

Para obtener más información sobre las aplicaciones de CDK, consulte [Aplicaciones de AWS CDK](apps.md). Para obtener más información sobre las pilas de CDK, consulte [Introducción a AWS](stacks.md) las pilas de 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.

**Example**  

```
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");
```

```
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");
```

```
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")
```
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();
    }
}
```

```
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 });
        }
    }
}
```

```
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
<a name="constructs-work"></a>

### Trabajo con constructos L1
<a name="constructs-l1-using"></a>

L1 crea un mapa directamente a los recursos individuales. AWS CloudFormation Usted debe brindar la configuración solicitada del recurso.

En este ejemplo, creamos un objeto `bucket` utilizando el constructo L1 `CfnBucket`:

**Example**  

```
const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", {
  bucketName: "amzn-s3-demo-bucket"
});
```

```
const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", {
  bucketName: "amzn-s3-demo-bucket"
});
```

```
bucket = s3.CfnBucket(self, "amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket")
```

```
CfnBucket bucket = new CfnBucket.Builder().bucketName("amzn-s3-demo-bucket").build();
```

```
var bucket = new CfnBucket(this, "amzn-s3-demo-bucket", new CfnBucketProps
{
    BucketName= "amzn-s3-demo-bucket"
});
```

```
	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.

**Example**  

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

```
const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", {
  bucketName: "amzn-s3-demo-bucket",
  corsConfiguration: {
    corsRules: [{
          allowedOrigins: ["*"],
          allowedMethods: ["GET"]
    }]
  }
});
```
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"]
        )]
    )
)
```
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();
```
En C\$1, 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" },
            }
        }
    }
});
```
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"},
				},
			},
		},
	})
```

**importante**  
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.

#### Hacer referencia a recursos de otras construcciones
<a name="constructs-resource-references"></a>

Al configurar las propiedades de construcción que hacen referencia a otros recursos de AWS, tiene dos opciones equivalentes:
+  **Referencias a cadenas**: pase valores de cadena explícitos ARNs, como nombres u otros identificadores de recursos
+  **Referencias a objetos**: pase los objetos de construcción directamente. Esto evita tener que determinar qué tipo de identificador espera una propiedad: el CDK se encarga de ello.

##### Uso de referencias a cadenas
<a name="_using_string_references"></a>

Siempre puedes pasar valores de cadena explícitos ARNs, como nombres u otros identificadores de recursos. Este enfoque funciona para todas las propiedades y es obligatorio para las propiedades anidadas dentro de objetos complejos.

En el siguiente ejemplo, se crea una función Lambda mediante una construcción L1 (`CfnFunction`) con una función definida mediante una construcción L2 (). `Role` El ARN del rol se pasa a la `role` propiedad:

**Example**  

```
const role = new iam.Role(this, 'MyRole', {
  assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
  managedPolicies: [
    iam.ManagedPolicy.fromAwsManagedPolicyName(
      'service-role/AWSLambdaBasicExecutionRole'
    ),
  ],
});

const myFunction = new lambda.CfnFunction(this, 'HelloWorldFunction', {
  runtime: 'nodejs24.x',
  role: role.roleArn, // Pass the ARN string explicitly
  handler: 'index.handler',
  code: {
    zipFile: `
    exports.handler = async function(event) {
      return {
        statusCode: 200,
        body: JSON.stringify('Hello World!'),
      };
    };
  `}
});
```

```
const role = new iam.Role(this, 'MyRole', {
  assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
  managedPolicies: [
    iam.ManagedPolicy.fromAwsManagedPolicyName(
      'service-role/AWSLambdaBasicExecutionRole'
    )
  ]
});

const myFunction = new lambda.CfnFunction(this, "HelloWorldFunction", {
  runtime: 'nodejs24.x',
  role: role.roleArn, // Pass the ARN string explicitly
  handler: 'index.handler',
  code: {
    zipFile: `
    exports.handler = async function(event) {
      return {
        statusCode: 200,
        body: JSON.stringify('Hello World!'),
      };
    };
  `}
});
```

```
role = iam.Role(self, "MyRole",
    assumed_by=iam.ServicePrincipal("lambda.amazonaws.com"),
    managed_policies=[
        iam.ManagedPolicy.from_aws_managed_policy_name(
            "service-role/AWSLambdaBasicExecutionRole"
        )
    ]
)

my_function = _lambda.CfnFunction(self, "HelloWorldFunction",
    runtime="nodejs24.x",
    role=role.role_arn,  # Pass the ARN string explicitly
    handler="index.handler",
    code=_lambda.CfnFunction.CodeProperty(
        zip_file=
        """
        exports.handler = async function(event) {
          return {
            statusCode: 200,
            body: JSON.stringify('Hello World!'),
          };
        };
        """
    )
)
```

```
Role role = Role.Builder.create(this, "MyRole")
    .assumedBy(new ServicePrincipal("lambda.amazonaws.com"))
    .managedPolicies(Arrays.asList(
        ManagedPolicy.fromAwsManagedPolicyName(
            "service-role/AWSLambdaBasicExecutionRole"
        )
    ))
    .build();

CfnFunction myFunction = CfnFunction.Builder.create(this, "HelloWorldFunction")
    .runtime("nodejs24.x")
    .role(role.getRoleArn())  // Pass the ARN string explicitly
    .handler("index.handler")
    .code(CfnFunction.CodeProperty.builder()
        .zipFile(
            "exports.handler = async function(event) {" +
            "  return {" +
            "    statusCode: 200," +
            "    body: JSON.stringify('Hello World!')," +
            "  };" +
            "};")
        .build())
    .build();
```

```
var role = new Role(this, "MyRole", new RoleProps
{
    AssumedBy = new ServicePrincipal("lambda.amazonaws.com"),
    ManagedPolicies = new[]
    {
        ManagedPolicy.FromAwsManagedPolicyName(
            "service-role/AWSLambdaBasicExecutionRole"
        )
    }
});

var myFunction = new CfnFunction(this, "HelloWorldFunction", new CfnFunctionProps
{
    Runtime = "nodejs24.x",
    Role = role.RoleArn,  // Pass the ARN string explicitly
    Handler = "index.handler",
    Code = new CfnFunction.CodeProperty
    {
        ZipFile = @"
        exports.handler = async function(event) {
          return {
            statusCode: 200,
            body: JSON.stringify('Hello World!'),
          };
        };
        "
    }
});
```

```
role := awsiam.NewRole(stack, jsii.String("MyRole"), &awsiam.RoleProps{
	AssumedBy: awsiam.NewServicePrincipal(jsii.String("lambda.amazonaws.com"), nil),
	ManagedPolicies: &[]awsiam.IManagedPolicy{
		awsiam.ManagedPolicy_FromAwsManagedPolicyName(jsii.String("service-role/AWSLambdaBasicExecutionRole")),
	},
})

myFunction := awslambda.NewCfnFunction(stack, jsii.String("HelloWorldFunction"), &awslambda.CfnFunctionProps{
	Runtime: jsii.String("nodejs24.x"),
	Role:    role.RoleArn(), // Pass the ARN string explicitly
	Handler: jsii.String("index.handler"),
	Code: &awslambda.CfnFunction_CodeProperty{
		ZipFile: jsii.String(`
		exports.handler = async function(event) {
		  return {
		    statusCode: 200,
		    body: JSON.stringify('Hello World!'),
		  };
		};
		`),
	},
})
```

##### Uso de referencias a objetos
<a name="_using_object_references"></a>

Para las propiedades seleccionadas, puede pasar los objetos de construcción directamente en lugar de extraer sus atributos manualmente. El soporte para referencias a objetos varía según la propiedad y puede ampliarse con el tiempo a medida que se agreguen nuevas propiedades.

Al pasar una referencia de objeto en la construcción`props`, la CDK la resuelve en el valor de cadena adecuado (como un ARN, un nombre u otro identificador). Si posteriormente accedes a la propiedad correspondiente de la instancia de construcción, verás este valor de cadena resuelto, no la referencia del objeto original.

Las referencias a objetos solo funcionan para las propiedades de nivel superior de los componentes fijos. Las propiedades anidadas dentro de objetos complejos requieren valores de cadena explícitos.

El siguiente ejemplo muestra la misma función Lambda, pero utilizando el objeto de rol en lugar de la cadena ARN del rol:

**Example**  

```
const role = new iam.Role(this, 'MyRole', {
  assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
  managedPolicies: [
    iam.ManagedPolicy.fromAwsManagedPolicyName(
      'service-role/AWSLambdaBasicExecutionRole'
    ),
  ],
});

const myFunction = new lambda.CfnFunction(this, 'HelloWorldFunction', {
  runtime: 'nodejs24.x',
  role: role, // CDK resolves to role ARN automatically
  handler: 'index.handler',
  code: {
    zipFile: `
    exports.handler = async function(event) {
      return {
        statusCode: 200,
        body: JSON.stringify('Hello World!'),
      };
    };
  `}
});

// After creation, myFunction.role contains the resolved ARN string
```

```
const role = new iam.Role(this, 'MyRole', {
  assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
  managedPolicies: [
    iam.ManagedPolicy.fromAwsManagedPolicyName(
      'service-role/AWSLambdaBasicExecutionRole'
    )
  ]
});

const myFunction = new lambda.CfnFunction(this, "HelloWorldFunction", {
  runtime: 'nodejs24.x',
  role: role, // CDK resolves to role ARN automatically
  handler: 'index.handler',
  code: {
    zipFile: `
    exports.handler = async function(event) {
      return {
        statusCode: 200,
        body: JSON.stringify('Hello World!'),
      };
    };
  `}
});

// After creation, myFunction.role contains the resolved ARN string
```

```
role = iam.Role(self, "MyRole",
    assumed_by=iam.ServicePrincipal("lambda.amazonaws.com"),
    managed_policies=[
        iam.ManagedPolicy.from_aws_managed_policy_name(
            "service-role/AWSLambdaBasicExecutionRole"
        )
    ]
)

my_function = _lambda.CfnFunction(self, "HelloWorldFunction",
    runtime="nodejs24.x",
    role=role,  # CDK resolves to role ARN automatically
    handler="index.handler",
    code=_lambda.CfnFunction.CodeProperty(
        zip_file=
        """
        exports.handler = async function(event) {
          return {
            statusCode: 200,
            body: JSON.stringify('Hello World!'),
          };
        };
        """
    )
)

# After creation, my_function.role contains the resolved ARN string
```

```
Role role = Role.Builder.create(this, "MyRole")
    .assumedBy(new ServicePrincipal("lambda.amazonaws.com"))
    .managedPolicies(Arrays.asList(
        ManagedPolicy.fromAwsManagedPolicyName(
            "service-role/AWSLambdaBasicExecutionRole"
        )
    ))
    .build();

CfnFunction myFunction = CfnFunction.Builder.create(this, "HelloWorldFunction")
    .runtime("nodejs24.x")
    .role(role)  // CDK resolves to role ARN automatically
    .handler("index.handler")
    .code(CfnFunction.CodeProperty.builder()
        .zipFile(
            "exports.handler = async function(event) {" +
            "  return {" +
            "    statusCode: 200," +
            "    body: JSON.stringify('Hello World!')," +
            "  };" +
            "};")
        .build())
    .build();

// After creation, myFunction.getRole() contains the resolved ARN string
```

```
var role = new Role(this, "MyRole", new RoleProps
{
    AssumedBy = new ServicePrincipal("lambda.amazonaws.com"),
    ManagedPolicies = new[]
    {
        ManagedPolicy.FromAwsManagedPolicyName(
            "service-role/AWSLambdaBasicExecutionRole"
        )
    }
});

var myFunction = new CfnFunction(this, "HelloWorldFunction", new CfnFunctionProps
{
    Runtime = "nodejs24.x",
    Role = role,  // CDK resolves to role ARN automatically
    Handler = "index.handler",
    Code = new CfnFunction.CodeProperty
    {
        ZipFile = @"
        exports.handler = async function(event) {
          return {
            statusCode: 200,
            body: JSON.stringify('Hello World!'),
          };
        };
        "
    }
});

// After creation, myFunction.Role contains the resolved ARN string
```

```
role := awsiam.NewRole(stack, jsii.String("MyRole"), &awsiam.RoleProps{
	AssumedBy: awsiam.NewServicePrincipal(jsii.String("lambda.amazonaws.com"), nil),
	ManagedPolicies: &[]awsiam.IManagedPolicy{
		awsiam.ManagedPolicy_FromAwsManagedPolicyName(jsii.String("service-role/AWSLambdaBasicExecutionRole")),
	},
})

myFunction := awslambda.NewCfnFunction(stack, jsii.String("HelloWorldFunction"), &awslambda.CfnFunctionProps{
	Runtime: jsii.String("nodejs24.x"),
	Role:    role, // CDK resolves to role ARN automatically
	Handler: jsii.String("index.handler"),
	Code: &awslambda.CfnFunction_CodeProperty{
		ZipFile: jsii.String(`
		exports.handler = async function(event) {
		  return {
		    statusCode: 200,
		    body: JSON.stringify('Hello World!'),
		  };
		};
		`),
	},
})

// After creation, *myFunction.Role() contains the resolved ARN string
```

### Trabajo con constructos L2
<a name="constructs-using"></a>

En el siguiente ejemplo, definimos un bucket de Amazon S3 mediante la creación de un objeto a partir del constructo L2 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html):

**Example**  

```
import * as s3 from 'aws-cdk-lib/aws-s3';

// "this" is HelloCdkStack
new s3.Bucket(this, 'MyFirstBucket', {
  versioned: true
});
```

```
const s3 = require('aws-cdk-lib/aws-s3');

// "this" is HelloCdkStack
new s3.Bucket(this, 'MyFirstBucket', {
  versioned: true
});
```

```
import aws_cdk.aws_s3 as s3

# "self" is HelloCdkStack
s3.Bucket(self, "MyFirstBucket", versioned=True)
```

```
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();
    }
}
```

```
using Amazon.CDK.AWS.S3;

// "this" is HelloCdkStack
new Bucket(this, "MyFirstBucket", new BucketProps
{
    Versioned = true
});
```

```
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 depósito que AWS CloudFormation se crea. Es un identificador lógico que se asigna al nuevo constructo en el contexto de la aplicación CDK. El valor [PhysicalName](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Resource.html#physicalname) se utilizará para asignar un nombre al AWS CloudFormation recurso.

## Trabajo con constructos de terceros
<a name="constructs-work-third"></a>

 [Construct Hub](https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&sort=downloadsDesc&offset=0) es un recurso que le ayuda a descubrir otras construcciones de terceros y de AWS la comunidad de CDK de código abierto.

### Escritura de sus propios constructos
<a name="constructs-author"></a>

Además de usar los constructos existentes, también puede escribir los suyos propios y permitir que cualquiera los use en sus aplicaciones. Todas las construcciones son iguales en el CDK. AWS Los constructos de la biblioteca AWS Construct se tratan de la misma manera que los constructos de una biblioteca de terceros publicada medianteNPM,, 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](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html) 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.

**Example**  

```
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 });
  }
}
```

```
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 }
```

```
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))
```

```
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());
     }
}
```

```
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
        });
    }
}
```

```
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
}
```

**nota**  
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 cuando se desarrollan 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:

**Example**  

```
new NotifyingBucket(this, 'MyNotifyingBucket');
```

```
new NotifyingBucket(this, 'MyNotifyingBucket');
```

```
NotifyingBucket(self, "MyNotifyingBucket")
```

```
new NotifyingBucket(this, "MyNotifyingBucket");
```

```
new NotifyingBucket(this, "MyNotifyingBucket");
```

```
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:

**Example**  

```
new NotifyingBucket(this, 'MyNotifyingBucket', { prefix: 'images/' });
```

```
new NotifyingBucket(this, 'MyNotifyingBucket', { prefix: 'images/' });
```

```
NotifyingBucket(self, "MyNotifyingBucket", prefix="images/")
```

```
new NotifyingBucket(this, "MyNotifyingBucket", "/images");
```

```
new NotifyingBucket(this, "MyNotifyingBucket", new NotifyingBucketProps
{
    Prefix = "/images"
});
```

```
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:

**Example**  

```
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 });
  }
}
```

```
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 };
```

```
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))
```

```
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());
     }
}
```

```
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
        });
    }
}
```
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:

**Example**  

```
const queue = new sqs.Queue(this, 'NewImagesQueue');
const images = new NotifyingBucket(this, '/images');
images.topic.addSubscription(new sns_sub.SqsSubscription(queue));
```

```
const queue = new sqs.Queue(this, 'NewImagesQueue');
const images = new NotifyingBucket(this, '/images');
images.topic.addSubscription(new sns_sub.SqsSubscription(queue));
```

```
queue = sqs.Queue(self, "NewImagesQueue")
images = NotifyingBucket(self, prefix="Images")
images.topic.add_subscription(sns_sub.SqsSubscription(queue))
```

```
NotifyingBucket images = new NotifyingBucket(this, "MyNotifyingBucket", "/images");
images.topic.addSubscription(new SqsSubscription(queue));
```

```
var queue = new Queue(this, "NewImagesQueue");
var images = new NotifyingBucket(this, "MyNotifyingBucket", new NotifyingBucketProps
{
    Prefix = "/images"
});
images.topic.AddSubscription(new SqsSubscription(queue));
```

```
	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
<a name="constructs-learn"></a>

El siguiente video ofrece una visión general completa de los constructos de CDK y explica cómo utilizarlas en sus aplicaciones de CDK.

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/PzU-i0rJPGw?rel=0/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/PzU-i0rJPGw?rel=0)


# Mezclas
<a name="mixins"></a>

Las mezclas son funciones reutilizables que se aplican a las construcciones mediante este método. `.with()` Añaden funciones a las construcciones L1 (CloudFormationnivel) y L2 (basadas en la intención), como el control de versiones, la eliminación automática de objetos o el bloqueo del acceso público. Cada mezcla funciona en un único recurso. Para conectar dos recursos, usa Facades en [su](facades.md) lugar.

Cada mezcla se dirige a un tipo de recurso específico y lleva el nombre de ese recurso. Por ejemplo, se `BucketVersioning` dirige a los buckets de Amazon S3. Puede acceder a mixins a través del espacio de `mixins` nombres de cada módulo de servicio, por ejemplo. `s3.mixins`

## Aplica Mixins
<a name="mixins-basic"></a>

Las mezclas se aplican mediante el `.with()` método, que está disponible en todas las construcciones. Puede encadenar varias mezclas:

**Example**  

```
import * as s3 from 'aws-cdk-lib/aws-s3';

const bucket = new s3.CfnBucket(this, 'MyBucket')
  .with(new s3.mixins.BucketVersioning())
  .with(new s3.mixins.BucketBlockPublicAccess());
```

```
const s3 = require('aws-cdk-lib/aws-s3');

const bucket = new s3.CfnBucket(this, 'MyBucket')
  .with(new s3.mixins.BucketVersioning())
  .with(new s3.mixins.BucketBlockPublicAccess());
```

```
import aws_cdk.aws_s3 as s3

bucket = s3.CfnBucket(self, "MyBucket") \
    .with_(s3.mixins.BucketVersioning()) \
    .with_(s3.mixins.BucketBlockPublicAccess())
```

```
import software.amazon.awscdk.services.s3.*;

CfnBucket bucket = new CfnBucket(this, "MyBucket");
bucket.with(new BucketVersioning());
bucket.with(new BucketBlockPublicAccess());
```

```
using Amazon.CDK.AWS.S3;

var bucket = new CfnBucket(this, "MyBucket");
bucket.With(new BucketVersioning());
bucket.With(new BucketBlockPublicAccess());
```

```
bucket := awss3.NewCfnBucket(stack, jsii.String("MyBucket"), nil)
bucket.With(awss3.NewBucketVersioning())
bucket.With(awss3.NewBucketBlockPublicAccess())
```

Cada mixin declara qué tipos de recursos admite. Si aplicas un mixin a una construcción que no admite, se omite silenciosamente. Esto significa que puedes aplicar mezclas de forma amplia y segura sin preocuparte por los desajustes de tipos. [Si necesita asegurarse de aplicar una mezcla, utilice o. `requireAll()``requireAny()`](#mixins-advanced)

## Utilice mezclas con las construcciones L1 y L2
<a name="mixins-l1-l2"></a>

Las mixinas funcionan con las construcciones L1 y L2. Cuando se aplica una mezcla a una construcción de L2, también se aplica al recurso de L1 subyacente.

El siguiente ejemplo muestra cómo aplicar mixins a las construcciones L1 y L2:

**Example**  

```
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';

// Using a mixin with an L1 construct
new s3.CfnBucket(this, 'L1Bucket')
  .with(new s3.mixins.BucketVersioning());

// Using a mixin with an L2 construct
new s3.Bucket(this, 'L2Bucket', {
  removalPolicy: cdk.RemovalPolicy.DESTROY,
}).with(new s3.mixins.BucketAutoDeleteObjects());
```

```
const cdk = require('aws-cdk-lib');
const s3 = require('aws-cdk-lib/aws-s3');

// Using a mixin with an L1 construct
new s3.CfnBucket(this, 'L1Bucket')
  .with(new s3.mixins.BucketVersioning());

// Using a mixin with an L2 construct
new s3.Bucket(this, 'L2Bucket', {
  removalPolicy: cdk.RemovalPolicy.DESTROY,
}).with(new s3.mixins.BucketAutoDeleteObjects());
```

```
import aws_cdk as cdk
import aws_cdk.aws_s3 as s3

# Using a mixin with an L1 construct
s3.CfnBucket(self, "L1Bucket") \
    .with_(s3.mixins.BucketVersioning())

# Using a mixin with an L2 construct
s3.Bucket(self, "L2Bucket",
    removal_policy=cdk.RemovalPolicy.DESTROY,
).with_(s3.mixins.BucketAutoDeleteObjects())
```

```
import software.amazon.awscdk.*;
import software.amazon.awscdk.services.s3.*;

// Using a mixin with an L1 construct
CfnBucket l1Bucket = new CfnBucket(this, "L1Bucket");
l1Bucket.with(new BucketVersioning());

// Using a mixin with an L2 construct
Bucket l2Bucket = Bucket.Builder.create(this, "L2Bucket")
        .removalPolicy(RemovalPolicy.DESTROY)
        .build();
l2Bucket.with(new BucketAutoDeleteObjects());
```

```
using Amazon.CDK;
using Amazon.CDK.AWS.S3;

// Using a mixin with an L1 construct
var l1Bucket = new CfnBucket(this, "L1Bucket");
l1Bucket.With(new BucketVersioning());

// Using a mixin with an L2 construct
var l2Bucket = new Bucket(this, "L2Bucket", new BucketProps
{
    RemovalPolicy = RemovalPolicy.DESTROY
});
l2Bucket.With(new BucketAutoDeleteObjects());
```

```
l1Bucket := awss3.NewCfnBucket(stack, jsii.String("L1Bucket"), nil)
l1Bucket.With(awss3.NewBucketVersioning())

l2Bucket := awss3.NewBucket(stack, jsii.String("L2Bucket"), &awss3.BucketProps{
    RemovalPolicy: awscdk.RemovalPolicy_DESTROY,
})
l2Bucket.With(awss3.NewBucketAutoDeleteObjects())
```

## Propiedades de mezcla frente a propiedades de construcción
<a name="mixins-vs-props"></a>

Las propiedades de mezcla y construcción funcionan juntas. Las propiedades de construcción L2 configuran un recurso al crearlo. Las mezclas se pueden aplicar en cualquier momento.

Utilice las propiedades del constructo L2 cuando  
Está utilizando una construcción L2 y la propiedad que necesita está disponible. Este es el enfoque más simple.

Use Mixins cuando  
+ Está trabajando con una construcción L1 y desea características similares a las de L2.
+ Desea añadir una función a una construcción de L2 que no esté disponible como propiedad.
+ Desea aplicar la misma función en varios componentes fijos de diferentes tipos.

Las mezclas no sustituyen a las propiedades de construcción. No pueden hacer que una propiedad obligatoria sea opcional ni cambiar los valores por defecto.

## Aplique mixins a varias construcciones
<a name="mixins-advanced"></a>

La `Mixins.of()` API proporciona un mayor control sobre cómo se aplican los mixins en un ámbito. En lugar de recurrir a `.with()` constructos individuales, puedes aplicar un mixin a todos los constructos coincidentes de una pila o ámbito a la vez:

**Example**  

```
import { Mixins } from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';

// Apply to all supported constructs in the stack
Mixins.of(stack).apply(new s3.mixins.BucketVersioning());
```

```
const { Mixins } = require('aws-cdk-lib');
const s3 = require('aws-cdk-lib/aws-s3');

// Apply to all supported constructs in the stack
Mixins.of(stack).apply(new s3.mixins.BucketVersioning());
```

```
from aws_cdk import Mixins
import aws_cdk.aws_s3 as s3

# Apply to all supported constructs in the stack
Mixins.of(stack).apply(s3.mixins.BucketVersioning())
```

```
import software.amazon.awscdk.Mixins;
import software.amazon.awscdk.services.s3.*;

// Apply to all supported constructs in the stack
Mixins.of(stack).apply(new BucketVersioning());
```

```
using Amazon.CDK;
using Amazon.CDK.AWS.S3;

// Apply to all supported constructs in the stack
Mixins.Of(stack).Apply(new BucketVersioning());
```

```
awscdk.Mixins_Of(stack, nil).Apply(awss3.NewBucketVersioning())
```

De forma predeterminada, las construcciones que no admiten el mixin se omiten silenciosamente. Se usa `requireAll()` para afirmar que el mixin se aplica a todos los constructos de la selección o `requireAny()` para afirmar que se aplica al menos a uno. Esto resulta útil para garantizar que los recursos tengan una configuración requerida:

**Example**  

```
// Throws an error if any construct in the scope doesn't support the mixin
Mixins.of(stack)
  .requireAll()
  .apply(new s3.mixins.BucketVersioning());
```

```
// Throws an error if any construct in the scope doesn't support the mixin
Mixins.of(stack)
  .requireAll()
  .apply(new s3.mixins.BucketVersioning());
```

```
# Throws an error if any construct in the scope doesn't support the mixin
Mixins.of(stack) \
    .require_all() \
    .apply(s3.mixins.BucketVersioning())
```

```
// Throws an error if any construct in the scope doesn't support the mixin
Mixins.of(stack)
        .requireAll()
        .apply(new BucketVersioning());
```

```
// Throws an error if any construct in the scope doesn't support the mixin
Mixins.Of(stack)
    .RequireAll()
    .Apply(new BucketVersioning());
```

```
awscdk.Mixins_Of(stack, nil).RequireAll().Apply(awss3.NewBucketVersioning())
```

## Mezclas y aspectos
<a name="mixins-aspects"></a>

Las mezclas y [los aspectos](aspects.md) están relacionados, pero tienen diferentes propósitos:
+  Los **mixins** se aplican inmediatamente cuando llamas. `.with()` Usted elige exactamente a qué constructos aplicarlos.
+  **Los aspectos** se aplican durante la síntesis a todos los constructos de un osciloscopio. Úselos para políticas y controles generales.

Utilice Mixins para añadir una función a construcciones específicas. Use Aspects para hacer cumplir las reglas o aplicar cambios en toda la aplicación.

## Recursos relacionados
<a name="mixins-related"></a>
+  [Facades](facades.md): conecte los recursos con los directores de IAM y otros servicios.
+  [Aspectos](aspects.md): aplique cambios o valide construcciones en toda la aplicación.
+  [Construcciones: obtenga información sobre las construcciones](constructs.md) L1, L2 y L3.
+  [Personalice las construcciones](cfn-layer.md): personalice las construcciones con trampillas de escape y anulaciones sin procesar.

# Fachadas
<a name="facades"></a>

Las fachadas son clases que conectan un recurso con otras partes de la aplicación. Cada fachada se dirige a un tipo de recurso. Por ejemplo, el nombre de la clase se `BucketGrants` debe a que permite el acceso a los buckets de Amazon S3. Las fachadas funcionan con construcciones L1 (CloudFormationnivel) y L2 (basadas en la intención).

Algunas fachadas se generan y están listas para usarse con la mayoría de los recursos, como las clases de métricas y reflections. Otras se crean manualmente para los recursos que necesitan una lógica personalizada, como las clases de Grants.

## Otorga clases
<a name="facades-grants"></a>

Las clases de fachadas más utilizadas son las subvencionadas. Permiten conceder acceso a AWS los recursos mediante métodos sencillos. Por ejemplo, puede usarlo `BucketGrants` para los buckets de Amazon S3 y `TopicGrants` para los temas de Amazon SNS.

Las construcciones L2 tienen una `grants` propiedad que facilita el acceso. También puede crear una clase Grants a partir de una construcción L1 utilizando su método de fábrica. El siguiente ejemplo muestra ambos enfoques:

**Example**  

```
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as iam from 'aws-cdk-lib/aws-iam';

// myRole is an IAM role defined elsewhere in your app

// Using grants on an L2 construct (via the grants property)
const l2Bucket = new s3.Bucket(this, 'L2Bucket');
l2Bucket.grants.read(myRole);

// Using grants on an L1 construct (via the factory method)
const l1Bucket = new s3.CfnBucket(this, 'L1Bucket');
s3.BucketGrants.fromBucket(l1Bucket).read(myRole);
```

```
const s3 = require('aws-cdk-lib/aws-s3');
const iam = require('aws-cdk-lib/aws-iam');

// myRole is an IAM role defined elsewhere in your app

// Using grants on an L2 construct (via the grants property)
const l2Bucket = new s3.Bucket(this, 'L2Bucket');
l2Bucket.grants.read(myRole);

// Using grants on an L1 construct (via the factory method)
const l1Bucket = new s3.CfnBucket(this, 'L1Bucket');
s3.BucketGrants.fromBucket(l1Bucket).read(myRole);
```

```
import aws_cdk.aws_s3 as s3
import aws_cdk.aws_iam as iam

# my_role is an IAM role defined elsewhere in your app

# Using grants on an L2 construct (via the grants property)
l2_bucket = s3.Bucket(self, "L2Bucket")
l2_bucket.grants.read(my_role)

# Using grants on an L1 construct (via the factory method)
l1_bucket = s3.CfnBucket(self, "L1Bucket")
s3.BucketGrants.from_bucket(l1_bucket).read(my_role)
```

```
import software.amazon.awscdk.services.s3.*;
import software.amazon.awscdk.services.iam.*;

// myRole is an IAM role defined elsewhere in your app

// Using grants on an L2 construct (via the grants property)
Bucket l2Bucket = new Bucket(this, "L2Bucket");
l2Bucket.getGrants().read(myRole);

// Using grants on an L1 construct (via the factory method)
CfnBucket l1Bucket = new CfnBucket(this, "L1Bucket");
BucketGrants.fromBucket(l1Bucket).read(myRole);
```

```
using Amazon.CDK.AWS.S3;
using Amazon.CDK.AWS.IAM;

// myRole is an IAM role defined elsewhere in your app

// Using grants on an L2 construct (via the grants property)
var l2Bucket = new Bucket(this, "L2Bucket");
l2Bucket.Grants.Read(myRole);

// Using grants on an L1 construct (via the factory method)
var l1Bucket = new CfnBucket(this, "L1Bucket");
BucketGrants.FromBucket(l1Bucket).Read(myRole);
```

```
import (
	"github.com/aws/jsii-runtime-go"
	awss3 "github.com/aws/aws-cdk-go/awscdk/v2/awss3"
)

// myRole is an IAM role defined elsewhere in your app

l2Bucket := awss3.NewBucket(stack, jsii.String("L2Bucket"), nil)
l2Bucket.Grants().Read(myRole, nil)

l1Bucket := awss3.NewCfnBucket(stack, jsii.String("L1Bucket"), nil)
awss3.BucketGrants_FromBucket(l1Bucket).Read(myRole, nil)
```

Para obtener más información sobre las concesiones y los permisos, consulte [Concesiones](permissions.md#permissions-grants).

## Utilice fachadas con mixins
<a name="facades-mixins-together"></a>

Puedes combinar Facades con [Mixins](mixins.md) para obtener una experiencia completa similar a la de L2 con construcciones de L1. Usa Mixins para configurar el recurso y Facades para conceder acceso:

**Example**  

```
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as iam from 'aws-cdk-lib/aws-iam';

// Configure the resource with Mixins
const bucket = new s3.CfnBucket(this, 'MyBucket')
  .with(new s3.mixins.BucketVersioning())
  .with(new s3.mixins.BucketBlockPublicAccess());

// Grant permissions using a Facade
const role = new iam.Role(this, 'MyRole', {
  assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
});
s3.BucketGrants.fromBucket(bucket).read(role);
```

```
const s3 = require('aws-cdk-lib/aws-s3');
const iam = require('aws-cdk-lib/aws-iam');

// Configure the resource with Mixins
const bucket = new s3.CfnBucket(this, 'MyBucket')
  .with(new s3.mixins.BucketVersioning())
  .with(new s3.mixins.BucketBlockPublicAccess());

// Grant permissions using a Facade
const role = new iam.Role(this, 'MyRole', {
  assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
});
s3.BucketGrants.fromBucket(bucket).read(role);
```

```
import aws_cdk.aws_s3 as s3
import aws_cdk.aws_iam as iam

# Configure the resource with Mixins
bucket = s3.CfnBucket(self, "MyBucket") \
    .with_(s3.mixins.BucketVersioning()) \
    .with_(s3.mixins.BucketBlockPublicAccess())

# Grant permissions using a Facade
role = iam.Role(self, "MyRole",
    assumed_by=iam.ServicePrincipal("lambda.amazonaws.com"),
)
s3.BucketGrants.from_bucket(bucket).read(role)
```

```
import software.amazon.awscdk.services.s3.*;
import software.amazon.awscdk.services.iam.*;

// Configure the resource with Mixins
CfnBucket bucket = new CfnBucket(this, "MyBucket");
bucket.with(new BucketVersioning());
bucket.with(new BucketBlockPublicAccess());

// Grant permissions using a Facade
Role role = Role.Builder.create(this, "MyRole")
        .assumedBy(new ServicePrincipal("lambda.amazonaws.com"))
        .build();
BucketGrants.fromBucket(bucket).read(role);
```

```
using Amazon.CDK.AWS.S3;
using Amazon.CDK.AWS.IAM;

// Configure the resource with Mixins
var bucket = new CfnBucket(this, "MyBucket");
bucket.With(new BucketVersioning());
bucket.With(new BucketBlockPublicAccess());

// Grant permissions using a Facade
var role = new Role(this, "MyRole", new RoleProps
{
    AssumedBy = new ServicePrincipal("lambda.amazonaws.com")
});
BucketGrants.FromBucket(bucket).Read(role);
```

```
bucket := awss3.NewCfnBucket(stack, jsii.String("MyBucket"), nil)
bucket.With(awss3.NewBucketVersioning())
bucket.With(awss3.NewBucketBlockPublicAccess())

role := awsiam.NewRole(stack, jsii.String("MyRole"), &awsiam.RoleProps{
    AssumedBy: awsiam.NewServicePrincipal(jsii.String("lambda.amazonaws.com"), nil),
})
awss3.BucketGrants_FromBucket(bucket).Read(role, nil)
```

## Recursos relacionados
<a name="facades-related"></a>
+  [Mixins](mixins.md): añade funciones reutilizables a las construcciones L1 y L2.
+  [Concesiones: otorga](permissions.md#permissions-grants) permisos entre recursos.
+  [Construcciones: obtenga información sobre las construcciones](constructs.md) L1, L2 y L3.

# Entornos para el AWS CDK
<a name="environments"></a>

Un entorno consta de la cuenta de AWS y la región de AWS en las que se implementa una pila de AWS Cloud Development Kit (AWS CDK).

 ** AWS Cuenta de**   
Al crear una cuenta de AWS, recibirá un ID de cuenta. Este ID es un número de 12 dígitos, como **012345678901**, que identifica de forma única a la cuenta. Para obtener más información, consulte [Visualización de identificadores de la cuenta de AWS](https://docs.aws.amazon.com/accounts/latest/reference/manage-acct-identifiers.html) en la *Guía de referencia de administración de cuentas de AWS*.

 ** AWS Región de**   
 Las regiones de AWS se nombran mediante una combinación de una ubicación geográfica y un número que representa una Zona de disponibilidad en la Región. Por ejemplo, **us-east-1** representa una Zona de disponibilidad de la Región Este de EE. UU. (Norte de Virginia) Para obtener más información acerca de las regiones de AWS, consulte [Regiones y Zonas de disponibilidad](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/). Para obtener una lista de códigos de región, consulte [Puntos de conexión regionales](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints) en la *Guía de referencia general de AWS*.

El AWS CDK puede determinar los entornos a partir de sus credenciales y archivos de configuración. Estos archivos se pueden crear y administrar con la interfaz de la línea de comandos de AWS (AWS CLI). A continuación, se muestra un ejemplo básico de estos archivos:

 **Archivo de credenciales**   

```
[default]
aws_access_key_id=ASIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
aws_session_token = IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZVERYLONGSTRINGEXAMPLE

[user1]
aws_access_key_id=ASIAI44QH8DHBEXAMPLE
aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY
aws_session_token = fcZib3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZVERYLONGSTRINGEXAMPLE
```

 **Archivo de configuración**   

```
[default]
region=us-west-2
output=json

[profile user1]
region=us-east-1
output=text
```

Puede pasar la información del entorno desde estos archivos en el código de CDK a través de las variables del entorno que proporciona CDK. Cuando ejecuta un comando de la CLI de CDK, por ejemplo `cdk deploy`, proporciona el perfil de sus credenciales y archivos de configuración para recopilar información del entorno.

A continuación, se muestra un ejemplo de cómo especificar estas variables del entorno en el código CDK:

```
new MyDevStack(app, 'dev', {
  env: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: process.env.CDK_DEFAULT_REGION
}});
```

A continuación, se muestra un ejemplo de cómo pasar los valores asociados al perfil `user1` desde sus credenciales y archivos de configuración a la CLI de CDK mediante la opción `--profile`. Los valores de estos archivos se pasarán a las variables del entorno:

```
$ cdk deploy <myStack> --profile <user1>
```

En lugar de utilizar los valores de las credenciales y los archivos de configuración, puede hacer una codificación rígida de los valores del entorno en su código CDK. A continuación, se muestra un ejemplo:

```
const envEU = { account: '238383838383', region: 'eu-west-1' };
const envUSA = { account: '837873873873', region: 'us-west-2' };

new MyFirstStack(app, 'first-stack-us', { env: envUSA });
new MyFirstStack(app, 'first-stack-eu', { env: envEU });
```

## Más información
<a name="environments-learn"></a>

Para empezar a utilizar entornos con el AWS CDK, consulte [Configurar entornos para utilizarlos con el AWS CDK](configure-env.md)

# Arranque de AWS CDK
<a name="bootstrapping"></a>

 El *arranque* es el proceso para preparar el entorno de AWS para su uso con AWS Cloud Development Kit (AWS CDK). Antes de implementar una pila de CDK en un entorno de AWS, primero se debe arrancar el entorno.

## ¿Qué es el arranque?
<a name="bootstrapping-what"></a>

El arranque prepara su entorno de AWS a través del aprovisionamiento de recursos de AWS específicos en su entorno que son utilizados por AWS CDK. Estos recursos suelen denominarse *recursos de arranque*. Incluyen lo siguiente:
+  El **bucket de Amazon Simple Storage Service (Amazon S3)**: se utiliza para almacenar los archivos de los proyectos de CDK, por ejemplo, el código de función y los activos de AWS Lambda.
+  **Repositorio de Amazon Elastic Container Registry (Amazon ECR)**: se utiliza principalmente para almacenar imágenes de Docker.
+  **Roles de AWS Identity and Access Management (IAM)**: configurados para conceder los permisos necesarios de AWS CDK para realizar las implementaciones. Para obtener más información sobre los roles de IAM creados durante el arranque, consulte [Roles de IAM creados durante el arranque](bootstrapping-env.md#bootstrapping-env-roles).

## ¿Cómo funciona el arranque?
<a name="bootstrapping-how"></a>

Los recursos y la configuración que utiliza CDK se definen en una plantilla de AWS CloudFormation. El equipo de CDK crea y administra esta plantilla. Para ver la versión más reciente de esta plantilla, consulte [https://github.com/aws/aws-cdk-cli/blob/main/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml](https://github.com/aws/aws-cdk-cli/blob/main/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml) en el *repositorio aws-cdk de aws-cdk-cli GitHub*.

Para arrancar un entorno, utilice el comando `cdk bootstrap` de la interfaz de la línea de comandos de AWS CDK (CLI de AWS CDK). La CLI de CDK recupera la plantilla y la implementa en AWS CloudFormation como a pila, conocida como *pila de arranque*. De forma predeterminada, el nombre de la pila es `CDKToolkit`. Al implementar esta plantilla, CloudFormation aprovisiona los recursos de su entorno. Tras la implementación, la pila de arranque aparecerá en la consola de AWS CloudFormation de su entorno.

También puede personalizar el arranque al modificar la plantilla o tras utilizar las opciones de la CLI de CDK con el comando `cdk bootstrap`.

 Los entornos de AWS son independientes. Primero debe arrancar cada entorno que desee utilizar con AWS CDK.

## Más información
<a name="bootstrapping-learn"></a>

Para obtener instrucciones sobre el arranque de su entorno, consulte [Arranque su entorno para utilizarlo con el AWS CDK](bootstrapping-env.md).

# Los recursos y el AWS CDK
<a name="resources"></a>

 Los *recursos* son lo que se configura para usar AWS los servicios en las aplicaciones. Los recursos son una característica de AWS CloudFormation. Al configurar los recursos y sus propiedades en una AWS CloudFormation plantilla, puede implementarlos AWS CloudFormation para aprovisionar sus recursos. Con el AWS Cloud Development Kit (AWS CDK), puede configurar los recursos mediante construcciones. A continuación, debe implementar su aplicación CDK, lo que implica sintetizar una AWS CloudFormation plantilla e implementarla para AWS CloudFormation aprovisionar sus recursos.

## Configuración de recursos mediante constructos
<a name="resources-configure"></a>

*Como se describe en [AWS CDK Constructs](constructs.md), la AWS CDK proporciona una amplia biblioteca de clases de construcciones, denominadas construcciones, que representan todos los recursos.* AWS 

Para crear una instancia de un recurso utilizando su constructo correspondiente, introduzca el ámbito como primer argumento, el identificador lógico del constructo y un conjunto de propiedades de configuración (props). Por ejemplo, aquí se explica cómo crear una cola de Amazon SQS con cifrado AWS KMS mediante la [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sqs.Queue.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sqs.Queue.html)construcción de la AWS biblioteca Construct.

**Example**  

```
import * as sqs from '@aws-cdk/aws-sqs';

new sqs.Queue(this, 'MyQueue', {
    encryption: sqs.QueueEncryption.KMS_MANAGED
});
```

```
const sqs = require('@aws-cdk/aws-sqs');

new sqs.Queue(this, 'MyQueue', {
    encryption: sqs.QueueEncryption.KMS_MANAGED
});
```

```
import aws_cdk.aws_sqs as sqs

sqs.Queue(self, "MyQueue", encryption=sqs.QueueEncryption.KMS_MANAGED)
```

```
import software.amazon.awscdk.services.sqs.*;

Queue.Builder.create(this, "MyQueue").encryption(
        QueueEncryption.KMS_MANAGED).build();
```

```
using Amazon.CDK.AWS.SQS;

new Queue(this, "MyQueue", new QueueProps
{
    Encryption = QueueEncryption.KMS_MANAGED
});
```

```
import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/jsii-runtime-go"
  sqs "github.com/aws/aws-cdk-go/awscdk/v2/awssqs"
)

sqs.NewQueue(stack, jsii.String("MyQueue"), &sqs.QueueProps{
  Encryption: sqs.QueueEncryption_KMS_MANAGED,
})
```

Algunos props de configuración son opcionales y, en muchos casos, tienen valores predeterminados. En algunos casos, todos los props son opcionales y el último argumento se puede omitir por completo.

### Atributos de recursos
<a name="resources-attributes"></a>

La mayoría de los recursos de la biblioteca AWS Construct muestran los atributos, que se resuelven en el momento de la implementación mediante. AWS CloudFormation Los atributos se exponen en forma de propiedades en las clases de recursos con el nombre del tipo como prefijo. En el siguiente ejemplo de código se muestra cómo obtener la URL de una cola de Amazon SQS usando la propiedad `queueUrl` (Python: `queue_url`).

**Example**  

```
import * as sqs from '@aws-cdk/aws-sqs';

const queue = new sqs.Queue(this, 'MyQueue');
const url = queue.queueUrl; // => A string representing a deploy-time value
```

```
const sqs = require('@aws-cdk/aws-sqs');

const queue = new sqs.Queue(this, 'MyQueue');
const url = queue.queueUrl; // => A string representing a deploy-time value
```

```
import aws_cdk.aws_sqs as sqs

queue = sqs.Queue(self, "MyQueue")
url = queue.queue_url # => A string representing a deploy-time value
```

```
Queue queue = new Queue(this, "MyQueue");
String url = queue.getQueueUrl();    // => A string representing a deploy-time value
```

```
var queue = new Queue(this, "MyQueue");
var url = queue.QueueUrl; // => A string representing a deploy-time value
```

```
import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/jsii-runtime-go"
  sqs "github.com/aws/aws-cdk-go/awscdk/v2/awssqs"
)

queue := sqs.NewQueue(stack, jsii.String("MyQueue"), &sqs.QueueProps{})
url := queue.QueueUrl() // => A string representing a deploy-time value
```

Consulte [Tokens y la AWS CDK](tokens.md) para obtener información sobre cómo la AWS CDK codifica los atributos de tiempo de despliegue como cadenas.

## Recursos de referencia
<a name="resources-referencing"></a>

Al configurar los recursos, a menudo tendrá que hacer referencia a las propiedades de otro recurso. A continuación se muestran algunos ejemplos:
+ Un recurso de Amazon Elastic Container Service (Amazon ECS) requiere una referencia al clúster en el que se ejecuta.
+ Una CloudFront distribución de Amazon requiere una referencia al bucket de Amazon Simple Storage Service (Amazon S3) que contiene el código fuente.

Puede hacer referencia a recursos en algunas de las siguientes maneras:
+ Transfiriendo un recurso definido en su aplicación de CDK, ya sea en la misma pila o en una diferente.
+ Al pasar un objeto proxy que hace referencia a un recurso definido en su AWS cuenta, creado a partir de un identificador único del recurso (como un ARN)

Si la propiedad de un constructo representa un constructo de otro recurso, su tipo es el del tipo de interfaz del constructo. Por ejemplo, el constructo Amazon ECS toma una propiedad `cluster` de tipo `ecs.ICluster`. Otro ejemplo es la construcción CloudFront de distribución que toma una propiedad `sourceBucket` (Python:`source_bucket`) de tipo`s3.IBucket`.

Puedes pasar directamente cualquier objeto de recurso del tipo adecuado definido en la misma aplicación de AWS CDK. En el siguiente ejemplo se define un clúster de Amazon ECS y, a continuación, se utiliza para definir un servicio de Amazon ECS.

**Example**  

```
const cluster = new ecs.Cluster(this, 'Cluster', { /*...*/ });

const service = new ecs.Ec2Service(this, 'Service', { cluster: cluster });
```

```
const cluster = new ecs.Cluster(this, 'Cluster', { /*...*/ });

const service = new ecs.Ec2Service(this, 'Service', { cluster: cluster });
```

```
cluster = ecs.Cluster(self, "Cluster")

service = ecs.Ec2Service(self, "Service", cluster=cluster)
```

```
Cluster cluster = new Cluster(this, "Cluster");
Ec2Service service = new Ec2Service(this, "Service",
        new Ec2ServiceProps.Builder().cluster(cluster).build());
```

```
var cluster = new Cluster(this, "Cluster");
var service = new Ec2Service(this, "Service", new Ec2ServiceProps { Cluster = cluster });
```

```
import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/jsii-runtime-go"
  ecs "github.com/aws/aws-cdk-go/awscdk/v2/awsecs"
)

cluster := ecs.NewCluster(stack, jsii.String("MyCluster"), &ecs.ClusterProps{})
service := ecs.NewEc2Service(stack, jsii.String("MyService"), &ecs.Ec2ServiceProps{
  Cluster: cluster,
})
```

### Referencia de recursos en una pila diferente
<a name="resource-stack"></a>

Puedes hacer referencia a los recursos de una pila diferente siempre que estén definidos en la misma aplicación y en el mismo AWS entorno. Generalmente, se utiliza el siguiente patrón:
+ Guarde una referencia al constructo como atributo de la pila que produce el recurso. (Para obtener una referencia a la pila del constructo actual, utilice `Stack.of(this)`).
+ Pase esta referencia al constructor de la pila que consume el recurso como parámetro o propiedad. Luego, la pila consumidora la pasa como una propiedad a cualquier constructo que la necesite.

En el ejemplo siguiente se define una pila `stack1`. Esta pila define un bucket de Amazon S3 y almacena una referencia al constructo del bucket como atributo de la pila. A continuación, la aplicación define una segunda pila`stack2`, que acepta un depósito en el momento de la instanciación. `stack2`podría, por ejemplo, definir una AWS Glue Table que utilice el depósito para el almacenamiento de datos.

**Example**  

```
const prod = { account: '123456789012', region: 'us-east-1' };

const stack1 = new StackThatProvidesABucket(app, 'Stack1', { env: prod });

// stack2 will take a property { bucket: IBucket }
const stack2 = new StackThatExpectsABucket(app, 'Stack2', {
  bucket: stack1.bucket,
  env: prod
});
```

```
const prod = { account: '123456789012', region: 'us-east-1' };

const stack1 = new StackThatProvidesABucket(app, 'Stack1', { env: prod });

// stack2 will take a property { bucket: IBucket }
const stack2 = new StackThatExpectsABucket(app, 'Stack2', {
  bucket: stack1.bucket,
  env: prod
});
```

```
prod = core.Environment(account="123456789012", region="us-east-1")

stack1 = StackThatProvidesABucket(app, "Stack1", env=prod)

# stack2 will take a property "bucket"
stack2 = StackThatExpectsABucket(app, "Stack2", bucket=stack1.bucket, env=prod)
```

```
// Helper method to build an environment
static Environment makeEnv(String account, String region) {
    return Environment.builder().account(account).region(region)
            .build();
}

App app = new App();

Environment prod = makeEnv("123456789012", "us-east-1");

StackThatProvidesABucket stack1 = new StackThatProvidesABucket(app, "Stack1",
        StackProps.builder().env(prod).build());

// stack2 will take an argument "bucket"
StackThatExpectsABucket stack2 = new StackThatExpectsABucket(app, "Stack,",
        StackProps.builder().env(prod).build(), stack1.bucket);
```

```
Amazon.CDK.Environment makeEnv(string account, string region)
{
    return new Amazon.CDK.Environment { Account = account, Region = region };
}

var prod = makeEnv(account: "123456789012", region: "us-east-1");

var stack1 = new StackThatProvidesABucket(app, "Stack1", new StackProps { Env = prod });

// stack2 will take a property "bucket"
var stack2 = new StackThatExpectsABucket(app, "Stack2", new StackProps { Env = prod,
    bucket = stack1.Bucket});
```

Si el AWS CDK determina que el recurso se encuentra en el mismo entorno, pero en una pila diferente, sintetiza automáticamente AWS CloudFormation [las exportaciones](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html) de la pila de producción y una [https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html)de la pila consumidora para transferir esa información de una pila a otra.

#### Resolución de interbloqueos de dependencia
<a name="resources-deadlock"></a>

Al hacer referencia a un recurso de una pila en una pila diferente, se crea una dependencia entre las dos pilas. Esto garantiza que se implementen en el orden correcto. Una vez implementadas las pilas, esta dependencia es concreta. Después de eso, eliminar el uso del recurso compartido de la pila que lo consume puede provocar un error de implementación inesperado. Esto ocurre si existe otra dependencia entre las dos pilas que obligue a implementarlas en el mismo orden. También puede ocurrir sin una dependencia si el kit de herramientas de CDK simplemente elige la pila de producción para implementarla primero. La AWS CloudFormation exportación se elimina de la pila de producción porque ya no es necesaria, pero el recurso exportado se sigue utilizando en la pila de consumo porque su actualización aún no se ha implementado. Por lo tanto, se produce un error al implementar la pila de productores.

Para salir de este bloqueo, elimine el uso del recurso compartido de la pila que lo consume. (Esto elimina la exportación automática de la pila de producción). A continuación, agregue manualmente la misma exportación a la pila de producción utilizando exactamente el mismo identificador lógico que la exportación generada automáticamente. Elimine el uso del recurso compartido en la pila consumidora e implemente ambas pilas. A continuación, elimine la exportación manual (y el recurso compartido si ya no es necesario) y vuelva a implementar ambas pilas. El método [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#exportwbrvalueexportedvalue-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#exportwbrvalueexportedvalue-options) de la pila es una forma cómoda de crear la exportación manual para este propósito. (Consulte el ejemplo en la referencia del método vinculado).

### Haciendo referencia a los recursos de tu cuenta AWS
<a name="resources-external"></a>

Supongamos que quieres usar un recurso que ya está disponible en tu AWS cuenta en tu aplicación AWS CDK. Puede ser un recurso que se definió a través de la consola, un AWS SDK, directamente con AWS CloudFormation o en una aplicación de AWS CDK diferente. Puede convertir el ARN del recurso (u otro atributo de identificación o grupo de atributos) en un objeto proxy. El objeto proxy sirve como referencia al recurso al llamar a un método de fábrica estático de la clase del recurso.

Al crear un proxy de este tipo, el recurso externo **no pasa** a formar parte de la aplicación de AWS CDK. Por lo tanto, los cambios que realices en el proxy de tu aplicación de AWS CDK no afectan al recurso implementado. Sin embargo, el proxy se puede pasar a cualquier método de AWS CDK que requiera un recurso de ese tipo.

El siguiente ejemplo muestra cómo hacer referencia a un bucket basado en un bucket existente con el ARN `arn:aws:s3:::amzn-s3-demo-bucket1` y una Amazon Virtual Private Cloud basada en una VPC existente con un identificador específico.

**Example**  

```
// Construct a proxy for a bucket by its name (must be same account)
s3.Bucket.fromBucketName(this, 'MyBucket', 'amzn-s3-demo-bucket1');

// Construct a proxy for a bucket by its full ARN (can be another account)
s3.Bucket.fromBucketArn(this, 'MyBucket', 'arn:aws:s3:::amzn-s3-demo-bucket1');

// Construct a proxy for an existing VPC from its attribute(s)
ec2.Vpc.fromVpcAttributes(this, 'MyVpc', {
  vpcId: 'vpc-1234567890abcde',
});
```

```
// Construct a proxy for a bucket by its name (must be same account)
s3.Bucket.fromBucketName(this, 'MyBucket', 'amzn-s3-demo-bucket1');

// Construct a proxy for a bucket by its full ARN (can be another account)
s3.Bucket.fromBucketArn(this, 'MyBucket', 'arn:aws:s3:::amzn-s3-demo-bucket1');

// Construct a proxy for an existing VPC from its attribute(s)
ec2.Vpc.fromVpcAttributes(this, 'MyVpc', {
  vpcId: 'vpc-1234567890abcde'
});
```

```
# Construct a proxy for a bucket by its name (must be same account)
s3.Bucket.from_bucket_name(self, "MyBucket", "amzn-s3-demo-bucket1")

# Construct a proxy for a bucket by its full ARN (can be another account)
s3.Bucket.from_bucket_arn(self, "MyBucket", "arn:aws:s3:::amzn-s3-demo-bucket1")

# Construct a proxy for an existing VPC from its attribute(s)
ec2.Vpc.from_vpc_attributes(self, "MyVpc", vpc_id="vpc-1234567890abcdef")
```

```
// Construct a proxy for a bucket by its name (must be same account)
Bucket.fromBucketName(this, "MyBucket", "amzn-s3-demo-bucket1");

// Construct a proxy for a bucket by its full ARN (can be another account)
Bucket.fromBucketArn(this, "MyBucket",
        "arn:aws:s3:::amzn-s3-demo-bucket1");

// Construct a proxy for an existing VPC from its attribute(s)
Vpc.fromVpcAttributes(this, "MyVpc", VpcAttributes.builder()
        .vpcId("vpc-1234567890abcdef").build());
```

```
// Construct a proxy for a bucket by its name (must be same account)
Bucket.FromBucketName(this, "MyBucket", "amzn-s3-demo-bucket1");

// Construct a proxy for a bucket by its full ARN (can be another account)
Bucket.FromBucketArn(this, "MyBucket", "arn:aws:s3:::amzn-s3-demo-bucket1");

// Construct a proxy for an existing VPC from its attribute(s)
Vpc.FromVpcAttributes(this, "MyVpc", new VpcAttributes
{
    VpcId = "vpc-1234567890abcdef"
});
```

```
// Define a proxy for a bucket by its name (must be same account)
s3.Bucket_FromBucketName(stack, jsii.String("MyBucket"), jsii.String("amzn-s3-demo-bucket1"))

// Define a proxy for a bucket by its full ARN (can be another account)
s3.Bucket_FromBucketArn(stack, jsii.String("MyBucket"), jsii.String("arn:aws:s3:::amzn-s3-demo-bucket1"))

// Define a proxy for an existing VPC from its attributes
ec2.Vpc_FromVpcAttributes(stack, jsii.String("MyVpc"), &ec2.VpcAttributes{
  VpcId: jsii.String("vpc-1234567890abcde"),
})
```

Echemos un vistazo más de cerca al método [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.Vpc.html#static-fromwbrlookupscope-id-options](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.Vpc.html#static-fromwbrlookupscope-id-options). Como el constructo `ec2.Vpc` es complejo, hay muchas maneras de seleccionar la VPC que se va a usar con la aplicación de CDK. Para solucionar este problema, la construcción de VPC tiene un método `fromLookup` estático (Python:`from_lookup`) que le permite buscar la Amazon VPC deseada consultando su AWS cuenta en el momento de la síntesis.

Para utilizar `Vpc.fromLookup()`, el sistema que sintetiza la pila debe tener acceso a la cuenta propietaria de la VPC de Amazon. Esto se debe a que el kit de herramientas de CDK consulta la cuenta para encontrar la VPC de Amazon adecuada en el momento de la síntesis.

Además, solo `Vpc.fromLookup()` funciona en pilas definidas con una **cuenta** y una **región** explícitas (consulte [Entornos para](environments.md) ver el CDK). AWS Si la AWS CDK intenta buscar una Amazon VPC desde [una pila independiente del entorno, el kit de](stacks.md#stack-api) herramientas de la CDK no sabrá qué entorno consultar para encontrar la VPC.

Debe proporcionar `Vpc.fromLookup()` atributos suficientes para identificar de forma exclusiva una VPC en su AWS cuenta. Por ejemplo, solo puede haber una VPC predeterminada, por lo que basta con especificar la VPC como predeterminada.

**Example**  

```
ec2.Vpc.fromLookup(this, 'DefaultVpc', {
  isDefault: true
});
```

```
ec2.Vpc.fromLookup(this, 'DefaultVpc', {
  isDefault: true
});
```

```
ec2.Vpc.from_lookup(self, "DefaultVpc", is_default=True)
```

```
Vpc.fromLookup(this, "DefaultVpc", VpcLookupOptions.builder()
        .isDefault(true).build());
```

```
Vpc.FromLookup(this, id = "DefaultVpc", new VpcLookupOptions { IsDefault = true });
```

```
ec2.Vpc_FromLookup(this, jsii.String("DefaultVpc"), &ec2.VpcLookupOptions{
  IsDefault: jsii.Bool(true),
})
```

También puede usar la `tags` propiedad para realizar consultas VPCs por etiqueta. Puede añadir etiquetas a la Amazon VPC en el momento de su creación mediante la AWS CloudFormation CDK. AWS Puede editar las etiquetas en cualquier momento después de crearlas mediante la consola AWS de administración, la AWS CLI o un AWS SDK. Además de las etiquetas que añada usted mismo, la AWS CDK añade automáticamente las siguientes etiquetas a todo VPCs lo que crea.
+  **Nombre**: nombre de la VPC.
+  **aws-cdk:subnet-name**: nombre de la subred.
+  **aws-cdk:subnet-type:** tipo de subred: pública, privada o aislada.

**Example**  

```
ec2.Vpc.fromLookup(this, 'PublicVpc',
    {tags: {'aws-cdk:subnet-type': "Public"}});
```

```
ec2.Vpc.fromLookup(this, 'PublicVpc',
    {tags: {'aws-cdk:subnet-type': "Public"}});
```

```
ec2.Vpc.from_lookup(self, "PublicVpc",
    tags={"aws-cdk:subnet-type": "Public"})
```

```
Vpc.fromLookup(this, "PublicVpc", VpcLookupOptions.builder()
        .tags(java.util.Map.of("aws-cdk:subnet-type", "Public"))  // Java 9 or later
        .build());
```

```
Vpc.FromLookup(this, id: "PublicVpc", new VpcLookupOptions
{
    Tags = new Dictionary<string, string> { ["aws-cdk:subnet-type"] = "Public" }
});
```

```
ec2.Vpc_FromLookup(this, jsii.String("DefaultVpc"), &ec2.VpcLookupOptions{
  Tags: &map[string]*string{"aws-cdk:subnet-type": jsii.String("Public")},
})
```

Los resultados de `Vpc.fromLookup()` se almacenan en caché en el archivo `cdk.context.json` del proyecto. (Consulte [Los valores de contexto y la AWS CDK).](context.md) Confirme este archivo al control de versiones para que la aplicación siga haciendo referencia a la misma VPC de Amazon. Esto funciona incluso si más adelante cambias los atributos de tu VPCs VPC de forma que se seleccione una VPC diferente. Esto es especialmente importante si vas a implementar la pila en un entorno que no tiene acceso a la AWS cuenta que define la VPC, como CDK [Pipelines](cdk-pipeline.md).

Si bien puedes usar un recurso externo en cualquier lugar en el que utilices un recurso similar definido en tu aplicación de AWS CDK, no puedes modificarlo. Por ejemplo, llamar a `addToResourcePolicy` (Python: `add_to_resource_policy`) en un `s3.Bucket` externo no hace nada.

## Nombres físicos de los recursos
<a name="resources-physical-names"></a>

Los nombres lógicos de los recursos AWS CloudFormation son diferentes de los nombres de los recursos que aparecen en la Consola AWS de administración una vez implementados por AWS CloudFormation. El AWS CDK llama a estos nombres finales *nombres físicos*.

Por ejemplo, AWS CloudFormation podría crear el bucket de Amazon S3 con el ID lógico `Stack2MyBucket4DD88B4F` y el nombre físico`stack2MyBucket4dd88b4f-iuv1rbv9z3to`.

Puede especificar un nombre físico al crear constructo que representen recursos mediante la propiedad `<resourceType>Name`. En el siguiente ejemplo se crea un bucket de Amazon S3 con el nombre físico `amzn-s3-demo-bucket`.

**Example**  

```
const bucket = new s3.Bucket(this, 'MyBucket', {
  bucketName: 'amzn-s3-demo-bucket',
});
```

```
const bucket = new s3.Bucket(this, 'MyBucket', {
  bucketName: 'amzn-s3-demo-bucket'
});
```

```
bucket = s3.Bucket(self, "MyBucket", bucket_name="amzn-s3-demo-bucket")
```

```
Bucket bucket = Bucket.Builder.create(this, "MyBucket")
        .bucketName("amzn-s3-demo-bucket").build();
```

```
var bucket = new Bucket(this, "MyBucket", new BucketProps { BucketName = "amzn-s3-demo-bucket" });
```

```
bucket := s3.NewBucket(this, jsii.String("MyBucket"), &s3.BucketProps{
  BucketName: jsii.String("amzn-s3-demo-bucket"),
})
```

La asignación de nombres físicos a los recursos tiene algunas desventajas. AWS CloudFormation Y lo que es más importante, cualquier cambio en los recursos implementados que requiera la sustitución de un recurso, como los cambios en las propiedades de un recurso que sean inmutables tras su creación, fallará si a un recurso se le ha asignado un nombre físico. Si terminas en ese estado, la única solución es eliminar la AWS CloudFormation pila y volver a implementar la aplicación AWS CDK. Consulte la [documentación de AWS CloudFormation ](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) para obtener más detalles.

En algunos casos, como cuando se crea una aplicación de AWS CDK con referencias a varios entornos, se requieren nombres físicos para que la AWS CDK funcione correctamente. En esos casos, si no quieres molestarte en crear un nombre físico tú mismo, puedes dejar que el AWS CDK se lo ponga por ti. Para ello, use el valor especial `PhysicalName.GENERATE_IF_NEEDED`, de la siguiente manera.

**Example**  

```
const bucket = new s3.Bucket(this, 'MyBucket', {
  bucketName: core.PhysicalName.GENERATE_IF_NEEDED,
});
```

```
const bucket = new s3.Bucket(this, 'MyBucket', {
  bucketName: core.PhysicalName.GENERATE_IF_NEEDED
});
```

```
bucket = s3.Bucket(self, "MyBucket",
                         bucket_name=core.PhysicalName.GENERATE_IF_NEEDED)
```

```
Bucket bucket = Bucket.Builder.create(this, "MyBucket")
        .bucketName(PhysicalName.GENERATE_IF_NEEDED).build();
```

```
var bucket = new Bucket(this, "MyBucket", new BucketProps
    { BucketName = PhysicalName.GENERATE_IF_NEEDED });
```

```
bucket := s3.NewBucket(this, jsii.String("MyBucket"), &s3.BucketProps{
  BucketName: awscdk.PhysicalName_GENERATE_IF_NEEDED(),
})
```

## Pasar identificadores de recursos únicos
<a name="resources-identifiers"></a>

Siempre que sea posible, debe pasar recursos por referencia, como se describe en la sección anterior. Sin embargo, hay casos en los que no tiene otra opción que hacer referencia a un recurso por uno de sus atributos. Algunos ejemplos de casos de uso incluyen lo siguiente:
+ Cuando utilice recursos de bajo nivel. AWS CloudFormation 
+ Cuando necesita exponer los recursos a los componentes de tiempo de ejecución de una aplicación de AWS CDK, como cuando se hace referencia a las funciones de Lambda a través de variables de entorno.

Estos identificadores están disponibles como atributos en los recursos, como los siguientes.

**Example**  

```
bucket.bucketName
lambdaFunc.functionArn
securityGroup.groupArn
```

```
bucket.bucketName
lambdaFunc.functionArn
securityGroup.groupArn
```

```
bucket.bucket_name
lambda_func.function_arn
security_group_arn
```
El enlace de AWS CDK de Java utiliza métodos de captación para los atributos.  

```
bucket.getBucketName()
lambdaFunc.getFunctionArn()
securityGroup.getGroupArn()
```

```
bucket.BucketName
lambdaFunc.FunctionArn
securityGroup.GroupArn
```

```
bucket.BucketName()
fn.FunctionArn()
```

El siguiente ejemplo muestra cómo pasar un nombre de bucket generado a una función AWS Lambda.

**Example**  

```
const bucket = new s3.Bucket(this, 'Bucket');

new lambda.Function(this, 'MyLambda', {
  // ...
  environment: {
    BUCKET_NAME: bucket.bucketName,
  },
});
```

```
const bucket = new s3.Bucket(this, 'Bucket');

new lambda.Function(this, 'MyLambda', {
  // ...
  environment: {
    BUCKET_NAME: bucket.bucketName
  }
});
```

```
bucket = s3.Bucket(self, "Bucket")

lambda.Function(self, "MyLambda", environment=dict(BUCKET_NAME=bucket.bucket_name))
```

```
final Bucket bucket = new Bucket(this, "Bucket");

Function.Builder.create(this, "MyLambda")
        .environment(java.util.Map.of(    // Java 9 or later
                "BUCKET_NAME", bucket.getBucketName()))
        .build();
```

```
var bucket = new Bucket(this, "Bucket");

new Function(this, "MyLambda", new FunctionProps
{
    Environment = new Dictionary<string, string>
    {
        ["BUCKET_NAME"] = bucket.BucketName
    }
});
```

```
bucket := s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{})
lambda.NewFunction(this, jsii.String("MyLambda"), &lambda.FunctionProps{
  Environment: &map[string]*string{"BUCKET_NAME": bucket.BucketName()},
})
```

## Otorgar permisos entre recursos
<a name="resources-grants"></a>

Las construcciones de nivel superior permiten obtener permisos con privilegios mínimos al ofrecer requisitos de permiso expresos simples y basados en la intención. APIs Por ejemplo, muchas construcciones ofrecen métodos de concesión que se pueden utilizar para conceder a una entidad (por ejemplo, un rol o un usuario de IAM) permiso para trabajar con el recurso, sin tener que crear manualmente las declaraciones de permiso de IAM.

Los métodos de concesión están disponibles a través de las clases de subvenciones (por ejemplo, `BucketGrants` para los buckets de Amazon S3). Estas clases funcionan con construcciones L1 y L2. Las construcciones L2 muestran una `grants` propiedad por comodidad, pero también se puede crear una clase Grants directamente a partir de una construcción L1. Puedes combinar las clases de Grants con las [mixins](mixins.md) para conseguir una comodidad similar a la de L2 en las construcciones de L1.

El siguiente ejemplo crea los permisos para permitir que el rol de ejecución de una función de Lambda lea y escriba objetos en un bucket de Amazon S3 concreto. Si el bucket de Amazon S3 está cifrado con una clave AWS KMS, este método también concede permisos a la función de ejecución de la función Lambda para descifrar con la clave.

**Example**  

```
if (bucket.grants.readWrite(func).success) {
  // ...
}
```

```
if ( bucket.grants.readWrite(func).success) {
  // ...
}
```

```
if bucket.grants.read_write(func).success:
    # ...
```

```
if (bucket.getGrants().readWrite(func).getSuccess()) {
    // ...
}
```

```
if (bucket.Grants.ReadWrite(func).Success)
{
    // ...
}
```

```
if *bucket.Grants().ReadWrite(function, nil).Success() {
  // ...
}
```

Los métodos de concesión devuelven un objeto `iam.Grant`. Utilice el atributo `success` del objeto `Grant` para determinar si la subvención se aplicó de manera efectiva (por ejemplo, es posible que no se haya aplicado a [recursos externos](#resources-referencing)). También puede usar el método `assertSuccess` (Python: `assert_success`) del objeto `Grant` para garantizar que la concesión se haya aplicado correctamente.

Si un método de concesión específico no está disponible para un caso de uso concreto, puede usar un método de concesión genérico para definir una nueva concesión con una lista de acciones específica.

En el siguiente ejemplo se muestra cómo conceder acceso a una función de Lambda al `CreateBackup` de Amazon DynamoDB.

**Example**  

```
table.grants.actions(func, 'dynamodb:CreateBackup');
```

```
table.grants.actions(func, 'dynamodb:CreateBackup');
```

```
table.grants.actions(func, "dynamodb:CreateBackup")
```

```
table.getGrants().actions(func, "dynamodb:CreateBackup");
```

```
table.Grants.Actions(func, "dynamodb:CreateBackup");
```

```
table := dynamodb.NewTable(this, jsii.String("MyTable"), &dynamodb.TableProps{})
table.Grants().Actions(function, jsii.String("dynamodb:CreateBackup"))
```

Muchos recursos, como las funciones de Lambda, requieren que se asuma un rol al ejecutar el código. Una propiedad de configuración le permite especificar un `iam.IRole`. Si no se especifica ningún rol, la función crea automáticamente un rol específico para este uso. A continuación, puede utilizar métodos de concesión en los recursos para agregar declaraciones al rol.

Los métodos de concesión se diseñan con un nivel inferior APIs para su gestión con las políticas de IAM. Las políticas se modelan como objetos. [PolicyDocument](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyDocument.html) Agregue instrucciones directamente a los roles (o al rol adjunto de un constructo) mediante el método `addToRolePolicy` (Python: `add_to_role_policy`) o a la política de un recurso (como una política `Bucket`) mediante el método `addToResourcePolicy` (Python: `add_to_resource_policy`).

## Métricas de recursos y alarmas
<a name="resources-metrics"></a>

Muchos recursos emiten CloudWatch métricas que se pueden utilizar para configurar paneles de control y alarmas. Los constructos de nivel superior tienen métodos métricos que permiten acceder a las métricas sin tener que buscar el nombre correcto que se va a utilizar.

El siguiente ejemplo muestra cómo definir una alarma cuando el `ApproximateNumberOfMessagesNotVisible` de Amazon SQS supera 100.

**Example**  

```
import * as cw from '@aws-cdk/aws-cloudwatch';
import * as sqs from '@aws-cdk/aws-sqs';
import { Duration } from '@aws-cdk/core';

const queue = new sqs.Queue(this, 'MyQueue');

const metric = queue.metricApproximateNumberOfMessagesNotVisible({
  label: 'Messages Visible (Approx)',
  period: Duration.minutes(5),
  // ...
});
metric.createAlarm(this, 'TooManyMessagesAlarm', {
  comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD,
  threshold: 100,
  // ...
});
```

```
const cw = require('@aws-cdk/aws-cloudwatch');
const sqs = require('@aws-cdk/aws-sqs');
const { Duration } = require('@aws-cdk/core');

const queue = new sqs.Queue(this, 'MyQueue');

const metric = queue.metricApproximateNumberOfMessagesNotVisible({
  label: 'Messages Visible (Approx)',
  period: Duration.minutes(5)
  // ...
});
metric.createAlarm(this, 'TooManyMessagesAlarm', {
  comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD,
  threshold: 100
  // ...
});
```

```
import aws_cdk.aws_cloudwatch as cw
import aws_cdk.aws_sqs as sqs
from aws_cdk.core import Duration

queue = sqs.Queue(self, "MyQueue")
metric = queue.metric_approximate_number_of_messages_not_visible(
    label="Messages Visible (Approx)",
    period=Duration.minutes(5),
    # ...
)
metric.create_alarm(self, "TooManyMessagesAlarm",
    comparison_operator=cw.ComparisonOperator.GREATER_THAN_THRESHOLD,
    threshold=100,
    # ...
)
```

```
import software.amazon.awscdk.core.Duration;
import software.amazon.awscdk.services.sqs.Queue;
import software.amazon.awscdk.services.cloudwatch.Metric;
import software.amazon.awscdk.services.cloudwatch.MetricOptions;
import software.amazon.awscdk.services.cloudwatch.CreateAlarmOptions;
import software.amazon.awscdk.services.cloudwatch.ComparisonOperator;

Queue queue = new Queue(this, "MyQueue");

Metric metric = queue
        .metricApproximateNumberOfMessagesNotVisible(MetricOptions.builder()
                .label("Messages Visible (Approx)")
                .period(Duration.minutes(5)).build());

metric.createAlarm(this, "TooManyMessagesAlarm", CreateAlarmOptions.builder()
                .comparisonOperator(ComparisonOperator.GREATER_THAN_THRESHOLD)
                .threshold(100)
                // ...
                .build());
```

```
using cdk = Amazon.CDK;
using cw = Amazon.CDK.AWS.CloudWatch;
using sqs = Amazon.CDK.AWS.SQS;

var queue = new sqs.Queue(this, "MyQueue");
var metric = queue.MetricApproximateNumberOfMessagesNotVisible(new cw.MetricOptions
{
    Label = "Messages Visible (Approx)",
    Period = cdk.Duration.Minutes(5),
    // ...
});
metric.CreateAlarm(this, "TooManyMessagesAlarm", new cw.CreateAlarmOptions
{
    ComparisonOperator = cw.ComparisonOperator.GREATER_THAN_THRESHOLD,
    Threshold = 100,
    // ..
});
```

```
import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/jsii-runtime-go"
  cw "github.com/aws/aws-cdk-go/awscdk/v2/awscloudwatch"
  sqs "github.com/aws/aws-cdk-go/awscdk/v2/awssqs"
)

queue := sqs.NewQueue(this, jsii.String("MyQueue"), &sqs.QueueProps{})
metric := queue.MetricApproximateNumberOfMessagesNotVisible(&cw.MetricOptions{
  Label: jsii.String("Messages Visible (Approx)"),
  Period: awscdk.Duration_Minutes(jsii.Number(5)),
})

metric.CreateAlarm(this, jsii.String("TooManyMessagesAlarm"), &cw.CreateAlarmOptions{
  ComparisonOperator: cw.ComparisonOperator_GREATER_THAN_THRESHOLD,
  Threshold: jsii.Number(100),
})
```

Si no hay ningún método para una métrica en particular, puede utilizar el método de métrica general para especificar el nombre de la métrica manualmente.

Las métricas también se pueden añadir a los CloudWatch paneles. Consulte [CloudWatch](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch-readme.html).

## Tráfico de red
<a name="resources-traffic"></a>

En muchos casos, debe habilitar los permisos en una red para que una aplicación funcione, por ejemplo, cuando la infraestructura informática necesita acceder a la capa de persistencia. Los recursos que establecen o detectan las conexiones exponen los métodos que permiten los flujos de tráfico, incluida la configuración de las reglas de los grupos de seguridad o la red ACLs.

 [IConnectable](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IConnectable.html)los recursos tienen una `connections` propiedad que es la puerta de entrada a la configuración de las reglas de tráfico de la red.

Para permitir que los datos fluyan en una ruta de red determinada, se utilizan métodos `allow`. El siguiente ejemplo habilita las conexiones HTTPS a la web y las conexiones entrantes desde el grupo Amazon EC2 Auto Scaling `fleet2`.

**Example**  

```
import * as asg from '@aws-cdk/aws-autoscaling';
import * as ec2 from '@aws-cdk/aws-ec2';

const fleet1: asg.AutoScalingGroup = asg.AutoScalingGroup(/*...*/);

// Allow surfing the (secure) web
fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 }));

const fleet2: asg.AutoScalingGroup = asg.AutoScalingGroup(/*...*/);
fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic());
```

```
const asg = require('@aws-cdk/aws-autoscaling');
const ec2 = require('@aws-cdk/aws-ec2');

const fleet1 = asg.AutoScalingGroup();

// Allow surfing the (secure) web
fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 }));

const fleet2 = asg.AutoScalingGroup();
fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic());
```

```
import aws_cdk.aws_autoscaling as asg
import aws_cdk.aws_ec2 as ec2

fleet1 = asg.AutoScalingGroup( ... )

# Allow surfing the (secure) web
fleet1.connections.allow_to(ec2.Peer.any_ipv4(),
  ec2.Port(PortProps(from_port=443, to_port=443)))

fleet2 = asg.AutoScalingGroup( ... )
fleet1.connections.allow_from(fleet2, ec2.Port.all_traffic())
```

```
import software.amazon.awscdk.services.autoscaling.AutoScalingGroup;
import software.amazon.awscdk.services.ec2.Peer;
import software.amazon.awscdk.services.ec2.Port;

AutoScalingGroup fleet1 = AutoScalingGroup.Builder.create(this, "MyFleet")
        /* ... */.build();

// Allow surfing the (secure) Web
fleet1.getConnections().allowTo(Peer.anyIpv4(),
        Port.Builder.create().fromPort(443).toPort(443).build());

AutoScalingGroup fleet2 = AutoScalingGroup.Builder.create(this, "MyFleet2")
        /* ... */.build();
fleet1.getConnections().allowFrom(fleet2, Port.allTraffic());
```

```
using cdk = Amazon.CDK;
using asg = Amazon.CDK.AWS.AutoScaling;
using ec2 = Amazon.CDK.AWS.EC2;

// Allow surfing the (secure) Web
var fleet1 = new asg.AutoScalingGroup(this, "MyFleet", new asg.AutoScalingGroupProps { /* ... */ });
fleet1.Connections.AllowTo(ec2.Peer.AnyIpv4(), new ec2.Port(new ec2.PortProps
  { FromPort = 443, ToPort = 443 }));

var fleet2 = new asg.AutoScalingGroup(this, "MyFleet2", new asg.AutoScalingGroupProps { /* ... */ });
fleet1.Connections.AllowFrom(fleet2, ec2.Port.AllTraffic());
```

```
import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/jsii-runtime-go"
  autoscaling "github.com/aws/aws-cdk-go/awscdk/v2/awsautoscaling"
  ec2 "github.com/aws/aws-cdk-go/awscdk/v2/awsec2"
)

fleet1 := autoscaling.NewAutoScalingGroup(this, jsii.String("MyFleet1"), &autoscaling.AutoScalingGroupProps{})
fleet1.Connections().AllowTo(ec2.Peer_AnyIpv4(),ec2.NewPort(&ec2.PortProps{ FromPort: jsii.Number(443), ToPort: jsii.Number(443) }),jsii.String("secure web"))

fleet2 := autoscaling.NewAutoScalingGroup(this, jsii.String("MyFleet2"), &autoscaling.AutoScalingGroupProps{})
fleet1.Connections().AllowFrom(fleet2, ec2.Port_AllTraffic(),jsii.String("all traffic"))
```

Algunos recursos tienen puertos predeterminados asociados. Los ejemplos incluyen el oyente de un equilibrador de carga en el puerto público y los puertos en los que el motor de base de datos acepta conexiones para instancias de una base de datos de Amazon RDS. En estos casos, puede imponer un control estricto de la red sin tener que especificar el puerto manualmente. Para hacerlo, utilice los métodos `allowDefaultPortFrom` y `allowToDefaultPort` (Python: `allow_default_port_from`, `allow_to_default_port`).

El siguiente ejemplo muestra cómo habilitar las conexiones desde cualquier IPV4 dirección y una conexión desde un grupo de Auto Scaling para acceder a una base de datos.

**Example**  

```
listener.connections.allowDefaultPortFromAnyIpv4('Allow public access');

fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database');
```

```
listener.connections.allowDefaultPortFromAnyIpv4('Allow public access');

fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database');
```

```
listener.connections.allow_default_port_from_any_ipv4("Allow public access")

fleet.connections.allow_to_default_port(rds_database, "Fleet can access database")
```

```
listener.getConnections().allowDefaultPortFromAnyIpv4("Allow public access");

fleet.getConnections().AllowToDefaultPort(rdsDatabase, "Fleet can access database");
```

```
listener.Connections.AllowDefaultPortFromAnyIpv4("Allow public access");

fleet.Connections.AllowToDefaultPort(rdsDatabase, "Fleet can access database");
```

```
listener.Connections().AllowDefaultPortFromAnyIpv4(jsii.String("Allow public Access"))
fleet.Connections().AllowToDefaultPort(rdsDatabase, jsii.String("Fleet can access database"))
```

## Control de eventos
<a name="resources-events"></a>

Algunos recursos pueden actuar como fuentes de eventos. Utilice el método `addEventNotification` (Python: `add_event_notification`) para registrar un objetivo de evento en un tipo de evento concreto emitido por el recurso. Además, los métodos `addXxxNotification` ofrecen una forma sencilla de registrar un controlador para los tipos de eventos más comunes.

En el siguiente ejemplo se muestra cómo activar una función de Lambda cuando se agrega un objeto a un bucket de Amazon S3.

**Example**  

```
import * as s3nots from '@aws-cdk/aws-s3-notifications';

const handler = new lambda.Function(this, 'Handler', { /*…*/ });
const bucket = new s3.Bucket(this, 'Bucket');
bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler));
```

```
const s3nots = require('@aws-cdk/aws-s3-notifications');

const handler = new lambda.Function(this, 'Handler', { /*…*/ });
const bucket = new s3.Bucket(this, 'Bucket');
bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler));
```

```
import aws_cdk.aws_s3_notifications as s3_nots

handler = lambda_.Function(self, "Handler", ...)
bucket = s3.Bucket(self, "Bucket")
bucket.add_object_created_notification(s3_nots.LambdaDestination(handler))
```

```
import software.amazon.awscdk.services.s3.Bucket;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.s3.notifications.LambdaDestination;

Function handler = Function.Builder.create(this, "Handler")/* ... */.build();
Bucket bucket = new Bucket(this, "Bucket");
bucket.addObjectCreatedNotification(new LambdaDestination(handler));
```

```
using lambda = Amazon.CDK.AWS.Lambda;
using s3 = Amazon.CDK.AWS.S3;
using s3Nots = Amazon.CDK.AWS.S3.Notifications;

var handler = new lambda.Function(this, "Handler", new lambda.FunctionProps { .. });
var bucket = new s3.Bucket(this, "Bucket");
bucket.AddObjectCreatedNotification(new s3Nots.LambdaDestination(handler));
```

```
import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/jsii-runtime-go"
  s3 "github.com/aws/aws-cdk-go/awscdk/v2/awss3"
  s3nots "github.com/aws/aws-cdk-go/awscdk/v2/awss3notifications"
)

handler := lambda.NewFunction(this, jsii.String("MyFunction"), &lambda.FunctionProps{})
bucket := s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{})
bucket.AddObjectCreatedNotification(s3nots.NewLambdaDestination(handler), nil)
```

## Políticas de eliminación
<a name="resources-removal"></a>

Los recursos que mantienen datos persistentes, como las bases de datos, los buckets de Amazon S3 y los registros de Amazon ECR, tienen una *política de eliminación*. La política de eliminación indica si se deben eliminar los objetos persistentes cuando se destruya la pila de AWS CDK que los contiene. Los valores que especifican la política de eliminación están disponibles en la `RemovalPolicy` enumeración del módulo AWS `core` CDK.

**nota**  
Los recursos, además de los que almacenan datos de forma persistente, también pueden tener una `removalPolicy` que se utilice para un propósito diferente. Por ejemplo, una versión de una función de Lambda usa un atributo `removalPolicy` para determinar si una versión determinada se conserva cuando se implementa una nueva versión. Tienen significados y valores predeterminados diferentes en comparación con la política de eliminación de un bucket de Amazon S3 o tabla de DynamoDB.


| Valor | Significado | 
| --- | --- | 
|   `RemovalPolicy.RETAIN`   |  Conserve el contenido del recurso al destruir la pila (opción predeterminada). El recurso queda huérfano de la pila y se debe eliminar manualmente. Si intenta volver a implementar la pila mientras el recurso aún existe, recibirá un mensaje de error debido a un conflicto de nombres.  | 
|   `RemovalPolicy.DESTROY`   |  El recurso se destruirá junto con la pila.  | 

 AWS CloudFormation no elimina los buckets de Amazon S3 que contienen archivos, incluso si su política de eliminación está establecida en. `DESTROY` Intentar hacerlo es un AWS CloudFormation error. Para que el AWS CDK elimine todos los archivos del depósito antes de destruirlo, defina `true` la `autoDeleteObjects` propiedad del depósito en.

A continuación, se muestra un ejemplo de cómo crear un bucket de Amazon S3 con la `RemovalPolicy` de `DESTROY` y `autoDeleteOjbects` establecido en `true`.

**Example**  

```
import * as cdk from '@aws-cdk/core';
import * as s3 from '@aws-cdk/aws-s3';

export class CdkTestStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const bucket = new s3.Bucket(this, 'Bucket', {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true
    });
  }
}
```

```
const cdk = require('@aws-cdk/core');
const s3 = require('@aws-cdk/aws-s3');

class CdkTestStack extends cdk.Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    const bucket = new s3.Bucket(this, 'Bucket', {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true
    });
  }
}

module.exports = { CdkTestStack }
```

```
import aws_cdk.core as cdk
import aws_cdk.aws_s3 as s3

class CdkTestStack(cdk.stack):
    def __init__(self, scope: cdk.Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        bucket = s3.Bucket(self, "Bucket",
            removal_policy=cdk.RemovalPolicy.DESTROY,
            auto_delete_objects=True)
```

```
software.amazon.awscdk.core.*;
import software.amazon.awscdk.services.s3.*;

public class CdkTestStack extends Stack {
    public CdkTestStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public CdkTestStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        Bucket.Builder.create(this, "Bucket")
                .removalPolicy(RemovalPolicy.DESTROY)
                .autoDeleteObjects(true).build();
    }
}
```

```
using Amazon.CDK;
using Amazon.CDK.AWS.S3;

public CdkTestStack(Construct scope, string id, IStackProps props) : base(scope, id, props)
{
    new Bucket(this, "Bucket", new BucketProps {
        RemovalPolicy = RemovalPolicy.DESTROY,
        AutoDeleteObjects = true
    });
}
```

```
import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/jsii-runtime-go"
  s3 "github.com/aws/aws-cdk-go/awscdk/v2/awss3"
)

s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{
  RemovalPolicy: awscdk.RemovalPolicy_DESTROY,
  AutoDeleteObjects: jsii.Bool(true),
})
```

También puedes aplicar una política de retirada directamente al AWS CloudFormation recurso subyacente mediante `applyRemovalPolicy()` este método. Este método está disponible en algunos recursos con estado que no tienen una propiedad `removalPolicy` en los props de sus recursos de nivel 2. Algunos ejemplos son los siguientes:
+  AWS CloudFormation pilas
+ Grupos de usuarios de Amazon Cognito
+ Instancias de base de datos de Amazon DocumentDB
+ Volúmenes de Amazon EC2
+ Dominios OpenSearch de Amazon Service
+ Sistemas de FSx archivos de Amazon
+ Colas de Amazon SQS

**Example**  

```
const resource = bucket.node.findChild('Resource') as cdk.CfnResource;
resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
```

```
const resource = bucket.node.findChild('Resource');
resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
```

```
resource = bucket.node.find_child('Resource')
resource.apply_removal_policy(cdk.RemovalPolicy.DESTROY);
```

```
CfnResource resource = (CfnResource)bucket.node.findChild("Resource");
resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
```

```
var resource = (CfnResource)bucket.node.findChild('Resource');
resource.ApplyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
```

**nota**  
Los AWS CDK `RemovalPolicy` se traducen como AWS CloudFormation s. `DeletionPolicy` Sin embargo, el valor predeterminado en AWS CDK es conservar los datos, que es lo opuesto al predeterminado. AWS CloudFormation 

# Los identificadores y el AWS CDK
<a name="identifiers"></a>

Al crear aplicaciones de AWS Cloud Development Kit (AWS CDK), utilizará muchos tipos de identificadores y nombres. Para utilizar el AWS CDK de forma eficaz y evitar errores, es importante entender los tipos de identificadores.

Los identificadores deben ser únicos dentro del ámbito en el que se crean; no es necesario que sean únicos a nivel mundial en su aplicación de AWS CDK.

Si intenta crear un identificador con el mismo valor dentro del mismo ámbito, el AWS CDK generará una excepción.

## ID del constructo
<a name="identifiers-construct-ids"></a>

El identificador más común, `id`, es el identificador que se pasa como segundo argumento al crear una instancia de un objeto de constructo. Este identificador, como todos los identificadores, solo debe ser único dentro del ámbito en el que se creó, que es el primer argumento al crear una instancia un objeto de constructo.

**nota**  
El `id` de una pila es también el identificador que se utiliza para hacer referencia a ella en la [referencia de la CLI de AWS CDK](cli.md).

Veamos un ejemplo en el que tenemos dos constructos con el identificador `MyBucket` en nuestra aplicación. El primero se define en el ámbito de la pila con el identificador `Stack1`. El segundo se define en el ámbito de una pila con el identificador `Stack2`. Como se definen en ámbitos diferentes, esto no genera ningún conflicto y pueden coexistir en la misma aplicación sin problemas.

**Example**  

```
import { App, Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';

class MyStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps = {}) {
    super(scope, id, props);

    new s3.Bucket(this, 'MyBucket');
  }
}

const app = new App();
new MyStack(app, 'Stack1');
new MyStack(app, 'Stack2');
```

```
const { App , Stack } = require('aws-cdk-lib');
const s3 = require('aws-cdk-lib/aws-s3');

class MyStack extends Stack {
  constructor(scope, id, props = {}) {
    super(scope, id, props);

    new s3.Bucket(this, 'MyBucket');
  }
}

const app = new App();
new MyStack(app, 'Stack1');
new MyStack(app, 'Stack2');
```

```
from aws_cdk import App, Construct, Stack, StackProps
from constructs import Construct
from aws_cdk import aws_s3 as s3

class MyStack(Stack):

    def __init__(self, scope: Construct, id: str, **kwargs):

        super().__init__(scope, id, **kwargs)
        s3.Bucket(self, "MyBucket")

app = App()
MyStack(app, 'Stack1')
MyStack(app, 'Stack2')
```

```
// MyStack.java
package com.myorg;

import software.amazon.awscdk.App;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.constructs.Construct;
import software.amazon.awscdk.services.s3.Bucket;

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);
        new Bucket(this, "MyBucket");
    }
}

// Main.java
package com.myorg;

import software.amazon.awscdk.App;

public class Main {
    public static void main(String[] args) {
        App app = new App();
        new MyStack(app, "Stack1");
        new MyStack(app, "Stack2");
    }
}
```

```
using Amazon.CDK;
using constructs;
using Amazon.CDK.AWS.S3;

public class MyStack : Stack
{
    public MyStack(Construct scope, string id, IStackProps props) : base(scope, id, props)
    {
        new Bucket(this, "MyBucket");
    }
}

class Program
{
    static void Main(string[] args)
    {
        var app = new App();
        new MyStack(app, "Stack1");
        new MyStack(app, "Stack2");
    }
}
```

## Rutas
<a name="identifiers-paths"></a>

Los constructos de una aplicación de AWS CDK forman una jerarquía basada en la clase `App`. Nos referimos a la colección de ID de un constructo dado, su constructo principal, su abuelo y así sucesivamente hasta la raíz del árbol del constructo, como una *ruta*.

Por lo general, el AWS CDK muestra las rutas de las plantillas en forma de cadena. Los ID de los niveles se separan mediante barras diagonales, empezando por el nodo situado inmediatamente debajo de la instancia `App` raíz, que suele ser una pila. Por ejemplo, las rutas de los dos recursos de bucket de Amazon S3 del ejemplo de código anterior son `Stack1/MyBucket` y `Stack2/MyBucket`.

Puede proporcionar la ruta de cualquier constructo mediante programación, como se muestra en el siguiente ejemplo. Esto obtiene la ruta `myConstruct` (o `my_construct`, como lo escribirían los desarrolladores de Python). Como los ID deben ser únicos dentro del ámbito en el que se crean, sus rutas siempre son únicas dentro de una aplicación de AWS CDK.

**Example**  

```
const path: string = myConstruct.node.path;
```

```
const path = myConstruct.node.path;
```

```
path = my_construct.node.path
```

```
String path = myConstruct.getNode().getPath();
```

```
string path = myConstruct.Node.Path;
```

## ID únicos
<a name="identifiers-unique-ids"></a>

 AWS CloudFormation requiere que todos los ID lógicos de una plantilla sean únicos. Por ello, AWS CDK debe poder generar un identificador único para cada constructo en una aplicación. Los recursos tienen rutas que son únicas a nivel mundial (los nombres de todos los ámbitos de la pila hasta un recurso específico). Por lo tanto, AWS CDK genera los identificadores únicos necesarios mediante la concatenación de los elementos de la ruta y la adición de un hash de 8 dígitos. (El hash es necesario para distinguir rutas distintas, como `A/B/C` y `A/BC`, que darían como resultado el mismo identificador de AWS CloudFormation. Los identificadores de AWS CloudFormation son alfanuméricos y no pueden contener barras diagonales ni otros caracteres separadores). El AWS CDK llama a esta cadena el *ID único* del constructo.

En general, la aplicación de AWS CDK no debería necesitar conocer los ID únicos. Sin embargo, es posible acceder al ID único de cualquier constructo mediante programación, como se muestra en el ejemplo siguiente.

**Example**  

```
const uid: string = Names.uniqueId(myConstruct);
```

```
const uid = Names.uniqueId(myConstruct);
```

```
uid = Names.unique_id(my_construct)
```

```
String uid = Names.uniqueId(myConstruct);
```

```
string uid = Names.Uniqueid(myConstruct);
```

La *dirección* es otro tipo de identificador único que distingue de forma única los recursos de CDK. Derivado del hash SHA-1 de la ruta, no es legible por humanos. Sin embargo, su longitud constante y relativamente corta (siempre 42 caracteres hexadecimales) la hace útil en situaciones en las que el ID único “tradicional” puede ser demasiado largo. Algunos constructos pueden utilizar la dirección de la plantilla de AWS CloudFormation sintetizada en lugar del ID único. De nuevo, por lo general, la aplicación no debería necesitar conocer las direcciones de sus constructos, pero puede recuperar la dirección de un componente de la siguiente manera.

**Example**  

```
const addr: string = myConstruct.node.addr;
```

```
const addr = myConstruct.node.addr;
```

```
addr = my_construct.node.addr
```

```
String addr = myConstruct.getNode().getAddr();
```

```
string addr = myConstruct.Node.Addr;
```

## ID lógicos
<a name="identifiers-logical-ids"></a>

Los ID únicos sirven como *identificadores lógicos* (o *nombres lógicos*) de los recursos en las plantillas de AWS CloudFormation generadas para los constructos que representan recursos de AWS.

Por ejemplo, el bucket de Amazon S3 del ejemplo anterior que se crea dentro de `Stack2` da como resultado un recurso de ` AWS::S3::Bucket`. El ID lógico del recurso es `Stack2MyBucket4DD88B4F` en la plantilla de AWS CloudFormation resultante. (Para obtener más información sobre cómo se genera este identificador, consulte [ID únicos](#identifiers-unique-ids)).

### Estabilidad de ID lógico
<a name="identifiers-logical-id-stability"></a>

Evite cambiar el ID lógico de un recurso después de su creación. AWS CloudFormation identifica los recursos por el ID lógico. Por lo tanto, si cambia el ID lógico de un recurso, AWS CloudFormation crea un nuevo recurso con el nuevo ID lógico y, a continuación, elimina el existente. Según el tipo de recurso, esto puede provocar la interrupción del servicio, la pérdida de datos o ambas cosas.

# Token y AWS CDK
<a name="tokens"></a>

En AWS Cloud Development Kit (AWS CDK), los *tokens* son marcadores de posición para los valores que no se conocen al definir constructos o sintetizar pilas. Estos valores se resolverán por completo en el momento de la implementación, cuando se cree la infraestructura real. Al desarrollar aplicaciones de AWS CDK, trabajará con tokens para administrar estos valores en toda la aplicación.

## Ejemplo de token
<a name="tokens-example"></a>

A continuación, se muestra un ejemplo de una pila de CDK que define un constructo para un bucket de Amazon Simple Storage Service (Amazon S3). Como aún no se conoce el nombre de nuestro bucket, el valor de `bucketName` se almacena como un token:

**Example**  

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';

export class CdkDemoAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Define an S3 bucket
    const myBucket = new s3.Bucket(this, 'myBucket');

    // Store value of the S3 bucket name
    const myBucketName = myBucket.bucketName;

    // Print the current value for the S3 bucket name at synthesis
    console.log("myBucketName: " + myBucketName);
  }
}
```

```
const { Stack, Duration } = require('aws-cdk-lib');
const s3 = require('aws-cdk-lib/aws-s3');

class CdkDemoAppStack extends Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    // Define an S3 bucket
    const myBucket = new s3.Bucket(this, 'myBucket');

    // Store value of the S3 bucket name
    const myBucketName = myBucket.bucketName;

    // Print the current value for the S3 bucket name at synthesis
    console.log("myBucketName: " + myBucketName);
  }
}

module.exports = { CdkDemoAppStack }
```

```
from aws_cdk import (
    Stack
)
from constructs import Construct
from aws_cdk import aws_s3 as s3

class CdkDemoAppStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # Define an S3 bucket
        my_bucket = s3.Bucket(self, "myBucket")

        # Store the value of the S3 bucket name
        my_bucket_name = my_bucket.bucket_name

        # Print the current value for the S3 bucket name at synthesis
        print(f"myBucketName: {my_bucket_name}")
```

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.s3.Bucket;

import java.util.Map;

public class CdkDemoAppStack extends Stack {
    public CdkDemoAppStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        // Define an S3 bucket
        Bucket myBucket = Bucket.Builder.create(this, "myBucket")
            .build();

        // Store the token for the bucket name
        String myBucketName = myBucket.getBucketName();

        // Print the token at synthesis
        System.out.println("myBucketName: " + myBucketName);
    }
}
```

```
using Amazon.CDK;
using Constructs;
using Amazon.CDK.AWS.S3;

namespace CdkDemoApp
{
    public class CdkDemoAppStack : Stack
    {
        internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Define an S3 bucket
            var myBucket = new Bucket(this, "myBucket");

            // Store the token for the bucket name
            var myBucketName = myBucket.BucketName;

            // Print the token at synthesis
            System.Console.WriteLine($"myBucketName: {myBucketName}");
        }
    }
}
```

```
package main

import (
	"fmt"

	"github.com/aws/aws-cdk-go/awscdk/v2"
	"github.com/aws/aws-cdk-go/awscdk/v2/awss3"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
)

type CdkDemoAppStackProps struct {
	awscdk.StackProps
}

func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	stack := awscdk.NewStack(scope, &id, &sprops)

	// Define an S3 bucket
	myBucket := awss3.NewBucket(stack, jsii.String("myBucket"), &awss3.BucketProps{})

	// Store the token for the bucket name
	myBucketName := myBucket.BucketName()

	// Print the token at synthesis
	fmt.Println("myBucketName: ", *myBucketName)

	return stack
}

// ...
```
Cuando ejecutamos `cdk synth` para sintetizar nuestra pila, el valor de `myBucketName` aparecerá en el formato de token como `${Token[TOKEN.<1234>]}`. Este formato de token es el resultado de cómo AWS CDK codifica los tokens. En este ejemplo, el token está codificado como una cadena:  

```
$ cdk synth --quiet
myBucketName: ${Token[TOKEN.21]}
```
Como el valor del nombre de nuestro bucket no se conoce en el momento de la síntesis, el token se representa como `myBucket<unique-hash>`. Nuestra plantilla de AWS CloudFormation utiliza la función intrínseca `Ref` como referencia a su valor, que se conocerá en el momento de la implementación:  

```
Resources:
  myBucket<5AF9C99B>:
    # ...
Outputs:
  bucketNameOutput:
    Description: The name of the S3 bucket
    Value:
      Ref: myBucket<5AF9C99B>
```

Consulte [ID lógicos generados en su plantilla de AWS CloudFormation](configure-synth.md#how-synth-default-logical-ids) para obtener más información sobre cómo se genera el hash único.

## Transferencia de tokens
<a name="tokens-passing"></a>

Los tokens se pueden transferir como si fueran el valor real que representan. A continuación, se muestra un ejemplo en el que se transfiere el token del nombre del bucket a un constructo de una función de AWS Lambda:

**Example**  

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as lambda from 'aws-cdk-lib/aws-lambda';

export class CdkDemoAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Define an S3 bucket
    const myBucket = new s3.Bucket(this, 'myBucket');

    // ...

    // Define a Lambda function
    const myFunction = new lambda.Function(this, "myFunction", {
      runtime: lambda.Runtime.NODEJS_20_X,
      handler: "index.handler",
      code: lambda.Code.fromInline(`
        exports.handler = async function(event) {
          return {
            statusCode: 200,
            body: JSON.stringify('Hello World!'),
          };
        };
      `),
      functionName: myBucketName + "Function", // Pass token for the S3 bucket name
      environment: {
        BUCKET_NAME: myBucketName, // Pass token for the S3 bucket name
      }
    });
  }
}
```

```
const { Stack, Duration } = require('aws-cdk-lib');
const s3 = require('aws-cdk-lib/aws-s3');
const lambda = require('aws-cdk-lib/aws-lambda');

class CdkDemoAppStack extends Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    // Define an S3 bucket
    const myBucket = new s3.Bucket(this, 'myBucket');

    // ...

    // Define a Lambda function
    const myFunction = new lambda.Function(this, 'myFunction', {
      runtime: lambda.Runtime.NODEJS_20_X,
      handler: 'index.handler',
      code: lambda.Code.fromInline(`
        exports.handler = async function(event) {
          return {
            statusCode: 200,
            body: JSON.stringify('Hello World!'),
          };
        };
      `),
      functionName: myBucketName + 'Function', // Pass token for the S3 bucket name
      environment: {
        BUCKET_NAME: myBucketName, // Pass token for the S3 bucket name
      }
    });
  }
}

module.exports = { CdkDemoAppStack }
```

```
from aws_cdk import (
    Stack
)
from constructs import Construct
from aws_cdk import aws_s3 as s3
from aws_cdk import aws_lambda as _lambda

class CdkDemoAppStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # Define an S3 bucket
        my_bucket = s3.Bucket(self, "myBucket")

        # ...

        # Define a Lambda function
        my_function = _lambda.Function(self, "myFunction",
            runtime=_lambda.Runtime.NODEJS_20_X,
            handler="index.handler",
            code=_lambda.Code.from_inline("""
                exports.handler = async function(event) {
                  return {
                    statusCode: 200,
                    body: JSON.stringify('Hello World!'),
                  };
                };
            """),
            function_name=f"{my_bucket_name}Function",  # Pass token for the S3 bucket name
            environment={
                "BUCKET_NAME": my_bucket_name  # Pass token for the S3 bucket name
            }
        )
```

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.s3.Bucket;
import software.amazon.awscdk.services.lambda.Code;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.lambda.Runtime;

import java.util.Map;

public class CdkDemoAppStack extends Stack {
    public CdkDemoAppStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        // Define an S3 bucket
        Bucket myBucket = Bucket.Builder.create(this, "myBucket")
            .build();

        // ...

        // Define a Lambda function
        Function myFunction = Function.Builder.create(this, "myFunction")
            .runtime(Runtime.NODEJS_20_X)
            .handler("index.handler")
            .code(Code.fromInline(
                "exports.handler = async function(event) {" +
                "return {" +
                "statusCode: 200," +
                "body: JSON.stringify('Hello World!')," +
                "};" +
                "};"
            ))
            .functionName(myBucketName + "Function") // Pass the token for the s3 bucket to the function construct
            .environment(Map.of("BUCKET_NAME", myBucketName))  // Pass the bucket name as environment variable
            .build();
    }
}
```

```
using Amazon.CDK;
using Constructs;
using Amazon.CDK.AWS.S3;
using Amazon.CDK.AWS.Lambda;
using System;
using System.Collections.Generic;

namespace CdkDemoApp
{
    public class CdkDemoAppStack : Stack
    {
        internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Define an S3 bucket
            var myBucket = new Bucket(this, "myBucket");

            // ...

            // Define a Lambda function
            var myFunction = new Function(this, "myFunction", new FunctionProps
            {
                 Runtime = Runtime.NODEJS_20_X,
                 Handler = "index.handler",
                 Code = Code.FromInline(@"
                     exports.handler = async function(event) {
                       return {
                         statusCode: 200,
                         body: JSON.stringify('Hello World!'),
                       };
                     };
                 "),
                 // Pass the token for the S3 bucket name
                 Environment = new Dictionary<string, string>
                 {
                     { "BUCKET_NAME", myBucketName }
                 },
                 FunctionName = $"{myBucketName}Function" // Pass the token for the s3 bucket to the function construct
            });
        }
    }
}
```

```
package main

import (
	"fmt"

	"github.com/aws/aws-cdk-go/awscdk/v2"
	"github.com/aws/aws-cdk-go/awscdk/v2/awslambda"
	"github.com/aws/aws-cdk-go/awscdk/v2/awss3"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
)

type CdkDemoAppStackProps struct {
	awscdk.StackProps
}

func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	stack := awscdk.NewStack(scope, &id, &sprops)

	// Define an S3 bucket
	myBucket := awss3.NewBucket(stack, jsii.String("myBucket"), &awss3.BucketProps{})

	// ...

	// Define a Lambda function
	myFunction := awslambda.NewFunction(stack, jsii.String("myFunction"), &awslambda.FunctionProps{
		Runtime: awslambda.Runtime_NODEJS_20_X(),
		Handler: jsii.String("index.handler"),
		Code: awslambda.Code_FromInline(jsii.String(`
			exports.handler = async function(event) {
				return {
					statusCode: 200,
					body: JSON.stringify('Hello World!'),
				};
			};
		`)),
		FunctionName: jsii.String(fmt.Sprintf("%sFunction", *myBucketName)), // Pass the token for the S3 bucket to the function name
		Environment: &map[string]*string{
			"BUCKET_NAME": myBucketName,
		},
	})

	return stack
}
// ...
```
Cuando sintetizamos nuestra plantilla, las funciones intrínsecas `Ref` y `Fn::Join` se utilizan para especificar los valores, que se conocerán en el momento de la implementación:  

```
Resources:
  myBucket<5AF9C99B>:
    Type: AWS::S3::Bucket
    # ...
  myFunction<884E1557>:
    Type: AWS::Lambda::Function
    Properties:
      # ...
      Environment:
        Variables:
          BUCKET_NAME:
            Ref: myBucket<5AF9C99B>
      FunctionName:
        Fn::Join:
          - ""
          - - Ref: myBucket<5AF9C99B>
            - Function
      # ...
```

## Cómo funcionan las codificaciones de tokens
<a name="tokens-work"></a>

Los tokens son objetos que implementan la interfaz [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.IResolvable.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.IResolvable.html) , que contiene un único método `resolve`. Durante la síntesis, AWS CDK llama a este método para generar el valor final de los tokens de la plantilla de CloudFormation.

**nota**  
En raras ocasiones trabajará con la interfaz `IResolvable`. Lo más probable es que solo vea las versiones de los tokens codificadas en cadenas.

### Tipos de codificación de token
<a name="tokens-work-types"></a>

Los tokens participan en el proceso de síntesis para producir valores arbitrarios de cualquier tipo. Por lo general, otras funciones solo aceptan argumentos de tipos básicos, como `string` o `number`. Para utilizar tokens en estos casos, puede codificarlos en uno de los tres tipos mediante métodos estáticos de la clase [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html).
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrstringvalue-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrstringvalue-options) para generar una codificación de cadena (o llamar a `.toString()` en el objeto token).
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrlistvalue-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrlistvalue-options) para generar una codificación de lista.
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrnumbervalue](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrnumbervalue) para generar una codificación numérica.

Estos tipos toman un valor arbitrario, que puede ser `IResolvable`, y lo codifican en un valor primitivo del tipo indicado.

**importante**  
Como cualquiera de los tipos anteriores puede ser un token codificado, tenga cuidado al analizar o intentar leer su contenido. Por ejemplo, si intenta analizar una cadena para extraer un valor de ella y la cadena es un token codificado, el análisis no se realizará correctamente. Del mismo modo, si intenta consultar la longitud de una matriz o realizar operaciones matemáticas con un número, primero debe comprobar que no sean tokens codificados.

## Cómo comprobar si hay tokens en la aplicación
<a name="tokens-check"></a>

Para comprobar si un valor contiene un token sin resolver, debe llamar al método [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-iswbrunresolvedobj](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-iswbrunresolvedobj) (Python: `is_unresolved`). A continuación, se muestra un ejemplo que comprueba si el valor del nombre del bucket de Amazon S3 es un token. Si no es un token, entonces se valida la longitud del nombre del bucket:

**Example**  

```
// ...

export class CdkDemoAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Define an S3 bucket
    const myBucket = new s3.Bucket(this, 'myBucket');
    // ...

    // Check if bucket name is a token. If not, check if length is less than 10 characters
    if (cdk.Token.isUnresolved(myBucketName)) {
      console.log("Token identified.");
    } else if (!cdk.Token.isUnresolved(myBucketName) && myBucketName.length > 10) {
      throw new Error('Maximum length for name is 10 characters.');
    };

    // ...
  }
}
```

```
const { Stack, Duration, Token, CfnOutput } = require('aws-cdk-lib');
// ...

class CdkDemoAppStack extends Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    // Define an S3 bucket
    const myBucket = new s3.Bucket(this, 'myBucket');

    // ...

    // Check if bucket name is a token. If not, check if length is less than 10 characters
    if (Token.isUnresolved(myBucketName)) {
      console.log("Token identified.");
    } else if (!Token.isUnresolved(myBucketName) && myBucketName.length > 10) {
      throw new Error('Maximum length for name is 10 characters.');
    };

    // ...
  }
}
```

```
from aws_cdk import (
    Stack,
    Token
)
# ...

class CdkDemoAppStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # Define an S3 bucket
        my_bucket = s3.Bucket(self, "myBucket")

        # ...

        # Check if bucket name is a token. If not, check if length is less than 10 characters
        if Token.is_unresolved(my_bucket_name):
            print("Token identified.")
        elif not Token.is_unresolved(my_bucket_name) and len(my_bucket_name) < 10:
            raise ValueError("Maximum length for name is 10 characters.")

        # ...
```

```
// ...
import software.amazon.awscdk.Token;
import software.amazon.awscdk.services.s3.Bucket;
// ...

public class CdkDemoAppStack extends Stack {
    public CdkDemoAppStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        // Define an S3 bucket
        Bucket myBucket = Bucket.Builder.create(this, "myBucket")
            .build();

        // ...

        // Get the bucket name
        String myBucketName = myBucket.getBucketName();

        // Check if the bucket name is a token. If not, check if length is less than 10 characters
        if (Token.isUnresolved(myBucketName)) {
            System.out.println("Token identified.");
        } else if (!Token.isUnresolved(myBucketName) && myBucketName.length() > 10) {
            throw new IllegalArgumentException("Maximum length for name is 10 characters.");
        }

        // ...
      }
    }
  }
```

```
using Amazon.CDK;
using Constructs;
using Amazon.CDK.AWS.S3;
using Amazon.CDK.AWS.Lambda;
using System;
using System.Collections.Generic;

namespace CdkDemoApp
{
    public class CdkDemoAppStack : Stack
    {
        internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Define an S3 bucket
            var myBucket = new Bucket(this, "myBucket");

            // ...

            // Get the bucket name
            var myBucketName = myBucket.BucketName;

            // Check if bucket name is a token. If not, check if length is less than 10 characters
            if (Token.IsUnresolved(myBucketName))
            {
                System.Console.WriteLine("Token identified.");
            }
            else if (!Token.IsUnresolved(myBucketName) && myBucketName.Length > 10)
            {
                throw new System.Exception("Maximum length for name is 10 characters.");
            }

            // ...
        }
    }
}
```

```
// ...

func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	stack := awscdk.NewStack(scope, &id, &sprops)

	// Define an S3 bucket
	myBucket := awss3.NewBucket(stack, jsii.String("myBucket"), &awss3.BucketProps{})

	// ...

	// Check if the bucket name is unresolved (a token)
	if tokenUnresolved := awscdk.Token_IsUnresolved(myBucketName); tokenUnresolved != nil && *tokenUnresolved {
		fmt.Println("Token identified.")
	} else if tokenUnresolved != nil && !*tokenUnresolved && len(*myBucketName) > 10 {
		panic("Maximum length for name is 10 characters.")
	}

	// ...
}
```

Cuando ejecutamos `cdk synth`, `myBucketName` se identifica como un token:

```
$ cdk synth --quiet
Token identified.
```

**nota**  
Puede utilizar codificaciones de token para escapar del sistema de tipos. Por ejemplo, puede codificar en cadena un token que produce un valor numérico en el momento de la síntesis. Si utiliza estas funciones, es su responsabilidad asegurarse de que la plantilla se resuelve a un estado utilizable después de la síntesis.

## Cómo trabajar con tokens codificados en cadena
<a name="tokens-string"></a>

Así se ven los tokens codificados en cadena.

```
${TOKEN[Bucket.Name.1234]}
```

Se pueden transferir como cadenas normales y se pueden concatenar, como se muestra en el siguiente ejemplo.

**Example**  

```
const functionName = bucket.bucketName + 'Function';
```

```
const functionName = bucket.bucketName + 'Function';
```

```
function_name = bucket.bucket_name + "Function"
```

```
String functionName = bucket.getBucketName().concat("Function");
```

```
string functionName = bucket.BucketName + "Function";
```

```
functionName := *bucket.BucketName() + "Function"
```

Si el idioma lo admite, también puede utilizar la interpolación de cadenas como se muestra en el siguiente ejemplo.

**Example**  

```
const functionName = `${bucket.bucketName}Function`;
```

```
const functionName = `${bucket.bucketName}Function`;
```

```
function_name = f"{bucket.bucket_name}Function"
```

```
String functionName = String.format("%sFunction". bucket.getBucketName());
```

```
string functionName = $"${bucket.bucketName}Function";
```
Utilice `fmt.Sprintf` para una funcionalidad similar:  

```
functionName := fmt.Sprintf("%sFunction", *bucket.BucketName())
```

Evite manipular la cadena de otras formas. Por ejemplo, si se toma una subcadena, es probable que se rompa el token de la cadena.

## Cómo trabajar con tokens codificados en lista
<a name="tokens-list"></a>

Así se ven los tokens codificados en lista:

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

Lo único seguro que se puede hacer con estas listas es transferirlas directamente a otros constructos. Los tokens en lista de cadenas no se pueden concatenar, así como tampoco se puede extraer ningún elemento del token. La única forma segura de manipularlos es mediante el uso de funciones intrínsecas de AWS CloudFormation como [https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-select.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-select.html).

## Cómo trabajar con tokens codificados en números
<a name="tokens-number"></a>

Los tokens codificados en números son un conjunto de pequeños números negativos de coma flotante con el siguiente aspecto.

```
-1.8881545897087626e+289
```

Al igual que ocurre con los tokens en lista, no se puede modificar el valor numérico, ya que es probable que se rompa el token numérico.

A continuación, se muestra un ejemplo de un constructo que contiene un token codificado como un número:

**Example**  

```
import { Stack, Duration, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as rds from 'aws-cdk-lib/aws-rds';
import * as ec2 from 'aws-cdk-lib/aws-ec2';

export class CdkDemoAppStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // Define a new VPC
    const vpc = new ec2.Vpc(this, 'MyVpc', {
      maxAzs: 3,  // Maximum number of availability zones to use
    });

    // Define an RDS database cluster
    const dbCluster = new rds.DatabaseCluster(this, 'MyRDSCluster', {
      engine: rds.DatabaseClusterEngine.AURORA,
      instanceProps: {
        vpc,
      },
    });

    // Get the port token (this is a token encoded as a number)
    const portToken = dbCluster.clusterEndpoint.port;

    // Print the value for our token at synthesis
    console.log("portToken: " + portToken);
  }
}
```

```
const { Stack, Duration } = require('aws-cdk-lib');
const lambda = require('aws-cdk-lib/aws-lambda');
const rds = require('aws-cdk-lib/aws-rds');
const ec2 = require('aws-cdk-lib/aws-ec2');

class CdkDemoAppStack extends Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    // Define a new VPC
    const vpc = new ec2.Vpc(this, 'MyVpc', {
      maxAzs: 3,  // Maximum number of availability zones to use
    });

    // Define an RDS database cluster
    const dbCluster = new rds.DatabaseCluster(this, 'MyRDSCluster', {
      engine: rds.DatabaseClusterEngine.AURORA,
      instanceProps: {
        vpc,
      },
    });

    // Get the port token (this is a token encoded as a number)
    const portToken = dbCluster.clusterEndpoint.port;

    // Print the value for our token at synthesis
    console.log("portToken: " + portToken);
  }
}

module.exports = { CdkDemoAppStack }
```

```
from aws_cdk import (
    Duration,
    Stack,
)
from aws_cdk import aws_rds as rds
from aws_cdk import aws_ec2 as ec2
from constructs import Construct

class CdkDemoAppStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # Define a new VPC
        vpc = ec2.Vpc(self, 'MyVpc',
            max_azs=3  # Maximum number of availability zones to use
        )

        # Define an RDS database cluster
        db_cluster = rds.DatabaseCluster(self, 'MyRDSCluster',
            engine=rds.DatabaseClusterEngine.AURORA,
            instance_props=rds.InstanceProps(
                vpc=vpc
            )
        )

        # Get the port token (this is a token encoded as a number)
        port_token = db_cluster.cluster_endpoint.port

        # Print the value for our token at synthesis
        print(f"portToken: {port_token}")
```

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.ec2.Vpc;
import software.amazon.awscdk.services.rds.DatabaseCluster;
import software.amazon.awscdk.services.rds.DatabaseClusterEngine;
import software.amazon.awscdk.services.rds.InstanceProps;

public class CdkDemoAppStack extends Stack {
    public CdkDemoAppStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        // Define a new VPC
        Vpc vpc = Vpc.Builder.create(this, "MyVpc")
            .maxAzs(3) // Maximum number of availability zones to use
            .build();

        // Define an RDS database cluster
        DatabaseCluster dbCluster = DatabaseCluster.Builder.create(this, "MyRDSCluster")
            .engine(DatabaseClusterEngine.AURORA)
            .instanceProps(InstanceProps.builder()
                .vpc(vpc)
                .build())
            .build();

        // Get the port token (this is a token encoded as a number)
        Number portToken = dbCluster.getClusterEndpoint().getPort();

        // Print the value for our token at synthesis
        System.out.println("portToken: " + portToken);
    }
}
```

```
using Amazon.CDK;
using Constructs;
using Amazon.CDK.AWS.EC2;
using Amazon.CDK.AWS.RDS;
using System;
using System.Collections.Generic;

namespace CdkDemoApp
{
    public class CdkDemoAppStack : Stack
    {
        internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Define a new VPC
            var vpc = new Vpc(this, "MyVpc", new VpcProps
            {
                MaxAzs = 3  // Maximum number of availability zones to use
            });

            // Define an RDS database cluster
            var dbCluster = new DatabaseCluster(this, "MyRDSCluster", new DatabaseClusterProps
            {
                Engine = DatabaseClusterEngine.AURORA,  // Remove parentheses
                InstanceProps = new Amazon.CDK.AWS.RDS.InstanceProps // Specify RDS InstanceProps
                {
                    Vpc = vpc
                }
            });

            // Get the port token (this is a token encoded as a number)
            var portToken = dbCluster.ClusterEndpoint.Port;

            // Print the value for our token at synthesis
            System.Console.WriteLine($"portToken: {portToken}");
        }
    }
}
```

```
package main

import (
	"fmt"

	"github.com/aws/aws-cdk-go/awscdk/v2"
	"github.com/aws/aws-cdk-go/awscdk/v2/awsec2"
	"github.com/aws/aws-cdk-go/awscdk/v2/awsrds"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
)

type CdkDemoAppStackProps struct {
	awscdk.StackProps
}

func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	stack := awscdk.NewStack(scope, &id, &sprops)

	// Define a new VPC
	vpc := awsec2.NewVpc(stack, jsii.String("MyVpc"), &awsec2.VpcProps{
		MaxAzs: jsii.Number(3), // Maximum number of availability zones to use
	})

	// Define an RDS database cluster
	dbCluster := awsrds.NewDatabaseCluster(stack, jsii.String("MyRDSCluster"), &awsrds.DatabaseClusterProps{
		Engine: awsrds.DatabaseClusterEngine_AURORA(),
		InstanceProps: &awsrds.InstanceProps{
			Vpc: vpc,
		},
	})

	// Get the port token (this is a token encoded as a number)
	portToken := dbCluster.ClusterEndpoint().Port()

	// Print the value for our token at synthesis
	fmt.Println("portToken: ", portToken)

	return stack
}

// ...
```

Cuando ejecutamos `cdk synth`, el valor de `portToken` se muestra como un token codificado en números:

```
$ cdk synth --quiet
portToken: -1.8881545897087968e+289
```

### Transferencia de tokens codificados en números
<a name="tokens-number-pass"></a>

Al transferir tokens codificados en números a otros constructos, puede que tenga sentido convertirlos primero en cadenas. Por ejemplo, si desea utilizar el valor de una cadena codificada en números como parte de una cadena concatenada, su conversión mejora la legibilidad.

En el siguiente ejemplo, `portToken` es un token codificado en números que queremos transferir a nuestra función de Lambda como parte de `connectionString`:

**Example**  

```
import { Stack, Duration, CfnOutput, StackProps } from 'aws-cdk-lib';
// ...
import * as lambda from 'aws-cdk-lib/aws-lambda';

export class CdkDemoAppStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // Define a new VPC
    // ...

    // Define an RDS database cluster
    // ...

    // Get the port token (this is a token encoded as a number)
    const portToken = dbCluster.clusterEndpoint.port;

    // ...

    // Example connection string with the port token as a number
    const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portToken}/mydatabase`;

    // Use the connection string as an environment variable in a Lambda function
    const myFunction = new lambda.Function(this, 'MyLambdaFunction', {
      runtime: lambda.Runtime.NODEJS_20_X,
      handler: 'index.handler',
      code: lambda.Code.fromInline(`
        exports.handler = async function(event) {
          return {
            statusCode: 200,
            body: JSON.stringify('Hello World!'),
          };
        };
      `),
      environment: {
        DATABASE_CONNECTION_STRING: connectionString,  // Using the port token as part of the string
      },
    });

    // Output the value of our connection string at synthesis
    console.log("connectionString: " + connectionString);

    // Output the connection string
    new CfnOutput(this, 'ConnectionString', {
      value: connectionString,
    });
  }
}
```

```
const { Stack, Duration, CfnOutput } = require('aws-cdk-lib');
// ...
const lambda = require('aws-cdk-lib/aws-lambda');

class CdkDemoAppStack extends Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    // Define a new VPC
    // ...

    // Define an RDS database cluster
    // ...

    // Get the port token (this is a token encoded as a number)
    const portToken = dbCluster.clusterEndpoint.port;

    // ...

    // Example connection string with the port token as a number
    const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portToken}/mydatabase`;

    // Use the connection string as an environment variable in a Lambda function
    const myFunction = new lambda.Function(this, 'MyLambdaFunction', {
      runtime: lambda.Runtime.NODEJS_20_X,
      handler: 'index.handler',
      code: lambda.Code.fromInline(`
        exports.handler = async function(event) {
          return {
            statusCode: 200,
            body: JSON.stringify('Hello World!'),
          };
        };
      `),
      environment: {
        DATABASE_CONNECTION_STRING: connectionString,  // Using the port token as part of the string
      },
    });

    // Output the value of our connection string at synthesis
    console.log("connectionString: " + connectionString);

    // Output the connection string
    new CfnOutput(this, 'ConnectionString', {
      value: connectionString,
    });
  }
}

module.exports = { CdkDemoAppStack }
```

```
from aws_cdk import (
    Duration,
    Stack,
    CfnOutput,
)
from aws_cdk import aws_lambda as _lambda
# ...

class CdkDemoAppStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # Define a new VPC
        # ...

        # Define an RDS database cluster
        # ...

        # Get the port token (this is a token encoded as a number)
        port_token = db_cluster.cluster_endpoint.port

        # ...

        # Example connection string with the port token as a number
        connection_string = f"jdbc:mysql://mydb.cluster.amazonaws.com:{port_token}/mydatabase"

        # Use the connection string as an environment variable in a Lambda function
        my_function = _lambda.Function(self, 'MyLambdaFunction',
            runtime=_lambda.Runtime.NODEJS_20_X,
            handler='index.handler',
            code=_lambda.Code.from_inline("""
                exports.handler = async function(event) {
                    return {
                        statusCode: 200,
                        body: JSON.stringify('Hello World!'),
                    };
                };
            """),
            environment={
                'DATABASE_CONNECTION_STRING': connection_string  # Using the port token as part of the string
            }
        )

        # Output the value of our connection string at synthesis
        print(f"connectionString: {connection_string}")

        # Output the connection string
        CfnOutput(self, 'ConnectionString',
            value=connection_string
        )
```

```
// ...
import software.amazon.awscdk.CfnOutput;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.lambda.Runtime;
import software.amazon.awscdk.services.lambda.Code;

import java.util.Map;

public class CdkDemoAppStack extends Stack {
    public CdkDemoAppStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        // Define a new VPC
        // ...

        // Define an RDS database cluster
        // ...

        // Get the port token (this is a token encoded as a number)
        Number portToken = dbCluster.getClusterEndpoint().getPort();

        // ...

        // Example connection string with the port token as a number
        String connectionString = "jdbc:mysql://mydb.cluster.amazonaws.com:" + portToken + "/mydatabase";

        // Use the connection string as an environment variable in a Lambda function
        Function myFunction = Function.Builder.create(this, "MyLambdaFunction")
            .runtime(Runtime.NODEJS_20_X)
            .handler("index.handler")
            .code(Code.fromInline(
                "exports.handler = async function(event) {\n" +
                "  return {\n" +
                "    statusCode: 200,\n" +
                "    body: JSON.stringify('Hello World!'),\n" +
                "  };\n" +
                "};"))
            .environment(Map.of(
                "DATABASE_CONNECTION_STRING", connectionString // Using the port token as part of the string
            ))
            .build();

        // Output the value of our connection string at synthesis
        System.out.println("connectionString: " + connectionString);

        // Output the connection string
        CfnOutput.Builder.create(this, "ConnectionString")
            .value(connectionString)
            .build();
    }
}
```

```
// ...
using Amazon.CDK.AWS.Lambda;
using Amazon.CDK.AWS.RDS;
using Amazon.CDK;
using Constructs;
using System;
using System.Collections.Generic;

namespace CdkDemoApp
{
    public class CdkDemoAppStack : Stack
    {
        internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Define a new VPC
            // ...

            // Define an RDS database cluster
            var dbCluster = new DatabaseCluster(this, "MyRDSCluster", new DatabaseClusterProps
            {
                // ... properties would go here
            });

            // Get the port token (this is a token encoded as a number)
            var portToken = dbCluster.ClusterEndpoint.Port;

            // ...

            // Example connection string with the port token as a number
            var connectionString = $"jdbc:mysql://mydb.cluster.amazonaws.com:{portToken}/mydatabase";

            // Use the connection string as an environment variable in a Lambda function
            var myFunction = new Function(this, "MyLambdaFunction", new FunctionProps
            {
                Runtime = Runtime.NODEJS_20_X,
                Handler = "index.handler",
                Code = Code.FromInline(@"
                    exports.handler = async function(event) {
                        return {
                            statusCode: 200,
                            body: JSON.stringify('Hello World!'),
                        };
                    };
                "),
                Environment = new Dictionary<string, string>
                {
                    { "DATABASE_CONNECTION_STRING", connectionString }  // Using the port token as part of the string
                }
            });

            // Output the value of our connection string at synthesis
            Console.WriteLine($"connectionString: {connectionString}");

            // Output the connection string
            new CfnOutput(this, "ConnectionString", new CfnOutputProps
            {
                Value = connectionString
            });
        }
    }
}
```

```
// ...
	"github.com/aws/aws-cdk-go/awscdk/v2/awslambda"
)

type CdkDemoAppStackProps struct {
	awscdk.StackProps
}

func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	stack := awscdk.NewStack(scope, &id, &sprops)

	// Define a new VPC
	// ...

	// Define an RDS database cluster
	// ...

	// Get the port token (this is a token encoded as a number)
	portToken := dbCluster.ClusterEndpoint().Port()

	// ...

	// Example connection string with the port token as a number
	 connectionString := fmt.Sprintf("jdbc:mysql://mydb.cluster.amazonaws.com:%s/mydatabase", portToken)

	// Use the connection string as an environment variable in a Lambda function
	myFunction := awslambda.NewFunction(stack, jsii.String("MyLambdaFunction"), &awslambda.FunctionProps{
		Runtime: awslambda.Runtime_NODEJS_20_X(),
		Handler: jsii.String("index.handler"),
		Code: awslambda.Code_FromInline(jsii.String(`
			exports.handler = async function(event) {
				return {
					statusCode: 200,
					body: JSON.stringify('Hello World!'),
				};
			};
		`)),
		Environment: &map[string]*string{
			"DATABASE_CONNECTION_STRING": jsii.String(connectionString), // Using the port token as part of the string
		},
	})

	// Output the value of our connection string at synthesis
	fmt.Println("connectionString: ", connectionString)

	// Output the connection string
	awscdk.NewCfnOutput(stack, jsii.String("ConnectionString"), &awscdk.CfnOutputProps{
		Value: jsii.String(connectionString),
	})

	return stack
}

// ...
```

Si transferimos este valor a `connectionString`, el valor de salida al ejecutar `cdk synth` puede resultar confuso debido a la cadena codificada en números:

```
$ cdk synth --quiet
connectionString: jdbc:mysql://mydb.cluster.amazonaws.com:-1.888154589708796e+289/mydatabase
```

Para convertir un token codificado en números en una cadena, utilice [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tokenization.html#static-stringifywbrnumberx](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tokenization.html#static-stringifywbrnumberx). En el siguiente ejemplo, convertimos el token codificado en números en una cadena antes de definir nuestra cadena de conexión:

**Example**  

```
import { Stack, Duration, Tokenization, CfnOutput, StackProps } from 'aws-cdk-lib';
// ...

export class CdkDemoAppStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // Define a new VPC
    // ...

    // Define an RDS database cluster
    // ...

    // Get the port token (this is a token encoded as a number)
    const portToken = dbCluster.clusterEndpoint.port;

    // ...

    // Convert the encoded number to an encoded string for use in the connection string
    const portAsString = Tokenization.stringifyNumber(portToken);

    // Example connection string with the port token as a string
    const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portAsString}/mydatabase`;

    // Use the connection string as an environment variable in a Lambda function
    const myFunction = new lambda.Function(this, 'MyLambdaFunction', {
      // ...
      environment: {
        DATABASE_CONNECTION_STRING: connectionString,  // Using the port token as part of the string
      },
    });

    // Output the value of our connection string at synthesis
    console.log("connectionString: " + connectionString);

    // Output the connection string
    new CfnOutput(this, 'ConnectionString', {
      value: connectionString,
    });
  }
}
```

```
const { Stack, Duration, Tokenization, CfnOutput } = require('aws-cdk-lib');
// ...

class CdkDemoAppStack extends Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    // Define a new VPC
    // ...

    // Define an RDS database cluster
    // ...

    // Get the port token (this is a token encoded as a number)
    const portToken = dbCluster.clusterEndpoint.port;

    // ...

    // Convert the encoded number to an encoded string for use in the connection string
    const portAsString = Tokenization.stringifyNumber(portToken);

    // Example connection string with the port token as a string
    const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portAsString}/mydatabase`;

    // Use the connection string as an environment variable in a Lambda function
    const myFunction = new lambda.Function(this, 'MyLambdaFunction', {
      // ...
      environment: {
        DATABASE_CONNECTION_STRING: connectionString,  // Using the port token as part of the string
      },
    });

    // Output the value of our connection string at synthesis
    console.log("connectionString: " + connectionString);

    // Output the connection string
    new CfnOutput(this, 'ConnectionString', {
      value: connectionString,
    });
  }
}

module.exports = { CdkDemoAppStack }
```

```
from aws_cdk import (
    Duration,
    Stack,
    Tokenization,
    CfnOutput,
)
# ...

class CdkDemoAppStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # Define a new VPC
        # ...

        # Define an RDS database cluster
        # ...

        # Get the port token (this is a token encoded as a number)
        port_token = db_cluster.cluster_endpoint.port

        # Convert the encoded number to an encoded string for use in the connection string
        port_as_string = Tokenization.stringify_number(port_token)

        # Example connection string with the port token as a string
        connection_string = f"jdbc:mysql://mydb.cluster.amazonaws.com:{port_as_string}/mydatabase"

        # Use the connection string as an environment variable in a Lambda function
        my_function = _lambda.Function(self, 'MyLambdaFunction',
            # ...
            environment={
                'DATABASE_CONNECTION_STRING': connection_string  # Using the port token as part of the string
            }
        )

        # Output the value of our connection string at synthesis
        print(f"connectionString: {connection_string}")

        # Output the connection string
        CfnOutput(self, 'ConnectionString',
            value=connection_string
        )
```

```
// ...
import software.amazon.awscdk.Tokenization;

public class CdkDemoAppStack extends Stack {
    public CdkDemoAppStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public CdkDemoAppStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        // Define a new VPC
        // ...

        // Define an RDS database cluster
        // ...

        // Get the port token (this is a token encoded as a number)
        Number portToken = dbCluster.getClusterEndpoint().getPort();

        // ...

        // Convert the encoded number to an encoded string for use in the connection string
        String portAsString = Tokenization.stringifyNumber(portToken);

        // Example connection string with the port token as a string
        String connectionString = "jdbc:mysql://mydb.cluster.amazonaws.com:" + portAsString + "/mydatabase";

        // Use the connection string as an environment variable in a Lambda function
        Function myFunction = Function.Builder.create(this, "MyLambdaFunction")
            // ...
            .environment(Map.of(
                "DATABASE_CONNECTION_STRING", connectionString // Using the port token as part of the string
            ))
            .build();

        // Output the value of our connection string at synthesis
        System.out.println("connectionString: " + connectionString);

        // Output the connection string
        CfnOutput.Builder.create(this, "ConnectionString")
            .value(connectionString)
            .build();
    }
}
```

```
// ...

namespace CdkDemoApp
{
    public class CdkDemoAppStack : Stack
    {
        internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Define a new VPC
            // ...

            // Define an RDS database cluster
            // ...

            // Get the port token (this is a token encoded as a number)
            var portToken = dbCluster.ClusterEndpoint.Port;

            // ...

            // Convert the encoded number to an encoded string for use in the connection string
            var portAsString = Tokenization.StringifyNumber(portToken);

            // Example connection string with the port token as a string
            var connectionString = $"jdbc:mysql://mydb.cluster.amazonaws.com:{portAsString}/mydatabase";

            // Use the connection string as an environment variable in a Lambda function
            var myFunction = new Function(this, "MyLambdaFunction", new FunctionProps
            {
                // ...
                Environment = new Dictionary<string, string>
                {
                    { "DATABASE_CONNECTION_STRING", connectionString }  // Using the port token as part of the string
                }
            });

            // Output the value of our connection string at synthesis
            Console.WriteLine($"connectionString: {connectionString}");

            // Output the connection string
            new CfnOutput(this, "ConnectionString", new CfnOutputProps
            {
                Value = connectionString
            });
        }
    }
}
```

```
// ...

func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	stack := awscdk.NewStack(scope, &id, &sprops)

	// Define a new VPC
	// ...

	// Define an RDS database cluster
	// ...

	// Get the port token (this is a token encoded as a number)
	portToken := dbCluster.ClusterEndpoint().Port()

	// ...

	// Convert the encoded number to an encoded string for use in the connection string
	portAsString := awscdk.Tokenization_StringifyNumber(portToken)

	// Example connection string with the port token as a string
	connectionString := fmt.Sprintf("jdbc:mysql://mydb.cluster.amazonaws.com:%s/mydatabase", portAsString)

	// Use the connection string as an environment variable in a Lambda function
	myFunction := awslambda.NewFunction(stack, jsii.String("MyLambdaFunction"), &awslambda.FunctionProps{
		// ...
		Environment: &map[string]*string{
			"DATABASE_CONNECTION_STRING": jsii.String(connectionString), // Using the port token as part of the string
		},
	})

	// Output the value of our connection string at synthesis
	fmt.Println("connectionString: ", connectionString)

	// Output the connection string
	awscdk.NewCfnOutput(stack, jsii.String("ConnectionString"), &awscdk.CfnOutputProps{
		Value: jsii.String(connectionString),
	})

	fmt.Println(myFunction)

	return stack
}

// ...
```

Cuando ejecutamos `cdk synth`, el valor de nuestra cadena de conexión se representa en un formato más limpio y claro:

```
$ cdk synth --quiet
connectionString: jdbc:mysql://mydb.cluster.amazonaws.com:${Token[TOKEN.242]}/mydatabase
```

## Valores diferidos
<a name="tokens-lazy"></a>

Además de representar los valores del tiempo de implementación, como los [parámetros](parameters.md) de AWS CloudFormation, los tokens también se utilizan habitualmente para representar los valores diferidos del tiempo de síntesis. Estos son valores para los que el valor final se determinará antes de que se complete la síntesis, pero no en el punto en el que se crea el valor. Utilice tokens para pasar una cadena literal o un valor numérico a otro constructo, mientras que el valor real en el momento de la síntesis podría depender de algún cálculo que aún no se ha producido.

Puede crear tokens que representen valores diferidos en el momento de la síntesis utilizando los métodos estáticos de la clase `Lazy`, como [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Lazy.html#static-stringproducer-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Lazy.html#static-stringproducer-options) y [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Lazy.html#static-numberproducer](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Lazy.html#static-numberproducer). Estos métodos aceptan un objeto cuya propiedad `produce` es una función que acepta un argumento de contexto y devuelve el valor final cuando se llama.

El siguiente ejemplo crea un grupo de escalado automático cuya capacidad se determina después de su creación.

**Example**  

```
let actualValue: number;

new AutoScalingGroup(this, 'Group', {
  desiredCapacity: Lazy.numberValue({
    produce(context) {
      return actualValue;
    }
  })
});

// At some later point
actualValue = 10;
```

```
let actualValue;

new AutoScalingGroup(this, 'Group', {
  desiredCapacity: Lazy.numberValue({
    produce(context) {
      return (actualValue);
    }
  })
});

// At some later point
actualValue = 10;
```

```
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
```

```
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;
```

```
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;
```

## Conversión a JSON
<a name="tokens-json"></a>

A veces, desea generar una cadena JSON de datos arbitrarios y es posible que no sepa si los datos contienen tokens. Para codificar correctamente en JSON cualquier estructura de datos, independientemente de si contiene o no tokens, utilice el método [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#towbrjsonwbrstringobj-space](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#towbrjsonwbrstringobj-space) como se muestra en el siguiente ejemplo.

**Example**  

```
const stack = Stack.of(this);
const str = stack.toJsonString({
  value: bucket.bucketName
});
```

```
const stack = Stack.of(this);
const str = stack.toJsonString({
  value: bucket.bucketName
});
```

```
stack = Stack.of(self)
string = stack.to_json_string(dict(value=bucket.bucket_name))
```

```
Stack stack = Stack.of(this);
String stringVal = stack.toJsonString(java.util.Map.of(    // Map.of requires Java 9+
        put("value", bucket.getBucketName())));
```

```
var stack = Stack.Of(this);
var stringVal = stack.ToJsonString(new Dictionary<string, string>
{
    ["value"] = bucket.BucketName
});
```

# Parámetros y el AWS CDK
<a name="parameters"></a>

 *Los parámetros* son valores personalizados que se proporcionan en el momento de la implementación. [Los parámetros](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html) son una característica de AWS CloudFormation. Dado que AWS Cloud Development Kit (AWS CDK) sintetiza las plantillas de AWS CloudFormation, también ofrece compatibilidad con parámetros en el momento de la implementación.

## Acerca de los parámetros
<a name="parameters-about"></a>

Al usar AWS CDK, puede definir parámetros que luego puede utilizar en las propiedades de los constructos que cree. También puede implementar pilas que contengan parámetros.

Al implementar la plantilla de AWS CloudFormation mediante la CLI de AWS CDK, debe proporcionar los valores de los parámetros en la línea de comandos. Si implementa la plantilla a través de la consola de AWS CloudFormation, se le solicita que ingrese los valores de los parámetros.

En general, no recomendamos utilizar parámetros de AWS CloudFormation con AWS CDK. Las formas habituales de pasar valores a las aplicaciones de AWS CDK son los [valores de contexto](context.md) y las variables de entorno. Dado que no se encuentran disponibles en el momento de la síntesis, los valores de los parámetros no se pueden usar fácilmente para controlar el flujo y otros fines en su aplicación de CDK.

**nota**  
Para realizar el flujo de control con parámetros, puede usar constructos [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnCondition.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnCondition.html), aunque esto es complicado en comparación con instrucciones `if` nativas.

El uso de parámetros requiere que tenga en cuenta cómo se comporta el código que está escribiendo en el momento de la implementación y también en el momento de la síntesis. Esto hace que sea más difícil comprender y razonar sobre su aplicación de AWS CDK, en muchos casos por poco beneficio.

Por lo general, es mejor que la aplicación de CDK acepte la información necesaria de manera bien definida y que la utilice directamente para declarar los constructos en la aplicación de CDK. Una plantilla de AWS CloudFormation generada con AWS CDK ideal es concreta, sin valores que deban especificarse en el momento de la implementación.

Sin embargo, hay casos de uso para los que los parámetros de AWS CloudFormation son especialmente adecuados. Si tiene equipos independientes que definen e implementan la infraestructura, por ejemplo, puede usar parámetros para que las plantillas generadas sean más útiles. Además, debido a que AWS CDK admite parámetros de AWS CloudFormation, puede usar AWS con servicios de AWS CDK que usan plantillas de AWS CloudFormation (como Service Catalog). Estos servicios de AWS usan parámetros para configurar la plantilla que se está implementando.

## Más información
<a name="parameters-learn"></a>

Para obtener instrucciones sobre cómo desarrollar aplicaciones de CDK con los parámetros, consulte [Cómo usar parámetros de CloudFormation para obtener un valor de CloudFormation](get-cfn-param.md).

# Etiquetas y el AWS CDK
<a name="tagging"></a>

Las etiquetas son elementos de clave-valor de información que puede agregar a los constructos de su aplicación de AWS CDK. Una etiqueta aplicada a un constructo determinado también se aplica a todos sus elementos secundarios que se pueden etiquetar. Las etiquetas se incluyen en la plantilla de AWS CloudFormation sintetizada a partir de la aplicación y se aplican a los recursos de AWS que implementa. Puede utilizar etiquetas para identificar y clasificar los recursos con los siguientes fines:
+ Administración simplificada
+ Asignación de costos
+ Control de acceso
+ Cualquier otra finalidad que se le ocurra

**sugerencia**  
Para obtener más información sobre cómo utilizar las etiquetas con los recursos de AWS, consulte las [Prácticas recomendadas para etiquetar los recursos de AWS](https://docs.aws.amazon.com/whitepapers/latest/tagging-best-practices/tagging-best-practices.html) en el *documento técnico de AWS*.

## Uso de etiquetas
<a name="tagging-use"></a>

La clase de [Etiquetas](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html) incluye el método estático `of()`, mediante el cual puede agregar o eliminar etiquetas del constructo especificado.
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#addkey-value-props](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#addkey-value-props) El código aplica una nueva etiqueta a un constructo determinado y a todos sus elementos secundarios.
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#removekey-props](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#removekey-props) El código elimina una etiqueta de un constructo determinado y de cualquiera de sus elementos secundarios, incluidas las etiquetas que un constructo secundario pueda haberse aplicado a sí mismo.

**nota**  
El etiquetado se implementa mediante [Aspectos y el AWS CDK](aspects.md). Los aspectos son una forma de aplicar una operación (como el etiquetado) a todos los constructos de un ámbito determinado.

El siguiente ejemplo aplica la etiqueta **clave** con el valor **valor** a un constructo.

**Example**  

```
Tags.of(myConstruct).add('key', 'value');
```

```
Tags.of(myConstruct).add('key', 'value');
```

```
Tags.of(my_construct).add("key", "value")
```

```
Tags.of(myConstruct).add("key", "value");
```

```
Tags.Of(myConstruct).Add("key", "value");
```

```
awscdk.Tags_Of(myConstruct).Add(jsii.String("key"), jsii.String("value"), &awscdk.TagProps{})
```

En el siguiente ejemplo, se elimina la etiqueta **clave** de un constructo.

**Example**  

```
Tags.of(myConstruct).remove('key');
```

```
Tags.of(myConstruct).remove('key');
```

```
Tags.of(my_construct).remove("key")
```

```
Tags.of(myConstruct).remove("key");
```

```
Tags.Of(myConstruct).Remove("key");
```

```
awscdk.Tags_Of(myConstruct).Remove(jsii.String("key"), &awscdk.TagProps{})
```

Si utiliza constructos `Stage` fijos, aplique la etiqueta en el nivel `Stage` o debajo. Las etiquetas no se aplican a través de los límites `Stage`.

## Prioridades de etiqueta
<a name="tagging-priorities"></a>

AWS CDK aplica y elimina las etiquetas de forma recursiva. Si hay conflictos, prevalece la operación de etiquetado con la prioridad más alta. (Las prioridades se establecen mediante la propiedad opcional `priority`). Si las prioridades de dos operaciones son las mismas, prevalece la operación de etiquetado que se encuentre más cerca de la parte inferior del árbol del constructo. De forma predeterminada, aplicar una etiqueta tiene una prioridad de 100 (excepto en el caso de las etiquetas que se agregan directamente a un recurso de AWS CloudFormation, que tienen una prioridad de 50). La prioridad predeterminada para eliminar una etiqueta es de 200.

A continuación, se aplica una etiqueta con una prioridad de 300 a un constructo.

**Example**  

```
Tags.of(myConstruct).add('key', 'value', {
  priority: 300
});
```

```
Tags.of(myConstruct).add('key', 'value', {
  priority: 300
});
```

```
Tags.of(my_construct).add("key", "value", priority=300)
```

```
Tags.of(myConstruct).add("key", "value", TagProps.builder()
        .priority(300).build());
```

```
Tags.Of(myConstruct).Add("key", "value", new TagProps { Priority = 300 });
```

```
awscdk.Tags_Of(myConstruct).Add(jsii.String("key"), jsii.String("value"), &awscdk.TagProps{
  Priority: jsii.Number(300),
})
```

## Propiedades opcionales
<a name="tagging-props"></a>

Las etiquetas admiten las [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagProps.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagProps.html) que permiten afinar cómo se aplican las etiquetas a los recursos o se eliminan de ellos. Todas las propiedades son opcionales.

 `applyToLaunchedInstances` (Python: `apply_to_launched_instances`)  
Disponible solo para add(). De forma predeterminada, las etiquetas se aplican a las instancias lanzadas en un grupo de escalado automático. Establezca esta propiedad como **falsa** para ignorar las instancias lanzadas en un grupo de escalado automático.

 `includeResourceTypes`/`excludeResourceTypes` (Python: `include_resource_types`/`exclude_resource_types`)  
Úselas para manipular las etiquetas solo en un subconjunto de recursos, en función de los tipos de recursos de AWS CloudFormation. De forma predeterminada, la operación se aplica a todos los recursos del subárbol de constructos, pero esto se puede cambiar si se incluyen o excluyen determinados tipos de recursos. La exclusión tiene prioridad sobre la inclusión, si se especifican ambas opciones.

 `priority`   
Utilice esta opción para establecer la prioridad de esta operación con respecto a otras `Tags.add()` y operaciones `Tags.remove()`. Los valores más altos tienen prioridad sobre los valores más bajos. El valor predeterminado es 100 para las operaciones de adición (50 para las etiquetas aplicadas directamente a los recursos de AWS CloudFormation) y 200 para las operaciones de eliminación.

En el siguiente ejemplo, se aplica la etiqueta **tagname** con el valor **value** y la prioridad **100** a los recursos del tipo ** AWS::Xxx::Yyy** del constructo. No aplica la etiqueta a las instancias lanzadas en un grupo de Amazon EC2 Auto Scaling ni a recursos del tipo ** AWS::Xxx::Zzz**. (Estos son marcadores de posición para dos tipos de recursos de AWS CloudFormation arbitrarios, pero diferentes).

**Example**  

```
Tags.of(myConstruct).add('tagname', 'value', {
  applyToLaunchedInstances: false,
  includeResourceTypes: ['AWS::Xxx::Yyy'],
  excludeResourceTypes: ['AWS::Xxx::Zzz'],
  priority: 100,
});
```

```
Tags.of(myConstruct).add('tagname', 'value', {
  applyToLaunchedInstances: false,
  includeResourceTypes: ['AWS::Xxx::Yyy'],
  excludeResourceTypes: ['AWS::Xxx::Zzz'],
  priority: 100
});
```

```
Tags.of(my_construct).add("tagname", "value",
    apply_to_launched_instances=False,
    include_resource_types=["AWS::Xxx::Yyy"],
    exclude_resource_types=["AWS::Xxx::Zzz"],
    priority=100)
```

```
Tags.of(myConstruct).add("tagname", "value", TagProps.builder()
                .applyToLaunchedInstances(false)
                .includeResourceTypes(Arrays.asList("AWS::Xxx::Yyy"))
                .excludeResourceTypes(Arrays.asList("AWS::Xxx::Zzz"))
                .priority(100).build());
```

```
Tags.Of(myConstruct).Add("tagname", "value", new TagProps
{
    ApplyToLaunchedInstances = false,
    IncludeResourceTypes = ["AWS::Xxx::Yyy"],
    ExcludeResourceTypes = ["AWS::Xxx::Zzz"],
    Priority = 100
});
```

```
awscdk.Tags_Of(myConstruct).Add(jsii.String("tagname"), jsii.String("value"), &awscdk.TagProps{
  ApplyToLaunchedInstances: jsii.Bool(false),
  IncludeResourceTypes:     &[]*string{jsii.String("AWS::Xxx:Yyy")},
  ExcludeResourceTypes:     &[]*string{jsii.String("AWS::Xxx:Zzz")},
  Priority:                 jsii.Number(100),
})
```

En el siguiente ejemplo, se elimina la etiqueta **tagname** con prioridad **200** de los recursos de tipo ** AWS::Xxx::Yyy** del constructo, pero no de los recursos de tipo ** AWS::Xxx::Zzz**.

**Example**  

```
Tags.of(myConstruct).remove('tagname', {
  includeResourceTypes: ['AWS::Xxx::Yyy'],
  excludeResourceTypes: ['AWS::Xxx::Zzz'],
  priority: 200,
});
```

```
Tags.of(myConstruct).remove('tagname', {
  includeResourceTypes: ['AWS::Xxx::Yyy'],
  excludeResourceTypes: ['AWS::Xxx::Zzz'],
  priority: 200
});
```

```
Tags.of(my_construct).remove("tagname",
    include_resource_types=["AWS::Xxx::Yyy"],
    exclude_resource_types=["AWS::Xxx::Zzz"],
    priority=200,)
```

```
Tags.of((myConstruct).remove("tagname", TagProps.builder()
        .includeResourceTypes(Arrays.asList("AWS::Xxx::Yyy"))
        .excludeResourceTypes(Arrays.asList("AWS::Xxx::Zzz"))
        .priority(100).build());
        )
```

```
Tags.Of(myConstruct).Remove("tagname", new TagProps
{
    IncludeResourceTypes = ["AWS::Xxx::Yyy"],
    ExcludeResourceTypes = ["AWS::Xxx::Zzz"],
    Priority = 100
});
```

```
awscdk.Tags_Of(myConstruct).Remove(jsii.String("tagname"), &awscdk.TagProps{
  IncludeResourceTypes: &[]*string{jsii.String("AWS::Xxx:Yyy")},
  ExcludeResourceTypes: &[]*string{jsii.String("AWS::Xxx:Zzz")},
  Priority:             jsii.Number(200),
})
```

## Ejemplo
<a name="tagging-example"></a>

En el siguiente ejemplo, se agrega la clave de etiqueta **StackType** con el valor **TheBest** a cualquier recurso creado dentro del `Stack` denominado `MarketingSystem`. A continuación, lo vuelve a eliminar de todos los recursos, excepto de las subredes de VPC de Amazon EC2. El resultado es que la etiqueta solo se aplica a las subredes.

**Example**  

```
import { App, Stack, Tags } from 'aws-cdk-lib';

const app = new App();
const theBestStack = new Stack(app, 'MarketingSystem');

// Add a tag to all constructs in the stack
Tags.of(theBestStack).add('StackType', 'TheBest');

// Remove the tag from all resources except subnet resources
Tags.of(theBestStack).remove('StackType', {
  excludeResourceTypes: ['AWS::EC2::Subnet']
});
```

```
const { App, Stack, Tags } = require('aws-cdk-lib');

const app = new App();
const theBestStack = new Stack(app, 'MarketingSystem');

// Add a tag to all constructs in the stack
Tags.of(theBestStack).add('StackType', 'TheBest');

// Remove the tag from all resources except subnet resources
Tags.of(theBestStack).remove('StackType', {
  excludeResourceTypes: ['AWS::EC2::Subnet']
});
```

```
from aws_cdk import App, Stack, Tags

app = App();
the_best_stack = Stack(app, 'MarketingSystem')

# Add a tag to all constructs in the stack
Tags.of(the_best_stack).add("StackType", "TheBest")

# Remove the tag from all resources except subnet resources
Tags.of(the_best_stack).remove("StackType",
    exclude_resource_types=["AWS::EC2::Subnet"])
```

```
import software.amazon.awscdk.App;
import software.amazon.awscdk.Tags;

// Add a tag to all constructs in the stack
Tags.of(theBestStack).add("StackType", "TheBest");

// Remove the tag from all resources except subnet resources
Tags.of(theBestStack).remove("StackType", TagProps.builder()
        .excludeResourceTypes(Arrays.asList("AWS::EC2::Subnet"))
        .build());
```

```
using Amazon.CDK;

var app = new App();
var theBestStack = new Stack(app, 'MarketingSystem');

// Add a tag to all constructs in the stack
Tags.Of(theBestStack).Add("StackType", "TheBest");

// Remove the tag from all resources except subnet resources
Tags.Of(theBestStack).Remove("StackType", new TagProps
{
    ExcludeResourceTypes = ["AWS::EC2::Subnet"]
});
```

```
import "github.com/aws/aws-cdk-go/awscdk/v2"
app := awscdk.NewApp(nil)
theBestStack := awscdk.NewStack(app, jsii.String("MarketingSystem"), &awscdk.StackProps{})

// Add a tag to all constructs in the stack
awscdk.Tags_Of(theBestStack).Add(jsii.String("StackType"), jsii.String("TheBest"), &awscdk.TagProps{})

// Remove the tag from all resources except subnet resources
awscdk.Tags_Of(theBestStack).Add(jsii.String("StackType"), jsii.String("TheBest"), &awscdk.TagProps{
  ExcludeResourceTypes: &[]*string{jsii.String("AWS::EC2::Subnet")},
})
```

Con el siguiente código se obtiene el mismo resultado. Considere qué enfoque (inclusión o exclusión) deja más en claro su intención.

**Example**  

```
Tags.of(theBestStack).add('StackType', 'TheBest',
  { includeResourceTypes: ['AWS::EC2::Subnet']});
```

```
Tags.of(theBestStack).add('StackType', 'TheBest',
  { includeResourceTypes: ['AWS::EC2::Subnet']});
```

```
Tags.of(the_best_stack).add("StackType", "TheBest",
    include_resource_types=["AWS::EC2::Subnet"])
```

```
Tags.of(theBestStack).add("StackType", "TheBest", TagProps.builder()
        .includeResourceTypes(Arrays.asList("AWS::EC2::Subnet"))
        .build());
```

```
Tags.Of(theBestStack).Add("StackType", "TheBest", new TagProps {
    IncludeResourceTypes = ["AWS::EC2::Subnet"]
});
```

```
awscdk.Tags_Of(theBestStack).Add(jsii.String("StackType"), jsii.String("TheBest"), &awscdk.TagProps{
  IncludeResourceTypes: &[]*string{jsii.String("AWS::EC2::Subnet")},
})
```

## Etiquetado de constructos individuales
<a name="tagging-single"></a>

 `Tags.of(scope).add(key, value)` es la forma estándar de agregar etiquetas a los componentes fijos del AWS CDK. Su comportamiento de tree-walking, que etiqueta de forma recursiva todos los recursos etiquetables dentro de un ámbito determinado, que casi siempre es lo que se busca. Sin embargo, a veces es necesario etiquetar un constructo (o constructos) arbitrarios específicos.

Uno de estos casos implica la aplicación de etiquetas cuyo valor se deriva de alguna propiedad del constructo que se etiqueta. El enfoque de etiquetado estándar aplica de forma recursiva la misma clave y valor a todos los recursos coincidentes del ámbito. Sin embargo, en este caso el valor podría ser diferente para cada constructo etiquetado.

Las etiquetas se implementan mediante [aspectos](aspects.md), y el CDK llama al método `visit()` de la etiqueta para cada constructo dentro del ámbito especificado mediante `Tags.of(scope)`. Podemos llamar a `Tag.visit()` directamente para aplicar una etiqueta a un solo constructo.

**Example**  

```
new cdk.Tag(key, value).visit(scope);
```

```
new cdk.Tag(key, value).visit(scope);
```

```
cdk.Tag(key, value).visit(scope)
```

```
Tag.Builder.create(key, value).build().visit(scope);
```

```
new Tag(key, value).Visit(scope);
```

```
awscdk.NewTag(key, value, &awscdk.TagProps{}).Visit(scope)
```

Puede etiquetar todos los constructos fijos incluidos en un ámbito, pero dejar que los valores de las etiquetas se deriven de las propiedades de cada constructo. Para ello, escriba un aspecto y aplique la etiqueta en el método del aspecto `visit()`, tal y como se muestra en el ejemplo anterior. A continuación, agregue el aspecto al ámbito deseado mediante `Aspects.of(scope).add(aspect)`.

En el siguiente ejemplo se aplica una etiqueta a cada recurso de una pila que contiene la ruta del recurso.

**Example**  

```
class PathTagger implements cdk.IAspect {
  visit(node: IConstruct) {
    new cdk.Tag("aws-cdk-path", node.node.path).visit(node);
  }
}

stack = new MyStack(app);
cdk.Aspects.of(stack).add(new PathTagger())
```

```
class PathTagger {
  visit(node) {
    new cdk.Tag("aws-cdk-path", node.node.path).visit(node);
  }
}

stack = new MyStack(app);
cdk.Aspects.of(stack).add(new PathTagger())
```

```
@jsii.implements(cdk.IAspect)
class PathTagger:
    def visit(self, node: IConstruct):
        cdk.Tag("aws-cdk-path", node.node.path).visit(node)

stack = MyStack(app)
cdk.Aspects.of(stack).add(PathTagger())
```

```
final class PathTagger implements IAspect {
	public void visit(IConstruct node) {
		Tag.Builder.create("aws-cdk-path", node.getNode().getPath()).build().visit(node);
	}
}

stack stack = new MyStack(app);
Aspects.of(stack).add(new PathTagger());
```

```
public class PathTagger : IAspect
{
    public void Visit(IConstruct node)
    {
        new Tag("aws-cdk-path", node.Node.Path).Visit(node);
    }
}

var stack = new MyStack(app);
Aspects.Of(stack).Add(new PathTagger);
```

**sugerencia**  
La lógica del etiquetado condicional, que incluye las prioridades, los tipos de recursos, etc., está integrada en la clase de la `Tag`. Puede utilizar estas características cuando aplica etiquetas a recursos arbitrarios; la etiqueta no se aplica si no se cumplen las condiciones. Además, la clase de `Tag` solo etiqueta los recursos etiquetables, por lo que no es necesario comprobar si un constructo es etiquetable antes de aplicar una etiqueta.

# Activos y el AWS CDK
<a name="assets"></a>

Los activos son archivos locales, directorios o imágenes de Docker que se pueden agrupar en bibliotecas y aplicaciones de AWS CDK. Por ejemplo, un activo puede ser un directorio que contiene el código del controlador de una función de AWS Lambda. Los activos pueden representar cualquier artefacto que la aplicación necesite para funcionar.

El siguiente video tutorial proporciona una descripción general completa de los activos CDK, y explica cómo puede utilizarlos en su infraestructura como código (IaC).

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/jHNtXQmkKfw?rel=0/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/jHNtXQmkKfw?rel=0)


Los activos se agregan a través de las API que están expuestas por constructos de AWS. Por ejemplo, cuando se define un constructo [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html), la propiedad [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html#code](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html#code) le permite pasar un [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Code.html#static-fromwbrassetpath-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Code.html#static-fromwbrassetpath-options) (directorio). `Function` utiliza activos para agrupar el contenido del directorio y usarlo para el código de la función. Del mismo modo, [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.ContainerImage.html#static-fromwbrassetdirectory-props](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.ContainerImage.html#static-fromwbrassetdirectory-props) utiliza una imagen de Docker creada a partir de un directorio local al definir una tarea de Amazon ECS.

## Activos en detalle
<a name="assets-details"></a>

Cuando hace referencia a un activo de su aplicación, el [ensamblaje de la nube](deploy.md#deploy-how-synth-assemblies), que se sintetiza a partir de su aplicación, incluye información de metadatos con instrucciones para la CLI de AWS CDK. Las instrucciones incluyen dónde encontrar el activo en el disco local y qué tipo de agrupación se debe realizar en función del tipo de activo, como comprimir un directorio (zip) o crear una imagen de Docker.

El AWS CDK genera un hash de origen para los activos. Esto se puede utilizar en el momento de la construcción para determinar si el contenido de un activo cambió.

De forma predeterminada y bajo el hash de origen, el AWS CDK crea una copia del activo en el directorio de ensamblaje de la nube, cuyo valor predeterminado es `cdk.out`. De esta forma, el ensamblaje de la nube es independiente, por lo que si se trasladó a un host diferente para su implementación, aún se puede implementar. Para obtener más información, consulte [Ensamblajes en la nube](deploy.md#deploy-how-synth-assemblies).

Cuando el AWS CDK implementa una aplicación que hace referencia a activos (ya sea directamente mediante el código de la aplicación o a través de una biblioteca), la CLI de AWS CDK primero prepara y publica los activos en un bucket de Amazon S3 o en un repositorio de Amazon ECR. (El bucket o repositorio de S3 se crea durante el arranque). Solo entonces se implementarán los recursos definidos en la pila.

En esta sección, se describen las API de bajo nivel disponibles en el marco.

## Tipos de activos
<a name="assets-types"></a>

El AWS CDK admite los siguientes tipos de bases de activos:

Activos de Amazon S3  
Se trata de archivos y directorios locales que el AWS CDK carga en Amazon S3.

Imagen de Docker  
Estas son imágenes de Docker que el AWS CDK carga en Amazon ECR.

Estos tipos de activos se explican en las siguientes secciones.

## Activos de Amazon S3
<a name="assets-types-s3"></a>

Puede definir los archivos y directorios locales como activos, y el AWS CDK los empaqueta y carga en Amazon S3 a través del módulo [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets-readme.html).

El siguiente ejemplo define un activo de directorio local y a un activo de archivo.

**Example**  

```
import { Asset } from 'aws-cdk-lib/aws-s3-assets';

// Archived and uploaded to Amazon S3 as a .zip file
const directoryAsset = new Asset(this, "SampleZippedDirAsset", {
  path: path.join(__dirname, "sample-asset-directory")
});

// Uploaded to Amazon S3 as-is
const fileAsset = new Asset(this, 'SampleSingleFileAsset', {
  path: path.join(__dirname, 'file-asset.txt')
});
```

```
const { Asset } = require('aws-cdk-lib/aws-s3-assets');

// Archived and uploaded to Amazon S3 as a .zip file
const directoryAsset = new Asset(this, "SampleZippedDirAsset", {
  path: path.join(__dirname, "sample-asset-directory")
});

// Uploaded to Amazon S3 as-is
const fileAsset = new Asset(this, 'SampleSingleFileAsset', {
  path: path.join(__dirname, 'file-asset.txt')
});
```

```
import os.path
dirname = os.path.dirname(__file__)

from aws_cdk.aws_s3_assets import Asset

# Archived and uploaded to Amazon S3 as a .zip file
directory_asset = Asset(self, "SampleZippedDirAsset",
  path=os.path.join(dirname, "sample-asset-directory")
)

# Uploaded to Amazon S3 as-is
file_asset = Asset(self, 'SampleSingleFileAsset',
  path=os.path.join(dirname, 'file-asset.txt')
)
```

```
import java.io.File;

import software.amazon.awscdk.services.s3.assets.Asset;

// Directory where app was started
File startDir = new File(System.getProperty("user.dir"));

// Archived and uploaded to Amazon S3 as a .zip file
Asset directoryAsset = Asset.Builder.create(this, "SampleZippedDirAsset")
                .path(new File(startDir, "sample-asset-directory").toString()).build();

// Uploaded to Amazon S3 as-is
Asset fileAsset = Asset.Builder.create(this, "SampleSingleFileAsset")
                .path(new File(startDir, "file-asset.txt").toString()).build();
```

```
using System.IO;
using Amazon.CDK.AWS.S3.Assets;

// Archived and uploaded to Amazon S3 as a .zip file
var directoryAsset = new Asset(this, "SampleZippedDirAsset", new AssetProps
{
    Path = Path.Combine(Directory.GetCurrentDirectory(), "sample-asset-directory")
});

// Uploaded to Amazon S3 as-is
var fileAsset = new Asset(this, "SampleSingleFileAsset", new AssetProps
{
    Path = Path.Combine(Directory.GetCurrentDirectory(), "file-asset.txt")
});
```

```
dirName, err := os.Getwd()
if err != nil {
  panic(err)
}

awss3assets.NewAsset(stack, jsii.String("SampleZippedDirAsset"), awss3assets.AssetProps{
  Path: jsii.String(path.Join(dirName, "sample-asset-directory")),
})

awss3assets.NewAsset(stack, jsii.String("SampleSingleFileAsset"), awss3assets.AssetProps{
  Path: jsii.String(path.Join(dirName, "file-asset.txt")),
})
```

En la mayoría de los casos, no es necesario utilizar directamente las API del módulo `aws-s3-assets`. Los módulos que admiten activos, como `aws-lambda`, tienen métodos prácticos para que pueda usarlos. Para las funciones de Lambda, el método estático [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Code.html#static-fromwbrassetpath-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Code.html#static-fromwbrassetpath-options) permite especificar un directorio o un archivo .zip en el sistema de archivos local.

### Ejemplos de funciones de Lambda
<a name="assets-types-s3-lambda"></a>

Un caso de uso común es la creación de funciones de Lambda con el código del controlador como un activo de Amazon S3.

El siguiente ejemplo usa un activo de Amazon S3 para definir un controlador de Python en el directorio local `handler`. También, crea una función de Lambda con el activo del directorio local como propiedad `code`. A continuación, se presenta el código Python para el controlador.

```
def lambda_handler(event, context):
  message = 'Hello World!'
  return {
    'message': message
  }
```

El código de la aplicación principal del AWS CDK debe tener un aspecto similar al siguiente.

**Example**  

```
import * as cdk from 'aws-cdk-lib';
import { Constructs } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as path from 'path';

export class HelloAssetStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    new lambda.Function(this, 'myLambdaFunction', {
      code: lambda.Code.fromAsset(path.join(__dirname, 'handler')),
      runtime: lambda.Runtime.PYTHON_3_6,
      handler: 'index.lambda_handler'
    });
  }
}
```

```
const cdk = require('aws-cdk-lib');
const lambda = require('aws-cdk-lib/aws-lambda');
const path = require('path');

class HelloAssetStack extends cdk.Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    new lambda.Function(this, 'myLambdaFunction', {
      code: lambda.Code.fromAsset(path.join(__dirname, 'handler')),
      runtime: lambda.Runtime.PYTHON_3_6,
      handler: 'index.lambda_handler'
    });
  }
}

module.exports = { HelloAssetStack }
```

```
from aws_cdk import Stack
from constructs import Construct
from aws_cdk import aws_lambda as lambda_

import os.path
dirname = os.path.dirname(__file__)

class HelloAssetStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        lambda_.Function(self, 'myLambdaFunction',
            code=lambda_.Code.from_asset(os.path.join(dirname, 'handler')),
            runtime=lambda_.Runtime.PYTHON_3_6,
            handler="index.lambda_handler")
```

```
import java.io.File;

import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.lambda.Runtime;

public class HelloAssetStack extends Stack {

    public HelloAssetStack(final App scope, final String id) {
        this(scope, id, null);
    }

    public HelloAssetStack(final App scope, final String id, final StackProps props) {
        super(scope, id, props);

        File startDir = new File(System.getProperty("user.dir"));

        Function.Builder.create(this, "myLambdaFunction")
                .code(Code.fromAsset(new File(startDir, "handler").toString()))
                .runtime(Runtime.PYTHON_3_6)
                .handler("index.lambda_handler").build();
    }
}
```

```
using Amazon.CDK;
using Amazon.CDK.AWS.Lambda;
using System.IO;

public class HelloAssetStack : Stack
{
    public HelloAssetStack(Construct scope, string id, StackProps props) : base(scope, id, props)
    {
        new Function(this, "myLambdaFunction", new FunctionProps
        {
            Code = Code.FromAsset(Path.Combine(Directory.GetCurrentDirectory(), "handler")),
            Runtime = Runtime.PYTHON_3_6,
            Handler = "index.lambda_handler"
        });
    }
}
```

```
import (
  "os"
  "path"

  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/aws-cdk-go/awscdk/v2/awslambda"
  "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets"
  "github.com/aws/constructs-go/constructs/v10"
  "github.com/aws/jsii-runtime-go"
)

func HelloAssetStack(scope constructs.Construct, id string, props *HelloAssetStackProps) awscdk.Stack {
  var sprops awscdk.StackProps
  if props != nil {
    sprops = props.StackProps
  }
  stack := awscdk.NewStack(scope, id, sprops)

  dirName, err := os.Getwd()
  if err != nil {
    panic(err)
  }

  awslambda.NewFunction(stack, jsii.String("myLambdaFunction"), awslambda.FunctionProps{
    Code: awslambda.AssetCode_FromAsset(jsii.String(path.Join(dirName, "handler")), awss3assets.AssetOptions{}),
    Runtime: awslambda.Runtime_PYTHON_3_6(),
    Handler: jsii.String("index.lambda_handler"),
  })

  return stack
}
```

El método `Function` utiliza activos para agrupar los contenidos del directorio y usarlos para el código de la función.

**sugerencia**  
Los archivos `.jar` de Java son archivos ZIP con una extensión diferente. Se cargan tal cual en Amazon S3, pero cuando se implementan como una función de Lambda, los archivos que contiene se extraen, lo que podría no convenirle. Para evitarlo, coloque el archivo `.jar` en un directorio y especifíquelo como activo.

### Ejemplo de atributos en tiempo de implementación
<a name="assets-types-s3-deploy"></a>

Los tipos de activos de Amazon S3 también exponen [atributos de tiempo de implementación](resources.md#resources-attributes) que se pueden referenciar en bibliotecas y aplicaciones del AWS CDK. El comando `cdk synth` CLI de AWS CDK muestra las propiedades de los activos como parámetros de AWS CloudFormation.

En el siguiente ejemplo, se utilizan atributos de tiempo de implementación para pasar la ubicación de un activo de imagen a una función de Lambda como variables de entorno. (El tipo de archivo no importa; la imagen PNG que se usa aquí es solo un ejemplo).

**Example**  

```
import { Asset } from 'aws-cdk-lib/aws-s3-assets';
import * as path from 'path';

const imageAsset = new Asset(this, "SampleAsset", {
  path: path.join(__dirname, "images/my-image.png")
});

new lambda.Function(this, "myLambdaFunction", {
  code: lambda.Code.asset(path.join(__dirname, "handler")),
  runtime: lambda.Runtime.PYTHON_3_6,
  handler: "index.lambda_handler",
  environment: {
    'S3_BUCKET_NAME': imageAsset.s3BucketName,
    'S3_OBJECT_KEY': imageAsset.s3ObjectKey,
    'S3_OBJECT_URL': imageAsset.s3ObjectUrl
  }
});
```

```
const { Asset } = require('aws-cdk-lib/aws-s3-assets');
const path = require('path');

const imageAsset = new Asset(this, "SampleAsset", {
  path: path.join(__dirname, "images/my-image.png")
});

new lambda.Function(this, "myLambdaFunction", {
  code: lambda.Code.asset(path.join(__dirname, "handler")),
  runtime: lambda.Runtime.PYTHON_3_6,
  handler: "index.lambda_handler",
  environment: {
    'S3_BUCKET_NAME': imageAsset.s3BucketName,
    'S3_OBJECT_KEY': imageAsset.s3ObjectKey,
    'S3_OBJECT_URL': imageAsset.s3ObjectUrl
  }
});
```

```
import os.path

import aws_cdk.aws_lambda as lambda_
from aws_cdk.aws_s3_assets import Asset

dirname = os.path.dirname(__file__)

image_asset = Asset(self, "SampleAsset",
    path=os.path.join(dirname, "images/my-image.png"))

lambda_.Function(self, "myLambdaFunction",
    code=lambda_.Code.asset(os.path.join(dirname, "handler")),
    runtime=lambda_.Runtime.PYTHON_3_6,
    handler="index.lambda_handler",
    environment=dict(
        S3_BUCKET_NAME=image_asset.s3_bucket_name,
        S3_OBJECT_KEY=image_asset.s3_object_key,
        S3_OBJECT_URL=image_asset.s3_object_url))
```

```
import java.io.File;

import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.lambda.Runtime;
import software.amazon.awscdk.services.s3.assets.Asset;

public class FunctionStack extends Stack {
    public FunctionStack(final App scope, final String id, final StackProps props) {
        super(scope, id, props);

        File startDir = new File(System.getProperty("user.dir"));

        Asset imageAsset = Asset.Builder.create(this, "SampleAsset")
                .path(new File(startDir, "images/my-image.png").toString()).build())

        Function.Builder.create(this, "myLambdaFunction")
                .code(Code.fromAsset(new File(startDir, "handler").toString()))
                .runtime(Runtime.PYTHON_3_6)
                .handler("index.lambda_handler")
                .environment(java.util.Map.of(    // Java 9 or later
                    "S3_BUCKET_NAME", imageAsset.getS3BucketName(),
                    "S3_OBJECT_KEY", imageAsset.getS3ObjectKey(),
                    "S3_OBJECT_URL", imageAsset.getS3ObjectUrl()))
                .build();
    }
}
```

```
using Amazon.CDK;
using Amazon.CDK.AWS.Lambda;
using Amazon.CDK.AWS.S3.Assets;
using System.IO;
using System.Collections.Generic;

var imageAsset = new Asset(this, "SampleAsset", new AssetProps
{
    Path = Path.Combine(Directory.GetCurrentDirectory(), @"images\my-image.png")
});

new Function(this, "myLambdaFunction", new FunctionProps
{
    Code = Code.FromAsset(Path.Combine(Directory.GetCurrentDirectory(), "handler")),
    Runtime = Runtime.PYTHON_3_6,
    Handler = "index.lambda_handler",
    Environment = new Dictionarystring, string
    {
        ["S3_BUCKET_NAME"] = imageAsset.S3BucketName,
        ["S3_OBJECT_KEY"] = imageAsset.S3ObjectKey,
        ["S3_OBJECT_URL"] = imageAsset.S3ObjectUrl
    }
});
```

```
import (
  "os"
  "path"

  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/aws-cdk-go/awscdk/v2/awslambda"
  "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets"
)

dirName, err := os.Getwd()
if err != nil {
  panic(err)
}

imageAsset := awss3assets.NewAsset(stack, jsii.String("SampleAsset"), awss3assets.AssetProps{
  Path: jsii.String(path.Join(dirName, "images/my-image.png")),
})

awslambda.NewFunction(stack, jsii.String("myLambdaFunction"), awslambda.FunctionProps{
  Code: awslambda.AssetCode_FromAsset(jsii.String(path.Join(dirName, "handler"))),
  Runtime: awslambda.Runtime_PYTHON_3_6(),
  Handler: jsii.String("index.lambda_handler"),
  Environment: map[string]*string{
    "S3_BUCKET_NAME": imageAsset.S3BucketName(),
    "S3_OBJECT_KEY": imageAsset.S3ObjectKey(),
    "S3_URL": imageAsset.S3ObjectUrl(),
  },
})
```

### Permisos
<a name="assets-types-s3-permissions"></a>

Si utiliza los activos de Amazon S3 directamente a través del módulo [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets-readme.html), los roles, los usuarios o los grupos de IAM, y necesita leer los activos en tiempo de ejecución, conceda los permisos de IAM a esos activos mediante el método [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets.Asset.html#grantwbrreadgrantee](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets.Asset.html#grantwbrreadgrantee).

El siguiente ejemplo otorga a un grupo de IAM los permisos de lectura sobre un activo de archivo.

**Example**  

```
import { Asset } from 'aws-cdk-lib/aws-s3-assets';
import * as path from 'path';

const asset = new Asset(this, 'MyFile', {
  path: path.join(__dirname, 'my-image.png')
});

const group = new iam.Group(this, 'MyUserGroup');
asset.grantRead(group);
```

```
const { Asset } = require('aws-cdk-lib/aws-s3-assets');
const path = require('path');

const asset = new Asset(this, 'MyFile', {
  path: path.join(__dirname, 'my-image.png')
});

const group = new iam.Group(this, 'MyUserGroup');
asset.grantRead(group);
```

```
from aws_cdk.aws_s3_assets import Asset
import aws_cdk.aws_iam as iam

import os.path
dirname = os.path.dirname(__file__)

        asset = Asset(self, "MyFile",
            path=os.path.join(dirname, "my-image.png"))

        group = iam.Group(self, "MyUserGroup")
        asset.grant_read(group)
```

```
import java.io.File;

import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.iam.Group;
import software.amazon.awscdk.services.s3.assets.Asset;

public class GrantStack extends Stack {
    public GrantStack(final App scope, final String id, final StackProps props) {
        super(scope, id, props);

        File startDir = new File(System.getProperty("user.dir"));

        Asset asset = Asset.Builder.create(this, "SampleAsset")
                .path(new File(startDir, "images/my-image.png").toString()).build();

        Group group = new Group(this, "MyUserGroup");
        asset.grantRead(group);   }
}
```

```
using Amazon.CDK;
using Amazon.CDK.AWS.IAM;
using Amazon.CDK.AWS.S3.Assets;
using System.IO;

var asset = new Asset(this, "MyFile", new AssetProps {
    Path = Path.Combine(Path.Combine(Directory.GetCurrentDirectory(), @"images\my-image.png"))
});

var group = new Group(this, "MyUserGroup");
asset.GrantRead(group);
```

```
import (
  "os"
  "path"

  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/aws-cdk-go/awscdk/v2/awsiam"
  "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets"
)

dirName, err := os.Getwd()
if err != nil {
  panic(err)
}

asset := awss3assets.NewAsset(stack, jsii.String("MyFile"), awss3assets.AssetProps{
  Path: jsii.String(path.Join(dirName, "my-image.png")),
})

group := awsiam.NewGroup(stack, jsii.String("MyUserGroup"), awsiam.GroupProps{})

asset.GrantRead(group)
```

## Activos de imagen de Docker
<a name="assets-types-docker"></a>

El AWS CDK admite la agrupación de imágenes de Docker locales como activos a través del módulo [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr_assets-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr_assets-readme.html).

El siguiente ejemplo define una imagen de Docker que se compilará de forma local y se enviará a Amazon ECR. Las imágenes se crean a partir de un directorio contextual de Docker local (con un Dockerfile), y la CLI de AWS CDK o la canalización de CI/CD de la aplicación se cargan en Amazon ECR. Se puede hacer referencia a las imágenes de forma natural en su aplicación de AWS CDK.

**Example**  

```
import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets';

const asset = new DockerImageAsset(this, 'MyBuildImage', {
  directory: path.join(__dirname, 'my-image')
});
```

```
const { DockerImageAsset } = require('aws-cdk-lib/aws-ecr-assets');

const asset = new DockerImageAsset(this, 'MyBuildImage', {
  directory: path.join(__dirname, 'my-image')
});
```

```
from aws_cdk.aws_ecr_assets import DockerImageAsset

import os.path
dirname = os.path.dirname(__file__)

asset = DockerImageAsset(self, 'MyBuildImage',
    directory=os.path.join(dirname, 'my-image'))
```

```
import software.amazon.awscdk.services.ecr.assets.DockerImageAsset;

File startDir = new File(System.getProperty("user.dir"));

DockerImageAsset asset = DockerImageAsset.Builder.create(this, "MyBuildImage")
            .directory(new File(startDir, "my-image").toString()).build();
```

```
using System.IO;
using Amazon.CDK.AWS.ECR.Assets;

var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps
{
    Directory = Path.Combine(Directory.GetCurrentDirectory(), "my-image")
});
```

```
import (
  "os"
  "path"

  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/aws-cdk-go/awscdk/v2/awsecrassets"
)

dirName, err := os.Getwd()
if err != nil {
  panic(err)
}

asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyBuildImage"), awsecrassets.DockerImageAssetProps{
  Directory: jsii.String(path.Join(dirName, "my-image")),
})
```

El directorio `my-image` debe tener un Dockerfile. La CLI de AWS CDK crea una imagen de Docker a partir de `my-image`, la envía a un repositorio de Amazon ECR y especifica el nombre del repositorio como parámetro de AWS CloudFormation de la pila. Los tipos de activos de imagen de Docker exponen [atributos de tiempo de implementación](resources.md#resources-attributes) que se pueden referenciar en bibliotecas y aplicaciones de AWS CDK. El comando `cdk synth` CLI de AWS CDK muestra las propiedades de los activos como parámetros de AWS CloudFormation.

### Ejemplo de definición de tarea de Amazon ECS
<a name="assets-types-docker-ecs"></a>

Un caso de uso común es crear una [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.TaskDefinition.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.TaskDefinition.html) en Amazon ECS para ejecutar contenedores de Docker. El siguiente ejemplo especifica la ubicación de un activo de imagen de Docker que el AWS CDK crea localmente y envía a Amazon ECR.

**Example**  

```
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecr_assets from 'aws-cdk-lib/aws-ecr-assets';
import * as path from 'path';

const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", {
  memoryLimitMiB: 1024,
  cpu: 512
});

const asset = new ecr_assets.DockerImageAsset(this, 'MyBuildImage', {
  directory: path.join(__dirname, 'my-image')
});

taskDefinition.addContainer("my-other-container", {
  image: ecs.ContainerImage.fromDockerImageAsset(asset)
});
```

```
const ecs = require('aws-cdk-lib/aws-ecs');
const ecr_assets = require('aws-cdk-lib/aws-ecr-assets');
const path = require('path');

const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", {
  memoryLimitMiB: 1024,
  cpu: 512
});

const asset = new ecr_assets.DockerImageAsset(this, 'MyBuildImage', {
  directory: path.join(__dirname, 'my-image')
});

taskDefinition.addContainer("my-other-container", {
  image: ecs.ContainerImage.fromDockerImageAsset(asset)
});
```

```
import aws_cdk.aws_ecs as ecs
import aws_cdk.aws_ecr_assets as ecr_assets

import os.path
dirname = os.path.dirname(__file__)

task_definition = ecs.FargateTaskDefinition(self, "TaskDef",
    memory_limit_mib=1024,
    cpu=512)

asset = ecr_assets.DockerImageAsset(self, 'MyBuildImage',
    directory=os.path.join(dirname, 'my-image'))

task_definition.add_container("my-other-container",
    image=ecs.ContainerImage.from_docker_image_asset(asset))
```

```
import java.io.File;

import software.amazon.awscdk.services.ecs.FargateTaskDefinition;
import software.amazon.awscdk.services.ecs.ContainerDefinitionOptions;
import software.amazon.awscdk.services.ecs.ContainerImage;

import software.amazon.awscdk.services.ecr.assets.DockerImageAsset;

File startDir = new File(System.getProperty("user.dir"));

FargateTaskDefinition taskDefinition = FargateTaskDefinition.Builder.create(
        this, "TaskDef").memoryLimitMiB(1024).cpu(512).build();

DockerImageAsset asset = DockerImageAsset.Builder.create(this, "MyBuildImage")
            .directory(new File(startDir, "my-image").toString()).build();

taskDefinition.addContainer("my-other-container",
        ContainerDefinitionOptions.builder()
            .image(ContainerImage.fromDockerImageAsset(asset))
            .build();
)
```

```
using System.IO;
using Amazon.CDK.AWS.ECS;
using Amazon.CDK.AWS.Ecr.Assets;

var taskDefinition = new FargateTaskDefinition(this, "TaskDef", new FargateTaskDefinitionProps
{
    MemoryLimitMiB = 1024,
    Cpu = 512
});

var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps
{
    Directory = Path.Combine(Directory.GetCurrentDirectory(), "my-image")
});

taskDefinition.AddContainer("my-other-container", new ContainerDefinitionOptions
{
    Image = ContainerImage.FromDockerImageAsset(asset)
});
```

```
import (
  "os"
  "path"

  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/aws-cdk-go/awscdk/v2/awsecrassets"
  "github.com/aws/aws-cdk-go/awscdk/v2/awsecs"
)

dirName, err := os.Getwd()
if err != nil {
  panic(err)
}

taskDefinition := awsecs.NewTaskDefinition(stack, jsii.String("TaskDef"), awsecs.TaskDefinitionProps{
  MemoryMiB: jsii.String("1024"),
  Cpu: jsii.String("512"),
})

asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyBuildImage"), awsecrassets.DockerImageAssetProps{
  Directory: jsii.String(path.Join(dirName, "my-image")),
})

taskDefinition.AddContainer(jsii.String("MyOtherContainer"), awsecs.ContainerDefinitionOptions{
  Image: awsecs.ContainerImage_FromDockerImageAsset(asset),
})
```

### Ejemplo de atributos en tiempo de implementación
<a name="assets-types-docker-deploy"></a>

El siguiente ejemplo muestra cómo utilizar los atributos `repository` y `imageUri` en tiempo de implementación para crear una definición de tarea de Amazon ECS con el tipo de lanzamiento de AWS Fargate. Tenga en cuenta que la búsqueda en el repositorio de Amazon ECR requiere la etiqueta de la imagen, no su URI, por lo que la recortamos del final de la URI del activo.

**Example**  

```
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as path from 'path';
import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets';

const asset = new DockerImageAsset(this, 'my-image', {
  directory: path.join(__dirname, "..", "demo-image")
});

const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", {
  memoryLimitMiB: 1024,
  cpu: 512
});

taskDefinition.addContainer("my-other-container", {
  image: ecs.ContainerImage.fromEcrRepository(asset.repository, asset.imageUri.split(":").pop())
});
```

```
const ecs = require('aws-cdk-lib/aws-ecs');
const path = require('path');
const { DockerImageAsset } = require('aws-cdk-lib/aws-ecr-assets');

const asset = new DockerImageAsset(this, 'my-image', {
  directory: path.join(__dirname, "..", "demo-image")
});

const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", {
  memoryLimitMiB: 1024,
  cpu: 512
});

taskDefinition.addContainer("my-other-container", {
  image: ecs.ContainerImage.fromEcrRepository(asset.repository, asset.imageUri.split(":").pop())
});
```

```
import aws_cdk.aws_ecs as ecs
from aws_cdk.aws_ecr_assets import DockerImageAsset

import os.path
dirname = os.path.dirname(__file__)

asset = DockerImageAsset(self, 'my-image',
    directory=os.path.join(dirname, "..", "demo-image"))

task_definition = ecs.FargateTaskDefinition(self, "TaskDef",
    memory_limit_mib=1024, cpu=512)

task_definition.add_container("my-other-container",
    image=ecs.ContainerImage.from_ecr_repository(
        asset.repository, asset.image_uri.rpartition(":")[-1]))
```

```
import java.io.File;

import software.amazon.awscdk.services.ecr.assets.DockerImageAsset;

import software.amazon.awscdk.services.ecs.FargateTaskDefinition;
import software.amazon.awscdk.services.ecs.ContainerDefinitionOptions;
import software.amazon.awscdk.services.ecs.ContainerImage;

File startDir = new File(System.getProperty("user.dir"));

DockerImageAsset asset = DockerImageAsset.Builder.create(this, "my-image")
            .directory(new File(startDir, "demo-image").toString()).build();

FargateTaskDefinition taskDefinition = FargateTaskDefinition.Builder.create(
        this, "TaskDef").memoryLimitMiB(1024).cpu(512).build();

// extract the tag from the asset's image URI for use in ECR repo lookup
String imageUri = asset.getImageUri();
String imageTag = imageUri.substring(imageUri.lastIndexOf(":") + 1);

taskDefinition.addContainer("my-other-container",
        ContainerDefinitionOptions.builder().image(ContainerImage.fromEcrRepository(
                asset.getRepository(), imageTag)).build());
```

```
using System.IO;
using Amazon.CDK.AWS.ECS;
using Amazon.CDK.AWS.ECR.Assets;

var asset = new DockerImageAsset(this, "my-image", new DockerImageAssetProps {
    Directory = Path.Combine(Directory.GetCurrentDirectory(), "demo-image")
});

var taskDefinition = new FargateTaskDefinition(this, "TaskDef", new FargateTaskDefinitionProps
{
    MemoryLimitMiB = 1024,
    Cpu = 512
});

taskDefinition.AddContainer("my-other-container", new ContainerDefinitionOptions
{
    Image = ContainerImage.FromEcrRepository(asset.Repository, asset.ImageUri.Split(":").Last())
});
```

```
import (
  "os"
  "path"

  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/aws-cdk-go/awscdk/v2/awsecrassets"
  "github.com/aws/aws-cdk-go/awscdk/v2/awsecs"
)

dirName, err := os.Getwd()
if err != nil {
  panic(err)
}

asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyImage"), awsecrassets.DockerImageAssetProps{
  Directory: jsii.String(path.Join(dirName, "demo-image")),
})

taskDefinition := awsecs.NewFargateTaskDefinition(stack, jsii.String("TaskDef"), awsecs.FargateTaskDefinitionProps{
  MemoryLimitMiB: jsii.Number(1024),
  Cpu: jsii.Number(512),
})

taskDefinition.AddContainer(jsii.String("MyOtherContainer"), awsecs.ContainerDefinitionOptions{
  Image: awsecs.ContainerImage_FromEcrRepository(asset.Repository(), asset.ImageTag()),
})
```

### Ejemplo de argumento de compilación
<a name="assets-types-docker-build"></a>

Puede proporcionar argumentos de compilación personalizados para el paso de compilación de Docker a través de la opción de propiedad `buildArgs` (Python: `build_args`) cuando la CLI de AWS CDK compila la imagen durante la implementación.

**Example**  

```
const asset = new DockerImageAsset(this, 'MyBuildImage', {
  directory: path.join(__dirname, 'my-image'),
  buildArgs: {
    HTTP_PROXY: 'http://10.20.30.2:1234'
  }
});
```

```
const asset = new DockerImageAsset(this, 'MyBuildImage', {
  directory: path.join(__dirname, 'my-image'),
  buildArgs: {
    HTTP_PROXY: 'http://10.20.30.2:1234'
  }
});
```

```
asset = DockerImageAsset(self, "MyBuildImage",
    directory=os.path.join(dirname, "my-image"),
    build_args=dict(HTTP_PROXY="http://10.20.30.2:1234"))
```

```
DockerImageAsset asset = DockerImageAsset.Builder.create(this, "my-image"),
            .directory(new File(startDir, "my-image").toString())
            .buildArgs(java.util.Map.of(    // Java 9 or later
                "HTTP_PROXY", "http://10.20.30.2:1234"))
            .build();
```

```
var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps {
    Directory = Path.Combine(Directory.GetCurrentDirectory(), "my-image"),
    BuildArgs = new Dictionarystring, string
    {
        ["HTTP_PROXY"] = "http://10.20.30.2:1234"
    }
});
```

```
dirName, err := os.Getwd()
if err != nil {
  panic(err)
}

asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyBuildImage"), awsecrassets.DockerImageAssetProps{
  Directory: jsii.String(path.Join(dirName, "my-image")),
  BuildArgs: map[string]*string{
    "HTTP_PROXY": jsii.String("http://10.20.30.2:1234"),
  },
})
```

### Permisos
<a name="assets-types-docker-permissions"></a>

Si utiliza un módulo que admite activos de imagen de Docker, como [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs-readme.html), el AWS CDK administrará los permisos cuando utilice los activos directamente o a través de [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.ContainerImage.html#static-fromwbrecrwbrrepositoryrepository-tag](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.ContainerImage.html#static-fromwbrecrwbrrepositoryrepository-tag) (Python: `from_ecr_repository`). Si utiliza los activos de imagen de Docker directamente, asegúrese de que la entidad principal tenga los permisos necesarios para extraer la imagen.

En la mayoría de los casos, debe utilizar el método [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr.Repository.html#grantwbrpullgrantee](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr.Repository.html#grantwbrpullgrantee) (Python: `grant_pull`). Esto modifica la política de IAM de la entidad principal para permitirle extraer imágenes de este repositorio. Si la entidad principal que está extrayendo la imagen no está en la misma cuenta o si se trata de un servicio de AWS que no asume ninguna función en su cuenta (como AWS CodeBuild), debe conceder permisos de extracción en la política de recursos y no en la política de la entidad principal. Utilice el método [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr.Repository.html#addwbrtowbrresourcewbrpolicystatement](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr.Repository.html#addwbrtowbrresourcewbrpolicystatement) (Python: `add_to_resource_policy`) para conceder los permisos principales correspondientes.

## Metadatos de recursos de AWS CloudFormation
<a name="assets-cfn"></a>

**nota**  
Esta sección es relevante solo para los autores de constructos. En determinadas situaciones, las herramientas necesitan saber que un determinado recurso de CFN está utilizando un activo local. Por ejemplo, puede usar la CLI de AWS SAM para invocar funciones de Lambda de manera local con fines de depuración. Consulte la [integración de AWS SAM](tools.md#sam) para obtener más información.

Para habilitar estos casos de uso, las herramientas externas consultan un conjunto de entradas de metadatos en los recursos de AWS CloudFormation:
+  `aws:asset:path`: señala la ruta local del activo.
+  `aws:asset:property`: es el nombre de la propiedad del recurso en la que se utiliza el activo.

Al utilizar estas dos entradas de metadatos, las herramientas pueden identificar qué activos utiliza un determinado recurso y permiten experiencias locales avanzadas.

Para agregar estas entradas de metadatos a un recurso, utilice el método `asset.addResourceMetadata` (Python: `add_resource_metadata`).

# Los permisos y la AWS CDK
<a name="permissions"></a>

La biblioteca AWS Construct utiliza algunos modismos comunes y ampliamente implementados para administrar el acceso y los permisos. El módulo de IAM le proporciona las herramientas que necesita para utilizar estas expresiones idiomáticas.

 AWS El CDK se utiliza AWS CloudFormation para implementar cambios. Cada implementación involucra a un actor (ya sea un desarrollador o un sistema automatizado) que inicia una AWS CloudFormation implementación. Mientras lo hace, el actor asumirá una o más identidades de IAM (usuario o roles) y, si lo desea, le transferirá un rol. AWS CloudFormation

Si utilizas el Centro de Identidad de AWS IAM para autenticarte como usuario, el proveedor de inicio de sesión único te proporcionará credenciales de sesión de corta duración que te autorizarán a actuar como una función de IAM predefinida. *Para saber cómo la AWS CDK obtiene las AWS credenciales de la autenticación del Centro de Identidad de IAM, consulte Cómo [entender la autenticación del Centro de Identidad de IAM en la Guía de referencia y herramientas](https://docs.aws.amazon.com/sdkref/latest/guide/understanding-sso.html). AWS SDKs *

## Entidades principales
<a name="permissions-principals"></a>

Una entidad principal de IAM es una AWS entidad autenticada que representa a un usuario, servicio o aplicación a la que puede llamar. AWS APIs La biblioteca AWS Construct permite especificar los directores de varias formas flexibles para permitirles acceder a sus recursos. AWS 

En contextos de seguridad, el término “entidad principal” se refiere específicamente a las entidades autenticadas, como los usuarios. Los objetos, como los grupos y los roles, no *representan* a los usuarios (ni a otras entidades autenticadas), sino que los *identifican* indirectamente con el fin de concederles permisos.

Por ejemplo, si crea un grupo de IAM, puede conceder al grupo (y, por lo tanto, a sus miembros) acceso para escribir en una tabla de Amazon RDS. Sin embargo, el grupo en sí no es una entidad principal porque no representa a una sola entidad (además, no puede iniciar sesión en un grupo).

En la biblioteca de IAM del CDK, las clases que identifican directa o indirectamente a las entidades principales implementan la interfaz de [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.IPrincipal.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.IPrincipal.html), lo que permite que estos objetos se usen de manera indistinta en las políticas de acceso. Sin embargo, no todos son entidades principales desde el punto de vista de la seguridad. Entre estos objetos, se incluyen:

1. Recursos de IAM, como [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html), [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html) y [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html) 

1. Entidades principales de servicio (`new iam.[ServicePrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ServicePrincipal.html)('service.amazonaws.com')`)

1. Entidades principales federadas (`new iam.[FederatedPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.FederatedPrincipal.html)('cognito-identity.amazonaws.com')`)

1. Principales de cuenta () `new iam.[AccountPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.AccountPrincipal.html)('0123456789012')`

1. Entidades principales de usuario canónico (`new iam.[CanonicalUserPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.CanonicalUserPrincipal.html)('79a59d[…​]7ef2be')`)

1.  AWS Organisations principals () `new iam.[OrganizationPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.OrganizationPrincipal.html)('org-id')`

1. Entidades principales de ARN arbitrarios (`new iam.[ArnPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ArnPrincipal.html)(res.arn)`)

1. `iam.[CompositePrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.CompositePrincipal.html)(principal1, principal2, …​)` para confiar en varias entidades principales

## Concesiones
<a name="permissions-grants"></a>

Muchas construcciones representan recursos a los que se puede acceder, como un bucket de Amazon S3 o una tabla de Amazon DynamoDB. En este caso, puede conceder acceso a otra entidad. Existen dos formas de hacerlo, en función de la construcción en particular: usar su clase de Grants correspondiente (por ejemplo, `BucketGrants` para los buckets de Amazon S3) o usar métodos en la propia construcción, cuyos nombres comienzan por **grant**. Se prefiere el primero porque se puede usar para conceder acceso a los recursos de nivel 1 y nivel 2 de la misma manera. Para crear una instancia de una clase Grants, usa su método de fábrica:

**Example**  

```
BucketGrants.fromBucket(bucket); // bucket can be either a Bucket (L2) or a CfnBucket (L1)
```

```
BucketGrants.fromBucket(bucket); // bucket can be either a Bucket (L2) or a CfnBucket (L1)
```

```
BucketGrants.from_bucket(bucket) # bucket can be either a Bucket (L2) or a CfnBucket (L1)
```

```
BucketGrants.fromBucket(bucket); // bucket can be either a Bucket (L2) or a CfnBucket (L1)
```

```
BucketGrants.FromBucket(bucket); // bucket can be either a Bucket (L2) or a CfnBucket (L1)
```

Las clases de Grants proporcionan métodos para conceder permisos específicos para acceder a sus recursos. Por ejemplo, `BucketGrants` tiene métodos `read` y `readWrite` (Python:`read`,`read_write`) para permitir la lectura y el read/write acceso, respectivamente, desde una entidad al depósito. La entidad no necesita saber exactamente qué permisos de IAM de Amazon S3 son necesarios para realizar estas operaciones.

El primer argumento de los métodos de una clase de Grants (o los métodos de **concesión** de los propios recursos) siempre es de tipo [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.IGrantable.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.IGrantable.html). Esta interfaz representa a las entidades a las que se les pueden conceder permisos. Es decir, representa los recursos con roles, como los objetos de IAM [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html), [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html) y [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html).

También se pueden conceder permisos a otras entidades. Por ejemplo, más adelante en este tema, mostraremos cómo conceder a un CodeBuild proyecto acceso a un bucket de Amazon S3. Por lo general, el rol asociado se obtiene a través de una propiedad `role` de la entidad a la que se concede el acceso.

Los recursos que utilizan roles de ejecución, como [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html), también implementan `IGrantable`, por lo que puede concederles acceso directamente, en lugar de concederle acceso a su rol. Por ejemplo, si `bucket` es un bucket de Amazon S3 y `function` es una función de Lambda, el siguiente código concede a la función acceso de lectura al bucket.

Para mayor comodidad, las construcciones L2 también ofrecen una `grants` propiedad que devuelve una instancia de la clase de Grants correspondiente.

**Example**  

```
bucket.grants.read(function);
```

```
bucket.grants.read(function);
```

```
bucket.grants.read(function)
```

```
bucket.getGrants().read(function);
```

```
bucket.Grants.Read(function);
```

A veces, los permisos se deben aplicar mientras se implementa la pila. Uno de estos casos es cuando se concede a un recurso AWS CloudFormation personalizado acceso a otro recurso. El recurso personalizado se invocará durante la implementación, por lo que debe tener los permisos especificados en el momento de la implementación.

Otro caso es cuando un servicio verifica que el rol que le transfiere tiene aplicadas las políticas correctas. (Varios AWS servicios lo hacen para asegurarse de que no te olvides de configurar las políticas). En esos casos, la implementación podría fallar si los permisos se aplican demasiado tarde.

Para forzar la aplicación de los permisos de la concesión antes de que se cree otro recurso, puede agregar una dependencia a la propia concesión, como se muestra aquí. Si bien el valor devuelto por los métodos de concesión suele descartarse, de hecho, todos los métodos de concesión devuelven un objeto `iam.Grant`.

**Example**  

```
const grant = bucket.grants.read(lambda);
const custom = new CustomResource(...);
custom.node.addDependency(grant);
```

```
const grant = bucket.grants.read(lambda);
const custom = new CustomResource(...);
custom.node.addDependency(grant);
```

```
grant = bucket.grants.read(function)
custom = CustomResource(...)
custom.node.add_dependency(grant)
```

```
Grant grant = bucket.getGrants().read(function);
CustomResource custom = new CustomResource(...);
custom.node.addDependency(grant);
```

```
var grant = bucket.Grants.Read(function);
var custom = new CustomResource(...);
custom.node.AddDependency(grant);
```

## Roles
<a name="permissions-roles"></a>

El paquete de IAM contiene un constructo [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html) que representa los roles de IAM. El siguiente código crea un nuevo rol, de confianza en el EC2 servicio de Amazon.

**Example**  

```
import * as iam from 'aws-cdk-lib/aws-iam';

const role = new iam.Role(this, 'Role', {
  assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),   // required
});
```

```
const iam = require('aws-cdk-lib/aws-iam');

const role = new iam.Role(this, 'Role', {
  assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com')   // required
});
```

```
import aws_cdk.aws_iam as iam

role = iam.Role(self, "Role",
          assumed_by=iam.ServicePrincipal("ec2.amazonaws.com")) # required
```

```
import software.amazon.awscdk.services.iam.Role;
import software.amazon.awscdk.services.iam.ServicePrincipal;

Role role = Role.Builder.create(this, "Role")
        .assumedBy(new ServicePrincipal("ec2.amazonaws.com")).build();
```

```
using Amazon.CDK.AWS.IAM;

var role = new Role(this, "Role", new RoleProps
{
    AssumedBy = new ServicePrincipal("ec2.amazonaws.com"),   // required
});
```

Puede agregar permisos para un rol llamando al método [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#addwbrtowbrpolicystatement](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#addwbrtowbrpolicystatement) del rol (Python: `add_to_policy`) y presentar una [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html) que defina la regla que se va a agregar. La declaración se agrega a la política predeterminada del rol; si no tiene ninguna, se crea una.

El siguiente ejemplo agrega una declaración de política `Deny` al rol para las acciones `ec2:SomeAction` y `s3:AnotherAction` en los recursos `bucket` y `otherRole` (Python: `other_role`), con la condición de que el servicio autorizado sea AWS CodeBuild.

**Example**  

```
role.addToPolicy(new iam.PolicyStatement({
  effect: iam.Effect.DENY,
  resources: [bucket.bucketArn, otherRole.roleArn],
  actions: ['ec2:SomeAction', 's3:AnotherAction'],
  conditions: {StringEquals: {
    'ec2:AuthorizedService': 'codebuild.amazonaws.com',
}}}));
```

```
role.addToPolicy(new iam.PolicyStatement({
  effect: iam.Effect.DENY,
  resources: [bucket.bucketArn, otherRole.roleArn],
  actions: ['ec2:SomeAction', 's3:AnotherAction'],
  conditions: {StringEquals: {
    'ec2:AuthorizedService': 'codebuild.amazonaws.com'
}}}));
```

```
role.add_to_policy(iam.PolicyStatement(
    effect=iam.Effect.DENY,
    resources=[bucket.bucket_arn, other_role.role_arn],
    actions=["ec2:SomeAction", "s3:AnotherAction"],
    conditions={"StringEquals": {
        "ec2:AuthorizedService": "codebuild.amazonaws.com"}}
))
```

```
role.addToPolicy(PolicyStatement.Builder.create()
        .effect(Effect.DENY)
        .resources(Arrays.asList(bucket.getBucketArn(), otherRole.getRoleArn()))
        .actions(Arrays.asList("ec2:SomeAction", "s3:AnotherAction"))
        .conditions(java.util.Map.of(    // Map.of requires Java 9 or later
            "StringEquals", java.util.Map.of(
                "ec2:AuthorizedService", "codebuild.amazonaws.com")))
        .build());
```

```
role.AddToPolicy(new PolicyStatement(new PolicyStatementProps
{
    Effect = Effect.DENY,
    Resources = new string[] { bucket.BucketArn, otherRole.RoleArn },
    Actions = new string[] { "ec2:SomeAction", "s3:AnotherAction" },
    Conditions = new Dictionary<string, object>
    {
        ["StringEquals"] = new Dictionary<string, string>
        {
            ["ec2:AuthorizedService"] = "codebuild.amazonaws.com"
        }
    }
}));
```

En el ejemplo anterior, hemos creado una nueva [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html) insertada con la llamada a [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#addwbrtowbrpolicystatement](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#addwbrtowbrpolicystatement) (Python: `add_to_policy`). También puede presentar una declaración de política existente o una que haya modificado. El objeto [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html) tiene [numerosos métodos](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html#methods) para agregar entidades principales, recursos, condiciones y acciones.

Si está utilizando un constructo que requiere un rol para funcionar correctamente, puede optar por una de las siguientes opciones:
+ Presenta un rol existente al crear una instancia del constructo.
+ Deje que el constructo cree un nuevo rol para usted, que confíe en la entidad principal de servicio apropiada. El siguiente ejemplo utiliza una construcción de este tipo: un CodeBuild proyecto.

**Example**  

```
import * as codebuild from 'aws-cdk-lib/aws-codebuild';

// imagine roleOrUndefined is a function that might return a Role object
// under some conditions, and undefined under other conditions
const someRole: iam.IRole | undefined = roleOrUndefined();

const project = new codebuild.Project(this, 'Project', {
  // if someRole is undefined, the Project creates a new default role,
  // trusting the codebuild.amazonaws.com service principal
  role: someRole,
});
```

```
const codebuild = require('aws-cdk-lib/aws-codebuild');

// imagine roleOrUndefined is a function that might return a Role object
// under some conditions, and undefined under other conditions
const someRole = roleOrUndefined();

const project = new codebuild.Project(this, 'Project', {
  // if someRole is undefined, the Project creates a new default role,
  // trusting the codebuild.amazonaws.com service principal
  role: someRole
});
```

```
import aws_cdk.aws_codebuild as codebuild

# imagine role_or_none is a function that might return a Role object
# under some conditions, and None under other conditions
some_role = role_or_none();

project = codebuild.Project(self, "Project",
# if role is None, the Project creates a new default role,
# trusting the codebuild.amazonaws.com service principal
role=some_role)
```

```
import software.amazon.awscdk.services.iam.Role;
import software.amazon.awscdk.services.codebuild.Project;

// imagine roleOrNull is a function that might return a Role object
// under some conditions, and null under other conditions
Role someRole = roleOrNull();

// if someRole is null, the Project creates a new default role,
// trusting the codebuild.amazonaws.com service principal
Project project = Project.Builder.create(this, "Project")
        .role(someRole).build();
```

```
using Amazon.CDK.AWS.CodeBuild;

// imagine roleOrNull is a function that might return a Role object
// under some conditions, and null under other conditions
var someRole = roleOrNull();

// if someRole is null, the Project creates a new default role,
// trusting the codebuild.amazonaws.com service principal
var project = new Project(this, "Project", new ProjectProps
{
    Role = someRole
});
```

Una vez creado el objeto, el rol (ya sea el rol presentado o el predeterminado que crea el constructo) está disponible como la propiedad de `role`. Sin embargo, esta propiedad no está disponible en los recursos externos. Por lo tanto, estos constructos tienen un método `addToRolePolicy` (Python: `add_to_role_policy`).

El método no hace nada si el constructo es un recurso externo y, de lo contrario, llama al método `addToPolicy` (Python: `add_to_policy`) de la propiedad `role`. Esto le ahorrará la molestia de tratar el caso indefinido de forma explícita.

El siguiente ejemplo lo demuestra:

**Example**  

```
// project is imported into the CDK application
const project = codebuild.Project.fromProjectName(this, 'Project', 'ProjectName');

// project is imported, so project.role is undefined, and this call has no effect
project.addToRolePolicy(new iam.PolicyStatement({
  effect: iam.Effect.ALLOW,   // ... and so on defining the policy
}));
```

```
// project is imported into the CDK application
const project = codebuild.Project.fromProjectName(this, 'Project', 'ProjectName');

// project is imported, so project.role is undefined, and this call has no effect
project.addToRolePolicy(new iam.PolicyStatement({
  effect: iam.Effect.ALLOW   // ... and so on defining the policy
}));
```

```
# project is imported into the CDK application
project = codebuild.Project.from_project_name(self, 'Project', 'ProjectName')

# project is imported, so project.role is undefined, and this call has no effect
project.add_to_role_policy(iam.PolicyStatement(
  effect=iam.Effect.ALLOW,   # ... and so on defining the policy
  )
)
```

```
// project is imported into the CDK application
Project project = Project.fromProjectName(this, "Project", "ProjectName");

// project is imported, so project.getRole() is null, and this call has no effect
project.addToRolePolicy(PolicyStatement.Builder.create()
        .effect(Effect.ALLOW)   // .. and so on defining the policy
        .build();
)
```

```
// project is imported into the CDK application
var project = Project.FromProjectName(this, "Project", "ProjectName");

// project is imported, so project.role is null, and this call has no effect
project.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps
{
    Effect = Effect.ALLOW, // ... and so on defining the policy
}));
```

## Políticas de recursos
<a name="permissions-resource-policies"></a>

Algunos recursos AWS, como los buckets de Amazon S3 y las funciones de IAM, también tienen una política de recursos. Estos constructos tienen un método `addToResourcePolicy` (Python: `add_to_resource_policy`), que toma una [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html) como argumento. Cada declaración de política agregada a una política de recursos debe especificar al menos una entidad principal.

En el siguiente ejemplo, el [bucket de Amazon S3](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) `bucket` otorga un rol con el permiso `s3:SomeAction` para sí mismo.

**Example**  

```
bucket.addToResourcePolicy(new iam.PolicyStatement({
  effect: iam.Effect.ALLOW,
  actions: ['s3:SomeAction'],
  resources: [bucket.bucketArn],
  principals: [role]
}));
```

```
bucket.addToResourcePolicy(new iam.PolicyStatement({
  effect: iam.Effect.ALLOW,
  actions: ['s3:SomeAction'],
  resources: [bucket.bucketArn],
  principals: [role]
}));
```

```
bucket.add_to_resource_policy(iam.PolicyStatement(
    effect=iam.Effect.ALLOW,
    actions=["s3:SomeAction"],
    resources=[bucket.bucket_arn],
    principals=role))
```

```
bucket.addToResourcePolicy(PolicyStatement.Builder.create()
        .effect(Effect.ALLOW)
        .actions(Arrays.asList("s3:SomeAction"))
        .resources(Arrays.asList(bucket.getBucketArn()))
        .principals(Arrays.asList(role))
        .build());
```

```
bucket.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps
{
    Effect = Effect.ALLOW,
    Actions = new string[] { "s3:SomeAction" },
    Resources = new string[] { bucket.BucketArn },
    Principals = new IPrincipal[] { role }
}));
```

## Uso de objetos de IAM externos
<a name="permissions-existing"></a>

Si ha definido un usuario, director, grupo o rol de IAM fuera de su aplicación de AWS CDK, puede usar ese objeto de IAM en su aplicación de CDK. AWS Para ello, cree una referencia a él con su ARN o su nombre. (Utilice el nombre para los usuarios, los grupos y los roles). A continuación, la referencia que se obtiene se puede utilizar para conceder permisos o para elaborar declaraciones de políticas, como se ha explicado anteriormente.
+ Para los usuarios, llame a [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html#static-fromwbruserwbrarnscope-id-userarn](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html#static-fromwbruserwbrarnscope-id-userarn) o [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html#static-fromwbruserwbrnamescope-id-username](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html#static-fromwbruserwbrnamescope-id-username). `User.fromUserAttributes()` también está disponible, pero en este momento ofrece la misma funcionalidad que `User.fromUserArn()`.
+ Para las entidades principales, cree una instancia de un objeto [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ArnPrincipal.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ArnPrincipal.html).
+ Para grupos, llame a [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html#static-fromwbrgroupwbrarnscope-id-grouparn](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html#static-fromwbrgroupwbrarnscope-id-grouparn) o [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html#static-fromwbrgroupwbrnamescope-id-groupname](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html#static-fromwbrgroupwbrnamescope-id-groupname).
+ Para roles, llame a [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#static-fromwbrrolewbrarnscope-id-rolearn-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#static-fromwbrrolewbrarnscope-id-rolearn-options) o [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#static-fromwbrrolewbrnamescope-id-rolename](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#static-fromwbrrolewbrnamescope-id-rolename).

Las políticas (incluidas las políticas administradas) se pueden utilizar de forma similar mediante los siguientes métodos. Puede utilizar las referencias a estos objetos en cualquier lugar que se requiera una política de IAM.
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Policy.html#static-fromwbrpolicywbrnamescope-id-policyname](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Policy.html#static-fromwbrpolicywbrnamescope-id-policyname) 
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrmanagedwbrpolicywbrarnscope-id-managedpolicyarn](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrmanagedwbrpolicywbrarnscope-id-managedpolicyarn) 
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrmanagedwbrpolicywbrnamescope-id-managedpolicyname](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrmanagedwbrpolicywbrnamescope-id-managedpolicyname) 
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrawswbrmanagedwbrpolicywbrnamemanagedpolicyname](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrawswbrmanagedwbrpolicywbrnamemanagedpolicyname) 

**nota**  
Como ocurre con todas las referencias a AWS recursos externos, no puede modificar los objetos de IAM externos en su aplicación de CDK.

# Los valores de contexto y la CDK AWS
<a name="context"></a>

Los valores de contexto son pares clave-valor que pueden asociarse a una aplicación, pila o constructo. Se pueden proporcionar a la aplicación desde un archivo (generalmente, `cdk.json` o `cdk.context.json` en el directorio del proyecto) o en la línea de comandos.

El kit de herramientas CDK utiliza el contexto para almacenar en caché los valores recuperados de su AWS cuenta durante la síntesis. Los valores incluyen las zonas de disponibilidad de su cuenta o los ID de imagen de máquina de Amazon (AMI) disponibles actualmente para las instancias de Amazon EC2. Como estos valores los proporciona su AWS cuenta, pueden cambiar de una ejecución a otra de la aplicación de CDK. Esto los convierte en una posible fuente de cambios no deseados. El comportamiento de almacenamiento en memoria caché del kit de herramientas de CDK “congela” estos valores para la aplicación de CDK hasta que usted decida aceptar los valores nuevos.

Imagine el siguiente escenario sin almacenamiento en memoria caché de contexto. Supongamos que especificó la “última versión de Amazon Linux” como AMI para las instancias de Amazon EC2, y se publicó una versión nueva de esta AMI. Entonces, la próxima vez que implemente su pila de CDK, las instancias ya implementadas utilizarán la AMI obsoleta (“incorrecta”) y deberán actualizarse. La actualización implicaría la sustitución de todas las instancias existentes por otras nuevas, lo que probablemente no sea lo deseado ni lo esperado.

En su lugar, la CDK registra la disponibilidad de su cuenta AMIs en el `cdk.context.json` archivo de su proyecto y utiliza el valor almacenado para futuras operaciones de síntesis. De esta forma, la lista de AMIs deja de ser una fuente potencial de cambio. También puedes estar seguro de que tus pilas siempre se sintetizarán en las mismas AWS CloudFormation plantillas.

No todos los valores de contexto son valores en caché de su entorno. AWS Las [AWS marcas de características de CDK](featureflags.md) también son valores de contexto. También puede crear sus propios valores de contexto para que sus aplicaciones o constructos los utilicen.

Las claves de contexto son cadenas. Los valores pueden ser de cualquier tipo compatible con JSON: números, cadenas, matrices u objetos.

**sugerencia**  
Si sus constructos crean sus propios valores de contexto, incorpore el nombre del paquete de la biblioteca en las claves para que no entren en conflicto con los valores de contexto de otros paquetes.

Muchos valores de contexto están asociados a un AWS entorno concreto, y una aplicación de CDK determinada se puede implementar en más de un entorno. La clave de dichos valores incluye la AWS cuenta y la región, de modo que los valores de distintos entornos no entren en conflicto.

La siguiente clave de contexto ilustra el formato utilizado por la AWS CDK, incluidas la cuenta y la región.

```
availability-zones:account=123456789012:region=eu-central-1
```

**importante**  
La AWS CDK y sus componentes, incluidos los que puede escribir, administran los valores de contexto almacenados en caché. No agregue ni modifique los valores de contexto almacenados en la memoria caché mediante la edición manual de los archivos. Sin embargo, puede resultar útil revisar `cdk.context.json` de vez en cuando para ver qué valores se están almacenando en la memoria caché. Los valores de contexto que no representan valores almacenados en la memoria caché deben almacenarse con la clave `context` de `cdk.json`. De esta forma, no se borrarán cuando se borren los valores almacenados en la memoria caché.

## Orígenes de los valores de contexto
<a name="context-construct"></a>

Los valores de contexto se pueden proporcionar a tu aplicación de AWS CDK de seis maneras diferentes:
+ Automáticamente desde la AWS cuenta corriente.
+ Mediante la opción `--context` al comando `cdk`. (Estos valores son siempre cadenas).
+ En el archivo `cdk.context.json` del proyecto.
+ En la clave `context` del archivo `cdk.json` del proyecto.
+ En la clave `context` de su archivo `~/.cdk.json`.
+ En tu aplicación AWS CDK utilizando el `construct.node.setContext()` método.

El archivo del proyecto `cdk.context.json` es donde la AWS CDK almacena en caché los valores de contexto recuperados de tu cuenta. AWS Esta práctica evita cambios inesperados en las implementaciones cuando, por ejemplo, se introduce una zona de disponibilidad nueva. La AWS CDK no escribe datos de contexto en ninguno de los demás archivos de la lista.

**importante**  
Dado que forman parte del estado de la aplicación, `cdk.json` y `cdk.context.json` deben estar sujetos al control de código fuente junto con el resto del código fuente de la aplicación. De lo contrario, las implementaciones en otros entornos (por ejemplo, una canalización de CI) podrían producir resultados incoherentes.

Los valores de contexto se asignan al constructo que los creó; son visibles para los constructos secundarios, pero no para los principales o del mismo nivel. Los valores de contexto que establece el kit de herramientas AWS CDK (el `cdk` comando) se pueden configurar automáticamente, desde un archivo o desde la opción. `--context` Los valores de contexto de estos orígenes se establecen de manera implícita en el constructo `App`. Por lo tanto, son visibles para todos los constructos de todas las pilas de la aplicación.

Su aplicación puede leer un valor de contexto mediante el método `construct.node.tryGetContext`. Si la entrada solicitada no se encuentra en el constructo actual ni en ninguno de los principales, el resultado será `undefined`. (Como alternativa, el resultado podría ser el equivalente en su lenguaje, como `None` en Python).

## Métodos de context
<a name="context-methods"></a>

La AWS CDK admite varios métodos de contexto que permiten a las aplicaciones de la AWS CDK obtener información contextual del entorno. AWS Por ejemplo, puede obtener una lista de las zonas de disponibilidad que están disponibles en una AWS cuenta y región determinadas mediante este método. [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones)

Los métodos de contexto son los siguientes:

 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_route53.HostedZone.html#static-fromwbrlookupscope-id-query](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_route53.HostedZone.html#static-fromwbrlookupscope-id-query)   
Obtiene las zonas alojadas de su cuenta.

 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones)   
Obtiene las zonas de disponibilidad compatibles.

 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameter.html#static-valuewbrfromwbrlookupscope-parametername](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameter.html#static-valuewbrfromwbrlookupscope-parametername)   
Obtiene un valor del almacén de parámetros de Systems Manager de Amazon EC2 de la región actual.

 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options)   
Obtiene las Amazon Virtual Private Cloud existentes en sus cuentas.

 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.LookupMachineImage.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.LookupMachineImage.html)   
Busca una imagen de máquina para utilizarla con una instancia de NAT en una Amazon Virtual Private Cloud.

Si el valor de contexto obligatorio no está disponible, la aplicación AWS CDK notifica al CDK Toolkit que falta la información de contexto. A continuación, la CLI consulta la información en la AWS cuenta corriente y almacena la información de contexto resultante en el `cdk.context.json` archivo. A continuación, vuelve a ejecutar la aplicación AWS CDK con los valores de contexto.

## Visualización y administración del contexto
<a name="context-viewing"></a>

Utilice el comando `cdk context` para ver y administrar la información del archivo `cdk.context.json`. Para ver esta información, utilice el comando `cdk context` sin ninguna opción. El resultado debería verse de la siguiente manera.

```
Context found in cdk.json:

┌───┬─────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────┐
│ # │ Key                                                         │ Value                                                   │
├───┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤
│ 1 │ availability-zones:account=123456789012:region=eu-central-1 │ [ "eu-central-1a", "eu-central-1b", "eu-central-1c" ]   │
├───┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤
│ 2 │ availability-zones:account=123456789012:region=eu-west-1    │ [ "eu-west-1a", "eu-west-1b", "eu-west-1c" ]            │
└───┴─────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────┘

Run

  cdk context --reset KEY_OR_NUMBER

 to remove a context key. If it is a cached value, it will be refreshed on the next

  cdk synth

.
```

Para eliminar un valor de contexto, ejecute `cdk context --reset` y especifique la clave o el número correspondiente al valor. En el siguiente ejemplo, se elimina el valor que corresponde a la segunda clave del ejemplo anterior. Este valor representa la lista de zonas de disponibilidad de la región de Europa (Irlanda).

```
cdk context --reset 2
```

```
Context value
availability-zones:account=123456789012:region=eu-west-1
reset. It will be refreshed on the next SDK synthesis run.
```

Por lo tanto, si desea actualizar a la última versión de la AMI de Amazon Linux, utilice el ejemplo anterior para realizar una actualización controlada del valor de contexto y restablecerlo. Luego, sintetice y vuelva a implementar la aplicación.

```
$ cdk synth
```

Para borrar todos los valores de contexto almacenados de su aplicación, ejecute `cdk context --clear`, como se muestra a continuación.

```
$ cdk context --clear
```

Solo se pueden restablecer o borrar los valores de contexto almacenados en `cdk.context.json`. La AWS CDK no toca otros valores de contexto. Por lo tanto, para evitar que un valor de contexto se restablezca mediante estos comandos, puede copiar el valor en `cdk.json`.

## AWS Bandera CDK Toolkit `--context`
<a name="context-cli"></a>

Utilice la opción `--context` (`-c` abreviada) para pasar los valores de contexto de tiempo de ejecución a su aplicación de CDK durante la síntesis o la implementación.

```
$ cdk synth --context key=value MyStack
```

Para especificar varios valores de contexto, repita la opción `--context` tantas veces como desee y proporcione un par clave-valor cada vez que repita la acción.

```
$ cdk synth --context key1=value1 --context key2=value2 MyStack
```

Cuando se sintetizan varias pilas, los valores de contexto especificados se transfieren a todas las pilas. Para proporcionar diferentes valores de contexto a pilas individuales, utilice diferentes claves para los valores o utilice varios comandos `cdk synth` o `cdk deploy`.

Los valores de contexto que se pasan desde la línea de comandos son siempre cadenas. Si un valor suele ser de otro tipo, el código debe estar preparado para convertir o analizar el valor. Es posible que los valores de contexto que no sean cadenas se proporcionen de otras formas (por ejemplo, en `cdk.context.json`). Para asegurarse de que este tipo de valor funciona según lo esperado, confirme que el valor es una cadena antes de convertirlo.

## Ejemplo
<a name="context-example"></a>

A continuación se muestra un ejemplo del uso de una Amazon VPC existente mediante el contexto de AWS CDK.

**Example**  

```
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { Construct } from 'constructs';

export class ExistsVpcStack extends cdk.Stack {

  constructor(scope: Construct, id: string, props?: cdk.StackProps) {

    super(scope, id, props);

    const vpcid = this.node.tryGetContext('vpcid');
    const vpc = ec2.Vpc.fromLookup(this, 'VPC', {
      vpcId: vpcid,
    });

    const pubsubnets = vpc.selectSubnets({subnetType: ec2.SubnetType.PUBLIC});

    new cdk.CfnOutput(this, 'publicsubnets', {
      value: pubsubnets.subnetIds.toString(),
    });
  }
}
```

```
const cdk = require('aws-cdk-lib');
const ec2 = require('aws-cdk-lib/aws-ec2');

class ExistsVpcStack extends cdk.Stack {

  constructor(scope, id, props) {

    super(scope, id, props);

    const vpcid = this.node.tryGetContext('vpcid');
    const vpc = ec2.Vpc.fromLookup(this, 'VPC', {
      vpcId: vpcid
    });

    const pubsubnets = vpc.selectSubnets({subnetType: ec2.SubnetType.PUBLIC});

    new cdk.CfnOutput(this, 'publicsubnets', {
      value: pubsubnets.subnetIds.toString()
    });
  }
}

module.exports = { ExistsVpcStack }
```

```
import aws_cdk as cdk
import aws_cdk.aws_ec2 as ec2
from constructs import Construct

class ExistsVpcStack(cdk.Stack):

    def __init__(scope: Construct, id: str, **kwargs):

        super().__init__(scope, id, **kwargs)

        vpcid = self.node.try_get_context("vpcid")
        vpc = ec2.Vpc.from_lookup(self, "VPC", vpc_id=vpcid)

        pubsubnets = vpc.select_subnets(subnetType=ec2.SubnetType.PUBLIC)

        cdk.CfnOutput(self, "publicsubnets",
            value=pubsubnets.subnet_ids.to_string())
```

```
import software.amazon.awscdk.CfnOutput;

import software.amazon.awscdk.services.ec2.Vpc;
import software.amazon.awscdk.services.ec2.VpcLookupOptions;
import software.amazon.awscdk.services.ec2.SelectedSubnets;
import software.amazon.awscdk.services.ec2.SubnetSelection;
import software.amazon.awscdk.services.ec2.SubnetType;
import software.constructs.Construct;

public class ExistsVpcStack extends Stack {
    public ExistsVpcStack(Construct context, String id) {
        this(context, id, null);
    }

    public ExistsVpcStack(Construct context, String id, StackProps props) {
        super(context, id, props);

        String vpcId = (String)this.getNode().tryGetContext("vpcid");
        Vpc vpc = (Vpc)Vpc.fromLookup(this, "VPC", VpcLookupOptions.builder()
                .vpcId(vpcId).build());

        SelectedSubnets pubSubNets = vpc.selectSubnets(SubnetSelection.builder()
                .subnetType(SubnetType.PUBLIC).build());

        CfnOutput.Builder.create(this, "publicsubnets")
                .value(pubSubNets.getSubnetIds().toString()).build();
    }
}
```

```
using Amazon.CDK;
using Amazon.CDK.AWS.EC2;
using Constructs;

class ExistsVpcStack : Stack
{
    public ExistsVpcStack(Construct scope, string id, StackProps props) : base(scope, id, props)
    {
        var vpcId = (string)this.Node.TryGetContext("vpcid");
        var vpc = Vpc.FromLookup(this, "VPC", new VpcLookupOptions
        {
            VpcId = vpcId
        });

        SelectedSubnets pubSubNets = vpc.SelectSubnets([new SubnetSelection
        {
            SubnetType = SubnetType.PUBLIC
        }]);

        new CfnOutput(this, "publicsubnets", new CfnOutputProps {
            Value = pubSubNets.SubnetIds.ToString()
        });
    }
}
```

Puede utilizar `cdk diff` para ver los efectos de pasar un valor de contexto en la línea de comandos:

```
$ cdk diff -c vpcid=vpc-0cb9c31031d0d3e22
```

```
Stack ExistsvpcStack
Outputs
[+] Output publicsubnets publicsubnets: {"Value":"subnet-06e0ea7dd302d3e8f,subnet-01fc0acfb58f3128f"}
```

Los valores de contexto resultantes pueden verse como se muestra a continuación.

```
$ cdk context -j
```

```
{
  "vpc-provider:account=123456789012:filter.vpc-id=vpc-0cb9c31031d0d3e22:region=us-east-1": {
    "vpcId": "vpc-0cb9c31031d0d3e22",
    "availabilityZones": [
      "us-east-1a",
      "us-east-1b"
    ],
    "privateSubnetIds": [
      "subnet-03ecfc033225be285",
      "subnet-0cded5da53180ebfa"
    ],
    "privateSubnetNames": [
      "Private"
    ],
    "privateSubnetRouteTableIds": [
      "rtb-0e955393ced0ada04",
      "rtb-05602e7b9f310e5b0"
    ],
    "publicSubnetIds": [
      "subnet-06e0ea7dd302d3e8f",
      "subnet-01fc0acfb58f3128f"
    ],
    "publicSubnetNames": [
      "Public"
    ],
    "publicSubnetRouteTableIds": [
      "rtb-00d1fdfd823c82289",
      "rtb-04bb1969b42969bcb"
    ]
  }
}
```

# Marcas de características de AWS CDK
<a name="featureflags"></a>

AWS CDK utiliza *marcas de características* para habilitar posibles comportamientos disruptivos en una versión. Las marcas se almacenan como [valores de contexto y los valores de AWS CDK](context.md) en `cdk.json` (o `~/.cdk.json`). Los comandos `cdk context --clear` y `cdk context --reset` no los eliminan.

Las marcas de características están desactivadas de forma predeterminada. Los proyectos existentes que no especifiquen la marca funcionarán como antes en las versiones de AWS CDK posteriores. Los nuevos proyectos creados con `cdk init` incluyen marcas que habilitan todas las características disponibles en la versión en la que se creó el proyecto. Edite `cdk.json` para deshabilitar las marcas para las que prefiera el comportamiento anterior. También puede agregar marcas para habilitar nuevos comportamientos después de actualizar el AWS CDK.

Puede encontrar una lista de todas las marcas de características actuales en el repositorio de AWS CDK de GitHub en [FEATURE\$1FLAGS.md](https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md). Consulte `CHANGELOG` de una versión determinada para ver una descripción de las nuevas marcas de características agregadas en esa versión.

## Restablecer al comportamiento de la v1
<a name="featureflags-disabling"></a>

En la v2 de CDK, los valores predeterminados de algunas marcas de características cambiaron con respecto a la v1. Puede volver a configurarlos como `false` para volver al comportamiento específico de la v1 de AWS CDK. Utilice el comando `cdk diff` para inspeccionar los cambios en la plantilla sintetizada y ver si se necesita alguna de estas marcas.

 `@aws-cdk/core:newStyleStackSynthesis`   
Utilice el nuevo método de síntesis de pilas, que asume recursos de arranque con nombres conocidos. Requiere un [arranque moderno](bootstrapping.md), pero a cambio permite CI/CD a través de [CDK Pipelines](cdk-pipeline.md) y las implementaciones entre cuentas desde el primer momento.

 `@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId`   
Si su aplicación utiliza varias claves de API de Amazon API Gateway y las asocia a planes de uso.

 `@aws-cdk/aws-rds:lowercaseDbIdentifier`   
Si su aplicación utiliza instancias de bases de datos o clústeres de bases de datos de Amazon RDS y especifica de forma explícita su identificador.

 `@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021`   
Si su aplicación utiliza la política de seguridad TLS\$1V1\$12\$12019 con las distribuciones de Amazon CloudFront. El CDK v2 utiliza la política de seguridad TLSv1.2\$12021 de forma predeterminada.

 `@aws-cdk/core:stackRelativeExports`   
Si la aplicación utiliza varias pilas y hace referencia a los recursos de una pila en otra, esto determinará si se utiliza la ruta absoluta o relativa para construir las exportaciones de AWS CloudFormation.

 `@aws-cdk/aws-lambda:recognizeVersionProps`   
Si se establece en `false`, el CDK incluye metadatos al detectar si una función de Lambda cambió. Esto puede provocar errores de implementación cuando solo se modificaron los metadatos, ya que no se permiten versiones duplicadas. No es necesario revertir esta marca si realizó al menos un cambio en todas las funciones de Lambda en la aplicación.

La sintaxis para revertir estas marcas en `cdk.json` se muestra aquí.

```
{
  "context": {
    "@aws-cdk/core:newStyleStackSynthesis": false,
    "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": false,
    "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": false,
    "@aws-cdk/aws-rds:lowercaseDbIdentifier": false,
    "@aws-cdk/core:stackRelativeExports": false,
    "@aws-cdk/aws-lambda:recognizeVersionProps": false
  }
}
```

# Aspectos y el AWS CDK
<a name="aspects"></a>

Los aspectos son una forma de aplicar una operación a todos los constructos de un ámbito determinado. El aspecto podría modificar los constructos, por ejemplo, mediante el agregado de etiquetas. O podría verificar algo sobre el estado de los constructos, como asegurarse de que todos los bucket estén cifrados.

Para aplicar un aspecto a un constructo y a todos los constructos del mismo ámbito, llame a ` [Aspects](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Aspects.html#static-ofscope).of(<SCOPE>).add()` con aspecto nuevo, como se muestra en el siguiente ejemplo.

**Example**  

```
Aspects.of(myConstruct).add(new SomeAspect(...));
```

```
Aspects.of(myConstruct).add(new SomeAspect(...));
```

```
Aspects.of(my_construct).add(SomeAspect(...))
```

```
Aspects.of(myConstruct).add(new SomeAspect(...));
```

```
Aspects.Of(myConstruct).add(new SomeAspect(...));
```

```
awscdk.Aspects_Of(stack).Add(awscdk.NewTag(...))
```

El AWS CDK usa aspectos para [etiquetar los recursos](tagging.md), pero el marco también se puede usar para otros fines. Por ejemplo, puede usarla para validar o cambiar los AWS CloudFormation recursos que definan para usted las construcciones de nivel superior.

## Aspectos frente a mixins
<a name="aspects-vs-mixins"></a>

Tanto Aspects como [Mixins](mixins.md) modifican los constructos, pero difieren en el momento y la forma en que se aplican:


| Característica | Aspectos | Mezclas | 
| --- | --- | --- | 
|   **Cuando se aplica**   |  Durante la síntesis, después de que se haya ejecutado el resto del código.  |  Inmediatamente cuando `.with()` se llama.  | 
|   **Alcance**   |  Todas las construcciones de un ámbito determinado, incluidas las que se agreguen posteriormente.  |  Solo las construcciones a las que las aplique de forma explícita.  | 
|   **Style (Estilo)**   |  Declarativo: se establece una regla y la CDK la aplica.  |  Imperativo: tú eliges qué aplicar y dónde.  | 
|   **Lo mejor para**   |  Validación, conformidad, etiquetado y políticas generales.  |  Añadir funciones específicas a los recursos individuales.  | 

Utilice Aspects cuando desee hacer cumplir las reglas en toda la aplicación o validar que las construcciones cumplan ciertos criterios. Utilice Mixins cuando desee añadir una función específica a una construcción específica.

Aspects y Mixins se pueden usar juntos. Por ejemplo, puede usar Mixins para configurar recursos individuales y Aspects para validar que todos los recursos de una pila cumplen con los requisitos de seguridad de su organización.

## Aspectos en detalle
<a name="aspects-detail"></a>

Los aspectos emplean el [patrón de visitantes](https://en.wikipedia.org/wiki/Visitor_pattern). Un aspecto es una clase que implementa la siguiente interfaz.

**Example**  

```
interface IAspect {
   visit(node: IConstruct): void;}
```
JavaScript no tiene interfaces como función de idioma. Por lo tanto, un aspecto es simplemente una instancia de una clase que tiene un método `visit` que acepta el nodo en el que se va a operar.
Python no tiene interfaces como característica del lenguaje. Por lo tanto, un aspecto es simplemente una instancia de una clase que tiene un método `visit` que acepta el nodo en el que se va a operar.

```
public interface IAspect {
    public void visit(Construct node);
}
```

```
public interface IAspect
{
    void Visit(IConstruct node);
}
```

```
type IAspect interface {
  Visit(node constructs.IConstruct)
}
```

Cuando llama a `Aspects.of(<SCOPE>).add(…​)`, el constructo agrega el aspecto a una lista interna de aspectos. Puede obtener la lista mediante `Aspects.of(<SCOPE>)`.

Durante la [fase de preparación](deploy.md#deploy-how-synth-app), el AWS CDK llama al `visit` método del objeto para la construcción y para cada uno de sus elementos secundarios en orden descendente.

El método `visit` puede cambiar cualquier aspecto del constructo. En lenguajes fuertemente tipados, convierta el constructo recibido en un tipo más específico antes de acceder a las propiedades o métodos específicos del constructo.

Los aspectos no se propagan a través de los límites `Stage` de los constructos, porque los `Stages` son autónomos e inmutables después de la definición. Aplique los aspectos en el propio `Stage` del constructo (o en una parte inferior) si quiere que visiten los constructos que se encuentran dentro del `Stage`.

## Ejemplo
<a name="aspects-example"></a>

El siguiente ejemplo valida que todos los buckets creados en la pila tengan activado el control de versiones. El aspecto agrega una anotación de error a los constructos que no superan la validación. Esto provoca un error en la operación `synth` e impide implementar el ensamblaje de nube resultante.

**Example**  

```
class BucketVersioningChecker implements IAspect {
  public visit(node: IConstruct): void {
    // See that we're dealing with a CfnBucket
    if (node instanceof s3.CfnBucket) {

      // Check for versioning property, exclude the case where the property
      // can be a token (IResolvable).
      if (!node.versioningConfiguration
        || (!Tokenization.isResolvable(node.versioningConfiguration)
            && node.versioningConfiguration.status !== 'Enabled')) {
        Annotations.of(node).addError('Bucket versioning is not enabled');
      }
    }
  }
}

// Later, apply to the stack
Aspects.of(stack).add(new BucketVersioningChecker());
```

```
class BucketVersioningChecker {
   visit(node) {
    // See that we're dealing with a CfnBucket
    if ( node instanceof s3.CfnBucket) {

      // Check for versioning property, exclude the case where the property
      // can be a token (IResolvable).
      if (!node.versioningConfiguration
        || !Tokenization.isResolvable(node.versioningConfiguration)
            && node.versioningConfiguration.status !== 'Enabled')) {
        Annotations.of(node).addError('Bucket versioning is not enabled');
      }
    }
  }
}

// Later, apply to the stack
Aspects.of(stack).add(new BucketVersioningChecker());
```

```
@jsii.implements(cdk.IAspect)
class BucketVersioningChecker:

  def visit(self, node):
    # See that we're dealing with a CfnBucket
    if isinstance(node, s3.CfnBucket):

      # Check for versioning property, exclude the case where the property
      # can be a token (IResolvable).
      if (not node.versioning_configuration or
              not Tokenization.is_resolvable(node.versioning_configuration)
                  and node.versioning_configuration.status != "Enabled"):
          Annotations.of(node).add_error('Bucket versioning is not enabled')

# Later, apply to the stack
Aspects.of(stack).add(BucketVersioningChecker())
```

```
public class BucketVersioningChecker implements IAspect
{
    @Override
    public void visit(Construct node)
    {
        // See that we're dealing with a CfnBucket
        if (node instanceof CfnBucket)
        {
            CfnBucket bucket = (CfnBucket)node;
            Object versioningConfiguration = bucket.getVersioningConfiguration();
            if (versioningConfiguration == null ||
                    !Tokenization.isResolvable(versioningConfiguration.toString()) &&
                    !versioningConfiguration.toString().contains("Enabled"))
                Annotations.of(bucket.getNode()).addError("Bucket versioning is not enabled");
        }
    }
}

// Later, apply to the stack
Aspects.of(stack).add(new BucketVersioningChecker());
```

```
class BucketVersioningChecker : Amazon.Jsii.Runtime.Deputy.DeputyBase, IAspect
{
    public void Visit(IConstruct node)
    {
        // See that we're dealing with a CfnBucket
        if (node is CfnBucket)
        {
            var bucket = (CfnBucket)node;
            if (bucket.VersioningConfiguration is null ||
                    !Tokenization.IsResolvable(bucket.VersioningConfiguration) &&
                    !bucket.VersioningConfiguration.ToString().Contains("Enabled"))
                Annotations.Of(bucket.Node).AddError("Bucket versioning is not enabled");
        }
    }
}

// Later, apply to the stack
Aspects.Of(stack).add(new BucketVersioningChecker());
```