diff --git a/.gitignore b/.gitignore index 3ad564a..14d0040 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .idea/ handler.so handler.zip +.env \ No newline at end of file diff --git a/Makefile b/Makefile deleted file mode 100644 index d782b46..0000000 --- a/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -IMAGE_LAMBDA_GO=eawsy/aws-lambda-go-shim -# we can't use .serverless folder because it gets wiped by sls deploy -OUTPUT_DIR=bin - -# serverless.yml env vars -ENV ?= dev -AWS_DEFAULT_REGION ?= ap-southeast-2 -AWS_PROFILE ?= default - -all: clean dist deploy invoke -.PHONY: all - -deps: - go get -u -d github.com/eawsy/aws-lambda-go-core/... - docker pull eawsy/aws-lambda-go-shim -.PHONY: deps - -clean: - make -f Makefile.shim clean -.PHONY: clean - -dist: - make -f Makefile.shim docker - -# serverless targets -deploy: - AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} ENV=${ENV} sls deploy -.PHONY: deploy - -invoke: - curl -v $(shell AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} ENV=${ENV} sls info | grep GET | cut -f5 -d" ") -.PHONY: invoke - -delete: - AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} ENV=${ENV} sls remove -v -.PHONY: delete diff --git a/Makefile.shim b/Makefile.shim deleted file mode 100644 index ab6830e..0000000 --- a/Makefile.shim +++ /dev/null @@ -1,62 +0,0 @@ -# -# This is free and unencumbered software released into the public domain. -# -# Anyone is free to copy, modify, publish, use, compile, sell, or -# distribute this software, either in source code form or as a compiled -# binary, for any purpose, commercial or non-commercial, and by any -# means. -# -# In jurisdictions that recognize copyright laws, the author or authors -# of this software dedicate any and all copyright interest in the -# software to the public domain. We make this dedication for the benefit -# of the public at large and to the detriment of our heirs and -# successors. We intend this dedication to be an overt act of -# relinquishment in perpetuity of all present and future rights to this -# software under copyright law. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. -# -# For more information, please refer to -# - -SHELL := /bin/bash - -HANDLER ?= handler -PACKAGE ?= $(HANDLER) -GOPATH ?= $(HOME)/go - -WORKDIR = $(CURDIR:$(GOPATH)%=/go%) -ifeq ($(WORKDIR),$(CURDIR)) - WORKDIR = /tmp -endif - -docker: - docker run --rm \ - -e HANDLER=$(HANDLER) \ - -e PACKAGE=$(PACKAGE) \ - -v $(GOPATH):/go \ - -v $(CURDIR):/tmp \ - -w $(WORKDIR) \ - eawsy/aws-lambda-go-shim:latest make -f Makefile.shim all - -all: build pack perm - -build: - @go build -buildmode=plugin -ldflags='-w -s' -o $(HANDLER).so - -pack: - @pack $(HANDLER) $(HANDLER).so $(PACKAGE).zip - -perm: - @chown $(shell stat -c '%u:%g' .) $(HANDLER).so $(PACKAGE).zip - -clean: - @rm -rf $(HANDLER) $(HANDLER).so $(PACKAGE).zip - -.PHONY: docker all build pack perm clean diff --git a/README.md b/README.md index 38e67c7..2e97f70 100644 --- a/README.md +++ b/README.md @@ -48,11 +48,17 @@ strategic Microservices. Serving 1M+ customers with up to 500CCU. ## Usage -Clone locally into your own Serverless project: +Install locally into your own Serverless project. For a generic event driven service, use: serverless install \ - -u https://github.com/yunspace/serverless-golang \ - -n my-golang-project + -u https://github.com/yunspace/serverless-golang/aws/event \ + -n my-golang-event-project + +For a `go/net` driven project, use: + + serverless install \ + -u https://github.com/yunspace/serverless-golang/net/event \ + -n my-golang-net-project Prior to running, you should have `go`, `make` and `docker` installed. Then once in your project directory run this to get all the build dependencies: @@ -65,9 +71,9 @@ used for authentication on AWS. Then deploy the function by running this command: - make + make clean dockerDist deploy To uninstall and clean up everything you just need to run: - make clean delete + make clean remove diff --git a/aws/event/.gitignore b/aws/event/.gitignore new file mode 100644 index 0000000..3678432 --- /dev/null +++ b/aws/event/.gitignore @@ -0,0 +1,3 @@ +.serverless +handler.so +handler.zip diff --git a/aws/event/Makefile b/aws/event/Makefile new file mode 100644 index 0000000..7df4eaa --- /dev/null +++ b/aws/event/Makefile @@ -0,0 +1,60 @@ +IMAGE_LAMBDA_GO=eawsy/aws-lambda-go-shim:latest + +# serverless.yml env vars +ENV ?= dev +AWS_DEFAULT_REGION ?= ap-southeast-2 +AWS_PROFILE ?= default + +HANDLER ?= handler +PACKAGE ?= $(HANDLER) +GOPATH ?= $(HOME)/go + +all: clean dist deploy +.PHONY: all + +# lambda shim targets +clean: + @rm -rf $(HANDLER) $(HANDLER).so $(PACKAGE).zip +.PHONY: clean + +deps: + @go get -u -d github.com/eawsy/aws-lambda-go-core/... + @docker pull $(IMAGE_LAMBDA_GO) +.PHONY: deps + +dist: build pack + +build: + @go build -buildmode=plugin -ldflags='-w -s' -o $(HANDLER).so + +pack: + @pack $(HANDLER) $(HANDLER).so $(PACKAGE).zip + @chown $(shell stat -c '%u:%g' .) $(HANDLER).so $(PACKAGE).zip + +# serverless targets +deploy: + AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} ENV=${ENV} sls deploy +.PHONY: deploy + +remove: + AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} ENV=${ENV} sls remove -v +.PHONY: delete + +# dockerised target +dockerDist: + $(call docker, make dist) +.PHONY: dockerAll + +dockerShell: + $(call docker, bash) +.PHONY: dockerShell + +define docker + docker run --rm -ti \ + -e HANDLER=$(HANDLER) \ + -e PACKAGE=$(PACKAGE) \ + -v $(GOPATH):/go \ + -v $(CURDIR):/tmp \ + -w /tmp \ + $(IMAGE_LAMBDA_GO) $1 +endef \ No newline at end of file diff --git a/aws/event/event_handler.go b/aws/event/event_handler.go new file mode 100644 index 0000000..ea0a9ee --- /dev/null +++ b/aws/event/event_handler.go @@ -0,0 +1,19 @@ +package main + +import ( + "github.com/eawsy/aws-lambda-go-core/service/lambda/runtime" + "github.com/eawsy/aws-lambda-go-event/service/lambda/runtime/event/apigatewayproxyevt" + "log" +) + +func handlAPIEvent(evt *apigatewayproxyevt.Event, ctx *runtime.Context) (*Response, error) { + log.Println(evt) + response := &Response{ + StatusCode: 200, + Headers: make(map[string]string), + } + response.SetBody(&APIBody{"Hello, serverless-golang!", evt.Body}) + response.Headers["X-Powered-By"] = "serverless-golang" + + return response, nil +} diff --git a/aws/event/event_handler_test.go b/aws/event/event_handler_test.go new file mode 100644 index 0000000..e24290e --- /dev/null +++ b/aws/event/event_handler_test.go @@ -0,0 +1,28 @@ +package main + +import ( + "testing" + "github.com/eawsy/aws-lambda-go-event/service/lambda/runtime/event/apigatewayproxyevt" + "github.com/eawsy/aws-lambda-go-core/service/lambda/runtime" + "github.com/stretchr/testify/assert" +) + +func TestCustomHeader(t *testing.T) { + // when + r, err := handlAPIEvent(&apigatewayproxyevt.Event{}, &runtime.Context{}) + + // then + assert.NoError(t, err) + assert.Equal(t, "serverless-golang", r.Headers["X-Powered-By"]) +} + +func TestAPIBody(t *testing.T) { + // when + r, err := handlAPIEvent(&apigatewayproxyevt.Event{Body: "GET"}, &runtime.Context{}) + + // then + assert.NoError(t, err) + assert.IsType(t, &Response{}, r) + //response, _ := r.(*Response) + assert.Equal(t, "{\"message\":\"Hello, serverless-golang!\",\"input\":\"GET\"}", r.Body) +} diff --git a/aws/event/handler.go b/aws/event/handler.go new file mode 100644 index 0000000..5ce7049 --- /dev/null +++ b/aws/event/handler.go @@ -0,0 +1,10 @@ +package main + +import ( + "github.com/eawsy/aws-lambda-go-event/service/lambda/runtime/event/apigatewayproxyevt" + "github.com/eawsy/aws-lambda-go-core/service/lambda/runtime" +) + +func EventHandle(evt *apigatewayproxyevt.Event, ctx *runtime.Context) (interface{}, error) { + return handlAPIEvent(evt, ctx) +} diff --git a/aws/event/models.go b/aws/event/models.go new file mode 100644 index 0000000..1b0cdbc --- /dev/null +++ b/aws/event/models.go @@ -0,0 +1,21 @@ +package main + +import "encoding/json" + +// special format need by API Gateway response body +type APIBody struct { + Message string `json:"message"` + Input string `json:"input"` +} + +type Response struct { + StatusCode int `json:"statusCode"` + Headers map[string]string `json:"headers"` + Body string `json:"body"` +} + +// inspired by serverless-java +func (r *Response) SetBody(b *APIBody) { + bytes, _ := json.Marshal(b) + r.Body = string(bytes) +} \ No newline at end of file diff --git a/aws/event/serverless.yml b/aws/event/serverless.yml new file mode 100644 index 0000000..4b2fae1 --- /dev/null +++ b/aws/event/serverless.yml @@ -0,0 +1,14 @@ +service: serverless-golang-event +package: + artifact: handler.zip +provider: + name: aws + runtime: python2.7 + stage: ${env:ENV} + region: ${env:AWS_DEFAULT_REGION} + profile: ${env:AWS_PROFILE} +functions: + hello-event: + handler: handler.EventHandle + events: + - http: GET hello-event \ No newline at end of file diff --git a/aws/net/.gitignore b/aws/net/.gitignore new file mode 100644 index 0000000..3678432 --- /dev/null +++ b/aws/net/.gitignore @@ -0,0 +1,3 @@ +.serverless +handler.so +handler.zip diff --git a/aws/net/Makefile b/aws/net/Makefile new file mode 100644 index 0000000..7df4eaa --- /dev/null +++ b/aws/net/Makefile @@ -0,0 +1,60 @@ +IMAGE_LAMBDA_GO=eawsy/aws-lambda-go-shim:latest + +# serverless.yml env vars +ENV ?= dev +AWS_DEFAULT_REGION ?= ap-southeast-2 +AWS_PROFILE ?= default + +HANDLER ?= handler +PACKAGE ?= $(HANDLER) +GOPATH ?= $(HOME)/go + +all: clean dist deploy +.PHONY: all + +# lambda shim targets +clean: + @rm -rf $(HANDLER) $(HANDLER).so $(PACKAGE).zip +.PHONY: clean + +deps: + @go get -u -d github.com/eawsy/aws-lambda-go-core/... + @docker pull $(IMAGE_LAMBDA_GO) +.PHONY: deps + +dist: build pack + +build: + @go build -buildmode=plugin -ldflags='-w -s' -o $(HANDLER).so + +pack: + @pack $(HANDLER) $(HANDLER).so $(PACKAGE).zip + @chown $(shell stat -c '%u:%g' .) $(HANDLER).so $(PACKAGE).zip + +# serverless targets +deploy: + AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} ENV=${ENV} sls deploy +.PHONY: deploy + +remove: + AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} ENV=${ENV} sls remove -v +.PHONY: delete + +# dockerised target +dockerDist: + $(call docker, make dist) +.PHONY: dockerAll + +dockerShell: + $(call docker, bash) +.PHONY: dockerShell + +define docker + docker run --rm -ti \ + -e HANDLER=$(HANDLER) \ + -e PACKAGE=$(PACKAGE) \ + -v $(GOPATH):/go \ + -v $(CURDIR):/tmp \ + -w /tmp \ + $(IMAGE_LAMBDA_GO) $1 +endef \ No newline at end of file diff --git a/aws/net/handler.go b/aws/net/handler.go new file mode 100644 index 0000000..f2588c7 --- /dev/null +++ b/aws/net/handler.go @@ -0,0 +1,12 @@ +package main + +import ( + "github.com/eawsy/aws-lambda-go-net/service/lambda/runtime/net/apigatewayproxy" +) + +// Handle is the exported handler called by AWS Lambda. +var NetHandle apigatewayproxy.Handler + +func init() { + NetHandle = NewNetHandler() +} diff --git a/handler.go b/aws/net/net_handler.go similarity index 67% rename from handler.go rename to aws/net/net_handler.go index 61e9d68..ec10475 100644 --- a/handler.go +++ b/aws/net/net_handler.go @@ -2,26 +2,24 @@ package main import ( "net/http" - - "github.com/eawsy/aws-lambda-go-net/service/lambda/runtime/net" "github.com/eawsy/aws-lambda-go-net/service/lambda/runtime/net/apigatewayproxy" + "github.com/eawsy/aws-lambda-go-net/service/lambda/runtime/net" ) -// Handle is the exported handler called by AWS Lambda. -var Handle apigatewayproxy.Handler - -func init() { +func NewNetHandler() apigatewayproxy.Handler { ln := net.Listen() // Amazon API Gateway Binary support out of the box. - Handle = apigatewayproxy.New(ln, nil).Handle + handle := apigatewayproxy.New(ln, nil).Handle // Any Go framework complying with the Go http.Handler interface can be used. // This includes, but is not limited to, Vanilla Go, Gin, Echo, Gorrila, Goa, etc. - go http.Serve(ln, http.HandlerFunc(handle)) + go http.Serve(ln, http.HandlerFunc(hello)) + + return handle } -func handle(w http.ResponseWriter, r *http.Request) { +func hello(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-Powered-By", "serverless-golang") w.Write([]byte("Hello, serverless-golang!")) -} +} \ No newline at end of file diff --git a/aws/net/net_handler_test.go b/aws/net/net_handler_test.go new file mode 100644 index 0000000..0a01373 --- /dev/null +++ b/aws/net/net_handler_test.go @@ -0,0 +1,7 @@ +package main + +import "testing" + +func TestCustomHeader(t *testing.T) { + +} \ No newline at end of file diff --git a/serverless.yml b/aws/net/serverless.yml similarity index 64% rename from serverless.yml rename to aws/net/serverless.yml index 6163df8..c647696 100644 --- a/serverless.yml +++ b/aws/net/serverless.yml @@ -1,4 +1,4 @@ -service: serverless-golang +service: serverless-golang-net package: artifact: handler.zip provider: @@ -8,7 +8,7 @@ provider: region: ${env:AWS_DEFAULT_REGION} profile: ${env:AWS_PROFILE} functions: - hello: - handler: handler.Handle + hello-net: + handler: handler.NetHandle events: - - http: GET hello \ No newline at end of file + - http: GET hello-net \ No newline at end of file