https://github.com/julien-muke/aws-serverless-microservices-api-architecture
Building a Serverless Microservices Architecture right in the AWS console using REST API to trigger a lambda function to perform CRUD operations in a database.
https://github.com/julien-muke/aws-serverless-microservices-api-architecture
dynamodb lambda-functions rest-api
Last synced: 5 months ago
JSON representation
Building a Serverless Microservices Architecture right in the AWS console using REST API to trigger a lambda function to perform CRUD operations in a database.
- Host: GitHub
- URL: https://github.com/julien-muke/aws-serverless-microservices-api-architecture
- Owner: julien-muke
- Created: 2023-12-28T12:29:22.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2023-12-30T14:48:22.000Z (over 2 years ago)
- Last Synced: 2024-05-28T19:28:51.006Z (about 2 years ago)
- Topics: dynamodb, lambda-functions, rest-api
- Homepage:
- Size: 10.7 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# ☁️ AWS Project - Serverless AWS Microservices Lab - REST API
## 📄 Introduction
A hands-on step-by-step lab of building a serverless microservices architecture right in the AWS console. We will create a working REST API to trigger our lambda function to perform CRUD operations in our database.
## 📝 Lab Overview
As shown in the architecture design below, we have serverless API microservice architecture, if we read it from left to right you'll notice that we have a client and that client is going to evoke a ref API through our API Gateway the API Gateway will then trigger a Lambda function and in our Lambda function, we're going to embed it with code python code and that code will allow the Lambda function to perform CRUD operations (Create Read Update and Delete), then Lambda will have the ability to perform CRUD operations into DynamoDB.
## 📐 Architecture Design

The client will perform the API call by using the "POST" HTTP method. Our client must provide a request payload to perform an API call. The request payload identifies the DynamoDB operation (CRUD) the client wants to perform with the necessary data.
*Assuming **apigateway-lambda-crud** is the table name of our DynamoDB table.*
An example request payload for a CREATE opertion shows as follows:
```json
{
"operation": "create",
"tableName": "apigateway-lambda-crud",
"payload": {
"Item": {
"id": "1",
"name": "Sam"
}
}
}
```
An example request payload for a DELETE operation shows as follows:
```json
{
"operation": "delete",
"tableName": "apigateway-lambda-crud",
"payload": {
"Item": {
"id": "1",
"name": "Sam"
}
}
}
```
An example request payload for a READ operation shows as follows:
```json
{
"operation": "read",
"tableName": "apigateway-lambda-crud",
"payload": {
"Key": {
"id": "1"
}
}
}
```
## ➡️ Step 1 - Create DynamoDB table
Create the DynamoDB table that the Lambda function uses.
To create a DynamoDB table
1. Open the DynamoDB console.
2. Choose Create table.
3. Create a table with the following settings.
* Table name – apigateway-lambda-crud
* Primary key – id (string)
4. Choose Create.

## ➡️ Step 2 - Create Lambda IAM Role
Create the execution role that gives your function permission to access AWS resources.
Before you can apply your Lambda Policy to a Lambda function, you have to create the policy in your own account and then apply it to an IAM role.
To create an IAM policy:
1. Navigate to the IAM console and choose Policies in the navigation pane. Choose Create policy.

2. Because I have already written the policy in JSON, you don’t need to use the Visual Editor, so you can choose the JSON tab and paste the content of the JSON policy document shown earlier in this post (remember to replace the placeholder account ID with your own account ID). Choose Review policy.
```bash
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"dynamodb:PutItem",
"dynamodb:DeleteItem",
"dynamodb:GetItem",
"dynamodb:Scan",
"dynamodb:Query",
"dynamodb:UpdateItem",
"logs:PutLogEvents",
"logs:CreateLogGroup"
],
"Resource": "*"
}
]
}
```

3. Name the policy `lambda-apigateway-dynamodb-policy` and give it a description that will help you remember the policy’s purpose. You also can view a summary of the policy’s permissions. Choose Create policy.

You have created the IAM policy that you will apply to the Lambda function.
### 👉 Attach the IAM policy to an IAM role
To apply `lambda-apigateway-dynamodb-policy` to a Lambda function, you first have to attach the policy to an IAM role.
To create a new role and attach MyLambdaPolicy to the role:
1. Navigate to the IAM console and choose Roles in the navigation pane. Choose Create role.

2. Choose AWS service and then choose Lambda. Choose Next: Permissions.

3. On the Attach permissions policies page, type `lambda-apigateway-dynamodb-policy` in the Search box. Choose `lambda-apigateway-dynamodb-policy` from the list of returned search results, and then choose Next: Review.

4. On the Review page, type `lambda-apigateway-dynamodb-role` in the Role name box and an appropriate description, and then choose Create role.

You have attached the policy you created earlier to a new IAM role, which in turn can be used by a Lambda function.
## ➡️ Step 3 - Apply the IAM role to a Lambda function
You have created an IAM role that has an attached IAM policy that grants both read and write access to DynamoDB and write access to CloudWatch Logs. The next step is to apply the IAM role to a Lambda function.
To apply the IAM role to a Lambda function:
Select "Author from scratch". Use name `LambdaCRUDOverHTTPS` , select Python 3.7 as Runtime. Under Permissions, select "Use an existing role", and select `lambda-apigateway-dynamodb-role` that we created, from the drop down
1. Navigate to the Lambda console and choose Create function.

2. Replace the existing sample code with the following code snippet and click "Deploy"
```bash
import boto3
import json
print('Loading function')
def lambda_handler(event,context):
'''Provide an event that contains the following keys:
- operation: one of the operations in the operations dict below
- tableName: required for operations that interact with DynamoDB
- payload: a parameter to pass to the operation being performed
'''
print("Received event: " + json.dumps(event, indent=1))
operation = event['operation']
if 'tableName' in event:
dynamo = boto3.resource('dynamodb').Table(event['tableName'])
operations = {
#CRUD operations shown below:
'create': lambda x: dynamo.put_item(**x),
'read': lambda x: dynamo.get_item(**x),
'update': lambda x: dynamo.update_item(**x),
'delete': lambda x: dynamo.delete_item(**x),
'echo': lambda x: x
}
if operation in operations:
return operations[operation](event.get('payload'))
else:
raise ValueError('Unrecognized operation "{}"'.format(operation))
```

## ➡️ Step 4 - Test Lambda Function
Let's test our newly created function. We will test our "echo" operation AND our "create" operation. "echo" is an operation that should output whatever the request/input/event submitted. "create" is an operation that will create a real record into the DynamoDB table (apigateway-lambda-crud) we created in the first step.
🔵 "echo" Operation TEST
1. Click the arrow on the "Test" button and click "Configure test events".

2. Paste the following JSON into the event. The field "operation" dictates what the lambda function will perform. In this case, it'd simply return the payload from input event as output. Click "Create" to save.
```bash
{
"operation": "echo",
"payload": {
"testkey1": "testvalue1",
"testkey2": "testvalue2"
}
}
```

3. Click "Test", and it will execute the test event. You should see the output in the console

🔵 "create" Operation TEST
1. Click the arrow on the "Test" button and click "Configure test events"

2. Paste the following JSON into the event. The field "operation" dictates what the lambda function will perform. In this case, it will create a new record into our DynamoDB table. Click "Create" to save.
```bash
{
"operation": "create",
"tableName": "apigateway-lambda-crud",
"payload": {
"Item": {
"id": "ABC",
"number": 5,
"name": "Bob",
"age": 42
}
}
}
```

3. Click "Test", and it will execute the test event. You should see the output in the console

🔵 "read" Operation TEST
1. Click the arrow on the "Test" button and click "Configure test events"
2. Paste the following JSON into the event. The field "operation" dictates what the lambda function will perform. In this case, it'd simply return the payload from input event as output. Click "Create" to save.
3. Click "Test", and it will execute the test event. You should see the output in the console.
```bash
{
"operation": "read",
"tableName": "apigateway-lambda-crud",
"payload": {
"Key":{"id":"ABC"}
}
}
```


Go back to your DynamoDB tables, click "Explore Items", if you check the `apigateway-lambda-crud` it will execute the test event successfully. You should see the output in the console.

## ➡️ Step 5 - Create API
To create the API
1. Go to API Gateway console
2. Scroll down to REST API and click "Build"

3. Make sure to select "New API" and Give the API name as `DynamoOperations`, keep everything as is, click "Create API"

4. Each API is collection of resources and methods that are integrated with backend HTTP endpoints, Lambda functions, or other AWS services. Typically, API resources are organized in a resource tree according to the application logic. At this time you only have the root resource, but let's add a resource next.
Click slash `/`, then click "Create Resource"

5. Input `DynamoOperations` in the Resource Name, Resource Path `/` will get populated. Click "Create Resource"

6. Let's create a `POST` Method for our API. With the `/DynamoOperations` resource selected, Click "Create Method".

7. Select `POST` from drop down,
The integration will come up automatically with "Lambda Function" option selected. Select `LambdaCRUDOverHTTPS` function that we created earlier. As you start typing the name, your function name will show up. Select and click "Save". Click "Create method"

Our API-Lambda integration is successfully created.
## ➡️ Step 6 - Deploy the API
In this step, you deploy the API that you created to a stage called Prod.
1. Click `POST`, select "Deploy API"

2. Now it is going to ask you about a stage. Select "[New Stage]" for "Deployment stage". Give `Prod` as "Stage name". Click "Deploy"

3. We're all set to run our solution! To invoke our API endpoint, we need the endpoint url. In the "Stages" screen, expand the stage "Prod", select "POST" method, and copy the "Invoke URL" from screen (we are going to need it in Step 7)

## ➡️ Step 7 - Running our solution
1. Go to Postman.com and go to your workspace. (If you've never used Postman then you will have to sign up, no worries it is free and you can use the browser interface)
2. Click the "New" button then select HTTP Request as shown in the screenshot below.

3. Switch `GET` to `POST`. Next, copy and paste the Invoke URL that we copied from our API Gateway in the previous step. Lastly, select "Body" then the `raw` option. All shown in the screenshot below.
4. The Lambda function supports using the create operation to create an item in your DynamoDB table. To request this operation, use the following JSON:
```bash
{
"operation": "create",
"tableName": "apigateway-lambda-crud",
"payload": {
"Item": {
"id": "ABCD",
"number": 879
}
}
}
```

5. Click "Send". API should execute and return "HTTPStatusCode" 200.

6. To validate that the item is indeed inserted into DynamoDB table, go to Dynamo console, select `apigateway-lambda-crud` table, select "Explore items" tab, and the newly inserted item should be displayed.

## 💰 Cost
All services used are eligible for the AWS Free Tier. However, charges will incur at some point so it's recommended that you shut down resources after completing this tutorial.