--- categories: - DevOps - Backend tags: [AWS] --- # AWS SAM SAM stands for **serverless application model**. It is a framework developed by AWS to simplify the process of building, deploying and managing serverless applications. It provides a concise syntax for defining the components of a serverless application, such as [Lambda functions](/DevOps/AWS/AWS_Lambda/Lambda_programming_model.md), [API gateway](/DevOps/AWS/AWS_API_Gateway.md) and database tables. The SAM infrastructure is defined in a YAML file which is then deployed to AWS. SAM syntax gets transformed into CloudFormation during the deployment process. (CloudFormation is a broader and more robust AWS tool for large, highly scaleable infrastructures). ## Key features of SAM - Single deployment configuration - Integration with development tools - Local testing and debugging - Built on AWS CloudFormation ## Main technologies required ### Docker Whilst SAM can be used to create a deployable file for AWS it can also be run as a container for local development with Docker. ### AWS CLI This is installed using Python and allows you to interact directly with AWS via the command-line. ### AWS SAM CLI See [https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html) ## Setting up credentials for the AWS CLI ``` aws configure AWS Access Key ID [None]: AK******* AWS Secret Access Key [None]: ukp****** Default region name [None]: Default output format [None]: ``` This information can be found in the Security Credentials section of the given [IAM](/DevOps/AWS/AWS_User_management_and_roles.md#iam) user: ![](/_img/access-key-aws.png) ## Starting a SAM project First create a directory for your project which will serve as the repository: ```sh mkdir aws-sam-learning cd aws-sam-learning ``` Then we can use the `sam` cli to bootstrap the project: ```sh sam init --runtime nodejs16.x ``` We can just click through and accept the basic HelloWorld Lambda. This will create the Lambda as well as an API Gateway trigger URL. ### `template.yaml` This is autogenerated and details the main constituents of the project. There are lots of fields but the most important are the following: ```yaml HelloWorldFunction: Type: AWS::Serverless::Function Properties: CodeUri: hello-world/ Handler: app.lambdaHandler Runtime: nodejs16.x Architectures: - x86_64 Events: HelloWorld: Type: Api Properties: Path: /hello Method: get ``` This details the location of the [handler function](/DevOps/AWS/AWS_Lambda/Lambda_handler_function.md) which is contained at the path `hello-world/app.js`: ```js exports.lambdaHandler = async (event, context) => { try { // const ret = await axios(url); response = { statusCode: 200, body: JSON.stringify({ message: "hello world", // location: ret.data.trim() }), }; } catch (err) { console.log(err); return err; } return response; }; ``` It also lists the `get` event that we can use to call API Gateway and trigger the Lambda. The full template is below: ![](/_img/sam-template-yaml.png) ## Adding our own code We will create our own function and API Gateway trigger. We will place our function after the existing `HelloWorldFunction` ```yaml ClockFunction: Type: AWS::Serverless::Function Properties: CodeUri: clock/ Handler: handler.clock Runtime: nodejs16.x Events: ClockApi: Type: Api Properties: Path: /clock Method: get ``` Just like with `HelloWorld`, we will create a directory for this function: `clock` and we will initialise it as an `npm` project. ```sh mkdir clock cd clock npm init ``` We will use `handler.js` as our root, handler function. We have said in the template file that our `Handler: handler.clock`, therefore the main function in the `handler` module should be `clock`: ```js const moment = require("moment"); exports.clock = async (event) => { console.log("Clock function run"); const message = moment().format(); const response = { statusCode: 200, body: JSON.stringify(message), }; return response; }; ```