From 58d7de6073b20f03b0d3fa3dbf4bf1316f218d9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=BCleki=20F=C3=A1bi=C3=A1n?= Date: Fri, 8 May 2020 19:34:29 +0200 Subject: [PATCH 01/13] updated redis structure --- consumer_api/views/sync_view.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/consumer_api/views/sync_view.py b/consumer_api/views/sync_view.py index a6f8eb5..1b034f1 100644 --- a/consumer_api/views/sync_view.py +++ b/consumer_api/views/sync_view.py @@ -1,4 +1,5 @@ import json +import time from flask import request, current_app, jsonify from flask_classful import FlaskView from db import redis_client # ez nagyon otvar @@ -10,20 +11,25 @@ class SyncView(FlaskView): remote_uuid = request.json['uuid'] remote_ip = request.remote_addr - consumer_list = json.loads((redis_client.get("consumer_list") or b"{}").decode('utf-8')) + cust_key = f"customer_{remote_uuid}" - # Log something about it - if remote_uuid not in consumer_list.keys(): + last_known_info = json.loads((redis_client.get("cust_key") or b"{}").decode('utf-8')) + + if not last_known_info: current_app.logger.info(f"New consumer registered (unknown UUID): {remote_uuid} at {remote_ip}") - else: # known - if consumer_list[remote_uuid]['ip'] != remote_ip: + + else: + if last_known_info['ip'] != remote_ip: current_app.logger.info(f"Address of consumer {remote_uuid} changed to {remote_ip}") - consumer_list.update( - {remote_uuid: {"ip": remote_ip}} - ) + info = { + "uuid": remote_uuid, + "ip": remote_ip, + "last_seen": time.time() + } - redis_client.set("consumer_list", json.dumps(consumer_list).encode('utf-8')) + redis_client.set(cust_key, json.dumps(info).encode('utf-8')) + redis_client.expire(cust_key, 30) response = { "uuid": current_app.config['LOCAL_UUID'] From eb034743923248e10e18f39ff9777701ed7f5da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=BCleki=20F=C3=A1bi=C3=A1n?= Date: Fri, 8 May 2020 19:44:42 +0200 Subject: [PATCH 02/13] Configure timeouts from envvar --- consumer_api/app.py | 2 ++ consumer_api/views/log_view.py | 2 +- consumer_api/views/sync_view.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/consumer_api/app.py b/consumer_api/app.py index dbedea3..3f5282f 100644 --- a/consumer_api/app.py +++ b/consumer_api/app.py @@ -19,6 +19,8 @@ sentry_sdk.init("https://0a106e104e114bc9a3fa47f9cb0db2f4@sentry.kmlabz.com/10") app = Flask(__name__) app.config['REDIS_URL'] = os.environ['REDIS_URL'] app.config['LOCAL_UUID'] = os.environ['LOCAL_UUID'] +app.config['CUSTOMER_TIMEOUT'] = int(os.environ.get('CUSTOMER_TIMEOUT', 30)) +app.config['PRODUCER_TIMEOUT'] = int(os.environ.get('PRODUCER_TIMEOUT', 60)) redis_client.init_app(app) diff --git a/consumer_api/views/log_view.py b/consumer_api/views/log_view.py index d2a4d15..2ebf4ff 100644 --- a/consumer_api/views/log_view.py +++ b/consumer_api/views/log_view.py @@ -23,7 +23,7 @@ class LogView(FlaskView): # update expirity redis_client.set(prod_key, remote_ip.encode('utf-8')) - redis_client.expire(prod_key, 240) + redis_client.expire(prod_key, current_app.config["PRODUCER_TIMEOUT"]) # print out message current_app.logger.info(f"New message: {request.json['message']}") diff --git a/consumer_api/views/sync_view.py b/consumer_api/views/sync_view.py index 1b034f1..071da44 100644 --- a/consumer_api/views/sync_view.py +++ b/consumer_api/views/sync_view.py @@ -29,7 +29,7 @@ class SyncView(FlaskView): } redis_client.set(cust_key, json.dumps(info).encode('utf-8')) - redis_client.expire(cust_key, 30) + redis_client.expire(cust_key, current_app.config["CUSTOMER_TIMEOUT"]) response = { "uuid": current_app.config['LOCAL_UUID'] From 67d71fa43ec34edf8143d04f3a00fb64a624c8bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=BCleki=20F=C3=A1bi=C3=A1n?= Date: Fri, 8 May 2020 19:48:31 +0200 Subject: [PATCH 03/13] Fixed customers endpoint --- consumer_api/views/consumers_view.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/consumer_api/views/consumers_view.py b/consumer_api/views/consumers_view.py index 0582bc4..ead5288 100644 --- a/consumer_api/views/consumers_view.py +++ b/consumer_api/views/consumers_view.py @@ -8,6 +8,13 @@ from flask_classful import FlaskView class ConsumersView(FlaskView): def get(self): - consumer_list = json.loads((redis_client.get("consumer_list") or b"{}").decode('utf-8')) - current_app.logger.warning(jsonify([v['ip'] for k, v in consumer_list.items()])) - return jsonify([v['ip'] for k, v in consumer_list.items()]) + + keys = redis_client.keys('producer_*') + + list_of_customer_ips = [] + + for key in keys: + info = json.loads((redis_client.get(key) or b"{}").decode('utf-8')) + list_of_customer_ips.append(info['ip']) + + return jsonify(list_of_customer_ips) From d34756d9fc12e3db3093de656863a4cef88fb6e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=BCleki=20F=C3=A1bi=C3=A1n?= Date: Fri, 8 May 2020 19:56:09 +0200 Subject: [PATCH 04/13] fixed getting customer instead of producer --- consumer_api/views/consumers_view.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consumer_api/views/consumers_view.py b/consumer_api/views/consumers_view.py index ead5288..097c42d 100644 --- a/consumer_api/views/consumers_view.py +++ b/consumer_api/views/consumers_view.py @@ -9,7 +9,7 @@ class ConsumersView(FlaskView): def get(self): - keys = redis_client.keys('producer_*') + keys = redis_client.keys('consumer_*') list_of_customer_ips = [] From 7fbd62659d3370fa74ddbf23d69474525777e06a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=BCleki=20F=C3=A1bi=C3=A1n?= Date: Fri, 8 May 2020 19:57:42 +0200 Subject: [PATCH 05/13] sync view fix --- consumer_api/views/sync_view.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/consumer_api/views/sync_view.py b/consumer_api/views/sync_view.py index 071da44..e0dc13a 100644 --- a/consumer_api/views/sync_view.py +++ b/consumer_api/views/sync_view.py @@ -11,9 +11,9 @@ class SyncView(FlaskView): remote_uuid = request.json['uuid'] remote_ip = request.remote_addr - cust_key = f"customer_{remote_uuid}" + cust_key = f"consumer_{remote_uuid}" - last_known_info = json.loads((redis_client.get("cust_key") or b"{}").decode('utf-8')) + last_known_info = json.loads((redis_client.get(cust_key) or b"{}").decode('utf-8')) if not last_known_info: current_app.logger.info(f"New consumer registered (unknown UUID): {remote_uuid} at {remote_ip}") From d6b8c528de842b550aca66fbed8dc9390e70d009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=BCleki=20F=C3=A1bi=C3=A1n?= Date: Fri, 8 May 2020 20:08:43 +0200 Subject: [PATCH 06/13] fixed sentry stuff --- consumer_api/app.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/consumer_api/app.py b/consumer_api/app.py index 3f5282f..e2829ac 100644 --- a/consumer_api/app.py +++ b/consumer_api/app.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 import sentry_sdk +from sentry_sdk.integrations.flask import FlaskIntegration from flask import Flask import os from db import redis_client @@ -14,7 +15,17 @@ __copyright__ = "Copyright 2020, GoldenPogácsa Team" __module_name__ = "app" __version__text__ = "1" -sentry_sdk.init("https://0a106e104e114bc9a3fa47f9cb0db2f4@sentry.kmlabz.com/10") +# Setup sentry +SENTRY_DSN = os.environ.get("SENTRY_DSN") +if SENTRY_DSN: + sentry_sdk.init( + dsn=SENTRY_DSN, + integrations=[FlaskIntegration()], + send_default_pii=True, + release=os.environ.get('RELEASE_ID', 'test'), + environment=os.environ.get('RELEASEMODE', 'dev') + ) + app = Flask(__name__) app.config['REDIS_URL'] = os.environ['REDIS_URL'] From f643b91a8b906a3e643ba73045b85ae72e34a2b1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 8 May 2020 20:36:45 +0200 Subject: [PATCH 07/13] test_initial_commit --- consumer_api/tests/__init__.py | 6 +++++ consumer_api/tests/consumers_view_test.py | 29 +++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 consumer_api/tests/__init__.py create mode 100644 consumer_api/tests/consumers_view_test.py diff --git a/consumer_api/tests/__init__.py b/consumer_api/tests/__init__.py new file mode 100644 index 0000000..883d9c7 --- /dev/null +++ b/consumer_api/tests/__init__.py @@ -0,0 +1,6 @@ +import os + +# Setup environment variables for testing +os.environ["INITIAL_SERVERS"] = "192.168.111.22" +os.environ["LOCAL_UUID"] = "d8b2e5e2-f675-4194-9324-af58e4b70c54" +os.environ["REDIS_URL"] = "redis://192.168.111.121/0" diff --git a/consumer_api/tests/consumers_view_test.py b/consumer_api/tests/consumers_view_test.py new file mode 100644 index 0000000..f713074 --- /dev/null +++ b/consumer_api/tests/consumers_view_test.py @@ -0,0 +1,29 @@ +import pytest + +from flask import current_app + + +@pytest.fixture +def client(): + current_app.config["TESTING"] = True + + with current_app.test_client() as client: + yield client + + +def test_access_denied(client): + r = client.get('/api/user') + + assert r.status_code == 401 + + +def test_access_denied2(client): + r = client.get('/api/user', headers = { "Authorization": "invalidkey" }) + + assert r.status_code == 401 + + +def test_empty_database(client): + r = client.get('/api/user', headers = { "Authorization": "testkey" }) + + assert len(r.json) == 0 From c58b6449aa26590f3f144fcd626c34cc1b767c5d Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 8 May 2020 20:55:47 +0200 Subject: [PATCH 08/13] tests definded --- consumer_api/tests/consumers_view_test.py | 25 +++-------------------- consumer_api/tests/log_view_test.py | 13 ++++++++++++ 2 files changed, 16 insertions(+), 22 deletions(-) create mode 100644 consumer_api/tests/log_view_test.py diff --git a/consumer_api/tests/consumers_view_test.py b/consumer_api/tests/consumers_view_test.py index f713074..2a65149 100644 --- a/consumer_api/tests/consumers_view_test.py +++ b/consumer_api/tests/consumers_view_test.py @@ -4,26 +4,7 @@ from flask import current_app @pytest.fixture -def client(): - current_app.config["TESTING"] = True +def test_response_length(client): + r = client.get('/log') - with current_app.test_client() as client: - yield client - - -def test_access_denied(client): - r = client.get('/api/user') - - assert r.status_code == 401 - - -def test_access_denied2(client): - r = client.get('/api/user', headers = { "Authorization": "invalidkey" }) - - assert r.status_code == 401 - - -def test_empty_database(client): - r = client.get('/api/user', headers = { "Authorization": "testkey" }) - - assert len(r.json) == 0 + assert len(r) == 0 diff --git a/consumer_api/tests/log_view_test.py b/consumer_api/tests/log_view_test.py new file mode 100644 index 0000000..934b210 --- /dev/null +++ b/consumer_api/tests/log_view_test.py @@ -0,0 +1,13 @@ +import pytest + +from flask import current_app + + +@pytest.fixture + +def test_log_code(client): + r = client.get('/log') + + assert r.status_code == 204 + + From 22275549771e79ad36b8858a2e18ab3613a677c3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 8 May 2020 21:02:49 +0200 Subject: [PATCH 09/13] backup --- consumer_api/tests/consumers_view_test.py | 8 +++++++- consumer_api/tests/log_view_test.py | 12 +++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/consumer_api/tests/consumers_view_test.py b/consumer_api/tests/consumers_view_test.py index 2a65149..fc1a9be 100644 --- a/consumer_api/tests/consumers_view_test.py +++ b/consumer_api/tests/consumers_view_test.py @@ -4,7 +4,13 @@ from flask import current_app @pytest.fixture +def client(): + current_app.config['TESTING'] = True + + with current_app.test_client() as client: + yield + def test_response_length(client): - r = client.get('/log') + r = client.post('/log') assert len(r) == 0 diff --git a/consumer_api/tests/log_view_test.py b/consumer_api/tests/log_view_test.py index 934b210..f102664 100644 --- a/consumer_api/tests/log_view_test.py +++ b/consumer_api/tests/log_view_test.py @@ -4,8 +4,18 @@ from flask import current_app @pytest.fixture +def client(): + current_app.config['TESTING'] = True -def test_log_code(client): + with current_app.test_client() as client: + yield + +def test_log_code_get(client): + r = client.get('/log') + + assert r.status_code == 405 + +def test_log_code_post(client): r = client.get('/log') assert r.status_code == 204 From 6ead97eee05914802c4370f9fc70aaf730d45a52 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 8 May 2020 21:03:40 +0200 Subject: [PATCH 10/13] minor fix --- consumer_api/tests/consumers_view_test.py | 2 +- consumer_api/tests/log_view_test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/consumer_api/tests/consumers_view_test.py b/consumer_api/tests/consumers_view_test.py index fc1a9be..7d8c8ea 100644 --- a/consumer_api/tests/consumers_view_test.py +++ b/consumer_api/tests/consumers_view_test.py @@ -8,7 +8,7 @@ def client(): current_app.config['TESTING'] = True with current_app.test_client() as client: - yield + yield client def test_response_length(client): r = client.post('/log') diff --git a/consumer_api/tests/log_view_test.py b/consumer_api/tests/log_view_test.py index f102664..2b619b9 100644 --- a/consumer_api/tests/log_view_test.py +++ b/consumer_api/tests/log_view_test.py @@ -8,7 +8,7 @@ def client(): current_app.config['TESTING'] = True with current_app.test_client() as client: - yield + yield client def test_log_code_get(client): r = client.get('/log') From 9fec4e81cc8ddcc76b11caee307fcd77da142879 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 8 May 2020 21:04:13 +0200 Subject: [PATCH 11/13] minor --- consumer_api/app.py | 15 +++++++-------- consumer_api/tests/consumers_view_test.py | 1 + consumer_api/views/consumers_view.py | 1 - consumer_api/views/log_view.py | 5 +++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/consumer_api/app.py b/consumer_api/app.py index e2829ac..097178d 100644 --- a/consumer_api/app.py +++ b/consumer_api/app.py @@ -19,14 +19,13 @@ __version__text__ = "1" SENTRY_DSN = os.environ.get("SENTRY_DSN") if SENTRY_DSN: sentry_sdk.init( - dsn=SENTRY_DSN, - integrations=[FlaskIntegration()], - send_default_pii=True, - release=os.environ.get('RELEASE_ID', 'test'), - environment=os.environ.get('RELEASEMODE', 'dev') + dsn = SENTRY_DSN, + integrations = [FlaskIntegration()], + send_default_pii = True, + release = os.environ.get('RELEASE_ID', 'test'), + environment = os.environ.get('RELEASEMODE', 'dev') ) - app = Flask(__name__) app.config['REDIS_URL'] = os.environ['REDIS_URL'] app.config['LOCAL_UUID'] = os.environ['LOCAL_UUID'] @@ -36,7 +35,7 @@ app.config['PRODUCER_TIMEOUT'] = int(os.environ.get('PRODUCER_TIMEOUT', 60)) redis_client.init_app(app) for view in [ConsumersView, LogView, SyncView]: - view.register(app, trailing_slash=False) + view.register(app, trailing_slash = False) if __name__ == "__main__": - app.run(debug=True) + app.run(debug = True) diff --git a/consumer_api/tests/consumers_view_test.py b/consumer_api/tests/consumers_view_test.py index 7d8c8ea..9a80230 100644 --- a/consumer_api/tests/consumers_view_test.py +++ b/consumer_api/tests/consumers_view_test.py @@ -10,6 +10,7 @@ def client(): with current_app.test_client() as client: yield client + def test_response_length(client): r = client.post('/log') diff --git a/consumer_api/views/consumers_view.py b/consumer_api/views/consumers_view.py index 097c42d..cba9382 100644 --- a/consumer_api/views/consumers_view.py +++ b/consumer_api/views/consumers_view.py @@ -8,7 +8,6 @@ from flask_classful import FlaskView class ConsumersView(FlaskView): def get(self): - keys = redis_client.keys('consumer_*') list_of_customer_ips = [] diff --git a/consumer_api/views/log_view.py b/consumer_api/views/log_view.py index 2ebf4ff..206be0d 100644 --- a/consumer_api/views/log_view.py +++ b/consumer_api/views/log_view.py @@ -19,7 +19,8 @@ class LogView(FlaskView): if not last_known_remote_ip: current_app.logger.info(f"New producer {remote_uuid} at {remote_ip}") elif last_known_remote_ip != remote_ip: - current_app.logger.info(f"IP address of producer {remote_uuid} have changed: {last_known_remote_ip} -> {remote_ip}") + current_app.logger.info( + f"IP address of producer {remote_uuid} have changed: {last_known_remote_ip} -> {remote_ip}") # update expirity redis_client.set(prod_key, remote_ip.encode('utf-8')) @@ -28,4 +29,4 @@ class LogView(FlaskView): # print out message current_app.logger.info(f"New message: {request.json['message']}") - return Response(status=204) + return Response(status = 204) From 2c5444a24553664d33eeaed9b4692723915d2ede Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 8 May 2020 21:08:37 +0200 Subject: [PATCH 12/13] post --- consumer_api/tests/log_view_test.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/consumer_api/tests/log_view_test.py b/consumer_api/tests/log_view_test.py index 2b619b9..195be38 100644 --- a/consumer_api/tests/log_view_test.py +++ b/consumer_api/tests/log_view_test.py @@ -1,3 +1,6 @@ +import json +import os + import pytest from flask import current_app @@ -10,14 +13,18 @@ def client(): with current_app.test_client() as client: yield client + def test_log_code_get(client): r = client.get('/log') assert r.status_code == 405 + def test_log_code_post(client): - r = client.get('/log') + data = { + "uuid": os.environ["LOCAL_UUID"], + "message": "Hello There!" + } + r = client.post('/log', data = json.dumps(data)) assert r.status_code == 204 - - From 7a565e0511dcc9deabe9ddcdf36788697074baec Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 8 May 2020 21:25:18 +0200 Subject: [PATCH 13/13] Fixed consumer test --- consumer_api/tests/consumers_view_test.py | 2 +- consumer_api/tests/sync_view_test.py | 30 +++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 consumer_api/tests/sync_view_test.py diff --git a/consumer_api/tests/consumers_view_test.py b/consumer_api/tests/consumers_view_test.py index 9a80230..dbb1b3d 100644 --- a/consumer_api/tests/consumers_view_test.py +++ b/consumer_api/tests/consumers_view_test.py @@ -12,6 +12,6 @@ def client(): def test_response_length(client): - r = client.post('/log') + r = client.get('/consumers') assert len(r) == 0 diff --git a/consumer_api/tests/sync_view_test.py b/consumer_api/tests/sync_view_test.py new file mode 100644 index 0000000..a7839f0 --- /dev/null +++ b/consumer_api/tests/sync_view_test.py @@ -0,0 +1,30 @@ +import json +import os + +import pytest + +from flask import current_app + + +@pytest.fixture +def client(): + current_app.config['TESTING'] = True + + with current_app.test_client() as client: + yield client + + +def test_log_code_get(client): + r = client.get('/sync') + + assert r.status_code == 405 + + +def test_log_code_post(client): + data = { + "uuid": os.environ["LOCAL_UUID"], + "message": "Hello There!" + } + r = client.post('/sync', data = json.dumps(data)) + + assert r.status_code == 204