

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

# Implantação de aplicações do AWS CDK
<a name="deploy"></a>

Uma implantação do kit de desenvolvimento em nuvem da AWS (CDK da AWS) é o processo de provisionamento de sua infraestrutura na AWS.

## Como funcionam as implantações do AWS CDK
<a name="deploy-how"></a>

O AWS CDK utiliza o serviço do AWS CloudFormation para realizar implantações. Antes de implantar, você sintetiza suas pilhas do CDK. Isso cria um modelo do CloudFormation e artefatos de implantação para cada pilha do CDK em sua aplicação. As implantações são iniciadas a partir de uma máquina de desenvolvimento local ou a partir de um *ambiente de integração e entrega contínuas (CI/CD)*. Durante a implantação, os ativos são enviados para os recursos que receberam o bootstrapping e o modelo do CloudFormation é enviado ao CloudFormation para provisionar seus recursos da AWS.

Para que uma implantação seja bem-sucedida, é necessário o seguinte:
+ A interface de linha de comandos do AWS CDK (CLI do AWS CDK) deve ser fornecida com permissões válidas.
+ O ambiente da AWS deve ser receber o bootstrapping.
+ O AWS CDK deve conhecer os recursos que receberam o bootstrapping para os quais o caregamento de ativos é feito.

## Pré-requisitos para implantações do CDK
<a name="deploy-prerequisites"></a>

Antes de implantar uma aplicação do AWS CDK, é necessário concluir as etapas a seguir:
+ Configure as credenciais de segurança para a CLI do CDK.
+ Faça o bootstrapping em seu ambiente da AWS.
+ Configure um ambiente da AWS para cada uma das suas pilhas do CDK.
+ Desenvolva sua aplicação do CDK.<a name="deploy-prerequisites-creds"></a>

 **Configurar credenciais de segurança**   
Para usar a CLI do CDK para interagir com a AWS, é necessário configurar as credenciais de segurança em seu computador local. Para obter instruções, consulte [Configuração de credenciais de segurança para a CLI do AWS CDK](configure-access.md).<a name="deploy-prerequisites-bootstrap"></a>

 **Faça o bootstrapping do seu ambiente da AWS**   
Uma implantação está sempre associada a um ou mais [ambientes](environments.md) da AWS. Antes de implantar, o ambiente deve primeiro receber o [bootstrapping](bootstrapping.md). O bootstrapping provisiona recursos em seu ambiente que o CDK usa para realizar e gerenciar implantações. Esses recursos incluem um bucket do Amazon Simple Storage Service (Amazon S3) e um repositório do Amazon Elastic Container Registry (Amazon ECR) para armazenar e gerenciar [ativos](assets.md). Esses recursos também incluem perfils do AWS AWS Identity and Access Management (IAM) que são usados para fornecer permissões durante o desenvolvimento e a implantação.  
Recomendamos que você use o comando `cdk bootstrap` da interface de linha de comandos do AWS CDK (CLI do AWS CDK) para fazer bootstrapping em seu ambiente. É possível personalizar o bootstrapping ou criar manualmente esses recursos em seu ambiente, se necessário. Para obter instruções, consulte [Bootstrapping do seu ambiente para uso com o AWS CDK](bootstrapping-env.md).<a name="deploy-prerequisites-env"></a>

 **Configuração dos ambientes da AWS**   
Cada pilha do CDK deve estar associada a um ambiente para determinar onde a pilha é implantada. Para obter instruções, consulte [Configuração de ambientes para uso com o AWS CDK](configure-env.md).<a name="deploy-prerequisites-develop"></a>

 **Desenvolver sua aplicação do CDK**   
Em um [projeto](projects.md) do CDK, você cria e desenvolve sua aplicação do CDK. Na sua aplicação, você cria uma ou mais [pilhas](stacks.md) do CDK. Em suas pilhas, você importa e usa [constructos](constructs.md) da Biblioteca de Constructos da AWS para definir sua infraestrutura. Antes que você possa implantar, sua aplicação CDK deve conter pelo menos uma pilha.

## Síntese da aplicação CDK
<a name="deploy-how-synth"></a>

Para realizar a síntese, recomendamos que você use o comando `cdk synth` da CLI do CDK. O comando `cdk deploy` também realizará a síntese antes de iniciar a implantação. No entanto, ao usar o `cdk synth`, você pode validar sua aplicação do CDK e detectar erros antes de iniciar a implantação.

O comportamento da síntese é determinado pelo [sintetizador de pilha](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html#stack-synthesizers) que você configura para sua pilha do CDK. Se você não configurar um sintetizador, ` [DefaultStackSynthesizer](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.DefaultStackSynthesizer.html) ` será usado. Você também pode configurar e personalizar a síntese para atender às suas necessidades. Para obter instruções, consulte [Configuração e realização da síntese de pilhas do CDK](configure-synth.md).

Para que seu modelo sintetizado do CloudFormation seja implantado em seu ambiente com êxito, ele deve ser compatível com a forma como seu ambiente recebeu o bootstrapping. Por exemplo, seu modelo do CloudFormation deve especificar o bucket correto do Amazon S3 no qual implantar ativos. Se você usar o método padrão de inicializar seu ambiente, o sintetizador de pilha padrão funcionará. Se você personalizar o comportamento do CDK, como personalizar o bootstrapping ou a síntese, o comportamento de implantação do CDK poderá variar.<a name="deploy-how-synth-app"></a>

 **O ciclo de vida da aplicação**   
Quando você realiza a síntese, sua aplicação do CDK passa pelas seguintes fases, conhecidas como *ciclo de vida da aplicação*:    
 **Construção (ou inicialização)**   
Seu código instancia todos os constructos definidos e, em seguida, vincula-os. Nesse estágio, todos os constructos (aplicação, pilhas e seus constructos secundários) são instanciados e a cadeia de construtores é executada. A maior parte do código da sua aplicação é executada nesse estágio.  
 **Preparação**   
Todos os constructos que implementaram o método `prepare` participam de uma rodada final de modificações, para configurar seu estado final. A fase de preparação acontece automaticamente. Como usuário, você não vê nenhum feedback dessa fase. É raro precisar usar o hook de “preparação”, e geralmente não é recomendado. Tenha muito cuidado ao alterar a árvore de constructos durante essa fase, pois a ordem das operações pode afetar o comportamento.  
Durante essa fase, depois que a árvore de constructos for construída, todos os [aspectos](aspects.md) que você configurou também serão aplicados.  
 **Validação**   
Todos os constructos que implementaram o método `validate` podem validar a si mesmos para garantir que estejam em um estado que será implantado corretamente. Você será notificado sobre quaisquer falhas de validação que ocorram durante essa fase. Geralmente, recomendamos a realização da validação o mais rápido possível (geralmente assim que você receber alguma informação) e o lançamento de exceções o mais rápido possível. A validação antecipada melhora a confiabilidade, pois os rastreamentos de pilha serão mais precisos e garantirão que seu código possa continuar sendo executado com segurança.  
 **Síntese**   
Esse é o estágio final da execução da sua aplicação do CDK. É acionado por uma chamada para `app.synth()`, percorre a árvore de constructos e invoca o método `synthesize` em todos os constructos. Os constructos que implementam `synthesize` podem participar da síntese e produzir artefatos de implantação no conjunto de nuvem resultante. Esses artefatos incluem modelos do CloudFormation, pacotes de aplicações do AWS Lambda, ativos de arquivos e imagens do Docker e outros artefatos de implantação. Na maioria dos casos, não é preciso implementar o método `synthesize`.<a name="deploy-how-synth-run"></a>

 **Executar sua aplicação**   
A CLI do CDK precisa saber como executar sua aplicação do CDK. Se você criou o projeto a partir de um modelo usando o comando `cdk init`, o arquivo `cdk.json` da sua aplicação inclui uma chave `app`. Essa chave especifica o comando necessário para a linguagem em que a aplicação está escrita. Se sua linguagem exigir compilação, a linha de comando executará essa etapa antes de executar a aplicação automaticamente.  

**Example**  

```
{
  "app": "npx ts-node --prefer-ts-exts bin/my-app.ts"
}
```

```
{
  "app": "node bin/my-app.js"
}
```

```
{
    "app": "python app.py"
}
```

```
{
  "app": "mvn -e -q compile exec:java"
}
```

```
{
  "app": "dotnet run -p src/MyApp/MyApp.csproj"
}
```

```
{
  "app": "go mod download && go run my-app.go"
}
```
Se você não criou seu projeto usando a CLI do CDK, ou se quiser substituir a linha de comando fornecida em `cdk.json`, é possível inserir a opção ` --app ` ao executar o comando `cdk`.

```
$ cdk --app '<executable>' <cdk-command> ...
```

A parte `<executable>` do comando indica o comando que deve ser emitido para executar sua aplicação do CDK. Use aspas conforme mostrado, pois esses comandos contêm espaços. O `<cdk-command>` é um subcomando, como `synth` ou `deploy`, que informa à CLI do CDK o que você quer fazer com sua aplicação. Siga isso com todas as opções adicionais necessárias para esse subcomando.

A CLI do CDK também pode interagir diretamente com um conjunto de nuvem já sintetizado. Para fazer isso, passe o diretório no qual o conjunto de nuvem está armazenado em `--app`. O exemplo a seguir lista as pilhas definidas no conjunto de nuvem armazenado em `./my-cloud-assembly`.

```
$ cdk --app <./my-cloud-assembly> ls
```<a name="deploy-how-synth-assemblies"></a>

 **Conjuntos de nuvem**   
A chamada para `app.synth()` é o que diz ao AWS CDK para sintetizar um conjunto de nuvem a partir de uma aplicação. Normalmente, você não interage diretamente com os conjuntos de nuvem. São arquivos que incluem tudo o que é necessário para implantar sua aplicação em um ambiente de nuvem. Por exemplo, ele inclui um modelo do AWS CloudFormation para cada pilha em sua aplicação. Também inclui uma cópia de todos os ativos de arquivo ou imagens do Docker que você referenciar na sua aplicação.  
Consulte a [especificação de conjunto de nuvem](https://github.com/aws/aws-cdk/blob/master/design/cloud-assembly.md) para detalhes sobre como os conjuntos de nuvem são formatados.  
Para interagir com o conjunto de nuvem que sua aplicação do AWS CDK cria, você normalmente usa a CLI do AWS CDK. No entanto, qualquer ferramenta que possa ler o formato de conjunto de nuvem pode ser usada para implantar sua aplicação.

## Implantar a aplicação
<a name="deploy-how-deploy"></a>

Para implantar sua aplicação, recomendamos que você use o comando `cdk deploy` da CLI do CDK para iniciar implantações ou configurar implantações automatizadas.

Quando você executa `cdk deploy`, a CLI do CDK inicia o `cdk synth` para se preparar para a implantação. O diagrama a seguir ilustra o ciclo de vida da aplicação no contexto de uma implantação:

![\[Fluxograma do ciclo de vida da aplicação do <shared id="AWS"/> CDK.\]](http://docs.aws.amazon.com/pt_br/cdk/v2/guide/images/app-lifecycle_cdk-flowchart.png)


Durante a implantação, a CLI do CDK pega o conjunto de nuvem produzido pela síntese e o implanta em um ambiente da AWS. Os ativos são enviados para o Amazon S3 e o Amazon ECR, e o modelo do CloudFormation é enviado ao AWS CloudFormation para implantação.

Quando a fase de implantação do AWS CloudFormation começa, sua aplicação do CDK já terminou de ser executada e foi encerrada. Isso ocasiona o seguinte:
+ A aplicação do CDK não pode responder a eventos que aconteçam durante a implantação, como a criação de um recurso ou o término de toda a implantação. Para executar o código durante a fase de implantação, é necessário injetá-lo no modelo do AWS CloudFormation como um [recurso personalizado](cfn-layer.md#develop-customize-custom). Para obter mais informações sobre como adicionar um recurso personalizado à sua aplicação, consulte o [Módulo do AWS CloudFormation](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudformation-readme.html) ou o exemplo de [recurso personalizado](https://github.com/aws-samples/aws-cdk-examples/tree/master/typescript/custom-resource/). Você também pode configurar o módulo [Acionadores](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.triggers-readme.html) para executar código durante as implantações.
+ Talvez a aplicação do CDK precise funcionar com valores que não possam ser conhecidos no momento em que é executada. Por exemplo, se a aplicação do AWS CDK define um bucket do Amazon S3 com um nome gerado automaticamente e você recupera o atributo `bucket.bucketName` (Python: `bucket_name`), esse valor não é o nome do bucket implantado. Em vez disso, você obtém um valor de `Token`. Para determinar se um valor específico está disponível, chame `cdk.isUnresolved(value)` (Python: `is_unresolved`). Consulte [Tokens e o AWS CDK](tokens.md) para obter detalhes.<a name="deploy-how-deploy-permissions"></a>

 **Permissões de implantação**   
Antes da execução da implantação, as permissões devem ser estabelecidas. O diagrama a seguir ilustra as permissões que são usadas durante uma implantação padrão, ao usar o processo de bootstrapping padrão e o sintetizador de pilha:  

![\[Fluxograma do processo padrão de implantação do <shared id="AWS"/> CDK.\]](http://docs.aws.amazon.com/pt_br/cdk/v2/guide/images/default-deploy-process_cdk_flowchart.png)
  
 **O ator inicia a implantação**   
As implantações são iniciadas por um *ator*, usando a CLI do CDK. Um ator pode ser uma pessoa ou um serviço como o AWS CodePipeline.  
Se necessário, a CLI do CDK executa `cdk synth` quando você executar `cdk deploy`. Durante a síntese, a identidade da AWS pressupõe que `LookupRole` realiza pesquisas de contexto no ambiente da AWS.  
 **As permissões são estabelecidas**   
Primeiro, as credenciais de segurança do ator são usadas para se autenticar na AWS e obter a primeira identidade do IAM no processo. Para atores humanos, a forma como as credenciais de segurança são configuradas e obtidas depende de como você ou sua organização gerencia os usuários. Para obter mais informações, consulte [Configuração de credenciais de segurança para a CLI do AWS CDK](configure-access.md). Para agentes de serviços, como o CodePipeline, um perfil de execução do IAM é assumido e usado.  
Em seguida, os perfis do IAM criados em seu ambiente da AWS durante o bootstrapping são usadas para estabelecer permissões para realizar as ações necessárias para a implantação. Para obter mais informações sobre esses perfis e para que eles concedem permissões, consulte [Perfis do IAM criados durante o bootstrapping](bootstrapping-env.md#bootstrapping-env-roles). Esse processo inclui o seguinte:  
+ A identidade da AWS assume o perfil `DeploymentActionRole` e o passa o perfil `CloudFormationExecutionRole` para o CloudFormation, garantindo que o CloudFormation assuma o perfil ao realizar qualquer ação em seu ambiente da AWS. O `DeploymentActionRole` concede permissão para realizar implantações em seu ambiente e `CloudFormationExecutionRole` determina quais ações o CloudFormation pode realizar.
+ A identidade da AWS assume o `FilePublishingRole`, que determina as ações que podem ser executadas no bucket do Amazon S3 criado durante o bootstrapping.
+ A identidade da AWS assume o `ImagePublishingRole`, que determina as ações que podem ser executadas no repositório do Amazon ECR criado durante o bootstrapping.
+ Se necessário, a identidade da AWS pressupõe que `LookupRole` realiza pesquisas de contexto no ambiente da AWS. Essa ação também pode ser executada durante a síntese do modelo.  
 **A implantação é executada**   
Durante a implantação, a CLI do CDK lê o parâmetro da versão do bootstrapping para confirmar o número da versão do bootstrapping. AWS O CloudFormation também lê esse parâmetro no momento da implantação para confirmar. Se as permissões em todo o fluxo de trabalho de implantação forem válidas, a implantação será executada. Os ativos são carregados nos recursos que receberam o bootstrapping e o modelo do CloudFormation produzido na síntese é implantado usando o serviço como uma pilha do CloudFormation para provisionar seus recursos.

# Validação da política do AWS CDK no momento da síntese
<a name="policy-validation-synthesis"></a>

## Validação de políticas no momento da síntese
<a name="policy-validation"></a>

Se você ou sua organização usarem alguma ferramenta de validação de políticas, como o [AWS CloudFormation Guard](https://docs.aws.amazon.com/cfn-guard/latest/ug/what-is-guard.html) ou o [OPA](https://www.openpolicyagent.org/), para definir restrições em seu modelo do AWS CloudFormation, será possível integrá-las ao AWS CDK no momento da síntese. Ao usar o plug-in de validação de política apropriado, é possível fazer com que a aplicação do AWS CDK verifique o modelo do AWS CloudFormation gerado em relação às suas políticas imediatamente após a síntese. Se houver alguma violação, a síntese falhará e um relatório será impresso no console.

A validação realizada pelo AWS CDK no momento da síntese valida os controles em um ponto do ciclo de vida da implantação, mas eles não podem afetar as ações que ocorrem fora da síntese. Os exemplos incluem ações realizadas diretamente no console ou por meio de APIs de serviço. Eles não são resistentes à alteração dos modelos AWS CloudFormation após a síntese. Algum outro mecanismo para validar o mesmo conjunto de regras com mais autoridade deve ser configurado de forma independente, como os [hooks do AWS CloudFormation](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/hooks.html) ou o [AWS Config](https://docs.aws.amazon.com/config/latest/developerguide/WhatIsConfig.html). No entanto, a capacidade do AWS CDK de avaliar o conjunto de regras durante o desenvolvimento ainda é útil, pois melhorará a velocidade de detecção e a produtividade do desenvolvedor.

O objetivo da validação da política do AWS CDK é o de minimizar a quantidade de configuração necessária durante o desenvolvimento e torná-la o mais fácil possível.

**nota**  
Esse atributo é considerado experimental, e tanto a API do plug-in quanto o formato do relatório de validação estão sujeitos a alterações no futuro.

## Para desenvolvedor de aplicações
<a name="for-application-developers"></a>

Para usar um ou mais plug-ins de validação em sua aplicação, use a propriedade `policyValidationBeta1` do `Stage`:

```
import { CfnGuardValidator } from '@cdklabs/cdk-validator-cfnguard';
const app = new App({
  policyValidationBeta1: [
    new CfnGuardValidator()
  ],
});
// only apply to a particular stage
const prodStage = new Stage(app, 'ProdStage', {
  policyValidationBeta1: [...],
});
```

Imediatamente após a síntese, todos os plug-ins registrados dessa forma serão invocados para validar todos os modelos gerados no escopo que você definiu. Em particular, se você registrar os modelos no objeto `App`, todos os modelos estarão sujeitos à validação.

**Atenção**  
Além de modificar o conjunto de nuvem, os plug-ins podem fazer tudo o que sua aplicação AWS CDK pode. Eles podem ler dados do sistema de arquivos, acessar a rede etc. É sua responsabilidade, como consumidor de um plug-in, verificar se ele é seguro para uso.

### Plug-in AWS CloudFormation Guard
<a name="cfnguard-plugin"></a>

O uso do plug-in [https://github.com/cdklabs/cdk-validator-cfnguard](https://github.com/cdklabs/cdk-validator-cfnguard) permite que você use o [AWS CloudFormation Guard](https://github.com/aws-cloudformation/cloudformation-guard) para realizar validações de políticas. O plug-in `CfnGuardValidator` vem com um conjunto selecionado de [controles proativos do AWS Control Tower](https://docs.aws.amazon.com/controltower/latest/userguide/proactive-controls.html) incorporados. O conjunto atual de regras pode ser encontrado na [documentação do projeto](https://github.com/cdklabs/cdk-validator-cfnguard/blob/main/README.md). Conforme mencionado em [Validação de políticas no momento da síntese](#policy-validation), recomendamos que as organizações criem um método de validação mais confiável usando [hooks do AWS CloudFormation](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/hooks.html).

Para os clientes do [AWS Control Tower](https://docs.aws.amazon.com/controltower/latest/userguide/what-is-control-tower.html), esses mesmos controles proativos podem ser implantados em toda a sua organização. Quando você habilita os controles proativos do AWS Control Tower em seu ambiente da AWS, os controles podem interromper a implantação de recursos não compatíveis implantados via AWS CloudFormation. Para obter mais informações sobre controles proativos gerenciados e como eles funcionam, consulte a [documentação do AWS Control Tower](https://docs.aws.amazon.com/controltower/latest/userguide/proactive-controls.html).

Esses controles agrupados do AWS CDK e os controles proativos do AWS Control Tower gerenciados são melhor usados juntos. Nesse cenário, é possível configurar esse plug-in de validação com os mesmos controles proativos que estão ativos em seu ambiente de nuvem do AWS Control Tower. Em seguida, é possível rapidamente ter certeza de que sua aplicação do AWS CDK passará pelos controles do AWS Control Tower executando o `cdk synth` localmente.

### Relatório de validação
<a name="validation-report"></a>

Quando você sintetizar a aplicação do AWS CDK, os plug-ins do validador serão chamados e os resultados serão impressos. Um exemplo de relatório está sendo exibido abaixo.

```
Validation Report (CfnGuardValidator)
-------------------------------------
(Summary)
╔═══════════╤════════════════════════╗
║ Status    │ failure                ║
╟───────────┼────────────────────────╢
║ Plugin    │ CfnGuardValidator      ║
╚═══════════╧════════════════════════╝
(Violations)
Ensure S3 Buckets are encrypted with a KMS CMK (1 occurrences)
Severity: medium
  Occurrences:

    - Construct Path: MyStack/MyCustomL3Construct/Bucket
    - Stack Template Path: ./cdk.out/MyStack.template.json
    - Creation Stack:
        └──  MyStack (MyStack)
             │ Library: aws-cdk-lib.Stack
             │ Library Version: 2.50.0
             │ Location: Object.<anonymous> (/home/johndoe/tmp/cdk-tmp-app/src/main.ts:25:20)
             └──  MyCustomL3Construct (MyStack/MyCustomL3Construct)
                  │ Library: N/A - (Local Construct)
                  │ Library Version: N/A
                  │ Location: new MyStack (/home/johndoe/tmp/cdk-tmp-app/src/main.ts:15:20)
                  └──  Bucket (MyStack/MyCustomL3Construct/Bucket)
                       │ Library: aws-cdk-lib/aws-s3.Bucket
                       │ Library Version: 2.50.0
                       │ Location: new MyCustomL3Construct (/home/johndoe/tmp/cdk-tmp-app/src/main.ts:9:20)
    - Resource Name: amzn-s3-demo-bucket
    - Locations:
      > BucketEncryption/ServerSideEncryptionConfiguration/0/ServerSideEncryptionByDefault/SSEAlgorithm
  Recommendation: Missing value for key `SSEAlgorithm` - must specify `aws:kms`
  How to fix:
    > Add to construct properties for `cdk-app/MyStack/Bucket`
      `encryption: BucketEncryption.KMS`

Validation failed. See above reports for details
```

Por padrão, o relatório será impresso em um formato legível por humanos. Se você quiser um relatório no formato JSON, habilite-o usando `@aws-cdk/core:validationReportJson` via a CLI ou passando-o diretamente para a aplicação:

```
const app = new App({
  context: { '@aws-cdk/core:validationReportJson': true },
});
```

Como alternativa, é possível definir esse par de chave-valor de contexto usando os arquivos `cdk.json` ou `cdk.context.json` no diretório do seu projeto (consulte [Valores de contexto e o AWS CDK](context.md)).

Se você escolher o formato JSON, o AWS CDK imprimirá o relatório de validação da política em um arquivo chamado `policy-validation-report.json` no diretório de conjunto de nuvem. Para o formato padrão legível por humanos, o relatório será impresso na saída padrão.

## Para autores de plugins
<a name="plugin-authors"></a>

### Plug-ins
<a name="plugins"></a>

A estrutura principal do AWS CDK é responsável por registrar e invocar plug-ins e, em seguida, exibir o relatório de validação formatado. A responsabilidade do plug-in é atuar como a camada de tradução entre a estrutura do AWS CDK e a ferramenta de validação de políticas. Um plug-in pode ser criado em qualquer linguagem com suporte no AWS CDK. Se você estiver criando um plug-in que pode ser consumido por várias linguagens, é recomendável criar o plug-in `TypeScript` para poder usar o JSII para publicar o plug-in em cada linguagem do AWS CDK.

### Criar plug-ins
<a name="creating-plugins"></a>

O protocolo de comunicação entre o módulo principal do AWS CDK e sua ferramenta de política é definido pela interface `IPolicyValidationPluginBeta1`. Para criar um novo plug-in, você deve escrever uma classe que implemente essa interface. Há duas coisas que você precisa implementar: o nome do plug-in (substituindo a propriedade `name`) e o método `validate()`.

A estrutura chamará `validate()`, passando um objeto `IValidationContextBeta1`. A localização dos modelos a serem validados é fornecida pelo `templatePaths`. O plug-in deve retornar uma instância de `ValidationPluginReportBeta1`. Esse objeto representa o relatório que o usuário receberá ao final da síntese.

```
validate(context: IPolicyValidationContextBeta1): PolicyValidationReportBeta1 {
  // First read the templates using context.templatePaths...
  // ...then perform the validation, and then compose and return the report.
  // Using hard-coded values here for better clarity:
  return {
    success: false,
    violations: [{
      ruleName: 'CKV_AWS_117',
      description: 'Ensure that AWS Lambda function is configured inside a VPC',
      fix: 'https://docs.bridgecrew.io/docs/ensure-that-aws-lambda-function-is-configured-inside-a-vpc-1',
      violatingResources: [{
        resourceName: 'MyFunction3BAA72D1',
        templatePath: '/home/johndoe/myapp/cdk.out/MyService.template.json',
        locations: 'Properties/VpcConfig',
      }],
    }],
  };
}
```

Observe que os plug-ins não podem modificar nada no conjunto de nuvem. Qualquer tentativa de fazer isso resultará em falha na síntese.

Se o seu plug-in depender de uma ferramenta externa, lembre-se de que alguns desenvolvedores talvez ainda não tenham essa ferramenta instalada em suas estações de trabalho. Para minimizar o atrito, é altamente recomendável que você forneça algum script de instalação junto com o pacote de plug-ins, para automatizar todo o processo. Melhor ainda, execute esse script como parte da instalação do seu pacote. Com o `npm`, por exemplo, você pode adicioná-lo ao [script ](https://docs.npmjs.com/cli/v9/using-npm/scripts) `postinstall` no arquivo `package.json`.

### Tratamento de exceções
<a name="handling-exemptions"></a>

Se sua organização tiver um mecanismo para lidar com exceções, ele poderá ser implementado como parte do plug-in validador.

Um exemplo de cenário para ilustrar um possível mecanismo de exceção:
+ Uma organização tem uma regra segundo a qual os buckets públicos do Amazon S3 não são permitidos, *exceto* em determinados cenários.
+ Um desenvolvedor está criando um bucket do Amazon S3 que se enquadra em um desses cenários e solicita uma exceção (cria um ticket, por exemplo).
+ As ferramentas de segurança sabem como ler o sistema interno que registra exceções

Nesse cenário, o desenvolvedor solicitaria uma exceção no sistema interno e, em seguida, precisaria de alguma forma de “registrar” essa exceção. Além do exemplo do plug-in de proteção, você pode criar um plug-in que lida com exceções filtrando as violações que têm uma exceção correspondente em um sistema interno de tickets.

Veja os plug-ins existentes para ver exemplos de implementações.
+  [@cdklabs/cdk-validator-cfnguard](https://github.com/cdklabs/cdk-validator-cfnguard) 

# Integração e entrega contínuas (CI/CD) usando CDK Pipelines
<a name="cdk-pipeline"></a>

Use o módulo [CDK Pipelines](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines-readme.html) da Biblioteca de Constructos da AWS para configurar a entrega contínua de aplicações do AWS CDK. Quando você confirma o código-fonte da sua aplicação do CDK no AWS CodeCommit, no GitHub ou no AWS CodeStar, o CDK Pipelines pode compilar, testar e implantar automaticamente sua nova versão.

O CDK Pipelines é atualizado automaticamente. Se você adicionar estágios ou pilhas de aplicações, o pipeline se reconfigura automaticamente para implantar esses novos estágios ou pilhas.

**nota**  
O CDK Pipelines oferece suporte a duas APIs. Uma delas é a API original que foi disponibilizada na Demonstração para desenvolvedores do CDK Pipelines. A outra é uma API moderna que incorpora o feedback dos clientes do CDK recebido durante a fase de pré-visualização. Os exemplos deste tópico usam a API moderna. Para obter detalhes sobre as diferenças entre as duas APIs com suporte, consulte [API original do CDK Pipelines](https://github.com/aws/aws-cdk/blob/master/packages/@aws-cdk/pipelines/ORIGINAL_API.md) no *repositório aws-cdk do GitHub*.

## Fazer bootstrapping em seus ambientes da AWS
<a name="cdk-pipeline-bootstrap"></a>

Antes de usar o CDK Pipelines, você deve inicializar o [ambiente](environments.md) da AWS no qual implantará suas pilhas.

Um CDK Pipeline envolve pelo menos dois ambientes. O primeiro ambiente é onde o pipeline é provisionado. O segundo ambiente é onde você deseja implantar as pilhas ou estágios da aplicação (os estágios são grupos de pilhas relacionadas). Esses ambientes podem ser os mesmos, mas uma é uma prática recomendada isolar os estágios uns dos outros em ambientes diferentes.

**nota**  
Consulte [Bootstrapping do AWS CDK](bootstrapping.md) para obter mais informações sobre os tipos de recursos criados pelo bootstrapping e como personalizar a pilha de bootstrapping.

A implantação contínua com o CDK Pipelines exige que o seguinte seja incluído na pilha do Kit de Ferramentas CDK:
+ Um bucket do Amazon Simple Storage Service (Amazon S3).
+ Um repositório do Amazon ECR.
+ Perfis do IAM para dar às várias partes de um pipeline as permissões de que elas precisam.

O Kit de Ferramentas CDK atualizará sua pilha de bootstrapping existente ou criará uma nova, se necessário.

Para fazer o bootstrapping em um ambiente que possa provisionar um pipeline do AWS CDK, invoque `cdk bootstrap` conforme mostrado no exemplo a seguir. Invocar o Kit de Ferramentas CDK da AWS por meio do comando `npx` o instalará temporariamente, se necessário. Ele também usará a versão do Kit de Ferramentas instalada no projeto atual, se houver.

 `--cloudformation-execution-policies` especifica o ARN de uma política sob a qual as futuras implantações do CDK Pipelines serão executadas. A política `AdministratorAccess` padrão garante que seu pipeline possa implantar todo tipo de recurso da AWS. Se você usar essa política, certifique-se de confiar em todos os códigos e dependências que compõem sua aplicação do AWS CDK.

A maioria das organizações exige controles mais rígidos sobre quais tipos de recursos podem ser implantados pela automação. Consulte o departamento apropriado da sua organização para determinar a política que seu pipeline deve usar.

É possível omitir a opção `--profile` se seu perfil da AWS padrão contiver a configuração de autenticação e a região da AWS necessárias.

**Example**  

```
npx cdk bootstrap aws://<ACCOUNT-NUMBER>/<REGION> --profile <ADMIN-PROFILE> \
    --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess
```

```
npx cdk bootstrap aws://<ACCOUNT-NUMBER></REGION> --profile< ADMIN-PROFILE> ^
    --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess
```

Para fazer o bootstrapping em ambientes adicionais nos quais as aplicações do AWS CDK serão implantados pelo pipeline, use os comandos a seguir. A opção `--trust` indica qual outra conta deve ter permissões para implantar aplicações do AWS CDK nesse ambiente. Para essa opção, especifique o ID da conta da AWS do pipeline.

Novamente, é possível omitir a opção `--profile` se seu perfil da AWS padrão contiver a configuração de autenticação e a região da AWS necessárias.

**Example**  

```
npx cdk bootstrap aws://<ACCOUNT-NUMBER>/<REGION> --profile <ADMIN-PROFILE> \
    --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess \
    --trust <PIPELINE-ACCOUNT-NUMBER>
```

```
npx cdk bootstrap aws://<ACCOUNT-NUMBER>/<REGION> --profile <ADMIN-PROFILE> ^
    --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess ^
    --trust <PIPELINE-ACCOUNT-NUMBER>
```

**dica**  
Use credenciais administrativas somente para fazer o bootstrapping e provisionar o pipeline inicial. Depois, use o próprio pipeline, não sua máquina local, para implantar as alterações.

Se você estiver atualizando um ambiente legado em que foi feito o bootstrapping, o bucket anterior do Amazon S3 ficará órfão quando o novo bucket for criado. Exclua-o manualmente usando o console do Amazon S3.

### Proteger sua pilha de bootstrapping contra exclusão
<a name="cdk-pipeline-protect"></a>

Se uma pilha de bootstrapping for excluída, os recursos da AWS que foram originalmente provisionados no ambiente para oferecer suporte a implantações do CDK também serão excluídos. Isso fará com que o pipeline pare de funcionar. Se isso acontecer, não há solução geral para recuperação.

Depois que seu ambiente receber o bootstrapping, não exclua e recrie a pilha de bootstrapping do ambiente. Em vez disso, tente atualizar a pilha de bootstrapping para uma nova versão executando o comando `cdk bootstrap` novamente.

Para se proteger contra a exclusão acidental de sua pilha de bootstrapping, recomendamos que você forneça a opção `--termination-protection` com o comando `cdk bootstrap` para ativar a proteção contra encerramento. É possível ativar a proteção contra encerramento em pilhas de bootstrapping novas ou existentes. Para saber mais sobre essa opção, consulte ` --termination-protection `.

Depois de ativar a proteção contra encerramento, será possível usar a AWS CLI ou o console do CloudFormation para verificar.

1. Execute o comando a seguir para ativar a proteção contra encerramento em uma pilha de bootstrapping nova ou existente:

   ```
   $ cdk bootstrap --termination-protection
   ```

1. Use a AWS CLI ou o console do CloudFormation para verificar. Veja a seguir um exemplo usando a AWS CLI. Se você modificou o nome da pilha de bootstrapping, substitua `CDKToolkit` pelo nome da pilha:

   ```
   $ aws cloudformation describe-stacks --stack-name <CDKToolkit> --query "Stacks[0].EnableTerminationProtection"
   true
   ```

## Inicializar um projeto
<a name="cdk-pipeline-init"></a>

Crie um novo projeto vazio do GitHub e clone-o em sua estação de trabalho no diretório `my-pipeline`. (Nossos exemplos de código neste tópico usam o GitHub. Você também pode usar o AWS CodeStar ou o AWS CodeCommit.)

```
git clone <GITHUB-CLONE-URL> my-pipeline
cd my-pipeline
```

**nota**  
É possível usar um nome diferente de `my-pipeline` no diretório principal da aplicação. No entanto, se você fizer isso, precisará ajustar os nomes dos arquivos e das classes posteriormente neste tópico. Isso ocorre porque o Kit de Ferramentas CDK da AWS baseia alguns nomes de arquivos e classes no nome do diretório principal.

Após a clonagem, inicialize o projeto normalmente.

**Example**  

```
$ cdk init app --language typescript
```

```
$ cdk init app --language javascript
```

```
$ cdk init app --language python
```
Depois que a aplicação for criado, insira também os dois comandos a seguir. Eles ativam o ambiente virtual Python da aplicação e instalam as dependências principais do AWS CDK.  

```
$ source .venv/bin/activate # On Windows, run `.\venv\Scripts\activate` instead
$ python -m pip install -r requirements.txt
```

```
$ cdk init app --language java
```
Se você estiver usando um IDE, agora pode abrir ou importar o projeto. No Eclipse, por exemplo, escolha **Arquivo** > **Importar** > **Maven** > **Projetos existentes do Maven**. Certifique-se de que as configurações do projeto estejam definidas para usar o Java 8 (1.8).

```
$ cdk init app --language csharp
```
Se você estiver usando o Visual Studio, abra o arquivo da solução no diretório `src`.

```
$ cdk init app --language go
```
Depois que a aplicação for criado, insira também o comando a seguir para instalar os módulos da Biblioteca de Constructos da AWS que a aplicação exige.  

```
$ go get
```

**Importante**  
Envie seus arquivos `cdk.json` e `cdk.context.json` para o controle de origem. As informações de contexto (como sinalizadores de atributos e valores armazenados em cache recuperados da sua conta da AWS) fazem parte do estado do seu projeto. Os valores podem ser diferentes em outro ambiente, o que pode causar alterações inesperadas nos resultados. Para obter mais informações, consulte [Valores de contexto e o AWS CDK](context.md).

## Definir um pipeline
<a name="cdk-pipeline-define"></a>

Seu aplicação do CDK Pipelines incluirá pelo menos duas pilhas: uma que representa o próprio pipeline e uma ou mais pilhas que representam a aplicação implantado por meio dele. As pilhas também podem ser agrupadas em *estágios*, que você pode usar para implantar cópias das pilhas de infraestrutura em diferentes ambientes. Por enquanto, consideraremos o pipeline e, posteriormente, nos aprofundaremos na aplicação que ele implantará.

O constructo ` [CodePipeline](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.CodePipeline.html) ` é o constructo que representa um CDK Pipeline que o AWS CodePipeline usa como mecanismo de implantação. Ao instanciar `CodePipeline` em uma pilha, você define o local de origem do pipeline (como um repositório do GitHub). Você também define os comandos para compilar a aplicação.

Por exemplo, o seguinte define um pipeline cuja fonte está armazenada em um repositório do GitHub. Também inclui uma etapa de criação para uma aplicação do TypeScript CDK. Preencha as informações sobre seu repositório do GitHub onde indicado.

**nota**  
Por padrão, o pipeline se autentica no GitHub usando um token de acesso pessoal armazenado no Secrets Manager sob o nome `github-token`.

Você também precisará atualizar a instanciação da pilha do pipeline para especificar a conta e a região da AWS.

**Example**  
Em `lib/my-pipeline-stack.ts` (pode variar se o nome da pasta do seu projeto não for `my-pipeline`):  

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { CodePipeline, CodePipelineSource, ShellStep } from 'aws-cdk-lib/pipelines';

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

    const pipeline = new CodePipeline(this, 'Pipeline', {
      pipelineName: 'MyPipeline',
      synth: new ShellStep('Synth', {
        input: CodePipelineSource.gitHub('OWNER/REPO', 'main'),
        commands: ['npm ci', 'npm run build', 'npx cdk synth']
      })
    });
  }
}
```
Em `bin/my-pipeline.ts` (pode variar se o nome da pasta do seu projeto não for `my-pipeline`):  

```
#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { MyPipelineStack } from '../lib/my-pipeline-stack';

const app = new cdk.App();
new MyPipelineStack(app, 'MyPipelineStack', {
  env: {
    account: '111111111111',
    region: 'eu-west-1',
  }
});

app.synth();
```
Em `lib/my-pipeline-stack.js` (pode variar se o nome da pasta do seu projeto não for `my-pipeline`):  

```
const cdk = require('aws-cdk-lib');
const { CodePipeline, CodePipelineSource, ShellStep } = require('aws-cdk-lib/pipelines');

 class MyPipelineStack extends cdk.Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    const pipeline = new CodePipeline(this, 'Pipeline', {
      pipelineName: 'MyPipeline',
      synth: new ShellStep('Synth', {
        input: CodePipelineSource.gitHub('OWNER/REPO', 'main'),
        commands: ['npm ci', 'npm run build', 'npx cdk synth']
      })
    });
  }
}

module.exports = { MyPipelineStack }
```
Em `bin/my-pipeline.js` (pode variar se o nome da pasta do seu projeto não for `my-pipeline`):  

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

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

const app = new cdk.App();
new MyPipelineStack(app, 'MyPipelineStack', {
  env: {
    account: '111111111111',
    region: 'eu-west-1',
  }
});

app.synth();
```
Em `my-pipeline/my-pipeline-stack.py` (pode variar se o nome da pasta do seu projeto não for `my-pipeline`):  

```
import aws_cdk as cdk
from constructs import Construct
from aws_cdk.pipelines import CodePipeline, CodePipelineSource, ShellStep

class MyPipelineStack(cdk.Stack):

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

        pipeline =  CodePipeline(self, "Pipeline",
                        pipeline_name="MyPipeline",
                        synth=ShellStep("Synth",
                            input=CodePipelineSource.git_hub("OWNER/REPO", "main"),
                            commands=["npm install -g aws-cdk",
                                "python -m pip install -r requirements.txt",
                                "cdk synth"]
                        )
                    )
```
Em `app.py`:  

```
#!/usr/bin/env python3
import aws_cdk as cdk
from my_pipeline.my_pipeline_stack import MyPipelineStack

app = cdk.App()
MyPipelineStack(app, "MyPipelineStack",
    env=cdk.Environment(account="111111111111", region="eu-west-1")
)

app.synth()
```
Em `src/main/java/com/myorg/MyPipelineStack.java` (pode variar se o nome da pasta do seu projeto não for `my-pipeline`):  

```
package com.myorg;

import java.util.Arrays;
import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.pipelines.CodePipeline;
import software.amazon.awscdk.pipelines.CodePipelineSource;
import software.amazon.awscdk.pipelines.ShellStep;

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

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

        CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline")
             .pipelineName("MyPipeline")
             .synth(ShellStep.Builder.create("Synth")
                .input(CodePipelineSource.gitHub("OWNER/REPO", "main"))
                .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth"))
                .build())
             .build();
    }
}
```
Em `src/main/java/com/myorg/MyPipelineApp.java` (pode variar se o nome da pasta do seu projeto não for `my-pipeline`):  

```
package com.myorg;

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

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

        new MyPipelineStack(app, "PipelineStack", StackProps.builder()
            .env(Environment.builder()
                .account("111111111111")
                .region("eu-west-1")
                .build())
            .build());

        app.synth();
    }
}
```
Em `src/MyPipeline/MyPipelineStack.cs` (pode variar se o nome da pasta do seu projeto não for `my-pipeline`):  

```
using Amazon.CDK;
using Amazon.CDK.Pipelines;

namespace MyPipeline
{
    public class MyPipelineStack : Stack
    {
        internal MyPipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps
            {
                PipelineName = "MyPipeline",
                Synth = new ShellStep("Synth", new ShellStepProps
                {
                    Input = CodePipelineSource.GitHub("OWNER/REPO", "main"),
                    Commands = new string[] { "npm install -g aws-cdk", "cdk synth" }
                })
            });
        }
    }
}
```
Em `src/MyPipeline/Program.cs` (pode variar se o nome da pasta do seu projeto não for `my-pipeline`):  

```
using Amazon.CDK;

namespace MyPipeline
{
    sealed class Program
    {
        public static void Main(string[] args)
        {
            var app = new App();
            new MyPipelineStack(app, "MyPipelineStack", new StackProps
            {
                Env = new Amazon.CDK.Environment {
                    Account = "111111111111", Region = "eu-west-1" }
            });

            app.Synth();
        }
    }
}
```

```
package main

import (
	"github.com/aws/aws-cdk-go/awscdk/v2"
	codebuild "github.com/aws/aws-cdk-go/awscdk/v2/awscodebuild"
	ssm "github.com/aws/aws-cdk-go/awscdk/v2/awsssm"
	pipeline "github.com/aws/aws-cdk-go/awscdk/v2/pipelines"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
	"os"
)

// my CDK Stack with resources
func NewCdkStack(scope constructs.Construct, id *string, props *awscdk.StackProps) awscdk.Stack {
	stack := awscdk.NewStack(scope, id, props)

	// create an example ssm parameter
	_ = ssm.NewStringParameter(stack, jsii.String("ssm-test-param"), &ssm.StringParameterProps{
		ParameterName: jsii.String("/testparam"),
		Description:   jsii.String("ssm parameter for demo"),
		StringValue:   jsii.String("my test param"),
	})

	return stack
}

// my CDK Application
func NewCdkApplication(scope constructs.Construct, id *string, props *awscdk.StageProps) awscdk.Stage {
	stage := awscdk.NewStage(scope, id, props)

	_ = NewCdkStack(stage, jsii.String("cdk-stack"), &awscdk.StackProps{Env: props.Env})

	return stage
}

// my CDK Pipeline
func NewCdkPipeline(scope constructs.Construct, id *string, props *awscdk.StackProps) awscdk.Stack {
	stack := awscdk.NewStack(scope, id, props)

	// GitHub repo with owner and repository name
	githubRepo := pipeline.CodePipelineSource_GitHub(jsii.String("owner/repo"), jsii.String("main"), &pipeline.GitHubSourceOptions{
		Authentication: awscdk.SecretValue_SecretsManager(jsii.String("my-github-token"), nil),
	})

	// self mutating pipeline
	myPipeline := pipeline.NewCodePipeline(stack, jsii.String("cdkPipeline"), &pipeline.CodePipelineProps{
		PipelineName: jsii.String("CdkPipeline"),
		// self mutation true - pipeline changes itself before application deployment
		SelfMutation: jsii.Bool(true),
		CodeBuildDefaults: &pipeline.CodeBuildOptions{
			BuildEnvironment: &codebuild.BuildEnvironment{
				// image version 6.0 recommended for newer go version
				BuildImage: codebuild.LinuxBuildImage_FromCodeBuildImageId(jsii.String("aws/codebuild/standard:6.0")),
			},
		},
		Synth: pipeline.NewCodeBuildStep(jsii.String("Synth"), &pipeline.CodeBuildStepProps{
			Input: githubRepo,
			Commands: &[]*string{
				jsii.String("npm install -g aws-cdk"),
				jsii.String("cdk synth"),
			},
		}),
	})

	// deployment of actual CDK application
	myPipeline.AddStage(NewCdkApplication(stack, jsii.String("MyApplication"), &awscdk.StageProps{
		Env: targetAccountEnv(),
	}), &pipeline.AddStageOpts{
		Post: &[]pipeline.Step{
			pipeline.NewCodeBuildStep(jsii.String("Manual Steps"), &pipeline.CodeBuildStepProps{
				Commands: &[]*string{
					jsii.String("echo \"My CDK App deployed, manual steps go here ... \""),
				},
			}),
		},
	})

	return stack
}

// main app
func main() {
	defer jsii.Close()

	app := awscdk.NewApp(nil)

	// call CDK Pipeline
	NewCdkPipeline(app, jsii.String("CdkPipelineStack"), &awscdk.StackProps{
		Env: pipelineEnv(),
	})

	app.Synth(nil)
}

// env determines the AWS environment (account+region) in which our stack is to
// be deployed. For more information see: https://docs.aws.amazon.com/cdk/latest/guide/environments.html
func pipelineEnv() *awscdk.Environment {
	return &awscdk.Environment{
		Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")),
		Region:  jsii.String(os.Getenv("CDK_DEFAULT_REGION")),
	}
}

func targetAccountEnv() *awscdk.Environment {
	return &awscdk.Environment{
		Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")),
		Region:  jsii.String(os.Getenv("CDK_DEFAULT_REGION")),
	}
}
```

É necessário implantar um pipeline manualmente uma vez. Depois disso, o pipeline se mantém atualizado a partir do repositório do código-fonte. Portanto, verifique se o código no repositório é o código que você deseja implantar. Verifique suas alterações, envie para o GitHub e, em seguida, implante:

```
git add --all
git commit -m "initial commit"
git push
cdk deploy
```

**dica**  
Agora que você fez a implantação inicial, sua conta da AWS local não precisará mais de acesso administrativo. Isso ocorre porque todas as alterações em sua aplicação serão implantadas por meio do pipeline. Tudo o que você precisa fazer é enviar para o GitHub.

## Estágios de aplicações
<a name="cdk-pipeline-stages"></a>

Para definir uma aplicação da AWS de várias pilhas que possa ser adicionado ao pipeline de uma só vez, defina uma subclasse de ` [Stage](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html) `. (Isso é diferente de `CdkStage` no módulo do CDK Pipelines.)

O estágio contém as pilhas do que compõem a aplicação. Se houver dependências entre as pilhas, as pilhas serão adicionadas automaticamente ao pipeline na ordem correta. As pilhas que não dependam umas das outras são implantadas paralelamente. É possível adicionar uma relação de dependência entre as pilhas chamando `stack1.addDependency(stack2)`.

Os estágios aceitam um argumento `env` padrão, que se torna o ambiente padrão para as pilhas dentro dele. (As pilhas ainda podem ter seu próprio ambiente especificado.)

Um aplicação é adicionada ao pipeline chamando ` [addStage()](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.CodePipeline.html#addwbrstagestage-optionss) ` com instâncias de [Stage](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html). Um estágio pode ser instanciado e adicionado ao pipeline várias vezes para definir diferentes estágios do seu pipeline de aplicações multirregional ou DTAP.

Criaremos uma pilha contendo uma função do Lambda simples e colocaremos essa pilha em um estágio. Em seguida, adicionaremos o estágio ao pipeline para que ele possa ser implantado.

**Example**  
Crie o novo arquivo `lib/my-pipeline-lambda-stack.ts` para armazenar nossa pilha de aplicações contendo uma função do Lambda.  

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { Function, InlineCode, Runtime } from 'aws-cdk-lib/aws-lambda';

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

      new Function(this, 'LambdaFunction', {
        runtime: Runtime.NODEJS_18_X,
        handler: 'index.handler',
        code: new InlineCode('exports.handler = _ => "Hello, CDK";')
      });
    }
}
```
Crie o novo arquivo `lib/my-pipeline-app-stage.ts` para manter nosso estágio.  

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from "constructs";
import { MyLambdaStack } from './my-pipeline-lambda-stack';

export class MyPipelineAppStage extends cdk.Stage {

    constructor(scope: Construct, id: string, props?: cdk.StageProps) {
      super(scope, id, props);

      const lambdaStack = new MyLambdaStack(this, 'LambdaStack');
    }
}
```
Edite `lib/my-pipeline-stack.ts` para adicionar o estágio ao nosso pipeline.  

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { CodePipeline, CodePipelineSource, ShellStep } from 'aws-cdk-lib/pipelines';
import { MyPipelineAppStage } from './my-pipeline-app-stage';

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

    const pipeline = new CodePipeline(this, 'Pipeline', {
      pipelineName: 'MyPipeline',
      synth: new ShellStep('Synth', {
        input: CodePipelineSource.gitHub('OWNER/REPO', 'main'),
        commands: ['npm ci', 'npm run build', 'npx cdk synth']
      })
    });

    pipeline.addStage(new MyPipelineAppStage(this, "test", {
      env: { account: "111111111111", region: "eu-west-1" }
    }));
  }
}
```
Crie o novo arquivo `lib/my-pipeline-lambda-stack.js` para armazenar nossa pilha de aplicações contendo uma função do Lambda.  

```
const cdk = require('aws-cdk-lib');
const { Function, InlineCode, Runtime } = require('aws-cdk-lib/aws-lambda');

class MyLambdaStack extends cdk.Stack {
    constructor(scope, id, props) {
      super(scope, id, props);

      new Function(this, 'LambdaFunction', {
        runtime: Runtime.NODEJS_18_X,
        handler: 'index.handler',
        code: new InlineCode('exports.handler = _ => "Hello, CDK";')
      });
    }
}

module.exports = { MyLambdaStack }
```
Crie o novo arquivo `lib/my-pipeline-app-stage.js` para manter nosso estágio.  

```
const cdk = require('aws-cdk-lib');
const { MyLambdaStack } = require('./my-pipeline-lambda-stack');

class MyPipelineAppStage extends cdk.Stage {

    constructor(scope, id, props) {
      super(scope, id, props);

      const lambdaStack = new MyLambdaStack(this, 'LambdaStack');
    }
}

module.exports = { MyPipelineAppStage };
```
Edite `lib/my-pipeline-stack.ts` para adicionar o estágio ao nosso pipeline.  

```
const cdk = require('aws-cdk-lib');
const { CodePipeline, CodePipelineSource, ShellStep } = require('aws-cdk-lib/pipelines');
const { MyPipelineAppStage } = require('./my-pipeline-app-stage');

 class MyPipelineStack extends cdk.Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    const pipeline = new CodePipeline(this, 'Pipeline', {
      pipelineName: 'MyPipeline',
      synth: new ShellStep('Synth', {
        input: CodePipelineSource.gitHub('OWNER/REPO', 'main'),
        commands: ['npm ci', 'npm run build', 'npx cdk synth']
      })
    });

    pipeline.addStage(new MyPipelineAppStage(this, "test", {
      env: { account: "111111111111", region: "eu-west-1" }
    }));

  }
}

module.exports = { MyPipelineStack }
```
Crie o novo arquivo `my_pipeline/my_pipeline_lambda_stack.py` para armazenar nossa pilha de aplicações contendo uma função do Lambda.  

```
import aws_cdk as cdk
from constructs import Construct
from aws_cdk.aws_lambda import Function, InlineCode, Runtime

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

        Function(self, "LambdaFunction",
            runtime=Runtime.NODEJS_18_X,
            handler="index.handler",
            code=InlineCode("exports.handler = _ => 'Hello, CDK';")
        )
```
Crie o novo arquivo `my_pipeline/my_pipeline_app_stage.py` para manter nosso estágio.  

```
import aws_cdk as cdk
from constructs import Construct
from my_pipeline.my_pipeline_lambda_stack import MyLambdaStack

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

        lambdaStack = MyLambdaStack(self, "LambdaStack")
```
Edite `my_pipeline/my-pipeline-stack.py` para adicionar o estágio ao nosso pipeline.  

```
import aws_cdk as cdk
from constructs import Construct
from aws_cdk.pipelines import CodePipeline, CodePipelineSource, ShellStep
from my_pipeline.my_pipeline_app_stage import MyPipelineAppStage

class MyPipelineStack(cdk.Stack):

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

        pipeline =  CodePipeline(self, "Pipeline",
                        pipeline_name="MyPipeline",
                        synth=ShellStep("Synth",
                            input=CodePipelineSource.git_hub("OWNER/REPO", "main"),
                            commands=["npm install -g aws-cdk",
                                "python -m pip install -r requirements.txt",
                                "cdk synth"]))

        pipeline.add_stage(MyPipelineAppStage(self, "test",
            env=cdk.Environment(account="111111111111", region="eu-west-1")))
```
Crie o novo arquivo `src/main/java/com.myorg/MyPipelineLambdaStack.java` para armazenar nossa pilha de aplicações contendo uma função do Lambda.  

```
package com.myorg;

import software.constructs.Construct;
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.lambda.InlineCode;

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

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

        Function.Builder.create(this, "LambdaFunction")
          .runtime(Runtime.NODEJS_18_X)
          .handler("index.handler")
          .code(new InlineCode("exports.handler = _ => 'Hello, CDK';"))
          .build();

    }

}
```
Crie o novo arquivo `src/main/java/com.myorg/MyPipelineAppStage.java` para manter nosso estágio.  

```
package com.myorg;

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

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

    public MyPipelineAppStage(final Construct scope, final String id, final StageProps props) {
        super(scope, id, props);

        Stack lambdaStack = new MyPipelineLambdaStack(this, "LambdaStack");
    }

}
```
Edite `src/main/java/com.myorg/MyPipelineStack.java` para adicionar o estágio ao nosso pipeline.  

```
package com.myorg;

import java.util.Arrays;
import software.constructs.Construct;
import software.amazon.awscdk.Environment;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.StageProps;
import software.amazon.awscdk.pipelines.CodePipeline;
import software.amazon.awscdk.pipelines.CodePipelineSource;
import software.amazon.awscdk.pipelines.ShellStep;

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

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

        final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline")
            .pipelineName("MyPipeline")
            .synth(ShellStep.Builder.create("Synth")
                .input(CodePipelineSource.gitHub("OWNER/REPO", "main"))
                .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth"))
                .build())
            .build();

        pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder()
            .env(Environment.builder()
                .account("111111111111")
                .region("eu-west-1")
                .build())
            .build()));
    }
}
```
Crie o novo arquivo `src/MyPipeline/MyPipelineLambdaStack.cs` para armazenar nossa pilha de aplicações contendo uma função do Lambda.  

```
using Amazon.CDK;
using Constructs;
using Amazon.CDK.AWS.Lambda;

namespace MyPipeline
{
    class MyPipelineLambdaStack : Stack
    {
        public MyPipelineLambdaStack(Construct scope, string id, StackProps props=null) : base(scope, id, props)
        {
            new Function(this, "LambdaFunction", new FunctionProps
            {
                Runtime = Runtime.NODEJS_18_X,
                Handler = "index.handler",
                Code = new InlineCode("exports.handler = _ => 'Hello, CDK';")
            });
        }
    }
}
```
Crie o novo arquivo `src/MyPipeline/MyPipelineAppStage.cs` para manter nosso estágio.  

```
using Amazon.CDK;
using Constructs;

namespace MyPipeline
{
    class MyPipelineAppStage : Stage
    {
        public MyPipelineAppStage(Construct scope, string id, StageProps props=null) : base(scope, id, props)
        {
            Stack lambdaStack = new MyPipelineLambdaStack(this, "LambdaStack");
        }
    }
}
```
Edite `src/MyPipeline/MyPipelineStack.cs` para adicionar o estágio ao nosso pipeline.  

```
using Amazon.CDK;
using Constructs;
using Amazon.CDK.Pipelines;

namespace MyPipeline
{
    public class MyPipelineStack : Stack
    {
        internal MyPipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps
            {
                PipelineName = "MyPipeline",
                Synth = new ShellStep("Synth", new ShellStepProps
                {
                    Input = CodePipelineSource.GitHub("OWNER/REPO", "main"),
                    Commands = new string[] { "npm install -g aws-cdk", "cdk synth" }
                })
            });

            pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps
            {
                Env = new Environment
                {
                    Account = "111111111111", Region = "eu-west-1"
                }
            }));
        }
    }
}
```

Cada estágio da aplicação adicionado por `addStage()` resulta na adição de um estágio de pipeline correspondente, representado por uma instância ` [StageDeployment](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.StageDeployment.html) ` retornada pela chamada `addStage()`. É possível adicionar ações de pré-implantação ou pós-implantação ao estágio chamando seu método `addPre()` ou `addPost()`.

**Example**  

```
// import { ManualApprovalStep } from 'aws-cdk-lib/pipelines';

const testingStage = pipeline.addStage(new MyPipelineAppStage(this, 'testing', {
  env: { account: '111111111111', region: 'eu-west-1' }
}));

    testingStage.addPost(new ManualApprovalStep('approval'));
```

```
// const { ManualApprovalStep } = require('aws-cdk-lib/pipelines');

const testingStage = pipeline.addStage(new MyPipelineAppStage(this, 'testing', {
  env: { account: '111111111111', region: 'eu-west-1' }
}));

testingStage.addPost(new ManualApprovalStep('approval'));
```

```
# from aws_cdk.pipelines import ManualApprovalStep

testing_stage = pipeline.add_stage(MyPipelineAppStage(self, "testing",
    env=cdk.Environment(account="111111111111", region="eu-west-1")))

testing_stage.add_post(ManualApprovalStep('approval'))
```

```
// import software.amazon.awscdk.pipelines.StageDeployment;
// import software.amazon.awscdk.pipelines.ManualApprovalStep;

StageDeployment testingStage =
        pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder()
                .env(Environment.builder()
                        .account("111111111111")
                        .region("eu-west-1")
                        .build())
                .build()));

testingStage.addPost(new ManualApprovalStep("approval"));
```

```
var testingStage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps
{
    Env = new Environment
    {
        Account = "111111111111", Region = "eu-west-1"
    }
}));

testingStage.AddPost(new ManualApprovalStep("approval"));
```

É possível adicionar estágios a uma ` [Wave](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.Wave.html) ` para implantá-los paralelamente, por exemplo, ao implantar um estágio em várias contas ou regiões.

**Example**  

```
const wave = pipeline.addWave('wave');
wave.addStage(new MyApplicationStage(this, 'MyAppEU', {
  env: { account: '111111111111', region: 'eu-west-1' }
}));
wave.addStage(new MyApplicationStage(this, 'MyAppUS', {
  env: { account: '111111111111', region: 'us-west-1' }
}));
```

```
const wave = pipeline.addWave('wave');
wave.addStage(new MyApplicationStage(this, 'MyAppEU', {
  env: { account: '111111111111', region: 'eu-west-1' }
}));
wave.addStage(new MyApplicationStage(this, 'MyAppUS', {
  env: { account: '111111111111', region: 'us-west-1' }
}));
```

```
wave = pipeline.add_wave("wave")
wave.add_stage(MyApplicationStage(self, "MyAppEU",
    env=cdk.Environment(account="111111111111", region="eu-west-1")))
wave.add_stage(MyApplicationStage(self, "MyAppUS",
    env=cdk.Environment(account="111111111111", region="us-west-1")))
```

```
// import software.amazon.awscdk.pipelines.Wave;
final Wave wave = pipeline.addWave("wave");
wave.addStage(new MyPipelineAppStage(this, "MyAppEU", StageProps.builder()
        .env(Environment.builder()
                .account("111111111111")
                .region("eu-west-1")
                .build())
        .build()));
wave.addStage(new MyPipelineAppStage(this, "MyAppUS", StageProps.builder()
        .env(Environment.builder()
                .account("111111111111")
                .region("us-west-1")
                .build())
        .build()));
```

```
var wave = pipeline.AddWave("wave");
wave.AddStage(new MyPipelineAppStage(this, "MyAppEU", new StageProps
{
    Env = new Environment
    {
        Account = "111111111111", Region = "eu-west-1"
    }
}));
wave.AddStage(new MyPipelineAppStage(this, "MyAppUS", new StageProps
{
    Env = new Environment
    {
        Account = "111111111111", Region = "us-west-1"
    }
}));
```

## Teste de implantações
<a name="cdk-pipeline-validation"></a>

É possível adicionar etapas a um CDK Pipeline para validar as implantações que você está realizando. Por exemplo, é possível usar o ` [ShellStep](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines.ShellStep.html) ` da biblioteca do CDK Pipelines para realizar tarefas como as seguintes:
+ Tentar acessar um Amazon API Gateway recém-implantado apoiado por uma função do Lambda
+ Verificar a configuração de um recurso implantado emitindo um comando do AWS CDK

Em sua forma mais simples, adicionar ações de validação tem a seguinte aparência:

**Example**  

```
// stage was returned by pipeline.addStage

stage.addPost(new ShellStep("validate", {
  commands: ['../tests/validate.sh'],
}));
```

```
// stage was returned by pipeline.addStage

stage.addPost(new ShellStep("validate", {
  commands: ['../tests/validate.sh'],
}));
```

```
# stage was returned by pipeline.add_stage

stage.add_post(ShellStep("validate",
  commands=[''../tests/validate.sh'']
))
```

```
// stage was returned by pipeline.addStage

stage.addPost(ShellStep.Builder.create("validate")
        .commands(Arrays.asList("'../tests/validate.sh'"))
        .build());
```

```
// stage was returned by pipeline.addStage

stage.AddPost(new ShellStep("validate", new ShellStepProps
{
    Commands = new string[] { "'../tests/validate.sh'" }
}));
```

Muitas implantações do AWS CloudFormation resultam na geração de recursos com nomes imprevisíveis. Por esse motivo, o CDK Pipelines fornece uma maneira de ler as saídas do AWS CloudFormation após uma implantação. Isso possibilita passar (por exemplo) o URL gerado de um balanceador de carga para uma ação de teste.

Para usar as saídas, exponha o objeto `CfnOutput` no qual você tem interesse. Em seguida, passe-o na propriedade `envFromCfnOutputs` de uma etapa para disponibilizá-lo como uma variável de ambiente nessa etapa.

**Example**  

```
// given a stack lbStack that exposes a load balancer construct as loadBalancer
this.loadBalancerAddress = new cdk.CfnOutput(lbStack, 'LbAddress', {
  value: `https://${lbStack.loadBalancer.loadBalancerDnsName}/`
});

// pass the load balancer address to a shell step
stage.addPost(new ShellStep("lbaddr", {
  envFromCfnOutputs: {lb_addr: lbStack.loadBalancerAddress},
  commands: ['echo $lb_addr']
}));
```

```
// given a stack lbStack that exposes a load balancer construct as loadBalancer
this.loadBalancerAddress = new cdk.CfnOutput(lbStack, 'LbAddress', {
  value: `https://${lbStack.loadBalancer.loadBalancerDnsName}/`
});

// pass the load balancer address to a shell step
stage.addPost(new ShellStep("lbaddr", {
  envFromCfnOutputs: {lb_addr: lbStack.loadBalancerAddress},
  commands: ['echo $lb_addr']
}));
```

```
# given a stack lb_stack that exposes a load balancer construct as load_balancer
self.load_balancer_address = cdk.CfnOutput(lb_stack, "LbAddress",
    value=f"https://{lb_stack.load_balancer.load_balancer_dns_name}/")

# pass the load balancer address to a shell step
stage.add_post(ShellStep("lbaddr",
    env_from_cfn_outputs={"lb_addr": lb_stack.load_balancer_address}
    commands=["echo $lb_addr"]))
```

```
// given a stack lbStack that exposes a load balancer construct as loadBalancer
loadBalancerAddress = CfnOutput.Builder.create(lbStack, "LbAddress")
                            .value(String.format("https://%s/",
                                    lbStack.loadBalancer.loadBalancerDnsName))
                            .build();

stage.addPost(ShellStep.Builder.create("lbaddr")
    .envFromCfnOutputs(     // Map.of requires Java 9 or later
        java.util.Map.of("lbAddr", loadBalancerAddress))
    .commands(Arrays.asList("echo $lbAddr"))
    .build());
```

```
// given a stack lbStack that exposes a load balancer construct as loadBalancer
loadBalancerAddress = new CfnOutput(lbStack, "LbAddress", new CfnOutputProps
{
    Value = string.Format("https://{0}/", lbStack.loadBalancer.LoadBalancerDnsName)
});

stage.AddPost(new ShellStep("lbaddr", new ShellStepProps
{
    EnvFromCfnOutputs = new Dictionary<string, CfnOutput>
    {
        {  "lbAddr", loadBalancerAddress }
    },
    Commands = new string[] { "echo $lbAddr" }
}));
```

É possível escrever testes de validação simples diretamente no `ShellStep`, mas essa abordagem se torna complicada quando o teste tem mais do que algumas linhas. Para testes mais complexos, você pode trazer arquivos adicionais (como scripts de shell completos ou programas em outras linguagens) para a propriedade `ShellStep` por meio da propriedade `inputs`. As entradas podem ser qualquer etapa que tenha uma saída, incluindo uma fonte (como um repositório do GitHub) ou outro `ShellStep`.

Trazer arquivos do repositório de origem é apropriado se os arquivos puderem ser usados diretamente no teste (por exemplo, se eles próprios forem executáveis). Neste exemplo, declaramos nosso repositório do GitHub como `source` (em vez de instanciá-lo em linha como parte do `CodePipeline`). Em seguida, passamos esse conjunto de arquivos para o pipeline e para o teste de validação.

**Example**  

```
const source = CodePipelineSource.gitHub('OWNER/REPO', 'main');

const pipeline = new CodePipeline(this, 'Pipeline', {
  pipelineName: 'MyPipeline',
  synth: new ShellStep('Synth', {
    input: source,
    commands: ['npm ci', 'npm run build', 'npx cdk synth']
  })
});

const stage = pipeline.addStage(new MyPipelineAppStage(this, 'test', {
  env: { account: '111111111111', region: 'eu-west-1' }
}));

stage.addPost(new ShellStep('validate', {
  input: source,
  commands: ['sh ../tests/validate.sh']
}));
```

```
const source = CodePipelineSource.gitHub('OWNER/REPO', 'main');

const pipeline = new CodePipeline(this, 'Pipeline', {
  pipelineName: 'MyPipeline',
  synth: new ShellStep('Synth', {
    input: source,
    commands: ['npm ci', 'npm run build', 'npx cdk synth']
  })
});

const stage = pipeline.addStage(new MyPipelineAppStage(this, 'test', {
  env: { account: '111111111111', region: 'eu-west-1' }
}));

stage.addPost(new ShellStep('validate', {
  input: source,
  commands: ['sh ../tests/validate.sh']
}));
```

```
source   = CodePipelineSource.git_hub("OWNER/REPO", "main")

pipeline =  CodePipeline(self, "Pipeline",
                pipeline_name="MyPipeline",
                synth=ShellStep("Synth",
                    input=source,
                    commands=["npm install -g aws-cdk",
                        "python -m pip install -r requirements.txt",
                        "cdk synth"]))

stage = pipeline.add_stage(MyApplicationStage(self, "test",
            env=cdk.Environment(account="111111111111", region="eu-west-1")))

stage.add_post(ShellStep("validate", input=source,
    commands=["sh ../tests/validate.sh"],
))
```

```
final CodePipelineSource source = CodePipelineSource.gitHub("OWNER/REPO", "main");

final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline")
        .pipelineName("MyPipeline")
        .synth(ShellStep.Builder.create("Synth")
                .input(source)
                .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth"))
                .build())
        .build();

final StageDeployment stage =
        pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder()
                .env(Environment.builder()
                        .account("111111111111")
                        .region("eu-west-1")
                        .build())
                .build()));

stage.addPost(ShellStep.Builder.create("validate")
        .input(source)
        .commands(Arrays.asList("sh ../tests/validate.sh"))
        .build());
```

```
var source = CodePipelineSource.GitHub("OWNER/REPO", "main");

var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps
{
    PipelineName = "MyPipeline",
    Synth = new ShellStep("Synth", new ShellStepProps
    {
        Input = source,
        Commands = new string[] { "npm install -g aws-cdk", "cdk synth" }
    })
});

var stage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps
{
    Env = new Environment
    {
        Account = "111111111111", Region = "eu-west-1"
    }
}));

stage.AddPost(new ShellStep("validate", new ShellStepProps
{
    Input = source,
    Commands = new string[] { "sh ../tests/validate.sh" }
}));
```

Obter os arquivos adicionais da etapa de sintetização é apropriado se seus testes precisarem ser compilados, o que é feito como parte da síntese.

**Example**  

```
const synthStep = new ShellStep('Synth', {
  input: CodePipelineSource.gitHub('OWNER/REPO', 'main'),
  commands: ['npm ci', 'npm run build', 'npx cdk synth'],
});

const pipeline = new CodePipeline(this, 'Pipeline', {
  pipelineName: 'MyPipeline',
  synth: synthStep
});

const stage = pipeline.addStage(new MyPipelineAppStage(this, 'test', {
  env: { account: '111111111111', region: 'eu-west-1' }
}));

// run a script that was transpiled from TypeScript during synthesis
stage.addPost(new ShellStep('validate', {
  input: synthStep,
  commands: ['node tests/validate.js']
}));
```

```
const synthStep = new ShellStep('Synth', {
  input: CodePipelineSource.gitHub('OWNER/REPO', 'main'),
  commands: ['npm ci', 'npm run build', 'npx cdk synth'],
});

const pipeline = new CodePipeline(this, 'Pipeline', {
  pipelineName: 'MyPipeline',
  synth: synthStep
});

const stage = pipeline.addStage(new MyPipelineAppStage(this, "test", {
  env: { account: "111111111111", region: "eu-west-1" }
}));

// run a script that was transpiled from TypeScript during synthesis
stage.addPost(new ShellStep('validate', {
  input: synthStep,
  commands: ['node tests/validate.js']
}));
```

```
synth_step = ShellStep("Synth",
                input=CodePipelineSource.git_hub("OWNER/REPO", "main"),
                commands=["npm install -g aws-cdk",
                  "python -m pip install -r requirements.txt",
                  "cdk synth"])

pipeline   = CodePipeline(self, "Pipeline",
                pipeline_name="MyPipeline",
                synth=synth_step)

stage = pipeline.add_stage(MyApplicationStage(self, "test",
            env=cdk.Environment(account="111111111111", region="eu-west-1")))

# run a script that was compiled during synthesis
stage.add_post(ShellStep("validate",
    input=synth_step,
    commands=["node test/validate.js"],
))
```

```
final ShellStep synth = ShellStep.Builder.create("Synth")
                            .input(CodePipelineSource.gitHub("OWNER/REPO", "main"))
                            .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth"))
                            .build();

final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline")
        .pipelineName("MyPipeline")
        .synth(synth)
        .build();

final StageDeployment stage =
        pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder()
                .env(Environment.builder()
                        .account("111111111111")
                        .region("eu-west-1")
                        .build())
                .build()));

stage.addPost(ShellStep.Builder.create("validate")
        .input(synth)
        .commands(Arrays.asList("node ./tests/validate.js"))
        .build());
```

```
var synth = new ShellStep("Synth", new ShellStepProps
{
    Input = CodePipelineSource.GitHub("OWNER/REPO", "main"),
    Commands = new string[] { "npm install -g aws-cdk", "cdk synth" }
});

var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps
{
    PipelineName = "MyPipeline",
    Synth = synth
});

var stage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps
{
    Env = new Environment
    {
        Account = "111111111111", Region = "eu-west-1"
    }
}));

stage.AddPost(new ShellStep("validate", new ShellStepProps
{
    Input = synth,
    Commands = new string[] { "node ./tests/validate.js" }
}));
```

## Observações de segurança
<a name="cdk-pipeline-security"></a>

Qualquer forma de entrega contínua tem riscos de segurança inerentes. De acordo com o [Modelo de Responsabilidade Compartilhada](https://aws.amazon.com/compliance/shared-responsibility-model/) da AWS, você é responsável pela segurança de suas informações na Nuvem AWS. A biblioteca do CDK Pipelines oferece uma vantagem inicial ao incorporar padrões seguros e práticas recomendadas de modelagem.

No entanto, por sua própria natureza, uma biblioteca que precisa de um alto nível de acesso para cumprir a finalidade pretendida não pode garantir segurança total. Há muitos vetores de ataque fora da sua organização da AWS.

Em especial, considere o seguinte:
+ Leve em consideração o software do qual você depende. Verifique todos os softwares de terceiros que você executa em seu pipeline, pois eles podem mudar a infraestrutura que é implantada.
+ Use o bloqueio de dependências para evitar atualizações acidentais. O CDK Pipelines respeita `package-lock.json` e `yarn.lock` para garantir que suas dependências sejam as que você espera.
+ O CDK Pipelines é executado em recursos criados em sua própria conta, e a configuração desses recursos é controlada pelos desenvolvedores que enviam o código pelo pipeline. Portanto, o CDK Pipelines por si só não pode se proteger contra desenvolvedores mal-intencionados que tentam burlar as verificações de conformidade. Se seu modelo de ameaça incluir desenvolvedores que escrevem código do CDK, é necessário ter mecanismos externos de conformidade, como [Hooks do AWS CloudFormation](https://aws.amazon.com/blogs/mt/proactively-keep-resources-secure-and-compliant-with-aws-cloudformation-hooks/) (preventivos) ou [AWS Config](https://aws.amazon.com/config/) (reativos), que o perfil de execução do AWS não tenha permissão para desabilitar.
+ As credenciais para ambientes de produção devem durar pouco. Após o bootstrapping e o provisionamento inicial, não é necessário que os desenvolvedores tenham as credenciais da conta. As mudanças podem ser implantadas por meio do pipeline. Reduza a possibilidade de vazamento de credenciais ao não precisar delas em primeiro lugar.

## Solução de problemas
<a name="cdk-pipeline-troubleshooting"></a>

Os problemas a seguir são comumente encontrados ao começar a usar o CDK Pipelines.

 **Pipeline: falha interna**   

```
CREATE_FAILED  | {aws}::CodePipeline::Pipeline | Pipeline/Pipeline
Internal Failure
```
Verifique o token de acesso do GitHub. Ele pode estar ausente ou pode não ter as permissões para acessar o repositório.

 **Chave: a política contém uma declaração com uma ou mais entidades principais inválidas**   

```
CREATE_FAILED | {aws}::KMS::Key | Pipeline/Pipeline/ArtifactsBucketEncryptionKey
Policy contains a statement with one or more invalid principals.
```
Um dos ambientes de destino não foi inicializado com a nova pilha de bootstrap. Certifique-se de fazer o bootstrapping em todos os seus ambientes de destino.

 **A pilha está no estado ROLLBACK\$1COMPLETE e não pode ser atualizada**   

```
Stack <STACK_NAME> is in ROLLBACK_COMPLETE state and cannot be updated. (Service:
AmazonCloudFormation; Status Code: 400; Error Code: ValidationError; Request
ID: ...)
```
A pilha falhou em sua implantação anterior e está em um estado que não pode ser repetido. Exclua a pilha do console do AWS CloudFormation e repita a implantação.

# Criação e implantação de ativos de imagem de contêiner em aplicações do CDK
<a name="build-containers"></a>

Quando você cria ativos de imagem de contêiner com o kit de desenvolvimento em nuvem da AWS (CDK da AWS), o Docker é utilizado por padrão para realizar essas ações. Se você desejar usar uma ferramenta diferente de gerenciamento de contêineres, poderá substituir o Docker por meio da variável de ambiente `CDK_DOCKER`.

## Exemplo: criação e publicação de um ativo de imagem de contêiner com o AWS CDK
<a name="build-containers-intro-example"></a>

Veja a seguir um exemplo simples de uma aplicação do AWS CDK que cria e publica um ativo de contêiner no Amazon Elastic Container Registry (Amazon ECR) usando o Docker por padrão:

 **Estrutura do projeto**   

```
my-cdk-app/
├── lib/
│   ├── my-stack.ts
│   └── docker/
│       ├── Dockerfile
│       └── app/
│           └── index.js
├── bin/
│   └── my-cdk-app.ts
├── package.json
├── tsconfig.json
└── cdk.json
```

 **Dockerfile**   

```
FROM public.ecr.aws/lambda/nodejs:16

# Copy application code
COPY app/ /var/task/

# (Optional) Install dependencies
# RUN npm install

# The Lambda Node.js base image looks for index.handler by default
```

 **Código da aplicação**   
Em `lib/docker/app/index.js`:  

```
console.log("Hello from inside the container!");
```

 **Pilha do CDK**   

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ecr_assets from 'aws-cdk-lib/aws-ecr-assets';

export class MyStack extends cdk.Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    // Define a Docker image asset
    const dockerImageAsset = new ecr_assets.DockerImageAsset(this, 'MyDockerImage', {
      directory: 'lib/docker', // Path to the directory containing the Dockerfile
    });

    // Output the ECR URI
    new cdk.CfnOutput(this, 'ECRImageUri', {
      value: dockerImageAsset.imageUri,
    });
  }
}
```

 **Aplicação do CDK**   

```
#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { MyStack } from '../lib/my-stack';

const app = new cdk.App();
new MyStack(app, 'MyStack');
```

Quando executamos `cdk deploy`, a interface de linha de comandos (CLI) do kit de desenvolvimento em nuvem da AWS (CDK da AWS) faz o seguinte:

1.  **Cria a imagem do Docker**: executa `docker build` localmente com base no `Dockerfile` no diretório especificado (`lib/docker`).

1.  **Marca a imagem**: executa `docker tag` para marcar a imagem criada com um hash exclusivo, com base no conteúdo da imagem.

1.  **Publica no Amazon ECR**: executa `docker push` para publicar a imagem do contêiner em um repositório do Amazon ECR. O repositório já deve existir. Ele é criado durante o processo de bootstrapping padrão.

1.  **Exibe o URI da imagem**: depois de uma implantação com êxito, o URI do Amazon ECR da imagem do contêiner publicada é exibido em seu prompt de comando. Esse é o URI da nossa imagem do Docker no Amazon ECR.

## Como substituir o Docker por outra ferramenta de gerenciamento de contêineres
<a name="build-container-replace"></a>

Use a variável de ambiente `CDK_DOCKER` para especificar o caminho para o binário da sua ferramenta de gerenciamento de contêineres substituta. Veja a seguir um exemplo de substituição do Docker pelo Finch:

```
$ which finch
/usr/local/bin/finch # Locate the path to the binary

$ export CDK_DOCKER='/usr/local/bin/finch' # Set the environment variable

$ cdk deploy # Deploy using the replacement
```

Não há suporte para aliases ou vinculação. Para substituir o Docker, é necessário usar a variável de ambiente `CDK_DOCKER`.

## Mecanismos de substituição direta do Docker com suporte
<a name="build-container-supported"></a>

 Há suporte para o Finch, embora alguns recursos do Docker possam estar indisponíveis ou funcionar de forma diferente à medida que a ferramenta evolui. Para obter mais informações sobre o Finch, consulte [Pronto para decolar: anúncio do Finch 1.0 GA\$1](https://aws.amazon.com/blogs/opensource/ready-for-flight-announcing-finch-1-0-ga/) no *blog AWS Open Source*.

Outras ferramentas de gerenciamento de contêineres podem funcionar. O CDK não verifica qual substituto do Docker você está usando para determinar se há suporte. Se a ferramenta tiver comandos equivalentes do Docker e se comportar de forma semelhante, deverá funcionar.

# Solução de problemas de implantações do CDK da AWS
<a name="deploy-troubleshoot"></a>

Solucione problemas comuns ao implantar aplicações do kit de desenvolvimento em nuvem da AWS (CDK da AWS).

## As entidades principais de serviço incorretas estão sendo criadas na implantação
<a name="deploy-troubleshoot-sp"></a>

Ao implantar aplicações do CDK que contenham perfis do AWS Identity and Access Management (IAM) com entidades principais de serviço, você descobre que domínios incorretos para as entidades principais de serviço estão sendo criadas.

A seguir está um exemplo básico da criação de um perfil do IAM que pode ser assumido pelo Amazon CloudWatch Logs usando sua entidade principal de serviço:

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

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

    // Create an IAM role for CloudWatch Logs to assume
    const cloudWatchLogsRole = new iam.Role(this, 'CloudWatchLogsRole', {
      assumedBy: new iam.ServicePrincipal('logs.amazonaws.com'), // This is for CloudWatch Logs
      managedPolicies: [
        iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSCloudWatchLogsFullAccess')
      ]
    });

    // You can then use this role in other constructs or configurations where CloudWatch Logs needs to assume a role
  }
}
```

Quando você implanta essa pilha, uma entidade principal de serviço chamada `logs.amazonaws.com` deve ser criada. Na maioria dos casos, os serviços da AWS usam a nomenclatura a seguir para entidades principais de serviço: `<service>.amazonaws.com`.

### Causas comuns
<a name="deploy-troubleshoot-sp-causes"></a>

Se você estiver usando uma versão do AWS CDK anterior à v2.150.0, poderá encontrar esse bug. Nas versões mais antigas do AWS CDK, a nomenclatura das entidades principais de serviço não era padronizada, o que poderia levar à criação de entidades principais de serviço com domínios incorretos.

No AWS CDK v2.51.0, uma correção foi implementada padronizando todas as entidades principais de serviço criadas automaticamente para usar `<service>.amazonaws.com` quando possível. Essa correção estava disponível ao permitir o sinalizador de atributo de `@aws-cdk/aws-iam:standardizedServicePrincipals`.

A partir do AWS CDK v2.150.0, esse se tornou o comportamento padrão.

### Resolução
<a name="deploy-troubleshoot-sp-resolution"></a>

Atualize para o AWS CDK v2.150.0 ou mais recente.

Se você não conseguir atualizar para o AWS CDK v2.150.0 ou mais recente, deverá atualizar para pelo menos v2.51.0 ou mais recente. Em seguida, permita o seguinte sinalizador de atributo em seu arquivo `cdk.json`: `@aws-cdk/aws-iam:standardizedServicePrincipals`.