Skip to main content

Cloud Function

Een cloud functie is een stuk code dat volledig serverless uitgevoerd wordt. Sinds enige tijd is daarvan een tweede versie beschikbaar. (v2) Dat stukje code kan je ofwel aanbieden in een zip op cloud storage, of rechtstreeks via een repository, zoals wij zullen doen. Bij de opstart van de functie kunnen variabelen meegegeven worden, en configuratie kan gebeuren met omgevingsvariabelen.

De broncode is de volgende: (main.py)

import os

import requests
import json
from google.cloud import bigquery
import logging
import datetime
import time


def stream_to_bq(data, table_id=None):
# Construct a BigQuery client object.
# table_id = "your-project.your_dataset.your_table"

client = bigquery.Client()

errors = client.insert_rows_json(table_id, data) # Make an API request.
if errors == []:
logging.info("new rows added")
else:
logging.error("Encountered errors while inserting rows: {}".format(errors))

def poll(data,context):
table_id = os.getenv("TABLE_ID", "empty_table_id")

api_response = requests.get(
url="https://data.stad.gent/api/records/1.0/search/?dataset=bezetting-parkeergarages-real-time&q=&sort=-occupation&facet=name&facet=lastupdate&facet=description&facet=lichtfestival&facet=lf_pr&facet=b_park")
parking_status = json.loads(api_response.content)

rows = []
for parking in parking_status["records"]:
row = {}
row["timestamp"] = datetime.datetime.fromisoformat(parking['fields']['lastupdate']).timestamp()
row["name"] = parking['fields']['name']
row["id"] = parking["fields"]['id']
row["url"] = parking["fields"]['urllinkaddress']
row["total_capacity"] = int(parking['fields']['totalcapacity'])
row["occupation"] = parking['fields']['occupation']

rows.append(row)
logging.info(rows)
stream_to_bq(rows, table_id=table_id)
return "ok", 200


if __name__ == '__main__':
while (True):
poll("empty request")
time.sleep(60)

In dezelfde map hoort ook een requirements file te staan:

requests
google-cloud-bigquery

De functie zelf heeft genoeg met 128MB Ram, de runtime is python312, en de functie wordt getriggerd met via een topic in pub/sub.

We zullen deze build uitvoeren via het cloud build script in de repository.

Er is ook een omgevingsvariabele nodig: TABLE_ID. Stel die gelijk aan de tabelnaam van je bigquery-tabel. (formaat projectnaam.datasetnaam.tabelnaam)

Tijdens het deployen bots je waarschijnlijk op enkele rechtenproblemen. Los die op via Terraform.

Omdat er een flink aantal parameters van belang zijn, krijg je hieronder een hint van hoe het eindresultaat er kan uitzien:

steps:
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
args:
- gcloud
- functions
- deploy
- poll_function
- --region=europe-west1
- --build-service-account=projects/**********/serviceAccounts/app-build-usr@**********.iam.gserviceaccount.com
- --run-service-account=app-cron-usr@**********.iam.gserviceaccount.com
- --service-account=app-cron-usr@c**********.iam.gserviceaccount.com
- --trigger-service-account=app-cron-usr@**********.iam.gserviceaccount.com
- --source=cf/.
- --trigger-topic=**********
- --entry-point=**********
- --set-env-vars
- TABLE_ID=**********
- --runtime=********

Trigger de build enkele keren manueel en bekijk aandachtig de logs die gegenereerd worden. Pas je configuratie aan tot je een werkend resultaat krijgt, en je een werkende cloud run functie hebt.