This commit is contained in:
parent
fefbb63f67
commit
479ca0f44d
@ -136,4 +136,4 @@ dmypy.json
|
|||||||
.git/
|
.git/
|
||||||
*.yml
|
*.yml
|
||||||
contrib/*
|
contrib/*
|
||||||
postman/*
|
postman/*
|
@ -16,4 +16,4 @@ COPY ./src .
|
|||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|
||||||
ENTRYPOINT ["gunicorn", "-b", "0.0.0.0:8080", "--workers", "1", "--threads", "8", "app:app"]
|
ENTRYPOINT ["gunicorn", "-b", "0.0.0.0:8080", "--workers", "1", "--threads", "1", "app:app"]
|
||||||
|
39
docker-compose.yml
Normal file
39
docker-compose.yml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
networks:
|
||||||
|
rabbitmq:
|
||||||
|
external: false
|
||||||
|
postgres:
|
||||||
|
external: false
|
||||||
|
|
||||||
|
services:
|
||||||
|
test-db:
|
||||||
|
image: postgres:12
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:5432:5432"
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=input-service
|
||||||
|
- POSTGRES_PASSWORD=input-service
|
||||||
|
- POSTGRES_DB=input-service
|
||||||
|
networks:
|
||||||
|
- postgres
|
||||||
|
volumes:
|
||||||
|
- postres-volume:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
rabbitmq:
|
||||||
|
image: "rabbitmq:3"
|
||||||
|
hostname: "test-rabbitmq"
|
||||||
|
environment:
|
||||||
|
RABBITMQ_ERLANG_COOKIE: "akjahsfvbkueasnvfjkhsga"
|
||||||
|
RABBITMQ_DEFAULT_USER: "rabbitmq"
|
||||||
|
RABBITMQ_DEFAULT_PASS: "rabbitmq"
|
||||||
|
RABBITMQ_DEFAULT_VHOST: "/"
|
||||||
|
networks:
|
||||||
|
- rabbitmq
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:15672:15672"
|
||||||
|
- "127.0.0.1:5672:5672"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postres-volume:
|
@ -1,6 +1,5 @@
|
|||||||
sentry_sdk
|
sentry_sdk[flask]
|
||||||
gunicorn
|
gunicorn
|
||||||
marshmallow
|
|
||||||
Flask
|
Flask
|
||||||
Flask-RESTful
|
Flask-RESTful
|
||||||
requests
|
requests
|
||||||
@ -8,5 +7,6 @@ werkzeug
|
|||||||
filetype
|
filetype
|
||||||
sqlalchemy
|
sqlalchemy
|
||||||
flask_sqlalchemy
|
flask_sqlalchemy
|
||||||
rstr
|
xeger
|
||||||
pika
|
pika
|
||||||
|
psycopg2-binary
|
12
src/app.py
12
src/app.py
@ -1,14 +1,14 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import logging
|
import logging
|
||||||
import sentry_sdk
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask_restful import Api
|
from flask_restful import Api
|
||||||
|
import sentry_sdk
|
||||||
from sentry_sdk.integrations.flask import FlaskIntegration
|
from sentry_sdk.integrations.flask import FlaskIntegration
|
||||||
import pika
|
|
||||||
|
|
||||||
|
import rabbitmqqueue
|
||||||
from config import *
|
from config import *
|
||||||
from db import db
|
from db import db
|
||||||
from resources import *
|
from resources import SampleResource, SampleParameterResource
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Main Flask RESTful API
|
Main Flask RESTful API
|
||||||
@ -37,10 +37,6 @@ db.init_app(app)
|
|||||||
with app.app_context():
|
with app.app_context():
|
||||||
db.create_all()
|
db.create_all()
|
||||||
|
|
||||||
rabbitmq = pika.BlockingConnection(pika.ConnectionParameters(host=RABBITMQ_HOST))
|
|
||||||
rabbitmq_channel = rabbitmq.channel()
|
|
||||||
rabbitmq_channel.queue_declare(RABBITMQ_QUEUE)
|
|
||||||
|
|
||||||
formatter = logging.Formatter(
|
formatter = logging.Formatter(
|
||||||
fmt="%(asctime)s - %(levelname)s - %(module)s - %(message)s"
|
fmt="%(asctime)s - %(levelname)s - %(module)s - %(message)s"
|
||||||
)
|
)
|
||||||
@ -53,7 +49,7 @@ logger.setLevel(logging.DEBUG)
|
|||||||
logger.addHandler(handler)
|
logger.addHandler(handler)
|
||||||
|
|
||||||
api.add_resource(SampleResource, "/v1/input/sample")
|
api.add_resource(SampleResource, "/v1/input/sample")
|
||||||
api.add_resource(SampleParameterResource, '/v1/input/sample<str:tag>')
|
api.add_resource(SampleParameterResource, '/v1/input/sample/<tag>')
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run(
|
app.run(
|
||||||
|
@ -18,12 +18,15 @@ DEBUG = os.environ.get("INPUT_SERVICE_DEBUG", True)
|
|||||||
|
|
||||||
|
|
||||||
SENTRY_DSN = os.environ.get("SENTRY_DSN")
|
SENTRY_DSN = os.environ.get("SENTRY_DSN")
|
||||||
RELEASE_ID = os.environ.get("RELEASE_ID")
|
RELEASE_ID = os.environ.get("RELEASE_ID", "test")
|
||||||
RELEASEMODE = os.environ.get("INPUT_SERVICE_RELEASEMODE")
|
RELEASEMODE = os.environ.get("INPUT_SERVICE_RELEASEMODE", "dev")
|
||||||
|
|
||||||
RABBITMQ_HOST = os.getenv("INPUT_RABBITMQ_HOSTNAME", "localhost")
|
RABBITMQ_HOST = os.getenv("INPUT_RABBITMQ_HOSTNAME", "localhost")
|
||||||
RABBITMQ_EXCHANGE = os.getenv("INPUT_RABBITMQ_EXCHANGE", "wave-extract")
|
RABBITMQ_EXCHANGE = os.getenv("INPUT_RABBITMQ_EXCHANGE", "wave-extract")
|
||||||
RABBITMQ_QUEUE = os.getenv("INPUT_RABBITMQ_QUEUE", "wave-extract")
|
RABBITMQ_QUEUE = os.getenv("INPUT_RABBITMQ_QUEUE", "wave-extract")
|
||||||
|
RABBITMQ_USERNAME = os.getenv("INPUT_RABBITMQ_USERNAME", "rabbitmq")
|
||||||
|
RABBITMQ_PASSWORD = os.getenv("INPUT_RABBITMQ_PASSWORD", "rabbitmq")
|
||||||
|
|
||||||
POSTGRES_HOSTNAME = os.getenv("INPUT_POSTGRES_HOSTNAME", "localhost")
|
POSTGRES_HOSTNAME = os.getenv("INPUT_POSTGRES_HOSTNAME", "localhost")
|
||||||
POSTGRES_USERNAME = os.getenv("INPUT_POSTGRES_USERNAME", "input-service")
|
POSTGRES_USERNAME = os.getenv("INPUT_POSTGRES_USERNAME", "input-service")
|
||||||
POSTGRES_PASSWORD = os.getenv("INPUT_POSTGRES_PASSWORD", "input-service")
|
POSTGRES_PASSWORD = os.getenv("INPUT_POSTGRES_PASSWORD", "input-service")
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import db
|
from db import db
|
||||||
from sqlalchemy.sql import func
|
from sqlalchemy.sql import func
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
18
src/rabbitmqqueue.py
Normal file
18
src/rabbitmqqueue.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import pika
|
||||||
|
from config import *
|
||||||
|
|
||||||
|
"""
|
||||||
|
Rabbitmq setup
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = '@tormakris'
|
||||||
|
__copyright__ = "Copyright 2020, Birbnetes Team"
|
||||||
|
__module_name__ = "endpoints"
|
||||||
|
__version__text__ = "1"
|
||||||
|
|
||||||
|
credentials = pika.PlainCredentials(RABBITMQ_USERNAME, RABBITMQ_PASSWORD)
|
||||||
|
rabbitmq = pika.BlockingConnection(pika.ConnectionParameters(host=RABBITMQ_HOST,credentials=credentials))
|
||||||
|
rabbitmq_channel = rabbitmq.channel()
|
||||||
|
rabbitmq_channel.queue_declare(RABBITMQ_QUEUE)
|
@ -1,15 +1,13 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from app import rabbitmq_channel
|
|
||||||
import logging
|
import logging
|
||||||
import json
|
from xeger import Xeger
|
||||||
import rstr
|
from flask_restful import Resource
|
||||||
from flask_restful import Resource, reqparse
|
from flask import request
|
||||||
from werkzeug.datastructures import FileStorage
|
|
||||||
import requests
|
import requests
|
||||||
import filetype
|
import filetype
|
||||||
from db import db
|
from db import db
|
||||||
from models import SampleMetadata
|
from models import SampleMetadata
|
||||||
from schemas import *
|
from rabbitmqqueue import rabbitmq_channel
|
||||||
from config import *
|
from config import *
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -35,35 +33,33 @@ class SampleResource(Resource):
|
|||||||
Post request send to the endpoint
|
Post request send to the endpoint
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
parse = reqparse.RequestParser()
|
if 'file' not in request.files:
|
||||||
parse.add_argument('soundFile', type=FileStorage, location='soundFile')
|
return {"status": "error", "message": "no file found"}, 469
|
||||||
parse.add_argument('description', type=str, location='description')
|
else:
|
||||||
args = parse.parse_args()
|
soundfile = request.files['file']
|
||||||
soundFile = args['soundFile']
|
|
||||||
description = args['description']
|
if 'date' not in request.form:
|
||||||
kind = filetype.guess(soundFile)
|
return {"status": "error", "message": "no date found"}, 470
|
||||||
if kind.mime != 'wav':
|
else:
|
||||||
|
date = request.form.get("date")
|
||||||
|
|
||||||
|
if 'device_id' not in request.form:
|
||||||
|
return {"status": "error", "message": "no device_id found"}, 471
|
||||||
|
else:
|
||||||
|
device_id = request.form.get("device_id")
|
||||||
|
|
||||||
|
kind = filetype.guess(soundfile)
|
||||||
|
if kind is None or kind.mime != 'wav':
|
||||||
LOGGER.error(
|
LOGGER.error(
|
||||||
"Input file was not WAV. Recieved metadata: {}",
|
f"Input file was not WAV. Recieved metadata: device_id: {device_id}")
|
||||||
description)
|
|
||||||
return {'status': 'error', 'message': 'Input file not WAV.'}, 415
|
return {'status': 'error', 'message': 'Input file not WAV.'}, 415
|
||||||
try:
|
|
||||||
desc = json.loads(description)
|
xeger = Xeger(limit=32)
|
||||||
except Exception as e:
|
generated_tag = xeger.xeger(r'^[a-zA-Z]+[0-9a-zA-Z_]*$')
|
||||||
LOGGER.exception(e)
|
|
||||||
return {'status': 'error',
|
|
||||||
'message': 'Input JSON could not be parsed'}, 400
|
|
||||||
validate_errors = SampleSchema().validate(desc)
|
|
||||||
if validate_errors:
|
|
||||||
LOGGER.error(
|
|
||||||
"Input JSON did not conform to schema. It was: {}", desc)
|
|
||||||
return {'status': 'error',
|
|
||||||
'message': 'Input JSON schema invalid'}, 417
|
|
||||||
generated_tag = rstr.xeger(r'^[a-zA-Z]+[0-9a-zA-Z_]*$', 2, 32)
|
|
||||||
|
|
||||||
record = SampleMetadata(
|
record = SampleMetadata(
|
||||||
device_id=desc['device_id'],
|
device_id=device_id,
|
||||||
device_date=desc['date'],
|
device_date=date,
|
||||||
tag=generated_tag)
|
tag=generated_tag)
|
||||||
try:
|
try:
|
||||||
db.session.add(record)
|
db.session.add(record)
|
||||||
@ -73,7 +69,7 @@ class SampleResource(Resource):
|
|||||||
'tag': (None, generated_tag),
|
'tag': (None, generated_tag),
|
||||||
'file': (
|
'file': (
|
||||||
'wave.wav',
|
'wave.wav',
|
||||||
soundFile,
|
soundfile,
|
||||||
kind.mime)})
|
kind.mime)})
|
||||||
rabbitmq_channel.basic_publish(
|
rabbitmq_channel.basic_publish(
|
||||||
exchange=RABBITMQ_EXCHANGE,
|
exchange=RABBITMQ_EXCHANGE,
|
||||||
@ -93,7 +89,7 @@ class SampleResource(Resource):
|
|||||||
Get all stored items
|
Get all stored items
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
samples = SampleMetadata.query.get.all()
|
samples = SampleMetadata.query.all()
|
||||||
return {"status": "ok", "message": samples}, 200
|
return {"status": "ok", "message": samples}, 200
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
from marshmallow import Schema, fields
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
Schemas of input objects
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
__author__ = "@tormakris"
|
|
||||||
__copyright__ = "Copyright 2020, Birbnetes Team"
|
|
||||||
__module_name__ = "schemas"
|
|
||||||
__version__text__ = "1"
|
|
||||||
|
|
||||||
|
|
||||||
class SampleSchema(Schema):
|
|
||||||
""" /v1/email/pay - POST
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
- date (date)
|
|
||||||
- device_id (str)
|
|
||||||
"""
|
|
||||||
|
|
||||||
date = fields.Date(required=True)
|
|
||||||
device_id = fields.Str(required=True)
|
|
Loading…
Reference in New Issue
Block a user