Skip to content

Commit

Permalink
feat(aws-lambda): set up components to test (#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
jordan-acosta authored Mar 19, 2024
1 parent ae0c230 commit 27425d1
Show file tree
Hide file tree
Showing 28 changed files with 651 additions and 0 deletions.
25 changes: 25 additions & 0 deletions aws-lambda-tutorial/components/api-gateway/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 46 additions & 0 deletions aws-lambda-tutorial/components/api-gateway/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
locals {
integrations = {
"GET /widgets/{id}" = {
lambda_arn = var.lambda_function_arn
payload_format_version = "2.0"
timeout_milliseconds = 12000
}

"POST /widgets" = {
lambda_arn = var.lambda_function_arn
payload_format_version = "2.0"
timeout_milliseconds = 12000
}

// "DELETE /widgets/{id}" = {
// lambda_arn = var.lambda_function_arn
// payload_format_version = "2.0"
// timeout_milliseconds = 12000
// }
}
}

module "api_gateway" {
source = "terraform-aws-modules/apigateway-v2/aws"

name = var.name
integrations = local.integrations
domain_name = var.domain_name
domain_name_certificate_arn = var.domain_name_certificate_arn
protocol_type = "HTTP"
create_default_stage_access_log_group = true

cors_configuration = {
allow_headers = ["content-type", "x-amz-date", "authorization", "x-api-key", "x-amz-security-token", "x-amz-user-agent"]
allow_methods = ["*"]
allow_origins = ["*"]
}
}

resource "aws_lambda_permission" "permission" {
function_name = element(split(":", var.lambda_function_arn), length(split(":", var.lambda_function_arn)) - 1)
statement_id = "AllowExecutionFromAPIGateway"
action = "lambda:InvokeFunction"
principal = "apigateway.amazonaws.com"
source_arn = "${module.api_gateway.apigatewayv2_api_execution_arn}/*/*"
}
15 changes: 15 additions & 0 deletions aws-lambda-tutorial/components/api-gateway/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
variable "name" {
type = string
}

variable "domain_name" {
type = string
}

variable "domain_name_certificate_arn" {
type = string
}

variable "lambda_function_arn" {
type = string
}
12 changes: 12 additions & 0 deletions aws-lambda-tutorial/components/api-gateway/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
terraform {
required_version = ">= 1.3.7"

backend "s3" {}

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.0"
}
}
}
11 changes: 11 additions & 0 deletions aws-lambda-tutorial/components/api/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM golang:1.22.1-alpine3.19 as build

WORKDIR /app
COPY ./ ./
RUN go mod download
COPY *.go ./
RUN CGO_ENABLED=0 GOOS=linux go build -o api

FROM alpine:3.19
COPY --from=build /app/api /main
ENTRYPOINT ["/main"]
10 changes: 10 additions & 0 deletions aws-lambda-tutorial/components/api/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module github.com/nuonco/guides/aws-lambda-tutorial/components/api

go 1.22.1

require (
github.com/aws/aws-lambda-go v1.46.0
github.com/aws/aws-sdk-go v1.51.2
)

require github.com/jmespath/go-jmespath v0.4.0 // indirect
21 changes: 21 additions & 0 deletions aws-lambda-tutorial/components/api/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
github.com/aws/aws-lambda-go v1.46.0 h1:UWVnvh2h2gecOlFhHQfIPQcD8pL/f7pVCutmFl+oXU8=
github.com/aws/aws-lambda-go v1.46.0/go.mod h1:dpMpZgvWx5vuQJfBt0zqBha60q7Dd7RfgJv23DymV8A=
github.com/aws/aws-sdk-go v1.51.2 h1:Ruwgz5aqIXin5Yfcgc+PCzoqW5tEGb9aDL/JWDsre7k=
github.com/aws/aws-sdk-go v1.51.2/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
13 changes: 13 additions & 0 deletions aws-lambda-tutorial/components/api/internal/dynamodb/db.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package dynamodb

import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/dynamodb"
)

const region = "us-east-1"

var db = dynamodb.New(session.New(), aws.NewConfig().WithRegion(region))

// var db = dynamodb.New(session.NewSession(), aws.NewConfig().WithRegion(region))
35 changes: 35 additions & 0 deletions aws-lambda-tutorial/components/api/internal/dynamodb/get_item.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package dynamodb

import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
"github.com/nuonco/guides/aws-lambda-tutorial/components/api/internal/widget"
)

func GetItem(id, table string) (*widget.Widget, error) {
input := &dynamodb.GetItemInput{
TableName: aws.String(table),
Key: map[string]*dynamodb.AttributeValue{
"ID": {
N: aws.String(id),
},
},
}

result, err := db.GetItem(input)
if err != nil {
return nil, err
}
if result.Item == nil {
return nil, nil
}

widget := new(widget.Widget)
err = dynamodbattribute.UnmarshalMap(result.Item, widget)
if err != nil {
return nil, err
}

return widget, nil
}
24 changes: 24 additions & 0 deletions aws-lambda-tutorial/components/api/internal/dynamodb/put_item.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package dynamodb

import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/dynamodb"
)

func PutItem(id, table string) error {
input := &dynamodb.PutItemInput{
TableName: aws.String(table),
Item: map[string]*dynamodb.AttributeValue{
"ID": {
N: aws.String(id),
},
},
}

_, err := db.PutItem(input)
if err != nil {
return err
}

return nil
}
8 changes: 8 additions & 0 deletions aws-lambda-tutorial/components/api/internal/logging/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package logging

import (
"log"
"os"
)

var DefaultLogger = log.New(os.Stdout, "", log.Llongfile)
5 changes: 5 additions & 0 deletions aws-lambda-tutorial/components/api/internal/widget/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package widget

type Widget struct {
ID string `json:"id"`
}
87 changes: 87 additions & 0 deletions aws-lambda-tutorial/components/api/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package main

import (
"encoding/json"
"fmt"
"net/http"
"strconv"

"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/nuonco/guides/aws-lambda-tutorial/components/api/internal/dynamodb"
"github.com/nuonco/guides/aws-lambda-tutorial/components/api/internal/logging"
"github.com/nuonco/guides/aws-lambda-tutorial/components/api/internal/widget"
)

var logger = logging.DefaultLogger

func response(statusCode int, body string, err error) (events.APIGatewayProxyResponse, error) {
if err != nil {
logger.Println(err.Error())
body = http.StatusText(statusCode)
}

return events.APIGatewayProxyResponse{
StatusCode: statusCode,
Body: body,
}, err
}

func get(event events.APIGatewayV2HTTPRequest) (events.APIGatewayProxyResponse, error) {
id := event.PathParameters["id"]
if _, err := strconv.Atoi(id); err != nil {
return response(http.StatusBadRequest, "", err)
}

widget, err := dynamodb.GetItem(id, "widgets")
if err != nil {
return response(http.StatusInternalServerError, "", err)
}
if widget == nil {
return response(http.StatusNotFound, "", err)
}

js, err := json.Marshal(widget)
if err != nil {
return response(http.StatusInternalServerError, "", err)
}

return response(http.StatusOK, string(js), nil)
}

func post(event events.APIGatewayV2HTTPRequest) (events.APIGatewayProxyResponse, error) {
w := widget.Widget{}
err := json.Unmarshal([]byte(event.Body), &w)
if err != nil {
return response(http.StatusUnprocessableEntity, "", err)
}

id := event.PathParameters["id"]
if _, err := strconv.Atoi(id); err != nil {
return response(http.StatusBadRequest, "", err)
}

err = dynamodb.PutItem(w.ID, "widgets")
if err != nil {
return response(http.StatusInternalServerError, "", err)
}

return response(http.StatusOK, "", nil)
}

func router(event events.APIGatewayV2HTTPRequest) (events.APIGatewayProxyResponse, error) {
logger.Printf("event: %+v", event)
method := event.RequestContext.HTTP.Method
switch method {
case "GET":
return get(event)
case "POST":
return post(event)
default:
return response(http.StatusMethodNotAllowed, "", fmt.Errorf("method %s not allowed", method))
}
}

func main() {
lambda.Start(router)
}
25 changes: 25 additions & 0 deletions aws-lambda-tutorial/components/certificate/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions aws-lambda-tutorial/components/certificate/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module "certificate" {
source = "terraform-aws-modules/acm/aws"
version = "~> 4.0"

domain_name = var.domain_name
zone_id = var.zone_id
validation_method = "DNS"
wait_for_validation = false
}
3 changes: 3 additions & 0 deletions aws-lambda-tutorial/components/certificate/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "public_domain_certificate_arn" {
value = module.certificate.acm_certificate_arn
}
7 changes: 7 additions & 0 deletions aws-lambda-tutorial/components/certificate/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
variable "domain_name" {
type = string
}

variable "zone_id" {
type = string
}
25 changes: 25 additions & 0 deletions aws-lambda-tutorial/components/dynamodb-table/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 27425d1

Please sign in to comment.