Specification : AWS, API Gateway, Serverless, Lambda, RDS, Postman

Lab Topology

aws-lambda-diagram

aws-lambda-detail

 

Step-by-step

  • Create IAM role for allow configuration
  • Create Database table with DynamoDB
  • Create AWS API Gateway service
  • Create Lambda function
  • Testing CRUD with postman
  • Verify

A. Create IAM role

First step is create IAM role to allow Lambda function to call AWS services, for it you can follow guide bellow :

  1. Login to your AWS console, search and chose IAM menu

aws1

  1. Choose Roles and create role

aws2

  1. Choose AWS Services -> Lambda and Next

aws3

  1. And you can see menu bellow aws4

  2. For integrate lambda with RDS & cloudwatch, wee need filter & checklist cloudwatchfullaccess aws5

  3. And the last one, search dynamodb and checklist full access permissions aws6

  4. Add rolename aws7

  5. Verify you already added two roles for it, and create role aws8


 

B. Create RDS DynamoDB Table

Next step we need create database for store data, with step bellow :

  1. Choose DynamoDB services

aws9

  1. Choose Dashboard and create Table

aws10

  1. Put table name, you can same with our tutorial use food-aws-serverless and put Partition Key with foodId for indexing like bellow, and create table

aws11

  1. You can see table after created

aws12


 

C. Create Lambda Function

  1. After create RDS, next create Lambda function to integrate between API Gateway to RDS DynamoDB

aws13

  1. Choose Functions and create function

aws14

  1. And follow function like bellow and create function

aws15

aws16

  1. And you can see lambda function has been created, after that we need increase specs of lambda with step bellow. Click configuration > Edit, Increase value of Memory and Storage and save.

aws17 aws18

  1. And Important step is create lambda function for CRUD, choose code > edit lambda_function.py > copas code from bellow > and last deploy

aws19

lambda_function.py

import boto3
import json
from botocore.vendored import requests

from custom_encoder import CustomEncoder
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)

dynamodbTableName = 'food-aws-serverless'
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(dynamodbTableName)

getMethod = 'GET'
postMethod = 'POST'
patchMethod = 'PATCH'
deleteMethod = 'DELETE'
healthPath = '/health'
foodPath = '/food'

def lambda_handler(event, context):
    logger.info(event)
    httpMethod = event['httpMethod']
    path = event['path']
    if httpMethod == getMethod and path == healthPath:
        response = buildResponse(200)
    elif httpMethod == getMethod and path == foodPath:
        response = getFood(event['queryStringParameters']['foodId'])
    elif httpMethod == postMethod and path == foodPath:
        response = saveFood(json.loads(event['body']))
    elif httpMethod == patchMethod and path == foodPath:
        requestBody = json.loads(event['body'])
        response = modifyFood(requestBody['foodId'], requestBody['updateKey'], requestBody['updateValue'])
    elif httpMethod == deleteMethod and path == foodPath:
        requestBody = json.loads(event['body'])
        response = deleteFood(requestBody['foodId'])
    else:
        response = buildResponse(404, 'Sorry, Not Found')
    
    return response

def getFood(foodId):
    try:
        response = table.get_item(
            Key={
                'foodId': foodId
            }
        )
        if 'Item' in response:
            return buildResponse(200, response['Item'])
        else:
            return buildResponse(404, {'Message' : 'FoodId: %s not found' % foodId})
    except:
        logger.exception('Do your custom error handling here, I am just gonna log it out there!')

def saveFood(requestBody):
    try:
        table.put_item(Item=requestBody)
        body = {
            'Operation' : 'SAVE',
            'Message' : 'SUCCESS',
            'Item' : requestBody
        }
        return buildResponse(200, body)
    except:
        logger.exception('Do your custom error handling here, I am just gonna log it out there!')

def modifyFood(foodId, updateKey, updateValue):
    try:
        response = table.update_item(
            Key={
                'foodId': foodId
            },
            UpdateExpression='set %s = :value' % updateKey,
            ExpressionAttributeValues={
                ':value': updateValue
            },
            ReturnValues='UPDATED_NEW'
        )
        body = {
            'Operation': 'UPDATE',
            'Message': 'SUCCESS',
            'UpdatedAttrebutes': response
        }
        return buildResponse(200, body)
    except:
        logger.exception('Do your custom error handling here, I am just gonna log it out there!')

def deleteFood(foodId):
    try:
        response = table.delete_item(
            Key={
                'foodId': foodId
            },
            ReturnValues='ALL_OLD'
        )
        body = {
            'Operation': 'DELETE',
            'Message': 'SUCCESS',
            'UpdatedAttrebutes': response
        }
        return buildResponse(200, body)
    except:
        logger.exception('Do your custom error handling here, I am just gonna log it out there!')



def buildResponse(statusCode, body=None):
    response = {
        'statusCode' : statusCode,
        'headers' : {
            'Content-Type': 'application/json',
            'Access-Controll-Allow-Origin': '*'
        }
    }
    if body is not None:
        response['body'] = json.dumps(body, cls=CustomEncoder)
    return response

  1. And last on is create new file named custom_encoder.py > put code bellow > and deploy again.

aws20

custom_encoder.py

import json
from decimal import Decimal

class CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Decimal):
            return float(obj)

        return json.JSONEncoder.default(self, obj)

 


 

D. Create AWS API Gateway

Next is create Rest API gateway, to interact between and user & AWS services, for more you can follow bellow step :

  1. Choose AWS API Gateway menu

aws21

  1. Choose Public REST API and build

aws22

  1. Click REST > New API and put API name

aws23

  1. And next create Resource for place are API Method, bellow for detail structure :
1. Resource /health
Method GET

2. Resource /food
Method GET, POST, PATCH, DELETE

3. Resource /foods (optional, not important)
Method GET, POST, PATCH, DELETE

aws24

  1. Input Resource name, Resource path and checklist Enable API Gateway

aws25

  1. And create also for /food resource like above

aws27

  1. After create Resource, next create Method for every resource. Click Resource name, for example /health > Create Method
1. Resource /health
Method GET

2. Resource /food
Method GET, POST, PATCH, DELETE

3. Resource /foods (optional, not important)
Method GET, POST, PATCH, DELETE

aws29

  1. Chose Method, for example GET and click OK

aws30

  1. Checklist Lambda Function > Proxy integration > and chose Lambda Function previously created > save

aws31

  1. Click OK for continue, and REPEAT create Method for every resource like it and follow structure

aws32

  1. After all Method and Resource has been created, last step is Deploy API like bellow

aws33

  1. Create new stage name, for example: prod, and finish you already created API Gateway

aws34


 

E. Testing & Verify CRUD

  1. Before testing, you need download Postman Application for testing API, download on : https://www.postman.com/downloads/
  2. First step is copy API Endpoint in APIs menu to access from public internet

aws36

GET Option (Health Check)

To check API status reached or not, with status 200 OK

aws37

POST Option

To Put new database to RDS via Json format file (key-value), bellow example to add data :

{
    "foodId": "001",
    "name": "Banana",
    "price": "500"
}

aws38 aws39

And you can see result success POST in DynamoDB table menu :

aws40

DELETE Option

For delete database on RDS you can use delete option with index ID (foodId) like bellow

aws41

And you can see after deleted foodId = 002 on RDS Table

aws42

GET Option

To check detail table by foodId

aws43

PATCH Option

Patch you can use for update about value/key, bellow example for update banana price, from 500 to 99999

aws44 aws45


 

Reference