Your first Lambda function on AWS with Python using the AWS CLI.

Today we will use the AWS CLI Tools to create a Basic Lambda Function that will use the requests library to make a GET request to a Random Quotes API, from the request we will get a random Quote, Category and Author.

Update: No need to install the requests library as you can import it from botocore as from botocore.vendored import requests

Breakdown on what we will be doing:

  • Create Lambda and Trust Relationship IAM Policy
  • Create Lambda Role and Associate the Policy
  • Create the Lambda Function in Python
  • Install the Requests Library and Zip the Package
  • Use the CLI To Upload and Create the Function
  • Invoke the Function and look at the Output

Create the IAM Role for Lambda:

Create the lambda-policy.json:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1508266078275",
      "Action": [
        "logs:PutLogEvents",
        "logs:CreateLogGroup",
        "logs:CreateLogStream"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}

Create the trust-relationship.json:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Create the Lambda Role:

$ aws iam create-role --role-name quotes-lambda-role --assume-role-policy-document file://trust-relationship.json
{
    "Role": {
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17", 
            "Statement": [
                {
                    "Action": "sts:AssumeRole", 
                    "Principal": {
                        "Service": "lambda.amazonaws.com"
                    }, 
                    "Effect": "Allow", 
                    "Sid": ""
                }
            ]
        }, 
        "RoleId": "12345678901234567890", 
        "CreateDate": "2017-10-18T23:07:18.509Z", 
        "RoleName": "quotes-lambda-role", 
        "Path": "/", 
        "Arn": "arn:aws:iam::123456789012:role/quotes-lambda-role"
    }
}

Create the IAM Policy for Lambda which is a Basic Execution Policy:

$ aws iam create-policy --policy-name quotes-lambda-policy --policy-document file://lambda-policy.json
{
    "Policy": {
        "PolicyName": "quotes-lambda-policy", 
        "CreateDate": "2017-10-18T23:08:28.671Z", 
        "AttachmentCount": 0, 
        "IsAttachable": true, 
        "PolicyId": "12345678901234567890", 
        "DefaultVersionId": "v1", 
        "Path": "/", 
        "Arn": "arn:aws:iam::123456789012:policy/quotes-lambda-policy", 
        "UpdateDate": "2017-10-18T23:08:28.671Z"
    }
}

Attach the Policy to the Role:

$ aws iam attach-role-policy --policy-arn arn:aws:iam::123456789012:policy/quotes-lambda-policy --role-name quotes-lambda-role

Delete the Policy Documents:

$ rm -rf trust-relationship.json lambda-policy.json

Create the Lambda Function and Zip the Package:

Create the Lmabda Function, which will use the os library to use environment variable within Lambda, and also the requests library which we will use to make the GET request to the Random Quotes API, to get a random quote, which we will return in the event handler.

Create the quotes.py

import os
import requests

url = os.environ['API_URL']

def handler(event, context):

    r = requests.get(url).json()
    responsedata = 'Author: '    + r['author'] + '\n'
    responsedata += 'Category: ' + r['cat']    + '\n'
    responsedata += 'Quote: '    + r['quote']  + '\n'

    return responsedata

In the current working directory, we will only have our quotes.py function. Now, as we require the requests library, we will need to install the requests library and specify the data directory to the current working directory. So then we will have our function and the directories of our dependencies, which we will zip up.

Update: No need to install the requests library as you can import it from botocore as from botocore.vendored import requests

Install the requests library:

$ pip install requests -t .
$ zip -r quotes.zip *

So at this moment, your working directory should look like the following (more or less):

$ ls ../code/ -la | awk '{print $9}'

certifi
certifi-2017.07.27.1-py2.7.egg-info
chardet
chardet-3.0.4-py2.7.egg-info
idna
idna-2.6-py2.7.egg-info
quotes.py
quotes.zip
requests
requests-2.18.4-py2.7.egg-info
urllib3
urllib3-1.22-py2.7.egg-info

As we have zipped up our package, we will create our Lambda function and we will pass the zip using the --zip-file option to upload the pakacge:

$ aws --region eu-west-1 lambda create-function --function-name quotes-lambda-function --zip-file fileb://quotes.zip --role arn:aws:iam::123456789012:role/quotes-lambda-role --handler quotes.handler --runtime python2.7 --environment Variables={API_URL=https://talaikis.com/api/quotes/random/}
{
    "TracingConfig": {
        "Mode": "PassThrough"
    }, 
    "CodeSha256": "cx3FK23409823FDSkjfsdhfhwoe394984", 
    "FunctionName": "quotes-lambda-function", 
    "CodeSize": 1125005, 
    "MemorySize": 128, 
    "FunctionArn": "arn:aws:lambda:eu-west-1:123456789012:function:quotes-lambda-function", 
    "Environment": {
        "Variables": {
            "API_URL": "https://talaikis.com/api/quotes/random/"
        }
    }, 
    "Version": "$LATEST", 
    "Role": "arn:aws:iam::123456789012:role/quotes-lambda-role", 
    "Timeout": 3, 
    "LastModified": "2017-10-18T23:25:47.642+0000", 
    "Handler": "quotes.handler", 
    "Runtime": "python2.7", 
    "Description": ""
}

Testing our Function:

Let's invoke our function via the AWS CLI and output the response to a text file:

$ aws --region eu-west-1 lambda invoke --function-name quotes-lambda-function output.txt
{
    "StatusCode": 200
}

And viewing the content from the file that we saved the content to:

$ cat output.txt 
"Author: Brian Tracy\nCategory: attitude\nQuote: Develop an attitude of gratitude, and give thanks for everything that happens to you, knowing that every step forward is a step toward achieving something bigger and better than your current situation.\n"

Coming Soon:

  • Replicating the Same Setup with OpenFaaS

In the following tutorial, I will go through the steps on only using the AWS CLI to setup API Gateway + Lambda, where we will setup a resource with a method that will accept a POST request that will invoke a Lambda function, that will push data, which sends a message to RocketChat via its API.