diff --git a/README.md b/README.md index e6ff0f7fa4e..044fb4b6c81 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ The following are services you can instantly install and use by running `serverl ## Features -* Supports Node.js, Python, Java, Scala, C#, F#, Groovy, Kotlin, PHP & Swift. +* Supports Node.js, Python, Java, Scala, C#, F#, Go, Groovy, Kotlin, PHP & Swift. * Manages the lifecycle of your serverless architecture (build, deploy, update, delete). * Safely deploy functions, events and their required resources together via provider resource managers (e.g., AWS CloudFormation). * Functions can be grouped ("serverless services") for easy management of code, resources & processes, across large projects & teams. diff --git a/docker-compose.yml b/docker-compose.yml index f9ae71b3ed3..98c398c8f73 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -63,6 +63,16 @@ services: image: microsoft/dotnet:1.0.4-sdk volumes: - ./tmp/serverless-integration-test-aws-fsharp:/app + aws-go: + image: golang:1.9 + volumes: + - ./tmp/serverless-integration-test-aws-go:/app + - ./tmp/serverless-integration-test-aws-go:/go/src/app + aws-go-dep: + image: yunspace/golang:1.9 + volumes: + - ./tmp/serverless-integration-test-aws-go-dep:/app + - ./tmp/serverless-integration-test-aws-go-dep:/go/src/app aws-nodejs-typescript: image: node:6.10.3 volumes: diff --git a/docs/providers/aws/examples/hello-world/README.md b/docs/providers/aws/examples/hello-world/README.md index d1f1d070a4c..378b0567756 100644 --- a/docs/providers/aws/examples/hello-world/README.md +++ b/docs/providers/aws/examples/hello-world/README.md @@ -17,6 +17,8 @@ Pick your language of choice: * [JavaScript](./node) * [Python](./python) -* [csharp](./csharp) +* [C#](./csharp) +* [F#](./fsharp) +* [Go](./go) [View all examples](https://www.serverless.com/framework/docs/providers/aws/examples/) diff --git a/docs/providers/aws/examples/hello-world/go/README.md b/docs/providers/aws/examples/hello-world/go/README.md new file mode 100644 index 00000000000..8c522ccaecd --- /dev/null +++ b/docs/providers/aws/examples/hello-world/go/README.md @@ -0,0 +1,72 @@ + + + +### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/aws/examples/hello-world/go/) + + +# Hello World Go Example + +Make sure `serverless` is installed. [See installation guide](../../../guide/installation.md). + +You should also have [go](https://golang.org/doc/install) and [make](https://www.gnu.org/software/make/) + +It is always good practice to organise your `go` projects within [GOPATH](https://golang.org/doc/code.html#GOPATH), to maximise the benefits of go tooling. + +## 1. Create a service +There are two templates for `go`: + +1. [aws-go](https://github.com/serverless/serverless/tree/master/lib/plugins/create/templates/aws-go) - `serverless create --template aws-go --path myService` +2. [aws-go-dep](https://github.com/serverless/serverless/tree/master/lib/plugins/create/templates/aws-go-dep) - `serverless create --template aws-go-dep --path myService` + +where: +- 'aws-go' fetches dependencies using standard `go get`. +- 'aws-go-dep' uses [go dep](https://github.com/golang/dep) and requires your project to be in `$GOPATH/src` +- 'myService' is a new folder to be created with template service files. + +Change directories into 'myService' folder and you can see this project has 2 handler functions: `hello` and `world` split into 2 separate go packages (folders): + +``` +. +├── hello/ +│ └── main.go +├── world/ +│ └── main.go +``` + +This because a `main()` function is required as entry point for each handler executable. + +## 2. Build using go build to create static binaries + +Run `make build` to build both functions. Successful build should generate the following binaries: + +``` +. +├── bin/ +│ |── hello +│ └── world +``` + +## 3. Deploy +`serverless deploy` or `sls deploy`. `sls` is shorthand for the Serverless CLI command + +## 4. Invoke deployed function +Invoking the both functions should return a successful results: + +```bash +serverless invoke -f hello +{ + "message": "Go Serverless v1.0! Your function executed successfully!" +} + +serverless invoke --f world +{ + "message": "Okay so your other function also executed successfully!" +} +``` + +Congrats you have just deployed and run your Hello World function! diff --git a/docs/providers/aws/guide/services.md b/docs/providers/aws/guide/services.md index 20a27a0270d..24d33dab159 100644 --- a/docs/providers/aws/guide/services.md +++ b/docs/providers/aws/guide/services.md @@ -63,6 +63,7 @@ Here are the available runtimes for AWS Lambda: * aws-scala-sbt * aws-csharp * aws-fsharp +* aws-go Check out the [create command docs](../cli-reference/create) for all the details and options. diff --git a/lib/plugins/create/create.js b/lib/plugins/create/create.js index 8027ba9fb97..84368002a70 100644 --- a/lib/plugins/create/create.js +++ b/lib/plugins/create/create.js @@ -28,6 +28,8 @@ const validTemplates = [ 'aws-scala-sbt', 'aws-csharp', 'aws-fsharp', + 'aws-go', + 'aws-go-dep', 'azure-nodejs', 'google-nodejs', 'kubeless-python', diff --git a/lib/plugins/create/create.test.js b/lib/plugins/create/create.test.js index 3bba193faa0..c0bf9d726da 100644 --- a/lib/plugins/create/create.test.js +++ b/lib/plugins/create/create.test.js @@ -726,5 +726,39 @@ describe('Create', () => { expect((/service: my-awesome-service/).test(serverlessYmlfileContent)).to.equal(true); }); }); + + it('should generate scaffolding for "aws-go" template', () => { + process.chdir(tmpDir); + create.options.template = 'aws-go'; + + return create.create().then(() => { + const dirContent = walkDirSync(tmpDir) + .map(elem => elem.replace(path.join(tmpDir, path.sep), '')); + + expect(dirContent).to.include('serverless.yml'); + expect(dirContent).to.include(path.join('hello', 'main.go')); + expect(dirContent).to.include(path.join('world', 'main.go')); + expect(dirContent).to.include('Makefile'); + expect(dirContent).to.include('.gitignore'); + }); + }); + + it('should generate scaffolding for "aws-go-dep" template', () => { + process.chdir(tmpDir); + create.options.template = 'aws-go-dep'; + + return create.create().then(() => { + const dirContent = walkDirSync(tmpDir) + .map(elem => elem.replace(path.join(tmpDir, path.sep), '')); + + expect(dirContent).to.include('serverless.yml'); + expect(dirContent).to.include(path.join('hello', 'main.go')); + expect(dirContent).to.include(path.join('world', 'main.go')); + expect(dirContent).to.include('Gopkg.toml'); + expect(dirContent).to.include('Gopkg.lock'); + expect(dirContent).to.include('Makefile'); + expect(dirContent).to.include('.gitignore'); + }); + }); }); }); diff --git a/lib/plugins/create/templates/aws-go-dep/Gopkg.lock b/lib/plugins/create/templates/aws-go-dep/Gopkg.lock new file mode 100644 index 00000000000..f93855f76bc --- /dev/null +++ b/lib/plugins/create/templates/aws-go-dep/Gopkg.lock @@ -0,0 +1,19 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/aws/aws-lambda-go" + packages = [ + "lambda", + "lambda/messages", + "lambdacontext" + ] + revision = "6e2e37798efbb1dfd8e9c6681702e683a6046517" + version = "v1.0.1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "85fa166cc59d0fa113a1517ffbb5dee0f1fa4a6795239936afb18c64364af759" + solver-name = "gps-cdcl" + solver-version = 1 \ No newline at end of file diff --git a/lib/plugins/create/templates/aws-go-dep/Gopkg.toml b/lib/plugins/create/templates/aws-go-dep/Gopkg.toml new file mode 100644 index 00000000000..8fce8929ead --- /dev/null +++ b/lib/plugins/create/templates/aws-go-dep/Gopkg.toml @@ -0,0 +1,25 @@ +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + + +[[constraint]] + name = "github.com/aws/aws-lambda-go" + version = "^1.0.1" diff --git a/lib/plugins/create/templates/aws-go-dep/Makefile b/lib/plugins/create/templates/aws-go-dep/Makefile new file mode 100644 index 00000000000..46a24c449e1 --- /dev/null +++ b/lib/plugins/create/templates/aws-go-dep/Makefile @@ -0,0 +1,4 @@ +build: + dep ensure + env GOOS=linux go build -ldflags="-s -w" -o bin/hello hello/main.go + env GOOS=linux go build -ldflags="-s -w" -o bin/world world/main.go \ No newline at end of file diff --git a/lib/plugins/create/templates/aws-go-dep/gitignore b/lib/plugins/create/templates/aws-go-dep/gitignore new file mode 100644 index 00000000000..99a966a94de --- /dev/null +++ b/lib/plugins/create/templates/aws-go-dep/gitignore @@ -0,0 +1,8 @@ +# Serverless directories +.serverless + +# golang output binary directory +bin + +# golang vendor (dependencies) directory +vendor \ No newline at end of file diff --git a/lib/plugins/create/templates/aws-go-dep/hello/main.go b/lib/plugins/create/templates/aws-go-dep/hello/main.go new file mode 100644 index 00000000000..e75c5af0407 --- /dev/null +++ b/lib/plugins/create/templates/aws-go-dep/hello/main.go @@ -0,0 +1,19 @@ +package main + +import ( + "github.com/aws/aws-lambda-go/lambda" +) + +type Response struct { + Message string `json:"message"` +} + +func Handler() (Response, error) { + return Response{ + Message: "Go Serverless v1.0! Your function executed successfully!", + }, nil +} + +func main() { + lambda.Start(Handler) +} diff --git a/lib/plugins/create/templates/aws-go-dep/serverless.yml b/lib/plugins/create/templates/aws-go-dep/serverless.yml new file mode 100644 index 00000000000..67f92c77f2e --- /dev/null +++ b/lib/plugins/create/templates/aws-go-dep/serverless.yml @@ -0,0 +1,104 @@ +# Welcome to Serverless! +# +# This file is the main config file for your service. +# It's very minimal at this point and uses default values. +# You can always add more config options for more control. +# We've included some commented out config examples here. +# Just uncomment any of them to get that config option. +# +# For full config options, check the docs: +# docs.serverless.com +# +# Happy Coding! + +service: aws-go-dep # NOTE: update this with your service name + +# You can pin your service to only deploy with a specific Serverless version +# Check out our docs for more details +# frameworkVersion: "=X.X.X" + +provider: + name: aws + runtime: go1.x + +# you can overwrite defaults here +# stage: dev +# region: us-east-1 + +# you can add statements to the Lambda function's IAM Role here +# iamRoleStatements: +# - Effect: "Allow" +# Action: +# - "s3:ListBucket" +# Resource: { "Fn::Join" : ["", ["arn:aws:s3:::", { "Ref" : "ServerlessDeploymentBucket" } ] ] } +# - Effect: "Allow" +# Action: +# - "s3:PutObject" +# Resource: +# Fn::Join: +# - "" +# - - "arn:aws:s3:::" +# - "Ref" : "ServerlessDeploymentBucket" +# - "/*" + +# you can define service wide environment variables here +# environment: +# variable1: value1 + +package: + exclude: + - ./** + include: + - ./bin/** + +functions: + hello: + handler: bin/hello + world: + handler: bin/world + +# The following are a few example events you can configure +# NOTE: Please make sure to change your handler code to work with those events +# Check the event documentation for details +# events: +# events: +# - http: +# path: users/create +# method: get +# - s3: ${env:BUCKET} +# - schedule: rate(10 minutes) +# - sns: greeter-topic +# - stream: arn:aws:dynamodb:region:XXXXXX:table/foo/stream/1970-01-01T00:00:00.000 +# - alexaSkill +# - alexaSmartHome: amzn1.ask.skill.xx-xx-xx-xx +# - iot: +# sql: "SELECT * FROM 'some_topic'" +# - cloudwatchEvent: +# event: +# source: +# - "aws.ec2" +# detail-type: +# - "EC2 Instance State-change Notification" +# detail: +# state: +# - pending +# - cloudwatchLog: '/aws/lambda/hello' +# - cognitoUserPool: +# pool: MyUserPool +# trigger: PreSignUp + +# Define function environment variables here +# environment: +# variable2: value2 + +# you can add CloudFormation resource templates here +#resources: +# Resources: +# NewResource: +# Type: AWS::S3::Bucket +# Properties: +# BucketName: my-new-bucket +# Outputs: +# NewOutput: +# Description: "Description for the output" +# Value: "Some output value" diff --git a/lib/plugins/create/templates/aws-go-dep/world/main.go b/lib/plugins/create/templates/aws-go-dep/world/main.go new file mode 100644 index 00000000000..bf46aa6fbcb --- /dev/null +++ b/lib/plugins/create/templates/aws-go-dep/world/main.go @@ -0,0 +1,19 @@ +package main + +import ( + "github.com/aws/aws-lambda-go/lambda" +) + +type Response struct { + Message string `json:"message"` +} + +func Handler() (Response, error) { + return Response{ + Message: "Okay so your other function also executed successfully!", + }, nil +} + +func main() { + lambda.Start(Handler) +} diff --git a/lib/plugins/create/templates/aws-go/Makefile b/lib/plugins/create/templates/aws-go/Makefile new file mode 100644 index 00000000000..3b697426e39 --- /dev/null +++ b/lib/plugins/create/templates/aws-go/Makefile @@ -0,0 +1,4 @@ +build: + go get github.com/aws/aws-lambda-go/lambda + env GOOS=linux go build -ldflags="-s -w" -o bin/hello hello/main.go + env GOOS=linux go build -ldflags="-s -w" -o bin/world world/main.go \ No newline at end of file diff --git a/lib/plugins/create/templates/aws-go/gitignore b/lib/plugins/create/templates/aws-go/gitignore new file mode 100644 index 00000000000..f5b4c36adc3 --- /dev/null +++ b/lib/plugins/create/templates/aws-go/gitignore @@ -0,0 +1,5 @@ +# Serverless directories +.serverless + +# golang output binary directory +bin \ No newline at end of file diff --git a/lib/plugins/create/templates/aws-go/hello/main.go b/lib/plugins/create/templates/aws-go/hello/main.go new file mode 100644 index 00000000000..e75c5af0407 --- /dev/null +++ b/lib/plugins/create/templates/aws-go/hello/main.go @@ -0,0 +1,19 @@ +package main + +import ( + "github.com/aws/aws-lambda-go/lambda" +) + +type Response struct { + Message string `json:"message"` +} + +func Handler() (Response, error) { + return Response{ + Message: "Go Serverless v1.0! Your function executed successfully!", + }, nil +} + +func main() { + lambda.Start(Handler) +} diff --git a/lib/plugins/create/templates/aws-go/serverless.yml b/lib/plugins/create/templates/aws-go/serverless.yml new file mode 100644 index 00000000000..c3a1e2c95d4 --- /dev/null +++ b/lib/plugins/create/templates/aws-go/serverless.yml @@ -0,0 +1,104 @@ +# Welcome to Serverless! +# +# This file is the main config file for your service. +# It's very minimal at this point and uses default values. +# You can always add more config options for more control. +# We've included some commented out config examples here. +# Just uncomment any of them to get that config option. +# +# For full config options, check the docs: +# docs.serverless.com +# +# Happy Coding! + +service: aws-go # NOTE: update this with your service name + +# You can pin your service to only deploy with a specific Serverless version +# Check out our docs for more details +# frameworkVersion: "=X.X.X" + +provider: + name: aws + runtime: go1.x + +# you can overwrite defaults here +# stage: dev +# region: us-east-1 + +# you can add statements to the Lambda function's IAM Role here +# iamRoleStatements: +# - Effect: "Allow" +# Action: +# - "s3:ListBucket" +# Resource: { "Fn::Join" : ["", ["arn:aws:s3:::", { "Ref" : "ServerlessDeploymentBucket" } ] ] } +# - Effect: "Allow" +# Action: +# - "s3:PutObject" +# Resource: +# Fn::Join: +# - "" +# - - "arn:aws:s3:::" +# - "Ref" : "ServerlessDeploymentBucket" +# - "/*" + +# you can define service wide environment variables here +# environment: +# variable1: value1 + +package: + exclude: + - ./** + include: + - ./bin/** + +functions: + hello: + handler: bin/hello + world: + handler: bin/world + +# The following are a few example events you can configure +# NOTE: Please make sure to change your handler code to work with those events +# Check the event documentation for details +# events: +# events: +# - http: +# path: users/create +# method: get +# - s3: ${env:BUCKET} +# - schedule: rate(10 minutes) +# - sns: greeter-topic +# - stream: arn:aws:dynamodb:region:XXXXXX:table/foo/stream/1970-01-01T00:00:00.000 +# - alexaSkill +# - alexaSmartHome: amzn1.ask.skill.xx-xx-xx-xx +# - iot: +# sql: "SELECT * FROM 'some_topic'" +# - cloudwatchEvent: +# event: +# source: +# - "aws.ec2" +# detail-type: +# - "EC2 Instance State-change Notification" +# detail: +# state: +# - pending +# - cloudwatchLog: '/aws/lambda/hello' +# - cognitoUserPool: +# pool: MyUserPool +# trigger: PreSignUp + +# Define function environment variables here +# environment: +# variable2: value2 + +# you can add CloudFormation resource templates here +#resources: +# Resources: +# NewResource: +# Type: AWS::S3::Bucket +# Properties: +# BucketName: my-new-bucket +# Outputs: +# NewOutput: +# Description: "Description for the output" +# Value: "Some output value" diff --git a/lib/plugins/create/templates/aws-go/world/main.go b/lib/plugins/create/templates/aws-go/world/main.go new file mode 100644 index 00000000000..bf46aa6fbcb --- /dev/null +++ b/lib/plugins/create/templates/aws-go/world/main.go @@ -0,0 +1,19 @@ +package main + +import ( + "github.com/aws/aws-lambda-go/lambda" +) + +type Response struct { + Message string `json:"message"` +} + +func Handler() (Response, error) { + return Response{ + Message: "Okay so your other function also executed successfully!", + }, nil +} + +func main() { + lambda.Start(Handler) +} diff --git a/tests/templates/integration-test-template b/tests/templates/integration-test-template index 468532a571b..4bbd065d859 100755 --- a/tests/templates/integration-test-template +++ b/tests/templates/integration-test-template @@ -37,5 +37,10 @@ serverless deploy -v echo "Invoking Service" serverless invoke --function hello +if [ $template == "aws-go" ] || [ $template == "aws-go-dep" ] +then + serverless invoke --function world +fi + echo "Removing Service" serverless remove -v diff --git a/tests/templates/test_all_templates b/tests/templates/test_all_templates index 79bbebd5530..fd88105abf8 100755 --- a/tests/templates/test_all_templates +++ b/tests/templates/test_all_templates @@ -10,6 +10,8 @@ function integration-test { integration-test aws-csharp 'apt-get -qq update && apt-get -qq -y install zip && dotnet restore && dotnet lambda package --configuration release --framework netcoreapp1.0 --output-package bin/release/netcoreapp1.0/deploy-package.zip' integration-test aws-fsharp 'apt-get -qq update && apt-get -qq -y install zip && dotnet restore && dotnet lambda package --configuration release --framework netcoreapp1.0 --output-package bin/release/netcoreapp1.0/deploy-package.zip' +integration-test aws-go 'cd /go/src/app && make build' +integration-test aws-go-dep 'cd /go/src/app && make build' integration-test aws-groovy-gradle ./gradlew build integration-test aws-java-gradle ./gradlew build integration-test aws-java-maven mvn package