

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# チュートリアル: CodeDeploy と AWS サーバーレスアプリケーションモデルを使用して更新された Lambda 関数をデプロイする
<a name="tutorial-lambda-sam"></a>

AWS SAM は、サーバーレスアプリケーションを構築するためのオープンソースフレームワークです。 AWS SAM テンプレート内の YAML 構文を CloudFormation 構文に変換して拡張し、Lambda 関数などのサーバーレスアプリケーションを構築します。詳細については、[「 AWS サーバーレスアプリケーションモデルとは何ですか。」](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html) を参照してください。

 このチュートリアルでは、SAM AWS を使用して、以下を実行するソリューションを作成します。
+  Lambda 関数を作成します。
+  CodeDeploy アプリケーションとデプロイグループを作成します。
+  CodeDeploy ライフサイクルフック中にデプロイの検証テストを実行する 2 つの Lambda 関数を作成します。
+  Lambda 関数がいつ更新されたかを検出します。Lambda 関数の更新により、CodeDeploy によるデプロイがトリガーされます。これにより、本稼働トラフィックが Lambda 関数の元のバージョンから更新されたバージョンに段階的に移行されます。

**注記**  
このチュートリアルでは、 AWS アカウントに課金される可能性のあるリソースを作成する必要があります。これには、CodeDeploy、Amazon CloudWatch、および に対して発生する可能性のある料金が含まれます AWS Lambda。詳細については、[CodeDeploy pricing](https://aws.amazon.com/codedeploy/pricing/)、[Amazon CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/) および [AWS Lambda pricing](https://aws.amazon.com/lambda/pricing/) を参照してください。

**Topics**
+ [前提条件](tutorial-lambda-sam-prereqs.md)
+ [ステップ 1: インフラストラクチャをセットアップする](tutorial-lambda-sam-setup-infrastructure.md)
+ [ステップ 2: Lambda 関数を更新します](tutorial-lambda-sam-update-function.md)
+ [ステップ 3: 更新された Lambda 関数をデプロイします。](tutorial-lambda-sam-deploy-update.md)
+ [ステップ 4: デプロイの結果を表示する](tutorial-lambda-sam-deploy-view-results.md)
+ [ステップ 5：クリーンアップ](tutorial-lambda-clean-up.md)

# 前提条件
<a name="tutorial-lambda-sam-prereqs"></a>

このチュートリアルを完了するには、まず以下を行う必要があります。
+  「[CodeDeploy の開始方法](getting-started-codedeploy.md)」のステップを完了します。
+  CLI AWS Serverless Application Model をインストールします。詳細については、[「SAM AWS CLI のインストール](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)」を参照してください。
+  S3 バケットを作成します。 AWS SAM は、[AWS SAM テンプレート](https://docs.aws.amazon.com/en_us/codedeploy/latest/userguide/tutorial-lambda-sam-template.html)で参照されているアーティファクトをこのバケットにアップロードします。

# ステップ 1: インフラストラクチャをセットアップする
<a name="tutorial-lambda-sam-setup-infrastructure"></a>

 このトピックでは、 AWS SAM を使用して AWS SAM テンプレートと Lambda 関数のファイルを作成する方法について説明します。次に、 コマンド AWS SAM `package`と `deploy` コマンドを使用して、インフラストラクチャ内のコンポーネントを生成します。インフラストラクチャの準備ができたら、CodeDeploy アプリケーションとデプロイグループ、更新およびデプロイする Lambda 関数、Lambda 関数をデプロイするときに実行される検証テストを含む 2 つの Lambda 関数があります。完了したら、 CloudFormation を使用して Lambda コンソールまたは でコンポーネントを表示 AWS CLI し、Lambda 関数をテストできます。

**Topics**
+ [ファイルを作成する](tutorial-lambda-create-files.md)
+ [SAM AWS アプリケーションをパッケージ化する](tutorial-lambda-sam-package.md)
+ [SAM AWS アプリケーションをデプロイする](tutorial-lambda-sam-deploy.md)
+ [(オプション) インフラストラクチャの検査とテスト](tutorial-lambda-sam-confirm-components.md)

# ファイルを作成する
<a name="tutorial-lambda-create-files"></a>

 インフラストラクチャを作成するには、次のファイルを作成する必要があります。
+ `template.yml`
+ `myDateTimeFunction.js`
+ `beforeAllowTraffic.js`
+ `afterAllowTraffic.js`

**Topics**
+ [AWS SAM テンプレートを作成する](tutorial-lambda-sam-template.md)
+ [Lambda 関数のファイルを作成します](tutorial-lambda-sam-create-lambda-function.md)
+ [[BeforeAllowTraffic] Lambda 関数のファイルを作成する](tutorial-lambda-sam-create-lambda-before-traffic.md)
+ [[AfterAllowTraffic] Lambda 関数のファイルを作成する](tutorial-lambda-sam-create-lambda-after-traffic.md)

# AWS SAM テンプレートを作成する
<a name="tutorial-lambda-sam-template"></a>

インフラストラクチャ内のコンポーネントを指定する AWS SAM テンプレートファイルを作成します。

**AWS SAM テンプレートを作成するには**

1.  `SAM-Tutorial` という名前のディレクトリを作成します。

1.  `SAM-Tutorial` ディレクトリに `template.yml` という名前のファイルを作成します。

1.  次の YAML コードを `template.yml` にコピーします。これが使用する AWS SAM テンプレートです。

   ```
   AWSTemplateFormatVersion : '2010-09-09'
   Transform: AWS::Serverless-2016-10-31
   Description: A sample SAM template for deploying Lambda functions.
   
   Resources:
   # Details about the myDateTimeFunction Lambda function
     myDateTimeFunction:
       Type: AWS::Serverless::Function
       Properties:
         Handler: myDateTimeFunction.handler
         Runtime: nodejs18.x
   # Instructs your myDateTimeFunction is published to an alias named "live".      
         AutoPublishAlias: live
   # Grants this function permission to call lambda:InvokeFunction
         Policies:
           - Version: "2012-10-17"		 	 	 
             Statement: 
             - Effect: "Allow"
               Action: 
                 - "lambda:InvokeFunction"
               Resource: '*'
         DeploymentPreference:
   # Specifies the deployment configuration      
             Type: Linear10PercentEvery1Minute
   # Specifies Lambda functions for deployment lifecycle hooks
             Hooks:
               PreTraffic: !Ref beforeAllowTraffic
               PostTraffic: !Ref afterAllowTraffic
               
   # Specifies the BeforeAllowTraffic lifecycle hook Lambda function
     beforeAllowTraffic:
       Type: AWS::Serverless::Function
       Properties:
         Handler: beforeAllowTraffic.handler
         Policies:
           - Version: "2012-10-17"		 	 	 
   # Grants this function permission to call codedeploy:PutLifecycleEventHookExecutionStatus        
             Statement: 
             - Effect: "Allow"
               Action: 
                 - "codedeploy:PutLifecycleEventHookExecutionStatus"
               Resource:
                 !Sub 'arn:aws:codedeploy:${AWS::Region}:${AWS::AccountId}:deploymentgroup:${ServerlessDeploymentApplication}/*'
           - Version: "2012-10-17"		 	 	 
   # Grants this function permission to call lambda:InvokeFunction        
             Statement: 
             - Effect: "Allow"
               Action: 
                 - "lambda:InvokeFunction"
               Resource: !Ref myDateTimeFunction.Version
         Runtime: nodejs18.x
   # Specifies the name of the Lambda hook function      
         FunctionName: 'CodeDeployHook_beforeAllowTraffic'
         DeploymentPreference:
           Enabled: false
         Timeout: 5
         Environment:
           Variables:
             NewVersion: !Ref myDateTimeFunction.Version
             
   # Specifies the AfterAllowTraffic lifecycle hook Lambda function
     afterAllowTraffic:
       Type: AWS::Serverless::Function
       Properties:
         Handler: afterAllowTraffic.handler
         Policies:
           - Version: "2012-10-17"		 	 	 
             Statement: 
   # Grants this function permission to call codedeploy:PutLifecycleEventHookExecutionStatus         
             - Effect: "Allow"
               Action: 
                 - "codedeploy:PutLifecycleEventHookExecutionStatus"
               Resource:
                 !Sub 'arn:aws:codedeploy:${AWS::Region}:${AWS::AccountId}:deploymentgroup:${ServerlessDeploymentApplication}/*'
           - Version: "2012-10-17"		 	 	 
             Statement: 
   # Grants this function permission to call lambda:InvokeFunction          
             - Effect: "Allow"
               Action: 
                 - "lambda:InvokeFunction"
               Resource: !Ref myDateTimeFunction.Version
         Runtime: nodejs18.x
   # Specifies the name of the Lambda hook function      
         FunctionName: 'CodeDeployHook_afterAllowTraffic'
         DeploymentPreference:
           Enabled: false
         Timeout: 5
         Environment:
           Variables:
             NewVersion: !Ref myDateTimeFunction.Version
   ```

このテンプレートは以下を指定します。詳細については、[AWS SAM template concepts (テンプレートの概念)](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-template-basics.html) を参照してください。

**`myDateTimeFunction` と呼ばれるLambda 関数**  
 この Lambda 関数が発行されると、テンプレート中の `AutoPublishAlias` の行は、それを `live` という名前のエイリアスにリンクします。このチュートリアルの後半で、この関数の更新により、本番トラフィックを元のバージョンから更新されたバージョンに段階的に移行 AWS CodeDeploy する によるデプロイがトリガーされます。

**2 つの Lambda デプロイ検証関数**  
 次の Lambda 関数は、CodeDeploy ライフサイクルフック中に実行されます。関数には、更新された `myDateTimeFunction` のデプロイを検証するコードが含まれています。検証テストの結果は、`PutLifecycleEventHookExecutionStatus` のAPI メソッドを使用して CodeDeploy に渡されます。検証テストが失敗すると、デプロイは失敗し、ロールバックされます。  
+  `CodeDeployHook_beforeAllowTraffic` は、`BeforeAllowTraffic` フック中に実行します。
+  `CodeDeployHook_afterAllowTraffic` は、`AfterAllowTraffic` フック中に実行します。
両方の関数の名前は `CodeDeployHook_` で始まります。`CodeDeployRoleForLambda` のロールは、このプレフィックスで始まる名前の Lambda 関数でのみ、Lambda の `invoke` のメソッドへの呼び出しを許可します。詳細については、[AWS Lambda デプロイの AppSpec 'hooks' セクション](reference-appspec-file-structure-hooks.md#appspec-hooks-lambda) および *CodeDeploy API Reference* 中の [PutLifecycleEventHookExecutionStatus](https://docs.aws.amazon.com/codedeploy/latest/APIReference/API_PutLifecycleEventHookExecutionStatus.html) を参照してください。

**更新された Lambda 関数の自動検出**  
 `AutoPublishAlias` 条件は、`myDateTimeFunction` 関数が変更されたときに検出し、`live` エイリアスを使用してデプロイするようにフレームワークに指示します。

**デプロイ設定**  
 デプロイ設定により、CodeDeploy アプリケーションが Lambda 関数の元のバージョンから新しいバージョンにトラフィックを移行するレートが決まります。このテンプレートは、事前定義されたデプロイ設定 `Linear10PercentEvery1Minute` を指定します。  
 AWS SAM テンプレートでカスタムデプロイ設定を指定することはできません。詳細については、「[CodeDeploy を使用してデプロイ設定を作成する](deployment-configurations-create.md)」を参照してください。

**デプロイライフサイクルフック関数**  
 `Hooks` セクションでは、ライフサイクルイベントフック中に実行する関数を指定します。`PreTraffic` は、`PostTraffic` フック中に実行する関数を指定します。`BeforeAllowTraffic` は、フック中に `AfterAllowTraffic` が実行する関数を指定します。

**Lambda が別の Lambda 関数を呼び出すための許可**  
 指定された`lambda:InvokeFunction`アクセス許可は、SAM AWS アプリケーションで使用されるロールに Lambda 関数を呼び出すアクセス許可を付与します。これは、`CodeDeployHook_beforeAllowTraffic` および `CodeDeployHook_afterAllowTraffic` の関数が、検証テスト中に、デプロイされた Lambda 関数を呼び出す場合に必要です。

# Lambda 関数のファイルを作成します
<a name="tutorial-lambda-sam-create-lambda-function"></a>

このチュートリアルの後半で更新してデプロイする関数のファイルを作成します。

**注記**  
 Lambda 関数は、 AWS Lambdaでサポートされている任意のランタイムを使用できます。詳細については、「[AWS Lambda ランタイム](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html)」を参照してください。

**Lambda 関数を作成するには**

1.  テキストファイルを作成し、`myDateTimeFunction.js` という名前で `SAM-Tutorial` ディレクトリに保存します。

1.  次の Node.js コードを `myDateTimeFunction.js` にコピーします。

   

   ```
   'use strict';
       
       exports.handler = function(event, context, callback) {
       
         if (event.body) {
           event = JSON.parse(event.body);
         }
       
         var sc; // Status code
         var result = ""; // Response payload
       
         switch(event.option) {
           case "date": 
             switch(event.period) {
               case "yesterday":
                 result = setDateResult("yesterday");
                 sc = 200;
                 break;
               case "today":
                 result = setDateResult();
                 sc = 200;
                 break;
               case "tomorrow":
                 result = setDateResult("tomorrow");
                 sc = 200;
                 break;
               default:
                 result = {
                   "error": "Must specify 'yesterday', 'today', or 'tomorrow'."
                 };
                 sc = 400;
                 break;
             }
             break;
             
       /*      Later in this tutorial, you update this function by uncommenting 
               this section. The framework created by AWS SAM detects the update 
               and triggers a deployment by CodeDeploy. The deployment shifts 
               production traffic to the updated version of this function.
               
               case "time":
               var d = new Date();
               var h = d.getHours();
               var mi = d.getMinutes();
               var s = d.getSeconds();
       
               result = {
                 "hour": h,
                 "minute": mi,
                 "second": s
               };
               sc = 200;
               break;
       */
             default:
               result = {
                 "error": "Must specify 'date' or 'time'."
               };
               sc = 400;
             break;
         }
       
         const response = {
           statusCode: sc,
           headers: { "Content-type": "application/json" },
           body: JSON.stringify( result )
         };
       
         callback(null, response);
       
         function setDateResult(option) {
       
           var d = new Date(); // Today
           var mo; // Month
           var da; // Day
           var y; // Year
       
           switch(option) {
             case "yesterday":
               d.setDate(d.getDate() - 1);
               break;
             case "tomorrow":
               d.setDate(d.getDate() + 1);
             default:
              break;
           }
       
           mo = d.getMonth() + 1; // Months are zero offset (0-11)
           da = d.getDate();
           y = d.getFullYear();
       
           result = {
             "month": mo,
             "day": da,
             "year": y
           };
       
           return result;
         }
       };
   ```

Lambda 関数は、昨日、今日、または明日に対して年月日を返します。このチュートリアルの後半では、指定した日または時間に関する情報(年月日または現在の時、分、秒など)を返す関数を更新するコードをコメント解除します。によって作成されたフレームワークは、関数の更新バージョン AWS SAM を検出してデプロイします。

**注記**  
 この Lambda 関数は、 AWS Cloud9 チュートリアルでも使用されます。 はクラウドベースの統合開発環境 AWS Cloud9 です。でこの関数を作成、実行、更新、デバッグする方法については AWS Cloud9、[AWS Lambda 「」のチュートリアル AWS Cloud9](https://docs.aws.amazon.com/cloud9/latest/user-guide/tutorial-lambda.html)を参照してください。

# [BeforeAllowTraffic] Lambda 関数のファイルを作成する
<a name="tutorial-lambda-sam-create-lambda-before-traffic"></a>

`beforeAllowTraffic` のフック Lambda 関数のファイルを作成します。

1.  テキストファイルを作成し、`beforeAllowTraffic.js` という名前で `SAM-Tutorial` ディレクトリに保存します。

1.  次の Node.js コードを `beforeAllowTraffic.js` にコピーします。この関数は、デプロイの `BeforeAllowTraffic` フック中に実行されます。

   ```
   'use strict';
       
       const AWS = require('aws-sdk'); 
       const codedeploy = new AWS.CodeDeploy({apiVersion: '2014-10-06'});
       var lambda = new AWS.Lambda();
       
       exports.handler = (event, context, callback) => {
       
       	console.log("Entering PreTraffic Hook!");
       	
       	// Read the DeploymentId and LifecycleEventHookExecutionId from the event payload
         var deploymentId = event.DeploymentId;
       	var lifecycleEventHookExecutionId = event.LifecycleEventHookExecutionId;
       
       	var functionToTest = process.env.NewVersion;
       	console.log("BeforeAllowTraffic hook tests started");
       	console.log("Testing new function version: " + functionToTest);
       
       	// Create parameters to pass to the updated Lambda function that
       	// include the newly added "time" option. If the function did not
       	// update, then the "time" option is invalid and function returns
       	// a statusCode of 400 indicating it failed.
       	var lambdaParams = {
       		FunctionName: functionToTest,    
       		Payload: "{\"option\": \"time\"}", 
       		InvocationType: "RequestResponse"
       	};
       
       	var lambdaResult = "Failed";
       	// Invoke the updated Lambda function.
       	lambda.invoke(lambdaParams, function(err, data) {
       		if (err){	// an error occurred
       			console.log(err, err.stack);
       			lambdaResult = "Failed";
       		}
       		else{	// successful response
       			var result = JSON.parse(data.Payload);
       			console.log("Result: " +  JSON.stringify(result));
             console.log("statusCode: " + result.statusCode);
             
             // Check if the status code returned by the updated
             // function is 400. If it is, then it failed. If 
             // is not, then it succeeded.
       			if (result.statusCode != "400"){
               console.log("Validation succeeded");
       				lambdaResult = "Succeeded";
             }
             else {
               console.log("Validation failed");
             }
       
       			// Complete the PreTraffic Hook by sending CodeDeploy the validation status
       			var params = {
       				deploymentId: deploymentId,
       				lifecycleEventHookExecutionId: lifecycleEventHookExecutionId,
       				status: lambdaResult // status can be 'Succeeded' or 'Failed'
       			};
       			
       			// Pass CodeDeploy the prepared validation test results.
       			codedeploy.putLifecycleEventHookExecutionStatus(params, function(err, data) {
       				if (err) {
       					// Validation failed.
       					console.log("CodeDeploy Status update failed");
       					console.log(err, err.stack);
       					callback("CodeDeploy Status update failed");
       				} else {
       					// Validation succeeded.
       					console.log("CodeDeploy status updated successfully");
       					callback(null, "CodeDeploy status updated successfully");
       				}
       			});
       		}  
       	});
       }
   ```

# [AfterAllowTraffic] Lambda 関数のファイルを作成する
<a name="tutorial-lambda-sam-create-lambda-after-traffic"></a>

`afterAllowTraffic` のフック Lambda 関数のファイルを作成します。

1.  テキストファイルを作成し、`afterAllowTraffic.js` という名前で `SAM-Tutorial` ディレクトリに保存します。

1.  次の Node.js コードを `afterAllowTraffic.js` にコピーします。この関数は、デプロイの `AfterAllowTraffic` フック中に実行されます。

   ```
   'use strict';
       
       const AWS = require('aws-sdk');
       const codedeploy = new AWS.CodeDeploy({apiVersion: '2014-10-06'});
       var lambda = new AWS.Lambda();
       
       exports.handler = (event, context, callback) => {
       
       	console.log("Entering PostTraffic Hook!");
       	
       	// Read the DeploymentId and LifecycleEventHookExecutionId from the event payload
         var deploymentId = event.DeploymentId;
       	var lifecycleEventHookExecutionId = event.LifecycleEventHookExecutionId;
       
       	var functionToTest = process.env.NewVersion;
       	console.log("AfterAllowTraffic hook tests started");
       	console.log("Testing new function version: " + functionToTest);
       
       	// Create parameters to pass to the updated Lambda function that
       	// include the original "date" parameter. If the function did not 
       	// update as expected, then the "date" option might be invalid. If 
       	// the parameter is invalid, the function returns
       	// a statusCode of 400 indicating it failed.
       	var lambdaParams = {
       		FunctionName: functionToTest,    
       		Payload: "{\"option\": \"date\", \"period\": \"today\"}", 
       		InvocationType: "RequestResponse"
       	};
       
       	var lambdaResult = "Failed";
       	// Invoke the updated Lambda function.
       	lambda.invoke(lambdaParams, function(err, data) {
       		if (err){	// an error occurred
       			console.log(err, err.stack);
       			lambdaResult = "Failed";
       		}
       		else{	// successful response
       			var result = JSON.parse(data.Payload);
       			console.log("Result: " +  JSON.stringify(result));
             console.log("statusCode: " + result.statusCode);
             
             // Check if the status code returned by the updated
             // function is 400. If it is, then it failed. If 
             // is not, then it succeeded.
       			if (result.statusCode != "400"){
               console.log("Validation of time parameter succeeded");
       				lambdaResult = "Succeeded";
             }
             else {
               console.log("Validation failed");
             }
       
       			// Complete the PostTraffic Hook by sending CodeDeploy the validation status
       			var params = {
       				deploymentId: deploymentId,
       				lifecycleEventHookExecutionId: lifecycleEventHookExecutionId,
       				status: lambdaResult // status can be 'Succeeded' or 'Failed'
       			};
       			
       			// Pass CodeDeploy the prepared validation test results.
       			codedeploy.putLifecycleEventHookExecutionStatus(params, function(err, data) {
       				if (err) {
       					// Validation failed.
       					console.log("CodeDeploy Status update failed");
       					console.log(err, err.stack);
       					callback("CodeDeploy Status update failed");
       				} else {
       					// Validation succeeded.
       					console.log("CodeDeploy status updated successfully");
       					callback(null, "CodeDeploy status updated successfully");
       				}
       			});
       		}  
       	});
       }
   ```

# SAM AWS アプリケーションをパッケージ化する
<a name="tutorial-lambda-sam-package"></a>

 これで、`SAM-Tutorial` ディレクトリに次の 4 つのファイルがあるはずです。
+ `beforeAllowTraffic.js`
+ `afterAllowTraffic.js`
+ `myDateTimeFunction.js`
+ `template.yml`

 これで、 AWS SAM **sam package** コマンドを使用して、Lambda 関数と CodeDeploy アプリケーションのアーティファクトを作成してパッケージ化する準備ができました。アーティファクトは S3 バケットにアップロードされます。コマンドの出力は、`package.yml` という新しいファイルです。このファイルは、次のステップで AWS SAM **sam deploy** コマンドによって使用されます。

**注記**  
 **sam package** のコマンドのさらなる詳細については、*AWS SAM デベロッパーガイド* の [AWS Serverless Application Model CLI command reference](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-command-reference.html) を参照してください。

 `SAM-Tutorial` ディレクトリで、以下を実行します。

```
sam package \
  --template-file template.yml \
  --output-template-file package.yml \
  --s3-bucket amzn-s3-demo-bucket
```

`s3-bucket` のパラメータには、このチュートリアルの前提条件として作成した Amazon S3 バケットを指定します。は、 AWS SAM **sam deploy** コマンドで使用される新しいファイルの名前`output-template-file`を指定します。

# SAM AWS アプリケーションをデプロイする
<a name="tutorial-lambda-sam-deploy"></a>

 `package.yml` ファイルで AWS SAM **sam deploy** コマンドを使用して、 を使用して Lambda 関数と CodeDeploy アプリケーションおよびデプロイグループを作成します CloudFormation。

**注記**  
**sam deploy** のコマンドのさらなる詳細については、*AWS Serverless Application Model デベロッパーガイド* の [AWS SAM CLI command reference](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-command-reference.html) を参照してください。

 `SAM-Tutorial` ディレクトリで、次のコマンドを実行します。

```
sam deploy \
  --template-file package.yml \
  --stack-name my-date-time-app \
  --capabilities CAPABILITY_IAM
```

 IAM ロールの作成を `--capabilities CAPABILITY_IAM` に許可するには、 CloudFormation のパラメータが必要です。

# (オプション) インフラストラクチャの検査とテスト
<a name="tutorial-lambda-sam-confirm-components"></a>

 このトピックでは、インフラストラクチャコンポーネントを表示し、Lambda 関数をテストする方法を示します。

**`sam deploy` の実行後にスタックの結果を表示するには**

1. [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/) で CloudFormation コンソールを開きます。

1.  ナビゲーションペインで、[**Stacks**] を選択します。`my-date-time-app` スタックが上部に表示されます。

1.  [**イベント**] タブを選択して、完了したイベントを確認します。スタックの作成の進行中に、イベントを表示できます。スタックの作成が完了すると、すべてのスタック作成イベントを表示できます。

1.  スタックを選択した状態で、[**リソース**] を選択します。**タイプ** 列に、Lambda関数、`myDateTimeFunction` 、`CodeDeployHook_beforeAllowTraffic` および `CodeDeployHook_afterAllowTraffic` が表示されます。Lambda 関数の **Physical ID** の各列には、Lambda コンソールで関数を表示するためのリンクが含まれています。
**注記**  
 `myDateTimeFunction` Lambda 関数の名前には CloudFormation スタックの名前が付加され、識別子が追加されているため、 のようになります`my-date-time-app-myDateTimeFunction-123456ABCDEF`。

1. [https://console.aws.amazon.com/codedeploy/](https://console.aws.amazon.com/codedeploy/) で、CodeDeploy コンソールを開きます。

1.  ナビゲーションペインで [**デプロイ**] を展開し、[**アプリケーション**] を選択します。

1.  で作成された新しい CodeDeploy アプリケーションは、 で始まる名前 CloudFormation で表示されます`my-date-time-app-ServerlessDeploymentApplication`。このアプリケーションを選択します。

1.  `my-date-time-app-myDateTimeFunctionDeploymentGroup` で始まる名前のデプロイグループが表示されます。このデプロイグループを選択します。

    [**デプロイ設定**] に、[**CodeDeployDefault.LambdaLinear10PercentEvery1Minute**] が表示されます。

**(オプション) 関数をテストするには (コンソール)**

1. [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/) で AWS Lambda コンソールを開きます。

1.  ナビゲーションペインで、`my-date-time-app-myDateTimeFunction` 関数を選択します。コンソールでは、名前に識別子が含まれているため、`my-date-time-app-myDateTimeFunction-123456ABCDEF` のようになります。

1.  **[テスト]** を選択します。

1.  [**イベント名**] にテストイベントの名前を入力します。

1.  テストイベントに以下を入力し、[**作成**] を選択します。

   ```
   {
     "option": "date",
     "period": "today"
   }
   ```

1.  **[テスト]** を選択します。テストイベントのリストには、テストイベントのみが表示されます。

    [**実行結果**] に [**成功**] と表示されます。

1.  [**実行結果**] で、[**詳細**] を展開して結果を表示します。現在の年月日が表示されます。

**(オプション) 関数をテストするには (AWS CLI)**

1.  Lambda 関数の ARN を配置します。関数を表示しているときに、Lambda コンソールの上部に表示されます。

1.  以下のコマンドを実行してください。[*your-function-arn*] を関数 ARN に置き換えます。

   ```
   aws lambda invoke \
   --function your-function-arn \
   --cli-binary-format raw-in-base64-out \
   --payload "{\"option\": \"date\", \"period\": \"today\"}" out.txt
   ```

1.  `out.txt` を開き、結果に現在の年月日が含まれていることを確認します。

# ステップ 2: Lambda 関数を更新します
<a name="tutorial-lambda-sam-update-function"></a>

 このトピックでは、`myDateTimeFunction.js` ファイルを更新します。次のステップでは、このファイルを使用して、更新された関数をデプロイします。これは、本稼働トラフィックを Lambda 関数の現在のバージョンから更新されたバージョンに移行することによってデプロイするために、CodeDeploy をトリガーします。

**Lambda 関数を更新するには**

1.  `myDateTimeFunction.js` を開きます。

1.  2 つのコメントマーカー(「`/*`」と「`*/`」)および `case` ブロック内の `time` という名前の `switch` の開始と終了にある説明テキストを削除します。

    コメントされていないコードを使用すると、新しいパラメータ `time` を関数に渡すことができます。`time` を更新された関数に渡すと、現在の `hour`、`minute`、および `second` が返されます。

1.  `myDateTimeFunction.js` を保存します。次のようになります。

   ```
   'use strict';
   
   exports.handler = function(event, context, callback) {
   
     if (event.body) {
       event = JSON.parse(event.body);
     }
   
     var sc; // Status code
     var result = ""; // Response payload
   
     switch(event.option) {
       case "date":
         switch(event.period) {
           case "yesterday":
             result = setDateResult("yesterday");
             sc = 200;
             break;
           case "today":
             result = setDateResult();
             sc = 200;
             break;
           case "tomorrow":
             result = setDateResult("tomorrow");
             sc = 200;
             break;
           default:
             result = {
               "error": "Must specify 'yesterday', 'today', or 'tomorrow'."
             };
             sc = 400;
             break;
         }
         break;
         case "time":
           var d = new Date();
           var h = d.getHours();
           var mi = d.getMinutes();
           var s = d.getSeconds();
   
           result = {
             "hour": h,
             "minute": mi,
             "second": s
           };
           sc = 200;
           break;
   
         default:
           result = {
             "error": "Must specify 'date' or 'time'."
           };
           sc = 400;
         break;
     }
   
     const response = {
       statusCode: sc,
       headers: { "Content-type": "application/json" },
       body: JSON.stringify( result )
     };
   
     callback(null, response);
   
     function setDateResult(option) {
   
       var d = new Date(); // Today
       var mo; // Month
       var da; // Day
       var y; // Year
   
       switch(option) {
         case "yesterday":
           d.setDate(d.getDate() - 1);
           break;
         case "tomorrow":
           d.setDate(d.getDate() + 1);
         default:
          break;
       }
   
       mo = d.getMonth() + 1; // Months are zero offset (0-11)
       da = d.getDate();
       y = d.getFullYear();
   
       result = {
         "month": mo,
         "day": da,
         "year": y
       };
   
       return result;
     }
   };
   ```

# ステップ 3: 更新された Lambda 関数をデプロイします。
<a name="tutorial-lambda-sam-deploy-update"></a>

 このステップでは、更新された `myDateTimeFunction.js` を使用して、Lambda 関数のデプロイを更新して開始します。CodeDeploy または AWS Lambda コンソールでデプロイの進行状況をモニタリングできます。

 AWS SAM テンプレートの `AutoPublishAlias: live`行により、インフラストラクチャは`live`エイリアスを使用する関数の更新を検出します。関数を更新すると、CodeDeploy によるデプロイがトリガーされます。これにより、本稼働トラフィックが関数の元のバージョンから更新されたバージョンに移行されます。

 **sam package** と **sam deploy** のコマンドは、Lambda 関数のデプロイを更新およびトリガーするために使用されます。これらのコマンドは、[SAM AWS アプリケーションをパッケージ化する](tutorial-lambda-sam-package.md) および [SAM AWS アプリケーションをデプロイする](tutorial-lambda-sam-deploy.md) で実行しました。

**更新された Lambda 関数をデプロイするには**

1.  `SAM-Tutorial` ディレクトリで、次のコマンドを実行します。

   ```
   sam package \
     --template-file template.yml \
     --output-template-file package.yml  \
     --s3-bucket amzn-s3-demo-bucket
   ```

    これにより、S3 バケットで更新された Lambda 関数を参照する新しいアーティファクトのセットが作成されます。

1.  `SAM-Tutorial` ディレクトリで、次のコマンドを実行します。

   ```
   sam deploy \
     --template-file package.yml \
     --stack-name my-date-time-app \
     --capabilities CAPABILITY_IAM
   ```

   スタック名はまだ であるため`my-date-time-app`、 はこれがスタックの更新である CloudFormation ことを認識します。更新されたスタックを表示するには、 CloudFormation コンソールを返し、ナビゲーションペインから **スタック**を選択します。

**(オプション)デプロイ中にトラフィックを表示するには(CodeDeploy コンソール)**

1. [https://console.aws.amazon.com/codedeploy/](https://console.aws.amazon.com/codedeploy/) で、CodeDeploy コンソールを開きます。

1.  ナビゲーションペインで、[**アプリケーション**] を展開し、[**my-date-time-app-ServerlessDeploymentApplication**] アプリケーションを選択します。

1.  [**デプロイグループ**] で、アプリケーションのデプロイグループを選択します。ステータスは [**進行中**]になります。

1.  [**Deployment group history (デプロイグループ履歴)**] で、進行中のデプロイを選択します。

   [**トラフィックの移行**] の進行状況バーと、このページの [**Original**] ボックスと **置換**] ボックスの割合に、進行状況が表示されます。  
![\[CodeDeploy コンソールのトラフィックシフトの進行状況セクション。\]](http://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/images/lambda-tutorial-codedeploy-console-20-percent-deployed.png)

**(オプション) デプロイ中にトラフィックを表示するには(Lambda コンソール)**

1. [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/) で AWS Lambda コンソールを開きます。

1.  ナビゲーションペインで、`my-date-time-app-myDateTimeFunction` 関数を選択します。コンソールでは、名前に識別子が含まれているため、`my-date-time-app-myDateTimeFunction-123456ABCDEF` のようになります。

1.  **Aliases**、**live** の順に選択します。

元の関数バージョン(バージョン 1)と更新された関数バージョン(バージョン 2)の横の重みは、この AWS Lambda コンソールページがロードされた時点で各バージョンに提供されているトラフィック量を示します。ページでは、時間が経過しても重みは更新されません。ページを 1 分に 1 回更新すると、バージョン 1 の重みは 10% 減り、バージョン 2 の重みは 10% 増加します。

![\[CodeDeploy コンソールのエイリアスセクション。\]](http://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/images/lambda-tutorial-lambda-console-20-percent-deployed.png)


# ステップ 4: デプロイの結果を表示する
<a name="tutorial-lambda-sam-deploy-view-results"></a>

このステップでは、デプロイの結果を表示します。デプロイが成功すると、更新された Lambda 関数が本稼働トラフィックを受信することを確認できます。デプロイが失敗した場合、CloudWatch Logs を使用して、デプロイのライフサイクルフックの間に実行される Lambda 関数の検証テストの出力を表示できます。

**Topics**
+ [デプロイされた関数をテストする](#tutorial-lambda-sam-deploy-test-deployed-function)
+ [CloudWatch Logs でのフックイベントを表示します。](#tutorial-lambda-view-hook-events)

## デプロイされた関数をテストする
<a name="tutorial-lambda-sam-deploy-test-deployed-function"></a>

 **sam deploy** のコマンドは、`my-date-time-app-myDateTimeFunction` のLambda 関数を更新します。関数のバージョンが 2 に更新され、`live` エイリアスに追加されます。

**Lambda コンソール中の更新を見るには**

1. [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/) で AWS Lambda コンソールを開きます。

1.  ナビゲーションペインで、`my-date-time-app-myDateTimeFunction` 関数を選択します。コンソールでは、名前に識別子が含まれているため、`my-date-time-app-myDateTimeFunction-123456ABCDEF` のようになります。

1.  [**Qualifiers (修飾子)**]、[**エイリアス**] の順に選択します。デプロイが完了した後(約 10 分)、`live` エイリアスに [**バージョン: 2**] と表示されます。  
![\[CodeDeploy コンソールのエイリアスセクション。\]](http://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/images/lambda-tutorial-function-version.png)

1.  [**関数コード**] で、関数のソースコードを表示します。変更が表示されます。

1.  (オプション)[ステップ 2: Lambda 関数を更新します](tutorial-lambda-sam-update-function.md) のテスト手順を使用して、更新された関数をテストできます。次のペイロードを使用して新しいテストイベントを作成し、結果に現在の時、分、秒が含まれていることを確認します。

   ```
   {
       "option": "time"
     }
   ```

    を使用して更新された関数を AWS CLI テストするには、次のコマンドを実行し、 `out.txt`を開いて、結果に現在の時間、分、秒が含まれていることを確認します。

   ```
   aws lambda invoke --function your-function-arn --payload "{\"option\": \"time\"}" out.txt 
   ```
**注記**  
 デプロイが完了する前に を使用して関数を AWS CLI テストすると、予期しない結果が表示されることがあります。これは、CodeDeploy がトラフィックの 10% を毎分更新バージョンに段階的に移行するためです。デプロイ中、一部のトラフィックは引き続き元のバージョンを指すため、`aws lambda invoke` は元のバージョンを使用する場合があります。10 分後には、デプロイが完了し、すべてのトラフィックが関数の新しいバージョンを指し示します。

## CloudWatch Logs でのフックイベントを表示します。
<a name="tutorial-lambda-view-hook-events"></a>

 `BeforeAllowTraffic` のフック中に、CodeDeploy は `CodeDeployHook_beforeAllowTraffic` の Lambda 関数を実行します。`AfterAllowTraffic` のフック中に、CodeDeploy は `CodeDeployHook_afterAllowTraffic` の Lambda 関数を実行します。各関数は、新しい `time` パラメータを使用して関数の更新バージョンを呼び出す検証テストを実行します。Lambda 関数の更新が成功した場合、`time` のオプションによるエラーは発生せず、検証は成功します。関数が更新されなかった場合、認識されないパラメータによってエラーが発生し、検証が失敗します。これらの検証テストはデモンストレーションのみを目的としています。デプロイを検証するには独自のテストを記述します。CloudWatch Logs コンソールを使用して、検証テストを表示できます。

**CodeDeploy フックイベントを表示するには**

1. CloudWatch コンソールの [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/) を開いてください。

1.  ナビゲーションペインで、[**Logs (ログ)**] を選択します。

1.  ロググループのリストから、[**/aws/lambda/CodeDeployHook\$1beforeAllowTraffic**] または [**/aws/lambda/CodeDeployHook\$1afterAllowTraffic**] を選択します。

1.  ログストリームを選択します。1 つのみ表示されます。

1.  イベントを展開して詳細を表示します。  
![\[CodeDeployHook ロググループのログストリーム。\]](http://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/images/lambda-tutorial-cloudwatch.png)

# ステップ 5：クリーンアップ
<a name="tutorial-lambda-clean-up"></a>

このチュートリアルで使用したリソースの追加料金を回避するには、 AWS SAM テンプレートによって作成されたリソースと、Lambda 検証関数によって作成された CloudWatch ログを削除します。

**CloudFormation スタックを削除するには**

1. にサインイン AWS マネジメントコンソール し、[https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/) で CloudFormation コンソールを開きます。

1. [**スタック**] 列で、`my-date-time-app` スタックを選択し、[**削除**] を選択します。

1. プロンプトが表示されたら、**[スタックの削除]** を選択します。Lambda 関数、CodeDeploy アプリケーションとデプロイグループ、および によって作成された IAM ロール AWS SAM は削除されます。

**CloudWatch Logs でログを削除するには**

1. CloudWatch コンソールの [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/) を開いてください。

1.  ナビゲーションペインで、[**Logs (ログ)**] を選択します。

1.  ロググループのリストから、[**/aws/lambda/CodeDeployHook\$1beforeAllowTraffic**] の横にあるボタンを選択します。

1.  [**アクション**] から、[**ロググループを削除する**] を選択し、次に [**はい、削除します**] を選択します。

1.  ロググループのリストから、[**/aws/lambda/CodeDeployHook\$1afterAllowTraffic**] の横にあるボタンを選択します。

1.  [**アクション**] から、[**ロググループを削除する**] を選択し、次に [**はい、削除します**] を選択します。