

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

# Sumber daya khusus yang didukung Lambda
<a name="template-custom-resources-lambda"></a>

Saat Anda mengaitkan fungsi Lambda dengan sumber daya khusus, fungsi tersebut akan dipanggil setiap kali sumber daya kustom dibuat, diperbarui, atau dihapus. CloudFormation memanggil API Lambda untuk memanggil fungsi dan meneruskan semua data permintaan (seperti jenis permintaan dan properti sumber daya) ke fungsi. Kekuatan dan kemampuan penyesuaian fungsi Lambda dalam kombinasi dengan CloudFormation memungkinkan berbagai skenario, seperti mencari IDs AMI secara dinamis selama pembuatan tumpukan, atau mengimplementasikan dan menggunakan fungsi utilitas, seperti fungsi pembalikan string.

Untuk pengenalan sumber daya khusus dan cara kerjanya, lihat[Cara kerja sumber daya kustom](template-custom-resources.md#how-custom-resources-work).

**Topics**
+ [Walkthrough: Buat mekanisme penundaan dengan sumber daya khusus yang didukung Lambda](walkthrough-lambda-backed-custom-resources.md)
+ [Modul `cfn-response`](cfn-lambda-function-code-cfnresponsemodule.md)

# Walkthrough: Buat mekanisme penundaan dengan sumber daya khusus yang didukung Lambda
<a name="walkthrough-lambda-backed-custom-resources"></a>

Panduan ini menunjukkan kepada Anda cara mengonfigurasi dan meluncurkan sumber daya kustom yang didukung Lambda menggunakan templat sampel. CloudFormation Template ini menciptakan mekanisme penundaan yang menjeda penerapan tumpukan untuk waktu yang ditentukan. Ini dapat berguna ketika Anda perlu memperkenalkan penundaan yang disengaja selama penyediaan sumber daya, seperti saat menunggu sumber daya stabil sebelum sumber daya dependen dibuat.

**catatan**  
Meskipun sumber daya kustom yang didukung Lambda sebelumnya direkomendasikan untuk mengambil IDs AMI, kami sekarang merekomendasikan penggunaan AWS Systems Manager parameter. Pendekatan ini membuat template Anda lebih dapat digunakan kembali dan lebih mudah dirawat. Untuk informasi selengkapnya, lihat [Dapatkan nilai plaintext dari Systems Manager Parameter Store](dynamic-references-ssm.md). 

**Topics**
+ [Ikhtisar](#walkthrough-lambda-backed-custom-resources-overview)
+ [Templat sampel](#walkthrough-lambda-backed-custom-resources-sample-template)
+ [Contoh panduan templat](#walkthrough-lambda-backed-custom-resources-sample-template-walkthrough)
+ [Prasyarat](#walkthrough-lambda-backed-custom-resources-prerequisites)
+ [Meluncurkan tumpukan](#walkthrough-lambda-backed-custom-resources-createfunction-createstack)
+ [Membersihkan sumber daya](#walkthrough-lambda-backed-custom-resources-createfunction-cleanup)
+ [Informasi Terkait](#w2aac11c45b9c24b9c23)

## Ikhtisar
<a name="walkthrough-lambda-backed-custom-resources-overview"></a>

Templat tumpukan sampel yang digunakan dalam panduan ini membuat sumber daya kustom yang didukung Lambda. Sumber daya khusus ini memperkenalkan penundaan yang dapat dikonfigurasi (60 detik secara default) selama pembuatan tumpukan. Penundaan terjadi selama pembaruan tumpukan hanya ketika properti sumber daya kustom diubah.

Template menyediakan sumber daya berikut:
+ sumber daya khusus,
+ fungsi Lambda, dan
+ peran IAM yang memungkinkan Lambda untuk menulis log ke. CloudWatch

Ini juga mendefinisikan dua output:
+ Waktu sebenarnya fungsi menunggu.
+ Pengidentifikasi unik yang dihasilkan selama setiap eksekusi fungsi Lambda.



**catatan**  
CloudFormation adalah layanan gratis tetapi Lambda mengenakan biaya berdasarkan jumlah permintaan untuk fungsi Anda dan waktu kode Anda dijalankan. [Untuk informasi selengkapnya tentang harga Lambda, lihat AWS Lambda harga.](https://aws.amazon.com/lambda/pricing/)

## Templat sampel
<a name="walkthrough-lambda-backed-custom-resources-sample-template"></a>

Anda dapat melihat template sampel sumber daya kustom yang didukung Lambda dengan mekanisme penundaan di bawah ini:

### JSON
<a name="walkthrough-lambda-backed-custom-resources-sample-template-json"></a>

```
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Resources": {
    "LambdaExecutionRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Statement": [{
            "Effect": "Allow",
            "Principal": { "Service": ["lambda.amazonaws.com"] },
            "Action": ["sts:AssumeRole"]
          }]
        },
        "Path": "/",
        "Policies": [{
          "PolicyName": "AllowLogs",
          "PolicyDocument": {
            "Statement": [{
              "Effect": "Allow",
              "Action": ["logs:*"],
              "Resource": "*"
            }]
          }
        }]
      }
    },
    "CFNWaiter": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Handler": "index.handler",
        "Runtime": "python3.9",
        "Timeout": 900,
        "Role": { "Fn::GetAtt": ["LambdaExecutionRole", "Arn"] },
        "Code": {
          "ZipFile": { "Fn::Join": ["\n", [
            "from time import sleep",
            "import json",
            "import cfnresponse",
            "import uuid",
            "",
            "def handler(event, context):",
            "  wait_seconds = 0",
            "  id = str(uuid.uuid1())",
            "  if event[\"RequestType\"] in [\"Create\", \"Update\"]:",
            "    wait_seconds = int(event[\"ResourceProperties\"].get(\"ServiceTimeout\", 0))",
            "    sleep(wait_seconds)",
            "  response = {",
            "    \"TimeWaited\": wait_seconds,",
            "    \"Id\": id ",
            "  }",
            "  cfnresponse.send(event, context, cfnresponse.SUCCESS, response, \"Waiter-\"+id)"
          ]]}
        }
      }
    },
    "CFNWaiterCustomResource": {
      "Type": "AWS::CloudFormation::CustomResource",
      "Properties": {
        "ServiceToken": { "Fn::GetAtt": ["CFNWaiter", "Arn"] },
        "ServiceTimeout": 60
      }
    }
  },
  "Outputs": {
    "TimeWaited": {
      "Value": { "Fn::GetAtt": ["CFNWaiterCustomResource", "TimeWaited"] },
      "Export": { "Name": "TimeWaited" }
    },
    "WaiterId": {
      "Value": { "Fn::GetAtt": ["CFNWaiterCustomResource", "Id"] },
      "Export": { "Name": "WaiterId" }
    }
  }
}
```

### YAML
<a name="walkthrough-lambda-backed-custom-resources-sample-template-yaml"></a>

```
AWSTemplateFormatVersion: "2010-09-09"
Resources:
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
                - "lambda.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      Path: "/"
      Policies:
        - PolicyName: "AllowLogs"
          PolicyDocument:
            Statement:
              - Effect: "Allow"
                Action:
                  - "logs:*"
                Resource: "*"
  CFNWaiter:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Runtime: python3.9 
      Timeout: 900
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile:
          !Sub |
          from time import sleep
          import json
          import cfnresponse
          import uuid
​
          def handler(event, context):
            wait_seconds = 0
            id = str(uuid.uuid1())
            if event["RequestType"] in ["Create", "Update"]:
              wait_seconds = int(event["ResourceProperties"].get("ServiceTimeout", 0))
              sleep(wait_seconds)
            response = {
              "TimeWaited": wait_seconds,
              "Id": id 
            }
            cfnresponse.send(event, context, cfnresponse.SUCCESS, response, "Waiter-"+id)
  CFNWaiterCustomResource:
    Type: AWS::CloudFormation::CustomResource
    Properties:
      ServiceToken: !GetAtt CFNWaiter.Arn
      ServiceTimeout: 60
Outputs:
  TimeWaited:
    Value: !GetAtt CFNWaiterCustomResource.TimeWaited
    Export:
      Name: TimeWaited
  WaiterId:
    Value: !GetAtt CFNWaiterCustomResource.Id
    Export:
      Name: WaiterId
```

## Contoh panduan templat
<a name="walkthrough-lambda-backed-custom-resources-sample-template-walkthrough"></a>

Cuplikan berikut menjelaskan bagian yang relevan dari template sampel untuk membantu Anda memahami bagaimana fungsi Lambda dikaitkan dengan sumber daya khusus dan memahami hasilnya.

[AWS::Lambda::Function](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html)sumber daya `CFNWaiter`  
`AWS::Lambda::Function`Resource menentukan kode sumber fungsi, nama handler, lingkungan runtime, dan peran eksekusi Amazon Resource Name (ARN).  
`Handler`Properti diatur ke `index.handler` karena menggunakan kode sumber Python. [Untuk informasi selengkapnya tentang pengidentifikasi handler yang diterima saat menggunakan kode sumber fungsi inline, lihat Kode. AWS::Lambda::Function ](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-code.html#cfn-lambda-function-code-zipfile)  
`Runtime`Ini ditentukan sebagai `python3.9` karena file sumber adalah kode Python.  
`Timeout`Ini diatur ke 900 detik.  
`Role`Properti menggunakan `Fn::GetAtt` fungsi untuk mendapatkan ARN dari peran `LambdaExecutionRole` eksekusi yang dideklarasikan dalam `AWS::IAM::Role` sumber daya dalam template.  
`Code`Properti mendefinisikan kode fungsi inline menggunakan fungsi Python. Fungsi Python dalam template sampel melakukan hal berikut:  
+ Buat ID unik menggunakan UUID
+ Periksa apakah permintaan tersebut adalah permintaan buat atau perbarui
+ Tidur selama durasi yang ditentukan `ServiceTimeout` selama `Create` atau `Update` permintaan
+ Kembalikan waktu tunggu dan ID unik

### JSON
<a name="walkthrough-lambda-backed-custom-resources-sample-template-lambda-resource-json"></a>

```
...
    "CFNWaiter": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Handler": "index.handler",
        "Runtime": "python3.9",
        "Timeout": 900,
        "Role": { "Fn::GetAtt": ["LambdaExecutionRole", "Arn"] },
        "Code": {
          "ZipFile": { "Fn::Join": ["\n", [
            "from time import sleep",
            "import json",
            "import cfnresponse",
            "import uuid",
            "",
            "def handler(event, context):",
            "  wait_seconds = 0",
            "  id = str(uuid.uuid1())",
            "  if event[\"RequestType\"] in [\"Create\", \"Update\"]:",
            "    wait_seconds = int(event[\"ResourceProperties\"].get(\"ServiceTimeout\", 0))",
            "    sleep(wait_seconds)",
            "  response = {",
            "    \"TimeWaited\": wait_seconds,",
            "    \"Id\": id ",
            "  }",
            "  cfnresponse.send(event, context, cfnresponse.SUCCESS, response, \"Waiter-\"+id)"
          ]]}
        }
      }
    },
...
```

### YAML
<a name="walkthrough-lambda-backed-custom-resources-sample-template-lambda-resource-yaml"></a>

```
...
  CFNWaiter:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Runtime: python3.9 
      Timeout: 900
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile:
          !Sub |
          from time import sleep
          import json
          import cfnresponse
          import uuid
​
          def handler(event, context):
            wait_seconds = 0
            id = str(uuid.uuid1())
            if event["RequestType"] in ["Create", "Update"]:
              wait_seconds = int(event["ResourceProperties"].get("ServiceTimeout", 0))
              sleep(wait_seconds)
            response = {
              "TimeWaited": wait_seconds,
              "Id": id 
            }
            cfnresponse.send(event, context, cfnresponse.SUCCESS, response, "Waiter-"+id)
...
```

[AWS::IAM::Role](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-role.html)sumber daya `LambdaExecutionRole`  
`AWS::IAM:Role`Sumber daya menciptakan peran eksekusi untuk fungsi Lambda, yang mencakup kebijakan peran asumsi yang memungkinkan Lambda menggunakannya. Ini juga berisi kebijakan yang memungkinkan akses CloudWatch Log.

### JSON
<a name="walkthrough-lambda-backed-custom-resources-sample-template-iam-role-json"></a>

```
...
    "LambdaExecutionRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Statement": [{
            "Effect": "Allow",
            "Principal": { "Service": ["lambda.amazonaws.com"] },
            "Action": ["sts:AssumeRole"]
          }]
        },
        "Path": "/",
        "Policies": [{
          "PolicyName": "AllowLogs",
          "PolicyDocument": {
            "Statement": [{
              "Effect": "Allow",
              "Action": ["logs:*"],
              "Resource": "*"
            }]
          }
        }]
      }
    },
...
```

### YAML
<a name="walkthrough-lambda-backed-custom-resources-sample-template-iam-role-yaml"></a>

```
...
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
                - "lambda.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      Path: "/"
      Policies:
        - PolicyName: "AllowLogs"
          PolicyDocument:
            Statement:
              - Effect: "Allow"
                Action:
                  - "logs:*"
                Resource: "*"
...
```

[AWS::CloudFormation::CustomResource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-customresource.html)sumber daya `CFNWaiterCustomResource`  
Sumber daya khusus menautkan ke fungsi Lambda dengan penggunaan ARN-nya. `!GetAtt CFNWaiter.Arn` Ini akan menerapkan waktu tunggu 60 detik untuk membuat dan memperbarui operasi, seperti yang diatur`ServiceTimeout`. Sumber daya hanya akan dipanggil untuk operasi pembaruan jika properti diubah.

### JSON
<a name="walkthrough-lambda-backed-custom-resources-sample-template-custom-resource-json"></a>

```
...
    "CFNWaiterCustomResource": {
      "Type": "AWS::CloudFormation::CustomResource",
      "Properties": {
        "ServiceToken": { "Fn::GetAtt": ["CFNWaiter", "Arn"] },
        "ServiceTimeout": 60
      }
    }
  },
...
```

### YAML
<a name="walkthrough-lambda-backed-custom-resources-sample-template-custom-resource-yaml"></a>

```
...
  CFNWaiterCustomResource:
    Type: AWS::CloudFormation::CustomResource
    Properties:
      ServiceToken: !GetAtt CFNWaiter.Arn
      ServiceTimeout: 60
...
```

`Outputs`  
Template ini adalah `TimeWaited` dan`WaiterId`. `Outputs` `TimeWaited`Nilai menggunakan `Fn::GetAtt` fungsi untuk memberikan jumlah waktu sumber daya pelayan benar-benar menunggu. `WaiterId`Menggunakan `Fn::GetAtt` fungsi untuk memberikan ID unik yang dihasilkan dan terkait dengan eksekusi.

### JSON
<a name="walkthrough-lambda-backed-custom-resources-sample-template-output-json"></a>

```
...
  "Outputs": {
    "TimeWaited": {
      "Value": { "Fn::GetAtt": ["CFNWaiterCustomResource", "TimeWaited"] },
      "Export": { "Name": "TimeWaited" }
    },
    "WaiterId": {
      "Value": { "Fn::GetAtt": ["CFNWaiterCustomResource", "Id"] },
      "Export": { "Name": "WaiterId" }
    }
  }
}
...
```

### YAML
<a name="walkthrough-lambda-backed-custom-resources-sample-template-output-yaml"></a>

```
...
Outputs:
  TimeWaited:
    Value: !GetAtt CFNWaiterCustomResource.TimeWaited
    Export:
      Name: TimeWaited
  WaiterId:
    Value: !GetAtt CFNWaiterCustomResource.Id
    Export:
      Name: WaiterId
...
```

## Prasyarat
<a name="walkthrough-lambda-backed-custom-resources-prerequisites"></a>

Anda harus memiliki izin IAM untuk menggunakan semua layanan terkait, seperti Lambda dan. CloudFormation

## Meluncurkan tumpukan
<a name="walkthrough-lambda-backed-custom-resources-createfunction-createstack"></a>

**Untuk membuat tumpukan**

1. Temukan template preferensi Anda (YAMAL atau JSON) dari [Templat sampel](#walkthrough-lambda-backed-custom-resources-sample-template) bagian dan simpan ke mesin Anda dengan nama. `samplelambdabackedcustomresource.template`

1. Buka CloudFormation konsol di [https://console.aws.amazon.com/cloudformation/](https://console.aws.amazon.com/cloudformation/).

1. Dari halaman **Stacks**, pilih **Buat tumpukan** di kanan atas, lalu pilih **Dengan sumber daya baru (standar)**.

1. Untuk **Prasyarat - Siapkan template**, pilih **Pilih template yang ada**.

1. Untuk **Menentukan templat**, pilih **Unggah file templat**, lalu pilih **Pilih file**.

1. Pilih file `samplelambdabackedcustomresource.template` template yang Anda simpan sebelumnya.

1. Pilih **Berikutnya**.

1. Untuk **nama Stack**, ketik **SampleCustomResourceStack** dan pilih **Berikutnya**.

1. Untuk panduan ini, Anda tidak perlu menambahkan tanda atau menentukan pengaturan lanjutan, jadi pilih **Selanjutnya**.

1. Pastikan nama tumpukan terlihat benar, lalu pilih **Buat**.

Mungkin perlu beberapa menit CloudFormation untuk membuat tumpukan Anda. Untuk memantau kemajuan, tampilkan peristiwa tumpukan. Untuk informasi selengkapnya, lihat [Lihat informasi tumpukan dari CloudFormation konsol](cfn-console-view-stack-data-resources.md).

Jika pembuatan tumpukan berhasil, semua sumber daya dalam tumpukan, seperti fungsi Lambda dan sumber daya khusus, dibuat. Anda telah berhasil menggunakan fungsi Lambda dan sumber daya khusus.

[Jika fungsi Lambda mengembalikan kesalahan, lihat log fungsi di konsol CloudWatch Log.](https://console.aws.amazon.com/cloudwatch/home#logs:) Nama pengaliran log adalah ID fisik sumber daya kustom, yang dapat Anda temukan dengan melihat sumber daya tumpukan. Untuk informasi selengkapnya, [lihat Melihat data log](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html#ViewingLogData) di *Panduan CloudWatch Pengguna Amazon*.

## Membersihkan sumber daya
<a name="walkthrough-lambda-backed-custom-resources-createfunction-cleanup"></a>

Hapus tumpukan untuk membersihkan semua sumber daya tumpukan yang Anda buat sehingga Anda tidak dikenakan biaya untuk sumber daya yang tidak diperlukan.

**Untuk menghapus tumpukan**

1. Dari CloudFormation konsol, pilih **SampleCustomResourceStack**tumpukan.

1. Pilih **Tindakan**, dan kemudian **Hapus Tumpukan**.

1. Pada pesan konfirmasi, pilih **Ya, Hapus**.

Semua sumber daya yang telah Anda buat sebelumnya akan dihapus.

Sekarang setelah Anda memahami cara membuat dan menggunakan sumber daya kustom yang didukung Lambda, Anda dapat menggunakan contoh template dan kode dari panduan ini untuk membangun dan bereksperimen dengan tumpukan dan fungsi lain.

## Informasi Terkait
<a name="w2aac11c45b9c24b9c23"></a>
+ [CloudFormation Referensi Sumber Daya Kustom](crpg-ref.md)
+ [AWS::CloudFormation::CustomResource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-customresource.html)

# Modul `cfn-response`
<a name="cfn-lambda-function-code-cfnresponsemodule"></a>

Dalam CloudFormation template Anda, Anda dapat menentukan fungsi Lambda sebagai target sumber daya kustom. Saat Anda menggunakan `ZipFile` properti untuk menentukan kode sumber [fungsi](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html) Anda, Anda dapat memuat `cfn-response` modul untuk mengirim respons dari fungsi Lambda Anda ke sumber daya khusus. `cfn-response`Modul ini adalah pustaka yang menyederhanakan pengiriman tanggapan ke sumber daya kustom yang memanggil fungsi Lambda Anda. Modul ini memiliki `send` metode yang mengirimkan [objek respons](crpg-ref.md#crpg-ref-responses) ke sumber daya khusus melalui URL presigned Amazon S3 (the). `ResponseURL`

Modul `cfn-response` tersedia hanya ketika Anda menggunakan properti `ZipFile` untuk menulis kode sumber Anda. Ini tidak tersedia untuk kode sumber yang disimpan di bucket Amazon S3. Untuk kode dalam bucket, Anda harus menulis fungsi Anda sendiri untuk mengirim tanggapan.

**catatan**  
Setelah mengeksekusi `send` metode, fungsi Lambda berakhir, jadi apa pun yang Anda tulis setelah metode itu diabaikan.

## Memuat modul `cfn-response`
<a name="cfn-lambda-function-code-cfnresponsemodule-loading"></a>

Untuk fungsi Node.js, gunakan fungsi `require()` untuk memuat modul `cfn-response`. Sebagai contoh, contoh kode berikut membuat objek `cfn-response` dengan nama `response`:

```
var response = require('cfn-response');
```

Untuk Python, gunakan pernyataan `import` untuk memuat modul `cfnresponse`, seperti yang ditunjukkan dalam contoh berikut:

**catatan**  
Gunakan pernyataan impor persis seperti ini. Jika Anda menggunakan varian lain dari pernyataan impor, CloudFormation tidak mencakup modul respon.

```
import cfnresponse
```

## Parameter metode `send`
<a name="cfn-lambda-function-code-cfnresponsemodule-send-parameters"></a>

Anda dapat menggunakan parameter berikut dengan metode `send`.

`event`  
Bidang dalam [permintaan sumber daya kustom](crpg-ref.md#crpg-ref-requesttypes).

`context`  
Objek, khusus untuk fungsi Lambda, yang dapat Anda gunakan untuk menentukan kapan fungsi dan callback telah menyelesaikan eksekusi, atau untuk mengakses informasi dari dalam lingkungan eksekusi Lambda. Untuk informasi selengkapnya, lihat [Membangun fungsi Lambda dengan Node.js](https://docs.aws.amazon.com/lambda/latest/dg/lambda-nodejs.html) di Panduan *AWS Lambda Pengembang*.

`responseStatus`  
Apakah fungsi berhasil diselesaikan. Gunakan konstanta modul `cfnresponse` untuk menentukan status: `SUCCESS` untuk eksekusi yang sukses dan `FAILED` untuk eksekusi yang gagal.

`responseData`  
Bidang `Data` dari [objek respons](crpg-ref.md#crpg-ref-responses) sumber daya kustom. Data tersebut merupakan daftar pasangan nama-nilai.

`physicalResourceId`  
Tidak wajib. Pengidentifikasi unik dari sumber daya kustom yang memanggil fungsi tersebut. Secara default, modul menggunakan nama aliran CloudWatch log Amazon Logs yang terkait dengan fungsi Lambda.  
Nilai yang dikembalikan untuk `PhysicalResourceId` dapat mengubah operasi pembaruan sumber daya kustom. Jika nilai yang dikembalikan sama, itu dianggap sebagai pembaruan normal. Jika nilai yang dikembalikan berbeda, CloudFormation mengenali pembaruan sebagai pengganti dan mengirimkan permintaan hapus ke sumber daya lama. Untuk informasi selengkapnya, lihat [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-customresource.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-customresource.html).

`noEcho`  
Tidak wajib. Menunjukkan apakah menutupi output dari sumber daya kustom ketika ia diambil dengan menggunakan fungsi `Fn::GetAtt`. Jika diatur ke `true`, semua nilai yang dikembalikan ditutupi dengan tanda bintang (\$1\$1\$1\$1\$1), kecuali untuk informasi yang tersimpan di lokasi yang ditentukan di bawah ini. Secara default, nilainya adalah `false`.  
Menggunakan `NoEcho` atribut tidak menutupi informasi apa pun yang disimpan sebagai berikut:  
+ Bagian `Metadata` template. CloudFormation tidak mengubah, memodifikasi, atau menyunting informasi apa pun yang Anda sertakan di `Metadata` bagian ini. Untuk informasi selengkapnya, lihat [Metadata](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html).
+ Bagian `Outputs` template. Untuk informasi selengkapnya, lihat [Output](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html).
+ `Metadata`Atribut definisi sumber daya. Untuk informasi lebih lanjut, lihat [Atribut `Metadata`](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-metadata.html).
Kami sangat menyarankan Anda untuk tidak menggunakan mekanisme ini untuk memasukkan informasi sensitif, seperti kata sandi atau rahasia.
Untuk informasi selengkapnya tentang penggunaan `NoEcho` untuk menutupi informasi sensitif, lihat praktik [Jangan menanamkan kredensial dalam templat Anda](security-best-practices.md#creds) terbaik.

## Contoh
<a name="cfn-lambda-function-code-cfnresponsemodule-examples"></a>

### Node.js
<a name="cfn-lambda-function-code-zipfile-examplenodejs"></a>

Dalam contoh Node.js berikut, fungsi Lambda inline mengambil nilai input dan mengalikannya dengan 5. Fungsi inline sangat berguna untuk fungsi yang lebih kecil karena memungkinkan Anda menentukan kode sumber secara langsung di template, alih-alih membuat paket dan mengunggahnya ke bucket Amazon S3. Fungsi ini menggunakan metode `cfn-response` `send` untuk mengirim hasil kembali ke sumber daya kustom yang memanggilnya.

#### JSON
<a name="cfn-lambda-function-code-zipfile-examplenodejs.json"></a>

```
"ZipFile": { "Fn::Join": ["", [
  "var response = require('cfn-response');",
  "exports.handler = function(event, context) {",
  "  var input = parseInt(event.ResourceProperties.Input);",
  "  var responseData = {Value: input * 5};",
  "  response.send(event, context, response.SUCCESS, responseData);",
  "};"
]]}
```

#### YAML
<a name="cfn-lambda-function-code-zipfile-examplenodejs-yaml"></a>

```
ZipFile: >
  var response = require('cfn-response');
  exports.handler = function(event, context) {
    var input = parseInt(event.ResourceProperties.Input);
    var responseData = {Value: input * 5};
    response.send(event, context, response.SUCCESS, responseData);
  };
```

### Python
<a name="cfn-lambda-function-code-zipfile-examplepython"></a>

Dalam contoh Python berikut, fungsi Lambda inline mengambil nilai integer dan mengalikannya dengan 5.

#### JSON
<a name="cfn-lambda-function-code-zipfile-examplepython.json"></a>

```
"ZipFile" : { "Fn::Join" : ["\n", [
  "import json",
  "import cfnresponse",
  "def handler(event, context):",
  "   responseValue = int(event['ResourceProperties']['Input']) * 5",
  "   responseData = {}",
  "   responseData['Data'] = responseValue",
  "   cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, \"CustomResourcePhysicalID\")"
]]}
```

#### YAML
<a name="cfn-lambda-function-code-zipfile-examplepython.yaml"></a>

```
ZipFile: |
  import json
  import cfnresponse
  def handler(event, context):
    responseValue = int(event['ResourceProperties']['Input']) * 5
    responseData = {}
    responseData['Data'] = responseValue
    cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
```

## Kode sumber modul
<a name="cfn-lambda-function-code-cfnresponsemodule-source"></a>

**Topics**
+ [Kode sumber Node.js asinkron](#cfn-lambda-function-code-cfnresponsemodule-source-nodejs-async)
+ [Kode sumber Node.js](#cfn-lambda-function-code-cfnresponsemodule-source-nodejs)
+ [Kode sumber Python](#cfn-lambda-function-code-cfnresponsemodule-source-python)

### Kode sumber Node.js asinkron
<a name="cfn-lambda-function-code-cfnresponsemodule-source-nodejs-async"></a>

Berikut ini adalah kode sumber modul respons untuk fungsi Node.js jika handler asinkron. Tinjau untuk memahami apa yang dilakukan modul dan untuk bantuan dengan menerapkan fungsi respon Anda sendiri.

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0

exports.SUCCESS = "SUCCESS";
exports.FAILED = "FAILED";

exports.send = function(event, context, responseStatus, responseData, physicalResourceId, noEcho) {

    return new Promise((resolve, reject) => {
        var responseBody = JSON.stringify({
            Status: responseStatus,
            Reason: "See the details in CloudWatch Log Stream: " + context.logStreamName,
            PhysicalResourceId: physicalResourceId || context.logStreamName,
            StackId: event.StackId,
            RequestId: event.RequestId,
            LogicalResourceId: event.LogicalResourceId,
            NoEcho: noEcho || false,
            Data: responseData
        });

        console.log("Response body:\n", responseBody);

        var https = require("https");
        var url = require("url");

        var parsedUrl = url.parse(event.ResponseURL);
        var options = {
            hostname: parsedUrl.hostname,
            port: 443,
            path: parsedUrl.path,
            method: "PUT",
            headers: {
                "content-type": "",
                "content-length": responseBody.length
            }
        };

        var request = https.request(options, function(response) {
            console.log("Status code: " + parseInt(response.statusCode));
            resolve(context.done());
        });

        request.on("error", function(error) {
            console.log("send(..) failed executing https.request(..): " + maskCredentialsAndSignature(error));
            reject(context.done(error));
        });

        request.write(responseBody);
        request.end();
    })
}
 
function maskCredentialsAndSignature(message) {
    return message.replace(/X-Amz-Credential=[^&\s]+/i, 'X-Amz-Credential=*****')
        .replace(/X-Amz-Signature=[^&\s]+/i, 'X-Amz-Signature=*****');
}
```

### Kode sumber Node.js
<a name="cfn-lambda-function-code-cfnresponsemodule-source-nodejs"></a>

Berikut ini adalah kode sumber modul respons untuk fungsi Node.js jika handler tidak asinkron. Tinjau untuk memahami apa yang dilakukan modul dan untuk bantuan dengan menerapkan fungsi respon Anda sendiri.

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0
 
exports.SUCCESS = "SUCCESS";
exports.FAILED = "FAILED";

exports.send = function(event, context, responseStatus, responseData, physicalResourceId, noEcho) {

    var responseBody = JSON.stringify({
        Status: responseStatus,
        Reason: "See the details in CloudWatch Log Stream: " + context.logStreamName,
        PhysicalResourceId: physicalResourceId || context.logStreamName,
        StackId: event.StackId,
        RequestId: event.RequestId,
        LogicalResourceId: event.LogicalResourceId,
        NoEcho: noEcho || false,
        Data: responseData
    });

    console.log("Response body:\n", responseBody);

    var https = require("https");
    var url = require("url");

    var parsedUrl = url.parse(event.ResponseURL);
    var options = {
        hostname: parsedUrl.hostname,
        port: 443,
        path: parsedUrl.path,
        method: "PUT",
        headers: {
            "content-type": "",
            "content-length": responseBody.length
        }
    };

    var request = https.request(options, function(response) {
        console.log("Status code: " + parseInt(response.statusCode));
        context.done();
    });

    request.on("error", function(error) {
        console.log("send(..) failed executing https.request(..): " + maskCredentialsAndSignature(error));
        context.done();
    });

    request.write(responseBody);
    request.end();
}
```

### Kode sumber Python
<a name="cfn-lambda-function-code-cfnresponsemodule-source-python"></a>

Berikut ini adalah kode sumber modul respon untuk fungsi Python:

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
 
from __future__ import print_function
import urllib3
import json
import re

SUCCESS = "SUCCESS"
FAILED = "FAILED"

http = urllib3.PoolManager()


def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False, reason=None):
    responseUrl = event['ResponseURL']

    responseBody = {
        'Status' : responseStatus,
        'Reason' : reason or "See the details in CloudWatch Log Stream: {}".format(context.log_stream_name),
        'PhysicalResourceId' : physicalResourceId or context.log_stream_name,
        'StackId' : event['StackId'],
        'RequestId' : event['RequestId'],
        'LogicalResourceId' : event['LogicalResourceId'],
        'NoEcho' : noEcho,
        'Data' : responseData
    }

    json_responseBody = json.dumps(responseBody)

    print("Response body:")
    print(json_responseBody)

    headers = {
        'content-type' : '',
        'content-length' : str(len(json_responseBody))
    }

    try:
        response = http.request('PUT', responseUrl, headers=headers, body=json_responseBody)
        print("Status code:", response.status)


    except Exception as e:

        print("send(..) failed executing http.request(..):", mask_credentials_and_signature(e))
 
 
def mask_credentials_and_signature(message):
    message = re.sub(r'X-Amz-Credential=[^&\s]+', 'X-Amz-Credential=*****', message, flags=re.IGNORECASE)
    return re.sub(r'X-Amz-Signature=[^&\s]+', 'X-Amz-Signature=*****', message, flags=re.IGNORECASE)
```