AWS Console : how to create a lambda microservice

AWS Console : how to create a lambda microservice

One of the most common use case of lambda is performing CRUD operation on a database table and expose these operations using API gateway as a lambda microservice

In this step by step guide, we will be using AWS Management Console to create a microservice to perform following operation on a User object

Operation Functionality
POST Create new users
PUT Update user details based on the unique id
GET Get user details based on the unique id
GET All Get all users
DELETE Delete user based on the unique id

Pre-requisites

  • AWS AccountIf you do not have an account follow this guide to create one
  • NodeJsIf you do not have NodeJs configured use this guide to install nodejs on your machine.

Following steps will guide us in creating a lambda microservice

1. Login to your AWS account and select a region (e.g. us-east-1)

Make sure this region will not change when working for all other services

Select Region

2. Create a DynamoDB table

  1. Go to DynamoDB service.
  2. Click create table
  3. Enter table name and primary id field name

In this guide will are using an autogenerated id field to uniquely distinguish different users. Based on your requirements you can use any other field like “email” or “username”

DynamoDB create table home

DynamoDB create table attributes

DynamoDB create table final

3. Create IAM role for lambda

3.1 Open IAM Service Console and create a new role

3.2 Select trust entity type

3.3 Assign DynamoDB and CloudWatch Permissions

3.4 Give a name to the role and complete role creation

4. NodeJS code for lambda function

4.1 Configure code directory using following steps

// create a directory
mkdir lambda-microservice

// make it woring directory
cd lambda-microservice

// initialize node project
npm init

// install dependency
npm install --save uuid

// create code files
touch create.js

touch update.js

touch list.js

touch get.js

touch delete.js

4.2 copy following code to each file

create.js

'use strict';

const uuid = require('uuid');
const AWS = require('aws-sdk');

const dynamoDb = new AWS.DynamoDB.DocumentClient();

module.exports.create = (event, context, callback) => {
    const timestamp = new Date().getTime();
    c
    const data = JSON.parse(event.body);

    // input validations
    if (typeof data.first_name !== 'string' || typeof data.last_name !== 'string') {
        console.error('Validation Failed');
        callback(null, {
            statusCode: 400,
            headers: {
                'Content-Type': 'text/plain'
            },
            body: 'Couldn\'t create the user.',
        });
        return;
    }

    // dynamo table input params
    const params = {
        TableName: "users",
        Item: {
            id: uuid.v1(),
            first_name: data.first_name,
            last_name: data.last_name,
            createdAt: timestamp,
            updatedAt: timestamp,
        },
    };

    // write the user to the database
    dynamoDb.put(params, (error) => {
        // handle potential errors
        if (error) {
            console.error(error);
            callback(null, {
                statusCode: error.statusCode || 501,
                headers: {
                    'Content-Type': 'text/plain'
                },
                body: 'Couldn\'t create the user.',
            });
            return;
        }

        // create a response
        const response = {
            statusCode: 200,
            body: JSON.stringify(params.Item),
        };
        callback(null, response);
    });
};

update.js

'use strict';

const AWS = require('aws-sdk');

const dynamoDb = new AWS.DynamoDB.DocumentClient();

module.exports.update = (event, context, callback) => {
    const timestamp = new Date().getTime();
    const data = JSON.parse(event.body);

    // validation
    if (typeof data.first_name !== 'string' || typeof data.last_name !== 'string') {
        console.error('Validation Failed');
        callback(null, {
            statusCode: 400,
            headers: {
                'Content-Type': 'text/plain'
            },
            body: 'Couldn\'t update the user.',
        });
        return;
    }

    const params = {
        TableName: "users",
        Key: {
            id: event.pathParameters.id,
        },
        ExpressionAttributeValues: {
            ':first_name': data.first_name,
            ':last_name': data.last_name,
            ':updatedAt': timestamp,
        },
        UpdateExpression: 'SET first_name = :first_name, last_name = :last_name, updatedAt = :updatedAt',
        ReturnValues: 'ALL_NEW',
    };

    // update the user in the database
    dynamoDb.update(params, (error, result) => {
        // handle potential errors
        if (error) {
            console.error(error);
            callback(null, {
                statusCode: error.statusCode || 501,
                headers: {
                    'Content-Type': 'text/plain'
                },
                body: 'Couldn\'t fetch the user.',
            });
            return;
        }

        // create a response
        const response = {
            statusCode: 200,
            body: JSON.stringify(result.Attributes),
        };
        callback(null, response);
    });
};

list.js

'use strict';

const AWS = require('aws-sdk');
const dynamoDb = new AWS.DynamoDB.DocumentClient();
const params = {
    TableName: "users",
};

module.exports.list = (event, context, callback) => {
    // fetch all users from the database
    dynamoDb.scan(params, (error, result) => {
        // handle potential errors
        if (error) {
            console.error(error);
            callback(null, {
                statusCode: error.statusCode || 501,
                headers: {
                    'Content-Type': 'text/plain'
                },
                body: 'Couldn\'t fetch the users.',
            });
            return;
        }

        // create a response
        const response = {
            statusCode: 200,
            body: JSON.stringify(result.Items),
        };
        callback(null, response);
    });
};

get.js

'use strict';

const AWS = require('aws-sdk');

const dynamoDb = new AWS.DynamoDB.DocumentClient();

module.exports.get = (event, context, callback) => {
    const params = {
        TableName: "users",
        Key: {
            id: event.pathParameters.id,
        },
    };

    // fetch user from the database
    dynamoDb.get(params, (error, result) => {
        // handle potential errors
        if (error) {
            console.error(error);
            callback(null, {
                statusCode: error.statusCode || 501,
                headers: {
                    'Content-Type': 'text/plain'
                },
                body: 'Couldn\'t fetch the user.',
            });
            return;
        }

        // create a response
        const response = {
            statusCode: 200,
            body: JSON.stringify(result.Item),
        };
        callback(null, response);
    });
};

delete.js

'use strict';

const AWS = require('aws-sdk'); // eslint-disable-line import/no-extraneous-dependencies

const dynamoDb = new AWS.DynamoDB.DocumentClient();

module.exports.delete = (event, context, callback) => {
    const params = {
        TableName: "users",
        Key: {
            id: event.pathParameters.id,
        },
    };

    // delete the user from the database
    dynamoDb.delete(params, (error) => {
        // handle potential errors
        if (error) {
            console.error(error);
            callback(null, {
                statusCode: error.statusCode || 501,
                headers: {
                    'Content-Type': 'text/plain'
                },
                body: 'Couldn\'t remove the user.',
            });
            return;
        }

        // create a response
        const response = {
            statusCode: 200,
            body: JSON.stringify({}),
        };
        callback(null, response);
    });
};

4.3 zip all code

// while inside lambda-microservice directory create zip

zip code.zip *

5. Create lambda functions

5.1 Open Lambda Console and click “create function”

Create New Lambda

5.2 Specify name, runtime and IAM role for lambda

Create Lambda Parameters

5.3 Repeat step 5.1 and 5.2 to create 4 more functions

5.4 Open each lambda function one by one and Upload code.zip (step 4.3) as shown in the image.

Please make sure to change the handler as following

  1. create lambda => create.create
  2. update lambda => update.update
  3. list lambda => list.list
  4. get lambda => get.get
  5. delete lambda => delete.delete

6. Configure API Gateway

6.1 Open API Gateway Console

6.2 Create a new API

6.3 Add API Post method for “users-create” lambda

6.4 Add API GET method for “users-list” lambda

Repeat step 6.3 to add a new method. This time method type will be “GET” and lambda function to be selected is “users-list”

6.5 Create a child resource for id parameter path

6.6 While selecting the child resource create GET method for “users-get”

Repeat step 6.3 to add a new method. This time method type will be “GET” and lambda function to be selected is “users-list”

6.7 While selecting the child resource create PUT method for “users-update”

Repeat step 6.3 to add a new method. This time method type will be “PUT” and lambda function to be selected is “users-update”

6.8 While selecting the child resource create DELETE method for “users-delete”

Repeat step 6.3 to add a new method. This time method type will be “DELETE” and lambda function to be selected is “users-delete”

6.9 Deploy API for use

Click Deploy API

Fill in the stage details and Deploy

Note down the URL

Now you can test the lambda microservice API using the URL generated in step 6.9

To test the API you can use POSTMAN or any other API client.

Let me know about any issue in any of the above step through comments I will try to resolve your query.

You can also ask me for any other step by step guide related to serverless services of AWS.

By |2018-04-06T09:48:50+00:00April 5th, 2018|Lambda, Step By Step|0 Comments

About the Author:

Leave A Comment