add nodejs 6 and python for serverless triggers on gcloud functions (#608)

This commit is contained in:
Rosário Pereira Fernandes 2018-10-02 11:09:06 +02:00 committed by Shahidh K Muhammed
parent f34338f792
commit f40da07aaa
15 changed files with 299 additions and 2 deletions

View File

@ -6,8 +6,8 @@ Some of the language/platforms are work in progress. We welcome contributions fo
| Folder name | Use-case| Node.js(8) | Node.js(6) | Python
|-------------|---------|:--------:|:------:|:----:
| echo | echo the trigger payload | ✅ | ❌ | ❌
| mutation | insert related data on an insert event using graphql mutation | ✅ | ❌ | ❌
| echo | echo the trigger payload | ✅ | ✅ | ✅
| mutation | insert related data on an insert event using graphql mutation | ✅ | ✅ | ❌
| push-notification | send push notification on database event | ❌ | ❌ | ❌
| etl | transform the trigger payload and update an algolia index | ❌ | ❌ | ❌

View File

@ -0,0 +1,20 @@
# This file specifies files that are *not* uploaded to Google Cloud Platform
# using gcloud. It follows the same syntax as .gitignore, with the addition of
# "#!include" directives (which insert the entries of the given .gitignore-style
# file at that point).
#
# For more information, run:
# $ gcloud topic gcloudignore
#
.gcloudignore
# If you would like to upload your .git directory, .gitignore file or files
# from your .gitignore file, remove the corresponding line
# below:
.git
.gitignore
node_modules
.env.yaml
.prod.env.yaml

View File

@ -0,0 +1,2 @@
node_modules
.prod.env.yaml

View File

@ -0,0 +1,40 @@
# Setup table
Create the table using the console:
```
Table name: profile
Columns:
id: Integer auto-increment
name: Text
address: Text
lat: Numeric, Nullable
lng: Numeric, Nullable
```
# Deploy Google Cloud function
Deploy the function:
```bash
gcloud beta functions deploy nodejs-echo \
--trigger-http
```
Get the trigger URL:
```yaml
httpsTrigger:
url: https://us-central1-hasura-test.cloudfunctions.net/nodejs-echo
```
Open Hasura console, goto `Events -> Add Trigger` and create a new trigger:
```
Trigger name: profile_change
Schema/Table: public/profile
Operations: Insert, Update, Delete
Webhook URL: [Trigger URL]
```
Once the trigger is created, goto `Data -> profile -> Insert row` and add a row.

View File

@ -0,0 +1,6 @@
exports.function = (req, res) => {
const { event: {op, data}, table: {name, schema} } = req.body;
const response = {message: 'received event', data: {op, data, name, schema}};
console.log(response);
res.json(response);
};

View File

@ -0,0 +1,2 @@
GMAPS_API_KEY: '[GMAPS_API_KEY]'
HASURA_GRAPHQL_ENGINE_URL: 'http://[HGE_IP]/v1alpha1/graphql'

View File

@ -0,0 +1,19 @@
# This file specifies files that are *not* uploaded to Google Cloud Platform
# using gcloud. It follows the same syntax as .gitignore, with the addition of
# "#!include" directives (which insert the entries of the given .gitignore-style
# file at that point).
#
# For more information, run:
# $ gcloud topic gcloudignore
#
.gcloudignore
# If you would like to upload your .git directory, .gitignore file or files
# from your .gitignore file, remove the corresponding line
# below:
.git
.gitignore
node_modules
.env.yaml
.prod.env.yaml

View File

@ -0,0 +1,2 @@
node_modules
.prod.env.yaml

View File

@ -0,0 +1,71 @@
# Setup table
Create the table using the console:
```
Table name: profile
Columns:
id: Integer auto-increment
name: Text
address: Text
lat: Numeric, Nullable
lng: Numeric, Nullable
```
# Deploy Google Cloud function
We are going to use Google Maps API in our cloud function.
Enable Google Maps API and get an API key (we'll call it `GMAPS_API_KEY`) following [this
guide](https://developers.google.com/maps/documentation/geocoding/start?hl=el#auth)
Check the `Places` box to get access to Geocoding API.
We'll follow [this guide](https://cloud.google.com/functions/docs/quickstart)
and create a Cloud Function with NodeJS 6.
```bash
gcloud components update &&
gcloud components install beta
```
Goto the `cloudfunction` directory:
```bash
cd cloudfunction
```
Edit `.env.yaml` and add values for the following as shown:
```yaml
# .env.yaml
GMAPS_API_KEY: '[GMAPS_API_KEY]'
HASURA_GRAPHQL_ENGINE_URL: 'http://[HGE_IP]/v1alpha1/graphql'
```
```bash
gcloud beta functions deploy trigger \
--runtime nodejs6 \
--trigger-http \
--region asia-south1 \
--env-vars-file .env.yaml
```
Get the trigger URL:
```yaml
httpsTrigger:
url: https://asia-south1-hasura-test.cloudfunctions.net/trigger
```
Goto `HGE_IP` on browser, `Events -> Add Trigger` and create a new trigger:
```
Trigger name: profile_change
Schema/Table: public/profile
Operations: Insert
Webhook URL: [Trigger URL]
```
Once the trigger is created, goto `Data -> profile -> Insert row` and add a new
profile with name and address, save. Goto `Browse rows` tabs to see lat and lng
updated, by the cloud function.

View File

@ -0,0 +1,49 @@
const fetch = require('node-fetch');
const { query } = require('graphqurl');
const MUTATION_UPDATE_LAT_LONG = `
mutation updateLatLong($id: Int!, $lat: numeric! $lng: numeric!) {
update_profile(
where: {id: {_eq: $id}},
_set: {
lat: $lat,
lng: $lng
}
) {
affected_rows
returning {
id
lat
lng
}
}
}`;
exports.trigger = (req, res) => {
const GMAPS_API_KEY = process.env.GMAPS_API_KEY;
const HASURA_GRAPHQL_ENGINE_URL = process.env.HASURA_GRAPHQL_ENGINE_URL;
const { event: {op, data}, table } = req.body;
if (op === 'INSERT' && table.name === 'profile' && table.schema === 'public') {
const { id, address } = data.new;
fetch(`https://maps.googleapis.com/maps/api/geocode/json?address=${address}&key=${GMAPS_API_KEY}`).then( gmaps => {
gmaps.json().then( gmapsResponse => {
if (gmapsResponse.results && gmapsResponse.results.length === 0) {
res.json({error: true, data: gmapsResponse, message: `no results for address ${address}`});
return;
}
const { lat, lng } = gmapsResponse.results[0].geometry.location;
query({
query: MUTATION_UPDATE_LAT_LONG,
endpoint: HASURA_GRAPHQL_ENGINE_URL,
variables: { id, lat, lng },
}).then( hgeResponse => {
res.json({error: false, data: hgeResponse.data});
});
});
});
} else {
res.json({error: false, message: 'ignored event'});
}
};

View File

@ -0,0 +1,15 @@
{
"name": "cloudfunction",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"graphqurl": "^0.3.1",
"node-fetch": "^2.2.0"
}
}

View File

@ -0,0 +1,18 @@
# This file specifies files that are *not* uploaded to Google Cloud Platform
# using gcloud. It follows the same syntax as .gitignore, with the addition of
# "#!include" directives (which insert the entries of the given .gitignore-style
# file at that point).
#
# For more information, run:
# $ gcloud topic gcloudignore
#
.gcloudignore
# If you would like to upload your .git directory, .gitignore file or files
# from your .gitignore file, remove the corresponding line
# below:
.git
.gitignore
.env.yaml
.prod.env.yaml

View File

@ -0,0 +1 @@
.prod.env.yaml

View File

@ -0,0 +1,41 @@
# Setup table
Create the table using the console:
```
Table name: profile
Columns:
id: Integer auto-increment
name: Text
address: Text
lat: Numeric, Nullable
lng: Numeric, Nullable
```
# Deploy Google Cloud function
Deploy the function:
```bash
gcloud beta functions deploy python-echo \
--runtime python37 \
--trigger-http
```
Get the trigger URL:
```yaml
httpsTrigger:
url: https://us-central1-hasura-test.cloudfunctions.net/python-echo
```
Open Hasura console, goto `Events -> Add Trigger` and create a new trigger:
```
Trigger name: profile_change
Schema/Table: public/profile
Operations: Insert, Update, Delete
Webhook URL: [Trigger URL]
```
Once the trigger is created, goto `Data -> profile -> Insert row` and add a row.

View File

@ -0,0 +1,11 @@
from flask import jsonify
def function(request):
request_json = request.get_json()
op = request_json['event']['op']
data = request_json['event']['data']
name = request_json['table']['name']
schema = request_json['table']['schema']
response = {'message': 'received event', 'data': {op, data, name, schema}}
print(response)
return jsonify(message='received event', data={'op': op, 'data': data, 'name': name, 'schema': schema})