

Ini adalah Panduan Pengembang AWS CDK v2. CDK v1 yang lebih lama memasuki pemeliharaan pada 1 Juni 2022 dan mengakhiri dukungan pada 1 Juni 2023.

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Pelajari AWS konsep inti CDK
<a name="core-concepts"></a>

Pelajari konsep inti di balik AWS Cloud Development Kit (AWS CDK).

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

 AWS CDK adalah kerangka kerja sumber terbuka yang dapat Anda gunakan untuk mengelola AWS infrastruktur Anda menggunakan kode. Pendekatan ini dikenal sebagai *infrastruktur sebagai code (IaC)*. Dengan mengelola dan menyediakan infrastruktur Anda sebagai kode, Anda memperlakukan infrastruktur Anda dengan cara yang sama seperti pengembang memperlakukan kode. Ini memberikan banyak manfaat, seperti kontrol versi dan skalabilitas. Untuk mempelajari lebih lanjut tentang IAc, lihat [Apa itu Infrastruktur sebagai Kode?](https://aws.amazon.com/what-is/iac/) 

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

 AWS CDK terintegrasi erat dengan AWS CloudFormation. AWS CloudFormation adalah layanan yang dikelola sepenuhnya yang dapat Anda gunakan untuk mengelola dan menyediakan infrastruktur Anda AWS. Dengan AWS CloudFormation, Anda menentukan infrastruktur Anda dalam template dan AWS CloudFormation menerapkannya. AWS CloudFormation Layanan kemudian menyediakan infrastruktur Anda sesuai dengan konfigurasi yang ditentukan dalam template Anda.

 AWS CloudFormation template bersifat *deklaratif*, artinya mereka mendeklarasikan status atau hasil yang diinginkan dari infrastruktur Anda. **Menggunakan JSON atau YAMB, Anda mendeklarasikan AWS infrastruktur Anda dengan mendefinisikan AWS sumber daya dan properti.** Sumber daya mewakili banyak layanan AWS dan properti mewakili konfigurasi yang Anda inginkan dari layanan tersebut. Saat Anda menerapkan templat AWS CloudFormation, sumber daya dan properti yang dikonfigurasikan akan disediakan seperti yang dijelaskan dalam templat Anda.

Dengan AWS CDK, Anda dapat mengelola infrastruktur Anda *secara imperatif*, menggunakan bahasa pemrograman tujuan umum. Alih-alih hanya mendefinisikan keadaan yang diinginkan secara deklaratif, Anda dapat menentukan logika atau urutan yang diperlukan untuk mencapai keadaan yang diinginkan. Misalnya, Anda dapat menggunakan `if` pernyataan atau loop bersyarat yang menentukan cara mencapai status akhir yang diinginkan untuk infrastruktur Anda.

Infrastruktur yang dibuat dengan AWS CDK akhirnya diterjemahkan, atau *disintesis* ke dalam AWS CloudFormation template dan digunakan menggunakan layanan. AWS CloudFormation Jadi, sementara AWS CDK menawarkan pendekatan berbeda untuk membuat infrastruktur Anda, Anda masih menerima manfaatnya AWS CloudFormation, seperti dukungan konfigurasi AWS sumber daya yang luas dan proses penerapan yang kuat.

Untuk mempelajari lebih lanjut tentang AWS CloudFormation, lihat [Apa itu AWS CloudFormation?](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html) dalam * AWS CloudFormation User Guide*.

## AWS CDK dan abstraksi
<a name="concepts-abstractions"></a>

Dengan AWS CloudFormation, Anda harus menentukan setiap detail tentang bagaimana sumber daya Anda dikonfigurasi. Ini memberikan manfaat memiliki kontrol penuh atas infrastruktur Anda. Namun, ini mengharuskan Anda untuk mempelajari, memahami, dan membuat templat tangguh yang berisi detail konfigurasi sumber daya dan hubungan antar sumber daya, seperti izin dan interaksi berbasis peristiwa.

Dengan AWS CDK, Anda dapat memiliki kontrol yang sama atas konfigurasi sumber daya Anda. Namun, AWS CDK juga menawarkan abstraksi yang kuat, yang dapat mempercepat dan menyederhanakan proses pengembangan infrastruktur. Misalnya, AWS CDK menyertakan konstruksi yang menyediakan konfigurasi default yang masuk akal dan metode pembantu yang menghasilkan kode boilerplate untuk Anda. AWS CDK juga menawarkan alat, seperti AWS CDK Command Line Interface (AWS CDK CLI), yang melakukan tindakan manajemen infrastruktur untuk Anda.

## Pelajari lebih lanjut tentang konsep inti AWS CDK
<a name="concepts-learn"></a><a name="concepts-learn-interact"></a>

 **Berinteraksi dengan CDK AWS **   
Saat menggunakan AWS CDK, Anda terutama akan berinteraksi dengan AWS Construct Library dan AWS CDK CLI.<a name="concepts-learn-develop"></a>

 **Berkembang dengan AWS CDK**   
 AWS CDK dapat ditulis dalam [bahasa pemrograman yang didukung](languages.md). Anda mulai dengan [proyek CDK](projects.md), yang berisi struktur folder dan file, termasuk [aset](assets.md). Dalam proyek, Anda membuat [aplikasi CDK](apps.md). Di dalam aplikasi, Anda menentukan [tumpukan](stacks.md), yang secara langsung mewakili CloudFormation tumpukan. Dalam tumpukan, Anda menentukan AWS sumber daya dan properti Anda menggunakan [konstruksi.](constructs.md)<a name="concepts-learn-deploy"></a>

 **Menyebarkan dengan CDK AWS **   
[Anda menyebarkan aplikasi CDK ke lingkungan AWS .](environments.md) Sebelum menerapkan, Anda harus melakukan [bootstrap satu kali untuk mempersiapkan lingkungan](bootstrapping.md) Anda.<a name="concepts-learn-more"></a>

 **Pelajari selengkapnya**   
Untuk mempelajari lebih lanjut tentang konsep inti AWS CDK, lihat topik di bagian ini.

# Bahasa pemrograman yang didukung untuk AWS CDK
<a name="languages"></a>

 AWS Cloud Development Kit (AWS CDK) memiliki dukungan kelas satu untuk bahasa pemrograman tujuan umum berikut:
+ TypeScript
+ JavaScript
+ Python
+ Java
+ C\$1
+  Go 

Lainnya JVM and .NET CLR bahasa juga dapat digunakan secara teori, tetapi kami tidak menawarkan dukungan resmi saat ini.

 AWS CDK dikembangkan dalam satu bahasa. TypeScript Untuk mendukung bahasa lain, AWS CDK menggunakan alat yang disebut [JSII](https://github.com/aws/jsii) untuk menghasilkan binding bahasa.

Kami mencoba menawarkan konvensi biasa setiap bahasa untuk membuat pengembangan dengan AWS CDK sealami dan seintuitif mungkin. Misalnya, kami mendistribusikan modul AWS Construct Library menggunakan repositori standar bahasa pilihan Anda, dan Anda menginstalnya menggunakan pengelola paket standar bahasa tersebut. Metode dan properti juga diberi nama menggunakan pola penamaan yang direkomendasikan bahasa Anda.

Berikut ini adalah beberapa contoh kode:

**Example**  

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

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

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

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

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

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

**catatan**  
Cuplikan kode ini ditujukan hanya untuk ilustrasi. Mereka tidak lengkap dan tidak akan berjalan sebagaimana adanya.

Perpustakaan AWS Konstruksi didistribusikan menggunakan alat manajemen paket standar masing-masing bahasa, termasuk NPM, PyPi, Maven, dan NuGet. Kami juga menyediakan versi [Referensi API AWS CDK](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html) untuk setiap bahasa.

Untuk membantu Anda menggunakan AWS CDK dalam bahasa pilihan Anda, panduan ini mencakup topik berikut untuk bahasa yang didukung:
+  [Bekerja dengan AWS CDK di TypeScript](work-with-cdk-typescript.md) 
+  [Bekerja dengan AWS CDK di JavaScript](work-with-cdk-javascript.md) 
+  [Bekerja dengan AWS CDK dengan Python](work-with-cdk-python.md) 
+  [Bekerja dengan AWS CDK di Jawa](work-with-cdk-java.md) 
+  [Bekerja dengan AWS CDK di C \$1](work-with-cdk-csharp.md) 
+  [Bekerja dengan AWS CDK di Go](work-with-cdk-go.md) 

TypeScript adalah bahasa pertama yang didukung oleh AWS CDK, dan sebagian besar kode contoh AWS CDK ditulis. TypeScript Panduan ini mencakup topik khusus untuk menunjukkan cara mengadaptasi kode TypeScript AWS CDK untuk digunakan dengan bahasa lain yang didukung. Untuk informasi selengkapnya, lihat [Membandingkan AWS CDK TypeScript dengan bahasa lain](work-with.md#work-with-cdk-compare).

# AWS Pustaka CDK
<a name="libraries"></a>

Pelajari tentang pustaka inti yang akan Anda gunakan dengan AWS Cloud Development Kit (AWS CDK).

## Perpustakaan AWS CDK
<a name="libraries-cdk"></a>

Perpustakaan AWS CDK, juga disebut sebagai`aws-cdk-lib`, adalah perpustakaan utama yang akan Anda gunakan untuk mengembangkan aplikasi dengan AWS CDK. Ini dikembangkan dan dipelihara oleh AWS. Pustaka ini berisi kelas dasar, seperti [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html)dan [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html). Ini juga berisi pustaka yang akan Anda gunakan untuk menentukan infrastruktur Anda melalui konstruksi.

## Perpustakaan AWS Konstruksi
<a name="libraries-construct"></a>

Perpustakaan AWS Konstruksi adalah bagian dari Perpustakaan AWS CDK. Ini berisi kumpulan [konstruksi](constructs.md) yang dikembangkan dan dipelihara oleh AWS. Ini diatur ke dalam berbagai modul untuk setiap AWS layanan. Setiap modul menyertakan konstruksi yang dapat Anda gunakan untuk menentukan AWS sumber daya dan properti Anda.

## Perpustakaan Constructs
<a name="libraries-constructs"></a>

Library Constructs, biasa disebut sebagai`constructs`, adalah perpustakaan untuk mendefinisikan dan menyusun komponen infrastruktur cloud. Ini berisi [https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html)kelas inti, yang mewakili blok bangunan konstruksi. Kelas ini adalah kelas dasar dasar dari semua konstruksi dari Construct Library AWS . *Pustaka Constructs adalah pustaka tujuan umum terpisah yang digunakan oleh alat berbasis konstruksi lainnya seperti *CDK untuk Terraform dan CDK untuk* Kubernetes.*

## Referensi API AWS CDK
<a name="libraries-reference"></a>

[Referensi AWS CDK API](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html) berisi dokumentasi referensi resmi untuk AWS CDK Library, termasuk AWS Construct Library dan Constructs library. Versi referensi API disediakan untuk setiap bahasa pemrograman yang didukung.
+ Untuk dokumentasi AWS CDK Library (`aws-cdk-lib`), lihat [aws-cdk-lib modul](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html).
+ Dokumentasi untuk konstruksi di Perpustakaan AWS Konstruksi diatur oleh AWS layanan dalam format berikut:. `aws-cdk-lib.<service>` [Misalnya, dokumentasi konstruksi untuk Amazon Simple Storage Service (Amazon S3) Simple Storage Service (Amazon S3), dapat ditemukan di modul.aws\$1s3. aws-cdk-lib](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3-readme.html)
+ Untuk dokumentasi Constructs library (constructs), lihat modul [constructs](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs-readme.html).

### Berkontribusi pada referensi API AWS CDK
<a name="libraries-reference-contribute"></a>

 AWS CDK adalah sumber terbuka dan kami menyambut Anda untuk berkontribusi. Kontribusi masyarakat berdampak positif dan meningkatkan AWS CDK. Untuk petunjuk tentang berkontribusi secara khusus pada dokumentasi referensi API AWS CDK, lihat [Dokumentasi di aws-cdk](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md#documentation) * GitHub repositori*.

## Pelajari selengkapnya
<a name="libraries-learn"></a>

Untuk petunjuk tentang mengimpor dan menggunakan Perpustakaan CDK, lihat [Bekerja dengan pustaka CDK](work-with.md).

# AWS Proyek CDK
<a name="projects"></a>

Proyek AWS Cloud Development Kit (AWS CDK) mewakili file dan folder yang berisi kode CDK Anda. Konten akan bervariasi berdasarkan bahasa pemrograman Anda.

Anda dapat membuat proyek AWS CDK Anda secara manual atau dengan perintah AWS CDK Command Line Interface (AWS CDK CLI). `cdk init` Dalam topik ini, kita akan merujuk pada struktur proyek dan konvensi penamaan file dan folder yang dibuat oleh AWS CDK CLI. Anda dapat menyesuaikan dan mengatur proyek CDK Anda agar sesuai dengan kebutuhan Anda.

**catatan**  
Struktur proyek yang dibuat oleh AWS CDK CLI dapat bervariasi antar versi dari waktu ke waktu.

## File dan folder universal
<a name="projects-universal"></a><a name="projects-universal-git"></a>

 `.git`   
Jika Anda telah `git` menginstal, AWS CDK CLI secara otomatis menginisialisasi a Git repositori untuk proyek Anda. `.git`Direktori berisi informasi tentang repositori.<a name="projects-universal-gitignore"></a>

 `.gitignore`   
File teks yang digunakan oleh Git untuk menentukan file dan folder untuk diabaikan.<a name="projects-universal-readme"></a>

 `README.md`   
File teks yang memberi Anda panduan dasar dan informasi penting untuk mengelola proyek AWS CDK Anda. Ubah file ini seperlunya untuk mendokumentasikan informasi penting mengenai proyek CDK Anda.<a name="projects-universal-cdk"></a>

 `cdk.json`   
File konfigurasi untuk AWS CDK. File ini memberikan instruksi kepada AWS CDK CLI mengenai cara menjalankan aplikasi Anda.

## File dan folder khusus bahasa
<a name="projects-specific"></a>

File dan folder berikut unik untuk setiap bahasa pemrograman yang didukung.

**Example**  
Berikut ini adalah contoh proyek yang dibuat dalam `my-cdk-ts-project` direktori menggunakan `cdk init --language typescript` perintah:  

```
my-cdk-ts-project
├── .git
├── .gitignore
├── .npmignore
├── README.md
├── bin
│   └── my-cdk-ts-project.ts
├── cdk.json
├── jest.config.js
├── lib
│   └── my-cdk-ts-project-stack.ts
├── node_modules
├── package-lock.json
├── package.json
├── test
│   └── my-cdk-ts-project.test.ts
└── tsconfig.json
```  
 `.npmignore`   
File yang menentukan file dan folder mana yang harus diabaikan saat menerbitkan paket ke `npm` registri. File ini mirip dengan`.gitignore`, tetapi khusus untuk `npm` paket.  
 `bin/my-cdk-ts-project.ts`   
*File aplikasi* mendefinisikan aplikasi CDK Anda. Proyek CDK dapat berisi satu atau lebih file aplikasi. File aplikasi disimpan di `bin` folder.  
Berikut ini adalah contoh file aplikasi dasar yang mendefinisikan aplikasi CDK:  

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

const app = new cdk.App();
new MyCdkTsProjectStack(app, 'MyCdkTsProjectStack');
```  
 `jest.config.js`   
File konfigurasi untuk Jest. *Jest* adalah kerangka JavaScript pengujian yang populer.  
 `lib/my-cdk-ts-project-stack.ts`   
*File stack* mendefinisikan tumpukan CDK Anda. Dalam tumpukan Anda, Anda mendefinisikan AWS sumber daya dan properti menggunakan konstruksi.  
Berikut ini adalah contoh file stack dasar yang mendefinisikan tumpukan CDK:  

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

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

  // code that defines your resources and properties go here
 }
}
```  
 `node_modules`   
Folder umum di Node.js proyek yang berisi dependensi untuk proyek Anda.  
 `package-lock.json`   
File metadata yang bekerja dengan `package.json` file untuk mengelola versi dependensi.  
 `package.json`   
File metadata yang biasa digunakan di Node.js proyek. File ini berisi informasi tentang proyek CDK Anda seperti nama proyek, definisi skrip, dependensi, dan informasi tingkat proyek impor lainnya.  
 `test/my-cdk-ts-project.test.ts`   
Folder pengujian dibuat untuk mengatur pengujian untuk proyek CDK Anda. File uji sampel juga dibuat.  
Anda dapat menulis tes TypeScript dan menggunakan Jest untuk mengkompilasi TypeScript kode Anda sebelum menjalankan tes.  
 `tsconfig.json`   
File konfigurasi yang digunakan dalam TypeScript proyek yang menentukan opsi kompiler dan pengaturan proyek.
Berikut ini adalah contoh proyek yang dibuat dalam `my-cdk-js-project` direktori menggunakan `cdk init --language javascript` perintah:  

```
my-cdk-js-project
├── .git
├── .gitignore
├── .npmignore
├── README.md
├── bin
│   └── my-cdk-js-project.js
├── cdk.json
├── jest.config.js
├── lib
│   └── my-cdk-js-project-stack.js
├── node_modules
├── package-lock.json
├── package.json
└── test
    └── my-cdk-js-project.test.js
```  
 `.npmignore`   
File yang menentukan file dan folder mana yang harus diabaikan saat menerbitkan paket ke `npm` registri. File ini mirip dengan`.gitignore`, tetapi khusus untuk `npm` paket.  
 `bin/my-cdk-js-project.js`   
*File aplikasi* mendefinisikan aplikasi CDK Anda. Proyek CDK dapat berisi satu atau lebih file aplikasi. File aplikasi disimpan di `bin` folder.  
Berikut ini adalah contoh file aplikasi dasar yang mendefinisikan aplikasi CDK:  

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

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

const app = new cdk.App();
new MyCdkJsProjectStack(app, 'MyCdkJsProjectStack');
```  
 `jest.config.js`   
File konfigurasi untuk Jest. *Jest* adalah kerangka JavaScript pengujian yang populer.  
 `lib/my-cdk-js-project-stack.js`   
*File stack* mendefinisikan tumpukan CDK Anda. Dalam tumpukan Anda, Anda mendefinisikan AWS sumber daya dan properti menggunakan konstruksi.  
Berikut ini adalah contoh file stack dasar yang mendefinisikan tumpukan CDK:  

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

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

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

module.exports = { MyCdkJsProjectStack }
```  
 `node_modules`   
Folder umum di Node.js proyek yang berisi dependensi untuk proyek Anda.  
 `package-lock.json`   
File metadata yang bekerja dengan `package.json` file untuk mengelola versi dependensi.  
 `package.json`   
File metadata yang biasa digunakan di Node.js proyek. File ini berisi informasi tentang proyek CDK Anda seperti nama proyek, definisi skrip, dependensi, dan informasi tingkat proyek impor lainnya.  
 `test/my-cdk-js-project.test.js`   
Folder pengujian dibuat untuk mengatur pengujian untuk proyek CDK Anda. File uji sampel juga dibuat.  
Anda dapat menulis tes JavaScript dan menggunakan Jest untuk mengkompilasi JavaScript kode Anda sebelum menjalankan tes.
Berikut ini adalah contoh proyek yang dibuat dalam `my-cdk-py-project` direktori menggunakan `cdk init --language python` perintah:  

```
my-cdk-py-project
├── .git
├── .gitignore
├── .venv
├── README.md
├── app.py
├── cdk.json
├── my_cdk_py_project
│   ├── __init__.py
│   └── my_cdk_py_project_stack.py
├── requirements-dev.txt
├── requirements.txt
├── source.bat
└── tests
    ├── __init__.py
    └── unit
```  
 `.venv`   
CDK CLI secara otomatis menciptakan lingkungan virtual untuk proyek Anda. `.venv`Direktori mengacu pada lingkungan virtual ini.  
 `app.py`   
*File aplikasi* mendefinisikan aplikasi CDK Anda. Proyek CDK dapat berisi satu atau lebih file aplikasi.  
Berikut ini adalah contoh file aplikasi dasar yang mendefinisikan aplikasi CDK:  

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

import aws_cdk as cdk

from my_cdk_py_project.my_cdk_py_project_stack import MyCdkPyProjectStack

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

app.synth()
```  
 `my_cdk_py_project`   
Direktori yang berisi *file tumpukan* Anda. CDK CLI membuat yang berikut di sini:  
+ \$1\$1init\$1\$1.py - Sebuah file definisi paket Python kosong.
+  `my_cdk_py_project`— File yang mendefinisikan tumpukan CDK Anda. Anda kemudian mendefinisikan AWS sumber daya dan properti dalam tumpukan menggunakan konstruksi.
Berikut ini adalah contoh file stack:  

```
from aws_cdk import Stack

from constructs import Construct

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

  # code that defines your resources and properties go here
```  
 `requirements-dev.txt`   
File mirip dengan`requirements.txt`, tetapi digunakan untuk mengelola dependensi khusus untuk tujuan pengembangan daripada produksi.  
 `requirements.txt`   
File umum yang digunakan dalam proyek Python untuk menentukan dan mengelola dependensi proyek.  
 `source.bat`   
Batch file untuk Windows yang digunakan untuk mengatur lingkungan virtual Python.  
 `tests`   
Direktori yang berisi pengujian untuk proyek CDK Anda.  
Berikut ini adalah contoh dari unit test:  

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

from my_cdk_py_project.my_cdk_py_project_stack import MyCdkPyProjectStack

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

 template.has_resource_properties("AWS::SQS::Queue", {
  "VisibilityTimeout": 300
 })
```
Berikut ini adalah contoh proyek yang dibuat dalam `my-cdk-java-project` direktori menggunakan `cdk init --language java` perintah:  

```
my-cdk-java-project
├── .git
├── .gitignore
├── README.md
├── cdk.json
├── pom.xml
└── src
    ├── main
    └── test
```  
 `pom.xml`   
File yang berisi informasi konfigurasi dan metadata tentang proyek CDK Anda. File ini adalah bagian dari Maven.  
 `src/main`   
Direktori yang berisi file *aplikasi* dan *tumpukan* Anda.  
Berikut ini adalah contoh file aplikasi:  

```
package com.myorg;

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

import java.util.Arrays;

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

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

  app.synth();
 }
}
```
Berikut ini adalah contoh file stack:  

```
package com.myorg;

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

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

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

  // code that defines your resources and properties go here
 }
}
```  
 `src/test`   
Direktori yang berisi file pengujian Anda. Berikut ini adalah contohnya:  

```
package com.myorg;

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

import java.util.HashMap;

import org.junit.jupiter.api.Test;

public class MyCdkJavaProjectTest {

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

  Template template = Template.fromStack(stack);

  template.hasResourceProperties("AWS::SQS::Queue", new HashMap<String, Number>() {{
   put("VisibilityTimeout", 300);
  }});
 }
}
```
Berikut ini adalah contoh proyek yang dibuat dalam `my-cdk-csharp-project` direktori menggunakan `cdk init --language csharp` perintah:  

```
my-cdk-csharp-project
├── .git
├── .gitignore
├── README.md
├── cdk.json
└── src
    ├── MyCdkCsharpProject
    └── MyCdkCsharpProject.sln
```  
 `src/MyCdkCsharpProject`   
Direktori yang berisi file *aplikasi* dan *tumpukan* Anda.  
Berikut ini adalah contoh file aplikasi:  

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

namespace MyCdkCsharpProject
{
 sealed class Program
 {
  public static void Main(string[] args)
  {
   var app = new App();
   new MyCdkCsharpProjectStack(app, "MyCdkCsharpProjectStack", new StackProps{});
   app.Synth();
  }
 }
}
```
Berikut ini adalah contoh file stack:  

```
using Amazon.CDK;
using Constructs;

namespace MyCdkCsharpProject
{
 public class MyCdkCsharpProjectStack : Stack
 {
  internal MyCdkCsharpProjectStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
  {
   // code that defines your resources and properties go here
  }
 }
}
```
Direktori ini juga berisi yang berikut:  
  
+  `GlobalSuppressions.cs`— File yang digunakan untuk menekan peringatan atau kesalahan kompiler tertentu di seluruh proyek Anda.
+  `.csproj`— File berbasis XML yang digunakan untuk menentukan pengaturan proyek, dependensi, dan membangun konfigurasi. ---  
 `src/MyCdkCsharpProject.sln`   
 Microsoft Visual Studio Solution File digunakan untuk mengatur dan mengelola proyek-proyek terkait.
Berikut ini adalah contoh proyek yang dibuat dalam `my-cdk-go-project` direktori menggunakan `cdk init --language go` perintah:  

```
my-cdk-go-project
├── .git
├── .gitignore
├── README.md
├── cdk.json
├── go.mod
├── my-cdk-go-project.go
└── my-cdk-go-project_test.go
```  
 `go.mod`   
File yang berisi informasi modul dan digunakan untuk mengelola dependensi dan pembuatan versi untuk Go proyek.  
 `my-cdk-go-project.go`   
File yang mendefinisikan aplikasi dan tumpukan CDK Anda.  
Berikut ini adalah contohnya:  

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

type MyCdkGoProjectStackProps struct {
 awscdk.StackProps
}

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

  return stack
}

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

func env() *awscdk.Environment {

 return nil
}
```  
 `my-cdk-go-project_test.go`   
File yang mendefinisikan uji sampel.  
Berikut ini adalah contohnya:  

```
package main

import (
 "testing"

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

func TestMyCdkGoProjectStack(t *testing.T) {

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

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

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

# AWS Aplikasi CDK
<a name="apps"></a>

[Aplikasi atau *aplikasi AWS * Cloud Development Kit (AWS CDK) adalah kumpulan dari satu atau lebih tumpukan CDK.](stacks.md) Tumpukan adalah kumpulan dari satu atau lebih [konstruksi](constructs.md), yang mendefinisikan AWS sumber daya dan properti. Oleh karena itu, pengelompokan keseluruhan tumpukan dan konstruksi Anda dikenal sebagai aplikasi CDK Anda.

## Cara membuat aplikasi CDK
<a name="apps-define"></a>

Anda membuat aplikasi dengan mendefinisikan instance aplikasi dalam file aplikasi [project](projects.md) Anda. Untuk melakukan ini, Anda mengimpor dan menggunakan build [App](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html) dari Construct AWS Library. `App`Konstruk tidak memerlukan argumen inisialisasi apa pun. Ini adalah satu-satunya konstruksi yang dapat digunakan sebagai root.

` [Stack](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html) `Kelas ` [App](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html) ` dan dari AWS Construct Library adalah konstruksi yang unik. Dibandingkan dengan konstruksi lain, mereka tidak mengonfigurasi AWS sumber daya sendiri. Sebaliknya, mereka digunakan untuk menyediakan konteks untuk konstruksi Anda yang lain. Semua konstruksi yang mewakili AWS sumber daya harus didefinisikan, secara langsung atau tidak langsung, dalam lingkup konstruksi. `Stack` `Stack`konstruksi didefinisikan dalam lingkup `App` konstruk.

Aplikasi kemudian disintesis untuk membuat AWS CloudFormation template untuk tumpukan Anda. Berikut ini adalah contohnya:

**Example**  

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

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

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

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

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

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

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

app.Synth(nil)
```

Tumpukan dalam satu aplikasi dapat dengan mudah merujuk ke sumber daya dan properti masing-masing. AWS CDK menyimpulkan dependensi antar tumpukan sehingga dapat digunakan dalam urutan yang benar. Anda dapat menerapkan salah satu atau semua tumpukan dalam aplikasi dengan satu `cdk deploy` perintah.

## Pohon konstruksi
<a name="apps-tree"></a>

Konstruksi didefinisikan di dalam konstruksi lain menggunakan `scope` argumen yang diteruskan ke setiap konstruksi, dengan `App` kelas sebagai root. *Dengan cara ini, aplikasi AWS CDK mendefinisikan hierarki konstruksi yang dikenal sebagai pohon konstruksi.*

Akar pohon ini adalah aplikasi Anda, yang merupakan instance dari `App` kelas. Di dalam aplikasi, Anda membuat instance satu atau lebih tumpukan. Di dalam tumpukan, Anda membuat instance konstruksi, yang mungkin membuat instance sumber daya atau konstruksi lain, dan seterusnya di bawah pohon.

Konstruksi *selalu* didefinisikan secara eksplisit dalam lingkup konstruksi lain, yang menciptakan hubungan antar konstruksi. Hampir selalu, Anda harus meneruskan `this` (dengan Python,`self`) sebagai ruang lingkup, yang menunjukkan bahwa konstruksi baru adalah anak dari konstruksi saat ini. Pola yang dimaksud adalah Anda mendapatkan konstruksi Anda [https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html), lalu membuat instance konstruksi yang digunakannya dalam konstruktornya.

[Melewati ruang lingkup secara eksplisit memungkinkan setiap konstruksi untuk menambahkan dirinya ke pohon, dengan perilaku ini sepenuhnya terkandung dalam kelas dasar. `Construct`](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html) Ini bekerja dengan cara yang sama di setiap bahasa yang didukung oleh AWS CDK dan tidak memerlukan penyesuaian tambahan.

**penting**  
Secara teknis, dimungkinkan untuk melewati beberapa ruang lingkup selain `this` saat membuat instance konstruksi. Anda dapat menambahkan konstruksi di mana saja di pohon, atau bahkan di tumpukan lain di aplikasi yang sama. Misalnya, Anda bisa menulis fungsi gaya mixin yang menambahkan konstruksi ke lingkup yang diteruskan sebagai argumen. Kesulitan praktis di sini adalah Anda tidak dapat dengan mudah memastikan bahwa yang IDs Anda pilih untuk konstruksi Anda unik dalam lingkup orang lain. Praktik ini juga membuat kode Anda lebih sulit untuk dipahami, dipelihara, dan digunakan kembali. Oleh karena itu, kami menyarankan Anda menggunakan struktur umum pohon konstruksi.

 AWS CDK menggunakan semua konstruksi di jalur dari akar pohon ke setiap konstruksi anak untuk menghasilkan keunikan IDs yang dibutuhkan oleh. IDs AWS CloudFormation Pendekatan ini berarti bahwa konstruksi IDs hanya perlu unik dalam cakupannya, bukan di dalam seluruh tumpukan seperti di asli AWS CloudFormation. Namun, jika Anda memindahkan konstruksi ke cakupan yang berbeda, ID unik tumpukan yang dihasilkan akan berubah, dan tidak AWS CloudFormation akan menganggapnya sebagai sumber daya yang sama.

Pohon konstruksi terpisah dari konstruksi yang Anda tentukan dalam kode AWS CDK Anda. Namun, ini dapat diakses melalui `node` atribut konstruksi apa pun, yang merupakan referensi ke simpul yang mewakili konstruksi itu di pohon. Setiap node adalah sebuah [https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Node.html](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Node.html)instance, atribut yang menyediakan akses ke akar pohon dan ke cakupan induk node dan anak-anak.

1.  `node.children`— Anak-anak langsung dari konstruksi.

1.  `node.id`— Pengidentifikasi konstruksi dalam ruang lingkupnya.

1.  `node.path`— Jalur penuh konstruksi termasuk semua IDs orang tuanya.

1.  `node.root`— Akar pohon konstruksi (aplikasi).

1.  `node.scope`— Ruang lingkup (induk) dari konstruksi, atau undefined jika node adalah root.

1.  `node.scopes`— Semua orang tua dari konstruksi, sampai ke akar.

1.  `node.uniqueId`— Pengidentifikasi alfanumerik unik untuk konstruksi ini di dalam pohon (secara default, dihasilkan dari `node.path` dan hash).

Pohon konstruksi mendefinisikan urutan implisit di mana konstruksi disintesis ke sumber daya dalam template akhir. AWS CloudFormation Dimana satu sumber daya harus dibuat sebelum yang lain, AWS CloudFormation atau AWS Construct Library umumnya menyimpulkan ketergantungan. Mereka kemudian memastikan bahwa sumber daya dibuat dalam urutan yang benar.

Anda juga dapat menambahkan ketergantungan eksplisit antara dua node dengan menggunakan. `node.addDependency()` Untuk informasi selengkapnya, lihat [Dependensi di Referensi](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html#dependencies) API * AWS CDK*.

 AWS CDK menyediakan cara sederhana untuk mengunjungi setiap node di pohon konstruksi dan melakukan operasi pada masing-masing node. Untuk informasi lebih lanjut, lihat [Aspek dan AWS CDK](aspects.md).

# Pengantar AWS tumpukan CDK
<a name="stacks"></a>

Tumpukan AWS CDK adalah unit penyebaran tunggal terkecil. Ini merupakan kumpulan AWS sumber daya yang Anda tentukan menggunakan konstruksi CDK. Saat Anda menerapkan aplikasi CDK, sumber daya dalam tumpukan CDK akan digunakan bersama sebagai tumpukan. AWS CloudFormation Untuk mempelajari lebih lanjut tentang AWS CloudFormation tumpukan, lihat [Mengelola AWS sumber daya sebagai satu unit dengan AWS CloudFormation tumpukan](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacks.html) di * AWS CloudFormation Panduan Pengguna*.

Anda mendefinisikan tumpukan dengan memperluas atau mewarisi dari konstruksi. [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html) Contoh berikut adalah pola umum untuk mendefinisikan tumpukan CDK pada file terpisah, yang dikenal sebagai file *tumpukan*. Di sini, kita memperluas atau mewarisi `Stack` kelas dan mendefinisikan konstruktor yang menerima`scope`,, `id` dan. `props` Kemudian, kita memanggil konstruktor `Stack` kelas dasar menggunakan `super` dengan yang diterima`scope`,`id`, dan: `props`

**Example**  

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

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

    // Define your constructs here

  }
}
```

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

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

    // Define your constructs here

  }
}

module.exports = { MyCdkStack }
```

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

class MyCdkStack(Stack):

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

    # Define your constructs here
```

```
package com.myorg;

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

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

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

    // Define your constructs here
  }
}
```

```
using Amazon.CDK;
using Constructs;

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

```
package main

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

type CdkDemoAppStackProps struct {
	awscdk.StackProps
}

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

	// The code that defines your stack goes here

	return stack
}

func main() {
	defer jsii.Close()

	app := awscdk.NewApp(nil)

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

	app.Synth(nil)
}

//...
```

Contoh sebelumnya hanya mendefinisikan tumpukan. Untuk membuat tumpukan, itu harus dipakai dalam konteks aplikasi CDK Anda. Pola umum adalah mendefinisikan aplikasi CDK Anda dan menginisialisasi tumpukan Anda pada file terpisah, yang dikenal sebagai file *aplikasi*.

Berikut ini adalah contoh yang membuat tumpukan CDK bernama`MyCdkStack`. Di sini, aplikasi CDK `MyCdkStack` dibuat dan dipakai dalam konteks aplikasi:

**Example**  

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

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

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

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

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

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

import aws_cdk as cdk

from my_cdk.my_cdk_stack import MyCdkStack


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

app.synth()
```

```
package com.myorg;

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

import java.util.Arrays;

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

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

    app.synth();
  }
}
```

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

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

```
package main

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

// ...

func main() {
  defer jsii.Close()

  app := awscdk.NewApp(nil)

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

  app.Synth(nil)
}

// ...
```

Contoh berikut membuat aplikasi CDK yang berisi dua tumpukan:

**Example**  

```
const app = new App();

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

app.synth();
```

```
const app = new App();

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

app.synth();
```

```
app = App()

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

app.synth()
```

```
App app = new App();

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

app.synth();
```

```
var app = new App();

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

app.Synth();
```

```
package main

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

type MyFirstStackProps struct {
	awscdk.StackProps
}

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

	// The code that defines your stack goes here

	return myFirstStack
}

type MySecondStackProps struct {
	awscdk.StackProps
}

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

	// The code that defines your stack goes here

	return mySecondStack
}

func main() {
	defer jsii.Close()

	app := awscdk.NewApp(nil)

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

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

	app.Synth(nil)
}

// ...
```

## Tentang stack API
<a name="stack-api"></a>

[https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html)Objek menyediakan API kaya, termasuk yang berikut:
+  `Stack.of(construct)`— Metode statis yang mengembalikan **Stack** di mana konstruksi didefinisikan. Ini berguna jika Anda perlu berinteraksi dengan tumpukan dari dalam konstruksi yang dapat digunakan kembali. Panggilan gagal jika tumpukan tidak dapat ditemukan dalam ruang lingkup.
+  `stack.stackName`(Python:`stack_name`) — Mengembalikan nama fisik tumpukan. Seperti disebutkan sebelumnya, semua tumpukan AWS CDK memiliki nama fisik yang dapat diselesaikan AWS CDK selama sintesis.
+  `stack.region`dan `stack.account` — Kembalikan AWS Wilayah dan akun, masing-masing, ke mana tumpukan ini akan digunakan. Properti ini mengembalikan salah satu dari yang berikut:
  + Akun atau Wilayah secara eksplisit ditentukan saat tumpukan ditentukan
  + Token yang disandikan string yang menyelesaikan parameter AWS CloudFormation semu untuk akun dan Wilayah untuk menunjukkan bahwa tumpukan ini adalah lingkungan agnostik

    Untuk informasi tentang bagaimana lingkungan ditentukan untuk tumpukan, lihat [Lingkungan untuk AWS CDK](environments.md).
+  `stack.addDependency(stack)`(Python:`stack.add_dependency(stack)`) - Dapat digunakan untuk secara eksplisit mendefinisikan urutan ketergantungan antara dua tumpukan. Urutan ini dihormati oleh `cdk deploy` perintah saat menerapkan beberapa tumpukan sekaligus.
+  `stack.tags`— Mengembalikan [TagManager](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagManager.html)yang dapat Anda gunakan untuk menambah atau menghapus tag tingkat tumpukan. Manajer tag ini menandai semua sumber daya di dalam tumpukan, dan juga menandai tumpukan itu sendiri saat dibuat AWS CloudFormation.
+  `stack.partition`, `stack.urlSuffix` (Python:`url_suffix`), (`stack.stackId`Python:`stack_id`), dan (`stack.notificationArn`Python:`notification_arn`) — Kembalikan token yang menyelesaikan parameter semu masing-masing AWS CloudFormation , seperti. `{ "Ref": "AWS::Partition" }` Token ini dikaitkan dengan objek tumpukan tertentu sehingga kerangka kerja AWS CDK dapat mengidentifikasi referensi cross-stack.
+  `stack.availabilityZones`(Python:`availability_zones`) — Mengembalikan set Availability Zones yang tersedia di lingkungan tempat tumpukan ini digunakan. Untuk tumpukan agnostik lingkungan, ini selalu mengembalikan array dengan dua Availability Zones. Untuk tumpukan khusus lingkungan, AWS CDK menanyakan lingkungan dan menampilkan kumpulan Zona Ketersediaan yang tersedia di Wilayah yang Anda tentukan.
+  `stack.parseArn(arn)`dan `stack.formatArn(comps)` (Python:`parse_arn`,`format_arn`) - Dapat digunakan untuk bekerja dengan Amazon Resource Names ()ARNs.
+  `stack.toJsonString(obj)`(Python:`to_json_string`) - Dapat digunakan untuk memformat objek arbitrer sebagai string JSON yang dapat disematkan dalam template. AWS CloudFormation Objek dapat menyertakan token, atribut, dan referensi, yang hanya diselesaikan selama penerapan.
+  `stack.templateOptions`(Python:`template_options`) — Gunakan untuk menentukan opsi AWS CloudFormation template, seperti Transform, Description, dan Metadata, untuk tumpukan Anda.

## Menggunakan tumpukan
<a name="stacks-work"></a>

[Tumpukan digunakan sebagai AWS CloudFormation tumpukan ke lingkungan AWS .](environments.md) Lingkungan mencakup AWS akun dan AWS Wilayah tertentu.

Saat Anda menjalankan `cdk synth` perintah untuk aplikasi dengan beberapa tumpukan, rakitan cloud menyertakan templat terpisah untuk setiap instance tumpukan. Bahkan jika kedua tumpukan adalah contoh dari kelas yang sama, AWS CDK memancarkannya sebagai dua templat individual.

Anda dapat mensintesis setiap template dengan menentukan nama tumpukan dalam perintah. `cdk synth` Contoh berikut mensintesis template untuk`stack1`:

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

[Pendekatan ini secara konseptual berbeda dari bagaimana AWS CloudFormation template biasanya digunakan, di mana template dapat digunakan beberapa kali dan diparameterisasi melalui parameter.AWS CloudFormation ](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html) Meskipun AWS CloudFormation parameter dapat didefinisikan dalam AWS CDK, mereka umumnya tidak disarankan karena AWS CloudFormation parameter diselesaikan hanya selama penerapan. Ini berarti Anda tidak dapat menentukan nilainya dalam kode Anda.

Misalnya, untuk menyertakan sumber daya secara kondisional di aplikasi berdasarkan nilai parameter, Anda harus menyiapkan [AWS CloudFormation kondisi](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html) dan menandai sumber daya dengannya. AWS CDK mengambil pendekatan di mana templat konkret diselesaikan pada waktu sintesis. Oleh karena itu, Anda dapat menggunakan `if` pernyataan untuk memeriksa nilai untuk menentukan apakah sumber daya harus didefinisikan atau beberapa perilaku harus diterapkan.

**catatan**  
 AWS CDK menyediakan resolusi sebanyak mungkin selama waktu sintesis untuk memungkinkan penggunaan bahasa pemrograman Anda secara idiomatik dan alami.

Seperti konstruksi lainnya, tumpukan dapat disusun bersama menjadi beberapa kelompok. Kode berikut menunjukkan contoh layanan yang terdiri dari tiga tumpukan: bidang kontrol, bidang data, dan tumpukan pemantauan. Konstruksi layanan didefinisikan dua kali: sekali untuk lingkungan beta dan sekali untuk lingkungan produksi.

**Example**  

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

interface EnvProps {
  prod: boolean;
}

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

class MyService extends Construct {

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

    super(scope, id);

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

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

app.synth();
```

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

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

class MyService extends Construct {

  constructor(scope, id, props) {

    super(scope, id);

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

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

app.synth();
```

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

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

class MyService(Construct):

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

    super().__init__(scope, id)

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

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

app.synth()
```

```
package com.myorg;

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

public class MyApp {

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

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

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

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

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

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

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

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

        app.synth();
    }
}
```

```
using Amazon.CDK;
using Constructs;

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

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

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

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

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

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

```
package main

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

type ControlPlaneStackProps struct {
	awscdk.StackProps
}

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

	// The code that defines your stack goes here

	return ControlPlaneStack
}

type DataPlaneStackProps struct {
	awscdk.StackProps
}

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

	// The code that defines your stack goes here

	return DataPlaneStack
}

type MonitoringStackProps struct {
	awscdk.StackProps
}

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

	// The code that defines your stack goes here

	return MonitoringStack
}

type MyServiceStackProps struct {
	awscdk.StackProps
	Prod bool
}

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

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

	return MyServiceStack
}

func main() {
	defer jsii.Close()

	app := awscdk.NewApp(nil)

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

	NewMyServiceStack(app, "beta", &betaProps)

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

	NewMyServiceStack(app, "prod", &prodProps)

	app.Synth(nil)
}

// ...
```
Aplikasi AWS CDK ini akhirnya terdiri dari enam tumpukan, tiga untuk setiap lingkungan:  

```
$ cdk ls

betacpDA8372D3
betadataE23DB2BA
betamon632BD457
prodcp187264CE
proddataF7378CE5
prodmon631A1083
```

Nama fisik AWS CloudFormation tumpukan secara otomatis ditentukan oleh AWS CDK berdasarkan jalur konstruksi tumpukan di pohon. Secara default, nama tumpukan berasal dari ID konstruksi `Stack` objek. Namun, Anda dapat menentukan nama eksplisit dengan menggunakan `stackName` prop (dalam Python,`stack_name`), sebagai berikut.

**Example**  

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

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

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

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

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

### Bekerja dengan tumpukan nest
<a name="stack-nesting"></a>

*Tumpukan bersarang adalah tumpukan* CDK yang Anda buat di dalam tumpukan lain, yang dikenal sebagai tumpukan induk. Anda membuat tumpukan bersarang menggunakan konstruksi. [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.NestedStack.html)

Dengan menggunakan tumpukan bersarang, Anda dapat mengatur sumber daya di beberapa tumpukan. Tumpukan bersarang juga menawarkan jalan di sekitar batas AWS CloudFormation 500 sumber daya untuk tumpukan. Tumpukan bersarang dihitung sebagai hanya satu sumber daya di tumpukan yang berisi itu. Namun, dapat berisi hingga 500 sumber daya, termasuk tumpukan bersarang tambahan.

Ruang lingkup tumpukan bersarang harus berupa `Stack` atau `NestedStack` konstruksi. Tumpukan bersarang tidak perlu dideklarasikan secara leksikal di dalam tumpukan induknya. Anda hanya perlu meneruskan tumpukan induk sebagai parameter pertama (`scope`) saat membuat instance tumpukan bersarang. Selain pembatasan ini, mendefinisikan konstruksi dalam tumpukan bersarang bekerja persis sama seperti di tumpukan biasa.

Pada waktu sintesis, tumpukan bersarang disintesis ke AWS CloudFormation templatnya sendiri, yang diunggah ke bucket staging AWS CDK saat penerapan. Tumpukan bersarang terikat pada tumpukan induknya dan tidak diperlakukan sebagai artefak penerapan independen. Mereka tidak terdaftar oleh`cdk list`, dan mereka tidak dapat digunakan oleh`cdk deploy`.

[Referensi antara tumpukan induk dan tumpukan bersarang secara otomatis diterjemahkan ke parameter tumpukan dan output dalam AWS CloudFormation templat yang dihasilkan, seperti halnya referensi tumpukan silang.](resources.md#resource-stack)

**Awas**  
Perubahan postur keamanan tidak ditampilkan sebelum penerapan untuk tumpukan bersarang. Informasi ini hanya ditampilkan untuk tumpukan tingkat atas.

# Pengantar AWS tahapan CDK
<a name="stages"></a>

*Tahap AWS * Cloud Development Kit (AWS CDK) mewakili sekelompok satu atau lebih tumpukan CDK yang dikonfigurasi untuk digunakan bersama. Gunakan tahapan untuk menyebarkan pengelompokan tumpukan yang sama ke beberapa lingkungan, seperti pengembangan, pengujian, dan produksi.

Untuk mengonfigurasi tahap CDK, impor dan gunakan [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stage.html)konstruksi.

Berikut ini adalah contoh dasar yang mendefinisikan tahap CDK bernama. `MyAppStage` Kami menambahkan dua tumpukan CDK, bernama `AppStack` dan `DatabaseStack` ke panggung kami. Untuk contoh ini, `AppStack` berisi sumber daya aplikasi dan `DatabaseStack` berisi sumber daya database. Kami kemudian membuat dua contoh`MyAppStage`, untuk lingkungan pengembangan dan produksi:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

```
from aws_cdk import Stack
from constructs import Construct

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

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

```
from aws_cdk import Stack
from constructs import Construct

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

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

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

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

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

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

import aws_cdk as cdk

from cdk_demo_app.my_stage import MyAppStage

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

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

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

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

```
package com.myorg;

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

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

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

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

```
package com.myorg;

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

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

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

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

```
package com.myorg;

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

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

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

```
package com.myorg;

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

import java.util.Arrays;

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

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

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

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

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

```
using Amazon.CDK;
using Constructs;

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

```
using Amazon.CDK;
using Constructs;

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

```
using Amazon.CDK;
using Constructs;

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

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

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

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

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

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

```
package main

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

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

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

	// The code that defines your application goes here

	return stack
}

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

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

	// The code that defines your database goes here

	return stack
}

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

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

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

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

	return stage
}

func main() {
	defer jsii.Close()

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

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

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

	app.Synth(nil)
}

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

Saat kami menjalankan`cdk synth`, dua rakitan cloud dibuat di. `cdk.out` Kedua rakitan cloud ini berisi AWS CloudFormation template dan aset yang disintesis untuk setiap tahap. Berikut ini adalah cuplikan direktori proyek kami:

**Example**  

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

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

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

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

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

```
cdk-demo-app
├── cdk-demo-app.go
└── cdk.out
    ├── assembly-Dev
    │   ├── DevAppStack<unique-hash>.assets.json
    │   ├── DevAppStack<unique-hash>.template.json
    │   ├── DevDatabaseStack<unique-hash>.assets.json
    │   ├── DevDatabaseStack<unique-hash>.template.json
    │   ├── cdk.out
    │   └── manifest.json
    ├── assembly-Prod
    │   ├── ProdAppStack<unique-hash>.assets.json
    │   ├── ProdAppStack<unique-hash>.template.json
    │   ├── ProdDatabaseStack<unique-hash>.assets.json
    │   ├── ProdDatabaseStack<unique-hash>.template.json
    │   ├── cdk.out
    │   └── manifest.json
    ├── cdk.out
    ├── manifest.json
    └── tree.json
```
Saat kami mencantumkan tumpukan kami`cdk list`, kami melihat total empat tumpukan:  

```
$ cdk list
Dev/AppStack (Dev-AppStack)
Dev/DatabaseStack (Dev-DatabaseStack)
Prod/AppStack (Prod-AppStack)
Prod/DatabaseStack (Prod-DatabaseStack)
```
Untuk menerapkan tahap tertentu, kami menjalankan `cdk deploy` dan menyediakan tumpukan untuk diterapkan. Berikut ini adalah contoh yang menggunakan `/*` wildcard untuk menyebarkan kedua tumpukan di tahap kami: `Dev`  

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

✨  Synthesis time: 3.18s

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

 ✅  Dev/AppStack (Dev-AppStack)

✨  Deployment time: 1.11s

Stack ARN:
...

✨  Total time: 4.29s

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

 ✅  Dev/DatabaseStack (Dev-DatabaseStack)

✨  Deployment time: 1.09s

Stack ARN:
...

✨  Total time: 4.27s
```

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

Konstruksi adalah blok bangunan dasar aplikasi AWS Cloud Development Kit (AWS CDK). Konstruk adalah komponen dalam aplikasi Anda yang mewakili satu atau lebih AWS CloudFormation sumber daya dan konfigurasinya. Anda membangun aplikasi Anda, sepotong demi sepotong, dengan mengimpor dan mengonfigurasi konstruksi.

## Impor dan gunakan konstruksi
<a name="constructs-import"></a>

Konstruksi adalah kelas yang Anda impor ke aplikasi CDK Anda dari [AWS Construct](libraries.md#libraries-construct) Library. Anda juga dapat membuat dan mendistribusikan konstruksi Anda sendiri, atau menggunakan konstruksi yang dibuat oleh pengembang pihak ketiga.

Konstruksi adalah bagian dari Construct Programming Model (CPM). Mereka tersedia untuk digunakan dengan alat lain seperti CDK for Terraform (CDKtf), CDK for Kubernetes (CDK8s), dan. Projen

Banyak pihak ketiga juga telah menerbitkan konstruksi yang kompatibel dengan AWS CDK. Kunjungi [Construct Hub](https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&offset=0) untuk menjelajahi ekosistem AWS mitra konstruksi CDK.

## Membangun tingkat
<a name="constructs-lib-levels"></a>

Konstruksi dari AWS Construct Library dikategorikan menjadi tiga tingkatan. Setiap tingkat menawarkan tingkat abstraksi yang meningkat. Semakin tinggi abstraksi, semakin mudah dikonfigurasi, membutuhkan lebih sedikit keahlian. Semakin rendah abstraksi, semakin banyak kustomisasi yang tersedia, membutuhkan lebih banyak keahlian.<a name="constructs-lib-levels-one"></a>

 **Konstruksi level 1 (L1)**   
Konstruksi L1, juga dikenal sebagai *sumber daya CFN*, adalah konstruksi tingkat terendah dan tidak menawarkan abstraksi. Setiap konstruksi L1 memetakan langsung ke satu AWS CloudFormation sumber daya. Dengan konstruksi L1, Anda mengimpor konstruksi yang mewakili sumber daya tertentu. AWS CloudFormation Anda kemudian menentukan properti sumber daya dalam instance konstruksi Anda.  
Konstruksi L1 sangat bagus untuk digunakan ketika Anda terbiasa AWS CloudFormation dan membutuhkan kontrol penuh untuk mendefinisikan properti sumber daya Anda AWS .  
Dalam AWS Construct Library, konstruksi L1 diberi nama dimulai dengan`Cfn`, diikuti oleh identifier untuk AWS CloudFormation sumber daya yang diwakilinya. Misalnya, konstruksi adalah [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.CfnBucket.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.CfnBucket.html)konstruksi L1 yang mewakili sumber daya. [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) AWS CloudFormation   
Konstruksi L1 dihasilkan dari spesifikasi [AWS CloudFormation sumber daya](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html). Jika sumber daya ada di AWS CloudFormation, itu akan tersedia di AWS CDK sebagai konstruksi L1. Sumber daya atau properti baru mungkin membutuhkan waktu hingga satu minggu untuk tersedia di Perpustakaan AWS Konstruksi. Untuk informasi selengkapnya, lihat [referensi jenis AWS sumber daya dan properti](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html) di *Panduan AWS CloudFormation Pengguna*.<a name="constructs-lib-levels-two"></a>

 **Konstruksi level 2 (L2)**   
Konstruksi L2, juga dikenal sebagai konstruksi *kurasi*, dikembangkan dengan cermat oleh tim CDK dan biasanya merupakan jenis konstruksi yang paling banyak digunakan. Konstruksi L2 memetakan langsung ke AWS CloudFormation sumber daya tunggal, mirip dengan konstruksi L1. Dibandingkan dengan konstruksi L1, konstruksi L2 memberikan abstraksi tingkat yang lebih tinggi melalui API berbasis niat intuitif. Konstruksi L2 mencakup konfigurasi properti default yang masuk akal, kebijakan keamanan praktik terbaik, dan menghasilkan banyak kode boilerplate dan logika lem untuk Anda.  
Konstruksi L2 juga menyediakan metode pembantu untuk sebagian besar sumber daya yang membuatnya lebih sederhana dan lebih cepat untuk menentukan properti, izin, interaksi berbasis peristiwa antara sumber daya, dan banyak lagi. Banyak dari fitur ini juga tersedia sebagai blok bangunan independen yang disebut [Mixins](mixins.md), yang dapat diterapkan pada konstruksi L1 dan L2 menggunakan metode ini. `.with()`  
[https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html)Kelas ini adalah contoh konstruksi L2 untuk sumber daya bucket Amazon Simple Storage Service (Amazon S3).  
Perpustakaan AWS Konstruksi berisi konstruksi L2 yang ditunjuk stabil dan siap untuk digunakan produksi. Untuk konstruksi L2 yang sedang dikembangkan, mereka ditunjuk sebagai eksperimental dan ditawarkan dalam modul terpisah.<a name="constructs-lib-levels-three"></a>

 **Konstruksi level 3 (L3)**   
Konstruksi L3, juga dikenal sebagai *pola*, adalah abstraksi tingkat tertinggi. Setiap konstruksi L3 dapat berisi kumpulan sumber daya yang dikonfigurasi untuk bekerja sama untuk menyelesaikan tugas atau layanan tertentu dalam aplikasi Anda. Konstruksi L3 digunakan untuk membuat seluruh AWS arsitektur untuk kasus penggunaan tertentu dalam aplikasi Anda.  
Untuk menyediakan desain sistem yang lengkap, atau bagian penting dari sistem yang lebih besar, konstruksi L3 menawarkan konfigurasi properti default yang berpendirian. Mereka dibangun di sekitar pendekatan tertentu untuk memecahkan masalah dan memberikan solusi. Dengan konstruksi L3, Anda dapat membuat dan mengonfigurasi beberapa sumber daya dengan cepat, dengan jumlah input dan kode paling sedikit.  
[https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs_patterns.ApplicationLoadBalancedFargateService.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs_patterns.ApplicationLoadBalancedFargateService.html)Kelas adalah contoh konstruksi L3 yang mewakili layanan AWS Fargate yang berjalan pada cluster Amazon Elastic Container Service (Amazon ECS) Container Service (Amazon ECS) dan diawali oleh penyeimbang beban aplikasi.  
Mirip dengan konstruksi L2, konstruksi L3 yang siap untuk penggunaan produksi disertakan dalam Construct Library. AWS Mereka yang sedang dikembangkan ditawarkan dalam modul terpisah.

## Mendefinisikan konstruksi
<a name="constructs-define"></a>

### Komposisi
<a name="constructs-composition"></a>

 *Komposisi* adalah pola kunci untuk mendefinisikan abstraksi tingkat yang lebih tinggi melalui konstruksi. Sebuah konstruksi tingkat tinggi dapat terdiri dari sejumlah konstruksi tingkat rendah. Dari perspektif bottom-up, Anda menggunakan konstruksi untuk mengatur AWS sumber daya individual yang ingin Anda terapkan. Anda menggunakan abstraksi apa pun yang nyaman untuk tujuan Anda, dengan level sebanyak yang Anda butuhkan.

Dengan komposisi, Anda menentukan komponen yang dapat digunakan kembali dan membagikannya seperti kode lainnya. Misalnya, tim dapat menentukan konstruksi yang mengimplementasikan praktik terbaik perusahaan untuk tabel Amazon DynamoDB, termasuk pencadangan, replikasi global, penskalaan otomatis, dan pemantauan. Tim dapat berbagi konstruksi secara internal dengan tim lain, atau secara publik.

Tim dapat menggunakan konstruksi seperti paket perpustakaan lainnya. Ketika pustaka diperbarui, pengembang mendapatkan akses ke perbaikan versi baru dan perbaikan bug, mirip dengan pustaka kode lainnya.

### Inisialisasi
<a name="constructs-init"></a>

Konstruksi diimplementasikan di kelas yang memperluas kelas [https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html)dasar. Anda mendefinisikan konstruksi dengan membuat instance kelas. Semua konstruksi mengambil tiga parameter saat diinisialisasi:
+  **lingkup** — Orang tua atau pemilik konstruksi. Ini bisa berupa tumpukan atau konstruksi lain. Lingkup menentukan tempat konstruksi di pohon [konstruksi](apps.md#apps-tree). Anda biasanya harus lulus `this` (`self`dalam Python), yang mewakili objek saat ini, untuk ruang lingkup.
+  **id** — [Pengenal](identifiers.md) yang harus unik dalam lingkup. Identifier berfungsi sebagai namespace untuk semua yang didefinisikan dalam konstruksi. Ini digunakan untuk menghasilkan pengidentifikasi unik, seperti [nama sumber daya](resources.md#resources-physical-names) dan AWS CloudFormation logis IDs.

  Pengidentifikasi hanya perlu unik dalam ruang lingkup. Ini memungkinkan Anda membuat instance dan menggunakan kembali konstruksi tanpa memperhatikan konstruksi dan pengidentifikasi yang mungkin dikandungnya, dan memungkinkan pembuatan konstruksi menjadi abstraksi tingkat yang lebih tinggi. Selain itu, cakupan memungkinkan untuk merujuk ke kelompok konstruksi sekaligus. Contohnya termasuk untuk [penandaan](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tag.html), atau menentukan di mana konstruksi akan digunakan.
+  **props** — Satu set properti atau argumen kata kunci, tergantung pada bahasa, yang menentukan konfigurasi awal konstruksi. Konstruksi tingkat yang lebih tinggi memberikan lebih banyak default, dan jika semua elemen prop opsional, Anda dapat menghilangkan parameter props sepenuhnya.

### Konfigurasi
<a name="constructs-config"></a>

Sebagian besar konstruksi menerima `props` sebagai argumen ketiga mereka (atau dalam Python, argumen kata kunci), kumpulan name/value yang mendefinisikan konfigurasi konstruksi. Contoh berikut mendefinisikan bucket dengan enkripsi AWS Key Management Service (AWS KMS) dan hosting situs web statis diaktifkan. Karena tidak secara eksplisit menentukan kunci enkripsi, `Bucket` konstruksi mendefinisikan yang baru `kms.Key` dan mengaitkannya dengan bucket.

**Example**  

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

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

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

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

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

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

### Berinteraksi dengan konstruksi
<a name="constructs-interact"></a>

Konstruksi adalah kelas yang memperluas kelas [Konstruksi](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html) dasar. Setelah Anda membuat instance konstruksi, objek konstruksi mengekspos satu set metode dan properti yang memungkinkan Anda berinteraksi dengan konstruksi dan meneruskannya sebagai referensi ke bagian lain dari sistem.

Kerangka kerja AWS CDK tidak membatasi konstruksi apa pun. APIs Penulis dapat menentukan API apa pun yang mereka inginkan. Namun, AWS konstruksi yang disertakan dengan AWS Construct Library, seperti`s3.Bucket`, mengikuti pedoman dan pola umum. Ini memberikan pengalaman yang konsisten di semua AWS sumber daya.

Sebagian besar AWS konstruksi memiliki seperangkat metode [hibah](permissions.md#permissions-grants) yang dapat Anda gunakan untuk memberikan izin AWS Identity and Access Management (IAM) pada konstruksi tersebut kepada prinsipal. Contoh berikut memberikan `data-science` izin grup IAM untuk membaca dari bucket Amazon S3. `raw-data`

**Example**  

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

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

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

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

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

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

Pola umum lainnya adalah AWS konstruksi untuk mengatur salah satu atribut sumber daya dari data yang disediakan di tempat lain. Atribut dapat mencakup Amazon Resource Names (ARNs), nama, atau URLs.

Kode berikut mendefinisikan fungsi AWS Lambda dan mengaitkannya dengan antrian Amazon Simple Queue Service (Amazon SQS) melalui URL antrian dalam variabel lingkungan.

**Example**  

```
const jobsQueue = new sqs.Queue(this, 'jobs');
const createJobLambda = new lambda.Function(this, 'create-job', {
  runtime: lambda.Runtime.NODEJS_18_X,
  handler: 'index.handler',
  code: lambda.Code.fromAsset('./create-job-lambda-code'),
  environment: {
    QUEUE_URL: jobsQueue.queueUrl
  }
});
```

```
const jobsQueue = new sqs.Queue(this, 'jobs');
const createJobLambda = new lambda.Function(this, 'create-job', {
  runtime: lambda.Runtime.NODEJS_18_X,
  handler: 'index.handler',
  code: lambda.Code.fromAsset('./create-job-lambda-code'),
  environment: {
    QUEUE_URL: jobsQueue.queueUrl
  }
});
```

```
jobs_queue = sqs.Queue(self, "jobs")
create_job_lambda = lambda_.Function(self, "create-job",
    runtime=lambda_.Runtime.NODEJS_18_X,
    handler="index.handler",
    code=lambda_.Code.from_asset("./create-job-lambda-code"),
    environment=dict(
        QUEUE_URL=jobs_queue.queue_url
    )
)
```

```
final Queue jobsQueue = new Queue(this, "jobs");
Function createJobLambda = Function.Builder.create(this, "create-job")
                .handler("index.handler")
                .code(Code.fromAsset("./create-job-lambda-code"))
                .environment(java.util.Map.of(   // Map.of is Java 9 or later
                    "QUEUE_URL", jobsQueue.getQueueUrl()))
                .build();
```

```
var jobsQueue = new Queue(this, "jobs");
var createJobLambda = new Function(this, "create-job", new FunctionProps
{
    Runtime = Runtime.NODEJS_18_X,
    Handler = "index.handler",
    Code = Code.FromAsset(@".\create-job-lambda-code"),
    Environment = new Dictionary<string, string>
    {
        ["QUEUE_URL"] = jobsQueue.QueueUrl
    }
});
```

```
	createJobLambda := awslambda.NewFunction(stack, jsii.String("create-job"), &awslambda.FunctionProps{
		Runtime: awslambda.Runtime_NODEJS_18_X(),
		Handler: jsii.String("index.handler"),
		Code:    awslambda.Code_FromAsset(jsii.String(".\\create-job-lambda-code"), nil),
		Environment: &map[string]*string{
			"QUEUE_URL": jsii.String(*jobsQueue.QueueUrl()),
		},
	})
```

Untuk informasi tentang pola API yang paling umum di AWS Construct Library, lihat [Resources dan AWS CDK](resources.md).

### Tambahkan fitur dengan Mixins
<a name="constructs-mixins"></a>

Mixin adalah fitur composable yang dapat Anda terapkan ke konstruksi apa pun menggunakan metode ini. `.with()` Mixins memungkinkan Anda menambahkan fungsionalitas ke konstruksi L1 dan L2 tanpa harus menggunakan konstruksi yang berbeda atau menulis kode tingkat rendah.

Misalnya, Anda dapat mengaktifkan pembuatan versi dan memblokir akses publik di bucket Amazon S3 — apakah itu L1 atau `CfnBucket` L2: `Bucket`

**Example**  

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Mixin tersedia melalui `mixins` namespace dari setiap modul layanan (misalnya,). `s3.mixins` Setiap mixin menargetkan jenis sumber daya tertentu dan dinamai menurut sumber daya itu. Saat Anda menerapkan mixin ke konstruksi L2, itu secara otomatis berlaku untuk sumber daya L1 yang mendasarinya.

Untuk informasi selengkapnya tentang Mixins, lihat [Mixins](mixins.md).

### Aplikasi dan konstruksi tumpukan
<a name="constructs-apps-stacks"></a>

[https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html)Kelas [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html)dan dari AWS Construct Library adalah konstruksi yang unik. Dibandingkan dengan konstruksi lain, mereka tidak mengonfigurasi AWS sumber daya sendiri. Sebaliknya, mereka digunakan untuk menyediakan konteks untuk konstruksi Anda yang lain. Semua konstruksi yang mewakili AWS sumber daya harus didefinisikan, secara langsung atau tidak langsung, dalam lingkup konstruksi. `Stack` `Stack`konstruksi didefinisikan dalam lingkup `App` konstruk.

Untuk mempelajari lebih lanjut tentang aplikasi CDK, lihat aplikasi [AWS CDK](apps.md). Untuk mempelajari lebih lanjut tentang tumpukan CDK, lihat [Pengantar tumpukan AWS CDK](stacks.md).

Contoh berikut mendefinisikan aplikasi dengan satu tumpukan. Di dalam tumpukan, konstruksi L2 digunakan untuk mengonfigurasi sumber daya bucket Amazon S3.

**Example**  

```
import { App, Stack, StackProps } from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';

class HelloCdkStack extends Stack {
  constructor(scope: App, id: string, props?: StackProps) {
    super(scope, id, props);

    new s3.Bucket(this, 'MyFirstBucket', {
      versioned: true
    });
  }
}

const app = new App();
new HelloCdkStack(app, "HelloCdkStack");
```

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

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

    new s3.Bucket(this, 'MyFirstBucket', {
      versioned: true
    });
  }
}

const app = new App();
new HelloCdkStack(app, "HelloCdkStack");
```

```
from aws_cdk import App, Stack
import aws_cdk.aws_s3 as s3
from constructs import Construct

class HelloCdkStack(Stack):

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

        s3.Bucket(self, "MyFirstBucket", versioned=True)

app = App()
HelloCdkStack(app, "HelloCdkStack")
```
Tumpukan didefinisikan dalam `HelloCdkStack.java` file:  

```
import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.s3.*;

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

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

        Bucket.Builder.create(this, "MyFirstBucket")
            .versioned(true).build();
    }
}
```
Aplikasi didefinisikan dalam `HelloCdkApp.java` file:  

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

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

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

        app.synth();
    }
}
```

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

namespace HelloCdkApp
{
    internal static class Program
    {
        public static void Main(string[] args)
        {
            var app = new App();
            new HelloCdkStack(app, "HelloCdkStack");
            app.Synth();
        }
    }

    public class HelloCdkStack : Stack
    {
        public HelloCdkStack(Construct scope, string id, IStackProps props=null) : base(scope, id, props)
        {
            new Bucket(this, "MyFirstBucket", new BucketProps { Versioned = true });
        }
    }
}
```

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

	awss3.NewBucket(stack, jsii.String("MyFirstBucket"), &awss3.BucketProps{
		Versioned: jsii.Bool(true),
	})

	return stack
}
```

## Bekerja dengan konstruksi
<a name="constructs-work"></a>

### Bekerja dengan konstruksi L1
<a name="constructs-l1-using"></a>

L1 membangun peta langsung ke sumber daya individu AWS CloudFormation . Anda harus menyediakan konfigurasi sumber daya yang diperlukan.

Dalam contoh ini, kita membuat `bucket` objek menggunakan konstruksi `CfnBucket` L1:

**Example**  

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

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

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

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

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

```
	awss3.NewCfnBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.CfnBucketProps{
		BucketName: jsii.String("amzn-s3-demo-bucket"),
	})
```

Properti konstruksi yang bukan Boolean sederhana, string, angka, atau kontainer ditangani secara berbeda dalam bahasa yang didukung.

**Example**  

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

```
const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", {
  bucketName: "amzn-s3-demo-bucket",
  corsConfiguration: {
    corsRules: [{
          allowedOrigins: ["*"],
          allowedMethods: ["GET"]
    }]
  }
});
```
Dalam Python, properti ini diwakili oleh tipe yang didefinisikan sebagai kelas dalam dari konstruksi L1. Misalnya, properti opsional `cors_configuration` dari sebuah `CfnBucket` memerlukan pembungkus tipe`CfnBucket.CorsConfigurationProperty`. Di sini kita mendefinisikan `cors_configuration` sebuah `CfnBucket` contoh.  

```
bucket = CfnBucket(self, "amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket",
    cors_configuration=CfnBucket.CorsConfigurationProperty(
        cors_rules=[CfnBucket.CorsRuleProperty(
            allowed_origins=["*"],
            allowed_methods=["GET"]
        )]
    )
)
```
Di Jawa, properti ini diwakili oleh tipe yang didefinisikan sebagai kelas dalam dari konstruksi L1. Misalnya, properti opsional `corsConfiguration` dari sebuah `CfnBucket` memerlukan pembungkus tipe`CfnBucket.CorsConfigurationProperty`. Di sini kita mendefinisikan `corsConfiguration` sebuah `CfnBucket` contoh.  

```
CfnBucket bucket = CfnBucket.Builder.create(this, "amzn-s3-demo-bucket")
                        .bucketName("amzn-s3-demo-bucket")
                        .corsConfiguration(new CfnBucket.CorsConfigurationProperty.Builder()
                            .corsRules(Arrays.asList(new CfnBucket.CorsRuleProperty.Builder()
                                .allowedOrigins(Arrays.asList("*"))
                                .allowedMethods(Arrays.asList("GET"))
                                .build()))
                            .build())
                        .build();
```
Dalam C \$1, properti ini diwakili oleh tipe yang didefinisikan sebagai kelas dalam dari konstruksi L1. Misalnya, properti opsional `CorsConfiguration` dari sebuah `CfnBucket` memerlukan pembungkus tipe`CfnBucket.CorsConfigurationProperty`. Di sini kita mendefinisikan `CorsConfiguration` sebuah `CfnBucket` contoh.  

```
var bucket = new CfnBucket(this, "amzn-s3-demo-bucket", new CfnBucketProps
{
    BucketName = "amzn-s3-demo-bucket",
    CorsConfiguration = new CfnBucket.CorsConfigurationProperty
    {
        CorsRules = new object[] {
            new CfnBucket.CorsRuleProperty
            {
                AllowedOrigins = new string[] { "*" },
                AllowedMethods = new string[] { "GET" },
            }
        }
    }
});
```
Di Go, jenis ini diberi nama menggunakan nama konstruksi L1, garis bawah, dan nama properti. Misalnya, properti opsional `CorsConfiguration` dari sebuah `CfnBucket` memerlukan pembungkus tipe`CfnBucket_CorsConfigurationProperty`. Di sini kita mendefinisikan `CorsConfiguration` sebuah `CfnBucket` contoh.  

```
	awss3.NewCfnBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.CfnBucketProps{
		BucketName: jsii.String("amzn-s3-demo-bucket"),
		CorsConfiguration: &awss3.CfnBucket_CorsConfigurationProperty{
			CorsRules: []awss3.CorsRule{
				awss3.CorsRule{
					AllowedOrigins: jsii.Strings("*"),
					AllowedMethods: &[]awss3.HttpMethods{"GET"},
				},
			},
		},
	})
```

**penting**  
Anda tidak dapat menggunakan tipe properti L2 dengan konstruksi L1, atau sebaliknya. Saat bekerja dengan konstruksi L1, selalu gunakan tipe yang ditentukan untuk konstruksi L1 yang Anda gunakan. Jangan gunakan tipe dari konstruksi L1 lainnya (beberapa mungkin memiliki nama yang sama, tetapi mereka bukan tipe yang sama).  
Beberapa referensi API khusus bahasa kami saat ini memiliki kesalahan di jalur ke tipe properti L1, atau tidak mendokumentasikan kelas ini sama sekali. Kami berharap untuk segera memperbaikinya. Sementara itu, ingatlah bahwa tipe seperti itu selalu merupakan kelas dalam dari konstruksi L1 yang digunakan.

#### Mereferensikan sumber daya dari konstruksi lain
<a name="constructs-resource-references"></a>

Saat mengonfigurasi properti konstruksi yang mereferensikan sumber daya AWS lainnya, Anda memiliki dua opsi yang setara:
+  **Referensi string**: Lulus nilai string eksplisit seperti ARNs, nama, atau pengidentifikasi sumber daya lainnya
+  **Referensi objek**: Lewati objek konstruksi secara langsung. Ini menghindari keharusan menentukan jenis pengenal mana yang diharapkan properti—CDK menanganinya untuk Anda.

##### Menggunakan referensi string
<a name="_using_string_references"></a>

Anda selalu dapat meneruskan nilai string eksplisit seperti ARNs, nama, atau pengidentifikasi sumber daya lainnya. Pendekatan ini bekerja untuk semua properti dan diperlukan untuk properti bersarang dalam objek kompleks.

Contoh berikut membuat fungsi Lambda menggunakan konstruk L1 (`CfnFunction`) dengan peran yang ditentukan menggunakan konstruksi L2 (). `Role` ARN peran diteruskan ke properti: `role`

**Example**  

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

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

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

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

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

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

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

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

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

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

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

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

##### Menggunakan referensi objek
<a name="_using_object_references"></a>

Untuk properti yang dipilih, Anda dapat meneruskan objek konstruksi secara langsung alih-alih mengekstraksi atributnya secara manual. Support untuk referensi objek bervariasi menurut properti dan dapat berkembang seiring waktu saat properti baru ditambahkan.

Saat Anda meneruskan referensi objek dalam konstruksi`props`, CDK menyelesaikannya ke nilai string yang sesuai (seperti ARN, nama, atau pengenal lainnya). Jika nanti Anda mengakses properti yang sesuai pada instance konstruksi, Anda akan melihat nilai string yang diselesaikan ini, bukan referensi objek asli.

Referensi objek hanya berfungsi untuk properti konstruksi tingkat atas. Properti bersarang dalam objek kompleks memerlukan nilai string eksplisit.

Contoh berikut menunjukkan fungsi Lambda yang sama, tetapi menggunakan objek peran alih-alih string ARN peran:

**Example**  

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

### Bekerja dengan konstruksi L2
<a name="constructs-using"></a>

Dalam contoh berikut, kita mendefinisikan bucket Amazon S3 dengan membuat objek dari konstruksi [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html)L2:

**Example**  

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

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

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

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

```
import aws_cdk.aws_s3 as s3

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

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

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

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

        Bucket.Builder.create(this, "MyFirstBucket")
                .versioned(true).build();
    }
}
```

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

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

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

// stack is HelloCdkStack
awss3.NewBucket(stack, jsii.String("MyFirstBucket"), &awss3.BucketProps{
		Versioned: jsii.Bool(true),
	})
```

 `MyFirstBucket`bukan nama ember yang AWS CloudFormation menciptakan. Ini adalah pengidentifikasi logis yang diberikan ke konstruksi baru dalam konteks aplikasi CDK Anda. Nilai [PhysicalName](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Resource.html#physicalname) akan digunakan untuk memberi nama sumber daya. AWS CloudFormation 

## Bekerja dengan konstruksi pihak ketiga
<a name="constructs-work-third"></a>

 [Construct Hub](https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&sort=downloadsDesc&offset=0) adalah sumber daya untuk membantu Anda menemukan konstruksi tambahan dari AWS, pihak ketiga, dan komunitas CDK sumber terbuka.

### Menulis konstruksi Anda sendiri
<a name="constructs-author"></a>

Selain menggunakan konstruksi yang ada, Anda juga dapat menulis konstruksi Anda sendiri dan membiarkan siapa pun menggunakannya di aplikasi mereka. Semua konstruksi sama dalam AWS CDK. Konstruksi dari Perpustakaan AWS Konstruksi diperlakukan sama seperti konstruksi dari pustaka pihak ketiga yang diterbitkan melaluiNPM,, Maven atau. PyPI Konstruksi yang dipublikasikan ke repositori paket internal perusahaan Anda juga diperlakukan dengan cara yang sama.

Untuk mendeklarasikan konstruksi baru, buat kelas yang memperluas kelas dasar [Construct](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html), dalam `constructs` paket, lalu ikuti pola untuk argumen penginisialisasi.

Contoh berikut menunjukkan cara mendeklarasikan konstruksi yang mewakili bucket Amazon S3. Bucket S3 mengirimkan notifikasi Amazon Simple Notification Service (Amazon SNS) setiap kali seseorang mengunggah file ke dalamnya.

**Example**  

```
export interface NotifyingBucketProps {
  prefix?: string;
}

export class NotifyingBucket extends Construct {
  constructor(scope: Construct, id: string, props: NotifyingBucketProps = {}) {
    super(scope, id);
    const bucket = new s3.Bucket(this, 'bucket');
    const topic = new sns.Topic(this, 'topic');
    bucket.addObjectCreatedNotification(new s3notify.SnsDestination(topic),
      { prefix: props.prefix });
  }
}
```

```
class NotifyingBucket extends Construct {
  constructor(scope, id, props = {}) {
    super(scope, id);
    const bucket = new s3.Bucket(this, 'bucket');
    const topic = new sns.Topic(this, 'topic');
    bucket.addObjectCreatedNotification(new s3notify.SnsDestination(topic),
      { prefix: props.prefix });
  }
}

module.exports = { NotifyingBucket }
```

```
class NotifyingBucket(Construct):

    def __init__(self, scope: Construct, id: str, *, prefix=None):
        super().__init__(scope, id)
        bucket = s3.Bucket(self, "bucket")
        topic = sns.Topic(self, "topic")
        bucket.add_object_created_notification(s3notify.SnsDestination(topic),
            s3.NotificationKeyFilter(prefix=prefix))
```

```
public class NotifyingBucket extends Construct {

    public NotifyingBucket(final Construct scope, final String id) {
        this(scope, id, null, null);
    }

    public NotifyingBucket(final Construct scope, final String id, final BucketProps props) {
        this(scope, id, props, null);
    }

    public NotifyingBucket(final Construct scope, final String id, final String prefix) {
        this(scope, id, null, prefix);
    }

    public NotifyingBucket(final Construct scope, final String id, final BucketProps props, final String prefix) {
        super(scope, id);

        Bucket bucket = new Bucket(this, "bucket");
        Topic topic = new Topic(this, "topic");
        if (prefix != null)
            bucket.addObjectCreatedNotification(new SnsDestination(topic),
                NotificationKeyFilter.builder().prefix(prefix).build());
     }
}
```

```
public class NotifyingBucketProps : BucketProps
{
    public string Prefix { get; set; }
}

public class NotifyingBucket : Construct
{
    public NotifyingBucket(Construct scope, string id, NotifyingBucketProps props = null) : base(scope, id)
    {
        var bucket = new Bucket(this, "bucket");
        var topic = new Topic(this, "topic");
        bucket.AddObjectCreatedNotification(new SnsDestination(topic), new NotificationKeyFilter
        {
            Prefix = props?.Prefix
        });
    }
}
```

```
type NotifyingBucketProps struct {
	awss3.BucketProps
	Prefix *string
}

func NewNotifyingBucket(scope constructs.Construct, id *string, props *NotifyingBucketProps) awss3.Bucket {
	var bucket awss3.Bucket
	if props == nil {
		bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), nil)
	} else {
		bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), &props.BucketProps)
	}
	topic := awssns.NewTopic(scope, jsii.String(*id+"Topic"), nil)
	if props == nil {
		bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic))
	} else {
		bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic), &awss3.NotificationKeyFilter{
			Prefix: props.Prefix,
		})
	}
	return bucket
}
```

**catatan**  
`NotifyingBucket`Konstruksi kami mewarisi bukan dari `Bucket` melainkan dari. `Construct` Kami menggunakan komposisi, bukan pewarisan, untuk menggabungkan bucket Amazon S3 dan topik Amazon SNS bersama-sama. Secara umum, komposisi lebih disukai daripada pewarisan saat mengembangkan konstruksi AWS CDK.

`NotifyingBucket`Konstruktor memiliki tanda tangan konstruksi yang khas:`scope`,`id`, dan. `props` Argumen terakhir,`props`, adalah opsional (mendapat nilai default`{}`) karena semua alat peraga adalah opsional. (`Construct`Kelas dasar tidak mengambil `props` argumen.) Anda dapat menentukan instance konstruksi ini di aplikasi Anda tanpa`props`, misalnya:

**Example**  

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

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

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

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

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

```
NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), nil)
```

Atau Anda dapat menggunakan `props` (di Java, parameter tambahan) untuk menentukan awalan jalur untuk difilter, misalnya:

**Example**  

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

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

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

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

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

```
NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), &NotifyingBucketProps{
	Prefix: jsii.String("images/"),
})
```

Biasanya, Anda juga ingin mengekspos beberapa properti atau metode pada konstruksi Anda. Tidak terlalu berguna untuk memiliki topik yang tersembunyi di balik konstruksi Anda, karena pengguna konstruksi Anda tidak dapat berlangganan. Menambahkan `topic` properti memungkinkan konsumen mengakses topik batin, seperti yang ditunjukkan pada contoh berikut:

**Example**  

```
export class NotifyingBucket extends Construct {
  public readonly topic: sns.Topic;

  constructor(scope: Construct, id: string, props: NotifyingBucketProps) {
    super(scope, id);
    const bucket = new s3.Bucket(this, 'bucket');
    this.topic = new sns.Topic(this, 'topic');
    bucket.addObjectCreatedNotification(new s3notify.SnsDestination(this.topic), { prefix: props.prefix });
  }
}
```

```
class NotifyingBucket extends Construct {

  constructor(scope, id, props) {
    super(scope, id);
    const bucket = new s3.Bucket(this, 'bucket');
    this.topic = new sns.Topic(this, 'topic');
    bucket.addObjectCreatedNotification(new s3notify.SnsDestination(this.topic), { prefix: props.prefix });
  }
}

module.exports = { NotifyingBucket };
```

```
class NotifyingBucket(Construct):

    def __init__(self, scope: Construct, id: str, *, prefix=None, **kwargs):
        super().__init__(scope, id)
        bucket = s3.Bucket(self, "bucket")
        self.topic = sns.Topic(self, "topic")
        bucket.add_object_created_notification(s3notify.SnsDestination(self.topic),
            s3.NotificationKeyFilter(prefix=prefix))
```

```
public class NotifyingBucket extends Construct {

    public Topic topic = null;

    public NotifyingBucket(final Construct scope, final String id) {
        this(scope, id, null, null);
    }

    public NotifyingBucket(final Construct scope, final String id, final BucketProps props) {
        this(scope, id, props, null);
    }

    public NotifyingBucket(final Construct scope, final String id, final String prefix) {
        this(scope, id, null, prefix);
    }

    public NotifyingBucket(final Construct scope, final String id, final BucketProps props, final String prefix) {
        super(scope, id);

        Bucket bucket = new Bucket(this, "bucket");
        topic = new Topic(this, "topic");
        if (prefix != null)
            bucket.addObjectCreatedNotification(new SnsDestination(topic),
                NotificationKeyFilter.builder().prefix(prefix).build());
     }
}
```

```
public class NotifyingBucket : Construct
{
    public readonly Topic topic;

    public NotifyingBucket(Construct scope, string id, NotifyingBucketProps props = null) : base(scope, id)
    {
        var bucket = new Bucket(this, "bucket");
        topic = new Topic(this, "topic");
        bucket.AddObjectCreatedNotification(new SnsDestination(topic), new NotificationKeyFilter
        {
            Prefix = props?.Prefix
        });
    }
}
```
Untuk melakukan ini di Go, kita perlu sedikit pipa tambahan. `NewNotifyingBucket`Fungsi asli kami mengembalikan file`awss3.Bucket`. Kita perlu memperluas `Bucket` untuk menyertakan `topic` anggota dengan membuat `NotifyingBucket` struct. Fungsi kita kemudian akan mengembalikan tipe ini.  

```
type NotifyingBucket struct {
	awss3.Bucket
	topic awssns.Topic
}

func NewNotifyingBucket(scope constructs.Construct, id *string, props *NotifyingBucketProps) NotifyingBucket {
	var bucket awss3.Bucket
	if props == nil {
		bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), nil)
	} else {
		bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), &props.BucketProps)
	}
	topic := awssns.NewTopic(scope, jsii.String(*id+"Topic"), nil)
	if props == nil {
		bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic))
	} else {
		bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic), &awss3.NotificationKeyFilter{
			Prefix: props.Prefix,
		})
	}
	var nbucket NotifyingBucket
	nbucket.Bucket = bucket
	nbucket.topic = topic
	return nbucket
}
```

Sekarang, konsumen dapat berlangganan topik, misalnya:

**Example**  

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

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

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

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

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

```
	queue := awssqs.NewQueue(stack, jsii.String("NewImagesQueue"), nil)
	images := NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), &NotifyingBucketProps{
		Prefix: jsii.String("/images"),
	})
	images.topic.AddSubscription(awssnssubscriptions.NewSqsSubscription(queue, nil))
```

## Pelajari selengkapnya
<a name="constructs-learn"></a>

Video berikut memberikan ikhtisar komprehensif tentang konstruksi CDK, dan menjelaskan bagaimana Anda dapat menggunakannya di aplikasi CDK Anda.

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


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

Mixin adalah fitur yang dapat digunakan kembali yang Anda terapkan pada konstruksi menggunakan metode ini. `.with()` Mereka menambahkan fitur ke konstruksi L1 (CloudFormation-level) dan L2 (berbasis niat), seperti pembuatan versi, objek penghapusan otomatis, atau memblokir akses publik. Setiap mixin bekerja pada satu sumber daya. Untuk menghubungkan dua sumber daya, gunakan [Fasad](facades.md) sebagai gantinya.

Setiap mixin menargetkan jenis sumber daya tertentu dan dinamai menurut sumber daya itu. Misalnya, `BucketVersioning` menargetkan ember Amazon S3. Anda mengakses mixin melalui `mixins` namespace dari setiap modul layanan, seperti. `s3.mixins`

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

Anda menerapkan mixin menggunakan `.with()` metode, yang tersedia di semua konstruksi. Anda dapat menghubungkan beberapa mixin bersama-sama:

**Example**  

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

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

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

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

```
import aws_cdk.aws_s3 as s3

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

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

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

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

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

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

Setiap mixin menyatakan jenis sumber daya yang didukungnya. Jika Anda menerapkan mixin ke konstruksi yang tidak didukungnya, itu dilewati secara diam-diam. Ini berarti Anda dapat dengan aman menerapkan mixin secara luas tanpa khawatir tentang ketidakcocokan tipe. Jika Anda perlu memastikan mixin diterapkan, gunakan [`requireAll()`atau `requireAny()`](#mixins-advanced).

## Gunakan Mixin dengan konstruksi L1 dan L2
<a name="mixins-l1-l2"></a>

Mixin bekerja dengan konstruksi L1 dan L2. Saat Anda menerapkan mixin ke konstruksi L2, itu juga berlaku untuk sumber daya L1 di belakangnya.

Contoh berikut menunjukkan bagaimana menerapkan mixin ke kedua konstruksi L1 dan L2:

**Example**  

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

## Mixins vs. properti konstruksi
<a name="mixins-vs-props"></a>

Mixin dan properti konstruksi bekerja sama. Properti konstruksi L2 menyiapkan sumber daya saat Anda membuatnya. Mixin dapat diterapkan kapan saja.

Gunakan properti konstruksi L2 saat  
Anda menggunakan konstruksi L2 dan properti yang Anda butuhkan tersedia. Ini adalah pendekatan paling sederhana.

Gunakan Mixins saat  
+ Anda bekerja dengan konstruksi L1 dan menginginkan fitur seperti L2.
+ Anda ingin menambahkan fitur ke konstruksi L2 yang tidak tersedia sebagai properti.
+ Anda ingin menerapkan fitur yang sama di beberapa konstruksi dari berbagai jenis.

Mixin tidak menggantikan properti konstruksi. Mereka tidak dapat membuat properti wajib opsional atau mengubah nilai default.

## Terapkan Mixins ke beberapa konstruksi
<a name="mixins-advanced"></a>

`Mixins.of()`API memberikan kontrol lebih besar atas bagaimana mixin diterapkan di seluruh cakupan. Alih-alih memanggil `.with()` konstruksi individual, Anda dapat menerapkan mixin ke semua konstruksi yang cocok dalam tumpukan atau cakupan sekaligus:

**Example**  

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

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

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

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

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

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

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

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

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

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

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

Secara default, konstruksi yang tidak mendukung mixin dilewati secara diam-diam. Gunakan `requireAll()` untuk menegaskan bahwa mixin diterapkan ke setiap konstruksi dalam seleksi, atau `requireAny()` untuk menegaskan itu diterapkan pada setidaknya satu. Ini berguna untuk menegakkan bahwa sumber daya memiliki konfigurasi yang diperlukan:

**Example**  

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

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

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

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

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

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

## Mixin dan Aspek
<a name="mixins-aspects"></a>

Mixin dan [Aspek](aspects.md) terkait tetapi melayani tujuan yang berbeda:
+  **Mixin** diterapkan segera saat Anda menelepon`.with()`. Anda memilih dengan tepat konstruksi mana yang akan diterapkan.
+  **Aspek** berlaku selama sintesis untuk semua konstruksi dalam ruang lingkup. Gunakan mereka untuk kebijakan dan pemeriksaan yang luas.

Gunakan Mixins untuk menambahkan fitur ke konstruksi tertentu. Gunakan Aspek untuk menegakkan aturan atau menerapkan perubahan di seluruh aplikasi Anda.

## Sumber daya terkait
<a name="mixins-related"></a>
+  [Fasad](facades.md) — Hubungkan sumber daya dengan prinsipal IAM dan layanan lainnya.
+  [Aspek](aspects.md) - Terapkan perubahan atau validasi konstruksi di seluruh aplikasi Anda.
+  [Konstruksi](constructs.md) - Pelajari tentang konstruksi L1, L2, dan L3.
+  [Sesuaikan konstruksi](cfn-layer.md) - Sesuaikan konstruksi dengan lubang keluar dan penggantian mentah.

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

Fasad adalah kelas yang menghubungkan sumber daya dengan bagian lain dari aplikasi Anda. Setiap Fasad menargetkan satu jenis sumber daya. Misalnya, kelas diberi nama `BucketGrants` karena memberikan akses ke bucket Amazon S3. Fasad bekerja dengan konstruksi L1 (CloudFormation-level) dan L2 (berbasis niat).

Beberapa Fasad dibuat dan siap digunakan untuk sebagian besar sumber daya, seperti kelas metrik dan reflections. Lainnya ditulis secara manual untuk sumber daya yang membutuhkan logika khusus, seperti kelas Grants.

## Kelas hibah
<a name="facades-grants"></a>

Fasad yang paling banyak digunakan adalah kelas Hibah. Mereka memungkinkan Anda memberikan akses ke AWS sumber daya menggunakan metode sederhana. Misalnya, Anda dapat menggunakan `BucketGrants` untuk bucket Amazon S3 dan untuk topik Amazon `TopicGrants` SNS.

Konstruksi L2 memiliki `grants` properti untuk akses mudah. Anda juga dapat membuat kelas Grants dari konstruksi L1 menggunakan metode pabriknya. Contoh berikut menunjukkan kedua pendekatan:

**Example**  

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

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

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

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

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

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

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

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

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

# my_role is an IAM role defined elsewhere in your app

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[Untuk informasi selengkapnya tentang hibah dan izin, lihat Hibah.](permissions.md#permissions-grants)

## Gunakan Fasad dengan Mixins
<a name="facades-mixins-together"></a>

Anda dapat menggabungkan Fasad dengan [Mixins](mixins.md) untuk mendapatkan pengalaman seperti L2 penuh pada konstruksi L1. Gunakan Mixins untuk menyiapkan sumber daya, dan Fasades untuk memberikan akses:

**Example**  

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

## Sumber daya terkait
<a name="facades-related"></a>
+  [Mixins](mixins.md) - Tambahkan fitur yang dapat digunakan kembali ke konstruksi L1 dan L2.
+  [Hibah](permissions.md#permissions-grants) — Berikan izin antar sumber daya.
+  [Konstruksi](constructs.md) - Pelajari tentang konstruksi L1, L2, dan L3.

# Lingkungan untuk AWS CDK
<a name="environments"></a>

Lingkungan terdiri dari AWS akun dan AWS Wilayah tempat Anda menerapkan tumpukan AWS Cloud Development Kit (AWS CDK).

 ** AWS akun**   
Saat Anda membuat AWS akun, Anda menerima ID akun. ID ini adalah nomor 12 digit, seperti **012345678901**, yang secara unik mengidentifikasi akun Anda. Untuk mempelajari selengkapnya, lihat [Melihat pengenal AWS akun](https://docs.aws.amazon.com/accounts/latest/reference/manage-acct-identifiers.html) di *Panduan Referensi Manajemen AWS Akun*.

 ** AWS Wilayah**   
 AWS Daerah diberi nama dengan menggunakan kombinasi lokasi geografis dan nomor yang mewakili Availability Zone di Wilayah. Sebagai contoh, **. us-east-1 **mewakili Availability Zone di Wilayah AS Timur (Virginia N.). Untuk mempelajari lebih lanjut tentang AWS Wilayah, lihat [Wilayah dan Zona Ketersediaan](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/). Untuk daftar kode Wilayah, lihat [Titik akhir Regional](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints) di Panduan *Referensi Referensi AWS Umum*.

 AWS CDK dapat menentukan lingkungan dari kredensi dan file konfigurasi Anda. File-file ini dapat dibuat dan dikelola dengan AWS Command Line Interface (AWS CLI). Berikut ini adalah contoh dasar dari file-file ini:

 **Berkas kredensialnya**   

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

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

 **File konfigurasi**   

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

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

Anda dapat meneruskan informasi lingkungan dari file-file ini dalam kode CDK Anda melalui variabel lingkungan yang disediakan oleh CDK. Ketika Anda menjalankan perintah CDK CLI, `cdk deploy` seperti, Anda kemudian memberikan profil dari kredensi dan file konfigurasi Anda untuk mengumpulkan informasi lingkungan dari.

Berikut ini adalah contoh menentukan variabel lingkungan ini dalam kode CDK Anda:

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

Berikut ini adalah contoh meneruskan nilai yang terkait dengan `user1` profil dari kredensi dan file konfigurasi Anda ke CDK CLI menggunakan opsi. `--profile` Nilai dari file-file ini akan diteruskan ke variabel lingkungan Anda:

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

Alih-alih menggunakan nilai dari kredensi dan file konfigurasi, Anda juga dapat meng-hard-code nilai lingkungan dalam kode CDK Anda. Berikut ini adalah contohnya:

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

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

## Pelajari selengkapnya
<a name="environments-learn"></a>

Untuk memulai menggunakan lingkungan dengan AWS CDK, lihat [Mengkonfigurasi lingkungan yang akan digunakan dengan AWS CDK](configure-env.md).

# AWS Bootstrap CDK
<a name="bootstrapping"></a>

 *Bootstrapping* adalah proses mempersiapkan AWS lingkungan Anda untuk digunakan dengan AWS Cloud Development Kit (AWS CDK). Sebelum Anda menyebarkan tumpukan CDK ke lingkungan, AWS lingkungan harus di-bootstrap terlebih dahulu.

## Apa itu bootstrapping?
<a name="bootstrapping-what"></a>

Bootstrapping mempersiapkan AWS lingkungan Anda dengan menyediakan AWS sumber daya tertentu di lingkungan Anda yang digunakan oleh CDK. AWS Sumber daya ini biasanya disebut sebagai *sumber daya bootstrap* Anda. Mereka termasuk yang berikut:
+  Bucket **Amazon Simple Storage Service (Amazon S3)** - Digunakan untuk menyimpan file proyek CDK Anda, seperti kode fungsi dan aset AWS Lambda.
+  Repositori **Amazon Elastic Container Registry (Amazon ECR)** - Digunakan terutama untuk menyimpan Docker gambar.
+  ** AWS Peran Identity and Access Management (IAM)** — Dikonfigurasi untuk memberikan izin yang diperlukan oleh CDK untuk melakukan penerapan. AWS Untuk informasi selengkapnya tentang peran IAM yang dibuat selama bootstrap, lihat peran [IAM](bootstrapping-env.md#bootstrapping-env-roles) yang dibuat selama bootstrap.

## Bagaimana cara kerja bootstrapping?
<a name="bootstrapping-how"></a>

Sumber daya dan konfigurasinya yang digunakan oleh CDK didefinisikan dalam AWS CloudFormation template. Template ini dibuat dan dikelola oleh tim CDK. Untuk versi terbaru dari template ini, lihat [https://github.com/aws/aws-cdk-cli/blob/main/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml](https://github.com/aws/aws-cdk-cli/blob/main/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml)di * aws-cdk-cli GitHub repositori*.

Untuk mem-bootstrap lingkungan, Anda menggunakan perintah AWS CDK Command Line Interface (AWS CDK CLI). `cdk bootstrap` *CDK CLI mengambil template dan menyebarkannya sebagai tumpukan, AWS CloudFormation yang dikenal sebagai tumpukan bootstrap.* Secara default, nama tumpukan adalah`CDKToolkit`. Dengan menerapkan template ini, berikan CloudFormation sumber daya di lingkungan Anda. Setelah penerapan, tumpukan bootstrap akan muncul di AWS CloudFormation konsol lingkungan Anda.

Anda juga dapat menyesuaikan bootstrap dengan memodifikasi template atau dengan menggunakan opsi CDK CLI dengan perintah. `cdk bootstrap`

 AWS lingkungan bersifat independen. Setiap lingkungan yang ingin Anda gunakan dengan AWS CDK harus di-bootstrap terlebih dahulu.

## Pelajari selengkapnya
<a name="bootstrapping-learn"></a>

Untuk petunjuk tentang bootstrap lingkungan Anda, lihat [Bootstrap lingkungan Anda untuk digunakan dengan](bootstrapping-env.md) CDK. AWS 

# Sumber daya dan AWS CDK
<a name="resources"></a>

 *Sumber daya* adalah apa yang Anda konfigurasikan untuk menggunakan AWS layanan dalam aplikasi Anda. Sumber daya adalah fitur dari AWS CloudFormation. Dengan mengonfigurasi sumber daya dan propertinya dalam AWS CloudFormation templat, Anda dapat menerapkan AWS CloudFormation untuk menyediakan sumber daya Anda. Dengan AWS Cloud Development Kit (AWS CDK), Anda dapat mengonfigurasi sumber daya melalui konstruksi. Anda kemudian menerapkan aplikasi CDK Anda, yang melibatkan sintesis AWS CloudFormation template dan penerapan untuk AWS CloudFormation menyediakan sumber daya Anda.

## Mengkonfigurasi sumber daya menggunakan konstruksi
<a name="resources-configure"></a>

Seperti yang dijelaskan dalam [Konstruksi AWS CDK](constructs.md), AWS CDK menyediakan perpustakaan kelas kaya konstruksi, yang disebut *konstruksi*, yang mewakili semua sumber daya. AWS 

Untuk membuat instance sumber daya menggunakan konstruksi yang sesuai, teruskan lingkup sebagai argumen pertama, ID logis konstruksi, dan satu set properti konfigurasi (props). Misalnya, berikut cara membuat antrean Amazon SQS dengan enkripsi AWS KMS menggunakan [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sqs.Queue.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_sqs.Queue.html)konstruksi dari Construct Library. AWS 

**Example**  

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

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

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

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

```
import aws_cdk.aws_sqs as sqs

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

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

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

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

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

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

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

Beberapa alat peraga konfigurasi bersifat opsional, dan dalam banyak kasus memiliki nilai default. Dalam beberapa kasus, semua alat peraga bersifat opsional, dan argumen terakhir dapat dihilangkan seluruhnya.

### Atribut sumber daya
<a name="resources-attributes"></a>

Sebagian besar sumber daya dalam AWS Construct Library mengekspos atribut, yang diselesaikan pada waktu penerapan oleh. AWS CloudFormation Atribut diekspos dalam bentuk properti pada kelas sumber daya dengan nama tipe sebagai awalan. Contoh berikut menunjukkan cara mendapatkan URL antrian Amazon SQS menggunakan properti (`queueUrl`Python:). `queue_url`

**Example**  

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

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

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

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

```
import aws_cdk.aws_sqs as sqs

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

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

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

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

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

Lihat [Token dan AWS CDK](tokens.md) untuk informasi tentang cara AWS CDK mengkodekan atribut waktu penerapan sebagai string.

## Referensi sumber daya
<a name="resources-referencing"></a>

Saat mengonfigurasi sumber daya, Anda sering harus mereferensikan properti dari sumber daya lain. Berikut ini adalah beberapa contohnya:
+ Sumber daya Amazon Elastic Container Service (Amazon ECS) memerlukan referensi ke cluster tempat ia berjalan.
+  CloudFront Distribusi Amazon memerlukan referensi ke bucket Amazon Simple Storage Service (Amazon S3) Simple Storage Service (Amazon S3) yang berisi kode sumber.

Anda dapat mereferensikan sumber daya dengan salah satu cara berikut:
+ Dengan meneruskan sumber daya yang ditentukan dalam aplikasi CDK Anda, baik di tumpukan yang sama atau di tumpukan yang berbeda
+ Dengan meneruskan objek proxy yang mereferensikan sumber daya yang ditentukan di AWS akun Anda, dibuat dari pengenal unik sumber daya (seperti ARN)

Jika properti konstruksi mewakili konstruksi untuk sumber daya lain, tipenya adalah tipe antarmuka konstruksi. Misalnya, konstruksi Amazon ECS mengambil properti `cluster` tipe. `ecs.ICluster` Contoh lain, adalah konstruksi CloudFront distribusi yang mengambil properti `sourceBucket` (Python`source_bucket`:) tipe. `s3.IBucket`

Anda dapat langsung meneruskan objek sumber daya apa pun dari jenis yang tepat yang ditentukan dalam aplikasi AWS CDK yang sama. Contoh berikut mendefinisikan cluster Amazon ECS dan kemudian menggunakannya untuk menentukan layanan Amazon ECS.

**Example**  

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

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

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

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

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

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

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

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

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

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

### Mereferensikan sumber daya dalam tumpukan yang berbeda
<a name="resource-stack"></a>

Anda dapat merujuk ke sumber daya di tumpukan yang berbeda selama mereka didefinisikan dalam aplikasi yang sama dan berada di AWS lingkungan yang sama. Pola berikut ini umumnya digunakan:
+ Simpan referensi ke konstruksi sebagai atribut tumpukan yang menghasilkan sumber daya. (Untuk mendapatkan referensi ke tumpukan konstruksi saat ini, gunakan`Stack.of(this)`.)
+ Berikan referensi ini ke konstruktor tumpukan yang mengkonsumsi sumber daya sebagai parameter atau properti. Tumpukan konsumsi kemudian meneruskannya sebagai properti ke konstruksi apa pun yang membutuhkannya.

Contoh berikut mendefinisikan tumpukan`stack1`. Tumpukan ini mendefinisikan bucket Amazon S3 dan menyimpan referensi ke konstruksi bucket sebagai atribut tumpukan. Kemudian aplikasi mendefinisikan tumpukan kedua`stack2`, yang menerima bucket saat instantiation. `stack2`mungkin, misalnya, mendefinisikan AWS Glue Table yang menggunakan bucket untuk penyimpanan data.

**Example**  

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

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

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

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

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

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

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

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

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

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

App app = new App();

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

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

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

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

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

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

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

Jika AWS CDK menentukan bahwa sumber daya berada di lingkungan yang sama, tetapi dalam tumpukan yang berbeda, secara otomatis mensintesis AWS CloudFormation [ekspor](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html) di tumpukan penghasil dan di tumpukan konsumsi untuk mentransfer informasi itu dari satu tumpukan ke tumpukan lainnya. [https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html)

#### Menyelesaikan kebuntuan ketergantungan
<a name="resources-deadlock"></a>

Mereferensikan sumber daya dari satu tumpukan di tumpukan yang berbeda menciptakan ketergantungan antara dua tumpukan. Ini memastikan bahwa mereka dikerahkan dalam urutan yang benar. Setelah tumpukan digunakan, ketergantungan ini konkret. Setelah itu, menghapus penggunaan sumber daya bersama dari tumpukan konsumsi dapat menyebabkan kegagalan penerapan yang tidak terduga. Ini terjadi jika ada ketergantungan lain antara dua tumpukan yang memaksa mereka untuk digunakan dalam urutan yang sama. Ini juga dapat terjadi tanpa ketergantungan jika tumpukan penghasil hanya dipilih oleh CDK Toolkit untuk digunakan terlebih dahulu. AWS CloudFormation Ekspor dihapus dari tumpukan penghasil karena tidak lagi diperlukan, tetapi sumber daya yang diekspor masih digunakan di tumpukan konsumsi karena pembaruannya belum diterapkan. Oleh karena itu, penerapan tumpukan produsen gagal.

Untuk memecahkan kebuntuan ini, hapus penggunaan sumber daya bersama dari tumpukan konsumsi. (Ini menghapus ekspor otomatis dari tumpukan produksi.) Selanjutnya, tambahkan ekspor yang sama secara manual ke tumpukan penghasil menggunakan ID logis yang sama persis dengan ekspor yang dihasilkan secara otomatis. Hapus penggunaan sumber daya bersama di tumpukan konsumsi dan terapkan kedua tumpukan. Kemudian, hapus ekspor manual (dan sumber daya bersama jika tidak lagi diperlukan) dan gunakan kedua tumpukan lagi. [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#exportwbrvalueexportedvalue-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#exportwbrvalueexportedvalue-options)Metode tumpukan adalah cara mudah untuk membuat ekspor manual untuk tujuan ini. (Lihat contoh dalam referensi metode tertaut.)

### Mereferensikan sumber daya di akun Anda AWS
<a name="resources-external"></a>

Misalkan Anda ingin menggunakan sumber daya yang sudah tersedia di AWS akun Anda di aplikasi AWS CDK Anda. Ini mungkin sumber daya yang didefinisikan melalui konsol, AWS SDK, langsung dengan AWS CloudFormation, atau dalam aplikasi AWS CDK yang berbeda. Anda dapat mengubah ARN sumber daya (atau atribut pengidentifikasi lain, atau grup atribut) menjadi objek proxy. Objek proxy berfungsi sebagai referensi ke sumber daya dengan memanggil metode pabrik statis pada kelas sumber daya.

Saat Anda membuat proxy seperti itu, sumber daya eksternal **tidak** menjadi bagian dari aplikasi AWS CDK Anda. Oleh karena itu, perubahan yang Anda buat pada proxy di aplikasi AWS CDK Anda tidak memengaruhi sumber daya yang diterapkan. Proxy dapat, bagaimanapun, diteruskan ke metode AWS CDK apa pun yang membutuhkan sumber daya jenis itu.

Contoh berikut menunjukkan cara mereferensikan bucket berdasarkan bucket yang ada dengan ARN`arn:aws:s3:::amzn-s3-demo-bucket1`, dan Amazon Virtual Private Cloud berdasarkan VPC yang sudah ada yang memiliki ID tertentu.

**Example**  

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Mari kita lihat lebih dekat [https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.Vpc.html#static-fromwbrlookupscope-id-options](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.Vpc.html#static-fromwbrlookupscope-id-options)metodenya. Karena `ec2.Vpc` konstruksinya rumit, ada banyak cara Anda mungkin ingin memilih VPC yang akan digunakan dengan aplikasi CDK Anda. Untuk mengatasi hal ini, konstruksi VPC memiliki metode `fromLookup` statis (Python:`from_lookup`) yang memungkinkan Anda mencari VPC Amazon yang diinginkan dengan menanyakan akun Anda pada waktu sintesis. AWS 

Untuk menggunakannya`Vpc.fromLookup()`, sistem yang mensintesis tumpukan harus memiliki akses ke akun yang memiliki Amazon VPC. Ini karena CDK Toolkit menanyakan akun untuk menemukan VPC Amazon yang tepat pada waktu sintesis.

Selanjutnya, hanya `Vpc.fromLookup()` berfungsi di tumpukan yang ditentukan dengan **akun** dan **wilayah** eksplisit (lihat [Lingkungan untuk AWS CDK](environments.md)). Jika AWS CDK mencoba mencari VPC Amazon dari tumpukan [agnostik lingkungan](stacks.md#stack-api), CDK Toolkit tidak tahu lingkungan mana yang harus ditanyakan untuk menemukan VPC.

Anda harus memberikan `Vpc.fromLookup()` atribut yang cukup untuk mengidentifikasi VPC secara unik di akun Anda. AWS Misalnya, hanya ada satu VPC default, jadi cukup untuk menentukan VPC sebagai default.

**Example**  

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

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

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

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

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

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

Anda juga dapat menggunakan `tags` properti untuk kueri VPCs berdasarkan tag. Anda dapat menambahkan tag ke VPC Amazon pada saat pembuatannya dengan menggunakan AWS CloudFormation atau CDK AWS . Anda dapat mengedit tag kapan saja setelah pembuatan menggunakan AWS Management Console, AWS CLI, atau SDK. AWS Selain tag apa pun yang Anda tambahkan sendiri, AWS CDK secara otomatis menambahkan tag berikut ke semua yang VPCs dibuatnya.
+  **Nama** — Nama VPC.
+  **aws-cdk:subnet-name — Nama subnet**.
+  **aws-cdk:subnet-type — Jenis subnet**: Publik, Pribadi, atau Terisolasi.

**Example**  

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

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

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

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

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

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

Hasil `Vpc.fromLookup()` cache dalam `cdk.context.json` file proyek. (Lihat [nilai Konteks dan AWS CDK](context.md).) Komit file ini ke kontrol versi sehingga aplikasi Anda akan terus merujuk ke VPC Amazon yang sama. Ini berfungsi bahkan jika nanti Anda mengubah atribut Anda dengan VPCs cara yang akan menghasilkan VPC yang berbeda dipilih. [Ini sangat penting jika Anda menerapkan tumpukan di lingkungan yang tidak memiliki akses ke AWS akun yang mendefinisikan VPC, seperti CDK Pipelines.](cdk-pipeline.md)

Meskipun Anda dapat menggunakan sumber daya eksternal di mana pun Anda menggunakan sumber daya serupa yang ditentukan dalam aplikasi AWS CDK Anda, Anda tidak dapat memodifikasinya. Misalnya, memanggil `addToResourcePolicy` (Python:`add_to_resource_policy`) pada eksternal `s3.Bucket` tidak melakukan apa-apa.

## Nama fisik sumber daya
<a name="resources-physical-names"></a>

Nama logis sumber daya AWS CloudFormation berbeda dari nama sumber daya yang ditampilkan di Konsol AWS Manajemen setelah digunakan oleh AWS CloudFormation. AWS CDK menyebut nama-nama akhir ini *nama fisik*.

Misalnya, AWS CloudFormation mungkin membuat bucket Amazon S3 dengan ID logis `Stack2MyBucket4DD88B4F` dan nama fisik. `stack2MyBucket4dd88b4f-iuv1rbv9z3to`

Anda dapat menentukan nama fisik saat membuat konstruksi yang mewakili sumber daya dengan menggunakan properti`<resourceType>Name`. Contoh berikut membuat bucket Amazon S3 dengan nama fisik. `amzn-s3-demo-bucket`

**Example**  

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

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

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

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

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

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

Menetapkan nama fisik ke sumber daya memiliki beberapa kelemahan. AWS CloudFormation Yang paling penting, setiap perubahan pada sumber daya yang digunakan yang memerlukan penggantian sumber daya, seperti perubahan pada properti sumber daya yang tidak dapat diubah setelah pembuatan, akan gagal jika sumber daya memiliki nama fisik yang ditetapkan. Jika Anda berakhir dalam keadaan itu, satu-satunya solusi adalah menghapus AWS CloudFormation tumpukan, lalu menerapkan aplikasi AWS CDK lagi. Lihat [AWS CloudFormation dokumentasi](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) untuk detailnya.

Dalam beberapa kasus, seperti saat membuat aplikasi AWS CDK dengan referensi lintas lingkungan, nama fisik diperlukan agar AWS CDK berfungsi dengan benar. Dalam kasus tersebut, jika Anda tidak ingin repot-repot membuat nama fisik sendiri, Anda dapat membiarkan AWS CDK menamainya untuk Anda. Untuk melakukannya, gunakan nilai khusus`PhysicalName.GENERATE_IF_NEEDED`, sebagai berikut.

**Example**  

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

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

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

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

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

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

## Melewati pengidentifikasi sumber daya unik
<a name="resources-identifiers"></a>

Bila memungkinkan, Anda harus melewatkan sumber daya dengan referensi, seperti yang dijelaskan di bagian sebelumnya. Namun, ada kasus di mana Anda tidak punya pilihan lain selain merujuk ke sumber daya dengan salah satu atributnya. Contoh kasus penggunaan meliputi yang berikut:
+ Saat Anda menggunakan AWS CloudFormation sumber daya tingkat rendah.
+ Saat Anda perlu mengekspos sumber daya ke komponen runtime aplikasi AWS CDK, seperti saat merujuk ke fungsi Lambda melalui variabel lingkungan.

Pengidentifikasi ini tersedia sebagai atribut pada sumber daya, seperti berikut ini.

**Example**  

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

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

```
bucket.bucket_name
lambda_func.function_arn
security_group_arn
```
Pengikatan AWS CDK Java menggunakan metode pengambil untuk atribut.  

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

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

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

Contoh berikut menunjukkan cara meneruskan nama bucket yang dihasilkan ke fungsi AWS Lambda.

**Example**  

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

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

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

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

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

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

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

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

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

new Function(this, "MyLambda", new FunctionProps
{
    Environment = new Dictionary<string, string>
    {
        ["BUCKET_NAME"] = bucket.BucketName
    }
});
```

```
bucket := s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{})
lambda.NewFunction(this, jsii.String("MyLambda"), &lambda.FunctionProps{
  Environment: &map[string]*string{"BUCKET_NAME": bucket.BucketName()},
})
```

## Memberikan izin antar sumber daya
<a name="resources-grants"></a>

Konstruksi tingkat yang lebih tinggi membuat izin hak istimewa paling sedikit dapat dicapai dengan menawarkan persyaratan izin yang sederhana dan berbasis niat untuk menyatakan. APIs Misalnya, banyak konstruksi menawarkan metode hibah yang dapat Anda gunakan untuk memberikan izin entitas (seperti peran IAM atau pengguna) untuk bekerja dengan sumber daya, tanpa harus membuat pernyataan izin IAM secara manual.

Metode hibah tersedia melalui kelas Grants (seperti `BucketGrants` untuk bucket Amazon S3). Kelas-kelas ini bekerja dengan konstruksi L1 dan L2. Konstruksi L2 mengekspos `grants` properti untuk kenyamanan, tetapi Anda juga dapat membuat kelas Grants langsung dari konstruksi L1. Anda dapat menggabungkan kelas Grants dengan [Mixins](mixins.md) untuk mendapatkan kenyamanan seperti L2 pada konstruksi L1.

Contoh berikut membuat izin untuk mengizinkan peran eksekusi fungsi Lambda membaca dan menulis objek ke bucket Amazon S3 tertentu. Jika bucket Amazon S3 dienkripsi dengan kunci AWS KMS, metode ini juga memberikan izin ke peran eksekusi fungsi Lambda untuk mendekripsi dengan kunci.

**Example**  

```
if (bucket.grants.readWrite(func).success) {
  // ...
}
```

```
if ( bucket.grants.readWrite(func).success) {
  // ...
}
```

```
if bucket.grants.read_write(func).success:
    # ...
```

```
if (bucket.getGrants().readWrite(func).getSuccess()) {
    // ...
}
```

```
if (bucket.Grants.ReadWrite(func).Success)
{
    // ...
}
```

```
if *bucket.Grants().ReadWrite(function, nil).Success() {
  // ...
}
```

Metode hibah mengembalikan `iam.Grant` objek. Gunakan `success` atribut `Grant` objek untuk menentukan apakah hibah diterapkan secara efektif (misalnya, mungkin tidak diterapkan pada [sumber daya eksternal](#resources-referencing)). Anda juga dapat menggunakan metode `assertSuccess` (Python:`assert_success`) `Grant` objek untuk menegakkan bahwa hibah berhasil diterapkan.

Jika metode hibah tertentu tidak tersedia untuk kasus penggunaan tertentu, Anda dapat menggunakan metode hibah generik untuk menentukan hibah baru dengan daftar tindakan tertentu.

Contoh berikut menunjukkan cara memberikan akses fungsi Lambda ke tindakan Amazon DynamoDB. `CreateBackup`

**Example**  

```
table.grants.actions(func, 'dynamodb:CreateBackup');
```

```
table.grants.actions(func, 'dynamodb:CreateBackup');
```

```
table.grants.actions(func, "dynamodb:CreateBackup")
```

```
table.getGrants().actions(func, "dynamodb:CreateBackup");
```

```
table.Grants.Actions(func, "dynamodb:CreateBackup");
```

```
table := dynamodb.NewTable(this, jsii.String("MyTable"), &dynamodb.TableProps{})
table.Grants().Actions(function, jsii.String("dynamodb:CreateBackup"))
```

Banyak sumber daya, seperti fungsi Lambda, memerlukan peran yang harus diasumsikan saat mengeksekusi kode. Properti konfigurasi memungkinkan Anda untuk menentukan`iam.IRole`. Jika tidak ada peran yang ditentukan, fungsi secara otomatis membuat peran khusus untuk penggunaan ini. Anda kemudian dapat menggunakan metode hibah pada sumber daya untuk menambahkan pernyataan ke peran.

Metode hibah dibangun menggunakan tingkat yang lebih rendah APIs untuk penanganan dengan kebijakan IAM. Kebijakan dimodelkan sebagai [PolicyDocument](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyDocument.html)objek. Tambahkan pernyataan langsung ke peran (atau peran terlampir konstruksi) menggunakan `addToRolePolicy` metode (Python`add_to_role_policy`:), atau ke kebijakan sumber daya (seperti `Bucket` kebijakan) menggunakan metode `addToResourcePolicy` (`add_to_resource_policy`Python:).

## Metrik sumber daya dan alarm
<a name="resources-metrics"></a>

Banyak sumber daya memancarkan CloudWatch metrik yang dapat digunakan untuk mengatur dasbor pemantauan dan alarm. Konstruksi tingkat yang lebih tinggi memiliki metode metrik yang memungkinkan Anda mengakses metrik tanpa mencari nama yang benar untuk digunakan.

Contoh berikut menunjukkan cara menentukan alarm ketika antrian Amazon SQS melebihi 100. `ApproximateNumberOfMessagesNotVisible`

**Example**  

```
import * as cw from '@aws-cdk/aws-cloudwatch';
import * as sqs from '@aws-cdk/aws-sqs';
import { Duration } from '@aws-cdk/core';

const queue = new sqs.Queue(this, 'MyQueue');

const metric = queue.metricApproximateNumberOfMessagesNotVisible({
  label: 'Messages Visible (Approx)',
  period: Duration.minutes(5),
  // ...
});
metric.createAlarm(this, 'TooManyMessagesAlarm', {
  comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD,
  threshold: 100,
  // ...
});
```

```
const cw = require('@aws-cdk/aws-cloudwatch');
const sqs = require('@aws-cdk/aws-sqs');
const { Duration } = require('@aws-cdk/core');

const queue = new sqs.Queue(this, 'MyQueue');

const metric = queue.metricApproximateNumberOfMessagesNotVisible({
  label: 'Messages Visible (Approx)',
  period: Duration.minutes(5)
  // ...
});
metric.createAlarm(this, 'TooManyMessagesAlarm', {
  comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD,
  threshold: 100
  // ...
});
```

```
import aws_cdk.aws_cloudwatch as cw
import aws_cdk.aws_sqs as sqs
from aws_cdk.core import Duration

queue = sqs.Queue(self, "MyQueue")
metric = queue.metric_approximate_number_of_messages_not_visible(
    label="Messages Visible (Approx)",
    period=Duration.minutes(5),
    # ...
)
metric.create_alarm(self, "TooManyMessagesAlarm",
    comparison_operator=cw.ComparisonOperator.GREATER_THAN_THRESHOLD,
    threshold=100,
    # ...
)
```

```
import software.amazon.awscdk.core.Duration;
import software.amazon.awscdk.services.sqs.Queue;
import software.amazon.awscdk.services.cloudwatch.Metric;
import software.amazon.awscdk.services.cloudwatch.MetricOptions;
import software.amazon.awscdk.services.cloudwatch.CreateAlarmOptions;
import software.amazon.awscdk.services.cloudwatch.ComparisonOperator;

Queue queue = new Queue(this, "MyQueue");

Metric metric = queue
        .metricApproximateNumberOfMessagesNotVisible(MetricOptions.builder()
                .label("Messages Visible (Approx)")
                .period(Duration.minutes(5)).build());

metric.createAlarm(this, "TooManyMessagesAlarm", CreateAlarmOptions.builder()
                .comparisonOperator(ComparisonOperator.GREATER_THAN_THRESHOLD)
                .threshold(100)
                // ...
                .build());
```

```
using cdk = Amazon.CDK;
using cw = Amazon.CDK.AWS.CloudWatch;
using sqs = Amazon.CDK.AWS.SQS;

var queue = new sqs.Queue(this, "MyQueue");
var metric = queue.MetricApproximateNumberOfMessagesNotVisible(new cw.MetricOptions
{
    Label = "Messages Visible (Approx)",
    Period = cdk.Duration.Minutes(5),
    // ...
});
metric.CreateAlarm(this, "TooManyMessagesAlarm", new cw.CreateAlarmOptions
{
    ComparisonOperator = cw.ComparisonOperator.GREATER_THAN_THRESHOLD,
    Threshold = 100,
    // ..
});
```

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

queue := sqs.NewQueue(this, jsii.String("MyQueue"), &sqs.QueueProps{})
metric := queue.MetricApproximateNumberOfMessagesNotVisible(&cw.MetricOptions{
  Label: jsii.String("Messages Visible (Approx)"),
  Period: awscdk.Duration_Minutes(jsii.Number(5)),
})

metric.CreateAlarm(this, jsii.String("TooManyMessagesAlarm"), &cw.CreateAlarmOptions{
  ComparisonOperator: cw.ComparisonOperator_GREATER_THAN_THRESHOLD,
  Threshold: jsii.Number(100),
})
```

Jika tidak ada metode untuk metrik tertentu, Anda dapat menggunakan metode metrik umum untuk menentukan nama metrik secara manual.

Metrik juga dapat ditambahkan ke CloudWatch dasbor. Lihat [CloudWatch](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch-readme.html).

## Lalu lintas jaringan
<a name="resources-traffic"></a>

Dalam banyak kasus, Anda harus mengaktifkan izin pada jaringan agar aplikasi berfungsi, seperti ketika infrastruktur komputasi perlu mengakses lapisan persistensi. Sumber daya yang membangun atau mendengarkan koneksi mengekspos metode yang memungkinkan arus lalu lintas, termasuk pengaturan aturan grup keamanan atau jaringan ACLs.

 [IConnectable](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.IConnectable.html)sumber daya memiliki `connections` properti yang merupakan gateway ke konfigurasi aturan lalu lintas jaringan.

Anda mengaktifkan data mengalir pada jalur jaringan tertentu dengan menggunakan `allow` metode. Contoh berikut memungkinkan koneksi HTTPS ke web dan koneksi masuk dari grup Amazon EC2 Auto Scaling. `fleet2`

**Example**  

```
import * as asg from '@aws-cdk/aws-autoscaling';
import * as ec2 from '@aws-cdk/aws-ec2';

const fleet1: asg.AutoScalingGroup = asg.AutoScalingGroup(/*...*/);

// Allow surfing the (secure) web
fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 }));

const fleet2: asg.AutoScalingGroup = asg.AutoScalingGroup(/*...*/);
fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic());
```

```
const asg = require('@aws-cdk/aws-autoscaling');
const ec2 = require('@aws-cdk/aws-ec2');

const fleet1 = asg.AutoScalingGroup();

// Allow surfing the (secure) web
fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 }));

const fleet2 = asg.AutoScalingGroup();
fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic());
```

```
import aws_cdk.aws_autoscaling as asg
import aws_cdk.aws_ec2 as ec2

fleet1 = asg.AutoScalingGroup( ... )

# Allow surfing the (secure) web
fleet1.connections.allow_to(ec2.Peer.any_ipv4(),
  ec2.Port(PortProps(from_port=443, to_port=443)))

fleet2 = asg.AutoScalingGroup( ... )
fleet1.connections.allow_from(fleet2, ec2.Port.all_traffic())
```

```
import software.amazon.awscdk.services.autoscaling.AutoScalingGroup;
import software.amazon.awscdk.services.ec2.Peer;
import software.amazon.awscdk.services.ec2.Port;

AutoScalingGroup fleet1 = AutoScalingGroup.Builder.create(this, "MyFleet")
        /* ... */.build();

// Allow surfing the (secure) Web
fleet1.getConnections().allowTo(Peer.anyIpv4(),
        Port.Builder.create().fromPort(443).toPort(443).build());

AutoScalingGroup fleet2 = AutoScalingGroup.Builder.create(this, "MyFleet2")
        /* ... */.build();
fleet1.getConnections().allowFrom(fleet2, Port.allTraffic());
```

```
using cdk = Amazon.CDK;
using asg = Amazon.CDK.AWS.AutoScaling;
using ec2 = Amazon.CDK.AWS.EC2;

// Allow surfing the (secure) Web
var fleet1 = new asg.AutoScalingGroup(this, "MyFleet", new asg.AutoScalingGroupProps { /* ... */ });
fleet1.Connections.AllowTo(ec2.Peer.AnyIpv4(), new ec2.Port(new ec2.PortProps
  { FromPort = 443, ToPort = 443 }));

var fleet2 = new asg.AutoScalingGroup(this, "MyFleet2", new asg.AutoScalingGroupProps { /* ... */ });
fleet1.Connections.AllowFrom(fleet2, ec2.Port.AllTraffic());
```

```
import (
  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/jsii-runtime-go"
  autoscaling "github.com/aws/aws-cdk-go/awscdk/v2/awsautoscaling"
  ec2 "github.com/aws/aws-cdk-go/awscdk/v2/awsec2"
)

fleet1 := autoscaling.NewAutoScalingGroup(this, jsii.String("MyFleet1"), &autoscaling.AutoScalingGroupProps{})
fleet1.Connections().AllowTo(ec2.Peer_AnyIpv4(),ec2.NewPort(&ec2.PortProps{ FromPort: jsii.Number(443), ToPort: jsii.Number(443) }),jsii.String("secure web"))

fleet2 := autoscaling.NewAutoScalingGroup(this, jsii.String("MyFleet2"), &autoscaling.AutoScalingGroupProps{})
fleet1.Connections().AllowFrom(fleet2, ec2.Port_AllTraffic(),jsii.String("all traffic"))
```

Sumber daya tertentu memiliki port default yang terkait dengannya. Contohnya termasuk pendengar penyeimbang beban di port publik, dan port tempat mesin database menerima koneksi untuk instance database Amazon RDS. Dalam kasus seperti itu, Anda dapat menerapkan kontrol jaringan yang ketat tanpa harus menentukan port secara manual. Untuk melakukannya, gunakan `allowToDefaultPort` metode `allowDefaultPortFrom` dan (Python:`allow_default_port_from`,`allow_to_default_port`).

Contoh berikut menunjukkan cara mengaktifkan koneksi dari IPV4 alamat apa pun, dan koneksi dari grup Auto Scaling untuk mengakses database.

**Example**  

```
listener.connections.allowDefaultPortFromAnyIpv4('Allow public access');

fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database');
```

```
listener.connections.allowDefaultPortFromAnyIpv4('Allow public access');

fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database');
```

```
listener.connections.allow_default_port_from_any_ipv4("Allow public access")

fleet.connections.allow_to_default_port(rds_database, "Fleet can access database")
```

```
listener.getConnections().allowDefaultPortFromAnyIpv4("Allow public access");

fleet.getConnections().AllowToDefaultPort(rdsDatabase, "Fleet can access database");
```

```
listener.Connections.AllowDefaultPortFromAnyIpv4("Allow public access");

fleet.Connections.AllowToDefaultPort(rdsDatabase, "Fleet can access database");
```

```
listener.Connections().AllowDefaultPortFromAnyIpv4(jsii.String("Allow public Access"))
fleet.Connections().AllowToDefaultPort(rdsDatabase, jsii.String("Fleet can access database"))
```

## Penanganan acara
<a name="resources-events"></a>

Beberapa sumber daya dapat bertindak sebagai sumber acara. Gunakan `addEventNotification` metode (Python:`add_event_notification`) untuk mendaftarkan target acara ke jenis peristiwa tertentu yang dipancarkan oleh sumber daya. Selain itu, `addXxxNotification` metode menawarkan cara sederhana untuk mendaftarkan handler untuk jenis acara umum.

Contoh berikut menunjukkan cara memicu fungsi Lambda saat objek ditambahkan ke bucket Amazon S3.

**Example**  

```
import * as s3nots from '@aws-cdk/aws-s3-notifications';

const handler = new lambda.Function(this, 'Handler', { /*…*/ });
const bucket = new s3.Bucket(this, 'Bucket');
bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler));
```

```
const s3nots = require('@aws-cdk/aws-s3-notifications');

const handler = new lambda.Function(this, 'Handler', { /*…*/ });
const bucket = new s3.Bucket(this, 'Bucket');
bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler));
```

```
import aws_cdk.aws_s3_notifications as s3_nots

handler = lambda_.Function(self, "Handler", ...)
bucket = s3.Bucket(self, "Bucket")
bucket.add_object_created_notification(s3_nots.LambdaDestination(handler))
```

```
import software.amazon.awscdk.services.s3.Bucket;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.s3.notifications.LambdaDestination;

Function handler = Function.Builder.create(this, "Handler")/* ... */.build();
Bucket bucket = new Bucket(this, "Bucket");
bucket.addObjectCreatedNotification(new LambdaDestination(handler));
```

```
using lambda = Amazon.CDK.AWS.Lambda;
using s3 = Amazon.CDK.AWS.S3;
using s3Nots = Amazon.CDK.AWS.S3.Notifications;

var handler = new lambda.Function(this, "Handler", new lambda.FunctionProps { .. });
var bucket = new s3.Bucket(this, "Bucket");
bucket.AddObjectCreatedNotification(new s3Nots.LambdaDestination(handler));
```

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

handler := lambda.NewFunction(this, jsii.String("MyFunction"), &lambda.FunctionProps{})
bucket := s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{})
bucket.AddObjectCreatedNotification(s3nots.NewLambdaDestination(handler), nil)
```

## Kebijakan penghapusan
<a name="resources-removal"></a>

*Sumber daya yang menyimpan data persisten, seperti database, bucket Amazon S3, dan pendaftar Amazon ECR, memiliki kebijakan penghapusan.* Kebijakan penghapusan menunjukkan apakah akan menghapus objek persisten saat tumpukan AWS CDK yang berisi objek tersebut dihancurkan. Nilai yang menentukan kebijakan penghapusan tersedia melalui `RemovalPolicy` enumerasi dalam modul CDK. AWS `core`

**catatan**  
Sumber daya selain yang menyimpan data terus-menerus mungkin juga memiliki `removalPolicy` yang digunakan untuk tujuan yang berbeda. Misalnya, versi fungsi Lambda menggunakan `removalPolicy` atribut untuk menentukan apakah versi tertentu dipertahankan saat versi baru diterapkan. Ini memiliki arti dan default yang berbeda dibandingkan dengan kebijakan penghapusan pada bucket Amazon S3 atau tabel DynamoDB.


| Nilai | Arti | 
| --- | --- | 
|   `RemovalPolicy.RETAIN`   |  Simpan isi sumber daya saat menghancurkan tumpukan (default). Sumber daya menjadi yatim piatu dari tumpukan dan harus dihapus secara manual. Jika Anda mencoba menerapkan kembali tumpukan saat sumber daya masih ada, Anda akan menerima pesan kesalahan karena konflik nama.  | 
|   `RemovalPolicy.DESTROY`   |  Sumber daya akan dihancurkan bersama dengan tumpukan.  | 

 AWS CloudFormation tidak menghapus bucket Amazon S3 yang berisi file meskipun kebijakan penghapusannya disetel ke. `DESTROY` Mencoba melakukannya adalah AWS CloudFormation kesalahan. Agar AWS CDK menghapus semua file dari bucket sebelum menghancurkannya, setel `autoDeleteObjects` properti bucket ke. `true`

Berikut ini adalah contoh membuat bucket Amazon S3 dengan `RemovalPolicy` of `DESTROY` dan `autoDeleteOjbects` disetel ke. `true`

**Example**  

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

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

    const bucket = new s3.Bucket(this, 'Bucket', {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true
    });
  }
}
```

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

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

    const bucket = new s3.Bucket(this, 'Bucket', {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true
    });
  }
}

module.exports = { CdkTestStack }
```

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

class CdkTestStack(cdk.stack):
    def __init__(self, scope: cdk.Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        bucket = s3.Bucket(self, "Bucket",
            removal_policy=cdk.RemovalPolicy.DESTROY,
            auto_delete_objects=True)
```

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

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

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

        Bucket.Builder.create(this, "Bucket")
                .removalPolicy(RemovalPolicy.DESTROY)
                .autoDeleteObjects(true).build();
    }
}
```

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

public CdkTestStack(Construct scope, string id, IStackProps props) : base(scope, id, props)
{
    new Bucket(this, "Bucket", new BucketProps {
        RemovalPolicy = RemovalPolicy.DESTROY,
        AutoDeleteObjects = true
    });
}
```

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

s3.NewBucket(this, jsii.String("Bucket"), &s3.BucketProps{
  RemovalPolicy: awscdk.RemovalPolicy_DESTROY,
  AutoDeleteObjects: jsii.Bool(true),
})
```

Anda juga dapat menerapkan kebijakan penghapusan langsung ke AWS CloudFormation sumber daya yang mendasarinya melalui `applyRemovalPolicy()` metode ini. Metode ini tersedia pada beberapa sumber daya stateful yang tidak memiliki `removalPolicy` properti di alat peraga sumber daya L2 mereka. Contohnya meliputi hal berikut:
+  AWS CloudFormation tumpukan
+ Kumpulan pengguna Amazon Cognito
+ Contoh basis data Amazon DocumentDB
+ Volume Amazon EC2
+ Domain OpenSearch Layanan Amazon
+ Sistem FSx file Amazon
+ Antrean Amazon SQS

**Example**  

```
const resource = bucket.node.findChild('Resource') as cdk.CfnResource;
resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
```

```
const resource = bucket.node.findChild('Resource');
resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
```

```
resource = bucket.node.find_child('Resource')
resource.apply_removal_policy(cdk.RemovalPolicy.DESTROY);
```

```
CfnResource resource = (CfnResource)bucket.node.findChild("Resource");
resource.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
```

```
var resource = (CfnResource)bucket.node.findChild('Resource');
resource.ApplyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
```

**catatan**  
 AWS CDK `RemovalPolicy` diterjemahkan menjadi's. AWS CloudFormation `DeletionPolicy` Namun, default dalam AWS CDK adalah menyimpan data, yang merupakan kebalikan dari AWS CloudFormation default.

# Pengidentifikasi dan CDK AWS
<a name="identifiers"></a>

Saat membuat aplikasi AWS Cloud Development Kit (AWS CDK), Anda akan menggunakan banyak jenis pengenal dan nama. Untuk menggunakan AWS CDK secara efektif dan menghindari kesalahan, penting untuk memahami jenis pengidentifikasi.

Pengidentifikasi harus unik dalam ruang lingkup di mana mereka dibuat; mereka tidak perlu unik secara global dalam aplikasi AWS CDK Anda.

Jika Anda mencoba membuat pengenal dengan nilai yang sama dalam lingkup yang sama, AWS CDK akan melempar pengecualian.

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

Pengidentifikasi yang paling umum,`id`, adalah pengidentifikasi yang diteruskan sebagai argumen kedua saat membuat instance objek konstruksi. Pengidentifikasi ini, seperti semua pengidentifikasi, hanya perlu unik dalam lingkup di mana ia dibuat, yang merupakan argumen pertama ketika membuat instance objek konstruksi.

**catatan**  
Tumpukan juga merupakan pengidentifikasi yang Anda gunakan untuk merujuknya dalam referensi [AWS CDK CLI](cli.md). `id`

Mari kita lihat contoh di mana kita memiliki dua konstruksi dengan identifier `MyBucket` di aplikasi kita. Yang pertama didefinisikan dalam lingkup tumpukan dengan pengenal`Stack1`. Yang kedua didefinisikan dalam lingkup tumpukan dengan pengenal`Stack2`. Karena mereka didefinisikan dalam cakupan yang berbeda, ini tidak menyebabkan konflik apa pun, dan mereka dapat hidup berdampingan di aplikasi yang sama tanpa masalah.

**Example**  

```
import { App, Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';

class MyStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps = {}) {
    super(scope, id, props);

    new s3.Bucket(this, 'MyBucket');
  }
}

const app = new App();
new MyStack(app, 'Stack1');
new MyStack(app, 'Stack2');
```

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

class MyStack extends Stack {
  constructor(scope, id, props = {}) {
    super(scope, id, props);

    new s3.Bucket(this, 'MyBucket');
  }
}

const app = new App();
new MyStack(app, 'Stack1');
new MyStack(app, 'Stack2');
```

```
from aws_cdk import App, Construct, Stack, StackProps
from constructs import Construct
from aws_cdk import aws_s3 as s3

class MyStack(Stack):

    def __init__(self, scope: Construct, id: str, **kwargs):

        super().__init__(scope, id, **kwargs)
        s3.Bucket(self, "MyBucket")

app = App()
MyStack(app, 'Stack1')
MyStack(app, 'Stack2')
```

```
// MyStack.java
package com.myorg;

import software.amazon.awscdk.App;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.constructs.Construct;
import software.amazon.awscdk.services.s3.Bucket;

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

    public MyStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);
        new Bucket(this, "MyBucket");
    }
}

// Main.java
package com.myorg;

import software.amazon.awscdk.App;

public class Main {
    public static void main(String[] args) {
        App app = new App();
        new MyStack(app, "Stack1");
        new MyStack(app, "Stack2");
    }
}
```

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

public class MyStack : Stack
{
    public MyStack(Construct scope, string id, IStackProps props) : base(scope, id, props)
    {
        new Bucket(this, "MyBucket");
    }
}

class Program
{
    static void Main(string[] args)
    {
        var app = new App();
        new MyStack(app, "Stack1");
        new MyStack(app, "Stack2");
    }
}
```

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

Konstruksi dalam aplikasi AWS CDK membentuk hierarki yang berakar di kelas. `App` *Kami mengacu pada koleksi IDs dari konstruksi tertentu, konstruksi induknya, kakek-neneknya, dan seterusnya ke akar pohon konstruksi, sebagai jalan.*

 AWS CDK biasanya menampilkan jalur di template Anda sebagai string. IDs Dari tingkat dipisahkan oleh garis miring, dimulai dari node segera di bawah `App` instance root, yang biasanya tumpukan. Misalnya, jalur dari dua sumber daya bucket Amazon S3 dalam contoh kode sebelumnya adalah `Stack1/MyBucket` dan. `Stack2/MyBucket`

Anda dapat mengakses jalur konstruksi apa pun secara terprogram, seperti yang ditunjukkan pada contoh berikut. Ini mendapatkan jalur `myConstruct` (atau`my_construct`, seperti yang akan ditulis oleh pengembang Python). Karena IDs harus unik dalam ruang lingkup mereka dibuat, jalur mereka selalu unik dalam aplikasi AWS CDK.

**Example**  

```
const path: string = myConstruct.node.path;
```

```
const path = myConstruct.node.path;
```

```
path = my_construct.node.path
```

```
String path = myConstruct.getNode().getPath();
```

```
string path = myConstruct.Node.Path;
```

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

 AWS CloudFormation mengharuskan semua logis IDs dalam template menjadi unik. Karena itu, AWS CDK harus dapat menghasilkan pengidentifikasi unik untuk setiap konstruksi dalam aplikasi. Sumber daya memiliki jalur yang unik secara global (nama semua cakupan dari tumpukan ke sumber daya tertentu). Oleh karena itu, AWS CDK menghasilkan pengidentifikasi unik yang diperlukan dengan menggabungkan elemen jalur dan menambahkan hash 8 digit. (Hash diperlukan untuk membedakan jalur yang berbeda, seperti `A/B/C` dan`A/BC`, yang akan menghasilkan AWS CloudFormation pengidentifikasi yang sama. AWS CloudFormation pengidentifikasi alfanumerik dan tidak dapat berisi garis miring atau karakter pemisah lainnya.) AWS CDK memanggil string ini *ID unik* dari konstruksi.

Secara umum, aplikasi AWS CDK Anda tidak perlu tahu tentang unik IDs. Namun, Anda dapat mengakses ID unik dari konstruksi apa pun secara terprogram, seperti yang ditunjukkan pada contoh berikut.

**Example**  

```
const uid: string = Names.uniqueId(myConstruct);
```

```
const uid = Names.uniqueId(myConstruct);
```

```
uid = Names.unique_id(my_construct)
```

```
String uid = Names.uniqueId(myConstruct);
```

```
string uid = Names.Uniqueid(myConstruct);
```

*Alamat* adalah jenis pengidentifikasi unik lain yang secara unik membedakan sumber daya CDK. Berasal dari hash SHA-1 jalan, itu tidak dapat dibaca manusia. Namun, panjangnya yang konstan dan relatif pendek (selalu 42 karakter heksadesimal) membuatnya berguna dalam situasi di mana ID unik “tradisional” mungkin terlalu panjang. Beberapa konstruksi mungkin menggunakan alamat dalam AWS CloudFormation template yang disintesis, bukan ID unik. Sekali lagi, aplikasi Anda umumnya tidak perlu tahu tentang alamat konstruksinya, tetapi Anda dapat mengambil alamat konstruksi sebagai berikut.

**Example**  

```
const addr: string = myConstruct.node.addr;
```

```
const addr = myConstruct.node.addr;
```

```
addr = my_construct.node.addr
```

```
String addr = myConstruct.getNode().getAddr();
```

```
string addr = myConstruct.Node.Addr;
```

## Logis IDs
<a name="identifiers-logical-ids"></a>

Unik IDs berfungsi sebagai *pengidentifikasi logis* (atau *nama logis*) sumber daya dalam AWS CloudFormation templat yang dihasilkan untuk konstruksi yang mewakili AWS sumber daya.

Misalnya, bucket Amazon S3 pada contoh sebelumnya yang dibuat dalam `Stack2` menghasilkan sumber daya. ` AWS::S3::Bucket` ID logis sumber daya ada `Stack2MyBucket4DD88B4F` di AWS CloudFormation template yang dihasilkan. (Untuk detail tentang cara pengidentifikasi ini dihasilkan, lihat [Unik IDs](#identifiers-unique-ids).)

### Stabilitas ID logis
<a name="identifiers-logical-id-stability"></a>

Hindari mengubah ID logis sumber daya setelah dibuat. AWS CloudFormation mengidentifikasi sumber daya dengan ID logisnya. Oleh karena itu, jika Anda mengubah ID logis sumber daya, AWS CloudFormation membuat sumber daya baru dengan ID logis baru, lalu hapus yang sudah ada. Tergantung pada jenis sumber daya, ini dapat menyebabkan gangguan layanan, kehilangan data, atau keduanya.

# Token dan AWS CDK
<a name="tokens"></a>

Dalam AWS Cloud Development Kit (AWS CDK), *token* adalah placeholder untuk nilai yang tidak diketahui saat mendefinisikan konstruksi atau mensintesis tumpukan. Nilai-nilai ini akan sepenuhnya diselesaikan pada penerapan, ketika infrastruktur Anda yang sebenarnya dibuat. Saat mengembangkan aplikasi AWS CDK, Anda akan bekerja dengan token untuk mengelola nilai-nilai ini di seluruh aplikasi Anda.

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

Berikut ini adalah contoh tumpukan CDK yang mendefinisikan konstruksi untuk bucket Amazon Simple Storage Service (Amazon S3). Karena nama bucket kami belum diketahui, nilai untuk `bucketName` disimpan sebagai token:

**Example**  

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

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

    // Define an S3 bucket
    const myBucket = new s3.Bucket(this, 'myBucket');

    // Store value of the S3 bucket name
    const myBucketName = myBucket.bucketName;

    // Print the current value for the S3 bucket name at synthesis
    console.log("myBucketName: " + myBucketName);
  }
}
```

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

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

    // Define an S3 bucket
    const myBucket = new s3.Bucket(this, 'myBucket');

    // Store value of the S3 bucket name
    const myBucketName = myBucket.bucketName;

    // Print the current value for the S3 bucket name at synthesis
    console.log("myBucketName: " + myBucketName);
  }
}

module.exports = { CdkDemoAppStack }
```

```
from aws_cdk import (
    Stack
)
from constructs import Construct
from aws_cdk import aws_s3 as s3

class CdkDemoAppStack(Stack):

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

        # Define an S3 bucket
        my_bucket = s3.Bucket(self, "myBucket")

        # Store the value of the S3 bucket name
        my_bucket_name = my_bucket.bucket_name

        # Print the current value for the S3 bucket name at synthesis
        print(f"myBucketName: {my_bucket_name}")
```

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.s3.Bucket;

import java.util.Map;

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

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

        // Define an S3 bucket
        Bucket myBucket = Bucket.Builder.create(this, "myBucket")
            .build();

        // Store the token for the bucket name
        String myBucketName = myBucket.getBucketName();

        // Print the token at synthesis
        System.out.println("myBucketName: " + myBucketName);
    }
}
```

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

namespace CdkDemoApp
{
    public class CdkDemoAppStack : Stack
    {
        internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Define an S3 bucket
            var myBucket = new Bucket(this, "myBucket");

            // Store the token for the bucket name
            var myBucketName = myBucket.BucketName;

            // Print the token at synthesis
            System.Console.WriteLine($"myBucketName: {myBucketName}");
        }
    }
}
```

```
package main

import (
	"fmt"

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

type CdkDemoAppStackProps struct {
	awscdk.StackProps
}

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

	// Define an S3 bucket
	myBucket := awss3.NewBucket(stack, jsii.String("myBucket"), &awss3.BucketProps{})

	// Store the token for the bucket name
	myBucketName := myBucket.BucketName()

	// Print the token at synthesis
	fmt.Println("myBucketName: ", *myBucketName)

	return stack
}

// ...
```
Ketika kita menjalankan `cdk synth` untuk mensintesis tumpukan kita, nilai untuk `myBucketName` akan ditampilkan dalam format token. `${Token[TOKEN.<1234>]}` Format token ini adalah hasil dari bagaimana AWS CDK mengkodekan token. Dalam contoh ini, token dikodekan sebagai string:  

```
$ cdk synth --quiet
myBucketName: ${Token[TOKEN.21]}
```
Karena nilai untuk nama bucket kami tidak diketahui saat sintesis, token dirender sebagai`myBucket<unique-hash>`. AWS CloudFormation Template kami menggunakan fungsi `Ref` intrinsik untuk mereferensikan nilainya, yang akan diketahui saat penerapan:  

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

Untuk informasi selengkapnya tentang cara hash unik dihasilkan, lihat [Generated logical IDs di AWS CloudFormation template Anda](configure-synth.md#how-synth-default-logical-ids).

## Melewati token
<a name="tokens-passing"></a>

Token dapat diedarkan seolah-olah itu adalah nilai aktual yang mereka wakili. Berikut ini adalah contoh yang meneruskan token untuk nama bucket kami ke konstruksi untuk fungsi AWS Lambda:

**Example**  

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

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

    // Define an S3 bucket
    const myBucket = new s3.Bucket(this, 'myBucket');

    // ...

    // Define a Lambda function
    const myFunction = new lambda.Function(this, "myFunction", {
      runtime: lambda.Runtime.NODEJS_20_X,
      handler: "index.handler",
      code: lambda.Code.fromInline(`
        exports.handler = async function(event) {
          return {
            statusCode: 200,
            body: JSON.stringify('Hello World!'),
          };
        };
      `),
      functionName: myBucketName + "Function", // Pass token for the S3 bucket name
      environment: {
        BUCKET_NAME: myBucketName, // Pass token for the S3 bucket name
      }
    });
  }
}
```

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

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

    // Define an S3 bucket
    const myBucket = new s3.Bucket(this, 'myBucket');

    // ...

    // Define a Lambda function
    const myFunction = new lambda.Function(this, 'myFunction', {
      runtime: lambda.Runtime.NODEJS_20_X,
      handler: 'index.handler',
      code: lambda.Code.fromInline(`
        exports.handler = async function(event) {
          return {
            statusCode: 200,
            body: JSON.stringify('Hello World!'),
          };
        };
      `),
      functionName: myBucketName + 'Function', // Pass token for the S3 bucket name
      environment: {
        BUCKET_NAME: myBucketName, // Pass token for the S3 bucket name
      }
    });
  }
}

module.exports = { CdkDemoAppStack }
```

```
from aws_cdk import (
    Stack
)
from constructs import Construct
from aws_cdk import aws_s3 as s3
from aws_cdk import aws_lambda as _lambda

class CdkDemoAppStack(Stack):

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

        # Define an S3 bucket
        my_bucket = s3.Bucket(self, "myBucket")

        # ...

        # Define a Lambda function
        my_function = _lambda.Function(self, "myFunction",
            runtime=_lambda.Runtime.NODEJS_20_X,
            handler="index.handler",
            code=_lambda.Code.from_inline("""
                exports.handler = async function(event) {
                  return {
                    statusCode: 200,
                    body: JSON.stringify('Hello World!'),
                  };
                };
            """),
            function_name=f"{my_bucket_name}Function",  # Pass token for the S3 bucket name
            environment={
                "BUCKET_NAME": my_bucket_name  # Pass token for the S3 bucket name
            }
        )
```

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.s3.Bucket;
import software.amazon.awscdk.services.lambda.Code;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.lambda.Runtime;

import java.util.Map;

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

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

        // Define an S3 bucket
        Bucket myBucket = Bucket.Builder.create(this, "myBucket")
            .build();

        // ...

        // Define a Lambda function
        Function myFunction = Function.Builder.create(this, "myFunction")
            .runtime(Runtime.NODEJS_20_X)
            .handler("index.handler")
            .code(Code.fromInline(
                "exports.handler = async function(event) {" +
                "return {" +
                "statusCode: 200," +
                "body: JSON.stringify('Hello World!')," +
                "};" +
                "};"
            ))
            .functionName(myBucketName + "Function") // Pass the token for the s3 bucket to the function construct
            .environment(Map.of("BUCKET_NAME", myBucketName))  // Pass the bucket name as environment variable
            .build();
    }
}
```

```
using Amazon.CDK;
using Constructs;
using Amazon.CDK.AWS.S3;
using Amazon.CDK.AWS.Lambda;
using System;
using System.Collections.Generic;

namespace CdkDemoApp
{
    public class CdkDemoAppStack : Stack
    {
        internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Define an S3 bucket
            var myBucket = new Bucket(this, "myBucket");

            // ...

            // Define a Lambda function
            var myFunction = new Function(this, "myFunction", new FunctionProps
            {
                 Runtime = Runtime.NODEJS_20_X,
                 Handler = "index.handler",
                 Code = Code.FromInline(@"
                     exports.handler = async function(event) {
                       return {
                         statusCode: 200,
                         body: JSON.stringify('Hello World!'),
                       };
                     };
                 "),
                 // Pass the token for the S3 bucket name
                 Environment = new Dictionary<string, string>
                 {
                     { "BUCKET_NAME", myBucketName }
                 },
                 FunctionName = $"{myBucketName}Function" // Pass the token for the s3 bucket to the function construct
            });
        }
    }
}
```

```
package main

import (
	"fmt"

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

type CdkDemoAppStackProps struct {
	awscdk.StackProps
}

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

	// Define an S3 bucket
	myBucket := awss3.NewBucket(stack, jsii.String("myBucket"), &awss3.BucketProps{})

	// ...

	// Define a Lambda function
	myFunction := awslambda.NewFunction(stack, jsii.String("myFunction"), &awslambda.FunctionProps{
		Runtime: awslambda.Runtime_NODEJS_20_X(),
		Handler: jsii.String("index.handler"),
		Code: awslambda.Code_FromInline(jsii.String(`
			exports.handler = async function(event) {
				return {
					statusCode: 200,
					body: JSON.stringify('Hello World!'),
				};
			};
		`)),
		FunctionName: jsii.String(fmt.Sprintf("%sFunction", *myBucketName)), // Pass the token for the S3 bucket to the function name
		Environment: &map[string]*string{
			"BUCKET_NAME": myBucketName,
		},
	})

	return stack
}
// ...
```
Saat kita mensintesis template kita, fungsi `Ref` dan `Fn::Join` intrinsik digunakan untuk menentukan nilai, yang akan diketahui saat penerapan:  

```
Resources:
  myBucket<5AF9C99B>:
    Type: AWS::S3::Bucket
    # ...
  myFunction<884E1557>:
    Type: AWS::Lambda::Function
    Properties:
      # ...
      Environment:
        Variables:
          BUCKET_NAME:
            Ref: myBucket<5AF9C99B>
      FunctionName:
        Fn::Join:
          - ""
          - - Ref: myBucket<5AF9C99B>
            - Function
      # ...
```

## Cara kerja pengkodean token
<a name="tokens-work"></a>

Token adalah objek yang mengimplementasikan [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.IResolvable.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.IResolvable.html)antarmuka, yang berisi satu `resolve` metode. Selama sintesis, AWS CDK memanggil metode ini untuk menghasilkan nilai akhir untuk token di CloudFormation template Anda.

**catatan**  
Anda jarang akan bekerja secara langsung dengan `IResolvable` antarmuka. Anda kemungkinan besar hanya akan melihat versi token yang disandikan string.

### Jenis pengkodean token
<a name="tokens-work-types"></a>

Token berpartisipasi dalam proses sintesis untuk menghasilkan nilai arbitrer dari jenis apa pun. Fungsi lain biasanya hanya menerima argumen tipe dasar, seperti `string` atau`number`. Untuk menggunakan token dalam kasus ini, Anda dapat menyandikannya menjadi salah satu dari tiga jenis dengan menggunakan metode statis pada [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html)kelas.
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrstringvalue-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrstringvalue-options)untuk menghasilkan pengkodean string (atau memanggil `.toString()` objek token).
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrlistvalue-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrlistvalue-options)untuk menghasilkan pengkodean daftar.
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrnumbervalue](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-aswbrnumbervalue)untuk menghasilkan pengkodean numerik.

Ini mengambil nilai arbitrer, yang bisa berupa`IResolvable`, dan menyandikannya menjadi nilai primitif dari tipe yang ditunjukkan.

**penting**  
Karena salah satu tipe sebelumnya berpotensi menjadi token yang dikodekan, berhati-hatilah saat Anda mengurai atau mencoba membaca isinya. Misalnya, jika Anda mencoba mengurai string untuk mengekstrak nilai darinya, dan string adalah token yang dikodekan, penguraian Anda gagal. Demikian pula, jika Anda mencoba menanyakan panjang array atau melakukan operasi matematika dengan angka, Anda harus terlebih dahulu memverifikasi bahwa itu bukan token yang dikodekan.

## Cara memeriksa token di aplikasi Anda
<a name="tokens-check"></a>

Untuk memeriksa apakah suatu nilai memiliki token yang belum terselesaikan di dalamnya, panggil metode [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-iswbrunresolvedobj](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Token.html#static-iswbrunresolvedobj)(Python`is_unresolved`:). Berikut ini adalah contoh yang memeriksa apakah nilai untuk nama bucket Amazon S3 kami adalah token. Jika bukan token, kami kemudian memvalidasi panjang nama bucket:

**Example**  

```
// ...

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

    // Define an S3 bucket
    const myBucket = new s3.Bucket(this, 'myBucket');
    // ...

    // Check if bucket name is a token. If not, check if length is less than 10 characters
    if (cdk.Token.isUnresolved(myBucketName)) {
      console.log("Token identified.");
    } else if (!cdk.Token.isUnresolved(myBucketName) && myBucketName.length > 10) {
      throw new Error('Maximum length for name is 10 characters.');
    };

    // ...
  }
}
```

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

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

    // Define an S3 bucket
    const myBucket = new s3.Bucket(this, 'myBucket');

    // ...

    // Check if bucket name is a token. If not, check if length is less than 10 characters
    if (Token.isUnresolved(myBucketName)) {
      console.log("Token identified.");
    } else if (!Token.isUnresolved(myBucketName) && myBucketName.length > 10) {
      throw new Error('Maximum length for name is 10 characters.');
    };

    // ...
  }
}
```

```
from aws_cdk import (
    Stack,
    Token
)
# ...

class CdkDemoAppStack(Stack):

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

        # Define an S3 bucket
        my_bucket = s3.Bucket(self, "myBucket")

        # ...

        # Check if bucket name is a token. If not, check if length is less than 10 characters
        if Token.is_unresolved(my_bucket_name):
            print("Token identified.")
        elif not Token.is_unresolved(my_bucket_name) and len(my_bucket_name) < 10:
            raise ValueError("Maximum length for name is 10 characters.")

        # ...
```

```
// ...
import software.amazon.awscdk.Token;
import software.amazon.awscdk.services.s3.Bucket;
// ...

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

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

        // Define an S3 bucket
        Bucket myBucket = Bucket.Builder.create(this, "myBucket")
            .build();

        // ...

        // Get the bucket name
        String myBucketName = myBucket.getBucketName();

        // Check if the bucket name is a token. If not, check if length is less than 10 characters
        if (Token.isUnresolved(myBucketName)) {
            System.out.println("Token identified.");
        } else if (!Token.isUnresolved(myBucketName) && myBucketName.length() > 10) {
            throw new IllegalArgumentException("Maximum length for name is 10 characters.");
        }

        // ...
      }
    }
  }
```

```
using Amazon.CDK;
using Constructs;
using Amazon.CDK.AWS.S3;
using Amazon.CDK.AWS.Lambda;
using System;
using System.Collections.Generic;

namespace CdkDemoApp
{
    public class CdkDemoAppStack : Stack
    {
        internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Define an S3 bucket
            var myBucket = new Bucket(this, "myBucket");

            // ...

            // Get the bucket name
            var myBucketName = myBucket.BucketName;

            // Check if bucket name is a token. If not, check if length is less than 10 characters
            if (Token.IsUnresolved(myBucketName))
            {
                System.Console.WriteLine("Token identified.");
            }
            else if (!Token.IsUnresolved(myBucketName) && myBucketName.Length > 10)
            {
                throw new System.Exception("Maximum length for name is 10 characters.");
            }

            // ...
        }
    }
}
```

```
// ...

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

	// Define an S3 bucket
	myBucket := awss3.NewBucket(stack, jsii.String("myBucket"), &awss3.BucketProps{})

	// ...

	// Check if the bucket name is unresolved (a token)
	if tokenUnresolved := awscdk.Token_IsUnresolved(myBucketName); tokenUnresolved != nil && *tokenUnresolved {
		fmt.Println("Token identified.")
	} else if tokenUnresolved != nil && !*tokenUnresolved && len(*myBucketName) > 10 {
		panic("Maximum length for name is 10 characters.")
	}

	// ...
}
```

Ketika kita menjalankan `cdk synth``myBucketName`, diidentifikasi sebagai token:

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

**catatan**  
Anda dapat menggunakan pengkodean token untuk keluar dari sistem tipe. Misalnya, Anda dapat mengkodekan string token yang menghasilkan nilai angka pada waktu sintesis. Jika Anda menggunakan fungsi-fungsi ini, Anda bertanggung jawab untuk memastikan bahwa template Anda menyelesaikan ke status yang dapat digunakan setelah sintesis.

## Bekerja dengan token yang disandikan string
<a name="tokens-string"></a>

Token yang disandikan string terlihat seperti berikut ini.

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

Mereka dapat diteruskan seperti string biasa, dan dapat digabungkan, seperti yang ditunjukkan pada contoh berikut.

**Example**  

```
const functionName = bucket.bucketName + 'Function';
```

```
const functionName = bucket.bucketName + 'Function';
```

```
function_name = bucket.bucket_name + "Function"
```

```
String functionName = bucket.getBucketName().concat("Function");
```

```
string functionName = bucket.BucketName + "Function";
```

```
functionName := *bucket.BucketName() + "Function"
```

Anda juga dapat menggunakan interpolasi string, jika bahasa Anda mendukungnya, seperti yang ditunjukkan pada contoh berikut.

**Example**  

```
const functionName = `${bucket.bucketName}Function`;
```

```
const functionName = `${bucket.bucketName}Function`;
```

```
function_name = f"{bucket.bucket_name}Function"
```

```
String functionName = String.format("%sFunction". bucket.getBucketName());
```

```
string functionName = $"${bucket.bucketName}Function";
```
Gunakan `fmt.Sprintf` untuk fungsionalitas serupa:  

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

Hindari memanipulasi string dengan cara lain. Misalnya, mengambil substring string kemungkinan akan merusak token string.

## Bekerja dengan token yang dikodekan daftar
<a name="tokens-list"></a>

Token yang dikodekan daftar terlihat seperti berikut:

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

Satu-satunya hal yang aman untuk dilakukan dengan daftar ini adalah meneruskannya langsung ke konstruksi lain. Token dalam bentuk daftar string tidak dapat digabungkan, juga elemen tidak dapat diambil dari token. Satu-satunya cara aman untuk memanipulasi mereka adalah dengan menggunakan fungsi AWS CloudFormation intrinsik seperti. [https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-select.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-select.html)

## Bekerja dengan token yang dikodekan angka
<a name="tokens-number"></a>

Token yang dikodekan angka adalah sekumpulan angka floating-point negatif kecil yang terlihat seperti berikut ini.

```
-1.8881545897087626e+289
```

Seperti halnya token daftar, Anda tidak dapat mengubah nilai angka, karena hal itu kemungkinan akan merusak token angka.

Berikut ini adalah contoh konstruksi yang berisi token yang dikodekan sebagai angka:

**Example**  

```
import { Stack, Duration, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as rds from 'aws-cdk-lib/aws-rds';
import * as ec2 from 'aws-cdk-lib/aws-ec2';

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

    // Define a new VPC
    const vpc = new ec2.Vpc(this, 'MyVpc', {
      maxAzs: 3,  // Maximum number of availability zones to use
    });

    // Define an RDS database cluster
    const dbCluster = new rds.DatabaseCluster(this, 'MyRDSCluster', {
      engine: rds.DatabaseClusterEngine.AURORA,
      instanceProps: {
        vpc,
      },
    });

    // Get the port token (this is a token encoded as a number)
    const portToken = dbCluster.clusterEndpoint.port;

    // Print the value for our token at synthesis
    console.log("portToken: " + portToken);
  }
}
```

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

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

    // Define a new VPC
    const vpc = new ec2.Vpc(this, 'MyVpc', {
      maxAzs: 3,  // Maximum number of availability zones to use
    });

    // Define an RDS database cluster
    const dbCluster = new rds.DatabaseCluster(this, 'MyRDSCluster', {
      engine: rds.DatabaseClusterEngine.AURORA,
      instanceProps: {
        vpc,
      },
    });

    // Get the port token (this is a token encoded as a number)
    const portToken = dbCluster.clusterEndpoint.port;

    // Print the value for our token at synthesis
    console.log("portToken: " + portToken);
  }
}

module.exports = { CdkDemoAppStack }
```

```
from aws_cdk import (
    Duration,
    Stack,
)
from aws_cdk import aws_rds as rds
from aws_cdk import aws_ec2 as ec2
from constructs import Construct

class CdkDemoAppStack(Stack):

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

        # Define a new VPC
        vpc = ec2.Vpc(self, 'MyVpc',
            max_azs=3  # Maximum number of availability zones to use
        )

        # Define an RDS database cluster
        db_cluster = rds.DatabaseCluster(self, 'MyRDSCluster',
            engine=rds.DatabaseClusterEngine.AURORA,
            instance_props=rds.InstanceProps(
                vpc=vpc
            )
        )

        # Get the port token (this is a token encoded as a number)
        port_token = db_cluster.cluster_endpoint.port

        # Print the value for our token at synthesis
        print(f"portToken: {port_token}")
```

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.ec2.Vpc;
import software.amazon.awscdk.services.rds.DatabaseCluster;
import software.amazon.awscdk.services.rds.DatabaseClusterEngine;
import software.amazon.awscdk.services.rds.InstanceProps;

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

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

        // Define a new VPC
        Vpc vpc = Vpc.Builder.create(this, "MyVpc")
            .maxAzs(3) // Maximum number of availability zones to use
            .build();

        // Define an RDS database cluster
        DatabaseCluster dbCluster = DatabaseCluster.Builder.create(this, "MyRDSCluster")
            .engine(DatabaseClusterEngine.AURORA)
            .instanceProps(InstanceProps.builder()
                .vpc(vpc)
                .build())
            .build();

        // Get the port token (this is a token encoded as a number)
        Number portToken = dbCluster.getClusterEndpoint().getPort();

        // Print the value for our token at synthesis
        System.out.println("portToken: " + portToken);
    }
}
```

```
using Amazon.CDK;
using Constructs;
using Amazon.CDK.AWS.EC2;
using Amazon.CDK.AWS.RDS;
using System;
using System.Collections.Generic;

namespace CdkDemoApp
{
    public class CdkDemoAppStack : Stack
    {
        internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Define a new VPC
            var vpc = new Vpc(this, "MyVpc", new VpcProps
            {
                MaxAzs = 3  // Maximum number of availability zones to use
            });

            // Define an RDS database cluster
            var dbCluster = new DatabaseCluster(this, "MyRDSCluster", new DatabaseClusterProps
            {
                Engine = DatabaseClusterEngine.AURORA,  // Remove parentheses
                InstanceProps = new Amazon.CDK.AWS.RDS.InstanceProps // Specify RDS InstanceProps
                {
                    Vpc = vpc
                }
            });

            // Get the port token (this is a token encoded as a number)
            var portToken = dbCluster.ClusterEndpoint.Port;

            // Print the value for our token at synthesis
            System.Console.WriteLine($"portToken: {portToken}");
        }
    }
}
```

```
package main

import (
	"fmt"

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

type CdkDemoAppStackProps struct {
	awscdk.StackProps
}

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

	// Define a new VPC
	vpc := awsec2.NewVpc(stack, jsii.String("MyVpc"), &awsec2.VpcProps{
		MaxAzs: jsii.Number(3), // Maximum number of availability zones to use
	})

	// Define an RDS database cluster
	dbCluster := awsrds.NewDatabaseCluster(stack, jsii.String("MyRDSCluster"), &awsrds.DatabaseClusterProps{
		Engine: awsrds.DatabaseClusterEngine_AURORA(),
		InstanceProps: &awsrds.InstanceProps{
			Vpc: vpc,
		},
	})

	// Get the port token (this is a token encoded as a number)
	portToken := dbCluster.ClusterEndpoint().Port()

	// Print the value for our token at synthesis
	fmt.Println("portToken: ", portToken)

	return stack
}

// ...
```

Saat kita menjalankan`cdk synth`, nilai untuk ditampilkan sebagai token yang `portToken` dikodekan angka:

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

### Lulus token yang dikodekan nomor
<a name="tokens-number-pass"></a>

Saat Anda meneruskan token yang dikodekan angka ke konstruksi lain, mungkin masuk akal untuk mengonversinya menjadi string terlebih dahulu. Misalnya, jika Anda ingin menggunakan nilai string yang dikodekan angka sebagai bagian dari string gabungan, mengonversinya membantu keterbacaan.

Dalam contoh berikut, `portToken` adalah token yang dikodekan angka yang ingin kita teruskan ke fungsi Lambda kita sebagai bagian dari: `connectionString`

**Example**  

```
import { Stack, Duration, CfnOutput, StackProps } from 'aws-cdk-lib';
// ...
import * as lambda from 'aws-cdk-lib/aws-lambda';

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

    // Define a new VPC
    // ...

    // Define an RDS database cluster
    // ...

    // Get the port token (this is a token encoded as a number)
    const portToken = dbCluster.clusterEndpoint.port;

    // ...

    // Example connection string with the port token as a number
    const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portToken}/mydatabase`;

    // Use the connection string as an environment variable in a Lambda function
    const myFunction = new lambda.Function(this, 'MyLambdaFunction', {
      runtime: lambda.Runtime.NODEJS_20_X,
      handler: 'index.handler',
      code: lambda.Code.fromInline(`
        exports.handler = async function(event) {
          return {
            statusCode: 200,
            body: JSON.stringify('Hello World!'),
          };
        };
      `),
      environment: {
        DATABASE_CONNECTION_STRING: connectionString,  // Using the port token as part of the string
      },
    });

    // Output the value of our connection string at synthesis
    console.log("connectionString: " + connectionString);

    // Output the connection string
    new CfnOutput(this, 'ConnectionString', {
      value: connectionString,
    });
  }
}
```

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

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

    // Define a new VPC
    // ...

    // Define an RDS database cluster
    // ...

    // Get the port token (this is a token encoded as a number)
    const portToken = dbCluster.clusterEndpoint.port;

    // ...

    // Example connection string with the port token as a number
    const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portToken}/mydatabase`;

    // Use the connection string as an environment variable in a Lambda function
    const myFunction = new lambda.Function(this, 'MyLambdaFunction', {
      runtime: lambda.Runtime.NODEJS_20_X,
      handler: 'index.handler',
      code: lambda.Code.fromInline(`
        exports.handler = async function(event) {
          return {
            statusCode: 200,
            body: JSON.stringify('Hello World!'),
          };
        };
      `),
      environment: {
        DATABASE_CONNECTION_STRING: connectionString,  // Using the port token as part of the string
      },
    });

    // Output the value of our connection string at synthesis
    console.log("connectionString: " + connectionString);

    // Output the connection string
    new CfnOutput(this, 'ConnectionString', {
      value: connectionString,
    });
  }
}

module.exports = { CdkDemoAppStack }
```

```
from aws_cdk import (
    Duration,
    Stack,
    CfnOutput,
)
from aws_cdk import aws_lambda as _lambda
# ...

class CdkDemoAppStack(Stack):

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

        # Define a new VPC
        # ...

        # Define an RDS database cluster
        # ...

        # Get the port token (this is a token encoded as a number)
        port_token = db_cluster.cluster_endpoint.port

        # ...

        # Example connection string with the port token as a number
        connection_string = f"jdbc:mysql://mydb.cluster.amazonaws.com:{port_token}/mydatabase"

        # Use the connection string as an environment variable in a Lambda function
        my_function = _lambda.Function(self, 'MyLambdaFunction',
            runtime=_lambda.Runtime.NODEJS_20_X,
            handler='index.handler',
            code=_lambda.Code.from_inline("""
                exports.handler = async function(event) {
                    return {
                        statusCode: 200,
                        body: JSON.stringify('Hello World!'),
                    };
                };
            """),
            environment={
                'DATABASE_CONNECTION_STRING': connection_string  # Using the port token as part of the string
            }
        )

        # Output the value of our connection string at synthesis
        print(f"connectionString: {connection_string}")

        # Output the connection string
        CfnOutput(self, 'ConnectionString',
            value=connection_string
        )
```

```
// ...
import software.amazon.awscdk.CfnOutput;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.lambda.Runtime;
import software.amazon.awscdk.services.lambda.Code;

import java.util.Map;

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

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

        // Define a new VPC
        // ...

        // Define an RDS database cluster
        // ...

        // Get the port token (this is a token encoded as a number)
        Number portToken = dbCluster.getClusterEndpoint().getPort();

        // ...

        // Example connection string with the port token as a number
        String connectionString = "jdbc:mysql://mydb.cluster.amazonaws.com:" + portToken + "/mydatabase";

        // Use the connection string as an environment variable in a Lambda function
        Function myFunction = Function.Builder.create(this, "MyLambdaFunction")
            .runtime(Runtime.NODEJS_20_X)
            .handler("index.handler")
            .code(Code.fromInline(
                "exports.handler = async function(event) {\n" +
                "  return {\n" +
                "    statusCode: 200,\n" +
                "    body: JSON.stringify('Hello World!'),\n" +
                "  };\n" +
                "};"))
            .environment(Map.of(
                "DATABASE_CONNECTION_STRING", connectionString // Using the port token as part of the string
            ))
            .build();

        // Output the value of our connection string at synthesis
        System.out.println("connectionString: " + connectionString);

        // Output the connection string
        CfnOutput.Builder.create(this, "ConnectionString")
            .value(connectionString)
            .build();
    }
}
```

```
// ...
using Amazon.CDK.AWS.Lambda;
using Amazon.CDK.AWS.RDS;
using Amazon.CDK;
using Constructs;
using System;
using System.Collections.Generic;

namespace CdkDemoApp
{
    public class CdkDemoAppStack : Stack
    {
        internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Define a new VPC
            // ...

            // Define an RDS database cluster
            var dbCluster = new DatabaseCluster(this, "MyRDSCluster", new DatabaseClusterProps
            {
                // ... properties would go here
            });

            // Get the port token (this is a token encoded as a number)
            var portToken = dbCluster.ClusterEndpoint.Port;

            // ...

            // Example connection string with the port token as a number
            var connectionString = $"jdbc:mysql://mydb.cluster.amazonaws.com:{portToken}/mydatabase";

            // Use the connection string as an environment variable in a Lambda function
            var myFunction = new Function(this, "MyLambdaFunction", new FunctionProps
            {
                Runtime = Runtime.NODEJS_20_X,
                Handler = "index.handler",
                Code = Code.FromInline(@"
                    exports.handler = async function(event) {
                        return {
                            statusCode: 200,
                            body: JSON.stringify('Hello World!'),
                        };
                    };
                "),
                Environment = new Dictionary<string, string>
                {
                    { "DATABASE_CONNECTION_STRING", connectionString }  // Using the port token as part of the string
                }
            });

            // Output the value of our connection string at synthesis
            Console.WriteLine($"connectionString: {connectionString}");

            // Output the connection string
            new CfnOutput(this, "ConnectionString", new CfnOutputProps
            {
                Value = connectionString
            });
        }
    }
}
```

```
// ...
	"github.com/aws/aws-cdk-go/awscdk/v2/awslambda"
)

type CdkDemoAppStackProps struct {
	awscdk.StackProps
}

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

	// Define a new VPC
	// ...

	// Define an RDS database cluster
	// ...

	// Get the port token (this is a token encoded as a number)
	portToken := dbCluster.ClusterEndpoint().Port()

	// ...

	// Example connection string with the port token as a number
	 connectionString := fmt.Sprintf("jdbc:mysql://mydb.cluster.amazonaws.com:%s/mydatabase", portToken)

	// Use the connection string as an environment variable in a Lambda function
	myFunction := awslambda.NewFunction(stack, jsii.String("MyLambdaFunction"), &awslambda.FunctionProps{
		Runtime: awslambda.Runtime_NODEJS_20_X(),
		Handler: jsii.String("index.handler"),
		Code: awslambda.Code_FromInline(jsii.String(`
			exports.handler = async function(event) {
				return {
					statusCode: 200,
					body: JSON.stringify('Hello World!'),
				};
			};
		`)),
		Environment: &map[string]*string{
			"DATABASE_CONNECTION_STRING": jsii.String(connectionString), // Using the port token as part of the string
		},
	})

	// Output the value of our connection string at synthesis
	fmt.Println("connectionString: ", connectionString)

	// Output the connection string
	awscdk.NewCfnOutput(stack, jsii.String("ConnectionString"), &awscdk.CfnOutputProps{
		Value: jsii.String(connectionString),
	})

	return stack
}

// ...
```

Jika kita meneruskan nilai ini`connectionString`, nilai output saat kita menjalankan `cdk synth` mungkin membingungkan karena string yang dikodekan angka:

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

Untuk mengonversi token yang dikodekan angka menjadi string, gunakan. [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tokenization.html#static-stringifywbrnumberx](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tokenization.html#static-stringifywbrnumberx) Dalam contoh berikut, kita mengubah token yang dikodekan angka menjadi string sebelum mendefinisikan string koneksi kita:

**Example**  

```
import { Stack, Duration, Tokenization, CfnOutput, StackProps } from 'aws-cdk-lib';
// ...

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

    // Define a new VPC
    // ...

    // Define an RDS database cluster
    // ...

    // Get the port token (this is a token encoded as a number)
    const portToken = dbCluster.clusterEndpoint.port;

    // ...

    // Convert the encoded number to an encoded string for use in the connection string
    const portAsString = Tokenization.stringifyNumber(portToken);

    // Example connection string with the port token as a string
    const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portAsString}/mydatabase`;

    // Use the connection string as an environment variable in a Lambda function
    const myFunction = new lambda.Function(this, 'MyLambdaFunction', {
      // ...
      environment: {
        DATABASE_CONNECTION_STRING: connectionString,  // Using the port token as part of the string
      },
    });

    // Output the value of our connection string at synthesis
    console.log("connectionString: " + connectionString);

    // Output the connection string
    new CfnOutput(this, 'ConnectionString', {
      value: connectionString,
    });
  }
}
```

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

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

    // Define a new VPC
    // ...

    // Define an RDS database cluster
    // ...

    // Get the port token (this is a token encoded as a number)
    const portToken = dbCluster.clusterEndpoint.port;

    // ...

    // Convert the encoded number to an encoded string for use in the connection string
    const portAsString = Tokenization.stringifyNumber(portToken);

    // Example connection string with the port token as a string
    const connectionString = `jdbc:mysql://mydb.cluster.amazonaws.com:${portAsString}/mydatabase`;

    // Use the connection string as an environment variable in a Lambda function
    const myFunction = new lambda.Function(this, 'MyLambdaFunction', {
      // ...
      environment: {
        DATABASE_CONNECTION_STRING: connectionString,  // Using the port token as part of the string
      },
    });

    // Output the value of our connection string at synthesis
    console.log("connectionString: " + connectionString);

    // Output the connection string
    new CfnOutput(this, 'ConnectionString', {
      value: connectionString,
    });
  }
}

module.exports = { CdkDemoAppStack }
```

```
from aws_cdk import (
    Duration,
    Stack,
    Tokenization,
    CfnOutput,
)
# ...

class CdkDemoAppStack(Stack):

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

        # Define a new VPC
        # ...

        # Define an RDS database cluster
        # ...

        # Get the port token (this is a token encoded as a number)
        port_token = db_cluster.cluster_endpoint.port

        # Convert the encoded number to an encoded string for use in the connection string
        port_as_string = Tokenization.stringify_number(port_token)

        # Example connection string with the port token as a string
        connection_string = f"jdbc:mysql://mydb.cluster.amazonaws.com:{port_as_string}/mydatabase"

        # Use the connection string as an environment variable in a Lambda function
        my_function = _lambda.Function(self, 'MyLambdaFunction',
            # ...
            environment={
                'DATABASE_CONNECTION_STRING': connection_string  # Using the port token as part of the string
            }
        )

        # Output the value of our connection string at synthesis
        print(f"connectionString: {connection_string}")

        # Output the connection string
        CfnOutput(self, 'ConnectionString',
            value=connection_string
        )
```

```
// ...
import software.amazon.awscdk.Tokenization;

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

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

        // Define a new VPC
        // ...

        // Define an RDS database cluster
        // ...

        // Get the port token (this is a token encoded as a number)
        Number portToken = dbCluster.getClusterEndpoint().getPort();

        // ...

        // Convert the encoded number to an encoded string for use in the connection string
        String portAsString = Tokenization.stringifyNumber(portToken);

        // Example connection string with the port token as a string
        String connectionString = "jdbc:mysql://mydb.cluster.amazonaws.com:" + portAsString + "/mydatabase";

        // Use the connection string as an environment variable in a Lambda function
        Function myFunction = Function.Builder.create(this, "MyLambdaFunction")
            // ...
            .environment(Map.of(
                "DATABASE_CONNECTION_STRING", connectionString // Using the port token as part of the string
            ))
            .build();

        // Output the value of our connection string at synthesis
        System.out.println("connectionString: " + connectionString);

        // Output the connection string
        CfnOutput.Builder.create(this, "ConnectionString")
            .value(connectionString)
            .build();
    }
}
```

```
// ...

namespace CdkDemoApp
{
    public class CdkDemoAppStack : Stack
    {
        internal CdkDemoAppStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Define a new VPC
            // ...

            // Define an RDS database cluster
            // ...

            // Get the port token (this is a token encoded as a number)
            var portToken = dbCluster.ClusterEndpoint.Port;

            // ...

            // Convert the encoded number to an encoded string for use in the connection string
            var portAsString = Tokenization.StringifyNumber(portToken);

            // Example connection string with the port token as a string
            var connectionString = $"jdbc:mysql://mydb.cluster.amazonaws.com:{portAsString}/mydatabase";

            // Use the connection string as an environment variable in a Lambda function
            var myFunction = new Function(this, "MyLambdaFunction", new FunctionProps
            {
                // ...
                Environment = new Dictionary<string, string>
                {
                    { "DATABASE_CONNECTION_STRING", connectionString }  // Using the port token as part of the string
                }
            });

            // Output the value of our connection string at synthesis
            Console.WriteLine($"connectionString: {connectionString}");

            // Output the connection string
            new CfnOutput(this, "ConnectionString", new CfnOutputProps
            {
                Value = connectionString
            });
        }
    }
}
```

```
// ...

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

	// Define a new VPC
	// ...

	// Define an RDS database cluster
	// ...

	// Get the port token (this is a token encoded as a number)
	portToken := dbCluster.ClusterEndpoint().Port()

	// ...

	// Convert the encoded number to an encoded string for use in the connection string
	portAsString := awscdk.Tokenization_StringifyNumber(portToken)

	// Example connection string with the port token as a string
	connectionString := fmt.Sprintf("jdbc:mysql://mydb.cluster.amazonaws.com:%s/mydatabase", portAsString)

	// Use the connection string as an environment variable in a Lambda function
	myFunction := awslambda.NewFunction(stack, jsii.String("MyLambdaFunction"), &awslambda.FunctionProps{
		// ...
		Environment: &map[string]*string{
			"DATABASE_CONNECTION_STRING": jsii.String(connectionString), // Using the port token as part of the string
		},
	})

	// Output the value of our connection string at synthesis
	fmt.Println("connectionString: ", connectionString)

	// Output the connection string
	awscdk.NewCfnOutput(stack, jsii.String("ConnectionString"), &awscdk.CfnOutputProps{
		Value: jsii.String(connectionString),
	})

	fmt.Println(myFunction)

	return stack
}

// ...
```

Saat kami menjalankan`cdk synth`, nilai untuk string koneksi kami direpresentasikan dalam format yang lebih bersih dan lebih jelas:

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

## Nilai malas
<a name="tokens-lazy"></a>

Selain mewakili nilai deploy-time, seperti AWS CloudFormation [parameter](parameters.md), token juga biasa digunakan untuk mewakili nilai malas waktu sintesis. Ini adalah nilai yang nilai akhirnya akan ditentukan sebelum sintesis selesai, tetapi tidak pada titik di mana nilai dibangun. Gunakan token untuk meneruskan string literal atau nilai angka ke konstruksi lain, sedangkan nilai aktual pada waktu sintesis mungkin bergantung pada beberapa perhitungan yang belum terjadi.

Anda dapat membuat token yang mewakili nilai malas synth-time menggunakan metode statis pada `Lazy` kelas, seperti dan. [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Lazy.html#static-stringproducer-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Lazy.html#static-stringproducer-options) Metode ini menerima objek yang `produce` propertinya adalah fungsi yang menerima argumen konteks dan mengembalikan nilai akhir ketika dipanggil.

Contoh berikut membuat grup Auto Scaling yang kapasitasnya ditentukan setelah pembuatannya.

**Example**  

```
let actualValue: number;

new AutoScalingGroup(this, 'Group', {
  desiredCapacity: Lazy.numberValue({
    produce(context) {
      return actualValue;
    }
  })
});

// At some later point
actualValue = 10;
```

```
let actualValue;

new AutoScalingGroup(this, 'Group', {
  desiredCapacity: Lazy.numberValue({
    produce(context) {
      return (actualValue);
    }
  })
});

// At some later point
actualValue = 10;
```

```
class Producer:
    def __init__(self, func):
        self.produce = func

actual_value = None

AutoScalingGroup(self, "Group",
    desired_capacity=Lazy.number_value(Producer(lambda context: actual_value))
)

# At some later point
actual_value = 10
```

```
double actualValue = 0;

class ProduceActualValue implements INumberProducer {

    @Override
    public Number produce(IResolveContext context) {
        return actualValue;
    }
}

AutoScalingGroup.Builder.create(this, "Group")
    .desiredCapacity(Lazy.numberValue(new ProduceActualValue())).build();

// At some later point
actualValue = 10;
```

```
public class NumberProducer : INumberProducer
{
    Func<Double> function;

    public NumberProducer(Func<Double> function)
    {
        this.function = function;
    }

    public Double Produce(IResolveContext context)
    {
        return function();
    }
}

double actualValue = 0;

new AutoScalingGroup(this, "Group", new AutoScalingGroupProps
{
    DesiredCapacity = Lazy.NumberValue(new NumberProducer(() => actualValue))
});

// At some later point
actualValue = 10;
```

## Konversi ke JSON
<a name="tokens-json"></a>

Terkadang Anda ingin menghasilkan string JSON dari data arbitrer, dan Anda mungkin tidak tahu apakah data tersebut berisi token. Untuk mengkodekan struktur data dengan benar JSON, terlepas dari apakah itu berisi token, gunakan metode ini [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#towbrjsonwbrstringobj-space](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#towbrjsonwbrstringobj-space), seperti yang ditunjukkan pada contoh berikut.

**Example**  

```
const stack = Stack.of(this);
const str = stack.toJsonString({
  value: bucket.bucketName
});
```

```
const stack = Stack.of(this);
const str = stack.toJsonString({
  value: bucket.bucketName
});
```

```
stack = Stack.of(self)
string = stack.to_json_string(dict(value=bucket.bucket_name))
```

```
Stack stack = Stack.of(this);
String stringVal = stack.toJsonString(java.util.Map.of(    // Map.of requires Java 9+
        put("value", bucket.getBucketName())));
```

```
var stack = Stack.Of(this);
var stringVal = stack.ToJsonString(new Dictionary<string, string>
{
    ["value"] = bucket.BucketName
});
```

# Parameter dan AWS CDK
<a name="parameters"></a>

 *Parameter* adalah nilai kustom yang disediakan pada waktu penerapan. [Parameter](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html) adalah fitur dari AWS CloudFormation. Karena AWS Cloud Development Kit (AWS CDK) mensintesis AWS CloudFormation template, ia juga menawarkan dukungan untuk parameter waktu penerapan.

## Tentang parameter
<a name="parameters-about"></a>

Menggunakan AWS CDK, Anda dapat menentukan parameter, yang kemudian dapat digunakan dalam properti konstruksi yang Anda buat. Anda juga dapat menerapkan tumpukan yang berisi parameter.

Saat menerapkan AWS CloudFormation template menggunakan AWS CDK CLI, Anda memberikan nilai parameter pada baris perintah. Jika Anda menerapkan template melalui AWS CloudFormation konsol, Anda akan diminta untuk nilai parameter.

Secara umum, kami merekomendasikan untuk tidak menggunakan AWS CloudFormation parameter dengan AWS CDK. Cara biasa untuk meneruskan nilai ke aplikasi AWS CDK adalah [nilai konteks](context.md) dan variabel lingkungan. Karena tidak tersedia pada waktu sintesis, nilai parameter tidak dapat dengan mudah digunakan untuk kontrol aliran dan tujuan lain di aplikasi CDK Anda.

**catatan**  
Untuk melakukan aliran kontrol dengan parameter, Anda dapat menggunakan [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnCondition.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.CfnCondition.html)konstruksi, meskipun ini canggung dibandingkan dengan pernyataan asli. `if`

Menggunakan parameter mengharuskan Anda untuk memperhatikan bagaimana kode yang Anda tulis berperilaku pada waktu penerapan, dan juga pada waktu sintesis. Hal ini membuat lebih sulit untuk memahami dan bernalar tentang aplikasi AWS CDK Anda, dalam banyak kasus untuk sedikit manfaat.

Secara umum, lebih baik meminta aplikasi CDK Anda menerima informasi yang diperlukan dengan cara yang terdefinisi dengan baik dan menggunakannya langsung untuk mendeklarasikan konstruksi di aplikasi CDK Anda. AWS CloudFormation Template yang AWS dihasilkan CDK yang ideal adalah konkret, tanpa nilai yang tersisa untuk ditentukan pada waktu penerapan.

Namun, ada kasus penggunaan yang AWS CloudFormation parameternya cocok secara unik. Jika Anda memiliki tim terpisah yang mendefinisikan dan menerapkan infrastruktur, misalnya, Anda dapat menggunakan parameter untuk membuat templat yang dihasilkan lebih berguna secara luas. Juga, karena AWS CDK mendukung AWS CloudFormation parameter, Anda dapat menggunakan AWS CDK dengan AWS layanan yang menggunakan AWS CloudFormation template (seperti Service Catalog). AWS Layanan ini menggunakan parameter untuk mengonfigurasi template yang sedang digunakan.

## Pelajari selengkapnya
<a name="parameters-learn"></a>

Untuk petunjuk tentang mengembangkan aplikasi CDK dengan parameter, lihat [Menggunakan CloudFormation parameter untuk mendapatkan CloudFormation nilai](get-cfn-param.md).

# Tag dan AWS CDK
<a name="tagging"></a>

Tag adalah elemen nilai kunci informasi yang dapat Anda tambahkan ke konstruksi di aplikasi CDK Anda. AWS Tag yang diterapkan pada konstruksi tertentu juga berlaku untuk semua anak yang dapat diberi tag. Tag disertakan dalam AWS CloudFormation templat yang disintesis dari aplikasi Anda dan diterapkan ke AWS sumber daya yang diterapkan. Anda dapat menggunakan tag untuk mengidentifikasi dan mengkategorikan sumber daya untuk tujuan berikut:
+ Menyederhanakan manajemen
+ Alokasi biaya
+ Kontrol akses
+ Tujuan lain yang Anda rancang

**Tip**  
Untuk informasi selengkapnya tentang cara menggunakan tag dengan AWS sumber daya, lihat [Praktik Terbaik untuk Menandai AWS Sumber Daya](https://docs.aws.amazon.com/whitepapers/latest/tagging-best-practices/tagging-best-practices.html) di * AWS Whitepaper*.

## Menggunakan tanda
<a name="tagging-use"></a>

Kelas [Tags](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html) mencakup metode statis`of()`, di mana Anda dapat menambahkan tag ke, atau menghapus tag dari, konstruksi yang ditentukan.
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#addkey-value-props](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#addkey-value-props)menerapkan tag baru ke konstruksi yang diberikan dan semua anak-anaknya.
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#removekey-props](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tags.html#removekey-props)menghapus tag dari konstruksi yang diberikan dan salah satu turunannya, termasuk tag yang mungkin diterapkan oleh konstruksi anak pada dirinya sendiri.

**catatan**  
Penandaan diimplementasikan menggunakan [Aspects dan AWS CDK](aspects.md). Aspek adalah cara untuk menerapkan operasi (seperti penandaan) ke semua konstruksi dalam lingkup tertentu.

Contoh berikut menerapkan **kunci** tag dengan nilai **nilai** untuk konstruksi.

**Example**  

```
Tags.of(myConstruct).add('key', 'value');
```

```
Tags.of(myConstruct).add('key', 'value');
```

```
Tags.of(my_construct).add("key", "value")
```

```
Tags.of(myConstruct).add("key", "value");
```

```
Tags.Of(myConstruct).Add("key", "value");
```

```
awscdk.Tags_Of(myConstruct).Add(jsii.String("key"), jsii.String("value"), &awscdk.TagProps{})
```

Contoh berikut menghapus **kunci** tag dari konstruksi.

**Example**  

```
Tags.of(myConstruct).remove('key');
```

```
Tags.of(myConstruct).remove('key');
```

```
Tags.of(my_construct).remove("key")
```

```
Tags.of(myConstruct).remove("key");
```

```
Tags.Of(myConstruct).Remove("key");
```

```
awscdk.Tags_Of(myConstruct).Remove(jsii.String("key"), &awscdk.TagProps{})
```

Jika Anda menggunakan `Stage` konstruksi, terapkan tag di `Stage` tingkat atau di bawah. Tag tidak diterapkan melintasi `Stage` batas.

## Menandai prioritas
<a name="tagging-priorities"></a>

 AWS CDK menerapkan dan menghapus tag secara rekursif. Jika ada konflik, operasi penandaan dengan prioritas tertinggi menang. (Prioritas ditetapkan menggunakan `priority` properti opsional.) Jika prioritas dua operasi sama, operasi penandaan yang paling dekat dengan bagian bawah pohon konstruksi menang. Secara default, menerapkan tag memiliki prioritas 100 (kecuali untuk tag yang ditambahkan langsung ke AWS CloudFormation sumber daya, yang memiliki prioritas 50). Prioritas default untuk menghapus tag adalah 200.

Berikut ini menerapkan tag dengan prioritas 300 untuk konstruksi.

**Example**  

```
Tags.of(myConstruct).add('key', 'value', {
  priority: 300
});
```

```
Tags.of(myConstruct).add('key', 'value', {
  priority: 300
});
```

```
Tags.of(my_construct).add("key", "value", priority=300)
```

```
Tags.of(myConstruct).add("key", "value", TagProps.builder()
        .priority(300).build());
```

```
Tags.Of(myConstruct).Add("key", "value", new TagProps { Priority = 300 });
```

```
awscdk.Tags_Of(myConstruct).Add(jsii.String("key"), jsii.String("value"), &awscdk.TagProps{
  Priority: jsii.Number(300),
})
```

## Properti opsional
<a name="tagging-props"></a>

Tag mendukung [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagProps.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.TagProps.html)yang menyempurnakan cara tag diterapkan, atau dihapus dari, sumber daya. Semua properti adalah opsional.

 `applyToLaunchedInstances`(Python:) `apply_to_launched_instances`  
Tersedia untuk add () saja. Secara default, tag diterapkan ke instance yang diluncurkan di grup Auto Scaling. Setel properti ini ke **false** untuk mengabaikan instance yang diluncurkan dalam grup Auto Scaling.

 `includeResourceTypes`/`excludeResourceTypes`(Python:`include_resource_types`/) `exclude_resource_types`  
Gunakan ini untuk memanipulasi tag hanya pada subset sumber daya, berdasarkan jenis AWS CloudFormation sumber daya. Secara default, operasi diterapkan ke semua sumber daya di subpohon konstruksi, tetapi ini dapat diubah dengan memasukkan atau mengecualikan jenis sumber daya tertentu. Kecualikan lebih diutamakan daripada include, jika keduanya ditentukan.

 `priority`   
Gunakan ini untuk menetapkan prioritas operasi ini sehubungan dengan operasi lain `Tags.add()` dan `Tags.remove()` operasi. Nilai yang lebih tinggi lebih diutamakan daripada nilai yang lebih rendah. Defaultnya adalah 100 untuk operasi tambah (50 untuk tag diterapkan langsung ke AWS CloudFormation sumber daya) dan 200 untuk menghapus operasi.

Contoh berikut menerapkan tag **tag** dengan nilai **nilai** dan prioritas **100** untuk sumber daya tipe ** AWS: :Xxx: :Yyy** dalam konstruksi. Itu tidak menerapkan tag ke instance yang diluncurkan di grup EC2 Auto Scaling Amazon atau ke sumber daya ** AWS tipe: :Xxx: :Zzz**. (Ini adalah placeholder untuk dua jenis AWS CloudFormation sumber daya yang sewenang-wenang tetapi berbeda.)

**Example**  

```
Tags.of(myConstruct).add('tagname', 'value', {
  applyToLaunchedInstances: false,
  includeResourceTypes: ['AWS::Xxx::Yyy'],
  excludeResourceTypes: ['AWS::Xxx::Zzz'],
  priority: 100,
});
```

```
Tags.of(myConstruct).add('tagname', 'value', {
  applyToLaunchedInstances: false,
  includeResourceTypes: ['AWS::Xxx::Yyy'],
  excludeResourceTypes: ['AWS::Xxx::Zzz'],
  priority: 100
});
```

```
Tags.of(my_construct).add("tagname", "value",
    apply_to_launched_instances=False,
    include_resource_types=["AWS::Xxx::Yyy"],
    exclude_resource_types=["AWS::Xxx::Zzz"],
    priority=100)
```

```
Tags.of(myConstruct).add("tagname", "value", TagProps.builder()
                .applyToLaunchedInstances(false)
                .includeResourceTypes(Arrays.asList("AWS::Xxx::Yyy"))
                .excludeResourceTypes(Arrays.asList("AWS::Xxx::Zzz"))
                .priority(100).build());
```

```
Tags.Of(myConstruct).Add("tagname", "value", new TagProps
{
    ApplyToLaunchedInstances = false,
    IncludeResourceTypes = ["AWS::Xxx::Yyy"],
    ExcludeResourceTypes = ["AWS::Xxx::Zzz"],
    Priority = 100
});
```

```
awscdk.Tags_Of(myConstruct).Add(jsii.String("tagname"), jsii.String("value"), &awscdk.TagProps{
  ApplyToLaunchedInstances: jsii.Bool(false),
  IncludeResourceTypes:     &[]*string{jsii.String("AWS::Xxx:Yyy")},
  ExcludeResourceTypes:     &[]*string{jsii.String("AWS::Xxx:Zzz")},
  Priority:                 jsii.Number(100),
})
```

**Contoh berikut menghapus tag **tag** dengan prioritas **200** dari sumber daya tipe ** AWS: :Xxx: :Yyy** dalam konstruksi, tetapi tidak dari sumber daya tipe: :Xxx: :Zzz. AWS**

**Example**  

```
Tags.of(myConstruct).remove('tagname', {
  includeResourceTypes: ['AWS::Xxx::Yyy'],
  excludeResourceTypes: ['AWS::Xxx::Zzz'],
  priority: 200,
});
```

```
Tags.of(myConstruct).remove('tagname', {
  includeResourceTypes: ['AWS::Xxx::Yyy'],
  excludeResourceTypes: ['AWS::Xxx::Zzz'],
  priority: 200
});
```

```
Tags.of(my_construct).remove("tagname",
    include_resource_types=["AWS::Xxx::Yyy"],
    exclude_resource_types=["AWS::Xxx::Zzz"],
    priority=200,)
```

```
Tags.of((myConstruct).remove("tagname", TagProps.builder()
        .includeResourceTypes(Arrays.asList("AWS::Xxx::Yyy"))
        .excludeResourceTypes(Arrays.asList("AWS::Xxx::Zzz"))
        .priority(100).build());
        )
```

```
Tags.Of(myConstruct).Remove("tagname", new TagProps
{
    IncludeResourceTypes = ["AWS::Xxx::Yyy"],
    ExcludeResourceTypes = ["AWS::Xxx::Zzz"],
    Priority = 100
});
```

```
awscdk.Tags_Of(myConstruct).Remove(jsii.String("tagname"), &awscdk.TagProps{
  IncludeResourceTypes: &[]*string{jsii.String("AWS::Xxx:Yyy")},
  ExcludeResourceTypes: &[]*string{jsii.String("AWS::Xxx:Zzz")},
  Priority:             jsii.Number(200),
})
```

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

Contoh berikut menambahkan kunci tag **StackType**dengan nilai **TheBest**ke sumber daya apa pun yang dibuat dalam `Stack` nama`MarketingSystem`. Kemudian menghapusnya lagi dari semua sumber daya kecuali subnet Amazon EC2 VPC. Hasilnya adalah hanya subnet yang memiliki tag yang diterapkan.

**Example**  

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

const app = new App();
const theBestStack = new Stack(app, 'MarketingSystem');

// Add a tag to all constructs in the stack
Tags.of(theBestStack).add('StackType', 'TheBest');

// Remove the tag from all resources except subnet resources
Tags.of(theBestStack).remove('StackType', {
  excludeResourceTypes: ['AWS::EC2::Subnet']
});
```

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

const app = new App();
const theBestStack = new Stack(app, 'MarketingSystem');

// Add a tag to all constructs in the stack
Tags.of(theBestStack).add('StackType', 'TheBest');

// Remove the tag from all resources except subnet resources
Tags.of(theBestStack).remove('StackType', {
  excludeResourceTypes: ['AWS::EC2::Subnet']
});
```

```
from aws_cdk import App, Stack, Tags

app = App();
the_best_stack = Stack(app, 'MarketingSystem')

# Add a tag to all constructs in the stack
Tags.of(the_best_stack).add("StackType", "TheBest")

# Remove the tag from all resources except subnet resources
Tags.of(the_best_stack).remove("StackType",
    exclude_resource_types=["AWS::EC2::Subnet"])
```

```
import software.amazon.awscdk.App;
import software.amazon.awscdk.Tags;

// Add a tag to all constructs in the stack
Tags.of(theBestStack).add("StackType", "TheBest");

// Remove the tag from all resources except subnet resources
Tags.of(theBestStack).remove("StackType", TagProps.builder()
        .excludeResourceTypes(Arrays.asList("AWS::EC2::Subnet"))
        .build());
```

```
using Amazon.CDK;

var app = new App();
var theBestStack = new Stack(app, 'MarketingSystem');

// Add a tag to all constructs in the stack
Tags.Of(theBestStack).Add("StackType", "TheBest");

// Remove the tag from all resources except subnet resources
Tags.Of(theBestStack).Remove("StackType", new TagProps
{
    ExcludeResourceTypes = ["AWS::EC2::Subnet"]
});
```

```
import "github.com/aws/aws-cdk-go/awscdk/v2"
app := awscdk.NewApp(nil)
theBestStack := awscdk.NewStack(app, jsii.String("MarketingSystem"), &awscdk.StackProps{})

// Add a tag to all constructs in the stack
awscdk.Tags_Of(theBestStack).Add(jsii.String("StackType"), jsii.String("TheBest"), &awscdk.TagProps{})

// Remove the tag from all resources except subnet resources
awscdk.Tags_Of(theBestStack).Add(jsii.String("StackType"), jsii.String("TheBest"), &awscdk.TagProps{
  ExcludeResourceTypes: &[]*string{jsii.String("AWS::EC2::Subnet")},
})
```

Kode berikut mencapai hasil yang sama. Pertimbangkan pendekatan mana (inklusi atau pengecualian) yang membuat maksud Anda lebih jelas.

**Example**  

```
Tags.of(theBestStack).add('StackType', 'TheBest',
  { includeResourceTypes: ['AWS::EC2::Subnet']});
```

```
Tags.of(theBestStack).add('StackType', 'TheBest',
  { includeResourceTypes: ['AWS::EC2::Subnet']});
```

```
Tags.of(the_best_stack).add("StackType", "TheBest",
    include_resource_types=["AWS::EC2::Subnet"])
```

```
Tags.of(theBestStack).add("StackType", "TheBest", TagProps.builder()
        .includeResourceTypes(Arrays.asList("AWS::EC2::Subnet"))
        .build());
```

```
Tags.Of(theBestStack).Add("StackType", "TheBest", new TagProps {
    IncludeResourceTypes = ["AWS::EC2::Subnet"]
});
```

```
awscdk.Tags_Of(theBestStack).Add(jsii.String("StackType"), jsii.String("TheBest"), &awscdk.TagProps{
  IncludeResourceTypes: &[]*string{jsii.String("AWS::EC2::Subnet")},
})
```

## Menandai konstruksi tunggal
<a name="tagging-single"></a>

 `Tags.of(scope).add(key, value)`adalah cara standar untuk menambahkan tag ke konstruksi di AWS CDK. Perilaku berjalan di pohon, yang secara rekursif menandai semua sumber daya yang dapat diberi tag di bawah lingkup yang diberikan, hampir selalu seperti yang Anda inginkan. Namun, terkadang, Anda perlu menandai konstruksi (atau konstruksi) tertentu yang sewenang-wenang.

Salah satu kasus tersebut melibatkan penerapan tag yang nilainya berasal dari beberapa properti konstruksi yang diberi tag. Pendekatan penandaan standar secara rekursif menerapkan kunci dan nilai yang sama ke semua sumber daya yang cocok dalam ruang lingkup. Namun, di sini nilainya bisa berbeda untuk setiap konstruksi yang ditandai.

Tag diimplementasikan menggunakan [aspek](aspects.md), dan CDK memanggil `visit()` metode tag untuk setiap konstruksi di bawah lingkup yang Anda tentukan menggunakan. `Tags.of(scope)` Kita dapat memanggil `Tag.visit()` langsung untuk menerapkan tag ke konstruksi tunggal.

**Example**  

```
new cdk.Tag(key, value).visit(scope);
```

```
new cdk.Tag(key, value).visit(scope);
```

```
cdk.Tag(key, value).visit(scope)
```

```
Tag.Builder.create(key, value).build().visit(scope);
```

```
new Tag(key, value).Visit(scope);
```

```
awscdk.NewTag(key, value, &awscdk.TagProps{}).Visit(scope)
```

Anda dapat menandai semua konstruksi di bawah lingkup tetapi membiarkan nilai tag berasal dari properti setiap konstruksi. Untuk melakukannya, tulis aspek dan terapkan tag dalam `visit()` metode aspek seperti yang ditunjukkan pada contoh sebelumnya. Kemudian, tambahkan aspek ke lingkup yang diinginkan menggunakan`Aspects.of(scope).add(aspect)`.

Contoh berikut menerapkan tag untuk setiap sumber daya dalam tumpukan yang berisi jalur sumber daya.

**Example**  

```
class PathTagger implements cdk.IAspect {
  visit(node: IConstruct) {
    new cdk.Tag("aws-cdk-path", node.node.path).visit(node);
  }
}

stack = new MyStack(app);
cdk.Aspects.of(stack).add(new PathTagger())
```

```
class PathTagger {
  visit(node) {
    new cdk.Tag("aws-cdk-path", node.node.path).visit(node);
  }
}

stack = new MyStack(app);
cdk.Aspects.of(stack).add(new PathTagger())
```

```
@jsii.implements(cdk.IAspect)
class PathTagger:
    def visit(self, node: IConstruct):
        cdk.Tag("aws-cdk-path", node.node.path).visit(node)

stack = MyStack(app)
cdk.Aspects.of(stack).add(PathTagger())
```

```
final class PathTagger implements IAspect {
	public void visit(IConstruct node) {
		Tag.Builder.create("aws-cdk-path", node.getNode().getPath()).build().visit(node);
	}
}

stack stack = new MyStack(app);
Aspects.of(stack).add(new PathTagger());
```

```
public class PathTagger : IAspect
{
    public void Visit(IConstruct node)
    {
        new Tag("aws-cdk-path", node.Node.Path).Visit(node);
    }
}

var stack = new MyStack(app);
Aspects.Of(stack).Add(new PathTagger);
```

**Tip**  
Logika penandaan bersyarat, termasuk prioritas, jenis sumber daya, dan sebagainya, dibangun ke dalam kelas. `Tag` Anda dapat menggunakan fitur ini saat menerapkan tag ke sumber daya arbitrer; tag tidak diterapkan jika kondisi tidak terpenuhi. Selain itu, `Tag` kelas hanya menandai sumber daya yang dapat diberi tag, jadi Anda tidak perlu menguji apakah konstruksi dapat diberi tag sebelum menerapkan tag.

# Aset dan AWS CDK
<a name="assets"></a>

Aset adalah file lokal, direktori, atau gambar Docker yang dapat dibundel ke dalam pustaka dan aplikasi AWS CDK. Misalnya, aset mungkin merupakan direktori yang berisi kode handler untuk fungsi AWS Lambda. Aset dapat mewakili artefak apa pun yang dibutuhkan aplikasi untuk beroperasi.

Video tutorial berikut memberikan gambaran menyeluruh tentang aset CDK, dan menjelaskan bagaimana Anda dapat menggunakannya dalam infrastruktur Anda sebagai kode (IAc).

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


Anda menambahkan aset melalui APIs yang diekspos oleh AWS konstruksi tertentu. Misalnya, ketika Anda mendefinisikan [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html)konstruksi, [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html#code](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html#code)properti memungkinkan Anda melewati [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Code.html#static-fromwbrassetpath-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Code.html#static-fromwbrassetpath-options)(direktori). `Function`menggunakan aset untuk menggabungkan isi direktori dan menggunakannya untuk kode fungsi. Demikian pula, [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.ContainerImage.html#static-fromwbrassetdirectory-props](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.ContainerImage.html#static-fromwbrassetdirectory-props)menggunakan image Docker yang dibangun dari direktori lokal saat mendefinisikan definisi tugas Amazon ECS.

## Aset secara detail
<a name="assets-details"></a>

Saat Anda merujuk ke aset di aplikasi Anda, [rakitan cloud](deploy.md#deploy-how-synth-assemblies) yang disintesis dari aplikasi Anda menyertakan informasi metadata dengan instruksi untuk AWS CDK CLI. Instruksi termasuk di mana menemukan aset pada disk lokal dan jenis bundling apa yang harus dilakukan berdasarkan jenis aset, seperti direktori untuk dikompres (zip) atau gambar Docker yang akan dibuat.

 AWS CDK menghasilkan hash sumber untuk aset. Ini dapat digunakan pada waktu konstruksi untuk menentukan apakah isi aset telah berubah.

Secara default, AWS CDK membuat salinan aset di direktori perakitan cloud, yang defaultnya`cdk.out`, di bawah hash sumber. Dengan cara ini, perakitan cloud mandiri, jadi jika dipindahkan ke host yang berbeda untuk penerapan, itu masih dapat digunakan. Lihat [rakitan Cloud untuk detailnya](deploy.md#deploy-how-synth-assemblies).

Saat AWS CDK menerapkan aplikasi yang mereferensikan aset (baik secara langsung oleh kode aplikasi atau melalui pustaka), CLI AWS CDK terlebih dahulu menyiapkan dan menerbitkan aset tersebut ke bucket Amazon S3 atau repositori Amazon ECR. (Bucket atau repositori S3 dibuat selama bootstrap.) Hanya dengan begitu sumber daya yang ditentukan dalam tumpukan digunakan.

Bagian ini menjelaskan tingkat rendah yang APIs tersedia dalam kerangka kerja.

## Jenis aset
<a name="assets-types"></a>

 AWS CDK mendukung jenis aset berikut:

Aset Amazon S3  
Ini adalah file dan direktori lokal yang diunggah AWS CDK ke Amazon S3.

Gambar Docker  
Ini adalah gambar Docker yang diunggah AWS CDK ke Amazon ECR.

Jenis aset ini dijelaskan di bagian berikut.

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

Anda dapat menentukan file dan direktori lokal sebagai aset, dan paket AWS CDK dan mengunggahnya ke Amazon S3 melalui modul. [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets-readme.html)

Contoh berikut mendefinisikan aset direktori lokal dan aset file.

**Example**  

```
import { Asset } from 'aws-cdk-lib/aws-s3-assets';

// Archived and uploaded to Amazon S3 as a .zip file
const directoryAsset = new Asset(this, "SampleZippedDirAsset", {
  path: path.join(__dirname, "sample-asset-directory")
});

// Uploaded to Amazon S3 as-is
const fileAsset = new Asset(this, 'SampleSingleFileAsset', {
  path: path.join(__dirname, 'file-asset.txt')
});
```

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

// Archived and uploaded to Amazon S3 as a .zip file
const directoryAsset = new Asset(this, "SampleZippedDirAsset", {
  path: path.join(__dirname, "sample-asset-directory")
});

// Uploaded to Amazon S3 as-is
const fileAsset = new Asset(this, 'SampleSingleFileAsset', {
  path: path.join(__dirname, 'file-asset.txt')
});
```

```
import os.path
dirname = os.path.dirname(__file__)

from aws_cdk.aws_s3_assets import Asset

# Archived and uploaded to Amazon S3 as a .zip file
directory_asset = Asset(self, "SampleZippedDirAsset",
  path=os.path.join(dirname, "sample-asset-directory")
)

# Uploaded to Amazon S3 as-is
file_asset = Asset(self, 'SampleSingleFileAsset',
  path=os.path.join(dirname, 'file-asset.txt')
)
```

```
import java.io.File;

import software.amazon.awscdk.services.s3.assets.Asset;

// Directory where app was started
File startDir = new File(System.getProperty("user.dir"));

// Archived and uploaded to Amazon S3 as a .zip file
Asset directoryAsset = Asset.Builder.create(this, "SampleZippedDirAsset")
                .path(new File(startDir, "sample-asset-directory").toString()).build();

// Uploaded to Amazon S3 as-is
Asset fileAsset = Asset.Builder.create(this, "SampleSingleFileAsset")
                .path(new File(startDir, "file-asset.txt").toString()).build();
```

```
using System.IO;
using Amazon.CDK.AWS.S3.Assets;

// Archived and uploaded to Amazon S3 as a .zip file
var directoryAsset = new Asset(this, "SampleZippedDirAsset", new AssetProps
{
    Path = Path.Combine(Directory.GetCurrentDirectory(), "sample-asset-directory")
});

// Uploaded to Amazon S3 as-is
var fileAsset = new Asset(this, "SampleSingleFileAsset", new AssetProps
{
    Path = Path.Combine(Directory.GetCurrentDirectory(), "file-asset.txt")
});
```

```
dirName, err := os.Getwd()
if err != nil {
  panic(err)
}

awss3assets.NewAsset(stack, jsii.String("SampleZippedDirAsset"), awss3assets.AssetProps{
  Path: jsii.String(path.Join(dirName, "sample-asset-directory")),
})

awss3assets.NewAsset(stack, jsii.String("SampleSingleFileAsset"), awss3assets.AssetProps{
  Path: jsii.String(path.Join(dirName, "file-asset.txt")),
})
```

Dalam kebanyakan kasus, Anda tidak perlu langsung menggunakan `aws-s3-assets` modul APIs dalam. Modul yang mendukung aset, seperti`aws-lambda`, memiliki metode kemudahan sehingga Anda dapat menggunakan aset. Untuk fungsi Lambda, metode [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Code.html#static-fromwbrassetpath-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Code.html#static-fromwbrassetpath-options)statis memungkinkan Anda menentukan direktori atau file.zip di sistem file lokal.

### Contoh fungsi Lambda
<a name="assets-types-s3-lambda"></a>

Kasus penggunaan umum adalah membuat fungsi Lambda dengan kode handler sebagai aset Amazon S3.

Contoh berikut menggunakan aset Amazon S3 untuk menentukan handler Python di direktori lokal. `handler` Ini juga menciptakan fungsi Lambda dengan aset direktori lokal sebagai properti. `code` Berikut ini adalah kode Python untuk handler.

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

Kode untuk aplikasi AWS CDK utama akan terlihat seperti berikut.

**Example**  

```
import * as cdk from 'aws-cdk-lib';
import { Constructs } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as path from 'path';

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

    new lambda.Function(this, 'myLambdaFunction', {
      code: lambda.Code.fromAsset(path.join(__dirname, 'handler')),
      runtime: lambda.Runtime.PYTHON_3_6,
      handler: 'index.lambda_handler'
    });
  }
}
```

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

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

    new lambda.Function(this, 'myLambdaFunction', {
      code: lambda.Code.fromAsset(path.join(__dirname, 'handler')),
      runtime: lambda.Runtime.PYTHON_3_6,
      handler: 'index.lambda_handler'
    });
  }
}

module.exports = { HelloAssetStack }
```

```
from aws_cdk import Stack
from constructs import Construct
from aws_cdk import aws_lambda as lambda_

import os.path
dirname = os.path.dirname(__file__)

class HelloAssetStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        lambda_.Function(self, 'myLambdaFunction',
            code=lambda_.Code.from_asset(os.path.join(dirname, 'handler')),
            runtime=lambda_.Runtime.PYTHON_3_6,
            handler="index.lambda_handler")
```

```
import java.io.File;

import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.lambda.Runtime;

public class HelloAssetStack extends Stack {

    public HelloAssetStack(final App scope, final String id) {
        this(scope, id, null);
    }

    public HelloAssetStack(final App scope, final String id, final StackProps props) {
        super(scope, id, props);

        File startDir = new File(System.getProperty("user.dir"));

        Function.Builder.create(this, "myLambdaFunction")
                .code(Code.fromAsset(new File(startDir, "handler").toString()))
                .runtime(Runtime.PYTHON_3_6)
                .handler("index.lambda_handler").build();
    }
}
```

```
using Amazon.CDK;
using Amazon.CDK.AWS.Lambda;
using System.IO;

public class HelloAssetStack : Stack
{
    public HelloAssetStack(Construct scope, string id, StackProps props) : base(scope, id, props)
    {
        new Function(this, "myLambdaFunction", new FunctionProps
        {
            Code = Code.FromAsset(Path.Combine(Directory.GetCurrentDirectory(), "handler")),
            Runtime = Runtime.PYTHON_3_6,
            Handler = "index.lambda_handler"
        });
    }
}
```

```
import (
  "os"
  "path"

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

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

  dirName, err := os.Getwd()
  if err != nil {
    panic(err)
  }

  awslambda.NewFunction(stack, jsii.String("myLambdaFunction"), awslambda.FunctionProps{
    Code: awslambda.AssetCode_FromAsset(jsii.String(path.Join(dirName, "handler")), awss3assets.AssetOptions{}),
    Runtime: awslambda.Runtime_PYTHON_3_6(),
    Handler: jsii.String("index.lambda_handler"),
  })

  return stack
}
```

`Function`Metode ini menggunakan aset untuk menggabungkan isi direktori dan menggunakannya untuk kode fungsi.

**Tip**  
`.jar`File Java adalah file ZIP dengan ekstensi berbeda. Ini diunggah apa adanya ke Amazon S3, tetapi ketika digunakan sebagai fungsi Lambda, file yang dikandungnya diekstraksi, yang mungkin tidak Anda inginkan. Untuk menghindari hal ini, tempatkan `.jar` file dalam direktori dan tentukan direktori itu sebagai aset.

### Contoh atribut waktu penerapan
<a name="assets-types-s3-deploy"></a>

Jenis aset Amazon S3 juga mengekspos [atribut waktu penerapan yang dapat direferensikan di pustaka](resources.md#resources-attributes) dan aplikasi CDK. AWS `cdk synth`Perintah AWS CDK CLI menampilkan properti AWS CloudFormation aset sebagai parameter.

Contoh berikut menggunakan atribut deploy-time untuk meneruskan lokasi aset gambar ke dalam fungsi Lambda sebagai variabel lingkungan. (Jenis file tidak masalah; gambar PNG yang digunakan di sini hanyalah sebuah contoh.)

**Example**  

```
import { Asset } from 'aws-cdk-lib/aws-s3-assets';
import * as path from 'path';

const imageAsset = new Asset(this, "SampleAsset", {
  path: path.join(__dirname, "images/my-image.png")
});

new lambda.Function(this, "myLambdaFunction", {
  code: lambda.Code.asset(path.join(__dirname, "handler")),
  runtime: lambda.Runtime.PYTHON_3_6,
  handler: "index.lambda_handler",
  environment: {
    'S3_BUCKET_NAME': imageAsset.s3BucketName,
    'S3_OBJECT_KEY': imageAsset.s3ObjectKey,
    'S3_OBJECT_URL': imageAsset.s3ObjectUrl
  }
});
```

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

const imageAsset = new Asset(this, "SampleAsset", {
  path: path.join(__dirname, "images/my-image.png")
});

new lambda.Function(this, "myLambdaFunction", {
  code: lambda.Code.asset(path.join(__dirname, "handler")),
  runtime: lambda.Runtime.PYTHON_3_6,
  handler: "index.lambda_handler",
  environment: {
    'S3_BUCKET_NAME': imageAsset.s3BucketName,
    'S3_OBJECT_KEY': imageAsset.s3ObjectKey,
    'S3_OBJECT_URL': imageAsset.s3ObjectUrl
  }
});
```

```
import os.path

import aws_cdk.aws_lambda as lambda_
from aws_cdk.aws_s3_assets import Asset

dirname = os.path.dirname(__file__)

image_asset = Asset(self, "SampleAsset",
    path=os.path.join(dirname, "images/my-image.png"))

lambda_.Function(self, "myLambdaFunction",
    code=lambda_.Code.asset(os.path.join(dirname, "handler")),
    runtime=lambda_.Runtime.PYTHON_3_6,
    handler="index.lambda_handler",
    environment=dict(
        S3_BUCKET_NAME=image_asset.s3_bucket_name,
        S3_OBJECT_KEY=image_asset.s3_object_key,
        S3_OBJECT_URL=image_asset.s3_object_url))
```

```
import java.io.File;

import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.lambda.Runtime;
import software.amazon.awscdk.services.s3.assets.Asset;

public class FunctionStack extends Stack {
    public FunctionStack(final App scope, final String id, final StackProps props) {
        super(scope, id, props);

        File startDir = new File(System.getProperty("user.dir"));

        Asset imageAsset = Asset.Builder.create(this, "SampleAsset")
                .path(new File(startDir, "images/my-image.png").toString()).build())

        Function.Builder.create(this, "myLambdaFunction")
                .code(Code.fromAsset(new File(startDir, "handler").toString()))
                .runtime(Runtime.PYTHON_3_6)
                .handler("index.lambda_handler")
                .environment(java.util.Map.of(    // Java 9 or later
                    "S3_BUCKET_NAME", imageAsset.getS3BucketName(),
                    "S3_OBJECT_KEY", imageAsset.getS3ObjectKey(),
                    "S3_OBJECT_URL", imageAsset.getS3ObjectUrl()))
                .build();
    }
}
```

```
using Amazon.CDK;
using Amazon.CDK.AWS.Lambda;
using Amazon.CDK.AWS.S3.Assets;
using System.IO;
using System.Collections.Generic;

var imageAsset = new Asset(this, "SampleAsset", new AssetProps
{
    Path = Path.Combine(Directory.GetCurrentDirectory(), @"images\my-image.png")
});

new Function(this, "myLambdaFunction", new FunctionProps
{
    Code = Code.FromAsset(Path.Combine(Directory.GetCurrentDirectory(), "handler")),
    Runtime = Runtime.PYTHON_3_6,
    Handler = "index.lambda_handler",
    Environment = new Dictionarystring, string
    {
        ["S3_BUCKET_NAME"] = imageAsset.S3BucketName,
        ["S3_OBJECT_KEY"] = imageAsset.S3ObjectKey,
        ["S3_OBJECT_URL"] = imageAsset.S3ObjectUrl
    }
});
```

```
import (
  "os"
  "path"

  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/aws-cdk-go/awscdk/v2/awslambda"
  "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets"
)

dirName, err := os.Getwd()
if err != nil {
  panic(err)
}

imageAsset := awss3assets.NewAsset(stack, jsii.String("SampleAsset"), awss3assets.AssetProps{
  Path: jsii.String(path.Join(dirName, "images/my-image.png")),
})

awslambda.NewFunction(stack, jsii.String("myLambdaFunction"), awslambda.FunctionProps{
  Code: awslambda.AssetCode_FromAsset(jsii.String(path.Join(dirName, "handler"))),
  Runtime: awslambda.Runtime_PYTHON_3_6(),
  Handler: jsii.String("index.lambda_handler"),
  Environment: map[string]*string{
    "S3_BUCKET_NAME": imageAsset.S3BucketName(),
    "S3_OBJECT_KEY": imageAsset.S3ObjectKey(),
    "S3_URL": imageAsset.S3ObjectUrl(),
  },
})
```

### Izin
<a name="assets-types-s3-permissions"></a>

Jika Anda menggunakan aset Amazon S3 secara langsung melalui [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets-readme.html)modul, peran IAM, pengguna, atau grup, dan Anda perlu membaca aset saat runtime, berikan izin IAM aset tersebut melalui metode. [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets.Asset.html#grantwbrreadgrantee](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets.Asset.html#grantwbrreadgrantee)

Contoh berikut memberikan izin baca grup IAM pada aset file.

**Example**  

```
import { Asset } from 'aws-cdk-lib/aws-s3-assets';
import * as path from 'path';

const asset = new Asset(this, 'MyFile', {
  path: path.join(__dirname, 'my-image.png')
});

const group = new iam.Group(this, 'MyUserGroup');
asset.grantRead(group);
```

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

const asset = new Asset(this, 'MyFile', {
  path: path.join(__dirname, 'my-image.png')
});

const group = new iam.Group(this, 'MyUserGroup');
asset.grantRead(group);
```

```
from aws_cdk.aws_s3_assets import Asset
import aws_cdk.aws_iam as iam

import os.path
dirname = os.path.dirname(__file__)

        asset = Asset(self, "MyFile",
            path=os.path.join(dirname, "my-image.png"))

        group = iam.Group(self, "MyUserGroup")
        asset.grant_read(group)
```

```
import java.io.File;

import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.iam.Group;
import software.amazon.awscdk.services.s3.assets.Asset;

public class GrantStack extends Stack {
    public GrantStack(final App scope, final String id, final StackProps props) {
        super(scope, id, props);

        File startDir = new File(System.getProperty("user.dir"));

        Asset asset = Asset.Builder.create(this, "SampleAsset")
                .path(new File(startDir, "images/my-image.png").toString()).build();

        Group group = new Group(this, "MyUserGroup");
        asset.grantRead(group);   }
}
```

```
using Amazon.CDK;
using Amazon.CDK.AWS.IAM;
using Amazon.CDK.AWS.S3.Assets;
using System.IO;

var asset = new Asset(this, "MyFile", new AssetProps {
    Path = Path.Combine(Path.Combine(Directory.GetCurrentDirectory(), @"images\my-image.png"))
});

var group = new Group(this, "MyUserGroup");
asset.GrantRead(group);
```

```
import (
  "os"
  "path"

  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/aws-cdk-go/awscdk/v2/awsiam"
  "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets"
)

dirName, err := os.Getwd()
if err != nil {
  panic(err)
}

asset := awss3assets.NewAsset(stack, jsii.String("MyFile"), awss3assets.AssetProps{
  Path: jsii.String(path.Join(dirName, "my-image.png")),
})

group := awsiam.NewGroup(stack, jsii.String("MyUserGroup"), awsiam.GroupProps{})

asset.GrantRead(group)
```

## Aset gambar Docker
<a name="assets-types-docker"></a>

 AWS CDK mendukung bundling image Docker lokal sebagai aset melalui modul. [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr_assets-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr_assets-readme.html)

Contoh berikut mendefinisikan image Docker yang dibangun secara lokal dan didorong ke Amazon ECR. Gambar dibuat dari direktori konteks Docker lokal (dengan Dockerfile) dan diunggah ke Amazon ECR oleh AWS CDK CLI atau pipeline CI/CD aplikasi Anda. Gambar dapat direferensikan secara alami di aplikasi AWS CDK Anda.

**Example**  

```
import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets';

const asset = new DockerImageAsset(this, 'MyBuildImage', {
  directory: path.join(__dirname, 'my-image')
});
```

```
const { DockerImageAsset } = require('aws-cdk-lib/aws-ecr-assets');

const asset = new DockerImageAsset(this, 'MyBuildImage', {
  directory: path.join(__dirname, 'my-image')
});
```

```
from aws_cdk.aws_ecr_assets import DockerImageAsset

import os.path
dirname = os.path.dirname(__file__)

asset = DockerImageAsset(self, 'MyBuildImage',
    directory=os.path.join(dirname, 'my-image'))
```

```
import software.amazon.awscdk.services.ecr.assets.DockerImageAsset;

File startDir = new File(System.getProperty("user.dir"));

DockerImageAsset asset = DockerImageAsset.Builder.create(this, "MyBuildImage")
            .directory(new File(startDir, "my-image").toString()).build();
```

```
using System.IO;
using Amazon.CDK.AWS.ECR.Assets;

var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps
{
    Directory = Path.Combine(Directory.GetCurrentDirectory(), "my-image")
});
```

```
import (
  "os"
  "path"

  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/aws-cdk-go/awscdk/v2/awsecrassets"
)

dirName, err := os.Getwd()
if err != nil {
  panic(err)
}

asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyBuildImage"), awsecrassets.DockerImageAssetProps{
  Directory: jsii.String(path.Join(dirName, "my-image")),
})
```

`my-image`Direktori harus menyertakan Dockerfile. AWS CDK CLI membangun image Docker `my-image` dari, mendorongnya ke repositori Amazon ECR, dan menentukan nama repositori sebagai parameter ke tumpukan Anda. AWS CloudFormation Jenis aset gambar Docker mengekspos [atribut waktu penerapan yang](resources.md#resources-attributes) dapat direferensikan di AWS pustaka dan aplikasi CDK. `cdk synth`Perintah AWS CDK CLI menampilkan properti AWS CloudFormation aset sebagai parameter.

### Contoh definisi tugas Amazon ECS
<a name="assets-types-docker-ecs"></a>

Kasus penggunaan yang umum adalah membuat Amazon ECS [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.TaskDefinition.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.TaskDefinition.html)untuk menjalankan kontainer Docker. Contoh berikut menentukan lokasi aset image Docker yang dibuat AWS CDK secara lokal dan mendorong ke Amazon ECR.

**Example**  

```
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecr_assets from 'aws-cdk-lib/aws-ecr-assets';
import * as path from 'path';

const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", {
  memoryLimitMiB: 1024,
  cpu: 512
});

const asset = new ecr_assets.DockerImageAsset(this, 'MyBuildImage', {
  directory: path.join(__dirname, 'my-image')
});

taskDefinition.addContainer("my-other-container", {
  image: ecs.ContainerImage.fromDockerImageAsset(asset)
});
```

```
const ecs = require('aws-cdk-lib/aws-ecs');
const ecr_assets = require('aws-cdk-lib/aws-ecr-assets');
const path = require('path');

const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", {
  memoryLimitMiB: 1024,
  cpu: 512
});

const asset = new ecr_assets.DockerImageAsset(this, 'MyBuildImage', {
  directory: path.join(__dirname, 'my-image')
});

taskDefinition.addContainer("my-other-container", {
  image: ecs.ContainerImage.fromDockerImageAsset(asset)
});
```

```
import aws_cdk.aws_ecs as ecs
import aws_cdk.aws_ecr_assets as ecr_assets

import os.path
dirname = os.path.dirname(__file__)

task_definition = ecs.FargateTaskDefinition(self, "TaskDef",
    memory_limit_mib=1024,
    cpu=512)

asset = ecr_assets.DockerImageAsset(self, 'MyBuildImage',
    directory=os.path.join(dirname, 'my-image'))

task_definition.add_container("my-other-container",
    image=ecs.ContainerImage.from_docker_image_asset(asset))
```

```
import java.io.File;

import software.amazon.awscdk.services.ecs.FargateTaskDefinition;
import software.amazon.awscdk.services.ecs.ContainerDefinitionOptions;
import software.amazon.awscdk.services.ecs.ContainerImage;

import software.amazon.awscdk.services.ecr.assets.DockerImageAsset;

File startDir = new File(System.getProperty("user.dir"));

FargateTaskDefinition taskDefinition = FargateTaskDefinition.Builder.create(
        this, "TaskDef").memoryLimitMiB(1024).cpu(512).build();

DockerImageAsset asset = DockerImageAsset.Builder.create(this, "MyBuildImage")
            .directory(new File(startDir, "my-image").toString()).build();

taskDefinition.addContainer("my-other-container",
        ContainerDefinitionOptions.builder()
            .image(ContainerImage.fromDockerImageAsset(asset))
            .build();
)
```

```
using System.IO;
using Amazon.CDK.AWS.ECS;
using Amazon.CDK.AWS.Ecr.Assets;

var taskDefinition = new FargateTaskDefinition(this, "TaskDef", new FargateTaskDefinitionProps
{
    MemoryLimitMiB = 1024,
    Cpu = 512
});

var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps
{
    Directory = Path.Combine(Directory.GetCurrentDirectory(), "my-image")
});

taskDefinition.AddContainer("my-other-container", new ContainerDefinitionOptions
{
    Image = ContainerImage.FromDockerImageAsset(asset)
});
```

```
import (
  "os"
  "path"

  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/aws-cdk-go/awscdk/v2/awsecrassets"
  "github.com/aws/aws-cdk-go/awscdk/v2/awsecs"
)

dirName, err := os.Getwd()
if err != nil {
  panic(err)
}

taskDefinition := awsecs.NewTaskDefinition(stack, jsii.String("TaskDef"), awsecs.TaskDefinitionProps{
  MemoryMiB: jsii.String("1024"),
  Cpu: jsii.String("512"),
})

asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyBuildImage"), awsecrassets.DockerImageAssetProps{
  Directory: jsii.String(path.Join(dirName, "my-image")),
})

taskDefinition.AddContainer(jsii.String("MyOtherContainer"), awsecs.ContainerDefinitionOptions{
  Image: awsecs.ContainerImage_FromDockerImageAsset(asset),
})
```

### Contoh atribut waktu penerapan
<a name="assets-types-docker-deploy"></a>

Contoh berikut menunjukkan cara menggunakan atribut deploy-time `repository` dan `imageUri` membuat definisi tugas Amazon ECS dengan tipe peluncuran Fargate AWS . Perhatikan bahwa pencarian repo Amazon ECR memerlukan tag gambar, bukan URI-nya, jadi kami memotongnya dari akhir URI aset.

**Example**  

```
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as path from 'path';
import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets';

const asset = new DockerImageAsset(this, 'my-image', {
  directory: path.join(__dirname, "..", "demo-image")
});

const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", {
  memoryLimitMiB: 1024,
  cpu: 512
});

taskDefinition.addContainer("my-other-container", {
  image: ecs.ContainerImage.fromEcrRepository(asset.repository, asset.imageUri.split(":").pop())
});
```

```
const ecs = require('aws-cdk-lib/aws-ecs');
const path = require('path');
const { DockerImageAsset } = require('aws-cdk-lib/aws-ecr-assets');

const asset = new DockerImageAsset(this, 'my-image', {
  directory: path.join(__dirname, "..", "demo-image")
});

const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", {
  memoryLimitMiB: 1024,
  cpu: 512
});

taskDefinition.addContainer("my-other-container", {
  image: ecs.ContainerImage.fromEcrRepository(asset.repository, asset.imageUri.split(":").pop())
});
```

```
import aws_cdk.aws_ecs as ecs
from aws_cdk.aws_ecr_assets import DockerImageAsset

import os.path
dirname = os.path.dirname(__file__)

asset = DockerImageAsset(self, 'my-image',
    directory=os.path.join(dirname, "..", "demo-image"))

task_definition = ecs.FargateTaskDefinition(self, "TaskDef",
    memory_limit_mib=1024, cpu=512)

task_definition.add_container("my-other-container",
    image=ecs.ContainerImage.from_ecr_repository(
        asset.repository, asset.image_uri.rpartition(":")[-1]))
```

```
import java.io.File;

import software.amazon.awscdk.services.ecr.assets.DockerImageAsset;

import software.amazon.awscdk.services.ecs.FargateTaskDefinition;
import software.amazon.awscdk.services.ecs.ContainerDefinitionOptions;
import software.amazon.awscdk.services.ecs.ContainerImage;

File startDir = new File(System.getProperty("user.dir"));

DockerImageAsset asset = DockerImageAsset.Builder.create(this, "my-image")
            .directory(new File(startDir, "demo-image").toString()).build();

FargateTaskDefinition taskDefinition = FargateTaskDefinition.Builder.create(
        this, "TaskDef").memoryLimitMiB(1024).cpu(512).build();

// extract the tag from the asset's image URI for use in ECR repo lookup
String imageUri = asset.getImageUri();
String imageTag = imageUri.substring(imageUri.lastIndexOf(":") + 1);

taskDefinition.addContainer("my-other-container",
        ContainerDefinitionOptions.builder().image(ContainerImage.fromEcrRepository(
                asset.getRepository(), imageTag)).build());
```

```
using System.IO;
using Amazon.CDK.AWS.ECS;
using Amazon.CDK.AWS.ECR.Assets;

var asset = new DockerImageAsset(this, "my-image", new DockerImageAssetProps {
    Directory = Path.Combine(Directory.GetCurrentDirectory(), "demo-image")
});

var taskDefinition = new FargateTaskDefinition(this, "TaskDef", new FargateTaskDefinitionProps
{
    MemoryLimitMiB = 1024,
    Cpu = 512
});

taskDefinition.AddContainer("my-other-container", new ContainerDefinitionOptions
{
    Image = ContainerImage.FromEcrRepository(asset.Repository, asset.ImageUri.Split(":").Last())
});
```

```
import (
  "os"
  "path"

  "github.com/aws/aws-cdk-go/awscdk/v2"
  "github.com/aws/aws-cdk-go/awscdk/v2/awsecrassets"
  "github.com/aws/aws-cdk-go/awscdk/v2/awsecs"
)

dirName, err := os.Getwd()
if err != nil {
  panic(err)
}

asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyImage"), awsecrassets.DockerImageAssetProps{
  Directory: jsii.String(path.Join(dirName, "demo-image")),
})

taskDefinition := awsecs.NewFargateTaskDefinition(stack, jsii.String("TaskDef"), awsecs.FargateTaskDefinitionProps{
  MemoryLimitMiB: jsii.Number(1024),
  Cpu: jsii.Number(512),
})

taskDefinition.AddContainer(jsii.String("MyOtherContainer"), awsecs.ContainerDefinitionOptions{
  Image: awsecs.ContainerImage_FromEcrRepository(asset.Repository(), asset.ImageTag()),
})
```

### Membangun contoh argumen
<a name="assets-types-docker-build"></a>

Anda dapat memberikan argumen build yang disesuaikan untuk langkah build Docker melalui opsi properti `buildArgs` (Python`build_args`:) saat AWS CDK CLI membangun gambar selama penerapan.

**Example**  

```
const asset = new DockerImageAsset(this, 'MyBuildImage', {
  directory: path.join(__dirname, 'my-image'),
  buildArgs: {
    HTTP_PROXY: 'http://10.20.30.2:1234'
  }
});
```

```
const asset = new DockerImageAsset(this, 'MyBuildImage', {
  directory: path.join(__dirname, 'my-image'),
  buildArgs: {
    HTTP_PROXY: 'http://10.20.30.2:1234'
  }
});
```

```
asset = DockerImageAsset(self, "MyBuildImage",
    directory=os.path.join(dirname, "my-image"),
    build_args=dict(HTTP_PROXY="http://10.20.30.2:1234"))
```

```
DockerImageAsset asset = DockerImageAsset.Builder.create(this, "my-image"),
            .directory(new File(startDir, "my-image").toString())
            .buildArgs(java.util.Map.of(    // Java 9 or later
                "HTTP_PROXY", "http://10.20.30.2:1234"))
            .build();
```

```
var asset = new DockerImageAsset(this, "MyBuildImage", new DockerImageAssetProps {
    Directory = Path.Combine(Directory.GetCurrentDirectory(), "my-image"),
    BuildArgs = new Dictionarystring, string
    {
        ["HTTP_PROXY"] = "http://10.20.30.2:1234"
    }
});
```

```
dirName, err := os.Getwd()
if err != nil {
  panic(err)
}

asset := awsecrassets.NewDockerImageAsset(stack, jsii.String("MyBuildImage"), awsecrassets.DockerImageAssetProps{
  Directory: jsii.String(path.Join(dirName, "my-image")),
  BuildArgs: map[string]*string{
    "HTTP_PROXY": jsii.String("http://10.20.30.2:1234"),
  },
})
```

### Izin
<a name="assets-types-docker-permissions"></a>

Jika Anda menggunakan modul yang mendukung aset image Docker, seperti [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs-readme.html), AWS CDK mengelola izin untuk Anda saat Anda menggunakan aset secara langsung atau melalui ([https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.ContainerImage.html#static-fromwbrecrwbrrepositoryrepository-tag](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.ContainerImage.html#static-fromwbrecrwbrrepositoryrepository-tag)Python:). `from_ecr_repository` Jika Anda menggunakan aset image Docker secara langsung, pastikan bahwa prinsipal konsumsi memiliki izin untuk menarik gambar.

Dalam kebanyakan kasus, Anda harus menggunakan [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr.Repository.html#grantwbrpullgrantee](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr.Repository.html#grantwbrpullgrantee)metode (Python:`grant_pull`). Ini memodifikasi kebijakan IAM dari prinsipal untuk memungkinkannya menarik gambar dari repositori ini. Jika prinsipal yang menarik gambar tidak berada di akun yang sama, atau jika itu adalah AWS layanan yang tidak berperan dalam akun Anda (seperti AWS CodeBuild), Anda harus memberikan izin tarik pada kebijakan sumber daya dan bukan pada kebijakan prinsipal. Gunakan [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr.Repository.html#addwbrtowbrresourcewbrpolicystatement](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecr.Repository.html#addwbrtowbrresourcewbrpolicystatement)metode (Python:`add_to_resource_policy`) untuk memberikan izin utama yang sesuai.

## AWS CloudFormation metadata sumber daya
<a name="assets-cfn"></a>

**catatan**  
Bagian ini hanya relevan untuk penulis konstruksi. Dalam situasi tertentu, alat perlu mengetahui bahwa sumber daya CFN tertentu menggunakan aset lokal. Misalnya, Anda dapat menggunakan AWS SAM CLI untuk menjalankan fungsi Lambda secara lokal untuk tujuan debugging. Lihat [Integrasi AWS SAM](tools.md#sam) untuk detailnya.

Untuk mengaktifkan kasus penggunaan seperti itu, alat eksternal berkonsultasi dengan satu set entri metadata tentang sumber daya: AWS CloudFormation 
+  `aws:asset:path`— Menunjuk ke jalur lokal aset.
+  `aws:asset:property`— Nama properti sumber daya tempat aset digunakan.

Dengan menggunakan dua entri metadata ini, alat dapat mengidentifikasi bahwa aset digunakan oleh sumber daya tertentu, dan memungkinkan pengalaman lokal tingkat lanjut.

Untuk menambahkan entri metadata ini ke sumber daya, gunakan metode (`asset.addResourceMetadata`Python:). `add_resource_metadata`

# Izin dan CDK AWS
<a name="permissions"></a>

Perpustakaan AWS Konstruksi menggunakan beberapa idiom umum yang diterapkan secara luas untuk mengelola akses dan izin. Modul IAM memberi Anda alat yang Anda butuhkan untuk menggunakan idiom ini.

 AWS CDK menggunakan AWS CloudFormation untuk menyebarkan perubahan. Setiap penyebaran melibatkan aktor (baik pengembang, atau sistem otomatis) yang memulai AWS CloudFormation penerapan. Selama melakukan ini, aktor akan mengambil satu atau lebih Identitas IAM (pengguna atau peran) dan secara opsional memberikan peran ke. AWS CloudFormation

Jika Anda menggunakan Pusat AWS Identitas IAM untuk mengautentikasi sebagai pengguna, maka penyedia masuk tunggal menyediakan kredensil sesi berumur pendek yang mengizinkan Anda untuk bertindak sebagai peran IAM yang telah ditentukan sebelumnya. *Untuk mempelajari cara AWS CDK memperoleh AWS kredensil dari autentikasi Pusat Identitas IAM, lihat [Memahami autentikasi Pusat Identitas IAM di Panduan Referensi Alat dan Alat](https://docs.aws.amazon.com/sdkref/latest/guide/understanding-sso.html). AWS SDKs *

## Pengguna utama
<a name="permissions-principals"></a>

Prinsipal IAM adalah AWS entitas yang diautentikasi yang mewakili pengguna, layanan, atau aplikasi yang dapat memanggil. AWS APIs AWS Construct Library mendukung penetapan prinsipal dalam beberapa cara fleksibel untuk memberi mereka akses sumber daya Anda. AWS 

Dalam konteks keamanan, istilah “prinsipal” mengacu secara khusus pada entitas yang diautentikasi seperti pengguna. Objek seperti grup dan peran tidak *mewakili* pengguna (dan entitas lain yang diautentikasi) melainkan *mengidentifikasi* mereka secara tidak langsung untuk tujuan pemberian izin.

Misalnya, jika Anda membuat grup IAM, Anda dapat memberikan grup (dan dengan demikian anggotanya) akses tulis ke tabel Amazon RDS. Namun, grup itu sendiri bukan prinsipal karena tidak mewakili satu entitas (juga, Anda tidak dapat masuk ke grup).

Di perpustakaan IAM CDK, kelas yang secara langsung atau tidak langsung mengidentifikasi prinsipal mengimplementasikan [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.IPrincipal.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.IPrincipal.html)antarmuka, memungkinkan objek ini digunakan secara bergantian dalam kebijakan akses. Namun, tidak semua dari mereka adalah kepala sekolah dalam arti keamanan. Benda-benda ini meliputi:

1. Sumber daya IAM seperti [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html), [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html), dan [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html) 

1. Prinsipal layanan () `new iam.[ServicePrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ServicePrincipal.html)('service.amazonaws.com')`

1. Kepala sekolah federasi () `new iam.[FederatedPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.FederatedPrincipal.html)('cognito-identity.amazonaws.com')`

1. Prinsipal akun () `new iam.[AccountPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.AccountPrincipal.html)('0123456789012')`

1. Prinsipal pengguna kanonik () `new iam.[CanonicalUserPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.CanonicalUserPrincipal.html)('79a59d[…​]7ef2be')`

1.  AWS Organizations principals () `new iam.[OrganizationPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.OrganizationPrincipal.html)('org-id')`

1. Prinsipal ARN sewenang-wenang () `new iam.[ArnPrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ArnPrincipal.html)(res.arn)`

1. An `iam.[CompositePrincipal](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.CompositePrincipal.html)(principal1, principal2, …​)` untuk mempercayai banyak prinsip

## Izin
<a name="permissions-grants"></a>

Banyak konstruksi mewakili sumber daya yang dapat diakses, seperti bucket Amazon S3 atau tabel Amazon DynamoDB. Untuk itu, Anda dapat memberikan akses ke entitas lain. **Ada dua cara untuk melakukan ini, tergantung pada konstruksi tertentu: menggunakan kelas Grants yang sesuai (misalnya, `BucketGrants` untuk bucket Amazon S3) atau menggunakan metode dalam konstruksi itu sendiri, yang memiliki nama yang dimulai dengan hibah.** Yang pertama lebih disukai karena mereka dapat digunakan untuk memberikan akses ke sumber daya L1 dan L2 dengan cara yang sama. Untuk membuat instance dari kelas Grants, gunakan metode pabriknya:

**Example**  

```
BucketGrants.fromBucket(bucket); // bucket can be either a Bucket (L2) or a CfnBucket (L1)
```

```
BucketGrants.fromBucket(bucket); // bucket can be either a Bucket (L2) or a CfnBucket (L1)
```

```
BucketGrants.from_bucket(bucket) # bucket can be either a Bucket (L2) or a CfnBucket (L1)
```

```
BucketGrants.fromBucket(bucket); // bucket can be either a Bucket (L2) or a CfnBucket (L1)
```

```
BucketGrants.FromBucket(bucket); // bucket can be either a Bucket (L2) or a CfnBucket (L1)
```

Kelas hibah menyediakan metode untuk memberikan izin khusus untuk mengakses sumber daya mereka. Misalnya, `BucketGrants` memiliki metode `read` dan `readWrite` (Python:`read`,`read_write`) untuk mengaktifkan baca dan read/write akses, masing-masing, dari entitas ke bucket. Entitas tidak harus tahu persis izin IAM Amazon S3 mana yang diperlukan untuk melakukan operasi ini.

Argumen pertama dari metode dalam kelas Grants (atau metode **hibah** dalam sumber daya itu sendiri) selalu bertipe [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.IGrantable.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.IGrantable.html). Antarmuka ini mewakili entitas yang dapat diberikan izin. Artinya, ini mewakili sumber daya dengan peran, seperti objek IAM [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html), [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html), dan [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html).

Entitas lain juga dapat diberikan izin. Misalnya, nanti dalam topik ini, kami menunjukkan cara memberikan akses CodeBuild proyek ke bucket Amazon S3. Umumnya, peran terkait diperoleh melalui `role` properti pada entitas yang diberikan akses.

Sumber daya yang menggunakan peran eksekusi, seperti [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html), juga diterapkan`IGrantable`, sehingga Anda dapat memberi mereka akses secara langsung alih-alih memberikan akses ke peran mereka. Misalnya, jika `bucket` adalah bucket Amazon S3, dan `function` merupakan fungsi Lambda, kode berikut memberikan akses baca fungsi ke bucket.

Untuk kenyamanan, konstruksi L2 juga menawarkan `grants` properti yang mengembalikan instance dari kelas Grants yang sesuai.

**Example**  

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

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

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

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

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

Terkadang izin harus diterapkan saat tumpukan Anda sedang digunakan. Salah satu kasus tersebut adalah ketika Anda memberikan akses sumber daya AWS CloudFormation khusus ke beberapa sumber daya lain. Sumber daya kustom akan dipanggil selama penerapan, sehingga harus memiliki izin yang ditentukan pada waktu penerapan.

Kasus lain adalah ketika layanan memverifikasi bahwa peran yang Anda berikan kepadanya memiliki kebijakan yang tepat diterapkan. (Sejumlah AWS layanan melakukan ini untuk memastikan bahwa Anda tidak lupa untuk menetapkan kebijakan.) Dalam kasus tersebut, penerapan mungkin gagal jika izin diterapkan terlambat.

Untuk memaksa izin hibah diterapkan sebelum sumber daya lain dibuat, Anda dapat menambahkan ketergantungan pada hibah itu sendiri, seperti yang ditunjukkan di sini. Meskipun nilai pengembalian metode hibah biasanya dibuang, setiap metode hibah sebenarnya mengembalikan objek`iam.Grant`.

**Example**  

```
const grant = bucket.grants.read(lambda);
const custom = new CustomResource(...);
custom.node.addDependency(grant);
```

```
const grant = bucket.grants.read(lambda);
const custom = new CustomResource(...);
custom.node.addDependency(grant);
```

```
grant = bucket.grants.read(function)
custom = CustomResource(...)
custom.node.add_dependency(grant)
```

```
Grant grant = bucket.getGrants().read(function);
CustomResource custom = new CustomResource(...);
custom.node.addDependency(grant);
```

```
var grant = bucket.Grants.Read(function);
var custom = new CustomResource(...);
custom.node.AddDependency(grant);
```

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

Paket IAM berisi [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html)konstruksi yang mewakili peran IAM. Kode berikut menciptakan peran baru, mempercayai EC2 layanan Amazon.

**Example**  

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

const role = new iam.Role(this, 'Role', {
  assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),   // required
});
```

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

const role = new iam.Role(this, 'Role', {
  assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com')   // required
});
```

```
import aws_cdk.aws_iam as iam

role = iam.Role(self, "Role",
          assumed_by=iam.ServicePrincipal("ec2.amazonaws.com")) # required
```

```
import software.amazon.awscdk.services.iam.Role;
import software.amazon.awscdk.services.iam.ServicePrincipal;

Role role = Role.Builder.create(this, "Role")
        .assumedBy(new ServicePrincipal("ec2.amazonaws.com")).build();
```

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

var role = new Role(this, "Role", new RoleProps
{
    AssumedBy = new ServicePrincipal("ec2.amazonaws.com"),   // required
});
```

Anda dapat menambahkan izin ke peran dengan memanggil [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#addwbrtowbrpolicystatement](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#addwbrtowbrpolicystatement)metode peran (Python`add_to_policy`:), meneruskan [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html)sebuah yang mendefinisikan aturan yang akan ditambahkan. Pernyataan ditambahkan ke kebijakan default peran; jika tidak ada, satu akan dibuat.

Contoh berikut menambahkan pernyataan `Deny` kebijakan untuk peran untuk tindakan `ec2:SomeAction` dan `s3:AnotherAction` sumber daya `bucket` dan `otherRole` (Python:`other_role`), dengan syarat bahwa layanan resmi adalah. AWS CodeBuild

**Example**  

```
role.addToPolicy(new iam.PolicyStatement({
  effect: iam.Effect.DENY,
  resources: [bucket.bucketArn, otherRole.roleArn],
  actions: ['ec2:SomeAction', 's3:AnotherAction'],
  conditions: {StringEquals: {
    'ec2:AuthorizedService': 'codebuild.amazonaws.com',
}}}));
```

```
role.addToPolicy(new iam.PolicyStatement({
  effect: iam.Effect.DENY,
  resources: [bucket.bucketArn, otherRole.roleArn],
  actions: ['ec2:SomeAction', 's3:AnotherAction'],
  conditions: {StringEquals: {
    'ec2:AuthorizedService': 'codebuild.amazonaws.com'
}}}));
```

```
role.add_to_policy(iam.PolicyStatement(
    effect=iam.Effect.DENY,
    resources=[bucket.bucket_arn, other_role.role_arn],
    actions=["ec2:SomeAction", "s3:AnotherAction"],
    conditions={"StringEquals": {
        "ec2:AuthorizedService": "codebuild.amazonaws.com"}}
))
```

```
role.addToPolicy(PolicyStatement.Builder.create()
        .effect(Effect.DENY)
        .resources(Arrays.asList(bucket.getBucketArn(), otherRole.getRoleArn()))
        .actions(Arrays.asList("ec2:SomeAction", "s3:AnotherAction"))
        .conditions(java.util.Map.of(    // Map.of requires Java 9 or later
            "StringEquals", java.util.Map.of(
                "ec2:AuthorizedService", "codebuild.amazonaws.com")))
        .build());
```

```
role.AddToPolicy(new PolicyStatement(new PolicyStatementProps
{
    Effect = Effect.DENY,
    Resources = new string[] { bucket.BucketArn, otherRole.RoleArn },
    Actions = new string[] { "ec2:SomeAction", "s3:AnotherAction" },
    Conditions = new Dictionary<string, object>
    {
        ["StringEquals"] = new Dictionary<string, string>
        {
            ["ec2:AuthorizedService"] = "codebuild.amazonaws.com"
        }
    }
}));
```

Pada contoh sebelumnya, kita telah membuat [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html)inline baru dengan panggilan ([https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#addwbrtowbrpolicystatement](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#addwbrtowbrpolicystatement)Python:). `add_to_policy` Anda juga dapat meneruskan pernyataan kebijakan yang ada atau yang telah Anda modifikasi. [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html)Objek memiliki [banyak metode](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html#methods) untuk menambahkan prinsip, sumber daya, kondisi, dan tindakan.

Jika Anda menggunakan konstruksi yang membutuhkan peran agar berfungsi dengan benar, Anda dapat melakukan salah satu hal berikut:
+ Lewati peran yang ada saat membuat instance objek konstruksi.
+ Biarkan konstruksi menciptakan peran baru untuk Anda, mempercayai prinsip layanan yang tepat. Contoh berikut menggunakan konstruksi seperti: CodeBuild proyek.

**Example**  

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

// imagine roleOrUndefined is a function that might return a Role object
// under some conditions, and undefined under other conditions
const someRole: iam.IRole | undefined = roleOrUndefined();

const project = new codebuild.Project(this, 'Project', {
  // if someRole is undefined, the Project creates a new default role,
  // trusting the codebuild.amazonaws.com service principal
  role: someRole,
});
```

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

// imagine roleOrUndefined is a function that might return a Role object
// under some conditions, and undefined under other conditions
const someRole = roleOrUndefined();

const project = new codebuild.Project(this, 'Project', {
  // if someRole is undefined, the Project creates a new default role,
  // trusting the codebuild.amazonaws.com service principal
  role: someRole
});
```

```
import aws_cdk.aws_codebuild as codebuild

# imagine role_or_none is a function that might return a Role object
# under some conditions, and None under other conditions
some_role = role_or_none();

project = codebuild.Project(self, "Project",
# if role is None, the Project creates a new default role,
# trusting the codebuild.amazonaws.com service principal
role=some_role)
```

```
import software.amazon.awscdk.services.iam.Role;
import software.amazon.awscdk.services.codebuild.Project;

// imagine roleOrNull is a function that might return a Role object
// under some conditions, and null under other conditions
Role someRole = roleOrNull();

// if someRole is null, the Project creates a new default role,
// trusting the codebuild.amazonaws.com service principal
Project project = Project.Builder.create(this, "Project")
        .role(someRole).build();
```

```
using Amazon.CDK.AWS.CodeBuild;

// imagine roleOrNull is a function that might return a Role object
// under some conditions, and null under other conditions
var someRole = roleOrNull();

// if someRole is null, the Project creates a new default role,
// trusting the codebuild.amazonaws.com service principal
var project = new Project(this, "Project", new ProjectProps
{
    Role = someRole
});
```

Setelah objek dibuat, peran (apakah peran diteruskan atau peran default yang dibuat oleh konstruksi) tersedia sebagai properti`role`. Namun, properti ini tidak tersedia pada sumber daya eksternal. Oleh karena itu, konstruksi ini memiliki metode `addToRolePolicy` (Python`add_to_role_policy`:).

Metode ini tidak melakukan apa-apa jika konstruksinya adalah sumber daya eksternal, dan ia memanggil metode `addToPolicy` (Python`add_to_policy`:) dari properti sebaliknya`role`. Ini menghemat kesulitan menangani kasus yang tidak ditentukan secara eksplisit.

Contoh berikut menunjukkan:

**Example**  

```
// project is imported into the CDK application
const project = codebuild.Project.fromProjectName(this, 'Project', 'ProjectName');

// project is imported, so project.role is undefined, and this call has no effect
project.addToRolePolicy(new iam.PolicyStatement({
  effect: iam.Effect.ALLOW,   // ... and so on defining the policy
}));
```

```
// project is imported into the CDK application
const project = codebuild.Project.fromProjectName(this, 'Project', 'ProjectName');

// project is imported, so project.role is undefined, and this call has no effect
project.addToRolePolicy(new iam.PolicyStatement({
  effect: iam.Effect.ALLOW   // ... and so on defining the policy
}));
```

```
# project is imported into the CDK application
project = codebuild.Project.from_project_name(self, 'Project', 'ProjectName')

# project is imported, so project.role is undefined, and this call has no effect
project.add_to_role_policy(iam.PolicyStatement(
  effect=iam.Effect.ALLOW,   # ... and so on defining the policy
  )
)
```

```
// project is imported into the CDK application
Project project = Project.fromProjectName(this, "Project", "ProjectName");

// project is imported, so project.getRole() is null, and this call has no effect
project.addToRolePolicy(PolicyStatement.Builder.create()
        .effect(Effect.ALLOW)   // .. and so on defining the policy
        .build();
)
```

```
// project is imported into the CDK application
var project = Project.FromProjectName(this, "Project", "ProjectName");

// project is imported, so project.role is null, and this call has no effect
project.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps
{
    Effect = Effect.ALLOW, // ... and so on defining the policy
}));
```

## Kebijakan sumber daya
<a name="permissions-resource-policies"></a>

Beberapa sumber daya AWS, seperti bucket Amazon S3 dan peran IAM, juga memiliki kebijakan sumber daya. Konstruksi ini memiliki `addToResourcePolicy` metode (Python`add_to_resource_policy`:), yang mengambil [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html)sebagai argumennya. Setiap pernyataan kebijakan yang ditambahkan ke kebijakan sumber daya harus menentukan setidaknya satu prinsipal.

Dalam contoh berikut, [bucket Amazon S3](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) `bucket` memberikan peran dengan `s3:SomeAction` izin untuk dirinya sendiri.

**Example**  

```
bucket.addToResourcePolicy(new iam.PolicyStatement({
  effect: iam.Effect.ALLOW,
  actions: ['s3:SomeAction'],
  resources: [bucket.bucketArn],
  principals: [role]
}));
```

```
bucket.addToResourcePolicy(new iam.PolicyStatement({
  effect: iam.Effect.ALLOW,
  actions: ['s3:SomeAction'],
  resources: [bucket.bucketArn],
  principals: [role]
}));
```

```
bucket.add_to_resource_policy(iam.PolicyStatement(
    effect=iam.Effect.ALLOW,
    actions=["s3:SomeAction"],
    resources=[bucket.bucket_arn],
    principals=role))
```

```
bucket.addToResourcePolicy(PolicyStatement.Builder.create()
        .effect(Effect.ALLOW)
        .actions(Arrays.asList("s3:SomeAction"))
        .resources(Arrays.asList(bucket.getBucketArn()))
        .principals(Arrays.asList(role))
        .build());
```

```
bucket.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps
{
    Effect = Effect.ALLOW,
    Actions = new string[] { "s3:SomeAction" },
    Resources = new string[] { bucket.BucketArn },
    Principals = new IPrincipal[] { role }
}));
```

## Menggunakan objek IAM eksternal
<a name="permissions-existing"></a>

Jika Anda telah menetapkan pengguna, prinsipal, grup, atau peran IAM di luar aplikasi AWS CDK, Anda dapat menggunakan objek IAM tersebut di aplikasi CDK Anda AWS . Untuk melakukannya, buat referensi untuk itu menggunakan ARN atau namanya. (Gunakan nama untuk pengguna, grup, dan peran.) Referensi yang dikembalikan kemudian dapat digunakan untuk memberikan izin atau untuk membuat pernyataan kebijakan seperti yang dijelaskan sebelumnya.
+ Untuk pengguna, hubungi [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html#static-fromwbruserwbrarnscope-id-userarn](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html#static-fromwbruserwbrarnscope-id-userarn)atau [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html#static-fromwbruserwbrnamescope-id-username](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.User.html#static-fromwbruserwbrnamescope-id-username). `User.fromUserAttributes()`juga tersedia, tetapi saat ini menyediakan fungsionalitas yang sama seperti`User.fromUserArn()`.
+ Untuk prinsipal, buat instance objek. [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ArnPrincipal.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ArnPrincipal.html)
+ Untuk grup, hubungi [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html#static-fromwbrgroupwbrarnscope-id-grouparn](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html#static-fromwbrgroupwbrarnscope-id-grouparn)atau [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html#static-fromwbrgroupwbrnamescope-id-groupname](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Group.html#static-fromwbrgroupwbrnamescope-id-groupname).
+ Untuk peran, hubungi [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#static-fromwbrrolewbrarnscope-id-rolearn-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#static-fromwbrrolewbrarnscope-id-rolearn-options)atau [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#static-fromwbrrolewbrnamescope-id-rolename](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html#static-fromwbrrolewbrnamescope-id-rolename).

Kebijakan (termasuk kebijakan terkelola) dapat digunakan dengan cara yang sama menggunakan metode berikut. Anda dapat menggunakan referensi ke objek ini di mana pun kebijakan IAM diperlukan.
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Policy.html#static-fromwbrpolicywbrnamescope-id-policyname](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Policy.html#static-fromwbrpolicywbrnamescope-id-policyname) 
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrmanagedwbrpolicywbrarnscope-id-managedpolicyarn](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrmanagedwbrpolicywbrarnscope-id-managedpolicyarn) 
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrmanagedwbrpolicywbrnamescope-id-managedpolicyname](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrmanagedwbrpolicywbrnamescope-id-managedpolicyname) 
+  [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrawswbrmanagedwbrpolicywbrnamemanagedpolicyname](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.ManagedPolicy.html#static-fromwbrawswbrmanagedwbrpolicywbrnamemanagedpolicyname) 

**catatan**  
Seperti semua referensi ke AWS sumber daya eksternal, Anda tidak dapat memodifikasi objek IAM eksternal di aplikasi CDK Anda.

# Nilai konteks dan AWS CDK
<a name="context"></a>

Nilai konteks adalah pasangan nilai kunci yang dapat dikaitkan dengan aplikasi, tumpukan, atau konstruksi. Mereka dapat diberikan ke aplikasi Anda dari file (biasanya salah satu `cdk.json` atau `cdk.context.json` di direktori proyek Anda) atau pada baris perintah.

CDK Toolkit menggunakan konteks untuk menyimpan nilai yang diambil dari AWS akun Anda selama sintesis. Nilai termasuk Availability Zone di akun Anda atau ID Amazon Machine Image (AMI) yang saat ini tersedia untuk instans Amazon EC2. Karena nilai-nilai ini disediakan oleh AWS akun Anda, mereka dapat berubah di antara proses aplikasi CDK Anda. Ini menjadikan mereka sumber potensial perubahan yang tidak diinginkan. Perilaku caching CDK Toolkit “membekukan” nilai-nilai ini untuk aplikasi CDK Anda hingga Anda memutuskan untuk menerima nilai baru.

Bayangkan skenario berikut tanpa cache konteks. Katakanlah Anda menentukan “Amazon Linux terbaru” sebagai AMI untuk instans Amazon EC2 Anda, dan versi baru AMI ini dirilis. Kemudian, lain kali Anda menerapkan tumpukan CDK Anda, instance Anda yang sudah diterapkan akan menggunakan AMI yang sudah ketinggalan zaman (“salah”) dan perlu ditingkatkan. Memutakhirkan akan mengakibatkan penggantian semua instance Anda yang ada dengan yang baru, yang mungkin tidak terduga dan tidak diinginkan.

Sebagai gantinya, CDK mencatat akun Anda yang tersedia AMIs di `cdk.context.json` file proyek Anda, dan menggunakan nilai tersimpan untuk operasi sintesis masa depan. Dengan cara ini, daftar AMIs tidak lagi menjadi sumber perubahan potensial. Anda juga dapat yakin bahwa tumpukan Anda akan selalu disintesis ke templat yang sama AWS CloudFormation .

Tidak semua nilai konteks adalah nilai cache dari AWS lingkungan Anda. [AWS Bendera fitur CDK](featureflags.md) juga merupakan nilai konteks. Anda juga dapat membuat nilai konteks Anda sendiri untuk digunakan oleh aplikasi atau konstruksi Anda.

Kunci konteks adalah string. Nilai dapat berupa jenis apa pun yang didukung oleh JSON: angka, string, array, atau objek.

**Tip**  
Jika konstruksi Anda membuat nilai konteksnya sendiri, sertakan nama paket perpustakaan Anda di kuncinya sehingga tidak akan bertentangan dengan nilai konteks paket lain.

Banyak nilai konteks dikaitkan dengan AWS lingkungan tertentu, dan aplikasi CDK tertentu dapat digunakan di lebih dari satu lingkungan. Kunci untuk nilai tersebut mencakup AWS akun dan Wilayah sehingga nilai dari lingkungan yang berbeda tidak bertentangan.

Kunci konteks berikut menggambarkan format yang digunakan oleh AWS CDK, termasuk akun dan Wilayah.

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

**penting**  
Nilai konteks cache dikelola oleh AWS CDK dan konstruksinya, termasuk konstruksi yang dapat Anda tulis. Jangan menambahkan atau mengubah nilai konteks cache dengan mengedit file secara manual. Akan tetapi, berguna untuk meninjau `cdk.context.json` sesekali untuk melihat nilai apa yang sedang di-cache. Nilai konteks yang tidak mewakili nilai cache harus disimpan di bawah `context` kunci. `cdk.json` Dengan cara ini, mereka tidak akan dihapus ketika nilai cache dihapus.

## Sumber nilai konteks
<a name="context-construct"></a>

Nilai konteks dapat diberikan ke aplikasi AWS CDK Anda dengan enam cara berbeda:
+ Secara otomatis dari AWS akun saat ini.
+ Melalui `--context` opsi ke `cdk` perintah. (Nilai-nilai ini selalu string.)
+ Dalam `cdk.context.json` file proyek.
+ Di `context` kunci `cdk.json` file proyek.
+ Di `context` kunci `~/.cdk.json` file Anda.
+ Di aplikasi AWS CDK Anda menggunakan `construct.node.setContext()` metode ini.

File proyek `cdk.context.json` adalah tempat AWS CDK menyimpan nilai konteks yang diambil dari akun Anda. AWS Praktik ini menghindari perubahan tak terduga pada penerapan Anda saat, misalnya, Availability Zone baru diperkenalkan. AWS CDK tidak menulis data konteks ke file lain yang terdaftar.

**penting**  
Karena mereka adalah bagian dari status aplikasi Anda, `cdk.json` dan `cdk.context.json` harus berkomitmen untuk kontrol sumber bersama dengan kode sumber aplikasi lainnya. Jika tidak, penerapan di lingkungan lain (misalnya, pipeline CI) mungkin menghasilkan hasil yang tidak konsisten.

Nilai-nilai konteks tercakup pada konstruksi yang menciptakannya; mereka terlihat oleh konstruksi anak, tetapi tidak untuk orang tua atau saudara kandung. Nilai konteks yang ditetapkan oleh AWS CDK Toolkit (`cdk`perintah) dapat diatur secara otomatis, dari file, atau dari opsi. `--context` Nilai konteks dari sumber-sumber ini secara implisit ditetapkan pada konstruksi. `App` Oleh karena itu, mereka terlihat oleh setiap konstruksi di setiap tumpukan di aplikasi.

Aplikasi Anda dapat membaca nilai konteks menggunakan `construct.node.tryGetContext` metode ini. Jika entri yang diminta tidak ditemukan pada konstruksi saat ini atau salah satu induknya, hasilnya adalah`undefined`. (Atau, hasilnya bisa setara dengan bahasa Anda, seperti `None` di Python.)

## Metode konteks
<a name="context-methods"></a>

 AWS CDK mendukung beberapa metode konteks yang memungkinkan aplikasi AWS CDK memperoleh informasi kontekstual dari lingkungan. AWS Misalnya, Anda bisa mendapatkan daftar Availability Zone yang tersedia di AWS akun dan Wilayah tertentu, menggunakan [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones)metode ini.

Berikut ini adalah metode konteksnya:

 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_route53.HostedZone.html#static-fromwbrlookupscope-id-query](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_route53.HostedZone.html#static-fromwbrlookupscope-id-query)   
Mendapatkan zona yang dihosting di akun Anda.

 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html#availabilityzones)   
Mendapatkan Availability Zone yang didukung.

 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameter.html#static-valuewbrfromwbrlookupscope-parametername](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ssm.StringParameter.html#static-valuewbrfromwbrlookupscope-parametername)   
Mendapat nilai dari Amazon EC2 Systems Manager Parameter Store Wilayah saat ini.

 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html#static-fromwbrlookupscope-id-options)   
Mendapatkan Amazon Virtual Private Clouds yang ada di akun Anda.

 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.LookupMachineImage.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.LookupMachineImage.html)   
Mencari image mesin untuk digunakan dengan instance NAT di Amazon Virtual Private Cloud.

Jika nilai konteks yang diperlukan tidak tersedia, aplikasi AWS CDK akan memberi tahu CDK Toolkit bahwa informasi konteks tidak ada. Selanjutnya, CLI menanyakan AWS akun saat ini untuk informasi dan menyimpan informasi konteks yang dihasilkan dalam file. `cdk.context.json` Kemudian, ia mengeksekusi aplikasi AWS CDK lagi dengan nilai konteks.

## Melihat dan mengelola konteks
<a name="context-viewing"></a>

Gunakan `cdk context` perintah untuk melihat dan mengelola informasi dalam `cdk.context.json` file Anda. Untuk melihat informasi ini, gunakan `cdk context` perintah tanpa opsi apa pun. Outputnya harus seperti berikut ini.

```
Context found in cdk.json:

┌───┬─────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────┐
│ # │ Key                                                         │ Value                                                   │
├───┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤
│ 1 │ availability-zones:account=123456789012:region=eu-central-1 │ [ "eu-central-1a", "eu-central-1b", "eu-central-1c" ]   │
├───┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤
│ 2 │ availability-zones:account=123456789012:region=eu-west-1    │ [ "eu-west-1a", "eu-west-1b", "eu-west-1c" ]            │
└───┴─────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────┘

Run

  cdk context --reset KEY_OR_NUMBER

 to remove a context key. If it is a cached value, it will be refreshed on the next

  cdk synth

.
```

Untuk menghapus nilai konteks, jalankan`cdk context --reset`, tentukan kunci atau angka nilai yang sesuai. Contoh berikut menghapus nilai yang sesuai dengan kunci kedua dalam contoh sebelumnya. Nilai ini mewakili daftar Availability Zone di Wilayah Eropa (Irlandia).

```
cdk context --reset 2
```

```
Context value
availability-zones:account=123456789012:region=eu-west-1
reset. It will be refreshed on the next SDK synthesis run.
```

Oleh karena itu, jika Anda ingin memperbarui ke versi terbaru AMI Amazon Linux, gunakan contoh sebelumnya untuk melakukan pembaruan terkontrol dari nilai konteks dan mengatur ulang. Kemudian, sintesis dan terapkan aplikasi Anda lagi.

```
$ cdk synth
```

Untuk menghapus semua nilai konteks yang disimpan untuk aplikasi Anda, jalankan`cdk context --clear`, sebagai berikut.

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

Hanya nilai konteks yang disimpan di `cdk.context.json` dapat diatur ulang atau dihapus. AWS CDK tidak menyentuh nilai konteks lainnya. Oleh karena itu, untuk melindungi nilai konteks agar tidak disetel ulang menggunakan perintah ini, Anda dapat menyalin nilainya`cdk.json`.

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

Gunakan opsi `--context` (`-c`singkatnya) untuk meneruskan nilai konteks runtime ke aplikasi CDK Anda selama sintesis atau penerapan.

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

Untuk menentukan beberapa nilai konteks, ulangi `--context` opsi beberapa kali, berikan satu pasangan kunci-nilai setiap kali.

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

Saat mensintesis beberapa tumpukan, nilai konteks yang ditentukan diteruskan ke semua tumpukan. Untuk memberikan nilai konteks yang berbeda ke tumpukan individu, gunakan kunci yang berbeda untuk nilai, atau gunakan beberapa `cdk synth` atau `cdk deploy` perintah.

Nilai konteks yang diteruskan dari baris perintah selalu string. Jika nilai biasanya dari beberapa jenis lain, kode Anda harus siap untuk mengonversi atau mengurai nilai. Anda mungkin memiliki nilai konteks non-string yang disediakan dengan cara lain (misalnya, dalam`cdk.context.json`). Untuk memastikan nilai semacam ini berfungsi seperti yang diharapkan, konfirmasikan bahwa nilainya adalah string sebelum mengonversinya.

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

Berikut ini adalah contoh penggunaan VPC Amazon yang ada menggunakan konteks AWS CDK.

**Example**  

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

export class ExistsVpcStack extends cdk.Stack {

  constructor(scope: Construct, id: string, props?: cdk.StackProps) {

    super(scope, id, props);

    const vpcid = this.node.tryGetContext('vpcid');
    const vpc = ec2.Vpc.fromLookup(this, 'VPC', {
      vpcId: vpcid,
    });

    const pubsubnets = vpc.selectSubnets({subnetType: ec2.SubnetType.PUBLIC});

    new cdk.CfnOutput(this, 'publicsubnets', {
      value: pubsubnets.subnetIds.toString(),
    });
  }
}
```

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

class ExistsVpcStack extends cdk.Stack {

  constructor(scope, id, props) {

    super(scope, id, props);

    const vpcid = this.node.tryGetContext('vpcid');
    const vpc = ec2.Vpc.fromLookup(this, 'VPC', {
      vpcId: vpcid
    });

    const pubsubnets = vpc.selectSubnets({subnetType: ec2.SubnetType.PUBLIC});

    new cdk.CfnOutput(this, 'publicsubnets', {
      value: pubsubnets.subnetIds.toString()
    });
  }
}

module.exports = { ExistsVpcStack }
```

```
import aws_cdk as cdk
import aws_cdk.aws_ec2 as ec2
from constructs import Construct

class ExistsVpcStack(cdk.Stack):

    def __init__(scope: Construct, id: str, **kwargs):

        super().__init__(scope, id, **kwargs)

        vpcid = self.node.try_get_context("vpcid")
        vpc = ec2.Vpc.from_lookup(self, "VPC", vpc_id=vpcid)

        pubsubnets = vpc.select_subnets(subnetType=ec2.SubnetType.PUBLIC)

        cdk.CfnOutput(self, "publicsubnets",
            value=pubsubnets.subnet_ids.to_string())
```

```
import software.amazon.awscdk.CfnOutput;

import software.amazon.awscdk.services.ec2.Vpc;
import software.amazon.awscdk.services.ec2.VpcLookupOptions;
import software.amazon.awscdk.services.ec2.SelectedSubnets;
import software.amazon.awscdk.services.ec2.SubnetSelection;
import software.amazon.awscdk.services.ec2.SubnetType;
import software.constructs.Construct;

public class ExistsVpcStack extends Stack {
    public ExistsVpcStack(Construct context, String id) {
        this(context, id, null);
    }

    public ExistsVpcStack(Construct context, String id, StackProps props) {
        super(context, id, props);

        String vpcId = (String)this.getNode().tryGetContext("vpcid");
        Vpc vpc = (Vpc)Vpc.fromLookup(this, "VPC", VpcLookupOptions.builder()
                .vpcId(vpcId).build());

        SelectedSubnets pubSubNets = vpc.selectSubnets(SubnetSelection.builder()
                .subnetType(SubnetType.PUBLIC).build());

        CfnOutput.Builder.create(this, "publicsubnets")
                .value(pubSubNets.getSubnetIds().toString()).build();
    }
}
```

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

class ExistsVpcStack : Stack
{
    public ExistsVpcStack(Construct scope, string id, StackProps props) : base(scope, id, props)
    {
        var vpcId = (string)this.Node.TryGetContext("vpcid");
        var vpc = Vpc.FromLookup(this, "VPC", new VpcLookupOptions
        {
            VpcId = vpcId
        });

        SelectedSubnets pubSubNets = vpc.SelectSubnets([new SubnetSelection
        {
            SubnetType = SubnetType.PUBLIC
        }]);

        new CfnOutput(this, "publicsubnets", new CfnOutputProps {
            Value = pubSubNets.SubnetIds.ToString()
        });
    }
}
```

Anda dapat menggunakan `cdk diff` untuk melihat efek dari meneruskan nilai konteks pada baris perintah:

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

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

Nilai konteks yang dihasilkan dapat dilihat seperti yang ditunjukkan di sini.

```
$ cdk context -j
```

```
{
  "vpc-provider:account=123456789012:filter.vpc-id=vpc-0cb9c31031d0d3e22:region=us-east-1": {
    "vpcId": "vpc-0cb9c31031d0d3e22",
    "availabilityZones": [
      "us-east-1a",
      "us-east-1b"
    ],
    "privateSubnetIds": [
      "subnet-03ecfc033225be285",
      "subnet-0cded5da53180ebfa"
    ],
    "privateSubnetNames": [
      "Private"
    ],
    "privateSubnetRouteTableIds": [
      "rtb-0e955393ced0ada04",
      "rtb-05602e7b9f310e5b0"
    ],
    "publicSubnetIds": [
      "subnet-06e0ea7dd302d3e8f",
      "subnet-01fc0acfb58f3128f"
    ],
    "publicSubnetNames": [
      "Public"
    ],
    "publicSubnetRouteTableIds": [
      "rtb-00d1fdfd823c82289",
      "rtb-04bb1969b42969bcb"
    ]
  }
}
```

# AWS Bendera fitur CDK
<a name="featureflags"></a>

 AWS CDK menggunakan *flag fitur* untuk mengaktifkan perilaku yang berpotensi melanggar dalam rilis. Bendera disimpan sebagai [nilai Konteks dan nilai AWS CDK](context.md) di `cdk.json` (atau`~/.cdk.json`). Mereka tidak dihapus oleh `cdk context --clear` perintah `cdk context --reset` atau.

Bendera fitur dinonaktifkan secara default. Proyek yang ada yang tidak menentukan bendera akan terus berfungsi seperti sebelumnya dengan rilis AWS CDK nanti. Proyek baru yang dibuat menggunakan flag `cdk init` include yang memungkinkan semua fitur yang tersedia dalam rilis yang membuat proyek. Edit `cdk.json` untuk menonaktifkan bendera apa pun yang Anda sukai perilaku sebelumnya. Anda juga dapat menambahkan flag untuk mengaktifkan perilaku baru setelah memutakhirkan CDK. AWS 

[Daftar semua flag fitur saat ini dapat ditemukan di GitHub repositori AWS CDK di Feature\$1flags.md.](https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md) Lihat `CHANGELOG` dalam rilis tertentu untuk deskripsi bendera fitur baru yang ditambahkan dalam rilis itu.

## Kembali ke perilaku v1
<a name="featureflags-disabling"></a>

Di CDK v2, default untuk beberapa flag fitur telah diubah sehubungan dengan v1. Anda dapat menyetelnya kembali `false` untuk kembali ke perilaku AWS CDK v1 tertentu. Gunakan `cdk diff` perintah untuk memeriksa perubahan pada template yang disintesis untuk melihat apakah salah satu flag ini diperlukan.

 `@aws-cdk/core:newStyleStackSynthesis`   
Gunakan metode sintesis tumpukan baru, yang mengasumsikan sumber daya bootstrap dengan nama terkenal. Membutuhkan [bootstrap modern](bootstrapping.md), tetapi pada gilirannya memungkinkan CI/CD melalui CDK [Pipelines dan penyebaran lintas akun di luar kotak](cdk-pipeline.md).

 `@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId`   
Jika aplikasi Anda menggunakan beberapa kunci API Amazon API Gateway dan mengaitkannya dengan paket penggunaan.

 `@aws-cdk/aws-rds:lowercaseDbIdentifier`   
Jika aplikasi Anda menggunakan instans database Amazon RDS atau cluster database, dan secara eksplisit menentukan pengenal untuk ini.

 `@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021`   
Jika aplikasi Anda menggunakan kebijakan keamanan TLS\$1V1\$12\$12019 dengan distribusi Amazon. CloudFront CDK v2 menggunakan kebijakan keamanan TLSv1 .2\$12021 secara default.

 `@aws-cdk/core:stackRelativeExports`   
Jika aplikasi Anda menggunakan beberapa tumpukan dan Anda merujuk ke sumber daya dari satu tumpukan di tumpukan lain, ini menentukan apakah jalur absolut atau relatif digunakan untuk membangun ekspor AWS CloudFormation .

 `@aws-cdk/aws-lambda:recognizeVersionProps`   
Jika disetel ke`false`, CDK menyertakan metadata saat mendeteksi apakah fungsi Lambda telah berubah. Ini dapat menyebabkan kegagalan penerapan ketika hanya metadata yang berubah, karena versi duplikat tidak diizinkan. Tidak perlu mengembalikan bendera ini jika Anda telah membuat setidaknya satu perubahan ke semua Fungsi Lambda di aplikasi Anda.

Sintaks untuk mengembalikan bendera ini ditampilkan di sini`cdk.json`.

```
{
  "context": {
    "@aws-cdk/core:newStyleStackSynthesis": false,
    "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": false,
    "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": false,
    "@aws-cdk/aws-rds:lowercaseDbIdentifier": false,
    "@aws-cdk/core:stackRelativeExports": false,
    "@aws-cdk/aws-lambda:recognizeVersionProps": false
  }
}
```

# Aspek dan AWS CDK
<a name="aspects"></a>

Aspek adalah cara untuk menerapkan operasi ke semua konstruksi dalam lingkup tertentu. Aspek dapat memodifikasi konstruksi, seperti dengan menambahkan tag. Atau bisa memverifikasi sesuatu tentang status konstruksi, seperti memastikan bahwa semua ember dienkripsi.

Untuk menerapkan aspek ke konstruksi dan semua konstruksi dalam lingkup yang sama, panggil ` [Aspects](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Aspects.html#static-ofscope).of(<SCOPE>).add()` dengan aspek baru, seperti yang ditunjukkan pada contoh berikut.

**Example**  

```
Aspects.of(myConstruct).add(new SomeAspect(...));
```

```
Aspects.of(myConstruct).add(new SomeAspect(...));
```

```
Aspects.of(my_construct).add(SomeAspect(...))
```

```
Aspects.of(myConstruct).add(new SomeAspect(...));
```

```
Aspects.Of(myConstruct).add(new SomeAspect(...));
```

```
awscdk.Aspects_Of(stack).Add(awscdk.NewTag(...))
```

 AWS CDK menggunakan aspek untuk [menandai sumber daya](tagging.md), tetapi kerangka kerja juga dapat digunakan untuk tujuan lain. Misalnya, Anda dapat menggunakannya untuk memvalidasi atau mengubah AWS CloudFormation sumber daya yang ditentukan untuk Anda oleh konstruksi tingkat yang lebih tinggi.

## Aspek vs Mixins
<a name="aspects-vs-mixins"></a>

Aspek dan [Mixin](mixins.md) keduanya memodifikasi konstruksi, tetapi mereka berbeda dalam kapan dan bagaimana mereka diterapkan:


| Fitur | Aspek | Mixin | 
| --- | --- | --- | 
|   **Saat diterapkan**   |  Selama sintesis, setelah semua kode lain berjalan.  |  Segera ketika `.with()` dipanggil.  | 
|   **Lingkup**   |  Semua konstruksi dalam lingkup tertentu, termasuk konstruksi yang ditambahkan nanti.  |  Hanya konstruksi yang Anda terapkan secara eksplisit.  | 
|   **Gaya**   |  Deklaratif — Anda menetapkan aturan dan CDK menerapkannya.  |  Imperatif — Anda memilih apa yang akan diterapkan dan di mana.  | 
|   **Terbaik untuk**   |  Validasi, kepatuhan, penandaan, kebijakan luas.  |  Menambahkan fitur spesifik ke sumber daya individu.  | 

Gunakan Aspek saat Anda ingin menegakkan aturan di seluruh aplikasi Anda atau memvalidasi bahwa konstruksi memenuhi kriteria tertentu. Gunakan Mixins saat Anda ingin menambahkan fitur tertentu ke konstruksi tertentu.

Aspek dan Mixin dapat digunakan bersama. Misalnya, Anda dapat menggunakan Mixin untuk mengonfigurasi sumber daya individual dan Aspek untuk memvalidasi bahwa semua sumber daya dalam tumpukan memenuhi persyaratan keamanan organisasi Anda.

## Aspek secara detail
<a name="aspects-detail"></a>

Aspek menggunakan [pola pengunjung](https://en.wikipedia.org/wiki/Visitor_pattern). Aspek adalah kelas yang mengimplementasikan antarmuka berikut.

**Example**  

```
interface IAspect {
   visit(node: IConstruct): void;}
```
JavaScript tidak memiliki antarmuka sebagai fitur bahasa. Oleh karena itu, sebuah aspek hanyalah sebuah instance dari kelas yang memiliki `visit` metode yang menerima node yang akan dioperasikan.
Python tidak memiliki antarmuka sebagai fitur bahasa. Oleh karena itu, sebuah aspek hanyalah sebuah instance dari kelas yang memiliki `visit` metode yang menerima node yang akan dioperasikan.

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

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

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

Saat Anda menelepon`Aspects.of(<SCOPE>).add(…​)`, konstruksi menambahkan aspek ke daftar aspek internal. Anda dapat memperoleh daftar dengan`Aspects.of(<SCOPE>)`.

Selama [fase persiapan](deploy.md#deploy-how-synth-app), AWS CDK memanggil `visit` metode objek untuk konstruksi dan masing-masing anaknya dalam urutan top-down.

`visit`Metode ini bebas untuk mengubah apa pun dalam konstruksi. Dalam bahasa yang diketik dengan kuat, lemparkan konstruksi yang diterima ke tipe yang lebih spesifik sebelum mengakses properti atau metode khusus konstruksi.

Aspek tidak menyebar melintasi batas-batas `Stage` konstruksi, karena mandiri dan `Stages` tidak dapat diubah setelah definisi. Terapkan aspek pada `Stage` konstruksi itu sendiri (atau lebih rendah) jika Anda ingin mereka mengunjungi konstruksi di dalam. `Stage`

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

Contoh berikut memvalidasi bahwa semua bucket yang dibuat di tumpukan mengaktifkan versi. Aspek menambahkan anotasi kesalahan ke konstruksi yang gagal validasi. Hal ini mengakibatkan `synth` operasi gagal dan mencegah penerapan rakitan cloud yang dihasilkan.

**Example**  

```
class BucketVersioningChecker implements IAspect {
  public visit(node: IConstruct): void {
    // See that we're dealing with a CfnBucket
    if (node instanceof s3.CfnBucket) {

      // Check for versioning property, exclude the case where the property
      // can be a token (IResolvable).
      if (!node.versioningConfiguration
        || (!Tokenization.isResolvable(node.versioningConfiguration)
            && node.versioningConfiguration.status !== 'Enabled')) {
        Annotations.of(node).addError('Bucket versioning is not enabled');
      }
    }
  }
}

// Later, apply to the stack
Aspects.of(stack).add(new BucketVersioningChecker());
```

```
class BucketVersioningChecker {
   visit(node) {
    // See that we're dealing with a CfnBucket
    if ( node instanceof s3.CfnBucket) {

      // Check for versioning property, exclude the case where the property
      // can be a token (IResolvable).
      if (!node.versioningConfiguration
        || !Tokenization.isResolvable(node.versioningConfiguration)
            && node.versioningConfiguration.status !== 'Enabled')) {
        Annotations.of(node).addError('Bucket versioning is not enabled');
      }
    }
  }
}

// Later, apply to the stack
Aspects.of(stack).add(new BucketVersioningChecker());
```

```
@jsii.implements(cdk.IAspect)
class BucketVersioningChecker:

  def visit(self, node):
    # See that we're dealing with a CfnBucket
    if isinstance(node, s3.CfnBucket):

      # Check for versioning property, exclude the case where the property
      # can be a token (IResolvable).
      if (not node.versioning_configuration or
              not Tokenization.is_resolvable(node.versioning_configuration)
                  and node.versioning_configuration.status != "Enabled"):
          Annotations.of(node).add_error('Bucket versioning is not enabled')

# Later, apply to the stack
Aspects.of(stack).add(BucketVersioningChecker())
```

```
public class BucketVersioningChecker implements IAspect
{
    @Override
    public void visit(Construct node)
    {
        // See that we're dealing with a CfnBucket
        if (node instanceof CfnBucket)
        {
            CfnBucket bucket = (CfnBucket)node;
            Object versioningConfiguration = bucket.getVersioningConfiguration();
            if (versioningConfiguration == null ||
                    !Tokenization.isResolvable(versioningConfiguration.toString()) &&
                    !versioningConfiguration.toString().contains("Enabled"))
                Annotations.of(bucket.getNode()).addError("Bucket versioning is not enabled");
        }
    }
}

// Later, apply to the stack
Aspects.of(stack).add(new BucketVersioningChecker());
```

```
class BucketVersioningChecker : Amazon.Jsii.Runtime.Deputy.DeputyBase, IAspect
{
    public void Visit(IConstruct node)
    {
        // See that we're dealing with a CfnBucket
        if (node is CfnBucket)
        {
            var bucket = (CfnBucket)node;
            if (bucket.VersioningConfiguration is null ||
                    !Tokenization.IsResolvable(bucket.VersioningConfiguration) &&
                    !bucket.VersioningConfiguration.ToString().Contains("Enabled"))
                Annotations.Of(bucket.Node).AddError("Bucket versioning is not enabled");
        }
    }
}

// Later, apply to the stack
Aspects.Of(stack).add(new BucketVersioningChecker());
```