From 27e83a32605cf7a39a7af8240128469e36b57402 Mon Sep 17 00:00:00 2001 From: Min RK Date: Wed, 7 Jun 2017 10:39:18 +0200 Subject: [PATCH 1/4] pass more arguments as environment variables instead of CLI args env is often easier to deal with for Spawners Now, only optional args are passed on the command-line and all required args come from environment variables. --- jupyterhub/singleuser.py | 12 ++++++++++-- jupyterhub/spawner.py | 16 ++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/jupyterhub/singleuser.py b/jupyterhub/singleuser.py index 5aa17f3d..73ccfc9b 100755 --- a/jupyterhub/singleuser.py +++ b/jupyterhub/singleuser.py @@ -193,6 +193,14 @@ class SingleUserNotebookApp(NotebookApp): user = CUnicode().tag(config=True) group = CUnicode().tag(config=True) + + @default('user') + def _default_user(self): + return os.environ.get('JUPYTERHUB_USER') or '' + + @default('group') + def _default_group(self): + return os.environ.get('JUPYTERHUB_GROUP') or '' @observe('user') def _user_changed(self, change): @@ -233,13 +241,13 @@ class SingleUserNotebookApp(NotebookApp): def _port_default(self): if os.environ.get('JUPYTERHUB_SERVICE_URL'): url = urlparse(os.environ['JUPYTERHUB_SERVICE_URL']) - return url.port + return url.port or 8888 @default('ip') def _ip_default(self): if os.environ.get('JUPYTERHUB_SERVICE_URL'): url = urlparse(os.environ['JUPYTERHUB_SERVICE_URL']) - return url.hostname + return url.hostname or '127.0.0.1' aliases = aliases flags = flags diff --git a/jupyterhub/spawner.py b/jupyterhub/spawner.py index 3abd8577..1e2de8ac 100644 --- a/jupyterhub/spawner.py +++ b/jupyterhub/spawner.py @@ -65,7 +65,7 @@ class Spawner(LoggingConfigurable): """ ) - ip = Unicode('127.0.0.1', + ip = Unicode('', help=""" The IP address (or hostname) the single-user server should listen on. @@ -434,6 +434,12 @@ class Spawner(LoggingConfigurable): env['JUPYTERHUB_HOST'] = self.hub.public_host env['JUPYTERHUB_OAUTH_CALLBACK_URL'] = \ url_path_join(self.user.url, 'oauth_callback') + + # Info previously passed on args + env['JUPYTERHUB_USER'] = self.user.name + env['JUPYTERHUB_API_URL'] = self.hub.api_url + env['JUPYTERHUB_BASE_URL'] = self.hub.base_url + env['JUPYTERHUB_SERVICE_PREFIX'] = self.user.server.base_url # Put in limit and guarantee info if they exist. # Note that this is for use by the humans / notebook extensions in the @@ -493,13 +499,7 @@ class Spawner(LoggingConfigurable): Doesn't expect shell expansion to happen. """ - args = [ - '--user="%s"' % self.user.name, - '--base-url="%s"' % self.user.base_url, - '--hub-host="%s"' % self.hub.public_host, - '--hub-prefix="%s"' % self.hub.base_url, - '--hub-api-url="%s"' % self.hub.api_url, - ] + args = [] if self.ip: args.append('--ip="%s"' % self.ip) From f5c703a04f65627938cb0136be256e6d303fe4d6 Mon Sep 17 00:00:00 2001 From: Min RK Date: Thu, 8 Jun 2017 15:27:13 +0200 Subject: [PATCH 2/4] update tests for env change --- jupyterhub/tests/test_api.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/jupyterhub/tests/test_api.py b/jupyterhub/tests/test_api.py index 0f0d1a64..f0cb3fce 100644 --- a/jupyterhub/tests/test_api.py +++ b/jupyterhub/tests/test_api.py @@ -423,10 +423,13 @@ def test_spawn(app, io_loop): r = requests.get(ujoin(url, 'args')) assert r.status_code == 200 argv = r.json() - for expected in ['--user="%s"' % name, '--base-url="%s"' % user.server.base_url]: - assert expected in argv + assert '--port' in ' '.join(argv) + r = requests.get(ujoin(url, 'env')) + env = r.json() + for expected in ['JUPYTERHUB_USER', 'JUPYTERHUB_BASE_URL', 'JUPYTERHUB_API_TOKEN']: + assert expected in env if app.subdomain_host: - assert '--hub-host="%s"' % app.subdomain_host in argv + assert env['JUPYTERHUB_HOST'] == app.subdomain_host r = api_request(app, 'users', name, 'server', method='delete') assert r.status_code == 204 From 178f1ed5e0910df8942b7193714a26d5dc03edc5 Mon Sep 17 00:00:00 2001 From: Min RK Date: Thu, 15 Jun 2017 11:06:48 +0200 Subject: [PATCH 3/4] fix defaults in singleuser ip/port when service url is undefined never return None --- jupyterhub/singleuser.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/jupyterhub/singleuser.py b/jupyterhub/singleuser.py index 73ccfc9b..afcb3353 100755 --- a/jupyterhub/singleuser.py +++ b/jupyterhub/singleuser.py @@ -241,13 +241,21 @@ class SingleUserNotebookApp(NotebookApp): def _port_default(self): if os.environ.get('JUPYTERHUB_SERVICE_URL'): url = urlparse(os.environ['JUPYTERHUB_SERVICE_URL']) - return url.port or 8888 + if url.port: + return url.port + elif url.scheme == 'http': + return 80 + elif url.scheme == 'https': + return 443 + return 8888 @default('ip') def _ip_default(self): if os.environ.get('JUPYTERHUB_SERVICE_URL'): url = urlparse(os.environ['JUPYTERHUB_SERVICE_URL']) - return url.hostname or '127.0.0.1' + if url.hostname: + return url.hostname + return '127.0.0.1' aliases = aliases flags = flags From 593a3c8ebb68b060b3b953d960f66194e3365d63 Mon Sep 17 00:00:00 2001 From: Min RK Date: Wed, 21 Jun 2017 13:52:47 +0200 Subject: [PATCH 4/4] fix base_url handling in services JUPYTERHUB_BASE_URL is the whole application base_url (default: /) JUPYTERHUB_SERVICE_PREFIX is the service prefix (/user/name/) --- jupyterhub/services/service.py | 9 ++++++--- jupyterhub/spawner.py | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/jupyterhub/services/service.py b/jupyterhub/services/service.py index 433b65a6..b6134a45 100644 --- a/jupyterhub/services/service.py +++ b/jupyterhub/services/service.py @@ -71,6 +71,12 @@ class _MockUser(HasTraits): return self.host + self.server.base_url else: return self.server.base_url + + @property + def base_url(self): + if not self.server: + return '' + return self.server.base_url # We probably shouldn't use a Spawner here, # but there are too many concepts to share. @@ -261,9 +267,6 @@ class Service(LoggingConfigurable): env.update(self.environment) env['JUPYTERHUB_SERVICE_NAME'] = self.name - env['JUPYTERHUB_API_TOKEN'] = self.api_token - env['JUPYTERHUB_API_URL'] = self.hub.api_url - env['JUPYTERHUB_BASE_URL'] = self.base_url if self.url: env['JUPYTERHUB_SERVICE_URL'] = self.url env['JUPYTERHUB_SERVICE_PREFIX'] = self.server.base_url diff --git a/jupyterhub/spawner.py b/jupyterhub/spawner.py index 1e2de8ac..9b6191b6 100644 --- a/jupyterhub/spawner.py +++ b/jupyterhub/spawner.py @@ -438,8 +438,8 @@ class Spawner(LoggingConfigurable): # Info previously passed on args env['JUPYTERHUB_USER'] = self.user.name env['JUPYTERHUB_API_URL'] = self.hub.api_url - env['JUPYTERHUB_BASE_URL'] = self.hub.base_url - env['JUPYTERHUB_SERVICE_PREFIX'] = self.user.server.base_url + env['JUPYTERHUB_BASE_URL'] = self.hub.base_url[:-4] + env['JUPYTERHUB_SERVICE_PREFIX'] = self.user.base_url # Put in limit and guarantee info if they exist. # Note that this is for use by the humans / notebook extensions in the