Skip to content

Commit f917c52

Browse files
authored
feat(triggers): NATS example (#54)
* Working example * Clean-up * Add link to top-level README * README fixes
1 parent 0e55567 commit f917c52

File tree

11 files changed

+192
-0
lines changed

11 files changed

+192
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Table of Contents:
5050
| **[PostgreSQL Python](functions/postgre-sql-python/README.md)** <br/> A Python function to perform a query on a PostgreSQL managed database. | python310 | [Serverless Framework] |
5151
| **[Terraform Python](functions/terraform-python-example/README.md)** <br/> A Python function deployed with Terraform. | python310 | [Terraform] |
5252
| **[Triggers Getting Started](functions/triggers-getting-started/README.md)** <br/> Simple SQS trigger example for all runtimes. | all | [Terraform] |
53+
| **[Triggers NATS](functions/triggers-nats/README.md)** <br/> Simple NATS trigger example using Terraform. | all | [Terraform] |
5354
| **[Typescript with Node runtime](functions/typescript-with-node/README.md)** <br/> A Typescript function using Node runtime. | node18 | [Serverless Framework] |
5455
| **[Serverless Gateway Python Example](functions/serverless-gateway-python/README.md)** <br/> A Python serverless API using Serverless Gateway. | python310 | [Python API Framework] |
5556

functions/triggers-nats/.gitignore

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Nats credentials
2+
files/nats-creds
3+
4+
# Local .terraform directories
5+
**/.terraform/*
6+
7+
# .tfstate files
8+
*.tfstate
9+
*.tfstate.*
10+
11+
# Crash log files
12+
crash.log
13+
crash.*.log

functions/triggers-nats/README.md

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Triggers NATS example
2+
3+
Simple example showing how to use NATS triggers with Scaleway Functions.
4+
5+
For complete examples of triggers in all function languages, see [triggers-getting-started](../triggers-getting-started).
6+
7+
The example function is triggered by a message to a NATS topic, and will log the message body.
8+
9+
## Requirements
10+
11+
This example requires [Terraform](https://www.scaleway.com/en/docs/tutorials/terraform-quickstart/).
12+
13+
Also, NATS **must** be [activated](https://www.scaleway.com/en/docs/serverless/messaging/how-to/get-started/#how-to-create-a-nats-account) on your project.
14+
15+
## Setup
16+
17+
The Terraform configuration will create an example function, a NATS account, and a trigger. It will also write the NATS credentials to a file (`files/nats-creds`).
18+
19+
To authenticate with Scaleway, you can either set up the [Scaleway CLI](https://www.scaleway.com/en/cli/), from which Terraform can extract credentials, or you can export `SCW_ACCESS_KEY`, `SCW_SECRET_KEY` and `SCW_DEFAULT_PROJECT_ID`.
20+
21+
Once auth is set up, you can run:
22+
23+
```console
24+
terraform init
25+
terraform apply
26+
```
27+
28+
You should be able to see your resources in the Scaleway console:
29+
30+
- NATS accounts can be found in the [MnQ section](https://console.scaleway.com/messaging/protocols/fr-par/nats/accounts)
31+
- Functions can be found in the `triggers-nats` namespace in the [Serverless functions section](https://console.scaleway.com/functions/namespaces)
32+
33+
## Running
34+
35+
You can trigger your functions by sending messages to the NATS topic associated to the trigger (`triggers-nats-topic`). Below is a description of how to do this with our dummy `tests/send_messages.py` script.
36+
37+
### Setup
38+
39+
First you need to extract your NATS endpoint from Terraform:
40+
41+
```console
42+
export NATS_ENDPOINT=$(terraform output -raw nats_endpoint)
43+
```
44+
45+
Then you can set up a Python environment in the `tests` directory, e.g.
46+
47+
```console
48+
cd tests
49+
python3 -m venv venv
50+
source venv/bin/activate
51+
pip3 install -r requirements.txt
52+
```
53+
54+
### Sending messages
55+
56+
Now you can run the `send_messages.py` script to send a message to the NATS topic:
57+
58+
```console
59+
python3 send_messages.py
60+
```
61+
62+
### Viewing function logs
63+
64+
In your [Cockpit](https://console.scaleway.com/cockpit), you can access the logs from your NATS topics and functions.
65+
66+
Navigate from your Cockpit to Grafana, and find the `Serverless Functions Logs` dashboard. There you should see logs from your function, printing the body of the NATS message.
67+
68+
## Cleanup
69+
70+
To delete all the resources used in this example, you can run the following from the root of the project:
71+
72+
```console
73+
terraform destroy
74+
```
279 Bytes
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
def handle(event, context):
2+
# The content of the NATS message is passed in the body
3+
msg_body = event.get("body")
4+
print(f"Received message: {msg_body}")
5+
6+
return "Hello NATS!"

functions/triggers-nats/main.tf

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
resource "scaleway_function_namespace" "main" {
2+
name = "triggers-nats"
3+
}
4+
5+
data "archive_file" "source_zip" {
6+
type = "zip"
7+
source_dir = "${path.module}/function"
8+
output_path = "${path.module}/files/function.zip"
9+
}
10+
11+
resource "scaleway_function" "main" {
12+
namespace_id = scaleway_function_namespace.main.id
13+
name = "nats-target"
14+
runtime = "python310"
15+
handler = "handler.handle"
16+
17+
zip_file = data.archive_file.source_zip.output_path
18+
zip_hash = filesha256(data.archive_file.source_zip.output_path)
19+
20+
privacy = "public"
21+
22+
deploy = true
23+
24+
memory_limit = 512 # MB / 280 mVCPU
25+
26+
min_scale = 0
27+
}
28+
29+
resource "scaleway_function_trigger" "main" {
30+
function_id = scaleway_function.main.id
31+
name = "nats-trigger"
32+
nats {
33+
account_id = scaleway_mnq_nats_account.main.id
34+
subject = "triggers-nats-topic"
35+
}
36+
}

functions/triggers-nats/messaging.tf

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
resource "scaleway_mnq_nats_account" "main" {
2+
name = "nats-account"
3+
}
4+
5+
resource "scaleway_mnq_nats_credentials" "main" {
6+
account_id = scaleway_mnq_nats_account.main.id
7+
name = "triggers-nats"
8+
}
9+
10+
resource "local_sensitive_file" "nats" {
11+
filename = "files/nats-creds"
12+
content = "${scaleway_mnq_nats_credentials.main.file}"
13+
}

functions/triggers-nats/outputs.tf

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
output "nats_endpoint" {
2+
value = scaleway_mnq_nats_account.main.endpoint
3+
sensitive = true
4+
}
5+

functions/triggers-nats/provider.tf

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
terraform {
2+
required_providers {
3+
scaleway = {
4+
source = "scaleway/scaleway"
5+
version = ">= 2.31"
6+
}
7+
archive = {
8+
source = "hashicorp/archive"
9+
version = ">= 2.4"
10+
}
11+
}
12+
required_version = ">= 0.13"
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
asyncio~=3.4.3
2+
boto3~=1.28.40
3+
nats-py~=2.5.0
4+
nkeys~=0.1.0
5+
requests~=2.31.0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import asyncio
2+
import os
3+
4+
import nats
5+
6+
NATS_ENDPOINT = os.environ.get("NATS_ENDPOINT")
7+
NATS_CREDS_PATH = "../files/nats-creds"
8+
9+
NATS_TOPIC = "triggers-nats-topic"
10+
11+
12+
async def main():
13+
print(f"Connecting to NATS account at {NATS_ENDPOINT}")
14+
15+
# Connect to NATS
16+
nc = await nats.connect(servers=[NATS_ENDPOINT], user_credentials=NATS_CREDS_PATH)
17+
18+
# Publish a message
19+
await nc.publish(NATS_TOPIC, b"Hello from the NATS trigger!")
20+
21+
# Close NATS connection
22+
await nc.close()
23+
24+
25+
if __name__ == "__main__":
26+
asyncio.run(main())

0 commit comments

Comments
 (0)