From 95e52b5f81c2d8ee5e574b17aa0d36020a471fab Mon Sep 17 00:00:00 2001 From: Reda Noureddine Date: Tue, 14 Mar 2023 15:56:31 +0100 Subject: [PATCH 01/10] doc(functions): add readme --- functions/postgre-sql-python/README.md | 60 ++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 functions/postgre-sql-python/README.md diff --git a/functions/postgre-sql-python/README.md b/functions/postgre-sql-python/README.md new file mode 100644 index 0000000..102a01d --- /dev/null +++ b/functions/postgre-sql-python/README.md @@ -0,0 +1,60 @@ +# Interact with a PostgreSQL database using pythonic functions + +## Requirements + +This example assumes that you are familiar with some products of Scaleway's ecosystem: + * how serverless functions work. If needed, you can check [Scaleway official documentation](https://www.scaleway.com/en/docs/serverless/functions/quickstart/). + * how a managed database for PostgreSQL works, and especially how to create a database and create users with appropriate permissions. Please refer to scaleway's documentation [here](https://www.scaleway.com/en/docs/managed-databases/postgresql-and-mysql/quickstart/). + +This example uses the Scaleway Serverless Framework Plugin. Please set up your environment with the requirements stated in the [Scaleway Serverless Framework Plugin](https://github.com/scaleway/serverless-scaleway-functions) before trying out the example. + + +## Context + +This example shows how to connect to a managed PostgreSQL database and perform a query on it. This example can be extended to adding, deleting, or processing data within a database. + + +## Description + +The function connects to a PostgreSQL database and performs an example query on it. This example uses Python 3.10 runtime. Used packages are specified in `package.json`. As a requirement for this example we use a pre-compiled [`psycopg2` version](https://www.psycopg.org/docs/install.html#install-from-source). + +## Setup + +### Create a managed PostgreSQL database + +Create a PostgreSQL database and a user profile with appropriate access permissions. + +### Fill environment variables + +Fill your secrets within `serverless.yml` file: + +``` +secret: + PG_HOST: "your host IP address" + PG_USER: "your database username" + PG_DATABASE: "your database name" + PG_PASSWORD: "your database user password" + PG_PORT: "your database port" +``` + +### Install npm modules + +Once your environment is set up, you can install `npm` dependencies from `package.json` file using: + +``` +npm install +``` + +### Deploy and call the function + +Then deploy your function and get its URL using: + +``` +./bin/deploy.sh +``` + +From the given function URL, you can run your function using: + +``` +curl +``` \ No newline at end of file From 7cf181e058ef28dd47f21767f9879a10f477cf91 Mon Sep 17 00:00:00 2001 From: Reda Noureddine Date: Tue, 14 Mar 2023 15:59:25 +0100 Subject: [PATCH 02/10] doc(functions): update project global readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f8380d9..c404a95 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Table of Contents: | **[Python Dependencies](functions/python-dependencies/README.md)**
Example showing how to use Python requirements with Serverless Framework. | python310 | [Serverless Framework] | | **[Redis TLS](functions/redis-tls/README.md)**
How to connect a function to a Scaleway Redis cluster with TLS enabled. | python310 | [Serverless Framework] | | **[Rust MNIST](functions/rust-mnist/README.md)**
A Rust function to recognize hand-written digits with a simple neural network. | rust165 | [Serverless Framework] | +| **[PostgreSQL Python](functions/postgre-sql-python/README.md)**
A Python function to perform a query on a PostgreSQL managed database. | python310 | [Serverless Framework] | | **[Terraform Python](functions/terraform-python-example/README.md)**
A Python function deployed with Terraform. | python310 | [Terraform] | ### 📦 Containers From fd38d993f4dcd6b33884cdb7ec2d5e2039b6b37e Mon Sep 17 00:00:00 2001 From: Reda Noureddine Date: Tue, 14 Mar 2023 15:59:47 +0100 Subject: [PATCH 03/10] feat(functions): add function handler --- .../postgre-sql-python/handlers/handler.py | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 functions/postgre-sql-python/handlers/handler.py diff --git a/functions/postgre-sql-python/handlers/handler.py b/functions/postgre-sql-python/handlers/handler.py new file mode 100644 index 0000000..d76be3d --- /dev/null +++ b/functions/postgre-sql-python/handlers/handler.py @@ -0,0 +1,53 @@ +import psycopg2 +from psycopg2 import Error +import os +import logging + +PG_HOST=os.environ.get('PG_HOST') +PG_USER=os.environ.get('PG_USER') +PG_DATABASE=os.environ.get('PG_DATABASE') +PG_PASSWORD=os.environ.get('PG_PASSWORD') +PG_PORT=os.environ.get('PG_PORT') + +def handle(event, context): + + try: + connection = psycopg2.connect( + database=PG_DATABASE, + user=PG_USER, + host=PG_HOST, + password=PG_PASSWORD, + port=PG_PORT, + sslmode="disable") + + except (Exception, Error) as error: + logging.error("Error while connecting to PostgreSQL database", error) + return { + "statusCode": 500, + "body": { + "message": "Error while connecting to PostgreSQL database, check function logs for more information" + } + } + + try: + cursor = connection.cursor() + logging.info("Connected to Database") + cursor.execute("SELECT * FROM table LIMIT 10") + record = cursor.fetchone() + logging.info("Successfully fetched data") + cursor.close() + return { + "statusCode": 200, + "body": { + "message": record + } + } + + except (Exception, Error) as error: + logging.error("Error while interacting with PostgreSQL", error) + return { + "statusCode": 500, + "body": { + "message": "Error while getting information from PostgreSQL database, check function logs for more information" + } + } \ No newline at end of file From daecb23c4c59678c1ebe79205e53e3add75b1947 Mon Sep 17 00:00:00 2001 From: Reda Noureddine Date: Tue, 14 Mar 2023 16:00:20 +0100 Subject: [PATCH 04/10] chore(functions): add function requirements --- functions/postgre-sql-python/requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 functions/postgre-sql-python/requirements.txt diff --git a/functions/postgre-sql-python/requirements.txt b/functions/postgre-sql-python/requirements.txt new file mode 100644 index 0000000..ce710a6 --- /dev/null +++ b/functions/postgre-sql-python/requirements.txt @@ -0,0 +1 @@ +psycopg2 == 2.9.5 \ No newline at end of file From 0336e2c30d4ad496a64d5e1967cc3537884782e9 Mon Sep 17 00:00:00 2001 From: Reda Noureddine Date: Tue, 14 Mar 2023 16:01:02 +0100 Subject: [PATCH 05/10] chore(functions): add npm dev dependencies --- functions/postgre-sql-python/package.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 functions/postgre-sql-python/package.json diff --git a/functions/postgre-sql-python/package.json b/functions/postgre-sql-python/package.json new file mode 100644 index 0000000..43cd65b --- /dev/null +++ b/functions/postgre-sql-python/package.json @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "serverless-scaleway-functions": "^0.4.6" + } +} From e0ac0eb7bf73b72ea012a81c79cebd405afae9c5 Mon Sep 17 00:00:00 2001 From: Reda Noureddine Date: Tue, 14 Mar 2023 16:01:22 +0100 Subject: [PATCH 06/10] chore(functions): add serverless config file --- functions/postgre-sql-python/serverless.yml | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 functions/postgre-sql-python/serverless.yml diff --git a/functions/postgre-sql-python/serverless.yml b/functions/postgre-sql-python/serverless.yml new file mode 100644 index 0000000..4536d43 --- /dev/null +++ b/functions/postgre-sql-python/serverless.yml @@ -0,0 +1,26 @@ +service: get-all-from-database + +configValidationMode: off + +provider: + name: scaleway + runtime: python310 + secret: + PG_HOST: "your database host IP address" + PG_USER: "your database username" + PG_DATABASE: "your database name" + PG_PASSWORD: "your database user password" + PG_PORT: "your database port" + +plugins: + - serverless-scaleway-functions + +package: + patterns: + - '!node_modules/**' + - '!.gitignore' + - '!.git/**' + +functions: + first: + handler: handlers/handler.handle From dd40f46d953736e76535cd10a0c0e43a0bb84eac Mon Sep 17 00:00:00 2001 From: Reda Noureddine Date: Tue, 14 Mar 2023 16:01:58 +0100 Subject: [PATCH 07/10] chore(functions): add deployment shell scripts --- functions/postgre-sql-python/bin/deploy.sh | 7 +++++++ functions/postgre-sql-python/bin/deps.sh | 11 +++++++++++ 2 files changed, 18 insertions(+) create mode 100755 functions/postgre-sql-python/bin/deploy.sh create mode 100755 functions/postgre-sql-python/bin/deps.sh diff --git a/functions/postgre-sql-python/bin/deploy.sh b/functions/postgre-sql-python/bin/deploy.sh new file mode 100755 index 0000000..c2157e1 --- /dev/null +++ b/functions/postgre-sql-python/bin/deploy.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +./bin/deps.sh + +serverless deploy diff --git a/functions/postgre-sql-python/bin/deps.sh b/functions/postgre-sql-python/bin/deps.sh new file mode 100755 index 0000000..352f156 --- /dev/null +++ b/functions/postgre-sql-python/bin/deps.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -e + +# This command will run pip install with the given requirements.txt file inside +# a docker container compatible with our function runtimes, and pull the installed +# dependencies locally to your package directory. As these dependencies have been +# installed on top of alpine Linux with our compatible system libraries, you will +# be able to upload your source code and deploy your function properly. +PYTHON_VERSION=3.10 +docker run --rm -v $(pwd):/home/app/function --workdir /home/app/function rg.fr-par.scw.cloud/scwfunctionsruntimes-public/python-dep:$PYTHON_VERSION pip install -r ./requirements.txt --target ./package From faed822dc4c5e5143514a2e23a004ecbf3f421b6 Mon Sep 17 00:00:00 2001 From: Reda Noureddine Date: Tue, 14 Mar 2023 17:01:22 +0100 Subject: [PATCH 08/10] fix(functions): update python requirements --- functions/postgre-sql-python/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/postgre-sql-python/requirements.txt b/functions/postgre-sql-python/requirements.txt index ce710a6..fe5c3f7 100644 --- a/functions/postgre-sql-python/requirements.txt +++ b/functions/postgre-sql-python/requirements.txt @@ -1 +1 @@ -psycopg2 == 2.9.5 \ No newline at end of file +psycopg2-binary == 2.9 \ No newline at end of file From 288dc758c391489fbb3875e1e4f0785dd2de88a6 Mon Sep 17 00:00:00 2001 From: Reda Noureddine Date: Fri, 24 Mar 2023 12:17:29 +0100 Subject: [PATCH 09/10] feat: require ssl certificate --- functions/postgre-sql-python/handlers/handler.py | 7 +++++-- functions/postgre-sql-python/serverless.yml | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/functions/postgre-sql-python/handlers/handler.py b/functions/postgre-sql-python/handlers/handler.py index d76be3d..b10a506 100644 --- a/functions/postgre-sql-python/handlers/handler.py +++ b/functions/postgre-sql-python/handlers/handler.py @@ -8,6 +8,7 @@ PG_DATABASE=os.environ.get('PG_DATABASE') PG_PASSWORD=os.environ.get('PG_PASSWORD') PG_PORT=os.environ.get('PG_PORT') +PG_SSL_ROOT_CERT=os.environ.get('PG_SSL_ROOT_CERT') def handle(event, context): @@ -18,7 +19,9 @@ def handle(event, context): host=PG_HOST, password=PG_PASSWORD, port=PG_PORT, - sslmode="disable") + sslmode="require", + sslrootcert=PG_SSL_ROOT_CERT, + ) except (Exception, Error) as error: logging.error("Error while connecting to PostgreSQL database", error) @@ -50,4 +53,4 @@ def handle(event, context): "body": { "message": "Error while getting information from PostgreSQL database, check function logs for more information" } - } \ No newline at end of file + } diff --git a/functions/postgre-sql-python/serverless.yml b/functions/postgre-sql-python/serverless.yml index 4536d43..27cb909 100644 --- a/functions/postgre-sql-python/serverless.yml +++ b/functions/postgre-sql-python/serverless.yml @@ -11,6 +11,7 @@ provider: PG_DATABASE: "your database name" PG_PASSWORD: "your database user password" PG_PORT: "your database port" + PG_SSL_ROOT_CERT: "path to you ssl certificate" plugins: - serverless-scaleway-functions From f2414b1853758a8614cfb31c1c11e2dfad397bab Mon Sep 17 00:00:00 2001 From: Reda Noureddine Date: Fri, 24 Mar 2023 13:21:13 +0100 Subject: [PATCH 10/10] docs: update readme --- functions/postgre-sql-python/README.md | 1 + functions/postgre-sql-python/serverless.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/functions/postgre-sql-python/README.md b/functions/postgre-sql-python/README.md index 102a01d..efb6a87 100644 --- a/functions/postgre-sql-python/README.md +++ b/functions/postgre-sql-python/README.md @@ -35,6 +35,7 @@ secret: PG_DATABASE: "your database name" PG_PASSWORD: "your database user password" PG_PORT: "your database port" + PG_SSL_ROOT_CERT: "path to your database ssl certificate" ``` ### Install npm modules diff --git a/functions/postgre-sql-python/serverless.yml b/functions/postgre-sql-python/serverless.yml index 27cb909..5aefaf7 100644 --- a/functions/postgre-sql-python/serverless.yml +++ b/functions/postgre-sql-python/serverless.yml @@ -11,7 +11,7 @@ provider: PG_DATABASE: "your database name" PG_PASSWORD: "your database user password" PG_PORT: "your database port" - PG_SSL_ROOT_CERT: "path to you ssl certificate" + PG_SSL_ROOT_CERT: "path to your database ssl certificate" plugins: - serverless-scaleway-functions