The AWS Serverless Application Model, SAM for short, is AWS’ powerful framework for designing and building serverless applications. The SAM CLI library makes the process of working with AWS cloudformation templates and projects extremely easy.
Once setup, it is trivial to extend the configuration to deploy a cloudformation template to any AW region or account. This could be the case when replicating a cloudformation stack from a development account/region to production, or for simply scaling your application to other regions among other reasons.
This guide will walkthrough the process of getting a local environment configured to be able to deploy a simple sample cloudformation template to an AWS account and demonstrate how to extend the SAM config file to replicate the stack.
Note: This guide assumes the following:
- You have access to an AWS account.
- You have an IAM user that has sufficient permissions to create resources in that AWS account.
Installing AWS SAM CLI and creating a AWS Access Key for remote access
If you don’t have AWS SAM CLI installed, that would be the first step. It is a good idea to also have the parent AWS library AWS CLI also installed.
Note: I am using windows and there are installers available, but personally I prefer working with pip and the command line. This guide will be using the command line when using the sam cli as well though there are very good plugins with editors like PyCharm.
pip install awscli
pip install aws-sam-cli
sam -h
Usage: sam [OPTIONS] COMMAND [ARGS]...
AWS Serverless Application Model (SAM) CLI
The AWS Serverless Application Model extends AWS CloudFormation to provide
a simplified way of defining the Amazon API Gateway APIs, AWS Lambda
functions, and Amazon DynamoDB tables needed by your serverless
application. You can find more in-depth guide about the SAM specification
here: https://github.com/awslabs/serverless-application-model.
Options:
--debug Turn on debug logging to print debug message generated by SAM
CLI and display timestamps.
--version Show the version and exit.
--info
-h, --help Show this message and exit.
Commands:
init Init an AWS SAM application.
validate Validate an AWS SAM template.
build Build your Lambda function code
local Run your Serverless application locally for quick development &...
package Package an AWS SAM application.
deploy Deploy an AWS SAM application.
delete Delete an AWS SAM application and the artifacts created by sam
deploy.
logs Fetch logs for a function
publish Publish a packaged AWS SAM template to the AWS Serverless
Application Repository.
traces [Beta Feature] Fetch AWS X-Ray traces
sync [Beta Feature] Sync a project to AWS
pipeline Manage the continuous delivery of the application
If all is well, you should see the options above. Next up, we will need to grab an AWS access key for an IAM user with sufficient permissions to the account. Read only is not going to cut it. If you do not have an access key, follow the steps below to create one:
- Login to the AWS console and navigate to IAM > Users > (your IAM user)
- Select the security credentials tab in the summary screen
- Hit the create access key button
- Save the id and secret in a secure location as AWS will not show this to you again, however you can create another one if you forgot to.
Creating the .aws credentials file
Now that we have the access key, we need to set up an aws profile – which is essentially a pointer for AWS SAM to use the access key in order to do cool stuff like creating your serverless cloudformation template in your AWS account.
We are going to create the file in one of these locations depending on your OS. As mentioned earlier, I am using Windows
C:\Users\<your_username>\.aws\credentials
on Windows- ~/.aws/credentials on Linux or Mac
Create the .aws folder, and the file named “credentials” and add the following entries inside it as below – but remember to replace values between <> tags with your own values…and remove the <,> tags as well.
[<ACCOUNT_PROFILE_NAME>]
aws_access_key_id = <ACCESS_KEY_ID>
aws_secret_access_key = <SECRET_KEY>
region=<us-east-1>
Note: Many guides including the AWS docs will usually have you enter the default entry “[default]” where I have <ACCOUNT_PROFILE_NAME>. I dislike having a default entry to reduce the chances of deploying to the default account/region accidentally.
Testing Access and Creating an S3 Bucket for SAM to use
We haven’t got to it yet, but in order to deploy our serverless application using SAM, we will need to provide SAM with an S3 Bucket. Every time SAM deploys a cloudformation “changeset”, it will upload the build with your cloudformation template specifications to the S3 Bucket before invoking Cloudformation to create your stack from there.
Since we want to validate our credentials setup, we can kill the two birds by creating the S3 bucket using the AWS CLI. If the access key works for AWS CLI, AWS SAM CLI should be good.
First export/set your AWS_PROFILE variable to what you set for <ACCOUNT_PROFILE_NAME> depending on your os command line tool. If like me you are using Git Bash on Windows, you can use export instead of set.
export AWS_PROFILE=<ACCOUNT_PROFILE_NAME> //Bash
set AWS_PROFILE=<ACCOUNT_PROFILE_NAME> //Cmd
Next, confirm access simply by listing your s3 buckets
aws s3 ls
If all was well, we are now ready to create an s3 bucket. Can be any name, but it is recommended to pick a name with a pattern that will meaningfully identify that this is the bucket AWS SAM will use in the region.
aws s3api create-bucket --bucket <myaccount-awsregion-sam-bucket> --object-ownership BucketOwnerEnforced --region <awsregion>
aws s3api put-public-access-block --bucket <myaccount-awsregion-sam-bucket> --public-access-block-configuration "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
Now we are ready to create a sample cloudformation project.
Creating a sample SAM Cloudformation Template
Lets create a simple template that is going to create a Dynamodb Table in the account it is deployed to.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: SAM Deploy How To
Resources:
DynamoDB:
Type: AWS::DynamoDB::Table
Properties:
TableName: aws-sam-table
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: primary_key
AttributeType: S
KeySchema:
- AttributeName: primary_key
KeyType: HASH
The above template specifies a single “aws-sam-table” with a “primary_key” and should be named template.yaml. You can specify any name and sometimes I do create yaml files with descriptive names, but lets stick with the default for now which is the name SAM will look for if you don’t pass in the name to it.
Creating the SAM Config TOML file
This step is the key to making any cloudformation stack configurable to be deployed to any account or region. The TOML file specifies all the information AWS SAM needs to create a stack in a region.
Again lets stick to the default name – samconfig.toml and save it in the same location as the yaml file from the previous step.
version = 0.1
[<DEPLOY_PROFILE_NAME>]
[<DEPLOY_PROFILE_NAME>.deploy]
[<DEPLOY_PROFILE_NAME>.deploy.parameters]
stack_name = "sam-deploy-how-to"
region = "<awsregion>"
s3_bucket="<myaccount-awsregion-sam-bucket>"
s3_prefix="sam_deploy"
confirm_changeset = true
capabilities = "CAPABILITY_IAM CAPABILITY_NAMED_IAM"
Make sure you are using all the names you used when following this guide in your own toml file. The stack name is what you want to call your Cloudformation stack.
Confirm changeset is recommended to prevent an accidental deployment.
Capabilities – to let Cloudformation use IAM credentials to do its magic…honestly this should be a redundant config setting but it is needed.
Now lets deploy the stack.
Deploying the Cloudformation Template with AWS SAM
First, navigate to the location where you have defined the yaml and toml files and run sam build.
sam build
Build Succeeded
Built Artifacts : .aws-sam\build
Built Template : .aws-sam\build\template.yaml
Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch
[*] Deploy: sam deploy --guided
Assuming there were no errors in your yaml, you should see the above output.
We are going to do sam deploy next but not with the –guided option – this will help you create the toml file which we already did. Honestly, its much faster to create the toml file directly than using –guided.
Run the command below, –config-env has to be what you set in line 2 of the toml file above “[<DEPLOY_PROFILE_NAME>]”
sam deploy --config-env <DEPLOY_PROFILE_NAME>
//You should see something like the snippets below
Waiting for changeset to be created..
CloudFormation stack changeset
-------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType Replacement
-------------------------------------------------------------------------------------------------
+ Add DynamoDB AWS::DynamoDB::Table N/A
-------------------------------------------------------------------------------------------------
//When prompted, accept
Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y
If all went well with the deployment, you should see this below in the shell.
CloudFormation events from stack operations
-------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
-------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS AWS::DynamoDB::Table DynamoDB -
CREATE_IN_PROGRESS AWS::DynamoDB::Table DynamoDB Resource creation
Initiated
CREATE_COMPLETE AWS::DynamoDB::Table DynamoDB -
CREATE_COMPLETE AWS::CloudFormation::S sam-deploy-how-to -
tack
-------------------------------------------------------------------------------------------------
Successfully created/updated stack
And that’s that for the deployment!
Extending the samconfig.toml file
You probable figured it out yourself – but for the sake of completeness, to extend the samconfig.toml to deploy to a different region or account, simply add a brand new entry specifying the appropriate values – especially the region and bucket names.
The account is sort of tied to the bucket – but you will need to change your AWS_PROFILE environment variable to the correct account profile as we di earlier in this guide.
[<NEW_DEPLOYMENT_PROFILE>]
[<NEW_DEPLOYMENT_PROFILE>.deploy]
[<NEW_DEPLOYMENT_PROFILE>.deploy.parameters]
stack_name = "sam-deploy-how-to"
region = "<NEWawsregion>"
s3_bucket="<myNEWaccount-awsregion-sam-bucket>"
s3_prefix="sam_deploy"
confirm_changeset = true
capabilities = "CAPABILITY_IAM CAPABILITY_NAMED_IAM"
And now it’s a wrap.
In a future guide I will cover setting up an AWS Code Pipeline to do the deployment for you. But for quick testing and developing needs, it is much faster to quickly use AWS SAM to deploy your stack.