

# Amazon SNS を利用するカスタムリソース
<a name="template-custom-resources-sns"></a>

次のトピックでは、CloudFormation がリクエストを送信する Amazon SNS トピックを指定するサービストークンを使用してカスタムリソースを設定する方法を示します。また、カスタムリソーススタックの作成、更新、削除の結果として送受信されるイベントとメッセージのシーケンスについても学習します。

カスタムリソースと Amazon SNS を使用すると、新しいリソースのスタックへの追加、スタックへの動的データの挿入などのシナリオが可能になります。例えば、スタックを作成する際に、CloudFormation は、Amazon EC2 インスタンスで実行しているアプリケーションによってモニタリングされるトピックに `Create` リクエストを送信できます。Amazon SNS 通知は、許可リストされた Elastic IP アドレスのプールの取得など、追加のプロビジョニングタスクを実行するようにアプリケーションをトリガーします。完了すると、アプリケーションは、CloudFormation にスタックオペレーションの続行を通知する応答 (および該当する場合は出力データ) を送信します。

カスタムリソースのターゲットとして Amazon SNS トピックを指定すると、CloudFormation はカスタムリソースに関連するスタックオペレーション中に指定された SNS トピックにメッセージを送信します。これらのメッセージを処理して必要なアクションを実行するには、サポートされているエンドポイントが SNS トピックをサブスクライブするようにする必要があります。

カスタムリソースとその仕組みの概要については、「[カスタムリソースのしくみ](template-custom-resources.md#how-custom-resources-work)」を参照してください。Amazon SNS とその仕組みの詳細については、「[Amazon Simple Notification Service デベロッパーガイド](https://docs.aws.amazon.com/sns/latest/dg/)」を参照してください。

## Amazon SNS を利用してカスタムリソースを作成する
<a name="walkthrough-custom-resources-sns-adding-nonaws-resource"></a>

**Topics**
+ [ステップ 1: スタックの作成](#crpg-walkthrough-stack-creation)
+ [ステップ 2: スタックの更新](#crpg-walkthrough-stack-updates)
+ [ステップ 3: スタックの削除](#crpg-walkthrough-stack-deletion)

### ステップ 1: スタックの作成
<a name="crpg-walkthrough-stack-creation"></a>

1. <a name="crpg-walkthrough-stack-creation-customer-template"></a>テンプレートデベロッパーは、カスタムリソースを含む CloudFormation スタックを作成します。

   以下のテンプレート例では、論理 ID `MySeleniumTest` を持つカスタムリソースにカスタムリソースタイプ名 `Custom::SeleniumTester` を使用します。カスタムリソースタイプの名前は、英数字で 60 文字までの長さにする必要があります。

   カスタムリソースのタイプとともに、カスタムリソースプロバイダーによって定義された情報として、サービストークン、オプションのプロバイダー固有のプロパティ、オプションの [Fn::GetAtt](resources-section-structure.md#resource-properties-getatt) 属性が宣言されています。これらのプロパティと属性を使用して、template developer から custom resource provider へ、または custom resource provider から template developer へ情報を受け渡しすることができます。サービストークンは、リソースプロバイダーが設定した Amazon SNS トピックを指定します。

   ```
   {
      "AWSTemplateFormatVersion" : "2010-09-09",
      "Resources" : {
         "MySeleniumTest" : {
            "Type": "Custom::SeleniumTester",
            "Version" : "1.0",
            "Properties" : {
               "ServiceToken": "arn:aws:sns:us-west-2:123456789012:CRTest",
               "seleniumTester" : "SeleniumTest()",
               "endpoints" : [ "http://mysite.com", "http://myecommercesite.com/", "http://search.mysite.com" ],
               "frequencyOfTestsPerHour" : [ "3", "2", "4" ]
            }
         }
      },
      "Outputs" : {
         "topItem" : {
            "Value" : { "Fn::GetAtt" : ["MySeleniumTest", "resultsPage"] }
         },
         "numRespondents" : {
            "Value" : { "Fn::GetAtt" : ["MySeleniumTest", "lastUpdate"] }
         }
      }
   }
   ```
**注記**  
`Fn::GetAtt` を使用してアクセスしたデータの名前と値は、プロバイダーから CloudFormation への応答中にカスタムリソースプロバイダーから返されます。custom resource provider がサードパーティーである場合、template developer は、それらの戻り値の名前を custom resource provider から入手する必要があります。

1. <a name="crpg-walkthrough-stack-creation-provider-request"></a>CloudFormation が、スタックに関する情報、スタックテンプレートからのカスタムリソースプロパティ、および応答のための S3 URL が含まれた `"RequestType" : "Create"` を使用して、リソースプロバイダーに Amazon SNS 通知を送信します。

   通知を送信する際に使用する SNS トピックは、テンプレートの `ServiceToken` プロパティに埋め込まれます。値をハードコーディングすることを避けるために、テンプレート開発者はテンプレートパラメータを使用します。スタックの起動時に値を入力することができます。

   次の例は、カスタムリソースの `Create` リクエストを示します。`Custom::SeleniumTester` を `LogicalResourceId` として作成されたカスタムリソースタイプの名前 (`MySeleniumTester`) が含まれています。

   ```
   {
      "RequestType" : "Create",
      "RequestId" : "unique-request-id",
      "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/5b918d10-cd98-11ea-90d5-0a9cd3354c10",
      "ResponseURL" : "http://pre-signed-S3-url-for-response",
      "ResourceType" : "Custom::SeleniumTester",
      "LogicalResourceId" : "MySeleniumTester",
      "ResourceProperties" : {
         "seleniumTester" : "SeleniumTest()",
         "endpoints" : [ "http://mysite.com", "http://myecommercesite.com/", "http://search.mysite.com" ],
         "frequencyOfTestsPerHour" : [ "3", "2", "4" ]
      }
   }
   ```

   `Create` リクエストのリクエストオブジェクトの詳細については、[リクエストおよびレスポンスのリファレンス](crpg-ref.md) トピックを参照してください。

1. <a name="crpg-walkthrough-stack-creation-provider-response"></a>custom resource provider は、template developer から送信されたデータを処理し、`Create` リクエストが成功したかどうかを判断します。リソースプロバイダーは、CloudFormation から送信された S3 URL を使用して、`SUCCESS` または `FAILED` の応答を送信します。

   CloudFormation に返される応答フィールドは、応答のタイプによって異なります。特定のリクエストタイプの応答フィールドの詳細については、[リクエストおよびレスポンスのリファレンス](crpg-ref.md) セクションのそのリクエストタイプのドキュメントを参照してください。

   custom resource provider は、作成リクエストまたは更新リクエストへの応答として、レスポンスの `Data` フィールドでデータ要素を返すことができます。これらは名前/値ペアであり、*名前*は、スタックテンプレートのカスタムリソースで使用されている `Fn::GetAtt` 属性に対応します。*値*は、テンプレート開発者が、リソースから属性名を使って `Fn::GetAtt` を呼び出したときに返されるデータです。

   次に、カスタムリソースのレスポンスの例を示します。

   ```
   {
      "Status" : "SUCCESS",
      "RequestId" : "unique-request-id",
      "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/5b918d10-cd98-11ea-90d5-0a9cd3354c10",
      "LogicalResourceId" : "MySeleniumTester",
      "PhysicalResourceId" : "Tester1",
      "Data" : {
         "resultsPage" : "http://www.myexampledomain/test-results/guid",
         "lastUpdate" : "2012-11-14T03:30Z"
      }
   }
   ```

   `Create` リクエストの応答オブジェクトの詳細については、[リクエストおよびレスポンスのリファレンス](crpg-ref.md) トピックを参照してください。

   `StackId`、`RequestId`、および `LogicalResourceId` フィールドはリクエストからそのままコピーする必要があります。

1. <a name="crpg-walkthrough-stack-creation-stack-status"></a> CloudFormation は、スタックのステータスを `CREATE_COMPLETE` または `CREATE_FAILED` として宣言します。スタックが正常に作成された場合、テンプレート開発者は、作成したカスタムリソースの出力値に [Fn::GetAtt](resources-section-structure.md#resource-properties-getatt) でアクセスすることで使用できます。

   たとえば、先ほど例示したカスタムリソーステンプレートでは、`Fn::GetAtt` を使用してリソースの出力をスタック出力にコピーしています。

   ```
   "Outputs" : {
      "topItem" : {
         "Value" : { "Fn::GetAtt" : ["MySeleniumTest", "resultsPage"] }
      },
      "numRespondents" : {
         "Value" : { "Fn::GetAtt" : ["MySeleniumTest", "lastUpdate"] }
      }
   }
   ```

### ステップ 2: スタックの更新
<a name="crpg-walkthrough-stack-updates"></a>

既存のスタックを更新するには、以下の例に示すように、スタック内のリソースのプロパティの更新を指定するテンプレートを送信する必要があります。CloudFormation は、テンプレートで指定された変更があるリソースのみを更新します。詳細については、「[スタックリソースの更新動作を理解する](using-cfn-updating-stacks-update-behaviors.md)」を参照してください。

カスタムリソースの更新には、基になる物理リソースの置き換えが伴うことがあります。CloudFormation テンプレートでカスタムリソースを更新すると、CloudFormation が、そのカスタムリソースに更新リクエストを送信します。カスタムリソースを置き換えることが必要になった場合には、新しいカスタムリソースから新しい物理 ID を含むレスポンスを送信する必要があります。CloudFormation は、そのレスポンスを受け取ると、古いカスタムリソースと新しいカスタムリソースの `PhysicalResourceId` を比較します。この 2 つが異なる場合には、CloudFormation は置き換えが必要な更新と認識し、古いリソースに削除リクエストを送信します (「[ステップ 3: スタックの削除](#crpg-walkthrough-stack-deletion)」を参照)。

**注記**  
カスタムリソースに変更を行なわない場合、CloudFormation はスタック更新中にリクエストを送信しません。

1. <a name="crpg-walkthrough-stack-updates-customer-template"></a>template developerが、カスタムリソースを含んだスタックの更新を開始します。更新時、template developerは、新しいプロパティをスタックテンプレートで指定できます。

   カスタムリソースタイプを使用したスタックテンプレートに対する `Update` の例を以下に示します。

   ```
   {
      "AWSTemplateFormatVersion" : "2010-09-09",
      "Resources" : {
         "MySeleniumTest" : {
            "Type": "Custom::SeleniumTester",
            "Version" : "1.0",
            "Properties" : {
               "ServiceToken": "arn:aws:sns:us-west-2:123456789012:CRTest",
               "seleniumTester" : "SeleniumTest()",
               "endpoints" : [ "http://mysite.com", "http://myecommercesite.com/", "http://search.mysite.com",
                  "http://mynewsite.com" ],
               "frequencyOfTestsPerHour" : [ "3", "2", "4", "3" ]
            }
         }
      },
      "Outputs" : {
         "topItem" : {
            "Value" : { "Fn::GetAtt" : ["MySeleniumTest", "resultsPage"] }
         },
         "numRespondents" : {
            "Value" : { "Fn::GetAtt" : ["MySeleniumTest", "lastUpdate"] }
         }
      }
   }
   ```

1. <a name="crpg-walkthrough-stack-updates-provider-request"></a>CloudFormation が、`"RequestType" : "Update"` を使用して Amazon SNS 通知をリソースプロバイダーに送信します。これには `Create` コールに類似する情報が含まれていますが、`OldResourceProperties` フィールドに古いリソースプロパティが含まれており、ResourceProperties に更新されたリソースプロパティ (存在する場合) が含まれている点が異なります。

   次は、`Update` リクエストの例です。

   ```
   {
      "RequestType" : "Update",
      "RequestId" : "unique-request-id",
      "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/5b918d10-cd98-11ea-90d5-0a9cd3354c10",
      "ResponseURL" : "http://pre-signed-S3-url-for-response",
      "ResourceType" : "Custom::SeleniumTester",
      "LogicalResourceId" : "MySeleniumTester",
      "PhysicalResourceId" : "Tester1",
      "ResourceProperties" : {
         "seleniumTester" : "SeleniumTest()",
         "endpoints" : [ "http://mysite.com", "http://myecommercesite.com/", "http://search.mysite.com",
            "http://mynewsite.com" ],
         "frequencyOfTestsPerHour" : [ "3", "2", "4", "3" ]
      },
      "OldResourceProperties" : {
         "seleniumTester" : "SeleniumTest()",
         "endpoints" : [ "http://mysite.com", "http://myecommercesite.com/", "http://search.mysite.com" ],
         "frequencyOfTestsPerHour" : [ "3", "2", "4" ]
      }
   }
   ```

   `Update` リクエストのリクエストオブジェクトの詳細については、[リクエストおよびレスポンスのリファレンス](crpg-ref.md) トピックを参照してください。

1. <a name="crpg-walkthrough-stack-updates-provider-response"></a>CloudFormation から送信されたデータをカスタムリソースプロバイダーが処理します。カスタムリソースは更新を実行し、`SUCCESS` または `FAILED` のいずれかの応答を S3 URL に送信します。その後、CloudFormation は古いカスタムリソースと新しいカスタムリソースの `PhysicalResourceIDs` を比較します。この 2 つが異なる場合には、CloudFormation は置き換えが必要な更新と認識し、古いリソースに削除リクエストを送信します。以下に示したのは、`Update` リクエストに対するcustom resource providerのレスポンスの例です。

   ```
   {
      "Status" : "SUCCESS",
      "RequestId" : "unique-request-id",
      "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/5b918d10-cd98-11ea-90d5-0a9cd3354c10",
      "LogicalResourceId" : "MySeleniumTester",
      "PhysicalResourceId" : "Tester2"
   }
   ```

   `Update` リクエストのレスポンスオブジェクトの詳細については、[リクエストおよびレスポンスのリファレンス](crpg-ref.md)「」トピックを参照してください。

   `StackId`、`RequestId`、および `LogicalResourceId` フィールドはリクエストからそのままコピーする必要があります。

1. <a name="crpg-walkthrough-stack-updates-stack-status"></a>CloudFormation は、スタックのステータスを `UPDATE_COMPLETE` または `UPDATE_FAILED` として宣言します。更新に失敗すると、スタックはロールバックされます。スタックが正常に更新された場合、template developer は、作成したカスタムリソースの新しい出力値に `Fn::GetAtt` でアクセスすることができます。

### ステップ 3: スタックの削除
<a name="crpg-walkthrough-stack-deletion"></a>

1. <a name="crpg-walkthrough-stack-deletion-customer-template"></a>テンプレートデベロッパーは、カスタムリソースを含むスタックを削除します。CloudFormation は、スタックテンプレートで指定されている現在のプロパティを SNS トピックとともに取得し、カスタムリソースプロバイダーに対してリクエストを実行する準備をします。

1. <a name="crpg-walkthrough-stack-deletion-provider-request"></a>CloudFormation が、スタックに関する現在の情報、スタックテンプレートからのカスタムリソースプロパティ、および応答のための S3 URL が含まれた `"RequestType" : "Delete"` を使用して、リソースプロバイダーに Amazon SNS 通知を送信します。

   スタックを削除したり、カスタムリソースの削除や置き換えを伴う更新を行ったりした場合は必ず、CloudFormation によって、新旧のカスタムリソース間で `PhysicalResourceId` が比較されます。この 2 つが異なる場合には、CloudFormation は置き換えが必要な更新と認識し、古いリソース (`OldPhysicalResource`) の削除リクエストを送信します (以下の `Delete` リクエストの例を参照)。

   ```
   {
      "RequestType" : "Delete",
      "RequestId" : "unique-request-id",
      "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/5b918d10-cd98-11ea-90d5-0a9cd3354c10",
      "ResponseURL" : "http://pre-signed-S3-url-for-response",
      "ResourceType" : "Custom::SeleniumTester",
      "LogicalResourceId" : "MySeleniumTester",
      "PhysicalResourceId" : "Tester1",
      "ResourceProperties" : {
         "seleniumTester" : "SeleniumTest()",
         "endpoints" : [ "http://mysite.com", "http://myecommercesite.com/", "http://search.mysite.com",
            "http://mynewsite.com" ],
         "frequencyOfTestsPerHour" : [ "3", "2", "4", "3" ]
      }
   }
   ```

   `Delete` リクエストのリクエストオブジェクトの詳細については、[リクエストおよびレスポンスのリファレンス](crpg-ref.md) トピックを参照してください。

   ユーザー定義の名前が指定されている場合、`DescribeStackResource`、`DescribeStackResources`、`ListStackResources` で表示できます。

1. <a name="crpg-walkthrough-stack-deletion-provider-response"></a>カスタムリソースプロバイダーは、CloudFormation から送信されたデータを処理し、`Delete` リクエストが成功したかどうかを判断します。リソースプロバイダーは、CloudFormation から送信された S3 URL を使用して、`SUCCESS` または `FAILED` の応答を送信します。カスタムリソースを持つスタックを正常に削除するには、削除リクエストに対して custom resource provider が適切に応答する必要があります。

   以下に示したのは、`Delete` リクエストに対する custom resource provider のレスポンスの例です。

   ```
   {
      "Status" : "SUCCESS",
      "RequestId" : "unique-request-id",
      "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/5b918d10-cd98-11ea-90d5-0a9cd3354c10",
      "LogicalResourceId" : "MySeleniumTester",
      "PhysicalResourceId" : "Tester1"
   }
   ```

   `Delete` リクエストのレスポンスオブジェクトの詳細については、[リクエストおよびレスポンスのリファレンス](crpg-ref.md)「」トピックを参照してください。

   `StackId`、`RequestId`、および `LogicalResourceId` フィールドはリクエストからそのままコピーする必要があります。

1. <a name="crpg-walkthrough-stack-updates-stack-status-delete"></a>CloudFormation は、スタックのステータスを `DELETE_COMPLETE` または `DELETE_FAILED` として宣言します。