AWS Lambda + Serverless Framework + Python— Part 1 : A Step By Step “Hello World”

Now add the permissions you need for the created user. In my case, I am going to choose the Administration permission (arn:aws:iam::aws:policy/AdministratorAccess) that provides full access to AWS services and resources.

Note: When thinking about security, the administrator access is not a good choice, you can refine your user permissions by choosing only the AWS permissions you need.

Please keep in mind that you must download and keep the generated credentials in a safe place:

For the sake of simplicity, I added a new profile to the file

~/.aws/credentials

with the name

serverless

By adding the credentials to the AWS credentials file, I can use any AWS command using the desired profile.

Example:

aws s3 cp my_file s3://my_bucket --profile serverless

Installing and Configuring Serverless Framework

You can install Serverless using a single command:

sudo npm install -g serverless

Let’s configure Serverless:

serverless config credentials --provider aws --key  --secret 

If you stored the key/secret to the credential files, we can use the different Serverless commands by designtating the profile at each command:

serverless deploy --aws-profile serverless

We can also export the profile as well as the region to environement variables:

export AWS_PROFILE="serverless" && export AWS_REGION=eu-west-1

Initializing our Project

In the app folder, we need to create a serverless.yml file. This file is needed to configure how our application will behave.

We need also to create our Python function (called handler.py):

In order to do this, let’s execute this command:

serverless create --template aws-python3 --name hello-world

This will create the handler file, the configuration file and the .gitignore file:

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

This is how our serverless.yml file looks like:

provider:
name: aws
runtime: python3.6
functions:
hello:
handler: handler.hello

This is how the handler.py file looks like:

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
}
"""

Deploying our Project

Once the template files are created, we have a working AWS Lambda function, we need to deploy it:

export AWS_PROFILE="serverless"
serverless deploy

Note: You need to change the profile name to use your own one.

The deployment output looks like this. You can see that our code is zipped and deployed to a S3 bucket before being deployed to Lambda.

Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
.....
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (390 B)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
................
Serverless: Stack update finished...
Service Information
service: hello-world
stage: dev
region: us-east-1
stack: hello-world-dev
api keys:
None
endpoints:
None
functions:
hello: hello-world-dev-hello

The function is now deployed.

Adding Events to our Function

While you do already have a function defined called hello that’s linked to a function handler, you currently have no way of triggering that function. That’s why we need to add an event to the function defined in serverless.yml. Update it as follows:

We defined a function called hello but we did not define a way to trigger the function, this is when adding an “event” is useful. Edit the serverless.yml file:

provider:
name: aws
runtime: python3.6
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get

According to our configuration, the function will be called using the /hello url.

Note: You can choose your own url.

Let’s deploy:

serverless deploy -v
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (390 B)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
CloudFormation - UPDATE_IN_PROGRESS - AWS::CloudFormation::Stack - hello-world-dev
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - UPDATE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - UPDATE_COMPLETE - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceHello
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - HelloLambdaPermissionApiGateway
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceHello
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - HelloLambdaPermissionApiGateway
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Resource - ApiGatewayResourceHello
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloGet
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloGet
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethodHelloGet
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1534113893559
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1534113893559
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Deployment - ApiGatewayDeployment1534113893559
CloudFormation - CREATE_COMPLETE - AWS::Lambda::Permission - HelloLambdaPermissionApiGateway
CloudFormation - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - hello-world-dev
CloudFormation - UPDATE_COMPLETE - AWS::CloudFormation::Stack - hello-world-dev
Serverless: Stack update finished...
Service Information
service: hello-world
stage: dev
region: us-east-1
stack: hello-world-dev
api keys:
None
endpoints:
GET - https://x7o0xwsbkd.execute-api.us-east-1.amazonaws.com/dev/hello
functions:
hello: hello-world-dev-hello
Stack Outputs
HelloLambdaFunctionQualifiedArn: arn:aws:lambda:us-east-1:998335703874:function:hello-world-dev-hello:1
ServiceEndpoint: https://x7o0xwsbkd.execute-api.us-east-1.amazonaws.com/dev
ServerlessDeploymentBucketName: hello-world-dev-serverlessdeploymentbucket-qqgrblrjprhu

As you may see in the deployment logs that the AWS lambda function has a new URL:

https://x7o0xwsbkd.execute-api.us-east-1.amazonaws.com/dev/hello

We can test our function using the browser, tools like Postman, the CLI or Serverless invoke command.

Using CURL:

curl -X GET https://x7o0xwsbkd.execute-api.us-east-1.amazonaws.com/dev/hello

Output:

{
"message":"Go Serverless v1.0! Your function executed successfully!",
"input":{
"resource":"/hello",
"path":"/hello",
"httpMethod":"GET",
"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":"FR",
"Host":"x7o0xwsbkd.execute-api.us-east-1.amazonaws.com",
"User-Agent":"curl/7.47.0",
"Via":"1.1 xxx.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id":"",
"X-Amzn-Trace-Id":"Root=1-5b70bbe0-f318b862a8dfdb1e38fc337e",
"X-Forwarded-For":"",
"X-Forwarded-Port":"443",
"X-Forwarded-Proto":"https"
},
"queryStringParameters":null,
"pathParameters":null,
"stageVariables":null,
"requestContext":{
"resourceId":"bsk6aq",
"resourcePath":"/hello",
"httpMethod":"GET",
"extendedRequestId":"LiJLDHe3oAMF7kQ=",
"requestTime":"12/Aug/2018:22:59:44 +0000",
"path":"/dev/hello",
"accountId":"xxx",
"protocol":"HTTP/1.1",
"stage":"dev",
"requestTimeEpoch":1534114784336,
"requestId":"6727b590-9e83-11e8-a9cc-61641c6c77ac",
"identity":{
"cognitoIdentityPoolId":null,
"accountId":null,
"cognitoIdentityId":null,
"caller":null,
"sourceIp":"",
"accessKey":null,
"cognitoAuthenticationType":null,
"cognitoAuthenticationProvider":null,
"userArn":null,
"userAgent":"curl/7.47.0",
"user":null
},
"apiId":"x7o0xwsbkd"
},
"body":null,
"isBase64Encoded":false
}
}

Using serverless invoke:

sls invoke -f hello

Output:

{
"statusCode": 200,
"body": "{"message": "Go Serverless v1.0! Your function executed successfully!", "input": {}}"
}

Tailing Logs

Sometimes, you need to see the execution or the deployment logs. This is the command to tail the logs:

sls logs -f hello --tail

Deleting the Function

Using sls remove command, we can delete the deployed service from AWS Lambda.

serverless remove

We can add other options like:

  • --stage or -s The name of the stage in service.
  • --region or -r The name of the region in stage.
  • --verbose or -v Shows all stack events during deployment.

Note: Removing a service will also remove the S3 bucket.

Connect Deeper

We have seen how to deploy our first Lambda function using the Serverless Framework. Stay in touch as the upcoming posts will go more in depth.

I am creating a series of blog posts to help you develop, deploy and run (mostly) Python applications on AWS Lambda using Serverless Framwork.

You can find my other articles about the same topic but using other frameworks like Creating a Serverless Uptime Monitor & Getting Alerted by SMS — Lambda, Zappa & Python or Creating a Serverless Python API Using AWS Lambda & Chalice

Don’t forget to subscribe to Shipped: An Independent Newsletter Focused On Serverless, Containers, FaaS & Other Interesting Stuff.

read original article here