From b2e7b474ff1b051ef0a0b9b82fe39c6faad5c717 Mon Sep 17 00:00:00 2001 From: Christine Banek Date: Mon, 26 Oct 2020 14:33:08 -0700 Subject: [PATCH 01/46] Allow options_from_form to be configurable --- jupyterhub/spawner.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/jupyterhub/spawner.py b/jupyterhub/spawner.py index ad07fa44..6389c1d0 100644 --- a/jupyterhub/spawner.py +++ b/jupyterhub/spawner.py @@ -354,8 +354,9 @@ class Spawner(LoggingConfigurable): return options_form - def options_from_form(self, form_data): - """Interpret HTTP form data + options_from_form = Callable( + help=""" + Interpret HTTP form data Form data will always arrive as a dict of lists of strings. Override this function to understand single-values, numbers, etc. @@ -379,7 +380,14 @@ class Spawner(LoggingConfigurable): (with additional support for bytes in case of uploaded file data), and any non-bytes non-jsonable values will be replaced with None if the user_options are re-used. - """ + """, + ).tag(config=True) + + @default("options_from_form") + def _options_from_form(self): + return self._default_options_from_form + + def _default_options_from_form(self, form_data): return form_data def options_from_query(self, query_data): From 2bef5ba9814d4bc1bb44cd9d661702161d7cebb8 Mon Sep 17 00:00:00 2001 From: agp8x Date: Wed, 4 Nov 2020 13:54:31 +0100 Subject: [PATCH 02/46] Add prefix to prometheus metrics to group all jupyter metrics (see #1585) --- jupyterhub/metrics.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/jupyterhub/metrics.py b/jupyterhub/metrics.py index 2bb9013b..a164ec50 100644 --- a/jupyterhub/metrics.py +++ b/jupyterhub/metrics.py @@ -3,9 +3,9 @@ Prometheus metrics exported by JupyterHub Read https://prometheus.io/docs/practices/naming/ for naming conventions for metrics & labels. We generally prefer naming them -`__`. So a histogram that's tracking +`jupyter___`. So a histogram that's tracking the duration (in seconds) of servers spawning would be called -SERVER_SPAWN_DURATION_SECONDS. +JUPYTER_SERVER_SPAWN_DURATION_SECONDS. We also create an Enum for each 'status' type label in every metric we collect. This is to make sure that the metrics exist regardless @@ -21,13 +21,13 @@ from prometheus_client import Gauge from prometheus_client import Histogram REQUEST_DURATION_SECONDS = Histogram( - 'request_duration_seconds', + 'jupyter_request_duration_seconds', 'request duration for all HTTP requests', ['method', 'handler', 'code'], ) SERVER_SPAWN_DURATION_SECONDS = Histogram( - 'server_spawn_duration_seconds', + 'jupyter_server_spawn_duration_seconds', 'time taken for server spawning operation', ['status'], # Use custom bucket sizes, since the default bucket ranges @@ -36,25 +36,25 @@ SERVER_SPAWN_DURATION_SECONDS = Histogram( ) RUNNING_SERVERS = Gauge( - 'running_servers', 'the number of user servers currently running' + 'jupyter_running_servers', 'the number of user servers currently running' ) -TOTAL_USERS = Gauge('total_users', 'total number of users') +TOTAL_USERS = Gauge('jupyter_total_users', 'total number of users') CHECK_ROUTES_DURATION_SECONDS = Histogram( - 'check_routes_duration_seconds', 'Time taken to validate all routes in proxy' + 'jupyter_check_routes_duration_seconds', 'Time taken to validate all routes in proxy' ) HUB_STARTUP_DURATION_SECONDS = Histogram( - 'hub_startup_duration_seconds', 'Time taken for Hub to start' + 'jupyter_hub_startup_duration_seconds', 'Time taken for Hub to start' ) INIT_SPAWNERS_DURATION_SECONDS = Histogram( - 'init_spawners_duration_seconds', 'Time taken for spawners to initialize' + 'jupyter_init_spawners_duration_seconds', 'Time taken for spawners to initialize' ) PROXY_POLL_DURATION_SECONDS = Histogram( - 'proxy_poll_duration_seconds', 'duration for polling all routes from proxy' + 'jupyter_proxy_poll_duration_seconds', 'duration for polling all routes from proxy' ) @@ -79,7 +79,7 @@ for s in ServerSpawnStatus: PROXY_ADD_DURATION_SECONDS = Histogram( - 'proxy_add_duration_seconds', 'duration for adding user routes to proxy', ['status'] + 'jupyter_proxy_add_duration_seconds', 'duration for adding user routes to proxy', ['status'] ) @@ -100,7 +100,7 @@ for s in ProxyAddStatus: SERVER_POLL_DURATION_SECONDS = Histogram( - 'server_poll_duration_seconds', + 'jupyter_server_poll_duration_seconds', 'time taken to poll if server is running', ['status'], ) @@ -127,7 +127,7 @@ for s in ServerPollStatus: SERVER_STOP_DURATION_SECONDS = Histogram( - 'server_stop_seconds', 'time taken for server stopping operation', ['status'] + 'jupyter_server_stop_seconds', 'time taken for server stopping operation', ['status'] ) @@ -148,7 +148,7 @@ for s in ServerStopStatus: PROXY_DELETE_DURATION_SECONDS = Histogram( - 'proxy_delete_duration_seconds', + 'jupyter_proxy_delete_duration_seconds', 'duration for deleting user routes from proxy', ['status'], ) From 9657430cacab210bdc69ea3aa5eec8185302a3a3 Mon Sep 17 00:00:00 2001 From: Mohammad Wasil Date: Wed, 4 Nov 2020 17:59:28 +0100 Subject: [PATCH 03/46] Fix reverse proxy redirect from https --- docs/source/reference/config-proxy.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/reference/config-proxy.md b/docs/source/reference/config-proxy.md index cd56025c..181ebf41 100644 --- a/docs/source/reference/config-proxy.md +++ b/docs/source/reference/config-proxy.md @@ -86,6 +86,7 @@ server { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; + proxy_set_header X-Scheme $scheme; proxy_buffering off; } From af09bc547af8161d287df520bb3a3df00d39aa26 Mon Sep 17 00:00:00 2001 From: agp8x Date: Tue, 17 Nov 2020 15:29:37 +0100 Subject: [PATCH 04/46] change metric prefix to jupyterhub --- jupyterhub/metrics.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/jupyterhub/metrics.py b/jupyterhub/metrics.py index a164ec50..68aeb884 100644 --- a/jupyterhub/metrics.py +++ b/jupyterhub/metrics.py @@ -3,9 +3,9 @@ Prometheus metrics exported by JupyterHub Read https://prometheus.io/docs/practices/naming/ for naming conventions for metrics & labels. We generally prefer naming them -`jupyter___`. So a histogram that's tracking +`jupyterhub___`. So a histogram that's tracking the duration (in seconds) of servers spawning would be called -JUPYTER_SERVER_SPAWN_DURATION_SECONDS. +jupyterhub_SERVER_SPAWN_DURATION_SECONDS. We also create an Enum for each 'status' type label in every metric we collect. This is to make sure that the metrics exist regardless @@ -21,13 +21,13 @@ from prometheus_client import Gauge from prometheus_client import Histogram REQUEST_DURATION_SECONDS = Histogram( - 'jupyter_request_duration_seconds', + 'jupyterhub_request_duration_seconds', 'request duration for all HTTP requests', ['method', 'handler', 'code'], ) SERVER_SPAWN_DURATION_SECONDS = Histogram( - 'jupyter_server_spawn_duration_seconds', + 'jupyterhub_server_spawn_duration_seconds', 'time taken for server spawning operation', ['status'], # Use custom bucket sizes, since the default bucket ranges @@ -36,25 +36,25 @@ SERVER_SPAWN_DURATION_SECONDS = Histogram( ) RUNNING_SERVERS = Gauge( - 'jupyter_running_servers', 'the number of user servers currently running' + 'jupyterhub_running_servers', 'the number of user servers currently running' ) -TOTAL_USERS = Gauge('jupyter_total_users', 'total number of users') +TOTAL_USERS = Gauge('jupyterhub_total_users', 'total number of users') CHECK_ROUTES_DURATION_SECONDS = Histogram( - 'jupyter_check_routes_duration_seconds', 'Time taken to validate all routes in proxy' + 'jupyterhub_check_routes_duration_seconds', 'Time taken to validate all routes in proxy' ) HUB_STARTUP_DURATION_SECONDS = Histogram( - 'jupyter_hub_startup_duration_seconds', 'Time taken for Hub to start' + 'jupyterhub_hub_startup_duration_seconds', 'Time taken for Hub to start' ) INIT_SPAWNERS_DURATION_SECONDS = Histogram( - 'jupyter_init_spawners_duration_seconds', 'Time taken for spawners to initialize' + 'jupyterhub_init_spawners_duration_seconds', 'Time taken for spawners to initialize' ) PROXY_POLL_DURATION_SECONDS = Histogram( - 'jupyter_proxy_poll_duration_seconds', 'duration for polling all routes from proxy' + 'jupyterhub_proxy_poll_duration_seconds', 'duration for polling all routes from proxy' ) @@ -79,7 +79,7 @@ for s in ServerSpawnStatus: PROXY_ADD_DURATION_SECONDS = Histogram( - 'jupyter_proxy_add_duration_seconds', 'duration for adding user routes to proxy', ['status'] + 'jupyterhub_proxy_add_duration_seconds', 'duration for adding user routes to proxy', ['status'] ) @@ -100,7 +100,7 @@ for s in ProxyAddStatus: SERVER_POLL_DURATION_SECONDS = Histogram( - 'jupyter_server_poll_duration_seconds', + 'jupyterhub_server_poll_duration_seconds', 'time taken to poll if server is running', ['status'], ) @@ -127,7 +127,7 @@ for s in ServerPollStatus: SERVER_STOP_DURATION_SECONDS = Histogram( - 'jupyter_server_stop_seconds', 'time taken for server stopping operation', ['status'] + 'jupyterhub_server_stop_seconds', 'time taken for server stopping operation', ['status'] ) @@ -148,7 +148,7 @@ for s in ServerStopStatus: PROXY_DELETE_DURATION_SECONDS = Histogram( - 'jupyter_proxy_delete_duration_seconds', + 'jupyterhub_proxy_delete_duration_seconds', 'duration for deleting user routes from proxy', ['status'], ) From 73cdd687e9e2a435e544a956dd14ea7158367d31 Mon Sep 17 00:00:00 2001 From: agp8x Date: Tue, 17 Nov 2020 15:36:30 +0100 Subject: [PATCH 05/46] fix formatting --- jupyterhub/metrics.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/jupyterhub/metrics.py b/jupyterhub/metrics.py index 68aeb884..08037aef 100644 --- a/jupyterhub/metrics.py +++ b/jupyterhub/metrics.py @@ -42,7 +42,8 @@ RUNNING_SERVERS = Gauge( TOTAL_USERS = Gauge('jupyterhub_total_users', 'total number of users') CHECK_ROUTES_DURATION_SECONDS = Histogram( - 'jupyterhub_check_routes_duration_seconds', 'Time taken to validate all routes in proxy' + 'jupyterhub_check_routes_duration_seconds', + 'Time taken to validate all routes in proxy', ) HUB_STARTUP_DURATION_SECONDS = Histogram( @@ -54,7 +55,8 @@ INIT_SPAWNERS_DURATION_SECONDS = Histogram( ) PROXY_POLL_DURATION_SECONDS = Histogram( - 'jupyterhub_proxy_poll_duration_seconds', 'duration for polling all routes from proxy' + 'jupyterhub_proxy_poll_duration_seconds', + 'duration for polling all routes from proxy', ) @@ -79,7 +81,9 @@ for s in ServerSpawnStatus: PROXY_ADD_DURATION_SECONDS = Histogram( - 'jupyterhub_proxy_add_duration_seconds', 'duration for adding user routes to proxy', ['status'] + 'jupyterhub_proxy_add_duration_seconds', + 'duration for adding user routes to proxy', + ['status'], ) @@ -127,7 +131,9 @@ for s in ServerPollStatus: SERVER_STOP_DURATION_SECONDS = Histogram( - 'jupyterhub_server_stop_seconds', 'time taken for server stopping operation', ['status'] + 'jupyterhub_server_stop_seconds', + 'time taken for server stopping operation', + ['status'], ) From fb5f98f2fa4566f1aa32534c9960ff9073e064eb Mon Sep 17 00:00:00 2001 From: Long Vu Date: Tue, 17 Nov 2020 17:24:38 -0500 Subject: [PATCH 06/46] login page: add optional feature to accept terms and conditions in order to login The feature is disabled by default. If enabled (by setting `login_term_url`), user will have to check the checkbox to accept the terms and conditions in order to login. --- share/jupyterhub/templates/login.html | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/share/jupyterhub/templates/login.html b/share/jupyterhub/templates/login.html index 130339c9..4aad65f5 100644 --- a/share/jupyterhub/templates/login.html +++ b/share/jupyterhub/templates/login.html @@ -63,6 +63,18 @@ value='Sign In' tabindex="3" /> + + {% block login_terms %} + {% if login_term_url %} + + {% endblock login_terms_text %} + {% endif %} + {% endblock login_terms %} + {% endif %} @@ -81,4 +93,21 @@ if (window.location.protocol === "http:") { } +{% if login_term_url %} + +{% endif %} + {% endblock %} From 11a85d1dc545a5e6295a607d5d09c4b026b3c3a9 Mon Sep 17 00:00:00 2001 From: Long Vu Date: Wed, 18 Nov 2020 14:25:49 -0500 Subject: [PATCH 07/46] login page: allow full override of the optional accept terms and conditions feature The text was already overridable but the endblock was at the wrong location. Now the javascript can also be overridden. --- share/jupyterhub/templates/login.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/share/jupyterhub/templates/login.html b/share/jupyterhub/templates/login.html index 6df3c535..6a946d66 100644 --- a/share/jupyterhub/templates/login.html +++ b/share/jupyterhub/templates/login.html @@ -75,8 +75,8 @@ {% block login_terms_text %} {# allow overriding the text #} By logging into the platform you accept the terms and conditions. - {% endblock login_terms_text %} + {% endif %} {% endblock login_terms %} @@ -105,6 +105,7 @@ $('form').submit((e) => { }); +{% block login_terms_script %} {# allow overriding the javascript #} {% if login_term_url %} {% endif %} +{% endblock login_terms_script %} {% endblock %} From b66d204d69ac12f423c2a7abfabaaf13acd52b6f Mon Sep 17 00:00:00 2001 From: Long Vu Date: Wed, 25 Nov 2020 10:30:22 -0500 Subject: [PATCH 08/46] login page: no javascript needed for the optional accept terms and conditions feature Bonus user gets a pop-up notification to check the checkbox. Tested on Mozilla Firefox (https://user-images.githubusercontent.com/11966697/100246404-18115e00-2f07-11eb-9061-d35434ace3aa.gif) and Google Chrome. Feedback from @minrk. --- share/jupyterhub/templates/login.html | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/share/jupyterhub/templates/login.html b/share/jupyterhub/templates/login.html index 6a946d66..98d43dc8 100644 --- a/share/jupyterhub/templates/login.html +++ b/share/jupyterhub/templates/login.html @@ -72,7 +72,7 @@ {% block login_terms %} {% if login_term_url %}