From d005f6b9b7306fe7bf98cc99d01e9a2ba9fb35a3 Mon Sep 17 00:00:00 2001 From: Ginger Burns Date: Thu, 31 Oct 2024 16:29:53 +0000 Subject: [PATCH 1/7] chore: ignore logs --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index e2f81da..d39543f 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,5 @@ dist/ api/phenome10k.egg-info/ docker/local.env + +logs/ From fe4a20edfa31b0c90308fbfc37d25d2ffab1404b Mon Sep 17 00:00:00 2001 From: Ginger Burns Date: Thu, 31 Oct 2024 16:32:24 +0000 Subject: [PATCH 2/7] patch: update admin email --- api/phenome10k/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/phenome10k/config.py b/api/phenome10k/config.py index ecbbea3..0a0ebb4 100644 --- a/api/phenome10k/config.py +++ b/api/phenome10k/config.py @@ -24,7 +24,7 @@ class Config(object): MAIL_PORT = os.environ.get('MAIL_PORT', 25) MAIL_USERNAME = os.environ.get('MAIL_USERNAME') MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD') - ADMIN_EMAIL = os.environ.get('ADMIN_EMAIL') or 'alycejenni@gmail.com' + ADMIN_EMAIL = os.environ.get('ADMIN_EMAIL') or 'phenome10k@nhm.ac.uk' LOG_FILE = os.environ.get('LOG_FILE') or 'logs/phenome10k.log' LOG_LEVEL = os.environ.get('LOG_LEVEL', 'WARNING') SERVER_NAME = os.environ.get('SERVER_NAME') or None From db584998d09a38414e99fda072c8667c727439f4 Mon Sep 17 00:00:00 2001 From: Ginger Burns Date: Thu, 31 Oct 2024 17:10:25 +0000 Subject: [PATCH 3/7] chore: sort requirements --- api/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/requirements.txt b/api/requirements.txt index fc6ffbc..04bf5b8 100644 --- a/api/requirements.txt +++ b/api/requirements.txt @@ -11,11 +11,11 @@ Flask==2.0.3 flask-caching==2.3.0 flask-hcaptcha==0.6.0 Flask-Mail==0.9.1 +Flask-Marshmallow==0.14.0 Flask-Migrate==3.1.0 flask-security-too==5.0.1 Flask-SQLAlchemy==2.5.1 Flask-WTF==1.0.1 -Flask-Marshmallow==0.14.0 flower==1.2.0 gunicorn==20.1.0 importlib-metadata==4.11.3 From 298d4c84a04d8ffee2ac033dc866d21dacb1d857 Mon Sep 17 00:00:00 2001 From: Ginger Burns Date: Thu, 31 Oct 2024 17:14:20 +0000 Subject: [PATCH 4/7] chore: update author name --- api/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/pyproject.toml b/api/pyproject.toml index 2c6bba1..d4fd8ab 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -6,7 +6,7 @@ requires-python = ">=3.8" license = { text = "GPL-3.0-or-later" } authors = [ { name = "Paul Kiddle" }, - { name = "Ginger Butcher", email = "phenome10k@nhm.ac.uk" } + { name = "Ginger Burns", email = "phenome10k@nhm.ac.uk" } ] keywords = [] classifiers = [ From f5077f9812026a596e8b95e1c748998d6b5f94d6 Mon Sep 17 00:00:00 2001 From: Josh Humphries Date: Fri, 1 Nov 2024 12:14:29 +0000 Subject: [PATCH 5/7] build: swap from gunicorn to uwsgi We've been having uptime issues with the phenome10k production site and it's unclear exactly what's going on. Changing gunicorn for uwsgi seems to have helped in testing so we're making the change for good. --- ansible/group_vars/all/main.yml | 5 +++-- ansible/playbook.yml | 2 +- ansible/roles/monit/monit/defaults/main.yml | 8 +++---- .../nginx/templates/phenome10k.org.conf.j2 | 2 +- .../templates/phenome10k.org.ssl.conf.j2 | 2 +- ansible/roles/phenome-10k/handlers/main.yml | 4 ++-- ansible/roles/phenome-10k/tasks/app-flask.yml | 21 +++++++++++++------ ansible/roles/phenome-10k/tasks/main.yml | 4 ++-- .../roles/phenome-10k/templates/uwsgi.ini.j2 | 14 +++++++++++++ .../{gunicorn.service.j2 => uwsgi.service.j2} | 2 +- api/requirements.txt | 2 +- 11 files changed, 45 insertions(+), 21 deletions(-) create mode 100644 ansible/roles/phenome-10k/templates/uwsgi.ini.j2 rename ansible/roles/phenome-10k/templates/{gunicorn.service.j2 => uwsgi.service.j2} (54%) diff --git a/ansible/group_vars/all/main.yml b/ansible/group_vars/all/main.yml index fa10192..dae43a1 100644 --- a/ansible/group_vars/all/main.yml +++ b/ansible/group_vars/all/main.yml @@ -79,8 +79,9 @@ flower_broker_api: http://{{ p10k_db_user }}:{{ p10k_db_password|urlencode() }}@ # p10k: flask cache_redis_url: redis://{{ redis_host }}:6379/1 flask_secret_key: G} 60% for 20 cycles diff --git a/ansible/roles/nginx/templates/phenome10k.org.conf.j2 b/ansible/roles/nginx/templates/phenome10k.org.conf.j2 index a4f827d..e315b70 100644 --- a/ansible/roles/nginx/templates/phenome10k.org.conf.j2 +++ b/ansible/roles/nginx/templates/phenome10k.org.conf.j2 @@ -1,5 +1,5 @@ upstream phenome10k { -{% for server in app_servers %} server {{ server }}:{{ gunicorn_port }};{% endfor %} +{% for server in app_servers %} server {{ server }}:{{ uwsgi_port }};{% endfor %} } server { diff --git a/ansible/roles/nginx/templates/phenome10k.org.ssl.conf.j2 b/ansible/roles/nginx/templates/phenome10k.org.ssl.conf.j2 index fc17882..132bc53 100644 --- a/ansible/roles/nginx/templates/phenome10k.org.ssl.conf.j2 +++ b/ansible/roles/nginx/templates/phenome10k.org.ssl.conf.j2 @@ -1,5 +1,5 @@ upstream phenome10k { -{% for server in app_servers %} server {{ server }}:{{ gunicorn_port }};{% endfor %} +{% for server in app_servers %} server {{ server }}:{{ uwsgi_port }};{% endfor %} } server { diff --git a/ansible/roles/phenome-10k/handlers/main.yml b/ansible/roles/phenome-10k/handlers/main.yml index 8e06d50..873d89b 100644 --- a/ansible/roles/phenome-10k/handlers/main.yml +++ b/ansible/roles/phenome-10k/handlers/main.yml @@ -17,9 +17,9 @@ become: true become_user: phenome10k -- name: restart gunicorn +- name: restart uwsgi service: - name: gunicorn + name: uwsgi state: restarted become: true diff --git a/ansible/roles/phenome-10k/tasks/app-flask.yml b/ansible/roles/phenome-10k/tasks/app-flask.yml index 2b945e2..26d372c 100644 --- a/ansible/roles/phenome-10k/tasks/app-flask.yml +++ b/ansible/roles/phenome-10k/tasks/app-flask.yml @@ -55,17 +55,26 @@ become_user: phenome10k run_once: true -- name: Create the gunicorn service +- name: Copy uwsgi.ini config template: - src: gunicorn.service.j2 - dest: /etc/systemd/system/gunicorn.service + src: uwsgi.ini.j2 + dest: '{{ uwsgi_ini }}' + become: true + become_user: phenome10k + notify: + - restart uwsgi + +- name: Create the uwsgi service + template: + src: uwsgi.service.j2 + dest: /etc/systemd/system/uwsgi.service become: true notify: - - restart gunicorn + - restart uwsgi -- name: Enable gunicorn service +- name: Enable uwsgi service systemd: - name: gunicorn.service + name: uwsgi.service state: started enabled: y become: true diff --git a/ansible/roles/phenome-10k/tasks/main.yml b/ansible/roles/phenome-10k/tasks/main.yml index 90107e3..289aced 100644 --- a/ansible/roles/phenome-10k/tasks/main.yml +++ b/ansible/roles/phenome-10k/tasks/main.yml @@ -17,7 +17,7 @@ when: not skip_git_checkout notify: - rebuild front end - - restart gunicorn + - restart uwsgi - restart node tags: - flask @@ -55,7 +55,7 @@ become: true become_user: phenome10k notify: - - restart gunicorn + - restart uwsgi - name: Create log directory file: diff --git a/ansible/roles/phenome-10k/templates/uwsgi.ini.j2 b/ansible/roles/phenome-10k/templates/uwsgi.ini.j2 new file mode 100644 index 0000000..51240fe --- /dev/null +++ b/ansible/roles/phenome-10k/templates/uwsgi.ini.j2 @@ -0,0 +1,14 @@ +[uwsgi] +http = 0.0.0.0:{{ uwsgi_port }} +wsgi-file = api/wsgi.py +callable = app +wsgi-disable-file-wrapper = true +master = true +processes = 3 +threads = 3 +buffer-size = 65535 +stats = 127.0.0.1:9191 +log-5xx = true + +req-logger = file:/var/log/phenome10k/u_access.log +logger = file:/var/log/phenome10k/u_error.log diff --git a/ansible/roles/phenome-10k/templates/gunicorn.service.j2 b/ansible/roles/phenome-10k/templates/uwsgi.service.j2 similarity index 54% rename from ansible/roles/phenome-10k/templates/gunicorn.service.j2 rename to ansible/roles/phenome-10k/templates/uwsgi.service.j2 index ae16f6c..8eee4d3 100644 --- a/ansible/roles/phenome-10k/templates/gunicorn.service.j2 +++ b/ansible/roles/phenome-10k/templates/uwsgi.service.j2 @@ -3,7 +3,7 @@ Description=phenome10k service [Service] Type=simple -ExecStart={{ gunicorn_binary }} --error-logfile /var/log/phenome10k/error.log --access-logfile /var/log/phenome10k/access.log -b 0.0.0.0:{{ gunicorn_port }} -w 9 --timeout 120 api.wsgi:app +ExecStart={{ uwsgi_binary }} --ini {{ uwsgi_ini }} Restart=on-abort WorkingDirectory={{ p10k_src_dir }} User={{ p10k_linux_user }} diff --git a/api/requirements.txt b/api/requirements.txt index fc6ffbc..9f0e207 100644 --- a/api/requirements.txt +++ b/api/requirements.txt @@ -17,7 +17,7 @@ Flask-SQLAlchemy==2.5.1 Flask-WTF==1.0.1 Flask-Marshmallow==0.14.0 flower==1.2.0 -gunicorn==20.1.0 +pyuwsgi==2.0.26 importlib-metadata==4.11.3 marshmallow-sqlalchemy==0.28.0 numpy==1.22.3 From 4fe41ff12f16cb5ebcc704168494109406036688 Mon Sep 17 00:00:00 2001 From: Ginger Burns Date: Fri, 1 Nov 2024 14:26:14 +0000 Subject: [PATCH 6/7] fix: disable strict_slashes by default there shouldn't be any routes that are differentiated by a trailing slash, so this should be fine. this fixes an issue where redirected (308) requests (from path-without-slash to path-with-slash) were not including the session cookie in firefox. Closes: #206 --- api/phenome10k/routes/__init__.py | 1 + api/phenome10k/routes/publications.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/api/phenome10k/routes/__init__.py b/api/phenome10k/routes/__init__.py index 93c0b73..88159f7 100644 --- a/api/phenome10k/routes/__init__.py +++ b/api/phenome10k/routes/__init__.py @@ -15,6 +15,7 @@ def init_routes(app): query.bp, ] + app.url_map.strict_slashes = False app.url_map.converters['scan'] = ScanConverter app.url_map.converters['publication'] = PublicationConverter app.url_map.converters['file'] = FileConverter diff --git a/api/phenome10k/routes/publications.py b/api/phenome10k/routes/publications.py index fb38bec..80377ed 100644 --- a/api/phenome10k/routes/publications.py +++ b/api/phenome10k/routes/publications.py @@ -123,7 +123,7 @@ def manage(page=1): return render_vue(data, title='Manage Publications') -@bp.route('//') +@bp.route('/') def view(pub_object): if not pub_object.published and not ( current_user.is_authenticated and current_user.can_edit(pub_object) From 18e455348f24300cf57775048ec9363ad3c64819 Mon Sep 17 00:00:00 2001 From: Ginger Burns Date: Fri, 1 Nov 2024 16:09:10 +0000 Subject: [PATCH 7/7] fix: ignore booleans in query otherwise this just adds `OR published=true` when looking for scans with a q parameter, and then you get all published scans. Closes: #207 --- api/phenome10k/routes/_utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/phenome10k/routes/_utils.py b/api/phenome10k/routes/_utils.py index d0942c4..fbea739 100644 --- a/api/phenome10k/routes/_utils.py +++ b/api/phenome10k/routes/_utils.py @@ -161,6 +161,8 @@ def search(self, **kwargs): for c in self._columns.values(): try: v = c.type.python_type(r.q) + if type(v) is bool: + continue or_filters.append(c == v) except: continue