

# Tutorial: Deploy an updated Lambda function with CodeDeploy and the AWS Serverless Application Model
<a name="tutorial-lambda-sam"></a>

AWS SAM is an open-source framework for building serverless applications. It transforms and expands YAML syntax in a AWS SAM template into CloudFormation syntax to build serverless applications, such as a Lambda function. For more information, see [What is the AWS Serverless Application Model?](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html) 

 In this tutorial, you use AWS SAM to create a solution that does the following: 
+  Creates your Lambda function. 
+  Creates your CodeDeploy application and deployment group. 
+  Creates two Lambda functions that execute deployment validation tests during CodeDeploy lifecycle hooks. 
+  Detects when your Lambda function is updated. The updating of the Lambda function triggers a deployment by CodeDeploy that incrementally shifts production traffic from the original version of your Lambda function to the updated version. 

**Note**  
This tutorial requires you to create resources that might result in charges to your AWS account. These include possible charges for CodeDeploy, Amazon CloudWatch, and AWS Lambda. For more information, see [CodeDeploy pricing](https://aws.amazon.com/codedeploy/pricing/), [Amazon CloudWatch pricing](https://aws.amazon.com/cloudwatch/pricing/), and [AWS Lambda pricing](https://aws.amazon.com/lambda/pricing/).

**Topics**
+ [Prerequisites](tutorial-lambda-sam-prereqs.md)
+ [Step 1: Set up your infrastructure](tutorial-lambda-sam-setup-infrastructure.md)
+ [Step 2: Update the Lambda function](tutorial-lambda-sam-update-function.md)
+ [Step 3: Deploy the updated Lambda function](tutorial-lambda-sam-deploy-update.md)
+ [Step 4: View your deployment results](tutorial-lambda-sam-deploy-view-results.md)
+ [Step 5: Clean up](tutorial-lambda-clean-up.md)

# Prerequisites
<a name="tutorial-lambda-sam-prereqs"></a>

To complete this tutorial, you must first:
+  Complete the steps in [Getting started with CodeDeploy](getting-started-codedeploy.md). 
+  Install the AWS Serverless Application Model CLI. For information, see [Install the AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html). 
+  Create an S3 bucket. AWS SAM uploads the artifacts that are referenced in your [AWS SAM template](https://docs.aws.amazon.com/en_us/codedeploy/latest/userguide/tutorial-lambda-sam-template.html) into this bucket. 

# Step 1: Set up your infrastructure
<a name="tutorial-lambda-sam-setup-infrastructure"></a>

 This topic shows you how to use AWS SAM to create files for your AWS SAM template and your Lambda functions. Then, you use the AWS SAM `package` and `deploy` commands to generate the components in your infrastructure. When your infrastructure is ready, you have a CodeDeploy application and deployment group, the Lambda function to update and deploy, and two Lambda functions that contain validation tests that run when you deploy the Lambda function. When complete, you can use CloudFormation to view your components in the Lambda console or the AWS CLI to test your Lambda function. 

**Topics**
+ [Create your files](tutorial-lambda-create-files.md)
+ [Package the AWS SAM application](tutorial-lambda-sam-package.md)
+ [Deploy the AWS SAM application](tutorial-lambda-sam-deploy.md)
+ [(Optional) inspect and test your infrastructure](tutorial-lambda-sam-confirm-components.md)

# Create your files
<a name="tutorial-lambda-create-files"></a>

 To create your infrastructure, you must create the following files: 
+ `template.yml`
+ `myDateTimeFunction.js`
+ `beforeAllowTraffic.js`
+ `afterAllowTraffic.js`

**Topics**
+ [Create your AWS SAM template](tutorial-lambda-sam-template.md)
+ [Create a file for your Lambda function](tutorial-lambda-sam-create-lambda-function.md)
+ [Create a file for your BeforeAllowTraffic Lambda function](tutorial-lambda-sam-create-lambda-before-traffic.md)
+ [Create a file for your AfterAllowTraffic Lambda function](tutorial-lambda-sam-create-lambda-after-traffic.md)

# Create your AWS SAM template
<a name="tutorial-lambda-sam-template"></a>

Create an AWS SAM template file that specifies the components in your infrastructure.

**To create your AWS SAM template**

1.  Create a directory named `SAM-Tutorial`. 

1.  In your `SAM-Tutorial` directory, create a file named `template.yml`. 

1.  Copy the following YAML code into `template.yml`. This is your AWS SAM template. 

   ```
   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
   ```

This template specifies the following. For more information, see [AWS SAM template concepts](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-template-basics.html).

**A Lambda function called `myDateTimeFunction`**  
 When this Lambda function is published, the `AutoPublishAlias` line in the template links it to an alias named `live`. Later in this tutorial, an update to this function triggers a deployment by AWS CodeDeploy that incrementally shifts production traffic from the original version to the updated version. 

**Two Lambda deployment validation functions**  
 The following Lambda functions are executed during CodeDeploy lifecycle hooks. The functions contain code that validate the deployment of the updated `myDateTimeFunction`. The result of the validation tests are passed to CodeDeploy using its `PutLifecycleEventHookExecutionStatus` API method. If a validation test fails, the deployment fails and is rolled back.   
+  `CodeDeployHook_beforeAllowTraffic` runs during the `BeforeAllowTraffic` hook. 
+  `CodeDeployHook_afterAllowTraffic` runs during the `AfterAllowTraffic` hook. 
The name of both functions start with `CodeDeployHook_`. The `CodeDeployRoleForLambda` role allows calls to the Lambda `invoke` method only in Lambda functions with names that start with this prefix. For more information, see [AppSpec 'hooks' section for an AWS Lambda deployment](reference-appspec-file-structure-hooks.md#appspec-hooks-lambda) and [PutLifecycleEventHookExecutionStatus](https://docs.aws.amazon.com/codedeploy/latest/APIReference/API_PutLifecycleEventHookExecutionStatus.html) in the *CodeDeploy API Reference*. 

**Automatic detection of an updated Lambda function**  
 The `AutoPublishAlias` term tells the framework to detect when the `myDateTimeFunction` function changes, and then deploy it using the `live` alias. 

**A deployment configuration**  
 The deployment configuration determines the rate at which your CodeDeploy application shifts traffic from the original version of the Lambda function to the new version. This template specifies the predefined deployment configuration `Linear10PercentEvery1Minute`.   
 You cannot specify a custom deployment configuration in an AWS SAM template. For more information, see [Create a deployment configuration with CodeDeploy](deployment-configurations-create.md).

**Deployment lifecycle hook functions**  
 The `Hooks` section specifies the functions to run during lifecycle event hooks. `PreTraffic` specifies the function that runs during the `BeforeAllowTraffic` hook. `PostTraffic` specifies the function that runs during the `AfterAllowTraffic` hook. 

**Permissions for Lambda to invoke another Lambda function**  
 The specified `lambda:InvokeFunction` permission grants the role used by the AWS SAM application permission to invoke a Lambda function. This is required when the `CodeDeployHook_beforeAllowTraffic` and `CodeDeployHook_afterAllowTraffic` functions invoke the deployed Lambda function during validation tests. 

# Create a file for your Lambda function
<a name="tutorial-lambda-sam-create-lambda-function"></a>

Create the file for the function you update and deploy later in this tutorial.

**Note**  
 A Lambda function can use any runtime supported by AWS Lambda. For more information, see [AWS Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html). 

**To create your Lambda function**

1.  Create a text file and save it as `myDateTimeFunction.js` in the `SAM-Tutorial` directory. 

1.  Copy the following Node.js code into `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;
         }
       };
   ```

The Lambda function returns the day, month, and year for yesterday, today, or tomorrow. Later in this tutorial, you uncomment code that updates the function to return information about the day or time you specify (for example, the day, month, and year, or the current hour, minute, and second). The framework created by AWS SAM detects and deploys the updated version of the function. 

**Note**  
 This Lambda function is also used in an AWS Cloud9 tutorial. AWS Cloud9 is a cloud-based integrated development environment. For information about how to create, execute, update, and debug this function in AWS Cloud9, see [AWS Lambda tutorial for AWS Cloud9](https://docs.aws.amazon.com/cloud9/latest/user-guide/tutorial-lambda.html). 

# Create a file for your BeforeAllowTraffic Lambda function
<a name="tutorial-lambda-sam-create-lambda-before-traffic"></a>

Create the file for your `beforeAllowTraffic` hook Lambda function.

1.  Create a text file and save it as `beforeAllowTraffic.js` in the `SAM-Tutorial` directory. 

1.  Copy the following Node.js code into `beforeAllowTraffic.js`. This function executes during your deployment's `BeforeAllowTraffic` hook. 

   ```
   '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");
       				}
       			});
       		}  
       	});
       }
   ```

# Create a file for your AfterAllowTraffic Lambda function
<a name="tutorial-lambda-sam-create-lambda-after-traffic"></a>

Create the file for your `afterAllowTraffic` hook Lambda function.

1.  Create a text file and save it as `afterAllowTraffic.js` in the `SAM-Tutorial` directory. 

1.  Copy the following Node.js code into `afterAllowTraffic.js`. This function executes during your deployment's `AfterAllowTraffic` hook. 

   ```
   '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");
       				}
       			});
       		}  
       	});
       }
   ```

# Package the AWS SAM application
<a name="tutorial-lambda-sam-package"></a>

 You should now have four files in your `SAM-Tutorial` directory: 
+ `beforeAllowTraffic.js`
+ `afterAllowTraffic.js`
+ `myDateTimeFunction.js`
+ `template.yml`

 You are now ready to use the AWS SAM **sam package** command to create and package artifacts for your Lambda functions and CodeDeploy application. The artifacts are uploaded to an S3 bucket. The output of the command is a new file called `package.yml`. This file is used by the AWS SAM **sam deploy** command in the next step. 

**Note**  
 For more information on the **sam package** command, see [AWS SAM CLI command reference](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-command-reference.html) in the *AWS Serverless Application Model Developer Guide*. 

 In the `SAM-Tutorial` directory, run the following. 

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

For the `s3-bucket` parameter, specify the Amazon S3 bucket you created as a prerequisite for this tutorial. The `output-template-file` specifies the name of the new file that is used by the AWS SAM **sam deploy** command.

# Deploy the AWS SAM application
<a name="tutorial-lambda-sam-deploy"></a>

 Use the AWS SAM **sam deploy** command with the `package.yml` file to create your Lambda functions and CodeDeploy application and deployment group using CloudFormation. 

**Note**  
For more information on the **sam deploy** command, see [AWS SAM CLI command reference](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-command-reference.html) in the *AWS Serverless Application Model Developer Guide*. 

 In the `SAM-Tutorial` directory, run the following command. 

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

 The `--capabilities CAPABILITY_IAM` parameter is required to authorize CloudFormation to create IAM roles. 

# (Optional) inspect and test your infrastructure
<a name="tutorial-lambda-sam-confirm-components"></a>

 This topic shows how to view your infrastructure components and test your Lambda function. 

**To see the result of your stack after you run `sam deploy`**

1. Open the CloudFormation console at [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/).

1.  In the navigation pane, choose **Stacks**. The `my-date-time-app` stack appears at the top. 

1.  Choose the **Events** tab to see which events are complete. You can view the events while the stack creation is in progress. When creation of the stack is complete, you can see all stack creation events. 

1.  With your stack selected, choose **Resources**. In the **Type** column, you can see your Lambda functions, `myDateTimeFunction`, `CodeDeployHook_beforeAllowTraffic`, and `CodeDeployHook_afterAllowTraffic`. The **Physical ID** column of each of your Lambda functions contains a link to view the functions in the Lambda console. 
**Note**  
 The name of the `myDateTimeFunction` Lambda function is prepended with the name of the CloudFormation stack and has an identifier added to it, so it looks like `my-date-time-app-myDateTimeFunction-123456ABCDEF`. 

1. Open the CodeDeploy console at [https://console.aws.amazon.com/codedeploy/](https://console.aws.amazon.com/codedeploy/).

1.  In the navigation pane, expand **Deploy**, and then choose **Applications**. 

1.  You should see a new CodeDeploy application created by CloudFormation with a name that starts with `my-date-time-app-ServerlessDeploymentApplication`. Choose this application. 

1.  You should see a deployment group with a name that starts with `my-date-time-app-myDateTimeFunctionDeploymentGroup`. Choose this deployment group. 

    Under **Deployment configuration**, you should see **CodeDeployDefault.LambdaLinear10PercentEvery1Minute**. 

**(Optional) to test your function (console)**

1. Open the AWS Lambda console at [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/).

1.  From the navigation pane, choose your `my-date-time-app-myDateTimeFunction` function. In the console, its name contains an identifier, so it looks like `my-date-time-app-myDateTimeFunction-123456ABCDEF`. 

1.  Choose **Test**. 

1.  In **Event name**, enter a name for your test event. 

1.  Enter the following for your test event, and then choose **Create**. 

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

1.  Choose **Test**. You should see only your test event in the list of test events. 

    For **Execution result**, you should see **succeeded**. 

1.  Under **Execution result**, expand **Details** to see the results. You should see the current month, day, and year. 

**(Optional) to test your function (AWS CLI)**

1.  Locate the ARN of your Lambda function. It appears at the top of the Lambda console when you are viewing your function. 

1.  Run the following command. Replace *your-function-arn* with the function ARN. 

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

1.  Open `out.txt` to confirm the result contains the current month, day, and year. 

# Step 2: Update the Lambda function
<a name="tutorial-lambda-sam-update-function"></a>

 In this topic, you update your `myDateTimeFunction.js` file. In the next step, you use the file to deploy the updated function. This triggers CodeDeploy to deploy it by shifting production traffic from the current version of the Lambda function to the updated version. 

**To update your Lambda function**

1.  Open `myDateTimeFunction.js`. 

1.  Remove the two comment markers ("`/*`" and "`*/`") and the explanatory text at the start and end of the `case` named `time` in the `switch` block. 

    The uncommented code lets you pass a new parameter, `time`, to the function. If you pass `time` to the updated function, it returns the current `hour`, `minute`, and `second`. 

1.  Save `myDateTimeFunction.js`. It should look like the following: 

   ```
   '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;
     }
   };
   ```

# Step 3: Deploy the updated Lambda function
<a name="tutorial-lambda-sam-deploy-update"></a>

 In this step, you use your updated `myDateTimeFunction.js` to update and initiate the deployment of your Lambda function. You can monitor the deployment progress in the CodeDeploy or AWS Lambda console. 

 The `AutoPublishAlias: live` line in your AWS SAM template causes your infrastructure to detect updates to functions that use the `live` alias. An update to your function triggers a deployment by CodeDeploy that shifts production traffic from the original version of the function to the updated version. 

 The **sam package** and **sam deploy** commands are used to update and trigger the deployment of your Lambda function. You executed these commands in [Package the AWS SAM application](tutorial-lambda-sam-package.md) and [Deploy the AWS SAM application](tutorial-lambda-sam-deploy.md). 

**To deploy your updated Lambda function**

1.  In the `SAM-Tutorial` directory, run the following command. 

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

    This creates a new set of artifacts that reference your updated Lambda function in your S3 bucket. 

1.  In the `SAM-Tutorial` directory, run the following command. 

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

   Because the stack name is still `my-date-time-app`, CloudFormation recognizes that this is a stack update. To view your updated stack, return the CloudFormation console, and from the navigation pane, choose **Stacks**.

**(Optional) to view traffic during a deployment (CodeDeploy console)**

1. Open the CodeDeploy console at [https://console.aws.amazon.com/codedeploy/](https://console.aws.amazon.com/codedeploy/).

1.  In the navigation pane, expand **Applications**, and then choose your **my-date-time-app-ServerlessDeploymentApplication** application. 

1.  In **Deployment groups**, choose your application's deployment group. Its status should be **In progress**. 

1.  In **Deployment group history**, choose the deployment that is in progress. 

   The **Traffic shifting** progress bar and the percentages in the **Original** and **Replacement** boxes on this page display its progress.   
![\[The traffic shifting progress section of the CodeDeploy console.\]](http://docs.aws.amazon.com/codedeploy/latest/userguide/images/lambda-tutorial-codedeploy-console-20-percent-deployed.png)

**(Optional) to view traffic during a deployment (Lambda console)**

1. Open the AWS Lambda console at [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/).

1.  From the navigation pane, choose your `my-date-time-app-myDateTimeFunction` function. In the console, its name contains an identifier, so it looks like `my-date-time-app-myDateTimeFunction-123456ABCDEF`. 

1.  Choose **Aliases**, and then choose **live**. 

The weights next to your original function version (version 1) and your updated function version (version 2) show how much traffic is served to each version at the time this AWS Lambda console page was loaded. The page does not update the weights over time. If you refresh the page once a minute, the weight for version 1 decreases by 10 percent and the weight for version 2 increases by 10 percent until the weight for version 2 is 100. 

![\[The aliases section of the CodeDeploy console.\]](http://docs.aws.amazon.com/codedeploy/latest/userguide/images/lambda-tutorial-lambda-console-20-percent-deployed.png)


# Step 4: View your deployment results
<a name="tutorial-lambda-sam-deploy-view-results"></a>

In this step, you view the results of your deployment. If your deployment succeeds, you can confirm that your updated Lambda function receives production traffic. If your deployment fails, you can use CloudWatch Logs to view the output of the validation tests in the Lambda function that run during your deployment's lifecycle hoooks. 

**Topics**
+ [Test your deployed function](#tutorial-lambda-sam-deploy-test-deployed-function)
+ [View hook events in CloudWatch Logs](#tutorial-lambda-view-hook-events)

## Test your deployed function
<a name="tutorial-lambda-sam-deploy-test-deployed-function"></a>

 The **sam deploy** command updates the `my-date-time-app-myDateTimeFunction` Lambda function. The function version is updated to 2 and added to the `live` alias. 

**To see the update in the Lambda console**

1. Open the AWS Lambda console at [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/).

1.  From the navigation pane, choose the `my-date-time-app-myDateTimeFunction` function. In the console, its name contains an identifier, so it looks like `my-date-time-app-myDateTimeFunction-123456ABCDEF`. 

1.  Choose **Qualifiers**, and then choose **Aliases**. After the deployment is complete (approximately 10 minutes), for the `live` alias, you should see **Version: 2**.  
![\[The aliases section of the CodeDeploy console.\]](http://docs.aws.amazon.com/codedeploy/latest/userguide/images/lambda-tutorial-function-version.png)

1.  In **Function code**, view the source code for your function. Your changes should appear. 

1.  (Optional) You can use the test instructions in [Step 2: Update the Lambda function](tutorial-lambda-sam-update-function.md) to test your updated function. Create a new test event with the following payload, and then confirm the result contains the current hour, minute, and second. 

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

    To use the AWS CLI to test your updated function, run the following command, and then open `out.txt` to confirm the result contains the current hour, minute, and second. 

   ```
   aws lambda invoke --function your-function-arn --payload "{\"option\": \"time\"}" out.txt 
   ```
**Note**  
 If you use the AWS CLI to test your function before the deployment is complete, you might receive unexpected results. This is because CodeDeploy incrementally shifts 10 percent of traffic to the updated version every minute. During the deployment, some traffic still points to the original version, so `aws lambda invoke` might use the original version. After 10 minutes, the deployment is complete and all traffic points to the new version of the function. 

## View hook events in CloudWatch Logs
<a name="tutorial-lambda-view-hook-events"></a>

 During the `BeforeAllowTraffic` hook, CodeDeploy executes your `CodeDeployHook_beforeAllowTraffic` Lambda function. During the `AfterAllowTraffic` hook, CodeDeploy executes your `CodeDeployHook_afterAllowTraffic` Lambda function. Each function runs a validation test that invokes the updated version of your function using the new `time` parameter. If the update of your Lambda function is successful, the `time` option does not cause an error and validation is successful. If the function was not updated, the unrecognized parameter causes an error and validation fails. These validation tests are for demonstration purposes only. You write your own tests to validate your deployment. You can use the CloudWatch Logs console to view your validation tests. 

**To view your CodeDeploy hook events**

1. Open the CloudWatch console at [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).

1.  From the navigation pane, choose **Logs**. 

1.  From the list of log groups, choose **/aws/lambda/CodeDeployHook\$1beforeAllowTraffic** or **/aws/lambda/CodeDeployHook\$1afterAllowTraffic**. 

1.  Choose the log stream. You should see only one. 

1.  Expand the events to see their details.   
![\[The log stream of a CodeDeployHook log group.\]](http://docs.aws.amazon.com/codedeploy/latest/userguide/images/lambda-tutorial-cloudwatch.png)

# Step 5: Clean up
<a name="tutorial-lambda-clean-up"></a>

To avoid further charges for resources you used during this tutorial, delete the resources created by your AWS SAM template and the CloudWatch logs created by your Lambda validation functions.

**To delete your CloudFormation stack**

1. Sign in to the AWS Management Console and open the CloudFormation console at [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/).

1. In the **Stacks** column, choose your `my-date-time-app` stack, and then choose **Delete**.

1. When prompted, choose **Delete stack**. The Lambda functions, CodeDeploy application and deployment group, and IAM roles created by AWS SAM are deleted.

**To delete your logs in CloudWatch Logs**

1. Open the CloudWatch console at [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).

1.  From the navigation pane, choose **Logs**. 

1.  From the list of log groups, choose the button next to **/aws/lambda/CodeDeployHook\$1beforeAllowTraffic**. 

1.  From **Actions**, choose **Delete log group**, and then choose **Yes, Delete**. 

1.  From the list of log groups, choose the button next to **/aws/lambda/CodeDeployHook\$1afterAllowTraffic**. 

1.  From **Actions**, choose **Delete log group**, and then choose **Yes, Delete**. 