From 9a907c3a8e590b77eed7de63cda1fec788d55f22 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Sat, 16 Jan 2021 19:47:34 +0100 Subject: [PATCH] initial --- .gitignore | 2 + Dockerfile | 42 +++++++++++++++++++++ Objekte.py | 46 +++++++++++++++++++++++ Wohnungen.py | 67 +++++++++++++++++++++++++++++++++ dbpool.py | 28 ++++++++++++++ server.ini | 7 ++++ server.py | 16 ++++++++ swagger.yaml | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 310 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 Objekte.py create mode 100644 Wohnungen.py create mode 100644 dbpool.py create mode 100644 server.ini create mode 100644 server.py create mode 100644 swagger.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f3e41d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +ENV \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..64124ea --- /dev/null +++ b/Dockerfile @@ -0,0 +1,42 @@ +FROM python:latest + +LABEL Maintainer="Wolfgang Hottgenroth wolfgang.hottgenroth@icloud.com" + +ARG APP_DIR="/opt/app" +ARG CONF_DIR="${APP_DIR}/config" + +ENV DB_HOST="172.16.10.18" +ENV DB_NAME="hausverwaltung" +ENV DB_USER="hausverwaltung-ui" +ENV DB_PASS="test123" + + +RUN \ + apt update && \ + apt install -y libmariadbclient-dev && \ + pip3 install mariadb && \ + pip3 install connexion && \ + pip3 install connexion[swagger-ui] && \ + pip3 install uwsgi && \ + pip3 install flask-cors + +RUN \ + mkdir -p ${APP_DIR} && \ + mkdir -p ${CONF_DIR} && \ + useradd -d ${APP_DIR} -u 1000 user + +COPY *.py ${APP_DIR}/ +COPY swagger.yaml ${APP_DIR}/ +COPY server.ini ${CONF_DIR}/ + +USER 1000:1000 +WORKDIR ${APP_DIR} +VOLUME ${CONF_DIR} + +EXPOSE 5000 +EXPOSE 9191 + +CMD [ "uwsgi", "./config/server.ini" ] + + + diff --git a/Objekte.py b/Objekte.py new file mode 100644 index 0000000..af9e19e --- /dev/null +++ b/Objekte.py @@ -0,0 +1,46 @@ +from dbpool import getConnection + +def get_objekte(): + try: + dbh = getConnection() + objekte = [] + cur = dbh.cursor() + cur.execute("SELECT id, shortname, flaeche FROM objekt") + for (id, shortname, flaeche) in cur: + objekte.append({ + "id": id, + "shortname": shortname, + "flaeche": flaeche + }) + return objekte + except Exception as err: + return str(err), 500 + finally: + dbh.close() + + +def get_objekt(id=None): + try: + dbh = getConnection() + cur = dbh.cursor() + cur.execute("SELECT id, shortname, flaeche FROM objekt WHERE id = ?", (id,)) + objekt = None + try: + (id, shortname, flaeche) = cur.next() + objekt = { + "id": id, + "shortname": shortname, + "flaeche": flaeche + } + except StopIteration: + return "Objekt not found", 404 + try: + (id, shortname, flaeche) = cur.next() + return "More than one Objekt by that id ({}, {}, {})".format(id, shortname, flaeche), 500 + except: + pass + return objekt + except Exception as err: + return str(err), 500 + finally: + dbh.close() diff --git a/Wohnungen.py b/Wohnungen.py new file mode 100644 index 0000000..d34a7d2 --- /dev/null +++ b/Wohnungen.py @@ -0,0 +1,67 @@ +from dbpool import getConnection + +def get_wohnungen(): + try: + dbh = getConnection() + wohnungen = [] + cur = dbh.cursor() + cur.execute(""" +SELECT w.id as id, + w.objekt as objekt_id, + w.shortname as wohnung, + w.flaeche as flaeche, + o.shortname as objekt + FROM wohnung w, objekt o + WHERE o.id = w.objekt +""") + for (id, objekt_id, wohnung, flaeche, objekt) in cur: + wohnungen.append({ + "id": id, + "objekt_id": objekt_id, + "wohnung": wohnung, + "flaeche": flaeche, + "objekt": objekt + }) + return wohnungen + except Exception as err: + return str(err), 500 + finally: + dbh.close() + + +def get_wohnung(id=None): + try: + dbh = getConnection() + cur = dbh.cursor() + cur.execute(""" +SELECT w.id as id, + w.objekt as objekt_id, + w.shortname as wohnung, + w.flaeche as flaeche, + o.shortname as objekt + FROM wohnung w, objekt o + WHERE o.id = w.objekt AND + w.id = ? +""", (id, )) + wohnung = None + try: + (id, objekt_id, wohnung_name, flaeche, objekt_name) = cur.next() + wohnung = { + "id": id, + "objekt_id": objekt_id, + "wohnung": wohnung_name, + "flaeche": flaeche, + "objekt": objekt_name + } + except StopIteration: + return "Wohnung not found", 404 + try: + (id, objekt_id, wohnung_name, flaeche, objekt_name) = cur.next() + return "More than one Wohnung by that id ({}, {}, {}, {})".format(id, objekt_name, wohnung_name, flaeche), 500 + except: + pass + return wohnung + except Exception as err: + return str(err), 500 + finally: + dbh.close() diff --git a/dbpool.py b/dbpool.py new file mode 100644 index 0000000..e8feb53 --- /dev/null +++ b/dbpool.py @@ -0,0 +1,28 @@ +import mariadb +import os + +pool = None + +def createConnectionPool(): + global pool + + try: + user = os.environ["DB_USER"] + password = os.environ["DB_PASS"] + host = os.environ["DB_HOST"] + database = os.environ["DB_NAME"] + except KeyError as err: + raise Exception("Database configuration variable {} not available".format(err)) + + pool = mariadb.ConnectionPool( + user = user, + password = password, + host = host, + database = database, + pool_name = 'hv-wep-app', + pool_size = 5 + ) + +def getConnection(): + global pool + return pool.get_connection() diff --git a/server.ini b/server.ini new file mode 100644 index 0000000..81f216b --- /dev/null +++ b/server.ini @@ -0,0 +1,7 @@ +[uwsgi] +http = :5000 +wsgi-file = server.py +processes = 4 +threads = 2 +stats = :9191 + diff --git a/server.py b/server.py new file mode 100644 index 0000000..c6aeb4c --- /dev/null +++ b/server.py @@ -0,0 +1,16 @@ +import connexion +from flask_cors import CORS +from dbpool import createConnectionPool + +# prepare database connections +createConnectionPool() + +# instantiate the webservice +app = connexion.App(__name__) +app.add_api('swagger.yaml') + +# CORSify it - otherwise Angular won't accept it +CORS(app.app) + +# provide the webservice application to uwsgi +application = app.app diff --git a/swagger.yaml b/swagger.yaml new file mode 100644 index 0000000..d5afe02 --- /dev/null +++ b/swagger.yaml @@ -0,0 +1,102 @@ +swagger: '2.0' +info: + title: Hausverwaltung + version: "0.1" + +paths: + /hv/objekte: + get: + tags: [ "Objekte" ] + operationId: Objekte.get_objekte + summary: Returns all Objekte + responses: + 200: + description: Successful response. + schema: + type: array + items: + $ref: '#/definitions/Objekt' + 404: + description: No Objekte available + 500: + description: Some server error + /hv/objekt/{id}: + get: + tags: [ "Objekte" ] + operationId: Objekte.get_objekt + summary: Returns Objekt by id + parameters: + - name: id + in: path + type: integer + required: true + responses: + 200: + description: Successful response. + schema: + $ref: '#/definitions/Objekt' + 404: + description: Objekt not found + 500: + description: Some server error + /hv/wohnungen: + get: + tags: [ "Wohnungen" ] + operationId: Wohnungen.get_wohnungen + summary: Returns all Wohnungen + responses: + 200: + description: Successful response. + schema: + type: array + items: + $ref: '#/definitions/Wohnung' + 404: + description: No Wohnung available + 500: + description: Some server error + /hv/wohnung/{id}: + get: + tags: [ "Wohnungen" ] + operationId: Wohnungen.get_wohnung + summary: Returns Wohnung by id + parameters: + - name: id + in: path + type: integer + required: true + responses: + 200: + description: Successful response. + schema: + $ref: '#/definitions/Wohnung' + 404: + description: Wohnung not found + 500: + description: Some server error + +definitions: + Objekt: + description: Objekt type + type: object + properties: + id: + type: integer + shortname: + type: string + flaeche: + type: number + Wohnung: + description: Wohnung type + type: object + properties: + id: + type: integer + objekt_id: + type: integer + wohnung: + type: string + flaeche: + type: number + objekt: + type: string