View a markdown version of this page

Identificadores e o CDK AWS - AWS Kit de desenvolvimento em nuvem (AWS CDK) v2

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

Identificadores e o CDK AWS

Ao criar aplicativos do AWS Cloud Development Kit (AWS CDK), você usará vários tipos de identificadores e nomes. Para usar o AWS CDK de 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 seu aplicativo AWS CDK.

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

Construir IDs

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.

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.

exemplo
TypeScript
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');
JavaScript
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');
Python
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')
Java
// 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"); } }
C#
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

As construções em um aplicativo AWS CDK formam uma hierarquia enraizada na classe. App Nós nos referimos à coleção IDs de uma determinada construção, sua construção original, sua avô e assim por diante até a raiz da árvore de construção, como um caminho.

O AWS CDK normalmente exibe caminhos em seus modelos como uma string. Os IDs níveis são separados por barras, começando no nó imediatamente abaixo da App instância raiz, 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 IDs devem ser exclusivos dentro do escopo em que são criados, seus caminhos são sempre exclusivos em um aplicativo AWS CDK.

exemplo
TypeScript
const path: string = myConstruct.node.path;
JavaScript
const path = myConstruct.node.path;
Python
path = my_construct.node.path
Java
String path = myConstruct.getNode().getPath();
C#
string path = myConstruct.Node.Path;

Único IDs

AWS CloudFormation exige que toda lógica IDs em um modelo seja exclusiva. Por isso, o AWS CDK deve ser capaz de gerar um identificador exclusivo para cada construção em um aplicativo. Os recursos têm caminhos que são globalmente exclusivos (os nomes de todos os escopos da pilha até um recurso específico). Portanto, o 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 eA/BC, que resultariam no mesmo AWS CloudFormation identificador. AWS CloudFormation os identificadores são alfanuméricos e não podem conter barras ou outros caracteres separadores.) O AWS CDK chama essa string de ID exclusiva da construção.

Em geral, seu aplicativo AWS CDK não precisa conhecer o que é exclusivo IDs. No entanto, é possível acessar programaticamente o ID exclusivo de qualquer constructo, conforme mostrado no exemplo a seguir.

exemplo
TypeScript
const uid: string = Names.uniqueId(myConstruct);
JavaScript
const uid = Names.uniqueId(myConstruct);
Python
uid = Names.unique_id(my_construct)
Java
String uid = Names.uniqueId(myConstruct);
C#
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. Algumas construções podem usar o endereço no AWS CloudFormation modelo sintetizado 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.

exemplo
TypeScript
const addr: string = myConstruct.node.addr;
JavaScript
const addr = myConstruct.node.addr;
Python
addr = my_construct.node.addr
Java
String addr = myConstruct.getNode().getAddr();
C#
string addr = myConstruct.Node.Addr;

Lógico IDs

Quando o AWS CDK sintetiza seu aplicativo em um AWS CloudFormation modelo, ele gera uma ID lógica para cada recurso. AWS CloudFormation usa IDs a lógica para identificar recursos em um modelo e rastreá-los em todas as implantações. Entender como a lógica IDs é gerada ajuda a evitar substituições não intencionais de recursos ao refatorar seu código CDK.

Como a lógica IDs é gerada

O AWS CDK gera lógica a IDs partir do caminho de construção usando o seguinte algoritmo:

  1. Concatene os componentes do caminho da árvore de construção, excluindo a própria pilha.

  2. Aplique heurísticas para melhorar a legibilidade (consulte Heurística do componente do caminho do Logical ID).

  3. Adicione um hash de 8 caracteres do caminho completo para garantir a exclusividade.

O formato resultante é:

<human-readable-portion><8-character-hash>

Por exemplo, uma tabela de rotas de sub-rede privada da VPC pode produzir a ID lógica. VPCPrivateSubnet2RouteTable0A19E10E

As regras a seguir se aplicam à geração lógica de ID:

  • O tamanho máximo é de 255 caracteres. A parte legível por humanos é limitada a 240 caracteres.

  • O hash de 8 caracteres garante que caminhos como A/B/C e A/BC — que se concatenam na mesma string — produzam lógicas diferentes. IDs

  • Recursos que são filhos diretos da pilha (caminhos de componente único) usam seus nomes diretamente sem um hash, desde que o nome tenha 255 caracteres ou menos.

Heurística do componente do caminho de ID lógico

O AWS CDK aplica a seguinte heurística aos componentes do caminho ao gerar a parte lógica legível por humanos. IDs

Default— removido inteiramente

Se um componente de caminho forDefault, o CDK o removerá da parte legível por humanos e da entrada de hash. Isso significa que agrupar uma construção existente dentro de uma nova construção — e nomear a construção interna Default — produz exatamente o mesmo ID lógico da construção original desembrulhada. Esse é o principal mecanismo para refatorar com segurança o código simples em construções de nível superior sem alterar as identidades dos recursos implantados.

Resource— oculto somente da parte legível por humanos

Se um componente de caminho forResource, o CDK o omite da parte legível por humanos, mas ainda o incluirá no cálculo de hash. As construções L1 (CloudFormation) são usadas Resource como ID de construção por convenção. Isso mantém a lógica IDs mais curta sem perder a exclusividade.

Componentes consecutivos duplicados — desduplicados

Se o nome do componente do caminho anterior terminar com o nome do componente atual, o CDK ignorará o componente atual. Isso evita a repetição redundante na lógica. IDs

Use Default para preservar a lógica IDs ao refatorar

Ao refatorar uma pilha plana em construções de nível superior, você pode usá-la Default como ID de construção do recurso primário para preservar sua ID lógica. Isso AWS CloudFormation impede a substituição do recurso durante a implantação.

O exemplo a seguir mostra uma pilha com recursos definidos diretamente:

exemplo
TypeScript
export class MyStack extends cdk.Stack { constructor(scope: Construct, id: string) { super(scope, id); new s3.Bucket(this, 'DataBucket'); new lambda.Function(this, 'ProcessFunction', { /* ... */ }); } }
JavaScript
class MyStack extends cdk.Stack { constructor(scope, id) { super(scope, id); new s3.Bucket(this, 'DataBucket'); new lambda.Function(this, 'ProcessFunction', { /* ... */ }); } }
Python
from aws_cdk import ( Stack, aws_s3 as s3, aws_lambda as _lambda, ) from constructs import Construct class MyStack(Stack): def __init__(self, scope: Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) s3.Bucket(self, "DataBucket") _lambda.Function(self, "ProcessFunction", # ... )
Java
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.Function; 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, "DataBucket"); Function.Builder.create(this, "ProcessFunction") // ... .build(); } }
C#
using Amazon.CDK; using Constructs; using Amazon.CDK.AWS.S3; using Amazon.CDK.AWS.Lambda; namespace MyApp { public class MyStack : Stack { public MyStack(Construct scope, string id, StackProps props = null) : base(scope, id, props) { new Bucket(this, "DataBucket"); new Function(this, "ProcessFunction", new FunctionProps { // ... }); } } }
Go
package main import ( "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 MyStackProps struct { awscdk.StackProps } func NewMyStack(scope constructs.Construct, id string, props *MyStackProps) awscdk.Stack { stack := awscdk.NewStack(scope, &id, &props.StackProps) awss3.NewBucket(stack, jsii.String("DataBucket"), &awss3.BucketProps{}) awslambda.NewFunction(stack, jsii.String("ProcessFunction"), &awslambda.FunctionProps{ // ... }) return stack }

O caminho do bucket éMyStack/DataBucket/Resource, o que produz uma identificação lógica deDataBucket<hash>.

Você pode extrair o bucket em uma construção de nível superior e preservar a mesma ID lógica nomeando a construção interna: Default

exemplo
TypeScript
class DataPipeline extends Construct { constructor(scope: Construct, id: string) { super(scope, id); new s3.Bucket(this, 'Default'); // 'Default' is hidden from logical ID new lambda.Function(this, 'ProcessFunction', { /* ... */ }); } } export class MyStack extends cdk.Stack { constructor(scope: Construct, id: string) { super(scope, id); new DataPipeline(this, 'DataBucket'); } }
JavaScript
class DataPipeline extends Construct { constructor(scope, id) { super(scope, id); new s3.Bucket(this, 'Default'); // 'Default' is hidden from logical ID new lambda.Function(this, 'ProcessFunction', { /* ... */ }); } } class MyStack extends cdk.Stack { constructor(scope, id) { super(scope, id); new DataPipeline(this, 'DataBucket'); } }
Python
from aws_cdk import ( Stack, aws_s3 as s3, aws_lambda as _lambda, ) from constructs import Construct class DataPipeline(Construct): def __init__(self, scope: Construct, id: str) -> None: super().__init__(scope, id) s3.Bucket(self, "Default") # 'Default' is hidden from logical ID _lambda.Function(self, "ProcessFunction", # ... ) class MyStack(Stack): def __init__(self, scope: Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs) DataPipeline(self, "DataBucket")
Java
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.Function; public class DataPipeline extends Construct { public DataPipeline(final Construct scope, final String id) { super(scope, id); new Bucket(this, "Default"); // 'Default' is hidden from logical ID Function.Builder.create(this, "ProcessFunction") // ... .build(); } } 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 DataPipeline(this, "DataBucket"); } }
C#
using Amazon.CDK; using Constructs; using Amazon.CDK.AWS.S3; using Amazon.CDK.AWS.Lambda; namespace MyApp { public class DataPipeline : Construct { public DataPipeline(Construct scope, string id) : base(scope, id) { new Bucket(this, "Default"); // 'Default' is hidden from logical ID new Function(this, "ProcessFunction", new FunctionProps { // ... }); } } public class MyStack : Stack { public MyStack(Construct scope, string id, StackProps props = null) : base(scope, id, props) { new DataPipeline(this, "DataBucket"); } } }
Go
package main import ( "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 DataPipeline struct { constructs.Construct } func NewDataPipeline(scope constructs.Construct, id string) constructs.Construct { this := constructs.NewConstruct(scope, &id) // 'Default' is hidden from logical ID awss3.NewBucket(this, jsii.String("Default"), &awss3.BucketProps{}) awslambda.NewFunction(this, jsii.String("ProcessFunction"), &awslambda.FunctionProps{ // ... }) return this } type MyStackProps struct { awscdk.StackProps } func NewMyStack(scope constructs.Construct, id string, props *MyStackProps) awscdk.Stack { stack := awscdk.NewStack(scope, &id, &props.StackProps) NewDataPipeline(stack, "DataBucket") return stack }

O caminho do balde é agoraMyStack/DataBucket/Default/Resource. Como Default é removido da parte legível por humanos e da entrada de hash, o ID lógico permanece DataBucket<hash> — idêntico ao original.

Importante

Você pode ter somente um filho com o ID Default por escopo de construção. Se você precisar de vários recursos no mesmo nível, forneça-os descritivos. IDs O Default padrão funciona melhor com construções de responsabilidade única que têm um recurso primário.

Limitações e considerações

Lembre-se do seguinte ao trabalhar com lógica IDs:

  • Você pode atribuir a ID de Default construção somente a um filho por escopo.

  • Se você alterar uma ID de construção após a implantação, a ID lógica será alterada, o que fará com AWS CloudFormation que o recurso seja substituído. Use cdk diff para verificar as alterações antes da implantação.

  • Nos casos em que a lógica IDs já foi alterada, você pode usar o cdk refactor comando para mapear a lógica antiga IDs para a nova. Para obter mais informações, consulte Preservar recursos implantados ao refatorar o código do CDK.

  • Para obter mais informações sobre como a lógica IDs aparece em modelos sintetizados, consulte Lógica gerada IDs em seu AWS CloudFormation modelo.

Estabilidade de ID lógico

Evite alterar a ID lógica de um recurso após sua criação. AWS CloudFormation identifica os recursos por meio de sua ID lógica. Portanto, se você alterar a ID lógica de um recurso, AWS CloudFormation cria um novo recurso com a nova ID lógica e exclui a existente. Dependendo do tipo de recurso, isso pode causar interrupção do serviço, perda de dados ou ambas.