Serverless framework - Getting Started with Python

Page content

I tried Serverless framework with Python+AWS Lambda.

Prerequirement

Node.js and npm:

$ node -v
v10.19.0
$ npm -v
7.5.2

Install

I created my serverless account with Google SSO:

sudo npm install -g serverless

Hello world

Create a project:

$ serverless

Serverless: No project detected. Do you want to create a new one? Yes
Serverless: What do you want to make? AWS Python
Serverless: What do you want to call this project? hello-sl-python

Project successfully created in 'hell-sl-python' folder.

You can monitor, troubleshoot, and test your new service with a free Serverless account.

Serverless: Would you like to enable this? Yes

You are not logged in or you do not have a Serverless account.

Serverless: Do you want to login or register? login
Serverless: Logging you in via your default browser...
Serverless: You sucessfully logged in to Serverless.
Serverless: Please run 'serverless' to configure your service

Serverless: What do you want to name this application? hello-serverless

Your project is setup for monitoring, troubleshooting and testing

Serverless: Would you like to setup a command line <tab> completion? Yes
Serverless: Which Shell do you use ? bash
Serverless: We will install completion to ~/.bashrc, is it ok ? Yes

Command line <tab> completion was successfully setup. Make sure to reload your SHELL.
You may uninstall it by running: serverless config tabcompletion uninstall

Deploy your project and monitor, troubleshoot and test it:
- Run “serverless deploy” to deploy your service.
- Run “serverless dashboard” to view the dashboard.

hello-sl-python directory structure:

.
├── handler.py
└── serverless.yml

handler.py:

import json

def hello(event, context):
    body = {
        "message": "Go Serverless v1.0! Your function executed successfully!",
        "input": event
    }

    response = {
        "statusCode": 200,
        "body": json.dumps(body)
    }

    return response

    # Use this code if you don't use the http event with the LAMBDA-PROXY
    # integration
    """
    return {
        "message": "Go Serverless v1.0! Your function executed successfully!",
        "event": event
    }
    """

Default serverless.yml without comment lines:

service: hello-sl-python
app: hello-serverless
org: atlex00

frameworkVersion: '2'

provider:
  name: aws
  runtime: python3.8
  lambdaHashingVersion: 20201221

functions:
  hello:
    handler: handler.hello

Change functions as follows:

functions:
  hello:
    handler: handler.hello
    events:
     - http:
        path: hello
        method: post

Deploy the handler:

$ serverless deploy -v
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Installing dependencies for custom CloudFormation resources...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
CloudFormation - CREATE_IN_PROGRESS - AWS::CloudFormation::Stack - hello-sl-python-dev
CloudFormation - CREATE_IN_PROGRESS - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - CREATE_IN_PROGRESS - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - CREATE_COMPLETE - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - CREATE_IN_PROGRESS - AWS::S3::BucketPolicy - ServerlessDeploymentBucketPolicy
CloudFormation - CREATE_IN_PROGRESS - AWS::S3::BucketPolicy - ServerlessDeploymentBucketPolicy
CloudFormation - CREATE_COMPLETE - AWS::S3::BucketPolicy - ServerlessDeploymentBucketPolicy
CloudFormation - CREATE_COMPLETE - AWS::CloudFormation::Stack - hello-sl-python-dev
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service hello-sl-python.zip file to S3 (81.83 KB)...
Serverless: Uploading custom CloudFormation resources...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
CloudFormation - UPDATE_IN_PROGRESS - AWS::CloudFormation::Stack - hello-sl-python-dev
CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - ApiGatewayLogGroup
CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - HelloLogGroup
CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleCustomResourcesLambdaExecution
CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleCustomResourcesLambdaExecution
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - HelloLogGroup
CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - ApiGatewayLogGroup
CloudFormation - CREATE_COMPLETE - AWS::Logs::LogGroup - HelloLogGroup
CloudFormation - CREATE_COMPLETE - AWS::Logs::LogGroup - ApiGatewayLogGroup
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceHello
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceHello
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Resource - ApiGatewayResourceHello
CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::SubscriptionFilter - CloudWatchLogsSubscriptionFilterHelloLogGroup
CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::SubscriptionFilter - CloudWatchLogsSubscriptionFilterApiGatewayLogGroup
CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::SubscriptionFilter - CloudWatchLogsSubscriptionFilterHelloLogGroup
CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::SubscriptionFilter - CloudWatchLogsSubscriptionFilterApiGatewayLogGroup
CloudFormation - CREATE_COMPLETE - AWS::Logs::SubscriptionFilter - CloudWatchLogsSubscriptionFilterHelloLogGroup
CloudFormation - CREATE_COMPLETE - AWS::Logs::SubscriptionFilter - CloudWatchLogsSubscriptionFilterApiGatewayLogGroup
CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - EnterpriseLogAccessIamRole
CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - EnterpriseLogAccessIamRole
CloudFormation - CREATE_COMPLETE - AWS::IAM::Role - IamRoleCustomResourcesLambdaExecution
CloudFormation - CREATE_COMPLETE - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - CustomDashresourceDashapigwDashcwDashroleLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - CustomDashresourceDashapigwDashcwDashroleLambdaFunction
CloudFormation - CREATE_COMPLETE - AWS::Lambda::Function - CustomDashresourceDashapigwDashcwDashroleLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - CREATE_COMPLETE - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - CREATE_COMPLETE - AWS::IAM::Role - EnterpriseLogAccessIamRole
CloudFormation - CREATE_IN_PROGRESS - Custom::ApiGatewayAccountRole - CustomApiGatewayAccountCloudWatchRole
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Version - HelloLambdaVersionu0ef7NQRbLbF3GnoljE9IcuPhKydwlJy6rHj1t8AKrU
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloPost
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - HelloLambdaPermissionApiGateway
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloPost
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Version - HelloLambdaVersionu0ef7NQRbLbF3GnoljE9IcuPhKydwlJy6rHj1t8AKrU
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethodHelloPost
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - HelloLambdaPermissionApiGateway
CloudFormation - CREATE_COMPLETE - AWS::Lambda::Version - HelloLambdaVersionu0ef7NQRbLbF3GnoljE9IcuPhKydwlJy6rHj1t8AKrU
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1614622959161
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1614622959161
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Deployment - ApiGatewayDeployment1614622959161
CloudFormation - CREATE_COMPLETE - AWS::Lambda::Permission - HelloLambdaPermissionApiGateway
CloudFormation - CREATE_IN_PROGRESS - Custom::ApiGatewayAccountRole - CustomApiGatewayAccountCloudWatchRole
CloudFormation - CREATE_COMPLETE - Custom::ApiGatewayAccountRole - CustomApiGatewayAccountCloudWatchRole
CloudFormation - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - hello-sl-python-dev
CloudFormation - UPDATE_COMPLETE - AWS::CloudFormation::Stack - hello-sl-python-dev
Serverless: Stack update finished...
Service Information
service: hello-sl-python
stage: dev
region: us-east-1
stack: hello-sl-python-dev
resources: 18
api keys:
  None
endpoints:
  POST - https://wi1enxyvse.execute-api.us-east-1.amazonaws.com/dev/hello
functions:
  hello: hello-sl-python-dev-hello
layers:
  None

Stack Outputs
EnterpriseLogAccessIamRole: arn:aws:iam::{{ my_account_ID }}:role/hello-sl-python-dev-EnterpriseLogAccessIamRole-1TGHCKLT2ISA2
HelloLambdaFunctionQualifiedArn: arn:aws:lambda:us-east-1:{{ my_account_ID }}:function:hello-sl-python-dev-hello:1
ServiceEndpoint: https://wi1enxyvse.execute-api.us-east-1.amazonaws.com/dev
ServerlessDeploymentBucketName: hello-sl-python-dev-serverlessdeploymentbucket-k82rer3pefda

Serverless: Publishing service to the Serverless Dashboard...
Serverless: Successfully published your service to the Serverless Dashboard: https://app.serverless.com/atlex00/apps/hello-serverless/hello-sl-python/dev/us-east-1
  • The AWS account used while deploying is the default AWS CLI profile.
  • API gateway was created.
    • integrationstyp: Lambda-Funktion
  • Lambda created
    • hello-sl-python-dev-hello <- API gateway pass to here, Laufzeit=Python 3.8
    • hello-sl-python-dev-custom-resource-apigw-cw-role :Laufzeit=Nodejs 12.x??

Check:

$ curl -X POST https://wi1enxyvse.execute-api.us-east-1.amazonaws.com/dev/hello -vvv
*   Trying 13.226.220.22:443...
* TCP_NODELAY set
* Connected to wi1enxyvse.execute-api.us-east-1.amazonaws.com (13.226.220.22) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=*.execute-api.us-east-1.amazonaws.com
*  start date: May  7 00:00:00 2020 GMT
*  expire date: Jun  7 12:00:00 2021 GMT
*  subjectAltName: host "wi1enxyvse.execute-api.us-east-1.amazonaws.com" matched cert's "*.execute-api.us-east-1.amazonaws.com"
*  issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x55cd1cf23800)
> POST /dev/hello HTTP/2
> Host: wi1enxyvse.execute-api.us-east-1.amazonaws.com
> user-agent: curl/7.68.0
> accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200
< content-type: application/json
< content-length: 2479
< date: Mon, 01 Mar 2021 18:26:42 GMT
< x-amzn-requestid: a1408afb-fbc6-4120-aa6e-0c01c8406b05
< x-amz-apigw-id: bhS7YFdmIAMFhcg=
< x-amzn-trace-id: Root=1-603d31e2-5187350962e6ac3c1376724a;Sampled=0
< x-cache: Miss from cloudfront
< via: 1.1 7f8004828cd106219da01f6385b03338.cloudfront.net (CloudFront)
< x-amz-cf-pop: LAX50-C1
< x-amz-cf-id: zaQiF2KGsewASi0a6_MsNVkYmZVIidZiEUjH4qHK_jWv__nWNTgivA==
<
{"message": "Go Serverless v1.0! Your function executed successfully!", "input": {"resource": "/hello", "path": "/hello", "httpMethod": "POST", "headers": {"Accept": "*/*", "CloudFront-Forwarded-Proto": "https", "CloudFront-Is-Desktop-Viewer": "true", "CloudFront-Is-Mobile-Viewer": "false", "CloudFront-Is-SmartTV-Viewer": "false", "CloudFront-Is-Tablet-Viewer": "false", "CloudFront-Viewer-Country": "DE", "Host": "wi1enxyvse.execute-api.us-east-1.amazonaws.com", "User-Agent": "curl/7.68.0", "Via": "2.0 7f8004828cd106219da01f6385b03338.cloudfront.net (CloudFront)", "X-Amz-Cf-Id": "zaQiF2KGsewASi0a6_MsNVkYmZVIidZiEUjH4qHK_jWv__nWNTgivA==", "X-Amzn-Trace-Id": "Root=1-603d31e2-5187350962e6ac3c1376724a", "X-Forwarded-For": "xxx.xxx.xxx.xxx, xxx.xxx.xxx.xxx", "X-Forwarded-Port": "443", "X-Forwarded-Proto": "https"}, "multiValueHeaders": {"Accept": ["*/*"], "CloudFront-Forwarded-Proto": ["https"], "CloudFront-Is-Desktop-Viewer": ["true"], "CloudFront-Is-Mobile-Viewer": ["false"], "CloudFront-Is-SmartTV-Viewer": ["false"], "CloudFront-Is-Tablet-Viewer": ["false"], "CloudFront-Viewer-Country": ["DE"], "Host": ["wi1enxyvse.execute-api.us-east-1.amazonaws.com"], "User-Agent": ["curl/7.68.0"], "Via": ["2.0 7f8004828cd106219da01f6385b03338.cloudfront.net (CloudFront)"], "X-Amz-Cf-Id": ["zaQiF2KGsewASi0a6_MsNVkYmZVIidZiEUjH4qHK_jWv__nWNTgivA=="], "X-Amzn-Trace-Id": ["Root=1-603d31e2-5187350962e6ac3c1376724a"], "X-Forwarded-For": ["xxx.xxx.xxx.xxx, xxx.xxx.xxx.xxx"], "X-Forwarded-Port": ["443"], "X-Forwarded-Proto": ["https"]}, "queryStringParameters": null, "multiValueQueryStringParameters": null, "pathParameters": null, "stageVariables": null, "requestContext": {"resourceId": "rckpj2", "resourcePath": "/hello", "httpMethod": "POST", "extendedRequestId": "bhS7YFdmIAMFhcg=", "requestTime": "01/Mar/2021:18:26:42 +0000", "path": "/dev/hello", "accountId": "{{ my_account_ID }}", "protocol": "HTTP/1.1", "stage": "dev", "domainPrefix": "wi1enxyvse", "requestTimeEpoch": 1614623202306, "requestId": "a1408afb-fbc6-4120-aa6e-0c01c8406b05", "identity"* Connection #0 to host wi1enxyvse.execute-api.us-east-1.amazonaws.com left intact
: {"cognitoIdentityPoolId": null, "accountId": null, "cognitoIdentityId": null, "caller": null, "sourceIp": "xxx.xxx.xxx.xxx", "principalOrgId": null, "accessKey": null, "cognitoAuthenticationType": null, "cognitoAuthenticationProvider": null, "userArn": null, "userAgent": "curl/7.68.0", "user": null}, "domainName": "wi1enxyvse.execute-api.us-east-1.amazonaws.com", "apiId": "wi1enxyvse"}, "body": null, "isBase64Encoded": false}}

Another way to check:

$ serverless invoke -f hello -l
Serverless: Deprecation warning: Starting with next major version, API Gateway naming will be changed from "{stage}-{service}" to "{service}-{stage}".
            Set "provider.apiGateway.shouldStartNameWithService" to "true" to adapt to the new behavior now.
            More Info: https://www.serverless.com/framework/docs/deprecations/#AWS_API_GATEWAY_NAME_STARTING_WITH_SERVICE
{
    "statusCode": 200,
    "body": "{\"message\": \"Go Serverless v1.0! Your function executed successfully!\", \"input\": {}}"
}
--------------------------------------------------------------------
START RequestId: 57d5a998-08a2-4e1a-a967-bb3191a38873 Version: $LATEST
SERVERLESS_ENTERPRISE {"c": true, "b": "{{ long_base64_like_strings }}", "origin": "sls-agent"}
END RequestId: 57d5a998-08a2-4e1a-a967-bb3191a38873
REPORT RequestId: 57d5a998-08a2-4e1a-a967-bb3191a38873  Duration: 4.43 ms       Billed Duration: 5 msMemory Size: 1024 MB     Max Memory Used: 64 MB

After playing, delete the environment:

$ serverless remove
Serverless: Deprecation warning: Starting with next major version, API Gateway naming will be changed from "{stage}-{service}" to "{service}-{stage}".
            Set "provider.apiGateway.shouldStartNameWithService" to "true" to adapt to the new behavior now.
            More Info: https://www.serverless.com/framework/docs/deprecations/#AWS_API_GATEWAY_NAME_STARTING_WITH_SERVICE
Serverless: Getting all objects in S3 bucket...
Serverless: Removing objects in S3 bucket...
Serverless: Removing Stack...
Serverless: Checking Stack delete progress...
.........................
Serverless: Stack delete finished...

Serverless: Stack delete finished...
Serverless: Publishing service to the Serverless Dashboard...
Serverless: Successfully published your service to the Serverless Dashboard: https://app.serverless.com/atlex00/apps/hello-serverless/hello-sl-python/dev/us-east-1

Auto created AWS resources in this example

  • Cloud Formation: To deploy and mange AWS infra.
  • S3: Zipped Python code is stored in here.
  • IAM: Lambda execution.