Serverless

Table of Contents

Overview

npm install -g serverless

You can use Serverless CLI with serverless or sls command.

Subcommands:

config ........................ Configure Serverless
config credentials ............ Configures a new provider profile for the Serverless Framework
create ........................ Create new Serverless service
deploy ........................ Deploy a Serverless service
deploy function ............... Deploy a single function from the service
deploy list ................... List deployed version of your Serverless Service
deploy list functions ......... List all the deployed functions and their versions
info .......................... Display information about the service
install ....................... Install a Serverless service from GitHub or a plugin from the Serverless registry
invoke ........................ Invoke a deployed function
invoke local .................. Invoke function locally
logs .......................... Output the logs of a deployed function
metrics ....................... Show metrics for a specific function
package ....................... Packages a Serverless service

Reference

serverless.yml

serverless-domain-manager

serverless-dynamodb-local

sls dynamodb install
sls dynamodb start
sls dynamodb remove
dynamodb:
  start:
    seed: true

  seed:
    <category>:
      sources:
        - table: domain-widgets
          sources: [./data.json]
[
  {
    "id": "John",
    "name": "Doe",
  }
]

serverless-python-requirements

serverless-wsgi

service: example

provider:
  name: aws
  runtime: python2.7

plugins:
  - serverless-wsgi

functions:
  api:
    handler: wsgi.handler
    events:
      - http: ANY /
      - http: ANY {proxy+}

custom:
  wsgi:
    app: api.app
# For development
sls wsgi serve
* Running on http://localhost:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 109-942-480

Topics

Services

users/
  serverless.yml # Contains 4 functions that do Users CRUD operations and the Users database
posts/
  serverless.yml # Contains 4 functions that do Posts CRUD operations and the Posts database
comments/
  serverless.yml # Contains 4 functions that do Comments CRUD operations and the Comments database
serverless create --template aws-nodejs --path myService

serverless.yml

Functions

functions:
  functionOne:
    handler: handler.functionOne
    description: optional description for your Lambda
  functionTwo:
    handler: handler.functionTwo
  functionThree:
    handler: handler.functionThree
provider:
  name: aws
  environment:
    SYSTEM_NAME: mySystem
    TABLE_NAME: tableName1

functions:
  hello:
    handler: handler.users
    environment:
      TABLE_NAME: tableName2 # overrides

Events

Resources

Resource:
        "Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table..."
provider:
  name: aws
  runtime: nodejs6.10
  # Allow for cf "AWS::" variables, see https://serverless.com/framework/docs/providers/aws/guide/variables#using-custom-variable-syntax
  variableSyntax: "\\${(?!AWS::)([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}"

Deploying

serverless deploy --verbose                      # uses AWS CloudFormation Stack Update
serverless deploy function --function myFunction # updates AWS Lambda only
serverless deploy --stage production --region eu-central-1

Variables

x: ${env:NAME}                 # Environment Variables
x: ${env:NAME, 'temp'}         # default
x: ${opt:stage}                # CLI Options
x: ${cf:service.name}          # CloudFormation
x: ${self:custom.stage}        # self reference
x: ${s3:bucket/key}            # value(content) of the s3 object
x: ${file(../config.yml):name} # js, json or yaml, can be json object or equivalents

Packaging

serverless package
serverless package --package my-artifacts

Serverless will run the glob patterns in order. At first it will apply the globs defined in exclude. After that it'll add all the globs from include.

package:
  exclude:
    - src/**
  include:
    - src/function/handler.js
module.exports = {
  defaultExcludes: [
    '.git/**',
    '.gitignore',
    '.DS_Store',
    'npm-debug.log',
    'serverless.yml',
    'serverless.yaml',
    'serverless.json',
    'serverless.js',
    '.serverless/**',
    '.serverless_plugins/**',
  ],

IAM

As those statements will be merged into the CloudFormation template, you can use Join, Ref or any other CloudFormation method or feature.

Additional Policies on the generated policies

provider.iamRoleStatements
Define additional policies in the CloudFormation format
provider.iamManagedPolicies
Additional policies managed outside of serverless
service: new-service

provider:
  name: aws
  iamRoleStatements:
    -  Effect: "Allow"
       Action:
         - "s3:ListBucket"
       Resource:
         Fn::Join:
           - ""
           - - "arn:aws:s3:::"
             - Ref: ServerlessDeploymentBucket
    -  Effect: "Allow"
       Action:
         - "s3:PutObject"
       Resource:
         Fn::Join:
           - ""
           - - "arn:aws:s3:::"
             - Ref: ServerlessDeploymentBucket
             - "/*"
  iamManagedPolicies:
      - 'some:aws:arn:xxx:*:*'
      - 'someOther:aws:arn:xxx:*:*'
      - { 'Fn::Join': [':', ['arn:aws:iam:', { Ref: 'AWSAccountId' }, 'some/path']] }

Completely custom roles

Using this way means that iamRoleStatements you've defined on the provider level won't be applied anymore. Furthermore, you need to provide the corresponding permissions for your Lambdas logs and stream events.

provider:
  name: aws
  # declare one of the following...
  role: myDefaultRole                                                  # must validly reference a role defined in the service
  role: arn:aws:iam::0123456789:role//my/default/path/roleInMyAccount  # must validly reference a role defined in your account
  role:                                                                # must validly resolve to the ARN of a role you have the rights to use
    Fn::GetAtt:
      - myRole
      - Arn

Plugins

How-to

Deploy Flask App

npm init -f
npm install --save-dev serverless-wsgi serverless-python-requirements

Set Custom Domains

$ npm install serverless-domain-manager --save-dev
plugins:
  - serverless-domain-manager

custom:
  customDomain:
    domainName: <registered_domain_name>
    basePath: ''
    stage: ${self:provider.stage}
    createRoute53Record: true

If you're using a certificate that doesn't exactly match your domain name, such as a wildcard certificate, you'll need to specify the certificate name with a certificateName property under customDomain.

$ sls create_domain --stage <stage>
custom:
  domain:
    dev: MY_DEV_DOMAIN
    prod: MY_PROD_DOMAIN
  customDomain:
    basePath: ''
    domainName: ${self:custom.domain.${opt:stage}}
    stage: ${opt:stage}
    createRoute53Record: true

Enable CORS

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: hello
          method: get
          cors:
            origin: '*'
            headers:
              - Content-Type
              - X-Amz-Date
              - Authorization
              - X-Api-Key
              - X-Amz-Security-Token
              - X-Amz-User-Agent
            allowCredentials: false

If you want to use CORS with the lambda-proxy integration, You should handle CORS within your application.

API Gateway says:

For Lambda or HTTP proxy integrations, you can still set up the required OPTIONS response headers in API Gateway. However, you must rely on the back end to return the Access-Control-Allow-Origin headers because the integration response is disabled for the proxy integration.