In this module you'll use the Serverless Application Model (SAM) to define a serverless RESTful API that has functionality to list, create, view, update, and delete the unicorns in the Wild Rydes stable.
The architecture for the Unicorn API uses API Gateway to define an HTTP interface that trigger Lambda functions to read and write data to the DynamoDB database.
AWS SAM is a model used to define serverless applications on AWS.
AWS SAM is based on AWS CloudFormation. A serverless application is defined in a CloudFormation template and deployed as a CloudFormation stack. An AWS SAM template is a CloudFormation template.
AWS SAM defines a set of objects which can be included in a CloudFormation template to describe common components of serverless applications easily. In order to include objects defined by AWS SAM within a CloudFormation template, the template must include a Transform
section in the document root with a value of AWS::Serverless-2016-10-31
.
The Unicorn API includes Amazon API Gateway HTTP endpoints that trigger AWS Lambda functions that read and write data to a Amazon DynamoDB database. The SAM template for the Unicorn API describes a DynamoDB table with a hash key and Lambda functions to list, view and update Unicorns in the Wild Rydes stable.
The Unicorn API components are defined in the app-sam.yaml CloudFormation template. Next we'll review the Unicorn API components in more detail.
Below is the code snippet from the SAM template that describes the DynamoDB table resource.
Table:
Type: 'AWS::Serverless::SimpleTable'
Properties:
PrimaryKey:
Name: name
Type: String
Unicorns are uniquely identified in the Wild Rydes stable by name, a single String attribute that is used as the primary key in the DynamoDB table. The AWS::Serverless::SimpleTable resource meets this requirement and is used to define the DynamoDB table used by the API. If a more complex configuration is required, you can substitute the SimpleTable with a AWS::DynamoDB::Table resource definition.
Below is the code snippet from the SAM template that describes the Lambda function that handles requests to view Unicorn data by Unicorn name.
ReadFunction:
Type: 'AWS::Serverless::Function'
Properties:
FunctionName: 'uni-api-read'
Runtime: nodejs6.10
CodeUri: app
Handler: read.lambda_handler
Description: View Unicorn by name
Timeout: 10
Events:
GET:
Type: Api
Properties:
Path: /unicorns/{name}
Method: get
Environment:
Variables:
TABLE_NAME: !Ref Table
Role:
Fn::ImportValue:
!Join ['-', [!Ref 'ProjectId', !Ref 'AWS::Region', 'LambdaTrustRole']]
There are several properties defined for the AWS::Serverless::Function resource, which we'll review in turn.
The FunctionName property defines a custom name for the Lambda function. If not specified, CloudFormation will generate a name using the CloudFormation Stack name, CloudFormation Resource name, and random ID.
The Unicorn API is implemented in Node.js 6.10. Additional runtimes are available for AWS Lambda. Please refer to the Lambda Execution Environment and Available Libraries for the complete list.
The CodeUri property defines the location to the function code on your workstation relative to the SAM template. In this example, "app" is used for the property value because the function code is in the app
directory relative to the SAM template.
The Handler property defines the entry point for the Lambda function. For Javascript, This is formatted as "file.function", where file is the Javascript filename without the ".js" extension relative to the CodeUri path defined above and function is the name of the function in the file that will be executed with the Lambda function is invoked.
The Events property defines the sources that trigger the Lambda function invocation. An Api event source is defined to integrate the Lambda function with an API Gateway endpoint, however SAM supports Lamdba function triggers from a variety of sources.
The Api event source to view details of a Unicorn is defined at the RESTful resource /unicorns/{name}
accessed using the HTTP GET method. SAM will transform the Api event to an API Gateway resource and map the name value in the URL to a pathParameter in the event used to invoke the Lambda function.
The Environment property defines a list of variables and values that will be accessible in the Lambda function, according to the access method defined by the Runtime.
The Lambda functions communicate with DynamoDB to read and write data. The DynamoDB table created by the CloudFormation Stack is referenced as the value for the TABLE_NAME
environment variable, which can be referenced within the Lambda function.
The Role property defines the IAM Role that specifies the access permissions to AWS resources in the Lambda execution policy. For each project, CodeStar generates a Lambda execution role that has access to a default set of AWS resources. This role can be modified with additional policies, as you will see in a later module.
Next, we'll look at how CloudFormation is used to deploy the SAM Unicorn API.
Each of the following sections provide an implementation overview and detailed, step-by-step instructions. The overview should provide enough context for you to complete the implementation if you're already familiar with the AWS Management Console or you want to explore the services yourself without following a walkthrough.
If you're using the latest version of the Chrome, Firefox, or Safari web browsers the step-by-step instructions won't be visible until you expand the section.
This workshop can be deployed in any AWS region that supports the following services:
- Amazon API Gateway
- Amazon S3
- Amazon DynamoDB
- AWS CodeBuild
- AWS CodePipeline
- AWS Lambda
- AWS X-Ray
You can refer to the region table in the AWS documentation to see which regions have the supported services. Among the supported regions you can choose are N. Virginia, Ohio, N. California, Oregon, Ireland, Frankfurt, and Sydney.
Once you've chosen a region, you should deploy all of the resources for this workshop there. Make sure you select your region from the dropdown in the upper right corner of the AWS Console before getting started.
CodeStar generates IAM Roles and Policies that control access to AWS resources. In this module, we will add permissions to Roles using IAM Managed Policies to support the customizations we will make to the Lambda function names.
-
In the AWS Management Console choose Services then select IAM under Security, Identity & Compliance.
-
Select Role in the left navigation, type
CodeStarWorker-uni-api-CloudFormation
in the filter text box, and click the Role name link in the Role table. -
On the Role Summary page, click the Attach Policy button in the Managed Policies section of the Permissions tab.
-
Type
AWSLambdaReadOnlyAccess
in the filter text box, select the checkbox next to the AWSLambdaReadOnlyAccess Managed Policy, and click the Attach Policy button. -
The Role Summary will now include the AWSLambdaReadOnlyAccess policy in the list of Managed Policies.
-
Each module has corresponding source code used to seed the CodeCommit Git repository for the CodeStart project. To seed the CodeCommit Git repository, click on the Launch Stack button for your region below:
Region Launch US East (N. Virginia) US West (N. California) US West (Oregon) EU (Ireland) EU (Frankfurt) Asia Pacific (Sydney) -
The CloudFormation template has been prepopulated with the necessary fields for this module. No changes are necessary
-
Select the I acknowledge that AWS CloudFormation might create IAM resources. checkbox to grant CloudFormation permission to create IAM resources on your behalf
-
Click the Create button in the lower right corner of the browser window to create the CloudFormation stack and seed the CodeCommit repository.
-
There will be a short delay as the Git repository seeded with the new source code. Upon successful completion, the CloudFormation will show Status
CREATE_COMPLETE
.
Now that the CodeCommit Git repository has been seeded with new source code, you will need to fetch the changes locally so that you may modify the code. Typically, this is accomplished using the git pull
command, however for the workshop we have replaced the repository with a new history and different Git commands will be used.
Using your preferred Git client, run the commands on your local uni-api Git repository:
git fetch --all
git reset --hard origin/master
CodeStar creates an S3 bucket to store the artifacts created by packaging SAM-based projects. The S3 bucket has the format, where {AWS::Region}
and {AWS::AccountId}
are populated with your details.
aws-codestar-{AWS::Region}-{AWS::AccountId}-uni-api-pipe
On your workstation:
-
Change directory to your local uni-api Git repository directory.
-
Use the AWS CLI to execute the CloudFormation package command to upload the local code from the
uni-api
directory to S3. Use the following command to do so. Make sure you replaceYOUR_BUCKET_NAME
with the name you identified in the previous step (i.e.aws-codestar-{AWS::Region}-{AWS::AccountId}-uni-api-pipe
)
aws cloudformation package --template-file app-sam.yaml --s3-bucket YOUR_BUCKET_NAME --output-template-file app-sam-output.yaml
The CloudFormation package command archives the local source code, uploads it to the S3 location specified, and returns an new CloudFormation template to the app-sam-output.yaml
file with the local CodeUri reference substituted with the location to the S3 object. For example:
Before:
ReadFunction:
Type: 'AWS::Serverless::Function'
Properties:
FunctionName: 'uni-api-read'
Handler: read.lambda_handler
Runtime: nodejs6.10
CodeUri: app
After:
ReadFunction:
Type: 'AWS::Serverless::Function'
Properties:
FunctionName: 'uni-api-read'
Handler: read.lambda_handler
Runtime: nodejs6.10
CodeUri: s3://YOUR_BUCKET_NAME/540839c2fc11f0214f88f6c5dfacd389
-
Change directory to your local uni-api Git repository, if necessary.
-
Use the AWS CLI to execute the CloudFormation deploy command to deploy the
app-sam-output.yaml
CloudFormation template returned by the package command, specifying the CloudFormation stack nameawscodestar-uni-api-lambda
and theCAPABILITY_IAM
CloudFormation capability as the stack will be creating IAM trust and execution policies for the Lambda functions. You can use the following command to do so.
aws cloudformation deploy --stack-name awscodestar-uni-api-lambda --template-file app-sam-output.yaml --capabilities CAPABILITY_IAM --parameter-overrides ProjectId=uni-api
After the CloudFormation deploy command completes, you will use the browser to test your API.
-
In the AWS Management Console choose Services then select CodeStar under Developer Tools.
-
Select the
uni-api
project -
Copy the URL from the Application endpoints tile on the right side of the dashboard.
-
Paste the URL in a browser window and append
/unicorns
to the path and hit enter. For example:https://xxxxxxxxxx.execute-api.us-west-1.amazonaws.com/Prod/unicorns/
-
Confirm that the browser shows a JSON result with an empty list:
[]
Now that you've reviewed and deployed the Unicorn API, let's enhance the API with the ability to create or update a Unicorn in the Wild Rydes stables. The code to do so is already present in the project, so you need to add an AWS::Serverless::Function resource in the SAM app-sam.yaml
template.
Using a text editor, open the app-sam.yaml
file and append a new AWS::Serverless::Function Resource labeled UpdateFunction
that has the following definition.
Note: whitespace is important in YAML files. Please verify that the configuration below is added with the same space indentation as the CloudFormation Resources in the app-sam.yaml file.
-
FunctionName is
uni-api-update
-
Runtime is
nodejs6.10
-
CodeUri is
app
-
Handler is
update.lambda_handler
-
Description is
Create or Update Unicorn
-
Timeout is
10
-
Event type is
Api
associated to the/unicorns/{name}
Path andput
Method -
Environment variable named
TABLE_NAME
that references theTable
Resource for its value. -
Role is duplicated from another function.
If you are unsure of the syntax to add to app-sam.yaml
please refer to the code snippet below.
app-sam.yaml additions to support Update function (expand for details)
UpdateFunction:
Type: 'AWS::Serverless::Function'
Properties:
FunctionName: 'uni-api-update'
Runtime: nodejs6.10
CodeUri: app
Handler: update.lambda_handler
Description: Create or Update Unicorn
Timeout: 10
Events:
PUT:
Type: Api
Properties:
Path: /unicorns/{name}
Method: put
Environment:
Variables:
TABLE_NAME: !Ref Table
Role:
Fn::ImportValue:
!Join ['-', [!Ref 'ProjectId', !Ref 'AWS::Region', 'LambdaTrustRole']]
Use the AWS CLI to execute the CloudFormation package command to upload the local code from the uni-api
directory to S3. You can use the following command to do so. Make sure you replace YOUR_BUCKET_NAME
with the name you used for the previous package command.
aws cloudformation package --template-file app-sam.yaml --s3-bucket YOUR_BUCKET_NAME --output-template-file app-sam-output.yaml
Use the AWS CLI to execute the CloudFormation deploy command to deploy the app-sam-output.yaml
CloudFormation template returned by the package command, specifying the CloudFormation stack name awscodestar-uni-api-lambda
and the CAPABILITY_IAM
CloudFormation capability as the stack will be creating IAM trust and execution policies for the Lambda functions. You can use the following command to do so.
aws cloudformation deploy --stack-name awscodestar-uni-api-lambda --template-file app-sam-output.yaml --capabilities CAPABILITY_IAM --parameter-overrides ProjectId=uni-api
CloudFormation will generate a ChangeSet for the awscodestar-uni-api-lambda
CloudFormation Stack and only update the resources that have changed since the previous deployment. In this case, awscodestar-uni-api-lambda
was the CloudFormation stack created by CodeStar for the Lambda functions and API Gateway specification, which you will be updating.
After the CloudFormation deploy command completes, you will use the AWS API Gateway to test your API.
-
In the AWS Management Console, click Services then select API Gateway under Application Services.
-
In the left nav, click on
awscodestar-uni-api-lambda
. -
From the list of API resources, click on the
PUT
link under the/{name}
resource. -
On the resource details panel, click the
TEST
link in the client box on the left side of the panel. -
On the test page, enter
Shadowfox
in the Path field. -
Scroll down the test page and enter the following as the Request Body:
{ "breed": "Brown Jersey", "description": "Shadowfox joined Wild Rydes after completing a distinguished career in the military, where he toured the world in many critical missions. Shadowfox enjoys impressing his ryders with magic tricks that he learned from his previous owner." }
-
Scroll down and click the Test button.
-
Scroll to the top of the test page, and verify that on the right side of the panel that the Status code of the HTTP response is 200.
-
In the AWS Management Console choose Services then select CodeStar under Developer Tools.
-
Select the
uni-api
project -
Copy the URL from the Application endpoints tile on the right side of the dashboard.
-
Paste the URL in a browser window and append
/unicorns
to the path and hit enter. For example:https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/Prod/unicorns/
-
Confirm that the browser shows a JSON result that includes
Shadowfox
, with the breed and description entered above.
Note: You may notice that your CodeStar project shows the Build stage has failed in the project pipeline. That's to be expected, and will be corrected in the next module.
Congratulations! You have successfully deployed a RESTful serverless API using the Serverless Application Model, and demonstrated that the same tools can be used to make modifications to the API. In the next Continuous Delivery Pipeline Module, you will learn how to automate this deployment process using AWS CodePipeline and AWS CodeBuild.