

Este é o Guia do desenvolvedor do AWS CDK v2. O CDK v1 antigo entrou em manutenção em 1º de junho de 2022 e encerrou o suporte em 1º de junho de 2023.

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Conheça os principais AWS conceitos do CDK
<a name="core-concepts"></a>

Conheça os principais conceitos por trás do AWS Cloud Development Kit (AWS CDK).

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

O AWS CDK é uma estrutura de código aberto que você pode usar para gerenciar sua AWS infraestrutura usando código. Essa abordagem é conhecida como *infraestrutura como código (IaC)*. Ao gerenciar e provisionar sua infraestrutura como código, você trata sua infraestrutura da mesma forma que os desenvolvedores tratam o código. Isso oferece muitos benefícios, como controle de versão e escalabilidade. Para saber mais sobre o IaC, consulte [O que é infraestrutura como código?](https://aws.amazon.com/what-is/iac/) 

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

O AWS CDK está totalmente integrado com o. AWS CloudFormation AWS CloudFormation é um serviço totalmente gerenciado que você pode usar para gerenciar e provisionar sua infraestrutura AWS. Com AWS CloudFormation, você define sua infraestrutura em modelos e os implanta em AWS CloudFormation. O AWS CloudFormation serviço então provisiona sua infraestrutura de acordo com a configuração definida em seus modelos.

 AWS CloudFormation os modelos são *declarativos*, o que significa que eles declaram o estado ou o resultado desejado de sua infraestrutura. *Usando JSON ou YAML, você declara sua AWS infraestrutura definindo AWS *recursos* e propriedades.* Os recursos representam os vários serviços AWS e as propriedades representam a configuração desejada desses serviços. Quando você implanta seu modelo em AWS CloudFormation, seus recursos e suas propriedades configuradas são provisionados conforme descrito em seu modelo.

Com o AWS CDK, você pode gerenciar sua infraestrutura de *forma imperativa*, usando linguagens de programação de uso geral. Em vez de apenas definir um estado desejado declarativamente, você pode definir a lógica ou a sequência necessária para alcançar o estado desejado. Por exemplo, você pode usar instruções `if` ou loops condicionais que determinam como alcançar o estado final desejado para sua infraestrutura.

A infraestrutura criada com o AWS CDK é eventualmente traduzida ou *sintetizada* em AWS CloudFormation modelos e implantada usando o serviço. AWS CloudFormation Portanto, embora o AWS CDK ofereça uma abordagem diferente para criar sua infraestrutura, você ainda recebe os benefícios de AWS CloudFormation, como amplo suporte à configuração de AWS recursos e processos robustos de implantação.

Para saber mais AWS CloudFormation, consulte [O que é AWS CloudFormation?](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html) no *Guia do AWS CloudFormation usuário*.

## AWS CDK e abstrações
<a name="concepts-abstractions"></a>

Com AWS CloudFormation, você deve definir todos os detalhes de como seus recursos são configurados. Isso oferece a vantagem de ter controle total sobre sua infraestrutura. No entanto, isso exige que você aprenda, compreenda e crie modelos robustos que contenham detalhes de configuração de recursos e relacionamentos entre recursos, como permissões e interações orientadas por eventos.

Com o AWS CDK, você pode ter o mesmo controle sobre suas configurações de recursos. No entanto, o AWS CDK também oferece abstrações poderosas, que podem acelerar e simplificar o processo de desenvolvimento da infraestrutura. Por exemplo, o AWS CDK inclui construções que fornecem configurações padrão sensatas e métodos auxiliares que geram código padronizado para você. O AWS CDK também oferece ferramentas, como a AWS CDK Command Line Interface (AWS CDK CLI), que executam ações de gerenciamento de infraestrutura para você.

## Saiba mais sobre os principais conceitos do AWS CDK
<a name="concepts-learn"></a><a name="concepts-learn-interact"></a>

 **Interagindo com o CDK AWS **   
Ao usar com o AWS CDK, você interagirá principalmente com a AWS Construct Library e a AWS CDK CLI.<a name="concepts-learn-develop"></a>

 **Desenvolvendo com o AWS CDK**   
O AWS CDK pode ser escrito em qualquer [linguagem de programação compatível](languages.md). Você começa com um [projeto do CDK](projects.md), que contém uma estrutura de pastas e arquivos, incluindo [ativos](assets.md). Dentro do projeto, você cria uma aplicação[ do CDK](apps.md). Dentro do aplicativo, você define uma [pilha](stacks.md), que representa diretamente uma CloudFormation pilha. Dentro da pilha, você define seus AWS recursos e propriedades usando [construções](constructs.md).<a name="concepts-learn-deploy"></a>

 **Implantação com o CDK AWS **   
Você implanta aplicações do CDK em um [ambiente](environments.md) da AWS . Antes da implantação, você deve executar um único [bootstrapping](bootstrapping.md) para preparar seu ambiente.<a name="concepts-learn-more"></a>

 **Saiba mais**   
Para saber mais sobre os principais conceitos do AWS CDK, consulte os tópicos desta seção.

# Linguagens de programação com suporte no AWS CDK
<a name="languages"></a>

O kit de desenvolvimento em nuvem da AWS (CDK da AWS) oferece suporte de primeira classe às linguagens de programação de uso geral a seguir:
+ TypeScript
+ JavaScript
+ Python
+ Java
+ C\$1
+  Go 

Outras linguagens de JVM e .NET CLR também podem ser usadas em teoria, mas não oferecemos suporte oficial no momento.

O AWS CDK foi desenvolvido em uma linguagem, TypeScript. Para oferecer suporte às outras linguagens, o AWS CDK utiliza uma ferramenta chamada [JSII](https://github.com/aws/jsii) para gerar vinculações de linguagem.

Tentamos oferecer as convenções usuais de cada linguagem para tornar o desenvolvimento com o AWS CDK mais natural e intuitivo possível. Por exemplo, distribuímos módulos da Biblioteca de Constructos da AWS usando o repositório padrão da sua linguagem preferida e você os instala usando o gerenciador de pacotes padrão da linguagem. Os métodos e propriedades também são nomeados usando os padrões de nomenclatura recomendados pela sua linguagem.

Veja a seguir alguns exemplos de código:

**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**  
Esses trechos de código servem apenas para fins ilustrativos. Eles estão incompletos e não funcionarão como estão.

A Biblioteca de Constructos da AWS é distribuída usando as ferramentas padrão de gerenciamento de pacotes de cada linguagem, incluindo NPM, PyPi, Maven e NuGet. Também fornecemos uma versão da [Referência de API do AWS CDK](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html) para cada linguagem.

Para ajudar você a usar o AWS CDK em sua linguagem preferida, este guia inclui os seguintes tópicos para linguagens com suporte:
+  [Trabalho com o AWS CDK em TypeScript](work-with-cdk-typescript.md) 
+  [Trabalho com o AWS CDK em JavaScript](work-with-cdk-javascript.md) 
+  [Trabalho com o AWS CDK em Python](work-with-cdk-python.md) 
+  [Trabalho com o AWS CDK em Java](work-with-cdk-java.md) 
+  [Trabalhar com o AWS CDK em C\$1](work-with-cdk-csharp.md) 
+  [Trabalho com o AWS CDK em C\$1](work-with-cdk-go.md) 

O TypeScript foi a primeira linguagem com suporte no AWS CDK, e grande parte do código de exemplo do AWS CDK está escrito em TypeScript. Este guia inclui um tópico específico para mostrar como adaptar o código em TypeScript do AWS CDK para uso com as outras linguagens com suporte. Para obter mais informações, consulte [Comparação do AWS CDK em TypeScript com outras linguagens](work-with.md#work-with-cdk-compare).

# As bibliotecas do AWS CDK
<a name="libraries"></a>

Saiba mais sobre as bibliotecas principais que você usará com o kit de desenvolvimento em nuvem da AWS (CDK da AWS).

## A Biblioteca do AWS CDK
<a name="libraries-cdk"></a>

A Biblioteca do AWS CDK, também conhecida como `aws-cdk-lib`, é a biblioteca principal que você usará para desenvolver aplicações com o AWS CDK. Ela é desenvolvida e mantida pela AWS. Essa biblioteca contém classes 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) e [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). Ela também contém as bibliotecas que você usará para definir sua infraestrutura por meio de constructos.

## Biblioteca de Constructos da AWS
<a name="libraries-construct"></a>

A Biblioteca de Constructos da AWS faz parte da Biblioteca do AWS CDK. Ela contém uma coleção de [constructos](constructs.md) que são desenvolvidos e mantidos pela AWS. Ela é organizada em vários módulos para cada serviço da AWS. Cada módulo inclui constructos que você pode usar para definir seus recursos AWS e propriedades.

## A Biblioteca de Constructos
<a name="libraries-constructs"></a>

A Biblioteca de Constructos, comumente chamada de `constructs`, é uma biblioteca para definir e compor componentes de infraestrutura de nuvem. Ela contém a classe principal [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 o bloco componente do constructo. Essa classe é a classe base fundamental de todos os constructos da Biblioteca de Constructos da AWS. A biblioteca de Constructos é uma biblioteca separada de uso geral usada por outras ferramentas baseadas em constructos, como *CDK para Terraform* e *CDK para Kubernetes*.

## A referência de API do AWS CDK
<a name="libraries-reference"></a>

A [Referência de API do AWS CDK](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html) contém a documentação de referência oficial da Biblioteca de Constructos do AWS CDK, incluindo a Biblioteca de Constructos da AWS e a Biblioteca de Constructos. Uma versão da referência de API é fornecida para cada linguagem de programação com suporte.
+ Para obter a documentação da Biblioteca do AWS CDK (`aws-cdk-lib`), consulte o módulo [aws-cdk-lib](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html).
+ A documentação dos constructos na Biblioteca de Constructos da AWS é organizada pelo serviço da AWS no formato a seguir: `aws-cdk-lib.<service>`. Por exemplo, a documentação da constructo do Amazon Simple Storage Service (Amazon S3) é encontrada no [módulo aws-cdk-lib.aws\$1s3](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3-readme.html).
+ Para a documentação da Biblioteca de Constructos (constructos), consulte o [módulo constructos](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs-readme.html).

### Contribuição à referência de API do AWS CDK
<a name="libraries-reference-contribute"></a>

O AWS CDK tem o código aberto e convidamos você a contribuir. As contribuições da comunidade impactam positivamente e melhoram o AWS CDK. Para obter instruções sobre como contribuir especificamente para a documentação de referência de API do AWS CDK, consulte [Documentação](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md#documentation) no *repositório do GitHub aws-cdk*.

## Saiba mais
<a name="libraries-learn"></a>

Para obter instruções sobre como importar e usar a Biblioteca do CDK, consulte [Trabalho com a Biblioteca do CDK](work-with.md).

# Projetos do AWS CDK
<a name="projects"></a>

Um projeto do kit de desenvolvimento em nuvem da AWS (CDK da AWS) representa os arquivos e pastas que contêm seu código do CDK. O conteúdo variará de acordo com sua linguagem de programação.

É possível criar seu projeto do AWS CDK manualmente ou com o comando `cdk init` da interface da linha de comandos do AWS CDK (CLI do AWS CDK). Neste tópico, nos referiremos à estrutura do projeto e às convenções de nomenclatura de arquivos e pastas criados pela CLI do AWS CDK. É possível personalizar e organizar seus projetos do CDK para atender às necessidades.

**nota**  
A estrutura do projeto criada pela CLI do AWS CDK pode variar entre as versões ao longo do tempo.

## Arquivos e pastas universais
<a name="projects-universal"></a><a name="projects-universal-git"></a>

 `.git`   
Se você tiver o `git` instalado, a CLI do AWS CDK inicializará automaticamente um repositório do Git para seu projeto. O diretório `.git` contém informações sobre o repositório.<a name="projects-universal-gitignore"></a>

 `.gitignore`   
Arquivo de texto usado pelo Git para especificar arquivos e pastas a serem ignorados.<a name="projects-universal-readme"></a>

 `README.md`   
Arquivo de texto que fornece orientações básicas e informações importantes para gerenciar seu projeto do AWS CDK. Modifique esse arquivo conforme necessário para documentar informações importantes sobre seu projeto do CDK.<a name="projects-universal-cdk"></a>

 `cdk.json`   
Arquivo de configuração para o AWS CDK. Esse arquivo fornece instruções à CLI do AWS CDK sobre como executar sua aplicação.

## Arquivos e pastas específicos de linguagem
<a name="projects-specific"></a>

Os arquivos e pastas a seguir são exclusivos para cada linguagem de programação compatível.

**Example**  
Veja a seguir um exemplo de projeto criado no diretório `my-cdk-ts-project` usando o 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`   
Arquivo que especifica quais arquivos e pastas devem ser ignorados ao publicar um pacote no registro `npm`. Esse arquivo é semelhante ao `.gitignore`, mas é específico para pacotes `npm`.  
 `bin/my-cdk-ts-project.ts`   
O *arquivo da aplicação* define sua aplicação CDK. Os projetos do CDK contêm um ou mais arquivos de aplicações. Os arquivos da aplicação são armazenados na pasta `bin`.  
Veja a seguir um exemplo de um arquivo de aplicação básico que define uma aplicação do 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`   
Arquivo de configuração para o Jest. * O Jest* é uma estrutura popular de testes de JavaScript.  
 `lib/my-cdk-ts-project-stack.ts`   
O *arquivo de pilha* define sua pilha do CDK. Na sua pilha, você define os recursos da AWS e as propriedades usando constructos.  
Veja a seguir um exemplo de um arquivo de pilha básico que define uma pilha do 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`   
Pasta comum em projetos Node.js que contêm dependências para seu projeto.  
 `package-lock.json`   
Arquivo de metadados que funcionam com o arquivo `package.json` para gerenciar versões de dependências.  
 `package.json`   
Arquivo de metadados que é comumente usado em projetos Node.js. Esse arquivo contém informações sobre seu projeto do CDK, como nome do projeto, definições de script, dependências e outras informações de importação em nível de projeto.  
 `test/my-cdk-ts-project.test.ts`   
Uma pasta de teste é criada para organizar os testes do seu projeto do CDK. Um arquivo de teste de amostra também é criado.  
É possível escrever testes em TypeScript e usar o Jest para compilar seu código de TypeScript antes de executar testes.  
 `tsconfig.json`   
Arquivo de configuração usado em projetos do TypeScript que especifica as opções do compilador e as configurações do projeto.
Veja a seguir um exemplo de projeto criado no diretório `my-cdk-js-project` usando o 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`   
Arquivo que especifica quais arquivos e pastas devem ser ignorados ao publicar um pacote no registro `npm`. Esse arquivo é semelhante ao `.gitignore`, mas é específico para pacotes `npm`.  
 `bin/my-cdk-js-project.js`   
O *arquivo da aplicação* define sua aplicação CDK. Os projetos do CDK contêm um ou mais arquivos de aplicações. Os arquivos da aplicação são armazenados na pasta `bin`.  
Veja a seguir um exemplo de um arquivo de aplicação básico que define uma aplicação do 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`   
Arquivo de configuração para o Jest. * O Jest* é uma estrutura popular de testes de JavaScript.  
 `lib/my-cdk-js-project-stack.js`   
O *arquivo de pilha* define sua pilha do CDK. Na sua pilha, você define os recursos da AWS e as propriedades usando constructos.  
Veja a seguir um exemplo de um arquivo de pilha básico que define uma pilha do 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`   
Pasta comum em projetos Node.js que contêm dependências para seu projeto.  
 `package-lock.json`   
Arquivo de metadados que funcionam com o arquivo `package.json` para gerenciar versões de dependências.  
 `package.json`   
Arquivo de metadados que é comumente usado em projetos Node.js. Esse arquivo contém informações sobre seu projeto do CDK, como nome do projeto, definições de script, dependências e outras informações de importação em nível de projeto.  
 `test/my-cdk-js-project.test.js`   
Uma pasta de teste é criada para organizar os testes do seu projeto do CDK. Um arquivo de teste de amostra também é criado.  
É possível escrever testes em JavaScript e usar o Jest para compilar seu código de JavaScript antes de executar testes.
Veja a seguir um exemplo de projeto criado no diretório `my-cdk-py-project` usando o 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`   
A CLI do CDK cria automaticamente um ambiente virtual para seu projeto. O diretório `.venv` se refere a esse ambiente virtual.  
 `app.py`   
O *arquivo da aplicação* define sua aplicação CDK. Os projetos do CDK contêm um ou mais arquivos de aplicações.  
Veja a seguir um exemplo de um arquivo de aplicação básico que define uma aplicação do 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`   
O diretório que contém seus *arquivos de pilha*. A CLI do CDK cria o seguinte aqui:  
+ \$1\$1init\$1\$1.py: Um arquivo de definição de pacote Python vazio.
+  `my_cdk_py_project`: arquivo que define sua pilha do CDK. Em seguida, você define recursos da AWS e propriedades na pilha usando constructos.
Este é um exemplo de um arquivo de pilha:  

```
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`   
Arquivo semelhante ao `requirements.txt`, mas usado para gerenciar dependências especificamente para fins de desenvolvimento em vez de produção.  
 `requirements.txt`   
Arquivo comum usado em projetos do Python para especificar e gerenciar dependências do projeto.  
 `source.bat`   
O arquivo de lote para o Windows que é usado para configurar o ambiente virtual do Python.  
 `tests`   
Diretório que contém testes para seu projeto do CDK.  
A seguir, veja um exemplo de um teste de unidade:  

```
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
 })
```
Veja a seguir um exemplo de projeto criado no diretório `my-cdk-java-project` usando o comando `cdk init --language java`:  

```
my-cdk-java-project
├── .git
├── .gitignore
├── README.md
├── cdk.json
├── pom.xml
└── src
    ├── main
    └── test
```  
 `pom.xml`   
Arquivo que contém informações de configuração e metadados sobre seu projeto do CDK. Este arquivo faz parte do Maven.  
 `src/main`   
Diretório contenda sua aplicação** e arquivos de *pilha*.  
Este é um exemplo de um arquivo de aplicação:  

```
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();
 }
}
```
Este é um exemplo de um arquivo de pilha:  

```
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`   
Diretório contendo seus arquivos de teste. Veja um exemplo a seguir:  

```
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);
  }});
 }
}
```
Veja a seguir um exemplo de projeto criado no diretório `my-cdk-csharp-project` usando o comando `cdk init --language csharp`:  

```
my-cdk-csharp-project
├── .git
├── .gitignore
├── README.md
├── cdk.json
└── src
    ├── MyCdkCsharpProject
    └── MyCdkCsharpProject.sln
```  
 `src/MyCdkCsharpProject`   
Diretório contenda sua aplicação** e arquivos de *pilha*.  
Este é um exemplo de um arquivo de aplicação:  

```
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();
  }
 }
}
```
Este é um exemplo de um arquivo de pilha:  

```
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
  }
 }
}
```
Esse diretório também contém o seguinte:  
  
+  `GlobalSuppressions.cs` — Arquivo usado para suprimir avisos ou erros específicos do compilador em seu projeto.
+  `.csproj`: arquivo baseado em XML usado para definir configurações de projeto, dependências e configurações de compilação. ---  
 `src/MyCdkCsharpProject.sln`   
 Microsoft Visual Studio Solution File usado para organizar e gerenciar projetos relacionados.
Veja a seguir um exemplo de projeto criado no diretório `my-cdk-go-project` usando o 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`   
Arquivo que contém informações do módulo e é usado para gerenciar dependências e versionamento do seu projeto Go.  
 `my-cdk-go-project.go`   
Arquivo que define sua aplicação e suas pilhas do CDK.  
Veja um exemplo a seguir:  

```
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`   
Arquivo que define um teste de amostra.  
Veja um exemplo a seguir:  

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

# Aplicações do CDK da AWS
<a name="apps"></a>

A aplicação ou *app* do kit de desenvolvimento em nuvem da AWS (CDK da AWS) é uma coleção de uma ou mais [pilhas](stacks.md) do CDK. As pilhas são uma coleção de um ou mais [constructos](constructs.md) que definem os recursos e propriedades da AWS. Portanto, o agrupamento geral de suas pilhas e constructos é conhecido coma sua aplicação do CDK.

## Como criar uma aplicação do CDK
<a name="apps-define"></a>

Você cria uma aplicação definindo uma instância da aplicação no arquivo do seu [projeto](projects.md). Para fazer isso, você importa e usa o constructo [App](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html) da Biblioteca de Constructos da AWS. O constructo `App` não requer nenhum argumento de inicialização. É o único constructo que pode ser usado como raiz.

As classes ` [App](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html) ` e ` [Stack](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html) ` da Biblioteca de Constructos AWS são constructos exclusivos. Em comparação com outros constructos, eles não configuram recursos da AWS sozinhos. Em vez disso, eles usados para fornecer contexto para seus outros constructos. Todos os constructos que representam recursos da AWS devem ser definidos, direta ou indiretamente, dentro do escopo de um constructo da `Stack`. Os constructos da `Stack` são definidos dentro do escopo do constructo de um `App`.

As aplicações são então sintetizadas para criar modelos do AWS CloudFormation para suas pilhas. Veja um exemplo a seguir:

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

As pilhas em uma única aplicação podem se referir facilmente aos recursos e propriedades umas das outras. O CDK da AWS infere dependências entre as pilhas para que elas possam ser implantadas na ordem correta. É possível implantar qualquer uma ou todas as pilhas em uma aplicação com um único comando `cdk deploy`.

## A árvore de constructos
<a name="apps-tree"></a>

Os constructos são definidos dentro de outros constructos usando o argumento `scope` que é passado para cada constructo, com a classe `App` como raiz. Dessa forma, uma aplicação do CDK da AWS define uma hierarquia de constructos, conhecida como *árvore de constructos*.

A raiz dessa árvore é sua aplicação, que é uma instância da classe `App`. Dentro da aplicação, você instancia uma ou mais pilhas. Nas pilhas, você instancia constructos, podendo eles mesmos instanciar recursos ou outros constructos, e assim por diante na árvore.

Os constructos são *sempre* definidos explicitamente dentro do escopo de outro constructo, o que cria relações entre os constructos. Quase sempre, você deve passar `this` (no Python, `self`) como escopo, indicando que o novo constructo é secundário do constructo atual. O padrão pretendido é que você derive seu constructo 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) e, em seguida, instancie os constructos que ele usa em seu construtor.

Passar o escopo explicitamente permite que cada constructo se adicione à árvore, com esse comportamento inteiramente contido na [classe de base `Construct`](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html). Isso funciona da mesma forma em todos as linguagens com suporte no CDK da AWS e não requer personalização adicional.

**Importante**  
Tecnicamente, é possível passar algum escopo além de `this` ao instanciar um constructo. É possível adicionar constructos em qualquer lugar da árvore ou até mesmo em outra pilha na mesma aplicação. Por exemplo, você pode escrever uma função mixin-style que adiciona constructos a um escopo passado como argumento. A dificuldade prática aqui é que você não pode garantir facilmente que os IDs escolhidos para seus constructos sejam exclusivos dentro do escopo de outra pessoa. Essa prática também torna seu código mais difícil de entender, manter e reutilizar. Portanto, convém usar a estrutura geral da árvore de constructos.

O CDK da AWS usa os IDs de todos os constructos no caminho da raiz da árvore até cada constructo secundário para gerar os IDs exclusivos exigidos pelo AWS CloudFormation. Essa abordagem significa que os IDs de constructo só precisam ser exclusivos em seu escopo, e não em toda a pilha, como no AWS CloudFormation nativo. No entanto, se você mover um constructo para um escopo diferente, o ID exclusivo da pilha gerado será alterado, e o AWS CloudFormation não o considerará como o mesmo recurso.

A árvore de constructos é separada dos constructos que você define no seu código do CDK da AWS. No entanto, ela é acessível por meio de qualquer atributo `node` do constructo, o que é uma referência ao nó que representa esse constructo na árvore. Cada nó é uma instância de [https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Node.html](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Node.html), cujos atributos fornecem acesso à raiz da árvore e aos escopos principais e secundários do nó.

1.  `node.children`: constructos secundários diretos do constructo.

1.  `node.id`: o identificador do constructo dentro de seu escopo.

1.  `node.path`: o caminho completo do constructo, incluindo os IDs de todos os seus constructos principais.

1.  `node.root`: a raiz da árvore de constructos (a aplicação).

1.  `node.scope`: o escopo (principal) do constructo ou indefinido se o nó for a raiz.

1.  `node.scopes`: todos os constructos principais do constructo, até a raiz.

1.  `node.uniqueId`: o identificador alfanumérico exclusivo para esse constructo na árvore (por padrão, gerado a partir de `node.path` e um hash).

A árvore de constructos define uma ordem implícita na qual os constructos são sintetizados em recursos no modelo final do AWS CloudFormation. Onde um recurso deve ser criado antes do outro, o AWS CloudFormation ou a Biblioteca de Constructos da AWS geralmente infere a dependência. Em seguida, eles garantem que os recursos sejam criados na ordem correta.

Você também pode adicionar uma dependência explícita entre dois nós usando `node.addDependency()`. Para obter mais informações, consulte [Dependências](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html#dependencies) na *Referência de API do CDK da AWS*.

O CDK da AWS fornece uma maneira simples de visitar todos os nós na árvore de constructos e realizar uma operação em cada um. Para obter mais informações, consulte [Aspectos e o CDK da AWS](aspects.md).

# Introdução às pilhas de AWS CDK
<a name="stacks"></a>

Uma pilha de AWS CDK é a menor unidade única de implantação. Ela representa uma coleção de AWS recursos que você define usando construções de CDK. Quando você implanta aplicativos CDK, os recursos em uma pilha de CDK são implantados juntos como uma pilha. AWS CloudFormation Para saber mais sobre AWS CloudFormation pilhas, consulte [Gerenciamento de AWS recursos como uma única unidade com AWS CloudFormation pilhas no Guia](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacks.html) do * AWS CloudFormation usuário*.

Você define uma pilha estendendo ou herdando do 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). O exemplo a seguir é um padrão comum para definir uma pilha do CDK em um arquivo separado, conhecido como *arquivo de pilha*. Aqui, estendemos ou herdamos a classe de `Stack` e definimos um construtor que aceita `scope`, `id` e `props`. Em seguida, invocamos o construtor da classe de base da `Stack` usando `super` com o recebido `scope`, `id` e `props`:

**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)
}

//...
```

O exemplo anterior definiu apenas uma pilha. Para criar a pilha, ela deve ser instanciada dentro do contexto da sua aplicação do CDK. Um padrão comum é definir sua aplicação do CDK e inicializar sua pilha em um arquivo separado, conhecido como *arquivo de aplicação*.

Veja a seguir um exemplo de criação de uma pilha do CDK chamada `MyCdkStack`. Aqui, a aplicação do CDK é criado e `MyCdkStack` é instanciado no contexto da aplicação:

**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', {
});
```
Localizado em `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)
}

// ...
```

O exemplo a seguir cria uma aplicação do CDK que contém duas pilhas:

**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)
}

// ...
```

## Sobre a API da pilha
<a name="stack-api"></a>

O 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) fornece uma API avançada, incluindo o seguinte:
+  `Stack.of(construct)`: um método estático que retorna a **pilha** na qual um constructo é definido. Isso é útil se você precisar interagir com uma pilha de dentro de um constructo reutilizável. A chamada falhará se uma pilha não puder ser encontrada no escopo.
+  `stack.stackName` (Python: `stack_name`): retorna o nome físico da pilha. Conforme mencionado anteriormente, todas as pilhas de AWS CDK têm um nome físico que o AWS CDK pode resolver durante a síntese.
+  `stack.region`e `stack.account` — Retorne a AWS região e a conta, respectivamente, nas quais essa pilha será implantada. Essas propriedades retornam uma das opções a seguir:
  + A conta ou região especificada explicitamente quando a pilha foi definida
  + Um token codificado em string que segue os AWS CloudFormation pseudoparâmetros da conta e da região para indicar que essa pilha é independente do ambiente

    Para obter informações sobre como os ambientes são determinados para pilhas, consulte [Ambientes para o AWS CDK](environments.md).
+  `stack.addDependency(stack)` (Python: `stack.add_dependency(stack)`): pode ser usado para definir explicitamente a ordem de dependência entre duas pilhas. Essa ordem é respeitada pelo comando `cdk deploy` ao implantar várias pilhas ao mesmo tempo.
+  `stack.tags`— Retorna um [TagManager](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagManager.html)que você pode usar para adicionar ou remover tags no nível da pilha. Esse gerenciador de tags marca todos os recursos da pilha e também marca a própria pilha quando ela é criada por meio dela. AWS CloudFormation
+  `stack.partition`, `stack.urlSuffix` (Python:`url_suffix`), (`stack.stackId`Python:) e (`stack.notificationArn`Python: `stack_id``notification_arn`) — Retorna tokens que se resolvem nos respectivos AWS CloudFormation pseudoparâmetros, como. `{ "Ref": "AWS::Partition" }` Esses tokens são associados ao objeto de pilha específico para que a estrutura do AWS CDK possa identificar referências entre pilhas.
+  `stack.availabilityZones` (Python: `availability_zones`): retorna o conjunto de zonas de disponibilidade disponíveis no ambiente em que essa pilha é implantada. Para pilhas independentes do ambiente, sempre retorna uma matriz com duas zonas de disponibilidade. Para pilhas específicas do ambiente, o AWS CDK consulta o ambiente e retorna o conjunto exato de zonas de disponibilidade disponíveis na região que você especificou.
+  `stack.parseArn(arn)`e `stack.formatArn(comps)` (Python:`parse_arn`,`format_arn`) — Pode ser usado para trabalhar com Amazon Resource Names ()ARNs.
+  `stack.toJsonString(obj)`(Python:`to_json_string`) — Pode ser usado para formatar um objeto arbitrário como uma string JSON que pode ser incorporada em um modelo. AWS CloudFormation O objeto pode incluir tokens, atributos e referências, que só são resolvidos durante a implantação.
+  `stack.templateOptions`(Python:`template_options`) — Use para especificar opções de AWS CloudFormation modelo, como Transformação, Descrição e Metadados, para sua pilha.

## Trabalhar com pilhas do
<a name="stacks-work"></a>

[As pilhas são implantadas como uma AWS CloudFormation pilha em um ambiente. AWS](environments.md) O ambiente abrange uma AWS conta e uma AWS região específicas.

Quando você executa o comando `cdk synth` para uma aplicação com várias pilhas, o conjunto de nuvem inclui um modelo separado para cada instância da pilha. Mesmo que as duas pilhas sejam instâncias da mesma classe, o AWS CDK as emite como dois modelos individuais.

É possível sintetizar cada modelo especificando o nome da pilha no comando `cdk synth`. O exemplo a seguir sintetiza o modelo de `stack1`:

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

[Essa abordagem é conceitualmente diferente de como os AWS CloudFormation modelos são normalmente usados, em que um modelo pode ser implantado várias vezes e parametrizado por meio de parâmetros.AWS CloudFormation ](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html) Embora AWS CloudFormation os parâmetros possam ser definidos no AWS CDK, eles geralmente são desencorajados porque AWS CloudFormation os parâmetros são resolvidos somente durante a implantação. Isso significa que você não pode determinar o valor deles no seu código.

Por exemplo, para incluir condicionalmente um recurso em sua aplicação com base em um valor de parâmetro, você deve configurar uma [condição do AWS CloudFormation ](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html) e marcar o recurso com ela. O AWS CDK adota uma abordagem em que modelos concretos são resolvidos no momento da síntese. Portanto, você pode usar uma instrução `if` para verificar o valor e determinar se um recurso deve ser definido ou se algum comportamento deve ser aplicado.

**nota**  
O AWS CDK fornece o máximo de resolução possível durante o tempo de síntese para permitir o uso natural e idiomático de sua linguagem de programação.

Como qualquer outro constructo, as pilhas podem ser compostas em grupos. O código a seguir mostra um exemplo de um serviço que consiste em três pilhas: um ambiente de gerenciamento, um plano de dados e pilhas de monitoramento. O constructo do serviço é definido duas vezes: uma para o ambiente beta e outra para o ambiente de produção.

**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)
}

// ...
```
Esse aplicativo AWS CDK eventualmente consiste em seis pilhas, três para cada ambiente:  

```
$ cdk ls

betacpDA8372D3
betadataE23DB2BA
betamon632BD457
prodcp187264CE
proddataF7378CE5
prodmon631A1083
```

Os nomes físicos das AWS CloudFormation pilhas são determinados automaticamente pelo AWS CDK com base no caminho de construção da pilha na árvore. Por padrão, o nome de uma pilha é derivado do ID de constructo do objeto da `Stack`. No entanto, você pode especificar um nome explícito usando a prop `stackName` (no Python, `stack_name`), da seguinte maneira.

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

### Trabalhar com pilhas aninhadas
<a name="stack-nesting"></a>

Uma *pilha aninhada* é uma pilha do CDK que você cria dentro de outra pilha, conhecida como pilha principal. Você cria pilhas aninhadas usando o 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).

Ao usar pilhas aninhadas, você pode organizar recursos em várias pilhas. As pilhas aninhadas também oferecem uma maneira de contornar o limite de AWS CloudFormation 500 recursos para pilhas. Uma pilha aninhada conta como apenas um recurso na pilha que a contém. No entanto, ele pode conter até 500 recursos, incluindo pilhas aninhadas adicionais.

O escopo de uma pilha aninhada deve ser um constructo a `Stack` ou `NestedStack`. A pilha aninhada não precisa ser declarada lexicamente dentro de sua pilha principal. É necessário apenas passar a pilha principal como o primeiro parâmetro (`scope`) ao instanciar a pilha aninhada. Além dessa restrição, definir constructos em uma pilha aninhada funciona exatamente da mesma forma que em uma pilha comum.

No momento da síntese, a pilha aninhada é sintetizada em seu próprio AWS CloudFormation modelo, que é carregado no bucket de preparação do AWS CDK na implantação. As pilhas aninhadas são vinculadas à pilha principal e não são tratadas como artefatos de implantação independentes. Eles não estão listados por `cdk list` e não podem ser implantados por `cdk deploy`.

[As referências entre pilhas principais e pilhas aninhadas são traduzidas automaticamente em parâmetros de pilha e saídas nos AWS CloudFormation modelos gerados, como acontece com qualquer referência de pilha cruzada.](resources.md#resource-stack)

**Atenção**  
As alterações na postura de segurança não são exibidas antes da implantação das pilhas aninhadas. Essas informações são exibidas somente para pilhas de nível superior.

# Introdução aos estágios do AWS CDK
<a name="stages"></a>

Um *estágio* do kit de desenvolvimento em nuvem da AWS (CDK da AWS) representa um grupo de uma ou mais pilhas do CDK configuradas para serem implantação em conjunto. Use estágios para implantar o mesmo agrupamento de pilhas em vários ambientes, como desenvolvimento, teste e produção.

Para configurar um estágio do CDK, importe e use o 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).

Este é um exemplo básico que define um estágio do CDK chamado `MyAppStage`. Adicionamos duas pilhas do CDK, chamadas `AppStack` e `DatabaseStack`, ao nosso estágio. Neste exemplo, `AppStack` contém recursos da aplicação e `DatabaseStack` contém recursos do banco de dados. Em seguida, criamos duas instâncias de `MyAppStage`, para ambientes de desenvolvimento e produção:

**Example**  
Em `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
  }
}
```
Em `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
  }
}
```
Em `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');
  }
}
```
Em `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'
  }
});
```
Em `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 }
```
Em `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 }
```
Em `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 };
```
Em `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',
  },
});
```
Em `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
```
Em `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
```
Em `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")
```
Em `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()
```
Em `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
    }
}
```
Em `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
    }
}
```
Em `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");
    }
}
```
Em `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();
    }
}
```
Em `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
        }
    }
}
```
Em `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
        }
    }
}
```
Em `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");
        }
    }
}
```
Em `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();
        }
    }
}
```
Em `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
}
```

Quando executamos `cdk synth`, seus conjuntos de nuvem são criados no `cdk.out`. Esses dois conjuntos de nuvem contêm o modelo sintetizado do AWS CloudFormation e os ativos para cada estágio. A seguir está um trecho do nosso diretório de projetos:

**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
```
Quando listamos nossas pilhas com `cdk list`, vemos um total de quatro pilhas:  

```
$ cdk list
Dev/AppStack (Dev-AppStack)
Dev/DatabaseStack (Dev-DatabaseStack)
Prod/AppStack (Prod-AppStack)
Prod/DatabaseStack (Prod-DatabaseStack)
```
Para implantar um estágio específico, executamos o `cdk deploy` e fornecemos as pilhas para implantação. Veja a seguir um exemplo que usa o curinga `/*` para implantar as duas pilhas em nosso estágio `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 Construções CDK
<a name="constructs"></a>

As construções são os componentes básicos dos aplicativos do AWS Cloud Development Kit (AWS CDK). Uma construção é um componente em seu aplicativo que representa um ou mais AWS CloudFormation recursos e sua configuração. Você compila sua aplicação, parte por parte, importando e configurando constructos.

## Importar e usar constructos
<a name="constructs-import"></a>

Os constructos são classes que você importa para suas aplicações do CDK da [Biblioteca de Constructos da AWS](libraries.md#libraries-construct). Você também pode criar e distribuir seus próprios constructos ou usar constructos criados por desenvolvedores terceirizados.

Os constructos fazem parte do Construct Programming Model (CPM – Modelo de programação de constructo). Eles estão disponíveis para uso com outras ferramentas, como CDK for Terraform (CDKtf), CDK for Kubernetes (CDK8s) e. Projen

Vários terceiros também publicaram construções compatíveis com o AWS CDK. Visite o [Construct Hub](https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&offset=0) para explorar o ecossistema de parceiros do AWS CDK Construct.

## Níveis de constructo
<a name="constructs-lib-levels"></a>

As construções da AWS Construct Library são categorizadas em três níveis. Cada nível oferece um nível crescente de abstração. Quanto maior a abstração, mais fácil de configurar, exigindo menos experiência. Quanto menor a abstração, mais personalização está disponível, exigindo mais experiência.<a name="constructs-lib-levels-one"></a>

 **Construções de nível 1 (L1)**   
Os constructos L1, também conhecidos como *recursos do CFN*, são os constructos de nível mais baixo e não oferecem abstração. Cada construção L1 é mapeada diretamente para um único AWS CloudFormation recurso. Com construções L1, você importa uma construção que representa um recurso específico AWS CloudFormation . Em seguida, você define as propriedades do recurso em sua instância de constructo.  
As construções L1 são ótimas para usar quando você está familiarizado AWS CloudFormation e precisa de controle total sobre a definição das propriedades de seus AWS recursos.  
Na AWS Construct Library, as construções L1 são nomeadas começando com`Cfn`, seguidas por um identificador para o AWS CloudFormation recurso que elas representam. Por exemplo, a [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)construção é uma construção L1 que representa um [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 recurso.  
Os constructos L1 são gerados a partir da especificação do [recurso do AWS CloudFormation ](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html). Se um recurso existir em AWS CloudFormation, ele estará disponível no AWS CDK como uma construção L1. Novos recursos ou propriedades podem levar até uma semana para serem disponibilizados na AWS Construct Library. Para obter mais informações, consulte a [referência de tipos de AWS recursos e propriedades](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html) no *Guia AWS CloudFormation do usuário*.<a name="constructs-lib-levels-two"></a>

 **Construções de nível 2 (L2)**   
Os constructos L2, também conhecidas como constructos *curados*, são cuidadosamente desenvolvidos pela equipe do CDK e geralmente são o tipo de constructo mais amplamente usado. As construções L2 são mapeadas diretamente para AWS CloudFormation recursos individuais, semelhantes às construções L1. Em comparação com os constructos L1, os constructos L2 fornecem uma abstração de alto nível por meio de uma API intuitiva baseada em intenção. Os constructos L2 incluem configurações de propriedades padrão sensatas, políticas de segurança de práticas recomendadas e geram muito código clichê e lógica de colagem para você.  
Os constructos L2 também fornecem métodos auxiliares para a maioria dos recursos que simplificam e agilizam a definição de propriedades, permissões, interações baseadas em eventos entre recursos e muito mais. Muitos desses recursos também estão disponíveis como blocos de construção independentes chamados [Mixins](mixins.md), que podem ser aplicados às construções L1 e L2 usando o método. `.with()`  
A classe [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) é um exemplo de um constructo L2 para um recurso de bucket do Amazon Simple Storage Service (Amazon S3).  
A AWS Construct Library contém construções L2 que são designadas como estáveis e prontas para uso em produção. Para constructos L2 em desenvolvimento, eles são designados como experimentais e oferecidos em um módulo separado.<a name="constructs-lib-levels-three"></a>

 **Construções de nível 3 (L3)**   
Os constructos L3, também conhecidos como *padrões*, são o nível mais alto de abstração. Cada constructo L3 pode conter uma coleção de recursos que são configurados para trabalhar juntos para realizar uma tarefa ou serviço específico em sua aplicação. As construções L3 são usadas para criar AWS arquiteturas inteiras para casos de uso específicos em seu aplicativo.  
Para fornecer projetos de sistema completos ou partes substanciais de um sistema maior, os constructos L3 oferecem configurações de propriedades padrão opinativas. Eles são construídos em torno de uma abordagem específica para resolver um problema e fornecer uma solução. Com constructos L3, você pode criar e configurar vários recursos rapidamente, com a menor quantidade de entrada e código.  
A [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)classe é um exemplo de uma construção L3 que representa um serviço AWS Fargate executado em um cluster do Amazon Elastic Container Service (Amazon ECS) e liderado por um balanceador de carga de aplicativos.  
Semelhantes às construções L2, as construções L3 que estão prontas para uso em produção estão incluídas na Construct Library. AWS Os que estão em desenvolvimento são oferecidos em módulos separados.

## Definição de constructos
<a name="constructs-define"></a>

### Composição
<a name="constructs-composition"></a>

 A *composição* é o padrão chave para definir abstrações de alto nível por meio de constructos. Um constructo de alto nível pode ser composto a partir de qualquer número de constructos de nível inferior. De uma perspectiva de baixo para cima, você usa construções para organizar os AWS recursos individuais que deseja implantar. Você usa quaisquer abstrações que sejam convenientes para seu propósito, com quantos níveis precisar.

Com a composição, você define componentes reutilizáveis e os compartilha como qualquer outro código. Por exemplo, uma equipe pode definir um constructo que implemente as práticas recomendadas da empresa em uma tabela do Amazon DynamoDB, incluindo backup, replicação global, escalabilidade automática e monitoramento. A equipe pode compartilhar o constructo internamente com outras equipes ou publicamente.

As equipes podem usar constructos como qualquer outro pacote de biblioteca. Quando a biblioteca é atualizada, os desenvolvedores têm acesso às melhorias e correções de erros da nova versão, de forma semelhante a qualquer outra biblioteca de código.

### Inicialização
<a name="constructs-init"></a>

As estruturas são implementadas em classes que estendem a classe base no [https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html). Você define um constructo instanciando a classe. Todas as estruturas usam três parâmetros ao serem inicializadas:
+  **escopo**: o pai ou proprietário do constructo. Pode ser uma pilha ou outro constructo. O escopo determina o lugar do constructo na [árvore de constructos](apps.md#apps-tree). Em geral, é necessário passar `this` (`self` no Python), que representa o objeto atual, para o escopo.
+  **id**: um [identificador](identifiers.md) que deve ser exclusivo dentro desse escopo. O identificador serve como um namespace para tudo o que está definido no constructo. Ele é usado para gerar identificadores exclusivos, como [nomes de recursos](resources.md#resources-physical-names) e AWS CloudFormation lógicos IDs.

  Os identificadores só precisam ser exclusivos dentro de um escopo. Ele permite que você instancie e reutilize constructos sem se preocupar com os constructos e identificadores que eles possam conter, além de permitir a composição de constructos em abstrações de alto nível. Além disso, os escopos possibilitam a referência a grupos de constructos de uma só vez. Os exemplos incluem a [marcação](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tag.html) ou a especificação de onde os constructos serão implantados.
+  **props**: um conjunto de propriedades ou argumentos de palavras-chave, dependendo da linguagem, que definem a configuração inicial do constructo. Constructos de nível superior fornecem mais padrões e, se todos os elementos prop forem opcionais, será possível omitir completamente o parâmetro props.

### Configuração
<a name="constructs-config"></a>

A maioria das construções aceita `props` como terceiro argumento (ou, em Python, argumentos de palavra-chave) name/value uma coleção que define a configuração da construção. O exemplo a seguir define um bucket com criptografia do AWS Key Management Service (AWS KMS) e hospedagem estática de sites ativados. Como não especifica explicitamente uma chave de criptografia, o constructo do `Bucket` define uma nova `kms.Key` e a associa ao 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"),
	})
```

### Interagir com constructos
<a name="constructs-interact"></a>

Os constructos são implementados em classes que estendem a classe de [constructo](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html) de base. Depois de instanciar um constructo, o objeto do constructo expõe um conjunto de métodos e propriedades que permitem que você interaja com o constructo e o transmita como referência para outras partes do sistema.

A estrutura AWS CDK não impõe nenhuma restrição às APIs construções. Os autores podem definir qualquer API que quiserem. No entanto, as AWS construções incluídas na AWS Construct Library, por exemplo`s3.Bucket`, seguem diretrizes e padrões comuns. Isso proporciona uma experiência consistente em todos os AWS recursos.

A maioria das AWS construções tem um conjunto de métodos de [concessão](permissions.md#permissions-grants) que você pode usar para conceder permissões de AWS Identity and Access Management (IAM) sobre essa construção a um diretor. O exemplo a seguir concede a permissão `data-science` ao grupo do IAM para ler a partir do bucket `raw-data` do 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)
```

Outro padrão comum é que AWS as construções definam um dos atributos do recurso a partir de dados fornecidos em outro lugar. Os atributos podem incluir nomes de recursos da Amazon (ARNs), nomes ou URLs.

O código a seguir define uma função AWS Lambda e a associa a uma fila do Amazon Simple Queue Service (Amazon SQS) por meio da URL da fila em uma variável de ambiente.

**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 obter informações sobre os padrões de API mais comuns na AWS Construct Library, consulte [Resources and the AWS CDK](resources.md).

### Adicione recursos com o Mixins
<a name="constructs-mixins"></a>

Os mixins são recursos combináveis que você pode aplicar a qualquer construção usando o método. `.with()` Os mixins permitem que você adicione funcionalidade às construções L1 e L2 sem precisar usar uma construção diferente ou escrever código de baixo nível.

Por exemplo, você pode habilitar o controle de versão e bloquear o acesso público em um bucket do Amazon S3, seja ele L1 ou `CfnBucket` 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())
```

Os mixins estão disponíveis por meio do `mixins` namespace de cada módulo de serviço (por exemplo,). `s3.mixins` Cada mixin tem como alvo um tipo de recurso específico e tem o nome desse recurso. Quando você aplica um mixin a uma construção L2, ele se aplica automaticamente ao recurso L1 subjacente.

Para obter mais informações sobre Mixins, consulte [Mixins](mixins.md).

### O constructo da aplicação e da pilha
<a name="constructs-apps-stacks"></a>

As [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)classes [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)e da AWS Construct Library são construções exclusivas. Em comparação com outras construções, elas não configuram AWS recursos sozinhas. Em vez disso, eles usados para fornecer contexto para seus outros constructos. Todas as construções que representam AWS recursos devem ser definidas, direta ou indiretamente, dentro do escopo de uma `Stack` construção. `Stack`construções são definidas dentro do escopo de uma `App` construção.

Para saber mais sobre as aplicações do CDK, consulte [Aplicações do AWS CDK](apps.md). Para saber mais sobre pilhas de CDK, consulte [Introdução às pilhas de AWS CDK](stacks.md).

O exemplo a seguir define uma aplicação com uma única pilha. Dentro da pilha, um constructo L2 é usado para configurar um recurso de bucket do 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")
```
Pilha definida no arquivo `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();
    }
}
```
Aplicação definida no arquivo `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
}
```

## Trabalhar com constructos
<a name="constructs-work"></a>

### Trabalhar com constructos L1
<a name="constructs-l1-using"></a>

L1 constrói mapas diretamente para recursos individuais AWS CloudFormation . Você mesmo deve fornecer a configuração necessária para o recurso.

Neste exemplo, criamos um objeto de `bucket` usando o 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"),
	})
```

Propriedades de constructos que não sejam simples booleanos, strings, números ou contêineres são tratadas de forma diferente nas linguagens com suporte.

**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"]
    }]
  }
});
```
Em Python, essas propriedades são representadas por tipos definidos como classes internas do constructo L1. Por exemplo, a propriedade opcional `cors_configuration` de um `CfnBucket` requer um wrapper do tipo `CfnBucket.CorsConfigurationProperty`. Aqui estamos definindo `cors_configuration` em uma instância `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"]
        )]
    )
)
```
Em Java, essas propriedades são representadas por tipos definidos como classes internas do constructo L1. Por exemplo, a propriedade opcional `corsConfiguration` de um `CfnBucket` requer um wrapper do tipo `CfnBucket.CorsConfigurationProperty`. Aqui estamos definindo `corsConfiguration` em uma instância `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();
```
Em C\$1, essas propriedades são representadas por tipos definidos como classes internas do constructo L1. Por exemplo, a propriedade opcional `CorsConfiguration` de um `CfnBucket` requer um wrapper do tipo `CfnBucket.CorsConfigurationProperty`. Aqui estamos definindo `CorsConfiguration` em uma instância `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" },
            }
        }
    }
});
```
Em Go, esses tipos são nomeados usando o nome do constructo L1, um sublinhado e o nome da propriedade. Por exemplo, a propriedade opcional `CorsConfiguration` de um `CfnBucket` requer um wrapper do tipo `CfnBucket_CorsConfigurationProperty`. Aqui estamos definindo `CorsConfiguration` em uma instância `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**  
Você não pode usar tipos de propriedade L2 com constructos L1 ou vice-versa. Ao trabalhar com constructos L1, sempre use os tipos definidos para o constructo L1 que você estiver usando. Não use tipos de outros constructos L1 (alguns podem ter o mesmo nome, mas não são do mesmo tipo).  
Algumas de nossas referências de API específicas da linguagem atualmente têm erros nos caminhos para os tipos de propriedades L1 ou não documentam essas classes. Esperamos corrigir isso em breve. Enquanto isso, lembre-se de que esses tipos são sempre classes internas do constructo L1 com o qual são usados.

#### Referenciando recursos de outras construções
<a name="constructs-resource-references"></a>

Ao configurar propriedades de construção que fazem referência a outros recursos da AWS, você tem duas opções equivalentes:
+  **Referências de string**: passe valores de string explícitos ARNs, como nomes ou outros identificadores de recursos
+  **Referências de objetos**: passe objetos de construção diretamente. Isso evita a necessidade de determinar qual tipo de identificador uma propriedade espera — o CDK trata disso para você.

##### Usando referências de string
<a name="_using_string_references"></a>

Você sempre pode transmitir valores de string explícitos ARNs, como nomes ou outros identificadores de recursos. Essa abordagem funciona para todas as propriedades e é necessária para propriedades aninhadas em objetos complexos.

O exemplo a seguir cria uma função Lambda usando uma construção L1 (`CfnFunction`) com uma função definida usando uma construção L2 (). `Role` O ARN da função é passado para a `role` propriedade:

**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!'),
		  };
		};
		`),
	},
})
```

##### Usando referências de objetos
<a name="_using_object_references"></a>

Para propriedades selecionadas, você pode passar objetos de construção diretamente em vez de extrair seus atributos manualmente. Support para referências de objetos varia de acordo com a propriedade e pode se expandir com o tempo à medida que novas propriedades são adicionadas.

Quando você passa uma referência de objeto na construção`props`, o CDK a resolve para o valor de string apropriado (como um ARN, nome ou outro identificador). Se você acessar posteriormente a propriedade correspondente na instância de construção, verá esse valor de string resolvido, não a referência original do objeto.

As referências a objetos funcionam somente para propriedades de nível superior de construções. Propriedades aninhadas em objetos complexos exigem valores de string explícitos.

O exemplo a seguir mostra a mesma função Lambda, mas usando o objeto de função em vez da string ARN da função:

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

### Trabalhar com constructos L2
<a name="constructs-using"></a>

No exemplo a seguir, definimos um bucket do Amazon S3 criando um objeto a partir do constructo L2 do [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`não é o nome do bucket que AWS CloudFormation cria. É um identificador lógico fornecido ao novo constructo dentro do contexto da sua aplicação do CDK. O valor [PhysicalName](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Resource.html#physicalname) será usado para nomear o AWS CloudFormation recurso.

## Trabalhar com constructos de terceiros
<a name="constructs-work-third"></a>

 O [Construct Hub](https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&sort=downloadsDesc&offset=0) é um recurso para ajudá-lo a descobrir construções adicionais de AWS terceiros e da comunidade CDK de código aberto.

### Escrever seus próprios constructos
<a name="constructs-author"></a>

Além de usar constructos existentes, você também pode escrever seus próprios constructos e permitir que qualquer pessoa os use em suas aplicações. Todas as construções são iguais no AWS CDK. As construções da AWS Construct Library são tratadas da mesma forma que uma construção de uma biblioteca de terceiros publicada viaNPM,Maven, ouPyPI. Os constructos publicados no repositório interno de pacotes da sua empresa também são tratados da mesma forma.

Para declarar um novo constructo, crie uma classe que estenda a classe de base do [Constructo](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html) no pacote `constructs` e siga o padrão dos argumentos do inicializador.

O exemplo a seguir mostra como declarar um constructo que representa um bucket do Amazon S3. O bucket do S3 envia uma notificação do Amazon Simple Notiﬁcation Service (Amazon SNS) toda vez que alguém carrega um arquivo nele.

**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**  
Nosso constructo `NotifyingBucket` não herda não do `Bucket`, mas sim do `Construct`. Estamos usando composição, não herança, para agrupar um bucket do Amazon S3 e um tópico do Amazon SNS. Em geral, a composição é preferida à herança ao desenvolver construções de AWS CDK.

O construtor `NotifyingBucket` tem uma assinatura de constructo típica: `scope`, `id` e `props`. O último argumento, `props`, é opcional (obtém o valor padrão `{}`) porque todos os props são opcionais. (A classe de base do `Construct` não aceita um argumento `props`.) É possível definir uma instância desse constructo em sua aplicação sem `props`, por exemplo:

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

Ou você pode usar `props` (em Java, um parâmetro adicional) para especificar o prefixo do caminho a ser filtrado, por exemplo:

**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/"),
})
```

Normalmente, você também gostaria de expor algumas propriedades ou métodos em seus constructos. Não é muito útil ter um tópico escondido atrás de seu constructo, porque os usuários de seu constructo não conseguem assiná-lo. Adicionar uma propriedade `topic` permite que os consumidores acessem o tópico interno, conforme mostrado no exemplo a seguir:

**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 fazer isso em Go, precisaremos de um pouco mais de encanamento. Nossa função original `NewNotifyingBucket` retornou um `awss3.Bucket`. Precisaremos estender o `Bucket` para incluir um membro do `topic` criando uma estrutura `NotifyingBucket`. Nossa função então retornará esse 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
}
```

Agora, os consumidores podem assinar o tópico, por exemplo:

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

## Saiba mais
<a name="constructs-learn"></a>

O vídeo a seguir fornece uma visão geral abrangente dos constructos do CDK e explica como você pode usá-los em suas aplicações do 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)


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

Os mixins são recursos reutilizáveis que você aplica às construções usando o método. `.with()` Eles adicionam recursos às construções L1 (CloudFormationnível) e L2 (com base em intenção), como controle de versão, exclusão automática de objetos ou bloqueio do acesso público. Cada mixin funciona em um único recurso. Para conectar dois recursos, use [Facades](facades.md) em vez disso.

Cada mixin tem como alvo um tipo de recurso específico e tem o nome desse recurso. Por exemplo, `BucketVersioning` tem como alvo buckets do Amazon S3. Você acessa mixins por meio do `mixins` namespace de cada módulo de serviço, como. `s3.mixins`

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

Você aplica mixins usando o `.with()` método, que está disponível em todas as construções. Você pode encadear vários mixins juntos:

**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 quais tipos de recursos ele suporta. Se você aplicar uma mixina a uma construção que ela não suporta, ela é ignorada silenciosamente. Isso significa que você pode aplicar mixins de forma ampla com segurança, sem se preocupar com incompatibilidades de tipos. Se você precisar garantir que uma mistura seja aplicada, use [`requireAll()`ou `requireAny()`](#mixins-advanced).

## Use mixins com construções L1 e L2
<a name="mixins-l1-l2"></a>

Os mixins funcionam com as construções L1 e L2. Quando você aplica um mixin a uma construção L2, ele também se aplica ao recurso L1 por trás dele.

O exemplo a seguir mostra como aplicar mixins às construções L1 e 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())
```

## Misturas versus propriedades de construção
<a name="mixins-vs-props"></a>

As misturas e as propriedades de construção funcionam juntas. As propriedades de construção L2 configuram um recurso quando você o cria. As misturas podem ser aplicadas a qualquer momento.

Use propriedades de construção L2 quando  
Você está usando uma construção L2 e a propriedade de que você precisa está disponível. Essa é a abordagem mais simples.

Use Mixins quando  
+ Você está trabalhando com uma construção L1 e deseja recursos semelhantes aos L2.
+ Você deseja adicionar um recurso a uma construção L2 que não está disponível como propriedade.
+ Você deseja aplicar o mesmo recurso em várias construções de tipos diferentes.

Os mixins não substituem as propriedades de construção. Eles não podem tornar uma propriedade obrigatória opcional nem alterar os valores padrão.

## Aplique Mixins a várias construções
<a name="mixins-advanced"></a>

A `Mixins.of()` API fornece mais controle sobre como os mixins são aplicados em um escopo. Em vez de chamar `.with()` construções individuais, você pode aplicar um mixin a todas as construções correspondentes em uma pilha ou escopo de uma só 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())
```

Por padrão, as construções que não suportam o mixin são ignoradas silenciosamente. Use `requireAll()` para afirmar que o mixin é aplicado a cada construção na seleção ou `requireAny()` para afirmar que ele é aplicado a pelo menos um. Isso é útil para garantir que os recursos tenham uma configuração necessária:

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

## Misturas e aspectos
<a name="mixins-aspects"></a>

Mixins e [Aspectos](aspects.md) estão relacionados, mas têm propósitos diferentes:
+  Os **mixins** são aplicados imediatamente quando você liga`.with()`. Você escolhe exatamente em quais construções aplicá-las.
+  **Os aspectos** se aplicam durante a síntese a todas as construções em um escopo. Use-os para políticas e verificações amplas.

Use Mixins para adicionar um recurso a construções específicas. Use Aspects para impor regras ou aplicar alterações em todo o aplicativo.

## Recursos relacionados
<a name="mixins-related"></a>
+  [Fachadas](facades.md) — Conecte recursos com diretores do IAM e outros serviços.
+  [Aspectos](aspects.md) — aplique alterações ou valide construções em todo o aplicativo.
+  [Construções](constructs.md) — Aprenda sobre as construções L1, L2 e L3.
+  [Personalize construções](cfn-layer.md) — Personalize construções com escotilhas de emergência e substituições brutas.

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

Fachadas são classes que conectam um recurso a outras partes do seu aplicativo. Cada fachada tem como alvo um tipo de recurso. Por exemplo, a classe é nomeada `BucketGrants` porque concede acesso aos buckets do Amazon S3. As fachadas funcionam com construções L1 (CloudFormationnível) e L2 (baseadas em intenção).

Algumas fachadas são geradas e estão prontas para uso para a maioria dos recursos, como classes de métricas e reflections. Outros são criados manualmente para recursos que precisam de lógica personalizada, como classes do Grants.

## Concede aulas
<a name="facades-grants"></a>

As fachadas mais usadas são as classes Grants. Eles permitem que você conceda acesso aos AWS recursos usando métodos simples. Por exemplo, você pode usar `BucketGrants` para buckets do Amazon S3 e para tópicos do Amazon `TopicGrants` SNS.

As construções L2 têm uma `grants` propriedade de fácil acesso. Você também pode criar uma classe Grants a partir de uma construção L1 usando seu método de fábrica. O exemplo a seguir mostra as duas abordagens:

**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 obter mais informações sobre subsídios e permissões, consulte [Concessões](permissions.md#permissions-grants).

## Use fachadas com mixins
<a name="facades-mixins-together"></a>

Você pode combinar Facades com [Mixins](mixins.md) para obter uma experiência completa semelhante à L2 em construções L1. Use Mixins para configurar o recurso e Facades para conceder acesso:

**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) — Adicione recursos reutilizáveis às construções L1 e L2.
+  [Concessões](permissions.md#permissions-grants) — conceda permissões entre recursos.
+  [Construções](constructs.md) — Aprenda sobre as construções L1, L2 e L3.

# Ambientes para o CDK da AWS
<a name="environments"></a>

Um ambiente consiste na conta da AWS e na região da AWS em que você implanta uma pilha do kit de desenvolvimento em nuvem da AWS (CDK da AWS).

 ** AWS Conta da**   
Ao criar uma conta da AWS, você recebe um ID da conta. Este ID é um número de 12 dígitos, como **012345678901**, que identifica de forma exclusiva sua conta. Para saber mais, consulte [Visualização de identificadores de conta da AWS](https://docs.aws.amazon.com/accounts/latest/reference/manage-acct-identifiers.html) no *Guia de referência de gerenciamento de contas da AWS*.

 ** AWS Região da**   
 As regiões da AWS são nomeadas usando uma combinação de localização geográfica e um número que representa uma zona de disponibilidade na região. Por exemplo, ** us-east-1 ** representa uma zona de disponibilidade na região Leste dos EUA (Norte da Virgínia). Para saber mais sobre as regiões da AWS, consulte [Regiões e zonas de disponibilidade](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/). Para obter uma lista de códigos de região, consulte [Endpoints regionais](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints) no *Guia de referência geral da AWS*.

O AWS CDK pode determinar ambientes a partir de suas credenciais e arquivos de configuração. Esses arquivos podem ser criados e gerenciados com a interface de linhad e comandos da AWS (AWS CLI). O seguinte é um exemplo básico de um desses arquivos:

 **Arquivo de credenciais**   

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

 **Arquivo de configuração**   

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

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

É possível passar informações de ambiente desses arquivos em seu código CDK por meio de variáveis de ambiente fornecidas pelo CDK. Ao executar um comando da CLI do CDK, como `cdk deploy`, você fornece o perfil de suas credenciais e arquivos de configuração para coletar informações do ambiente.

Veja a seguir um exemplo de especificação dessas variáveis de ambiente no seu código CDK:

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

Veja a seguir um exemplo de passagem de valores associados ao perfil `user1` de suas credenciais e arquivos de configuração para a CLI do CDK usando a opção `--profile`. Os valores desses arquivos serão passados para suas variáveis de ambiente:

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

Em vez de usar valores das credenciais e dos arquivos de configuração, você também pode codificar os valores do ambiente em seu código CDK. Veja um exemplo a seguir:

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

## Saiba mais
<a name="environments-learn"></a>

Para começar a usar ambientes com o AWS CDK, consulte [Configuração de ambientes para uso com o AWS CDK](configure-env.md).

# Bootstrapping do AWS CDK
<a name="bootstrapping"></a>

 O *bootstrapping* é o processo de preparação do seu ambiente da AWS para uso com o kit de desenvolvimento em nuvem da AWS (CDK da AWS). Antes de implantar uma pilha do CDK em um ambiente da AWS, o ambiente deve primeiro receber o bootstrapping.

## O que é bootstrapping?
<a name="bootstrapping-what"></a>

O bootstrapping prepara seu ambiente da AWS provisionando recursos da AWS específicos em seu ambiente que são usados pelo AWS CDK. Esses recursos são comumente chamados de *recursos de bootstrap*. Entre elas estão:
+  **Bucket do Amazon Simple Storage Service (Amazon S3)**: usado para armazenar arquivos de projeto do CDK, como código de função do AWS Lambda e ativos.
+  **Repositório do Amazon Elastic Container Registry (Amazon ECR)**: usado principalmente para armazenar imagens do Docker.
+  **Perfis do AWS Identity and Access Management (IAM)**: configurados para conceder as permissões necessárias pelo AWS CDK para realizar implantações. Para obter mais informações sobre os perfis do IAM criados durante o bootstrapping, consulte [Perfis do IAM criados durante o bootstrapping](bootstrapping-env.md#bootstrapping-env-roles).

## Como o bootstrapping funciona?
<a name="bootstrapping-how"></a>

Os recursos e suas configurações que são usados pelo CDK são definidos em um modelo do AWS CloudFormation. Esse modelo é criado e gerenciado pela equipe do CDK. Para a versão mais recente desse modelo, 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) no *repositório aws-cdk-cli no GitHub*.

Para fazer bootstrapping em um ambiente, você usa o comando `cdk bootstrap` da interface de linha de comandos do AWS CDK (CLI do AWS CDK). A CLI do CDK recupera o modelo e o implanta no AWS CloudFormation como uma pilha, conhecida como *pilha de bootstrapping*. Por padrão, o nome de pilha é `CDKToolkit`. Ao implantar esse modelo, o CloudFormation provisiona os recursos em seu ambiente. Após a implantação, a pilha de bootstrapping aparecerá no console do AWS CloudFormation do seu ambiente.

Você também pode personalizar o bootstrapping modificando o modelo ou usando as opções da CLI do CDK com o comando `cdk bootstrap`.

 Os ambientes da AWS são independentes. Cada ambiente que você desejar usar com o AWS CDK deve primeiro receber o bootstrapping.

## Saiba mais
<a name="bootstrapping-learn"></a>

Para obter instruções sobre como fazer o bootstrapping no seu ambiente, consulte [Bootstrapping do seu ambiente para uso com o AWS CDK](bootstrapping-env.md).

# Recursos e o AWS CDK
<a name="resources"></a>

 *Recursos* são o que você configura para usar AWS serviços em seus aplicativos. Os recursos são uma característica do AWS CloudFormation. Ao configurar recursos e suas propriedades em um AWS CloudFormation modelo, você pode implantar para AWS CloudFormation provisionar seus recursos. Com o AWS Cloud Development Kit (AWS CDK), você pode configurar recursos por meio de construções. Em seguida, você implanta seu aplicativo CDK, o que envolve sintetizar um AWS CloudFormation modelo e implantá-lo para AWS CloudFormation provisionar seus recursos.

## Configurar recursos usando constructos
<a name="resources-configure"></a>

Conforme descrito em [AWS CDK Constructs](constructs.md), o AWS CDK fornece uma rica biblioteca de classes de construções, chamadas de construções, que representam *todos os* recursos. AWS 

Para criar uma instância de um recurso usando seu constructo correspondente, passe o escopo como o primeiro argumento, o ID lógico do constructo e um conjunto de propriedades de configuração (props). Por exemplo, veja como criar uma fila do Amazon SQS com criptografia AWS KMS usando a [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)construção da Construct Library. AWS 

**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,
})
```

Alguns props de configuração são opcionais e, em muitos casos, têm valores padrão. Em alguns casos, todos os props são opcionais e o último argumento pode ser totalmente omitido.

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

A maioria dos recursos na AWS Construct Library expõe atributos, que são resolvidos no momento da implantação pelo AWS CloudFormation. Os atributos são expostos na forma de propriedades nas classes de recursos com o nome do tipo como prefixo. O exemplo a seguir mostra como obter o URL de uma fila do Amazon SQS usando a propriedade `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 e o AWS CDK](tokens.md) para obter informações sobre como o AWS CDK codifica atributos de tempo de implantação como cadeias de caracteres.

## Fazer referência a recursos
<a name="resources-referencing"></a>

Ao configurar recursos, muitas vezes você precisará referenciar propriedades de outro recurso. Veja os exemplos a seguir:
+ Um recurso do Amazon Elastic Container Service (Amazon ECS) requer uma referência ao cluster no qual é executado.
+ Uma CloudFront distribuição da Amazon exige uma referência ao bucket do Amazon Simple Storage Service (Amazon S3) contendo o código-fonte.

É possível fazer referência a recursos de qualquer uma das formas a seguir:
+ Ao passar um recurso definido em sua aplicação CDK, na mesma pilha ou em uma diferente
+ Ao passar um objeto proxy referenciando um recurso definido em sua AWS conta, criado a partir de um identificador exclusivo do recurso (como um ARN)

Se a propriedade de um constructo representa um constructo para outro recurso, seu tipo é o tipo de interface de constructo. Por exemplo, o constructo do Amazon ECS assume uma propriedade `cluster` do tipo `ecs.ICluster`. Outro exemplo é a construção CloudFront de distribuição que usa uma propriedade `sourceBucket` (Python:`source_bucket`) do tipo. `s3.IBucket`

Você pode transmitir diretamente qualquer objeto de recurso do tipo adequado definido no mesmo aplicativo AWS CDK. O exemplo a seguir define um cluster do Amazon ECS e o usa para definir um serviço do 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,
})
```

### Como fazer referência a recursos em uma pilha diferente
<a name="resource-stack"></a>

Você pode se referir aos recursos em uma pilha diferente, desde que estejam definidos no mesmo aplicativo e no mesmo AWS ambiente. O seguinte padrão é geralmente usado:
+ Armazene uma referência ao constructo como um atributo da pilha que produz o recurso. (Para obter uma referência à pilha do constructo atual, use `Stack.of(this)`.)
+ Passe essa referência ao construtor da pilha que consome o recurso como parâmetro ou propriedade. A pilha consumidora então a passa como uma propriedade para qualquer constructo que precise dela.

O exemplo a seguir define uma pilha `stack1`. Essa pilha define um bucket do Amazon S3 e armazena uma referência ao constructo do bucket como um atributo da pilha. Em seguida, o aplicativo define uma segunda pilha,`stack2`, que aceita um bucket na instanciação. `stack2`pode, por exemplo, definir uma AWS Glue Table que usa o bucket para armazenamento de dados.

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

Se o AWS CDK determinar que o recurso está no mesmo ambiente, mas em uma pilha diferente, ele sintetiza automaticamente AWS CloudFormation [as exportações](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html) na pilha de produção e as da pilha consumidora para transferir essas informações de uma [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)pilha para a outra.

#### Como resolver os deadlocks de dependência
<a name="resources-deadlock"></a>

Fazer referência a um recurso de uma pilha em outra pilha cria uma dependência entre as duas pilhas. Isso garante que eles sejam implantados na ordem correta. Depois que as pilhas são implantadas, essa dependência é concreta. Depois disso, remover o uso do recurso compartilhado da pilha consumidora pode causar uma falha inesperada na implantação. Isso acontece se houver outra dependência entre as duas pilhas que as força a serem implantadas na mesma ordem. Isso também pode acontecer sem dependência se a pilha de produção for simplesmente escolhida pelo Kit de Ferramentas CDK para ser implantada primeiro. A AWS CloudFormation exportação é removida da pilha de produção porque não é mais necessária, mas o recurso exportado ainda está sendo usado na pilha de consumo porque sua atualização ainda não foi implantada. Portanto, a implantação da pilha do produtor falha.

Para resolver esse impasse, remova o uso do recurso compartilhado da pilha de consumo. (Isso remove a exportação automática da pilha de produção.) Em seguida, adicione manualmente a mesma exportação à pilha de produção usando exatamente o mesmo ID lógico da exportação gerado automaticamente. Remova o uso do recurso compartilhado na pilha de consumo e implante as duas pilhas. Em seguida, remova a exportação manual (e o recurso compartilhado, se não for mais necessário) e implante as duas pilhas novamente. O 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) da pilha é uma maneira conveniente de criar a exportação manual para essa finalidade. (Veja o exemplo na referência do método vinculado.)

### Referenciando recursos em sua conta AWS
<a name="resources-external"></a>

Suponha que você queira usar um recurso já disponível em sua AWS conta em seu aplicativo AWS CDK. Isso pode ser um recurso definido por meio do console, de um AWS SDK, diretamente com AWS CloudFormation ou em um aplicativo AWS CDK diferente. É possível transformar o ARN do recurso (ou outro atributo de identificação ou grupo de atributos) em um objeto proxy. O objeto proxy serve como referência ao recurso chamando um método estático de fábrica na classe do recurso.

Quando você cria esse proxy, o recurso externo **não** se torna parte do seu aplicativo AWS CDK. Portanto, as alterações feitas no proxy em seu aplicativo AWS CDK não afetam o recurso implantado. No entanto, o proxy pode ser passado para qualquer método AWS CDK que exija um recurso desse tipo.

O exemplo a seguir mostra como referenciar um bucket baseado em um bucket existente com o ARN `arn:aws:s3:::amzn-s3-demo-bucket1` e uma Amazon Virtual Private Cloud com base em uma VPC existente com um ID 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"),
})
```

Vamos examinar com mais cuidado o 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 o `ec2.Vpc` constructo é complexo, talvez você queira selecionar a VPC de várias maneiras para ser usada com sua aplicação CDK. Para resolver isso, a construção da VPC tem um método `fromLookup` estático (Python:`from_lookup`) que permite pesquisar a Amazon VPC desejada consultando sua conta no momento da síntese. AWS 

Para usar o `Vpc.fromLookup()`, o sistema que sintetiza a pilha deve ter acesso à conta proprietária da Amazon VPC. Isso ocorre porque o Kit de Ferramentas CDK consulta a conta para encontrar a Amazon VPC certa no momento da síntese.

Além disso, `Vpc.fromLookup()` funciona somente em pilhas definidas com uma **conta** e uma **região** explícitas (consulte [Ambientes para o AWS CDK](environments.md)). Se o AWS CDK tentar pesquisar uma Amazon VPC a partir de uma pilha [independente do ambiente](stacks.md#stack-api), o CDK Toolkit não saberá qual ambiente consultar para encontrar a VPC.

Você deve fornecer `Vpc.fromLookup()` atributos suficientes para identificar de forma exclusiva uma VPC em sua conta. AWS Por exemplo, só pode haver uma VPC padrão, então basta especificar a VPC como padrão.

**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),
})
```

Você também pode usar a `tags` propriedade para consultar VPCs por tag. Você pode adicionar tags à Amazon VPC no momento de sua criação usando AWS CloudFormation ou o AWS CDK. Você pode editar as tags a qualquer momento após a criação usando o AWS Management Console, a AWS CLI ou um AWS SDK. Além de todas as tags que você mesmo adiciona, o AWS CDK adiciona automaticamente as seguintes tags a tudo o VPCs que ele cria.
+  **Nome** – O nome da VPC.
+  **aws-cdk:subnet-name** – O nome da sub-rede.
+  **aws-cdk:subnet-type** – O tipo de sub-rede: pública, privada ou isolada.

**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")},
})
```

Os resultados de `Vpc.fromLookup()` são armazenados em cache no arquivo `cdk.context.json` do projeto. (Consulte [Valores de contexto e o AWS CDK.)](context.md) Confirme esse arquivo com o controle de versão para que sua aplicação continue se referindo à mesma Amazon VPC. Isso funciona mesmo se você alterar posteriormente os atributos do seu de uma VPCs forma que resultaria na seleção de uma VPC diferente. [Isso é particularmente importante se você estiver implantando a pilha em um ambiente que não tem acesso à AWS conta que define a VPC, como o CDK Pipelines.](cdk-pipeline.md)

Embora você possa usar um recurso externo em qualquer lugar em que usaria um recurso semelhante definido em seu aplicativo AWS CDK, você não pode modificá-lo. Por exemplo, chamar `addToResourcePolicy` (Python: `add_to_resource_policy`) em um `s3.Bucket` externo não faz nada.

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

Os nomes lógicos dos recursos em AWS CloudFormation são diferentes dos nomes dos recursos que são mostrados no AWS Management Console depois de serem implantados pelo AWS CloudFormation. O AWS CDK chama esses nomes finais de *nomes físicos*.

Por exemplo, AWS CloudFormation pode criar o bucket do Amazon S3 com o ID lógico `Stack2MyBucket4DD88B4F` e o nome físico. `stack2MyBucket4dd88b4f-iuv1rbv9z3to`

É possível especificar um nome físico ao criar constructos que representam recursos usando a propriedade `<resourceType>Name`. O exemplo a seguir cria um bucket do Amazon S3 com o nome 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"),
})
```

A atribuição de nomes físicos aos recursos tem algumas desvantagens em AWS CloudFormation. Mais importante ainda, qualquer alteração nos recursos implantados que exija a substituição de um recurso, como alterações nas propriedades de um recurso que sejam imutáveis após a criação, falhará se um recurso tiver um nome físico atribuído. Se você acabar nesse estado, a única solução é excluir a AWS CloudFormation pilha e implantar o aplicativo AWS CDK novamente. Consulte a [Documentação do AWS CloudFormation ](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) para obter detalhes.

Em alguns casos, como ao criar um aplicativo AWS CDK com referências entre ambientes, nomes físicos são necessários para que o AWS CDK funcione corretamente. Nesses casos, se você não quiser se preocupar em criar um nome físico sozinho, deixe o AWS CDK nomeá-lo para você. Para isso, use o valor especial `PhysicalName.GENERATE_IF_NEEDED`, da forma a seguir.

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

## Passando identificadores de recursos exclusivos
<a name="resources-identifiers"></a>

Sempre que possível, você deve passar os recursos por referência, conforme descrito na seção anterior. No entanto, há casos em que você não tem outra escolha a não ser se referir a um recurso por meio de um de seus atributos. Alguns casos de uso incluem o seguinte:
+ Quando você está usando AWS CloudFormation recursos de baixo nível.
+ Quando você precisa expor recursos aos componentes de tempo de execução de um aplicativo AWS CDK, como ao se referir às funções do Lambda por meio de variáveis de ambiente.

Esses identificadores estão disponíveis como atributos nos recursos, como os seguintes.

**Example**  

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

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

```
bucket.bucket_name
lambda_func.function_arn
security_group_arn
```
A vinculação Java AWS CDK usa métodos getter para atributos.  

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

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

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

O exemplo a seguir mostra como passar um nome de bucket gerado para uma função 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()},
})
```

## Concedendo permissões entre recursos
<a name="resources-grants"></a>

Construções de alto nível possibilitam a obtenção de permissões com privilégios mínimos, oferecendo requisitos de permissão simples e baseados em intenção para expressar. APIs Por exemplo, muitas construções oferecem métodos de concessão que você pode usar para conceder permissão a uma entidade (como um papel ou usuário do IAM) para trabalhar com o recurso, sem precisar criar manualmente declarações de permissão do IAM.

Os métodos de concessão estão disponíveis por meio de classes do Grants (como `BucketGrants` para buckets do Amazon S3). Essas classes funcionam com construções L1 e L2. As construções L2 expõem uma `grants` propriedade por conveniência, mas você também pode criar uma classe Grants diretamente de uma construção L1. Você pode combinar classes de Grants com [Mixins](mixins.md) para obter conveniência semelhante à de L2 em construções de L1.

O exemplo a seguir cria as permissões para permitir que a função de execução de uma função do Lambda leia e grave objetos em um determinado bucket do Amazon S3. Se o bucket do Amazon S3 for criptografado com uma chave AWS KMS, esse método também concederá permissões à função de execução da função Lambda para descriptografar com a chave.

**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() {
  // ...
}
```

Os métodos de concessão retornam um objeto `iam.Grant`. Use o atributo `success` do objeto `Grant` para determinar se a concessão foi efetivamente aplicada (por exemplo, ela pode não ter sido aplicada em [recursos externos](#resources-referencing)). Você também pode usar o método `assertSuccess` (Python: `assert_success`) do objeto `Grant` para garantir que a concessão tenha sido aplicada com sucesso.

Se um método de concessão específico não estiver disponível para o caso de uso específico, será possível usar um método de concessão genérico para definir uma nova concessão com uma lista específica de ações.

O exemplo a seguir mostra como conceder a uma função do Lambda acesso à ação do Amazon DynamoDB `CreateBackup`.

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

Muitos recursos, como as funções do Lambda, exigem que um perfil seja assumido ao executar o código. Uma propriedade de configuração permite que você especifique um `iam.IRole`. Se nenhum perfil for especificado, a função criará automaticamente um perfil específico para esse uso. Em seguida, você pode usar métodos de concessão nos recursos para adicionar declarações ao perfil.

Os métodos de concessão são criados usando um nível inferior APIs para lidar com as políticas do IAM. As políticas são modeladas como [PolicyDocument](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyDocument.html)objetos. Adicione declarações diretamente aos perfils (ou ao perfil anexado a um constructo) usando o método `addToRolePolicy` (Python: `add_to_role_policy`) ou à política de um recurso (como uma política `Bucket`) usando o método `addToResourcePolicy` (Python: `add_to_resource_policy`).

## Métricas de recursos e alarmes
<a name="resources-metrics"></a>

Muitos recursos emitem CloudWatch métricas que podem ser usadas para configurar painéis de monitoramento e alarmes. Constructos de nível superior têm métodos métricos que permitem acessar as métricas sem procurar o nome correto a ser usado.

O exemplo a seguir mostra como definir um alarme quando o `ApproximateNumberOfMessagesNotVisible` de uma fila do Amazon SQS exceder 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),
})
```

Se não houver um método para uma métrica específica, será possível usar o método métrico geral para especificar o nome da métrica manualmente.

As métricas também podem ser adicionadas aos CloudWatch painéis. Consulte [CloudWatch](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch-readme.html).

## Tráfego de rede
<a name="resources-traffic"></a>

Em muitos casos, você deve habilitar permissões em uma rede para que uma aplicação funcione, como quando a infraestrutura computacional precisa acessar a camada de persistência. Recursos que estabelecem ou escutam conexões expõem métodos que permitem fluxos de tráfego, incluindo a definição de regras de grupos de segurança ou rede ACLs.

 [IConnectable](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IConnectable.html)os recursos têm uma `connections` propriedade que é a porta de entrada para a configuração das regras de tráfego de rede.

Você permite que os dados fluam em um determinado caminho de rede usando métodos `allow`. O exemplo a seguir permite conexões HTTPS com a web e conexões de entrada do 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"))
```

Alguns recursos têm portas padrão associadas a eles. Os exemplos incluem o receptor de um balanceador de carga na porta pública e as portas nas quais o mecanismo de banco de dados aceita conexões para instâncias de um banco de dados do Amazon RDS. Nesses casos, você pode aplicar um controle rígido da rede sem precisar especificar manualmente a porta. Para fazer isso, use os métodos `allowDefaultPortFrom` e `allowToDefaultPort` (Python: `allow_default_port_from`, `allow_to_default_port`).

O exemplo a seguir mostra como habilitar conexões de qualquer IPV4 endereço e uma conexão de um grupo do Auto Scaling para acessar um banco de dados.

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

## Processar eventos
<a name="resources-events"></a>

Alguns recursos podem atuar como fontes de eventos. Use o método `addEventNotification` (Python: `add_event_notification`) para registrar um destino de evento para um determinado tipo de evento emitido pelo recurso. Além disso, os métodos `addXxxNotification` oferecem uma maneira simples de registrar um manipulador para tipos de eventos comuns.

O exemplo a seguir mostra como acionar uma função do Lambda quando um objeto é adicionado a um bucket do 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 remoção
<a name="resources-removal"></a>

Recursos que mantêm dados persistentes, como bancos de dados, buckets do Amazon S3 e registros do Amazon ECR, têm uma *política de remoção*. A política de remoção indica se objetos persistentes devem ser excluídos quando a pilha de AWS CDK que os contém for destruída. Os valores que especificam a política de remoção estão disponíveis por meio da `RemovalPolicy` enumeração no módulo CDK. AWS `core`

**nota**  
Recursos além daqueles que armazenam dados de forma persistente também podem ter um `removalPolicy` que é usado para uma finalidade diferente. Por exemplo, uma versão da função do Lambda usa um atributo `removalPolicy` para determinar se uma determinada versão é retida quando uma nova versão é implantada. Eles têm significados e padrões diferentes em comparação com a política de remoção em um bucket do Amazon S3 ou uma tabela do DynamoDB.


| Valor | Significado | 
| --- | --- | 
|   `RemovalPolicy.RETAIN`   |  Manter o conteúdo do recurso ao destruir a pilha (padrão). O recurso fica órfão da pilha e deve ser excluído manualmente. Se você tentar reimplantar a pilha enquanto o recurso ainda existe, você receberá uma mensagem de erro devido a um conflito de nomes.  | 
|   `RemovalPolicy.DESTROY`   |  O recurso será destruído junto com a pilha.  | 

 AWS CloudFormation não remove buckets do Amazon S3 que contêm arquivos, mesmo que sua política de remoção esteja definida como. `DESTROY` Tentar fazer isso é um AWS CloudFormation erro. Para que o AWS CDK exclua todos os arquivos do bucket antes de destruí-lo, defina a `autoDeleteObjects` propriedade do bucket como. `true`

Veja a seguir um exemplo de criação de um bucket do Amazon S3 com `RemovalPolicy` de `DESTROY` e `autoDeleteOjbects` definido como `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),
})
```

Você também pode aplicar uma política de remoção diretamente ao AWS CloudFormation recurso subjacente por meio do `applyRemovalPolicy()` método. Esse método está disponível em alguns recursos com estado que não têm uma propriedade `removalPolicy` nas propriedades do recurso L2. Os exemplos incluem:
+  AWS CloudFormation pilhas
+ Grupos de usuários do Amazon Cognito
+ Instâncias de banco de dados do Amazon DocumentDB
+ Volumes do Amazon EC2
+  OpenSearch Domínios do Amazon Service
+ Sistemas de FSx arquivos da Amazon
+ Filas do 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**  
O AWS CDK se `RemovalPolicy` traduz em s. AWS CloudFormation `DeletionPolicy` No entanto, o padrão no AWS CDK é reter os dados, o que é o oposto do AWS CloudFormation padrão.

# Identificadores e o AWS CDK
<a name="identifiers"></a>

Ao compilar aplicações do kit de desenvolvimento em nuvem da AWS (CDK da AWS), você usará vários tipos de identificadores e nomes. Para usar o AWS CDK forma eficaz e evitar erros, é importante entender os tipos de identificadores.

Os identificadores devem ser exclusivos dentro do escopo em que foram criados; eles não precisam ser globalmente exclusivos em sua aplicação do AWS CDK.

Se você tentar criar um identificador com o mesmo valor dentro do mesmo escopo, o AWS CDK gerará uma exceção.

## IDs de constructo
<a name="identifiers-construct-ids"></a>

O identificador mais comum, `id`, é o identificador passado como segundo argumento ao instanciar um objeto de constructo. Esse identificador, como todos os identificadores, só precisa ser exclusivo dentro do escopo em que foi criado, que é o primeiro argumento ao instanciar um objeto de constructo.

**nota**  
O `id` de uma pilha também é o identificador que você usa para se referir a ela na [Referência da CLI do AWS CDK](cli.md).

Vejamos um exemplo em que temos dois constructos com o identificador `MyBucket` em nossa aplicação. O primeiro é definido no escopo da pilha com o identificador `Stack1`. O segundo é definido no escopo de uma pilha com o identificador `Stack2`. Como eles são definidos em escopos diferentes, isso não causa nenhum conflito e eles podem coexistir na mesma aplicação sem 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");
    }
}
```

## Caminhos
<a name="identifiers-paths"></a>

Os constructos em uma aplicação do AWS CDK formam uma hierarquia enraizada na classe `App`. Nós nos referimos à coleção de IDs de um determinado constructo, seu constructo pai, seu avô e assim por diante até a raiz da árvore de constructo, como um *caminho*.

O AWS CDK normalmente exibe caminhos em seus modelos como uma string. Os IDs dos níveis são separados por barras, começando no nó imediatamente abaixo da instância raiz `App`, que geralmente é uma pilha. Por exemplo, os caminhos dos dois recursos de bucket do Amazon S3 no exemplo de código anterior são `Stack1/MyBucket` e `Stack2/MyBucket`.

É possível acessar o caminho de qualquer constructo de aneira programática, conforme mostrado no exemplo a seguir. Isso segue o caminho de `myConstruct` (ou `my_construct`, como escreveriam os desenvolvedores do Python). Como os IDs devem ser exclusivos dentro do escopo em que são criadas, seus caminhos são sempre exclusivos em uma aplicação do 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;
```

## IDs exclusivos
<a name="identifiers-unique-ids"></a>

 O AWS CloudFormation exige que todos os IDs lógicos em um modelo sejam exclusivos. Por isso, o AWS CDK deve ser capaz de gerar um identificador exclusivo para cada constructo em uma aplicação. Os recursos têm caminhos que são globalmente exclusivos (os nomes de todos os escopos da pilha até um recurso específico). Dessa forma, AWS CDK gera os identificadores exclusivos necessários concatenando os elementos do caminho e adicionando um hash de 8 dígitos. (O hash é necessário para distinguir caminhos distintos, como `A/B/C` e `A/BC`, que resultariam no mesmo identificador do AWS CloudFormation. Os identificadores do AWS CloudFormation são alfanuméricos e não podem conter barras ou outros caracteres separadores.) O AWS CDK chama essa string de *ID exclusivo* do constructo.

Em geral, sua aplicação do AWS CDK não precisa saber sobre IDs exclusivos. No entanto, é possível acessar programaticamente o ID exclusivo de qualquer constructo, conforme mostrado no exemplo a seguir.

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

O *endereço* é outro tipo de identificador exclusivo que distingue de forma exclusiva os recursos do CDK. Derivado do hash SHA-1 do caminho, não é legível por humanos. No entanto, seu comprimento constante e relativamente curto (sempre 42 caracteres hexadecimais) o torna útil em situações em que o ID exclusivo “tradicional” pode ser muito longo. Alguns constructos podem usar o endereço no modelo sintetizado AWS CloudFormation em vez do ID exclusivo. Novamente, sua aplicação geralmente não precisa saber sobre os endereços de seus constructos, mas é possível recuperar o endereço de um constructo da maneira a seguir.

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

## IDs lógicos
<a name="identifiers-logical-ids"></a>

Os IDs exclusivos servem como *identificadores lógicos* (ou *nomes lógicos*) dos recursos nos modelos do AWS CloudFormation gerados para constructos que representam recursos da AWS.

Por exemplo, o bucket do Amazon S3 no exemplo anterior, criado dentro do `Stack2`, resulta em um recurso ` AWS::S3::Bucket`. O ID lógico do recurso é `Stack2MyBucket4DD88B4F` no modelo do AWS CloudFormation resultante. (Para obter detalhes sobre como esse identificador é gerado, consulte [IDs exclusivos](#identifiers-unique-ids).)

### Estabilidade de ID lógico
<a name="identifiers-logical-id-stability"></a>

Evite alterar o ID lógico de um recurso após sua criação. AWS O CloudFormation identifica os recursos por meio dos seus IDs lógicos. Portanto, se você alterar o ID lógico de um recurso, o AWS CloudFormation criará um novo recurso com o novo ID lógico e excluirá o existente. Dependendo do tipo de recurso, isso pode causar interrupção do serviço, perda de dados ou ambas.

# Tokens e o AWS CDK
<a name="tokens"></a>

No kit de desenvolvimento em nuvem da AWS (CDK da AWS), os *tokens* são espaços reservados para valores que não são conhecidos ao definir constructos ou sintetizar pilhas. Esses valores serão totalmente resolvidos na implantação, quando sua infraestrutura real for criada. Ao desenvolver aplicações do AWS CDK, você trabalhará com tokens para gerenciar esses valores em toda a sua aplicação.

## Exemplo de token
<a name="tokens-example"></a>

A seguir temos um exemplo de uma pilha CDK que define uma constructo para um bucket do Amazon Simple Storage Service (Amazon S3). Como o nome do nosso bucket ainda não é conhecido, o valor de `bucketName` é armazenado como um 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
}

// ...
```
Quando executamos `cdk synth` para sintetizar nossa pilha, o valor de `myBucketName` será exibido no formato de token `${Token[TOKEN.<1234>]}`. Esse formato de token é um resultado de como o AWS CDK codifica os tokens. Neste exemplo, o token é codificado como uma string:  

```
$ cdk synth --quiet
myBucketName: ${Token[TOKEN.21]}
```
Como o valor do nome do nosso bucket não é conhecido na síntese, o token é renderizado como `myBucket<unique-hash>`. Nosso modelo do AWS CloudFormation usa a função intrínseca `Ref` para referenciar seu valor, que será conhecido na implantação:  

```
Resources:
  myBucket<5AF9C99B>:
    # ...
Outputs:
  bucketNameOutput:
    Description: The name of the S3 bucket
    Value:
      Ref: myBucket<5AF9C99B>
```

Para obter mais informações sobre como o hash exclusivo é gerado, consulte [IDs lógicos gerados no seu modelo do AWS CloudFormation](configure-synth.md#how-synth-default-logical-ids).

## Passando tokens
<a name="tokens-passing"></a>

Os tokens podem ser passados como se fossem o valor real que representam. Veja a seguir um exemplo que passa o token do nome do nosso bucket para um constructo de uma função do 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
}
// ...
```
Quando sintetizamos nosso modelo, as funções intrínsecas `Ref` e as funções intrínsecas `Fn::Join` são usadas para especificar os valores, que serão conhecidos na implantação:  

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

## Como funciona a codificação de token
<a name="tokens-work"></a>

Tokens são objetos que implementam a interface [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 contém um único método `resolve`. Durante a síntese, o AWS CDK chama esse método para produzir o valor final dos tokens em seu modelo do CloudFormation.

**nota**  
Você raramente trabalhará diretamente com a interface `IResolvable`. Provavelmente, você verá apenas versões codificadas por string dos tokens.

### Tipos de codificação de token
<a name="tokens-work-types"></a>

Os tokens participam do processo de síntese para produzir valores arbitrários de qualquer tipo. Outras funções normalmente aceitam apenas argumentos de tipos básicos, como `string` ou `number`. Para usar tokens nesses casos, é possível codificá-los em um dos três tipos usando métodos estáticos na classe [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 gerar uma codificação de string (ou chamar `.toString()` no objeto do 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 gerar uma codificação 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 gerar uma codificação numérica.

Eles pegam um valor arbitrário, que pode ser um `IResolvable`, e os codificam em um valor primitivo do tipo indicado.

**Importante**  
Como qualquer um dos tipos anteriores pode ser potencialmente um token codificado, tenha cuidado ao analisar ou tentar ler seu conteúdo. Por exemplo, se você tentar analisar uma string para extrair um valor dela, e a string for um token codificado, sua análise falhará. Da mesma forma, se você tentar consultar o comprimento de uma matriz ou realizar operações matemáticas com um número, primeiro verifique se eles não são tokens codificados.

## Como verificar se há tokens em sua aplicação
<a name="tokens-check"></a>

Para verificar se um valor tem um token não resolvido, chame o 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`). Veja a seguir um exemplo que verifica se o valor do nome do nosso bucket do Amazon S3 é um token. Se não for um token, então validamos o tamanho do nome do 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.")
	}

	// ...
}
```

Quando executamos `cdk synth`, `myBucketName` é identificado como um token:

```
$ cdk synth --quiet
Token identified.
```

**nota**  
É possível usar codificações de token para escapar do sistema de tipos. Por exemplo, você pode codificar em string um token que produz um valor numérico no momento da síntese. Se você usar essas funções, é sua responsabilidade garantir que seu modelo seja resolvido em um estado utilizável após a síntese.

## Trabalhando com tokens codificados por string
<a name="tokens-string"></a>

Os tokens codificados por string são semelhantes aos seguintes:

```
${TOKEN[Bucket.Name.1234]}
```

Eles podem ser transmitidos como strings regulares e podem ser concatenados, conforme mostrado no exemplo a seguir.

**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"
```

Você também pode usar interpolação de strings, se a sua linguagem oferecer suporte, conforme mostrado no exemplo a seguir.

**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";
```
Use `fmt.Sprintf` para uma funcionalidade semelhante:  

```
functionName := fmt.Sprintf("%sFunction", *bucket.BucketName())
```

Evite manipular a string de outras formas. Por exemplo, pegar uma substring de uma string provavelmente quebrará o token da string.

## Trabalhando com tokens codificados em lista
<a name="tokens-list"></a>

Os tokens codificados em lista são semelhantes aos seguintes:

```
["#{TOKEN[Stack.NotificationArns.1234]}"]
```

A única coisa segura a fazer com essas listas é passá-las diretamente para outros constructos. Os tokens no formato de lista de strings não podem ser concatenados, nem um elemento pode ser retirado do token. A única maneira segura de manipulá-los é usando funções intrínsecas do 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).

## Trabalhando com tokens codificados por números
<a name="tokens-number"></a>

Os tokens codificados por números são um conjunto de pequenos números negativos de ponto flutuante que se parecem com os seguintes.

```
-1.8881545897087626e+289
```

Assim como acontece com os tokens da lista, você não pode modificar o valor do número, pois isso provavelmente quebrará o token numérico.

A seguir temos um exemplo de um constructo que contém um token codificado como um 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
}

// ...
```

Quando executamos `cdk synth`, o valor de `portToken` é exibido como um token codificado por número:

```
$ cdk synth --quiet
portToken: -1.8881545897087968e+289
```

### Passar tokens codificados por números
<a name="tokens-number-pass"></a>

Quando você passa tokens codificados em números para outros constructos, pode fazer sentido convertê-los em strings primeiro. Por exemplo, se você quiser usar o valor de uma string codificada por número como parte de uma string concatenada, convertê-la ajuda na legibilidade.

No exemplo a seguir, `portToken` é um token codificado em números que queremos passar para nossa função do 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
}

// ...
```

Se passarmos esse valor para `connectionString`, o valor de saída quando executamos `cdk synth` pode ser confuso devido à string codificada por números:

```
$ cdk synth --quiet
connectionString: jdbc:mysql://mydb.cluster.amazonaws.com:-1.888154589708796e+289/mydatabase
```

Para converter um token codificado por número em uma string, use [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). No exemplo a seguir, convertemos o token codificado por número em uma string antes de definir nossa string de conexão:

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

// ...
```

Quando executamos o `cdk synth`, o valor da nossa string de conexão é representado em um formato mais limpo e claro:

```
$ cdk synth --quiet
connectionString: jdbc:mysql://mydb.cluster.amazonaws.com:${Token[TOKEN.242]}/mydatabase
```

## Valores lentos
<a name="tokens-lazy"></a>

Além de representar valores de tempo de implantação, como [parâmetros](parameters.md) do AWS CloudFormation, os tokens também são comumente usados para representar valores lentos de tempo de síntese. Esses são valores para os quais o valor final será determinado antes da conclusão da síntese, mas não no ponto em que o valor é construído. Use tokens para passar uma string literal ou um valor numérico para outro constructo, enquanto o valor real no momento da síntese pode depender de algum cálculo que ainda não foi feito.

É possível criar tokens representando valores lentos de tempo de sintetizador usando métodos estáticos na classe `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) e [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). Esses métodos aceitam um objeto cuja propriedade `produce` é uma função que aceita um argumento de contexto e retorna o valor final quando chamada.

O exemplo a seguir cria um grupo do Auto Scaling cuja capacidade é determinada após sua criação.

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

## Conversão para JSON
<a name="tokens-json"></a>

Às vezes, você deseja produzir uma string JSON de dados arbitrários e talvez não saiba se os dados contêm tokens. Para codificar adequadamente qualquer estrutura de dados em JSON, independentemente de ela conter tokens, use o 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), conforme mostrado no exemplo a seguir.

**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 e o AWS CDK
<a name="parameters"></a>

 Os *parâmetros* são valores personalizados fornecidos no momento da implantação. Os [parâmetros](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html) são um recurso do AWS CloudFormation. Como o kit de desenvolvimento em nuvem da AWS (CDK da AWS) sintetiza modelos do AWS CloudFormation, ele também oferece suporte para parâmetros de tempo de implantação.

## Sobre parâmetros
<a name="parameters-about"></a>

Usando o AWS CDK, é possível definir parâmetros, que podem então ser usados nas propriedades dos constructos que você cria. Você também pode implantar pilhas que contenham parâmetros.

Ao implantar o modelo do AWS CloudFormation usando a CLI do AWS CDK, você fornece os valores dos parâmetros na linha de comando. Se você implantar o modelo por meio do console AWS do CloudFormation, você será solicitado a fornecer os valores dos parâmetros.

Em geral, não recomendamos o uso de parâmetros do AWS CloudFormation com o AWS CDK. As formas usuais de passar valores para aplicações do AWS CDK são [valores de contexto](context.md) e variáveis de ambiente. Como não estão disponíveis no momento da síntese, os valores dos parâmetros não podem ser facilmente usados para controle de fluxo e outras finalidades em sua aplicação CDK.

**nota**  
Para controlar o fluxo com parâmetros, você pode 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), embora isso seja estranho em comparação com declarações `if` nativas.

O uso de parâmetros exige que você esteja ciente de como o código que você está escrevendo se comporta no momento da implantação e também no momento da síntese. Isso torna mais difícil entender e raciocinar sobre sua aplicação do AWS CDK, em muitos casos com poucos benefícios.

Geralmente, é melhor que sua aplicação do CDK aceite as informações necessárias de uma forma bem definida e as use diretamente para declarar constructos em sua aplicação do CDK. Um modelo ideal do AWS CloudFormation gerado pelo AWS CDK é concreto, sem valores a serem especificados no momento da implantação.

Entretanto, existem casos de uso para os quais os parâmetros do AWS CloudFormation são exclusivamente adequados. Se você tiver equipes separadas definindo e implantando a infraestrutura, por exemplo, você pode usar parâmetros para tornar os modelos gerados mais amplamente úteis. Além disso, como o AWS CDK oferece suporte aos parâmetros do AWS CloudFormation, é possível usar o AWS CDK com serviços da AWS que usem modelos do AWS CloudFormation (como o Catálogo de Serviços). Esses serviços da AWS usam parâmetros para configurar o modelo que está sendo implantado.

## Saiba mais
<a name="parameters-learn"></a>

Para obter instruções sobre o desenvolvimento de aplicações do CDK com parâmetros, consulte [Uso de parâmetros do CloudFormation para obter um valor do CloudFormation](get-cfn-param.md).

# Tags e o AWS CDK
<a name="tagging"></a>

As tags são elementos de chave-valor informativos que podem ser adicionados aos constructos da sua aplicação do CDK da AWS. Uma tag aplicada a um determinado constructo também se aplica a todos os seus filhos que podem receber tags. As tags são incluídas no modelo sintetizado do AWS CloudFormation a partir da sua aplicação e aplicadas aos recursos AWS que ele implanta. É possível usar tags para identificar e categorizar os recursos para as seguintes finalidades:
+ Simplificando o gerenciamento
+ Alocação de custos
+ Controle de acesso
+ Quaisquer outros propósitos que você conceba

**dica**  
Para obter mais informações sobre como é possível usar tags com seus recursos da AWS, consulte [Práticas recomendadas para aplicação de tags em recursos da AWS](https://docs.aws.amazon.com/whitepapers/latest/tagging-best-practices/tagging-best-practices.html) no *Whitepaper da AWS*.

## Usar tags
<a name="tagging-use"></a>

A classe [Tags](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html) inclui o método estático `of()`, por meio do qual é possível adicionar ou remover tags do 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) aplica uma nova tag ao constructo fornecido e a todos os seus filhos.
+  [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) remove uma tag de um determinado constructo e de qualquer um de seus filhos, incluindo tags que um constructo secundário possa ter aplicado a si mesmo.

**nota**  
A aplicação de tags é implementada usando [Aspectos e o AWS CDK](aspects.md). Aspectos são uma forma de aplicar uma operação (como as tags) a todos os constructos em um determinado escopo.

O exemplo a seguir aplica a tag **key** com o valor **value** a um 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{})
```

O exemplo a seguir exclui a tag **key** de um 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{})
```

Se você estiver usando constructos `Stage`, aplique a tag no nível `Stage` ou abaixo. As tags não são aplicadas além dos limites `Stage`.

## Prioridades de tags
<a name="tagging-priorities"></a>

O AWS CDK aplica e remove tags recursivamente. Se houver conflitos, a operação de tag com a prioridade mais alta vence. (As prioridades são definidas usando a propriedade opcional `priority`.) Se as prioridades de duas operações forem as mesmas, a operação com tag mais próxima da parte inferior da árvore de constructo vence. Por padrão, a aplicação de uma tag tem uma prioridade de 100 (exceto as tags adicionadas diretamente a um recurso do AWS CloudFormation, que tem uma prioridade de 50). A prioridade padrão para remover uma tag é 200.

O seguinte aplica uma tag com prioridade de 300 a uma 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),
})
```

## Propriedades opcionais
<a name="tagging-props"></a>

As tags oferecem suporte ao [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 ajusta a forma como as tags são aplicadas ou removidas dos recursos. Todas as propriedades são opcionais.

 `applyToLaunchedInstances` (Python: `apply_to_launched_instances`)  
Disponível somente para add(). Por padrão, as tags são aplicadas às instâncias executadas em um grupo do Auto Scaling. Defina essa propriedade como **false** para ignorar instâncias iniciadas em um grupo do Auto Scaling.

 `includeResourceTypes`/`excludeResourceTypes` (Python: `include_resource_types`/`exclude_resource_types`)  
Use para manipular tags somente em um subconjunto de recursos, com base nos tipos de recursos do AWS CloudFormation. Por padrão, a operação é aplicada a todos os recursos na subárvore de constructo, mas isso pode ser alterado incluindo ou excluindo determinados tipos de recursos. Excluir tem precedência sobre incluir, se ambas forem especificadas.

 `priority`   
Use isso para definir a prioridade dessa operação em relação a outras operações `Tags.add()` e `Tags.remove()`. Valores mais altos têm precedência sobre valores mais baixos. O padrão é 100 para operações de adição (50 para tags aplicadas diretamente aos recursos do AWS CloudFormation) e 200 para operações de remoção.

O exemplo a seguir aplica a tag **tagname** com o valor **value** e a prioridade **100** aos recursos do tipo **AWS::Xxx::Yyy** no constructo. Ele não aplica a tag a instâncias lançadas em um grupo do Amazon EC2 Auto Scaling ou a recursos do tipo **AWS::Xxx::Zzz**. (Esses são espaços reservados para dois tipos de recursos arbitrários do AWS CloudFormation, mas 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),
})
```

O exemplo a seguir remove a tag **tagname** com prioridade **200** de recursos do tipo **AWS::Xxx::Yyy** no constructo, mas não de recursos do 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),
})
```

## Exemplo
<a name="tagging-example"></a>

O exemplo a seguir adiciona a tag chave **StackType** com o valor **TheBest** a qualquer recurso criado dentro do `Stack` chamado `MarketingSystem`. Em seguida, ele o remove novamente de todos os recursos, exceto das sub-redes VPC do Amazon EC2. O resultado é que somente as sub-redes têm a tag aplicada.

**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")},
})
```

O código a seguir obtém o mesmo resultado. Considere qual abordagem (inclusão ou exclusão) torna sua intenção mais clara.

**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")},
})
```

## Aplicar tags de constructos individuais
<a name="tagging-single"></a>

 `Tags.of(scope).add(key, value)` é a forma padrão de adicionar tags aos constructos no AWS CDK. Seu comportamento de caminhar em árvores, que aplica tags recursivamente todos os recursos que podem ter aplicação de tag sob um determinado escopo, é quase sempre o que você deseja. Às vezes, no entanto, você precisa aplicat tags a um constructo (ou constructos) específico e arbitrário.

Um desses casos envolve a aplicação de tags cujo valor é derivado de alguma propriedade do constructo que está tendo a aplicação de tag. A abordagem de aplicação de tags padrão aplica recursivamente a mesma chave e valor a todos os recursos correspondentes no escopo. No entanto, aqui o valor pode ser diferente para cada constructo com tags.

As tags são implementadas usando [aspectos](aspects.md), e o CDK chama o método `visit()` da tag para cada constructo sob o escopo que você especificou usando o `Tags.of(scope)`. Podemos chamar o `Tag.visit()` diretamente para aplicar uma tag a um único 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)
```

É possível marcar todos os constructos em um escopo, mas deixar que os valores das tags sejam derivados das propriedades de cada constructo. Para fazer isso, escreva um aspecto e aplique a tag no método `visit()` do aspecto, conforme mostrado no exemplo anterior. Em seguida, adicione o aspecto ao escopo desejado usando `Aspects.of(scope).add(aspect)`.

O exemplo a seguir aplica uma tag a cada recurso em uma pilha contendo o caminho do 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);
```

**dica**  
A lógica da marcação condicional, incluindo prioridades, tipos de recursos e assim por diante, é incorporada à classe `Tag`. É possível usar esses recursos ao aplicar tags a recursos arbitrários; a tag não é aplicada se as condições não forem atendidas. Além disso, a classe `Tag` só aplica tags em recursos aplicáveis, então você não precisa testar se um constructo pode ser aplicável antes de aplicar uma tag.

# Ativos e o CDK da AWS
<a name="assets"></a>

Os ativos são arquivos, diretórios ou imagens do Docker locais que podem ser agrupados em bibliotecas e aplicações do CDK da AWS. Por exemplo, um ativo pode ser um diretório que contenha o código do manipulador de uma função do AWS Lambda. Os ativos podem representar qualquer artefato de que a aplicação precise para operar.

O vídeo tutorial a seguir fornece uma visão geral abrangente dos ativos do CDK e explica como é possível usá-los em sua infraestrutura 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)


Você adiciona ativos por meio de APIs que são expostas por constructos da AWS específicos. Por exemplo, quando você define um 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), a propriedade [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) permite que você passe um [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) (diretório). `Function` usa ativos para agrupar o conteúdo do diretório e usá-lo para o código da função. Da mesma forma, [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) usa uma imagem do Docker criada a partir de um diretório local ao definir uma definição de tarefa do Amazon ECS.

## Ativos em detalhes
<a name="assets-details"></a>

Quando você se refere a um ativo na sua aplicação, o [conjunto de nuvem](deploy.md#deploy-how-synth-assemblies) que é sintetizado a partir da sua aplicação inclui informações de metadados com instruções para a CLI do CDK da AWS. As instruções incluem onde encontrar o ativo no disco local e que tipo de empacotamento executar com base no tipo de ativo, como um diretório para compactar (zip) ou uma imagem do Docker para compilar.

O CDK da AWS gera um hash de origem para ativos. Isso pode ser usado no momento da construção para determinar se o conteúdo de um ativo foi alterado.

Por padrão, o CDK da AWS cria uma cópia do ativo no diretório do conjunto de nuvem, cujo padrão é `cdk.out`, sob o hash de origem. Dessa forma, o conjunto de nuvem é independente, portanto, se for transferido para um host diferente para implantação, ele ainda poderá ser implantado. Consulte [Conjuntos de nuvem](deploy.md#deploy-how-synth-assemblies) para obter detalhes.

Quando o CDK da AWS implanta uma aplicação que faz referência a ativos (diretamente pelo código da aplicação ou por meio de uma biblioteca), a CLI do CDK da AWS primeiro prepara e publica os ativos em um bucket do Amazon S3 ou repositório do Amazon ECR. (O bucket do S3 ou o repositório é criado durante o bootstrapping.) Só então os recursos definidos na pilha são implantados.

Esta seção descreve as APIs de baixo nível disponíveis na estrutura.

## Tipos de ativo
<a name="assets-types"></a>

O CDK da AWS oferece suporte aos tipos de ativos a seguir:

Ativos do Amazon S3  
Esses são arquivos e diretórios locais que o CDK da AWS carrega no Amazon S3.

Imagem de docker  
Essas são imagens do Docker que o CDK da AWS carrega no Amazon ECR.

Esses tipos de ativos são explicados nas seguintes seções.

## Ativos do Amazon S3
<a name="assets-types-s3"></a>

É possível definir arquivos e diretórios locais como ativos. O CDK da AWS os empacota e transfere para o Amazon S3 por meio do 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).

O exemplo a seguir define um ativo de diretório local e um ativo de arquivo.

**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")),
})
```

Na maioria dos casos, não é preciso usar diretamente as APIs no módulo `aws-s3-assets`. Módulos que oferecem suporte a ativos, como `aws-lambda`, têm métodos convenientes para que você possa usar ativos. Para funções do Lambda, o 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 que você especifique um diretório ou um arquivo .zip no sistema de arquivos local.

### Exemplo de função do Lambda
<a name="assets-types-s3-lambda"></a>

Um caso de uso comum é criar funções do Lambda com o código do manipulador como um ativo do Amazon S3.

O exemplo a seguir usa um ativo do Amazon S3 para definir um manipulador do Python no do diretório local `handler`. Ele também cria uma função do Lambda com o ativo do diretório local como propriedade `code`. A seguir está o código do Python para o manipulador.

```
def lambda_handler(event, context):
  message = 'Hello World!'
  return {
    'message': message
  }
```

O código da aplicação principal do CDK da AWS será parecido com o seguinte:

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

O método `Function` usa ativos para empacotar o conteúdo do diretório e usá-lo para o código da função.

**dica**  
Os arquivos `.jar` do Java são arquivos ZIP com uma extensão diferente. Eles são carregados no estado em que se encontram no Amazon S3, mas quando implantados como uma função do Lambda, os arquivos que eles contêm são extraídos, o que pode ser indesejado. Para evitar isso, coloque o arquivo `.jar` em um diretório e especifique esse diretório como o ativo.

### Exemplo de atributos de tempo de implantação
<a name="assets-types-s3-deploy"></a>

Os tipos de ativos do Amazon S3 também expõem [atributos de tempo de implantação](resources.md#resources-attributes) que podem ser referenciados em bibliotecas e aplicações do CDK da AWS. O comando `cdk synth` da CLI do CDK da AWS exibe as propriedades do ativo como parâmetros do AWS CloudFormation.

O exemplo a seguir usa atributos de tempo de implantação para passar a localização de um ativo de imagem para uma função do Lambda como variáveis de ambiente. (O tipo de arquivo não importa; a imagem PNG usada aqui é apenas um exemplo.)

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

### Permissões
<a name="assets-types-s3-permissions"></a>

Se você usa ativos do Amazon S3 diretamente por meio do 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), grupos, usuários ou perfis do IAM, e precisa ler ativos em tempo de execução, conceda a esses ativos permissões do IAM por meio do 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).

O exemplo a seguir concede a um grupo do IAM permissões de leitura em um ativo de arquivo.

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

## Ativos de imagem do Docker
<a name="assets-types-docker"></a>

O CDK da AWS oferece suporte ao empacotamento de imagens locais do Docker como ativos por meio do 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).

O exemplo a seguir define uma imagem do Docker, que é criada localmente e enviada para o Amazon ECR. As imagens são criadas a partir de um diretório de contexto local do Docker (com um Dockerfile) e carregadas no Amazon ECR pela CLI do CDK da AWS ou pelo pipeline de CI/CD da sua aplicação. As imagens podem ser referenciadas naturalmente na sua aplicação do CDK da AWS.

**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")),
})
```

O diretório `my-image` deve incluir um Dockerfile. A CLI do CDK da AWS compila uma imagem do Docker a partir de `my-image`, envia-a para um repositório do Amazon ECR e especifica o nome do repositório como um parâmetro do AWS CloudFormation para sua pilha. Os tipos de ativos de imagem do Docker expõem [atributos de tempo de implantação](resources.md#resources-attributes) que podem ser referenciados em bibliotecas e aplicações do CDK da AWS. O comando `cdk synth` da CLI do CDK da AWS exibe as propriedades do ativo como parâmetros do AWS CloudFormation.

### Exemplo de definição de tarefa do Amazon ECS
<a name="assets-types-docker-ecs"></a>

Um caso de uso comum é criar uma [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) do Amazon ECS para executar contêineres do Docker. O exemplo a seguir especifica a localização de um ativo de imagem do Docker que o CDK da AWS compila localmente e envia para o 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),
})
```

### Exemplo de atributos de tempo de implantação
<a name="assets-types-docker-deploy"></a>

O exemplo a seguir mostra como usar os atributos de tempo de implantação `repository` e `imageUri` para criar uma definição de tarefa do Amazon ECS com o tipo de execução do AWS Fargate. Observe que a pesquisa do repositório do Amazon ECR exige a tag da imagem, não seu URI, então nós a recortamos do final do URI do ativo.

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

### Exemplo de argumentos de compilação
<a name="assets-types-docker-build"></a>

É possível fornecer argumentos de compilação personalizados para a etapa de compilação do Docker por meio da opção de propriedade `buildArgs` (Python: `build_args`) quando a CLI do CDK da AWS compila a imagem durante a implantação.

**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"),
  },
})
```

### Permissões
<a name="assets-types-docker-permissions"></a>

Se você usa um módulo com suporte a ativos de imagem do Docker, como o [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), o CDK da AWSgerencia as permissões quando você usa ativos diretamente ou por meio 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`). Se você usa ativos de imagem do Docker diretamente, verifique se a entidade principal de consumo tem permissão para extrair a imagem.

Na maioria dos casos, é necessário usar o 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`). Isso modifica a política do IAM da entidade principal para permitir que ela extraia imagens desse repositório. Se a entidade principal que está extraindo a imagem não estiver na mesma conta ou se for um serviço da AWS que não assume um perfil na sua conta (como o AWS CodeBuild), será necessário conceder permissões de extração na política de recursos e não na política da entidade principal. Use o 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 as permissões da entidade principal apropriadas.

## Metadados de recurso do AWS CloudFormation
<a name="assets-cfn"></a>

**nota**  
Esta seção é relevante somente para autores de constructos. Em determinadas situações, as ferramentas precisam saber que um determinado recurso do CFN está usando um ativo local. Por exemplo, é possível usar a CLI do AWS SAM para invocar funções do Lambda localmente para fins de depuração. Consulte [Integração do AWS SAM](tools.md#sam) para obter detalhes.

Para habilitar esses casos de uso, as ferramentas externas consultam um conjunto de entradas de metadados sobre recursos do AWS CloudFormation:
+  `aws:asset:path`: aponta para o caminho local do ativo.
+  `aws:asset:property`: o nome da propriedade do recurso em que o ativo é usado.

Usando essas duas entradas de metadados, as ferramentas podem identificar que os ativos são usados por um determinado recurso e permitir experiências locais avançadas.

Para adicionar essas entradas de metadados a um recurso, use o método `asset.addResourceMetadata` (Python :`add_resource_metadata`).

# Permissões e o AWS CDK
<a name="permissions"></a>

A AWS Construct Library usa alguns idiomas comuns e amplamente implementados para gerenciar o acesso e as permissões. O módulo IAM fornece as ferramentas necessárias para usar essas linguagens.

 AWS O CDK usa AWS CloudFormation para implantar mudanças. Cada implantação envolve um ator (um desenvolvedor ou um sistema automatizado) que inicia uma AWS CloudFormation implantação. Ao fazer isso, o ator assumirá uma ou mais identidades do IAM (usuário ou funções) e, opcionalmente, passará uma função para. AWS CloudFormation

Se você usa o AWS IAM Identity Center para se autenticar como usuário, o provedor de login único fornece credenciais de sessão de curta duração que autorizam você a atuar como uma função predefinida do IAM. Para saber como o AWS CDK obtém AWS credenciais da autenticação do IAM Identity Center, consulte [Entenda a autenticação do IAM Identity Center no Guia](https://docs.aws.amazon.com/sdkref/latest/guide/understanding-sso.html) de referência * AWS SDKs de ferramentas*.

## Entidades principais
<a name="permissions-principals"></a>

Um principal do IAM é uma AWS entidade autenticada que representa um usuário, serviço ou aplicativo que pode chamar AWS APIs. A AWS Construct Library suporta a especificação de diretores de várias maneiras flexíveis para permitir que eles acessem seus AWS recursos.

Em contextos de segurança, o termo “entidade principal” se refere especificamente a entidades autenticadas, como usuários. Objetos como grupos e perfis não *representam* usuários (e outras entidades autenticadas), mas os *identificam* indiretamente com o objetivo de conceder permissões.

Por exemplo, se você criar um grupo do IAM, poderá conceder ao grupo (e, portanto, a seus membros) acesso de gravação a uma tabela do Amazon RDS. No entanto, o grupo em si não é uma entidade principal porque não representa uma única entidade (além disso, você não pode fazer login em um grupo).

Na biblioteca do IAM do CDK, classes que identificam direta ou indiretamente as entidades principais implementam a interface [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), permitindo que esses objetos sejam usados de forma intercambiável nas políticas de acesso. No entanto, nem todos são entidades principais no sentido de segurança. Esses objetos incluem:

1. Recursos do 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) e [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 principais de serviço (`new iam.[ServicePrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ServicePrincipal.html)('service.amazonaws.com')`)

1. Entidades principais 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. Diretores da conta () `new iam.[AccountPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.AccountPrincipal.html)('0123456789012')`

1. Entidades principais de usuários canônicos (`new iam.[CanonicalUserPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.CanonicalUserPrincipal.html)('79a59d[…​]7ef2be')`)

1.  AWS Diretores de organizações () `new iam.[OrganizationPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.OrganizationPrincipal.html)('org-id')`

1. Entidades principais arbitrárias do ARN (`new iam.[ArnPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ArnPrincipal.html)(res.arn)`)

1. Um `iam.[CompositePrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.CompositePrincipal.html)(principal1, principal2, …​)` para confiar em várias entidades principais

## Concessões
<a name="permissions-grants"></a>

Muitas construções representam recursos que podem ser acessados, como um bucket do Amazon S3 ou uma tabela do Amazon DynamoDB. Para eles, você pode conceder acesso a outra entidade. **Há duas maneiras de fazer isso, dependendo da construção específica: usando a classe Grants correspondente (por exemplo, `BucketGrants` para buckets do Amazon S3) ou usando métodos na própria construção, que têm nomes começando com grant.** O primeiro é preferido porque pode ser usado para conceder acesso aos recursos L1 e L2 da mesma forma. Para criar uma instância de uma classe Grants, use seu 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)
```

As classes Grants fornecem métodos para conceder permissões específicas para acessar seus recursos. Por exemplo, `BucketGrants` tem métodos `read` e `readWrite` (Python:`read`,`read_write`) para permitir a leitura e o read/write acesso, respectivamente, de uma entidade ao bucket. A entidade não precisa saber exatamente quais permissões do Amazon S3 IAM são necessárias para realizar essas operações.

O primeiro argumento dos métodos em uma classe Grants (ou dos métodos de **concessão** nos próprios recursos) é sempre do 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). Essa interface representa entidades que podem receber permissões. Ou seja, ela representa recursos com perfis, como os objetos do 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) e [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).

Outras entidades também podem receber permissões. Por exemplo, mais adiante neste tópico, mostraremos como conceder a um CodeBuild projeto acesso a um bucket do Amazon S3. Geralmente, o perfil associado é obtido por meio de uma propriedade `role` na entidade que está recebendo acesso.

Recursos que usam perfis de execução, como o [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), também implementam `IGrantable`, para que você possa conceder acesso direto a eles em vez de conceder acesso ao perfil deles. Por exemplo, se `bucket` for um bucket do Amazon S3 e `function` for uma função do Lambda, o código a seguir concede à função acesso de leitura ao bucket.

Por conveniência, as construções L2 também oferecem uma `grants` propriedade que retorna uma instância da classe Grants correspondente.

**Example**  

```
bucket.grants.read(function);
```

```
bucket.grants.read(function);
```

```
bucket.grants.read(function)
```

```
bucket.getGrants().read(function);
```

```
bucket.Grants.Read(function);
```

Às vezes, as permissões precisam ser aplicadas enquanto sua pilha está sendo implantada. Um desses casos é quando você concede a um recurso AWS CloudFormation personalizado acesso a algum outro recurso. O recurso personalizado será invocado durante a implantação, portanto, ele deve ter as permissões especificadas no momento da implantação.

Outro caso é quando um serviço verifica se o perfil que você passa para ele tem as políticas corretas aplicadas. (Vários AWS serviços fazem isso para garantir que você não se esqueça de definir as políticas.) Nesses casos, a implantação pode falhar se as permissões forem aplicadas tarde demais.

Para forçar a aplicação das permissões da concessão antes da criação de outro recurso, é possível adicionar uma dependência da concessão em si, conforme mostrado aqui. Embora o valor de retorno dos métodos de concessão seja geralmente descartado, todo método de concessão na verdade retorna um 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);
```

## Perfis
<a name="permissions-roles"></a>

O pacote do IAM contém um 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 os perfis do IAM. O código a seguir cria uma nova função, confiando no EC2 serviço da 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
});
```

É possível adicionar permissões a um perfil chamando o 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) do perfil (Python: `add_to_policy`), passando um [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 define a regra a ser adicionada. A declaração será adicionada à política padrão do perfil. Se não houver nenhuma, uma será criada.

O exemplo a seguir adiciona uma declaração de política `Deny` ao perfis para as ações `ec2:SomeAction` e `s3:AnotherAction` dos recursos `bucket` e `otherRole` (Python: `other_role`), sob a condição de que o serviço autorizado seja 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"
        }
    }
}));
```

No exemplo anterior, criamos uma nova linha [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) com a chamada [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`). Você também pode passar uma declaração de política existente ou uma que você tenha modificado. O 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) possui [vários métodos](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html#methods) para adicionar entidades principais, recursos, condições e ações.

Se você estiver usando um constructo que requer um perfil para funcionar corretamente, é possível executar uma das ações a seguir:
+ Passar um perfil existente ao instanciar o objeto de constructo.
+ Deixar que o constructo crie um novo perfil para você, confiando na entidade principal de serviço apropriada. O exemplo a seguir usa essa construção: um CodeBuild projeto.

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

Depois que o objeto é criado, o perfil (seja o perfil passado ou o padrão criado pelo constructo) fica disponível como a propriedade `role`. No entanto, essa propriedade não está disponível em recursos externos. Portanto, esses constructos têm um método `addToRolePolicy` (Python: `add_to_role_policy`).

O método não faz nada se o constructo for um recurso externo e, caso contrário, chama o método `addToPolicy` (Python: `add_to_policy`) da propriedade `role`. Isso evita que você precise lidar com o caso indefinido de forma explícita.

O exemplo a seguir demonstra:

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

Alguns recursos AWS, como buckets do Amazon S3 e funções do IAM, também têm uma política de recursos. Esses constructos possuem um método `addToResourcePolicy` (Python: `add_to_resource_policy`), que usa uma [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 declaração de política adicionada a uma política de recursos deve especificar pelo menos uma entidade principal.

No exemplo a seguir, o [bucket do Amazon S3](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) concede ao `bucket` um perfil com a permissão `s3:SomeAction` para si mesmo.

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

## Usando objetos externos do IAM
<a name="permissions-existing"></a>

Se você definiu um usuário, diretor, grupo ou função do IAM fora do seu aplicativo AWS CDK, você pode usar esse objeto do IAM em seu aplicativo AWS CDK. Para fazer isso, crie uma referência a ele usando seu ARN ou seu nome. (Use o nome para usuários, grupos e perfis.) A referência retornada pode então ser usada para conceder permissões ou criar declarações de política, conforme explicado anteriormente.
+ Para usuários, chame [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) ou [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()` também está disponível, mas atualmente fornece a mesma funcionalidade que `User.fromUserArn()`.
+ Para as entidades principais, instancie um 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, chame [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) ou [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 perfis, chame [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) ou [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).

As políticas (incluindo políticas gerenciadas) podem ser usadas de forma semelhante usando os métodos a seguir. É possível usar referências a esses objetos em qualquer lugar em que uma política do IAM seja necessária.
+  [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 acontece com todas as referências a AWS recursos externos, você não pode modificar objetos externos do IAM em seu aplicativo CDK.

# Valores de contexto e o AWS CDK
<a name="context"></a>

Os valores de contexto são pares de chave-valor que podem ser associados a uma aplicação, pilha ou construct. Eles podem ser fornecidos à sua aplicação a partir de um arquivo (geralmente `cdk.json` ou `cdk.context.json` no diretório do projeto) ou na linha de comando.

O CDK Toolkit usa contexto para armazenar em cache os valores recuperados da sua AWS conta durante a síntese. Os valores incluem as zonas de disponibilidade na sua conta ou os IDs da imagem de máquina da Amazon (AMI) atualmente disponíveis para instâncias do Amazon EC2. Como esses valores são fornecidos pela sua AWS conta, eles podem mudar entre as execuções do seu aplicativo CDK. Isso os torna uma fonte potencial de mudanças não intencionais. O comportamento de armazenamento em cache do Kit de Ferramentas CDK "congela" esses valores em sua aplicação do CDK até que você decida aceitar os novos valores.

Imagine o cenário a seguir sem o armazenamento em cache do contexto. Digamos que você tenha especificado “Amazon Linux mais recente” como a AMI para suas instâncias do Amazon EC2 e uma nova versão dessa AMI foi lançada. Então, na próxima vez que você implantasse sua pilha do CDK, suas instâncias já implantadas usariam a AMI desatualizada (“errada”) e precisariam ser atualizadas. A atualização resultaria na substituição de todas as suas instâncias existentes por novas, o que provavelmente seria inesperado e indesejado.

Em vez disso, o CDK registra a disponibilidade da sua conta AMIs no `cdk.context.json` arquivo do seu projeto e usa o valor armazenado para futuras operações de síntese. Dessa forma, a lista de não AMIs é mais uma fonte potencial de mudança. Você também pode ter certeza de que suas pilhas sempre serão sintetizadas nos mesmos modelos. AWS CloudFormation 

Nem todos os valores de contexto são valores armazenados em cache do seu AWS ambiente. Os [AWS sinalizadores de atributos do CDK](featureflags.md) também são valores de contexto. Você também pode criar seus próprios valores de contexto para uso pelos suas aplicações ou constructos.

As chaves de contexto são strings. Os valores podem ser de qualquer tipo compatível com o JSON: números, strings, matrizes ou objetos.

**dica**  
Se seus constructos criarem seus próprios valores de contexto, incorpore o nome do pacote da sua biblioteca em suas chaves para que não entrem em conflito com os valores de contexto de outros pacotes.

Muitos valores de contexto estão associados a um AWS ambiente específico, e um determinado aplicativo CDK pode ser implantado em mais de um ambiente. A chave para esses valores inclui a AWS conta e a região, para que os valores de diferentes ambientes não entrem em conflito.

A chave de contexto a seguir ilustra o formato usado pelo AWS CDK, incluindo a conta e a região.

```
availability-zones:account=123456789012:region=eu-central-1
```

**Importante**  
Os valores de contexto em cache são gerenciados pelo AWS CDK e suas construções, incluindo construções que você pode escrever. Não adicione nem altere valores de contexto armazenados em cache editando arquivos manualmente. No entanto, pode ser útil revisar `cdk.context.json` ocasionalmente para ver quais valores estão sendo armazenados em cache. Os valores de contexto que não representam valores armazenados em cache devem ser armazenados sob a chave `context` de `cdk.json`. Dessa forma, eles não serão apagados quando os valores armazenados em cache forem limpos.

## Fontes de valores de contexto
<a name="context-construct"></a>

Os valores de contexto podem ser fornecidos ao seu aplicativo AWS CDK de seis maneiras diferentes:
+ Automaticamente da AWS conta corrente.
+ Através da opção `--context` para o comando `cdk`. (Esses valores são sempre strings.)
+ No arquivo `cdk.context.json` do projeto.
+ Na chave `context` do arquivo `cdk.json` do projeto.
+ Na chave `context` do seu arquivo `~/.cdk.json`.
+ Em seu aplicativo AWS CDK usando o `construct.node.setContext()` método.

O arquivo do projeto `cdk.context.json` é onde o AWS CDK armazena em cache os valores de contexto recuperados da sua conta. AWS Essa prática evita mudanças inesperadas em suas implantações quando, por exemplo, uma nova zona de disponibilidade é introduzida. O AWS CDK não grava dados de contexto em nenhum dos outros arquivos listados.

**Importante**  
Como eles fazem parte do estado da sua aplicação, `cdk.json` e `cdk.context.json` devem estar comprometidos com o controle da fonte junto com o restante do código-fonte da sua aplicação. Caso contrário, implantações em outros ambientes (por exemplo, um pipeline de CI) podem produzir resultados inconsistentes.

Os valores de contexto têm como escopo o constructo que os criou; eles são visíveis para constructos secundários, mas não para principais ou irmãos. Os valores de contexto definidos pelo AWS CDK Toolkit (o `cdk` comando) podem ser definidos automaticamente, a partir de um arquivo ou da `--context` opção. Os valores de contexto dessas fontes são definidos implicitamente no constructo do `App`. Portanto, eles são visíveis para todos os constructos em todas as pilhas da aplicação.

Seu aplicação pode ler um valor de contexto usando o método `construct.node.tryGetContext`. Se a entrada solicitada não for encontrada no constructo atual ou em qualquer um de seus principais, o resultado será `undefined`. (Como alternativa, o resultado pode ser equivalente à sua linguagem, como `None` no Python.)

## Métodos de contexto
<a name="context-methods"></a>

O AWS CDK oferece suporte a vários métodos de contexto que permitem que os aplicativos AWS CDK obtenham informações contextuais do ambiente. AWS Por exemplo, você pode obter uma lista de zonas de disponibilidade que estão disponíveis em uma determinada AWS conta e região usando o [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)método.

A seguir estão os métodos de contexto:

 [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)   
Obtém as zonas hospedadas em sua conta.

 [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)   
Obtém as zonas de disponibilidade compatíveis.

 [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)   
Obtém um valor do armazenamento do Amazon EC2 Systems Manager Parameter Store da região atual.

 [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)   
Obtém as nuvens privadas virtuais da Amazon existentes em suas contas.

 [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)   
Pesquisa uma imagem de máquina para uso com uma instância NAT na nuvem privada virtual da Amazon.

Se um valor de contexto necessário não estiver disponível, o aplicativo AWS CDK notifica o CDK Toolkit de que as informações de contexto estão ausentes. Em seguida, a CLI consulta as informações na AWS conta atual e armazena as informações de contexto resultantes no arquivo. `cdk.context.json` Em seguida, ele executa o aplicativo AWS CDK novamente com os valores de contexto.

## Visualizar e gerenciar o contexto
<a name="context-viewing"></a>

Use o comando `cdk context` para visualizar e gerenciar as informações em seu arquivo `cdk.context.json`. Para ver essas informações, use o comando `cdk context` sem nenhuma opção. A saída deve ser semelhante ao seguinte.

```
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 remover um valor de contexto, execute `cdk context --reset`, especificando a chave ou o número correspondente do valor. O exemplo a seguir remove o valor que corresponde à segunda chave no exemplo anterior. Esse valor representa a lista de zonas de disponibilidade na região 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.
```

Portanto, se você quiser atualizar para a versão mais recente do Amazon Linux AMI, use o exemplo anterior para fazer uma atualização controlada do valor do contexto e redefini-lo. Em seguida, sintetize e implante sua aplicação novamente.

```
$ cdk synth
```

Para limpar todos os valores de contexto armazenados para sua aplicação, execute `cdk context --clear` da seguinte maneira.

```
$ cdk context --clear
```

Somente os valores de contexto armazenados em `cdk.context.json` podem ser redefinidos ou apagados. O AWS CDK não toca em outros valores de contexto. Portanto, para evitar que um valor de contexto seja redefinido usando esses comandos, você pode copiar o valor para `cdk.json`.

## AWS Bandeira do CDK Toolkit `--context`
<a name="context-cli"></a>

Use a opção `--context` (`-c` abreviada) para passar valores de contexto de runtime para sua aplicação do CDK durante a síntese ou a implantação.

```
$ cdk synth --context key=value MyStack
```

Para especificar vários valores de contexto, repita a opção `--context` quantas vezes quiser, fornecendo um par de chave-valor a cada vez.

```
$ cdk synth --context key1=value1 --context key2=value2 MyStack
```

Ao sintetizar várias pilhas, os valores de contexto especificados são passados para todas as pilhas. Para fornecer valores de contexto diferentes para pilhas individuais, use chaves diferentes para os valores ou use vários comandos `cdk synth` ou `cdk deploy`.

Os valores de contexto passados da linha de comando são sempre strings. Se um valor geralmente é de algum outro tipo, seu código deve estar preparado para converter ou analisar o valor. É possível ter valores de contexto que não sejam de string fornecidos de outras formas (por exemplo, em `cdk.context.json`). Para garantir que esse tipo de valor funcione conforme o esperado, confirme se o valor é uma string antes de convertê-lo.

## Exemplo
<a name="context-example"></a>

Veja a seguir um exemplo do uso de uma Amazon VPC existente usando o contexto 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()
        });
    }
}
```

É possível usar `cdk diff` para ver os efeitos da transmissão de um valor de contexto na linha de comando:

```
$ cdk diff -c vpcid=vpc-0cb9c31031d0d3e22
```

```
Stack ExistsvpcStack
Outputs
[+] Output publicsubnets publicsubnets: {"Value":"subnet-06e0ea7dd302d3e8f,subnet-01fc0acfb58f3128f"}
```

Os valores de contexto resultantes podem ser visualizados conforme mostrado aqui.

```
$ 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"
    ]
  }
}
```

# Sinalizadores de atributo do AWS CDK
<a name="featureflags"></a>

O AWS CDK usa *sinalizadores de atributos* para habilitar comportamentos potencialmente incorretos em uma versão. Os sinalizadores são armazenados como [valores de contexto e valores do AWS CDK](context.md) em `cdk.json` (ou `~/.cdk.json`). Eles não são removidos pelos comandos `cdk context --reset` ou `cdk context --clear`.

Sinalizadores de atributo são desabilitados por padrão. Os projetos existentes que não especifiquem o sinalizador continuarão funcionando como antes nas versões posteriores do AWS CDK. Novos projetos criados usando `cdk init` incluem sinalizadores que habilitam todos os atributos disponíveis na versão que criou o projeto. Edite o `cdk.json` para desativar todos os sinalizadores para os quais você prefere o comportamento anterior. Você também pode adicionar sinalizadores para ativar novos comportamentos após a atualização do AWS CDK.

Uma lista de todos os sinalizadores de atributos atuais pode ser encontrada no repositório do GitHub do AWS CDK em [FEATURE\$1FLAGS.md](https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md). Consulte `CHANGELOG` em uma determinada versão para obter uma descrição de quaisquer novos sinalizadores de atributos adicionados nessa versão.

## Revertendo para o comportamento v1
<a name="featureflags-disabling"></a>

No CDK v2, os padrões de alguns sinalizadores de atributos foram alterados em relação à v1. É possível configurá-los novamente para reverter o `false` para um comportamento específico do AWS CDK v1. Use o comando `cdk diff` para inspecionar as alterações em seu modelo sintetizado e ver se algum desses sinalizadores é necessário.

 `@aws-cdk/core:newStyleStackSynthesis`   
Use o novo método de síntese de pilha, que pressupõe recursos de inicialização com nomes conhecidos. Requer uma [inicialização moderna](bootstrapping.md), mas, por sua vez, permite CI/CD via [CDK Pipelines](cdk-pipeline.md) e implantações entre contas prontas para uso.

 `@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId`   
Se sua aplicação usa várias chaves de API do Amazon API Gateway e as associa aos planos de uso.

 `@aws-cdk/aws-rds:lowercaseDbIdentifier`   
Se sua aplicação usa uma instância de banco de dados ou clusters de banco de dados do Amazon RDS e especifica explicitamente o identificador para eles.

 `@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021`   
Se a sua aplicação usar a política de segurança TLS\$1V1\$12\$12019 com distribuições do Amazon CloudFront. O CDK v2 usa a política de segurança TLSv1.2\$12021 por padrão.

 `@aws-cdk/core:stackRelativeExports`   
Se a sua aplicação usar várias pilhas e você se refere aos recursos de uma pilha em outra, isso determina se o caminho absoluto ou relativo é usado para criar exportações do AWS CloudFormation.

 `@aws-cdk/aws-lambda:recognizeVersionProps`   
Se definido como `false`, o CDK inclui metadados ao detectar se uma função do Lambda foi alterada. Isso pode causar falhas na implantação quando somente os metadados são alterados, já que versões duplicadas não são permitidas. Não há necessidade de reverter esse sinalizador se você tiver feito pelo menos uma alteração em todas as funções do Lambda em sua aplicação.

A sintaxe para reverter esses sinalizadores `cdk.json` é mostrada aqui.

```
{
  "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 e o AWS CDK
<a name="aspects"></a>

Aspectos são uma forma de aplicar uma operação a todos os constructos em um determinado escopo. O aspecto pode modificar os constructos, por exemplo, adicionando tags. Ou pode verificar algo sobre o estado dos constructos, como garantir que todos os buckets estejam criptografados.

Para aplicar um aspecto a um constructo e a todos os constructos no mesmo escopo, chame ` [Aspects](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Aspects.html#static-ofscope).of(<SCOPE>).add()` com um novo aspecto, conforme mostrado no exemplo a seguir.

**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(...))
```

O AWS CDK usa aspectos para [marcar recursos](tagging.md), mas a estrutura também pode ser usada para outras finalidades. Por exemplo, você pode usá-lo para validar ou alterar os AWS CloudFormation recursos definidos para você por construções de nível superior.

## Aspectos versus misturas
<a name="aspects-vs-mixins"></a>

Tanto os Aspects quanto os [Mixins](mixins.md) modificam construções, mas diferem em quando e como são aplicados:


| Recurso | Aspectos | Misturas | 
| --- | --- | --- | 
|   **Quando aplicado**   |  Durante a síntese, após a execução de todos os outros códigos.  |  Imediatamente quando `.with()` é chamado.  | 
|   **Escopo**   |  Todas as construções em um determinado escopo, incluindo construções adicionadas posteriormente.  |  Somente as construções às quais você as aplica explicitamente.  | 
|   **Style (Estilo)**   |  Declarativo — você define uma regra e o CDK a aplica.  |  Imperativo — você escolhe o que aplicar e onde.  | 
|   **Melhor para**   |  Validação, conformidade, marcação, políticas amplas.  |  Adicionar recursos específicos a recursos individuais.  | 

Use Aspects quando quiser aplicar regras em todo o aplicativo ou validar se as construções atendem a determinados critérios. Use Mixins quando quiser adicionar um recurso específico a uma construção específica.

Aspects e Mixins podem ser usados juntos. Por exemplo, você pode usar o Mixins para configurar recursos e aspectos individuais para validar se todos os recursos em uma pilha atendem aos requisitos de segurança da sua organização.

## Aspectos em detalhes
<a name="aspects-detail"></a>

Os aspectos empregam o [padrão do visitante](https://en.wikipedia.org/wiki/Visitor_pattern). Um aspecto é uma classe que implementa a interface a seguir.

**Example**  

```
interface IAspect {
   visit(node: IConstruct): void;}
```
JavaScript não tem interfaces como recurso de linguagem. Portanto, um aspecto é simplesmente uma instância de uma classe com um método `visit` que aceita o nó no qual ele será operado.
O Python não tem interfaces como atributo de linguagem. Portanto, um aspecto é simplesmente uma instância de uma classe com um método `visit` que aceita o nó no qual ele será operado.

```
public interface IAspect {
    public void visit(Construct node);
}
```

```
public interface IAspect
{
    void Visit(IConstruct node);
}
```

```
type IAspect interface {
  Visit(node constructs.IConstruct)
}
```

Quando você chama `Aspects.of(<SCOPE>).add(…​)`, o constructo adiciona o aspecto a uma lista interna de aspectos. É possível obter a lista com `Aspects.of(<SCOPE>)`.

Durante a [fase de preparação](deploy.md#deploy-how-synth-app), o AWS CDK chama o `visit` método do objeto para a construção e cada um de seus filhos na ordem de cima para baixo.

O método `visit` é livre para alterar qualquer coisa no constructo. Em linguagens de tipagem forte, converta o constructo recebido em um tipo mais específico antes de acessar propriedades ou métodos específicos do constructo.

Os aspectos não se propagam além dos limites do constructo `Stage`, porque `Stages` são independentes e imutáveis após a definição. Aplique aspectos no constructo `Stage` em si (ou inferior) se quiser que eles visitem constructos dentro do `Stage`.

## Exemplo
<a name="aspects-example"></a>

O exemplo a seguir confirma que todos os buckets criados na pilha têm o versionamento ativado. O aspecto adiciona uma anotação de erro aos constructos que falham na validação. Isso resulta na falha da operação `synth` e impede a implantação do conjunto de nuvem 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());
```