Skip to content

Commit a5509b7

Browse files
committed
first commit
0 parents  commit a5509b7

File tree

11 files changed

+322
-0
lines changed

11 files changed

+322
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.serverless/
2+
bin/
3+
vendor/
4+
Gopkg.lock
5+
lambda.zip

Gopkg.toml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Gopkg.toml example
2+
#
3+
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
4+
# for detailed Gopkg.toml documentation.
5+
#
6+
# required = ["github.com/user/thing/cmd/thing"]
7+
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
8+
#
9+
# [[constraint]]
10+
# name = "github.com/user/project"
11+
# version = "1.0.0"
12+
#
13+
# [[constraint]]
14+
# name = "github.com/user/project2"
15+
# branch = "dev"
16+
# source = "github.com/myfork/project2"
17+
#
18+
# [[override]]
19+
# name = "github.com/x/y"
20+
# version = "2.4.0"
21+
22+
23+
[[constraint]]
24+
name = "github.com/aws/aws-lambda-go"
25+
version = "1.x"
26+
27+
[[constraint]]
28+
name = "github.com/aws/aws-sdk-go"
29+
version = "1.15.46"

Makefile

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
.ONESHELL:
2+
.SHELL := /usr/bin/bash
3+
.PHONY: build clean deploy undeploy run deps
4+
5+
CURRENT_FOLDER := $(shell pwd)
6+
7+
EXECUTABLES = docker docker-machine serverless dep sam npm pip python zip
8+
K := $(foreach exec,$(EXECUTABLES),\
9+
$(if $(shell command -v $(exec) 2> /dev/null),,$(error "ERROR: $(exec) is missing)))
10+
11+
default: build
12+
13+
build:
14+
@dep ensure -v
15+
@env GOOS=linux GOARCH=amd64 go build -o bin/app app/*
16+
ifeq ($(OS),Windows_NT)
17+
@build-lambda-zip -o lambda.zip bin/app
18+
else
19+
@chmod +x bin/app
20+
@zip -jq lambda.zip bin/app
21+
endif
22+
23+
clean:
24+
@rm -rf ./bin ./vendor Gopkg.lock
25+
26+
deploy:
27+
@serverless deploy --verbose
28+
29+
undeploy:
30+
@serverless remove --verbose
31+
32+
run:
33+
ifeq ($(DOCKER_HOST),)
34+
$(error DOCKER_HOST is not set)
35+
endif
36+
@MSYS2_ARG_CONV_EXCL="*" sam local invoke app --event test/event.json --docker-volume-basedir "$(CURRENT_FOLDER)"
37+
38+
deps:
39+
@npm install -g serverless
40+
@pip install aws-sam-cli

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# AWS Lambda in Go
2+
3+
## What's inside
4+
5+
* Sample AWS Lambda function written in Golang with DynamoDB as a storage backend
6+
* AWS SNS Topic used as a trigger
7+
* Dependencies management with Dep
8+
* Serverless framework for infrastructure deployment
9+
* Operations with Makefile
10+
11+
## Dependencies
12+
13+
1. [serverless framework](https://serverless.com/)
14+
1. [AWS SAM](https://docs.aws.amazon.com/lambda/latest/dg/serverless_app.html)
15+
1. docker & docker-machine for AWS SAM
16+
17+
## Workflow
18+
19+
1. `make`
20+
1. `make run`
21+
1. `make deploy`
22+
1. `test.sh`
23+
1. `make undeploy`
24+
25+
## Windows notes
26+
27+
Additional dependency
28+
29+
```
30+
go.exe get -u github.com/aws/aws-lambda-go/cmd/build-lambda-zip
31+
```
32+
33+
Issue with AWS SAM and path detection in python
34+
35+
```
36+
https://github.com/awslabs/aws-sam-cli/issues/461#issuecomment-403231130
37+
```

app/db.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package main
2+
3+
import (
4+
"strconv"
5+
6+
"github.com/aws/aws-sdk-go/aws"
7+
"github.com/aws/aws-sdk-go/aws/session"
8+
"github.com/aws/aws-sdk-go/service/dynamodb"
9+
)
10+
11+
const tableName = "Items"
12+
13+
var db = dynamodb.New(session.New(), aws.NewConfig().WithRegion("eu-west-1"))
14+
15+
func (e *eventData) createOrUpdateDB() error {
16+
input := &dynamodb.PutItemInput{
17+
TableName: aws.String(tableName),
18+
Item: map[string]*dynamodb.AttributeValue{
19+
"id": {
20+
N: aws.String(strconv.Itoa(e.ID)),
21+
},
22+
"data": {
23+
S: aws.String(e.Data),
24+
},
25+
},
26+
}
27+
_, err := db.PutItem(input)
28+
return err
29+
}
30+
31+
func (e *eventData) deleteDB() error {
32+
input := &dynamodb.DeleteItemInput{
33+
TableName: aws.String(tableName),
34+
Key: map[string]*dynamodb.AttributeValue{
35+
"id": {
36+
N: aws.String(strconv.Itoa(e.ID)),
37+
},
38+
},
39+
}
40+
_, err := db.DeleteItem(input)
41+
return err
42+
}

app/main.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
7+
"github.com/aws/aws-lambda-go/events"
8+
"github.com/aws/aws-lambda-go/lambda"
9+
)
10+
11+
type eventData struct {
12+
Operation string `json:"operation"`
13+
ID int `json:"id"`
14+
Data string `json:"data"`
15+
}
16+
17+
func (e *eventData) sync() {
18+
switch e.Operation {
19+
case "CREATE":
20+
e.createOrUpdateDB()
21+
case "UPDATE":
22+
e.createOrUpdateDB()
23+
case "DELETE":
24+
e.deleteDB()
25+
default:
26+
fmt.Println("Unknown operation", e.Operation)
27+
}
28+
}
29+
30+
func handler(event events.SNSEvent) {
31+
eventJSON, err := json.Marshal(event)
32+
if err != nil {
33+
fmt.Println("Error during decoding event data")
34+
return
35+
}
36+
fmt.Println("SNS event:", string(eventJSON))
37+
38+
for _, record := range event.Records {
39+
msg := record.SNS.Message
40+
subj := record.SNS.Subject
41+
fmt.Println("Message", msg, "Subject", subj)
42+
e := &eventData{}
43+
json.Unmarshal([]byte(msg), e)
44+
e.sync()
45+
}
46+
}
47+
48+
func main() {
49+
lambda.Start(handler)
50+
}

serverless.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
service: app
2+
3+
frameworkVersion: ">=1.28.0 <2.0.0"
4+
5+
provider:
6+
name: aws
7+
runtime: go1.x
8+
stage: dev
9+
region: eu-west-1
10+
profile: ${self:custom.myProfile.${self:custom.myStage}}
11+
environment:
12+
DYNAMODB_TABLE: Items
13+
iamRoleStatements:
14+
- Effect: Allow
15+
Action:
16+
- dynamodb:Query
17+
- dynamodb:Scan
18+
- dynamodb:GetItem
19+
- dynamodb:PutItem
20+
- dynamodb:UpdateItem
21+
- dynamodb:DeleteItem
22+
Resource: { "Fn::Join" : ["", ["arn:aws:dynamodb:${opt:region, self:provider.region}:", { "Ref" : "AWS::AccountId" }, ":table/${self:provider.environment.DYNAMODB_TABLE}" ] ] }
23+
24+
package:
25+
individually: true
26+
27+
functions:
28+
hello:
29+
handler: app
30+
events:
31+
- sns: ${self:service}
32+
package:
33+
artifact: lambda.zip
34+
35+
custom:
36+
myStage: ${opt:stage, self:provider.stage}
37+
myProfile:
38+
dev: personal
39+
40+
resources:
41+
Resources:
42+
myDynamoDbTable:
43+
Type: 'AWS::DynamoDB::Table'
44+
DeletionPolicy: Retain
45+
Properties:
46+
AttributeDefinitions:
47+
- AttributeName: id
48+
AttributeType: 'N'
49+
KeySchema:
50+
- AttributeName: id
51+
KeyType: HASH
52+
ProvisionedThroughput:
53+
ReadCapacityUnits: 5
54+
WriteCapacityUnits: 5
55+
TableName: ${self:provider.environment.DYNAMODB_TABLE}

template.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Resources:
2+
app:
3+
Type: AWS::Serverless::Function
4+
Properties:
5+
Handler: bin/app
6+
Runtime: go1.x

test.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env bash
2+
3+
if [ "$#" -ne 1 ]; then
4+
echo "Input ARN of SNS topic as parameter"
5+
exit 1
6+
fi
7+
8+
export AWS_PROFILE="personal"
9+
10+
MSGS=0
11+
12+
while [ $MSGS -lt 5 ]; do
13+
aws sns publish --topic-arn "$1" --subject "TEST CREATE $MSGS" --message "{\"operation\":\"CREATE\",\"id\":${MSGS},\"data\":\"TEST CREATE ${MSGS}\"}"
14+
MSGS=$((MSGS+1))
15+
done
16+
17+
MSGS=0
18+
19+
while [ $MSGS -lt 5 ]; do
20+
aws sns publish --topic-arn "$1" --subject "TEST DELETE $MSGS" --message "{\"operation\":\"DELETE\",\"id\":${MSGS},\"data\":\"TEST DELETE ${MSGS}\"}"
21+
MSGS=$((MSGS+1))
22+
done

test/data.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"operation": "CREATE",
3+
"id": 1,
4+
"data": "TEST CREATE"
5+
}

test/event.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"Records": [
3+
{
4+
"EventVersion": "1.0",
5+
"EventSubscriptionArn": "arn:aws:sns:EXAMPLE",
6+
"EventSource": "aws:sns",
7+
"Sns": {
8+
"SignatureVersion": "1",
9+
"Timestamp": "1970-01-01T00:00:00.000Z",
10+
"Signature": "EXAMPLE",
11+
"SigningCertUrl": "EXAMPLE",
12+
"MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
13+
"Message": "{ \"operation\" : \"CREATE\", \"id\" : 1, \"data\" : \"Some awesome data\" }",
14+
"MessageAttributes": {
15+
"Test": {
16+
"Type": "String",
17+
"Value": "TestString"
18+
},
19+
"TestBinary": {
20+
"Type": "Binary",
21+
"Value": "TestBinary"
22+
}
23+
},
24+
"Type": "Notification",
25+
"UnsubscribeUrl": "EXAMPLE",
26+
"TopicArn": "arn:aws:sns:EXAMPLE",
27+
"Subject": "TestInvoke"
28+
}
29+
}
30+
]
31+
}

0 commit comments

Comments
 (0)