05_aws_complete_serverless_stack

module
v0.0.0-...-f3f54b2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 12, 2024 License: MIT

README

AWS Complete Serverless Stack

This is a simple demonstration of how to create a serverless application using AWS: API Gateway, DynamoDB, and Lambda.

Features

This application has the following features.

Functional:

  • store, retrieve, update, and delete users' data in a DynamoDB table,
  • expose the CRUD operations on users' data through an API Gateway and Lambda.

Non-functional:

  • use AWS cloud or LocalStack to run the application,
  • use the AWS SDK for Go and AWS Lambda for Go to interact with the AWS services.

Technologies

The application is built using the following technologies, libraries, frameworks, and tools:

Setup

To run this application, you need to have the following installed on your system:

Of course, you also need an AWS account or a LocalStack instance running (requires Docker).

To install LocalStack, you can run the following command:

pip install localstack

To start LocalStack, you can run the following command:

localstack start -d

Alternatively, you can use the docker-compose file provided in this repository:

docker-compose up -d

If you want to use the AWS CLI with LocalStack, please follow this guide.

For LocalStack, you need to add to every command the --endpoint-url=http://localhost:4566 flag (or define an alias awslocal for the AWS CLI with the same flag).

I've tested everything under LocalStack, and if you want to deploy this application to real AWS, you need to modify main.go and replace the existing code for the DynamoDB client with the following code:

awsSession, err := session.NewSession(&aws.Config{
  Region:      aws.String(region),
})

First, you need to create a role for your lambda function. You can do this by running the following command:

aws iam create-role --role-name lambda-ex --assume-role-policy-document file://trust-policy.json

Then you need to attach the AWSLambdaBasicExecutionRole policy to the role:

aws iam attach-role-policy --role-name lambda-ex --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

To allow access to the DynamoDB table, you need to attach the AmazonDynamoDBFullAccess policy to the role (you can also create a custom policy with the required permissions):

aws iam attach-role-policy --role-name lambda-ex --policy-arn arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess

Now you can build the application:

GOOS=linux GOARCH=amd64 go build -o ./build ./cmd/api/main.go

Then you can create a zip file with the application:

zip -jrm ./build/main.zip ./build/main

Now you can deploy the application to AWS or LocalStack:

aws lambda create-function --function-name aws-complete-serverless-stack --runtime go1.x --role arn:aws:iam::PUT_YOUR_ID_HERE:role/lambda-ex --handler main --zip-file fileb://./build/main.zip --timeout 900

Now, you need to create a DynamoDB table:

aws dynamodb create-table \
    --table-name aws-complete-serverless-stack-users \
    --attribute-definitions AttributeName=email,AttributeType=S \
    --key-schema AttributeName=email,KeyType=HASH \
    --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5

You can also add some data to the table:

aws dynamodb put-item --table-name aws-complete-serverless-stack-users --item '{"email": {"S": "jdoe@unknown.com"}}'
aws dynamodb put-item --table-name aws-complete-serverless-stack-users --item '{"email": {"S": "asmith@unknown.com"}}'

To retrieve the data from the table, you can run the following command:

aws dynamodb scan --table-name aws-complete-serverless-stack-users

You can invoke the lambda function using GET:

aws lambda invoke --function-name aws-complete-serverless-stack --cli-binary-format raw-in-base64-out --payload file://get-request.json response.json

Where get-request.json is:

{
  "httpMethod": "GET",
  "path": "/users",
  "queryStringParameters": {
    "email": "jdoe@unknown.com"
  }
}

Alternatively, you can use the following command:

aws lambda invoke --function-name aws-complete-serverless-stack --payload "{\"httpMethod\": \"GET\", \"path\": \"/users\", \"queryStringParameters\": {}}" --endpoint-url=http://localhost:4566 response.json

You can also invoke the lambda function using POST:

aws lambda invoke --function-name aws-complete-serverless-stack --cli-binary-format raw-in-base64-out --payload file://post-request.json response.json

Where post-request.json is:

{
  "httpMethod": "POST",
  "path": "/users",
  "body": "{\"email\": \"asmith@unknown.com\"}"
}

To see logs from the lambda function, you can run the following command:

aws logs tail /aws/lambda/aws-complete-serverless-stack --follow

And finally, you can create the API Gateway, to simplify that part I've create a script that you can run (adjust it to your needs):

./setup_api_gateway.sh

Great explanation of what this script is doing can be found here.

If that succeeded, you can list all the APIs:

aws apigateway get-rest-apis

to remove the API Gateway:

aws apigateway delete-rest-api --rest-api-id <rest-api-id>

You can retrieve endpoint URL:

region=$(aws configure get region)
endpoint_url=http://localhost:4566
echo "https://$(aws apigateway get-rest-apis --query 'items[0].id' --output text --region $region --endpoint-url=$endpoint_url).execute-api.$region.amazonaws.com/prod"

Now you can test the API Gateway (LocalStack):

rest_api_id=$(aws apigateway get-rest-apis --query 'items[0].id' --output text --region $region --endpoint-url=$endpoint_url)
stage_name=prod
curl -X GET -H "Content-Type: application/json" http://localhost:4566/restapis/$rest_api_id/$stage_name/_user_request_/

If it works, you should see something like this:

[
  { "firstName": "", "lastName": "", "email": "jdoe@unknown.com" },
  { "firstName": "", "lastName": "", "email": "asmith@unknown.com" }
]

And it means that you have successfully deployed the complete serverless stack application using AWS :-).

Directories

Path Synopsis
cmd
api
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL