Skip to content

feat(go): mongo db sample #100

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Table of Contents:
<!-- markdownlint-disable MD033 -->

| Example | Runtime | Deployment |
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|------------------------|
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ---------------------- |
| **[Badge PHP](functions/badge-php/README.md)** <br/> A PHP function to generate repository badges. | php82 | [Serverless Framework] |
| **[CORS Go](functions/cors-go/README.md)** <br/> A Go function which allows CORS requests. | go122 | [Serverless Framework] |
| **[CORS Node](functions/cors-node/README.md)** <br/> A Node function which allows CORS requests. | node18 | [Serverless Framework] |
Expand Down Expand Up @@ -61,11 +61,12 @@ Table of Contents:
| **[Serverless Gateway Python Example](functions/serverless-gateway-python/README.md)** <br/> A Python serverless API using Serverless Gateway. | python310 | [Python API Framework] |
| **[Go and Transactional Email](functions/go-mail/README.md)** <br/> A Go function that send emails using Scaleway SDK. | go121 | [Serverless Framework] |
| **[Rotate RDB Credentials](functions/secret-manager-rotate-secret/README.md)** <br/> A Go function that rotates RDB credentials stored in Secret Manager. | go120 | [Serverless Framework] |
| **[Connect to Mongo DB](functions/go-mongo/)** <br/> A Go example to connect to Mongo DB | go124 | [Console] |

### 📦 Containers

| Example | Language | Deployment |
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|------------------------|
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ---------------------- |
| **[Container Bash Script](containers/bash-scheduled-job/README.md)** <br/> A Bash script runnning on a schedule using serverless containers. | Bash | [Serverless Framework] |
| **[Function Handler Java](containers/function-handler-java/README.md)** <br/> A Java function handler deployed on CaaS. | Java | [Serverless Framework] |
| **[NGINX CORS Private](containers/nginx-cors-private-python/README.md)** <br/> An NGINX proxy to allow CORS requests to a private container. | Python Flask | [Terraform] |
Expand All @@ -79,7 +80,7 @@ Table of Contents:
### ⚙️ Jobs

| Example | Language | Deployment |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------------------------|
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------------------------- |
| **[Serverless Jobs Hello World](jobs/terraform-hello-world/README.md)** <br/> An example of building a container image and running it as a Serverless Job using Terraform. | N/A | [Terraform]-[Console] |
| **[Serverless MLOps](jobs/ml-ops/README.md)** <br/> An example of running a Serverless Machine Leaning workflow. | Python | [Terraform]-[Console]-[CLI] |
| **[Auto Snapshot Instances](jobs/instances-snapshot/README.md)** <br/> Use Serverless Jobs to create snapshots of your instances | Go | [Console] |
Expand All @@ -90,15 +91,15 @@ Table of Contents:
### 💬 Messaging and Queueing

| Example | Services | Language | Deployment |
|--------------------------------------------------------------------------------------------------------------------------------------------------------|------------------|----------|-------------|
| ------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------- | -------- | ----------- |
| **[Manage large message](mnq/large-messages/README.md)** <br/> An example of infrastructure to manage large messages. | PaaS & S3 | Python | [Terraform] |
| **[Serverless scraping](mnq/serverless-scraping/README.md)** <br/> An example of infrastructure to scrape the hackernews website. | PaaS & RDB | Python | [Terraform] |
| **[SNS Instances Notification System](mnq/sns-instances-notification-system/README.md)** <br/> An example of infrastructure to use SNS with Instances. | PaaS & Instances | Golang | [Terraform] |

### 💜 Projects

| Example | Services | Language | Deployment |
|-------------------------------------------------------------------------------------------------------------------------------------------|-------------|----------|------------------------|
| ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | -------- | ---------------------- |
| **[Kong API Gateway](projects/kong-api-gateway/README.md)** <br/> Deploying a Kong Gateway on containers to provide routing to functions. | CaaS & FaaS | Python | [Serverless Framework] |
| **[Serverless Gateway](https://github.com/scaleway/serverless-gateway)** <br/> Our serverless gateway for functions and containers. | API Gateway | Python | [Python API Framework] |
| **[Monitoring Glaciers](projects/blogpost-glacier/README.md)** <br/> A project to monitor glaciers and the impact of global warming. | S3 & RDB | Golang | [Serverless Framework] |
Expand Down
59 changes: 59 additions & 0 deletions functions/go-mongo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Mongo + Go example

Example to demonstrate the possibility to connect Serverless Functions to MongoDB.

For this example, [Scaleway Console](https://console.scaleway.com/) will be used for deployment.

> [!WARNING]
> This is a basic sample that does not use certificate for authentication, not recommended for production.

## Requirements

- Mongo DB created [documentation](https://www.scaleway.com/en/docs/managed-mongodb-databases/quickstart/#how-to-create-a-database-instance)

## Step 1 - Mongo

After Mongo DB creation, in the console find the public endpoint of the database, it should look lile: `<scw_database_id>.mgdb.<scw_region>.scw.cloud`

Once you get the endpoint, keep it somewhere for later use.

## Step 2 - Function Creation

Before creating a the Function, we need to package it into a zip file.

> [!TIP]
> It's recommended to do it via command line tools, so the following example shows how to zip this current folder:
>
> ```sh
> cd ~/scaleway/serverless-examples/functions/go-mongo/
> zip -r go-mongo.zip *
> ```

- Create a Serverless Function namespace. [Documentation](https://www.scaleway.com/en/docs/serverless-functions/how-to/create-manage-delete-functions-namespace/#creating-a-serverless-functions-namespace)
- In the created namespace, create Serverless Function
- Select the Go runtime
- Upload the previously created `go-mongo.zip`
- Ensure the handler is `Handle`
- Add required Secrets to the Function:

| Key | Value |
| --------------------- | -------------------------------------------------------------------------------------------------------------- |
| MONGO_PUBLIC_ENDPOINT | (replace with required values): `<scw_database_id>.mgdb.<scw_region>.scw.cloud` |
| MONGO_USER | user created during Mongo DB setup |
| MONGO_PASSWORD | password created during Mongo DB user setup |

## Step 3 - Test

Once your Serverless Function is in `ready` state, you can call it using the generated endpoint.

Result should be similar to:

```json
{ "ID": 2911126, "Name": "RandomName2911126" }
```

## Local testing

For testing you can use [Go Offline Testing](https://github.com/scaleway/serverless-functions-go).

To run locally, execute: `go run cmd/main.go`.
12 changes: 12 additions & 0 deletions functions/go-mongo/cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

import (
scw "github.com/scaleway/serverless-examples/functions/go-mongo"
"github.com/scaleway/serverless-functions-go/local"
)

// https://github.com/scaleway/serverless-functions-go
func main() {
// Replace "Handle" with your function handler name if necessary
local.ServeHandler(scw.Handle, local.WithPort(8080))
}
22 changes: 22 additions & 0 deletions functions/go-mongo/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module github.com/scaleway/serverless-examples/functions/go-mongo

go 1.24.1

require (
github.com/scaleway/serverless-functions-go v0.1.2
go.mongodb.org/mongo-driver v1.17.3
)

require (
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/montanaflynn/stats v0.7.1 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
golang.org/x/crypto v0.26.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/text v0.17.0 // indirect
)
60 changes: 60 additions & 0 deletions functions/go-mongo/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
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/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
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/scaleway/serverless-functions-go v0.1.2 h1:UUToB+XXpLDG9l6c9c0ALhAs1jvb6rV2Lkyj2kZEYCo=
github.com/scaleway/serverless-functions-go v0.1.2/go.mod h1:23Hj74DYzTsVY3QgvsM0MGnx0+0OAAabTC06BOMJE58=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ=
go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
91 changes: 91 additions & 0 deletions functions/go-mongo/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package example

import (
"context"
"encoding/json"
"fmt"
"log/slog"
"math/rand"
"net/http"
"net/url"
"os"

"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)

var client *mongo.Client

type RandomDocument struct {
ID int `bson:"id"`
Name string `bson:"name"`
}

func init() {
mongoPublicEndpoint := os.Getenv("MONGO_PUBLIC_ENDPOINT")
if mongoPublicEndpoint == "" {
panic("MONGO_PUBLIC_ENDPOINT is required")
}

mongoUser := os.Getenv("MONGO_USER")
if mongoUser == "" {
panic("MONGO_USER is required")
}

mongoPassword := url.PathEscape(os.Getenv("MONGO_PASSWORD"))
if mongoPassword == "" {
panic("MONGO_PASSWORD is required")
}

// This is a basic sample that does not use certificate for authentication, not recommended for production.
mongo_uri := fmt.Sprintf(`mongodb+srv://%s:%s@%s/?tls=true&tlsInsecure=true`,
mongoUser,
mongoPassword,
mongoPublicEndpoint)

var err error
client, err = mongo.Connect(context.TODO(), options.Client().ApplyURI(mongo_uri))
if err != nil {
panic(err)
}

err = client.Ping(context.TODO(), nil)
if err != nil {
panic(err)
}

slog.Info("Connected to MongoDB")
}

func Handle(w http.ResponseWriter, r *http.Request) {
collection := client.Database("testdb").Collection("testcollection")

randomID := rand.Intn(100000000)

doc := RandomDocument{
ID: randomID,
Name: fmt.Sprintf("RandomName%d", randomID),
}

insertResult, err := collection.InsertOne(context.TODO(), doc)
if err != nil {
panic(err)
}

slog.Info("Inserted document with ID:", insertResult.InsertedID)

var result RandomDocument

if err := collection.FindOne(context.TODO(), bson.M{"_id": insertResult.InsertedID}).Decode(&result); err != nil {
panic(err)
}

slog.Info("Found document", result.Name, result.ID)

w.Header().Set("Content-Type", "application/json")

if err := json.NewEncoder(w).Encode(result); err != nil {
panic(err)
}
}
Loading