Tests are passing with subdomains

This commit is contained in:
Min RK
2016-02-26 17:32:38 +01:00
parent 79df83f0d3
commit f922561003
5 changed files with 67 additions and 26 deletions

View File

@@ -593,14 +593,14 @@ class JupyterHub(Application):
q = self.db.query(orm.Hub) q = self.db.query(orm.Hub)
assert q.count() <= 1 assert q.count() <= 1
self._local.hub = q.first() self._local.hub = q.first()
if self.use_subdomains: if self.use_subdomains and self._local.hub:
self._local.hub.host = self.subdomain_host self._local.hub.host = self.subdomain_host
return self._local.hub return self._local.hub
@hub.setter @hub.setter
def hub(self, hub): def hub(self, hub):
self._local.hub = hub self._local.hub = hub
if self.use_subdomains: if hub and self.use_subdomains:
hub.host = self.subdomain_host hub.host = self.subdomain_host
@property @property

View File

@@ -1,7 +1,7 @@
"""mock utilities for testing""" """mock utilities for testing"""
import os
import sys import sys
from datetime import timedelta
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
import threading import threading
@@ -13,10 +13,11 @@ from tornado import gen
from tornado.concurrent import Future from tornado.concurrent import Future
from tornado.ioloop import IOLoop from tornado.ioloop import IOLoop
from ..spawner import LocalProcessSpawner
from ..app import JupyterHub from ..app import JupyterHub
from ..auth import PAMAuthenticator from ..auth import PAMAuthenticator
from .. import orm from .. import orm
from ..spawner import LocalProcessSpawner
from ..utils import url_path_join
from pamela import PAMError from pamela import PAMError
@@ -110,6 +111,12 @@ class MockHub(JupyterHub):
db_file = None db_file = None
confirm_no_ssl = True confirm_no_ssl = True
def _subdomain_host_default(self):
return os.environ.get('JUPYTERHUB_TEST_SUBDOMAIN_HOST', '')
def _use_subdomains_default(self):
return bool(self.subdomain_host)
def _ip_default(self): def _ip_default(self):
return '127.0.0.1' return '127.0.0.1'
@@ -161,7 +168,11 @@ class MockHub(JupyterHub):
self.db_file.close() self.db_file.close()
def login_user(self, name): def login_user(self, name):
r = requests.post(self.proxy.public_server.url + 'hub/login', if self.subdomain_host:
base_url = 'http://' + self.subdomain_host + self.proxy.public_server.base_url
else:
base_url = self.proxy.public_server.url
r = requests.post(base_url + 'hub/login',
data={ data={
'username': name, 'username': name,
'password': name, 'password': name,
@@ -171,3 +182,22 @@ class MockHub(JupyterHub):
assert r.cookies assert r.cookies
return r.cookies return r.cookies
def public_host(app):
if app.use_subdomains:
return app.subdomain_host
else:
return app.proxy.public_server.host
def public_url(app):
return 'http://%s%s' % (public_host(app), app.proxy.public_server.base_url)
def user_url(user, app):
print(user.host)
if app.use_subdomains:
host = user.host
else:
host = public_host(app)
return url_path_join('http://%s' % host, user.server.base_url)

View File

@@ -2,7 +2,6 @@
import json import json
import time import time
from datetime import timedelta
from queue import Queue from queue import Queue
from urllib.parse import urlparse from urllib.parse import urlparse
@@ -14,6 +13,7 @@ from .. import orm
from ..user import User from ..user import User
from ..utils import url_path_join as ujoin from ..utils import url_path_join as ujoin
from . import mocking from . import mocking
from .mocking import public_url, user_url
def check_db_locks(func): def check_db_locks(func):
@@ -105,7 +105,7 @@ def test_auth_api(app):
def test_referer_check(app, io_loop): def test_referer_check(app, io_loop):
url = app.hub.server.url url = ujoin(public_url(app), app.hub.server.base_url)
host = urlparse(url).netloc host = urlparse(url).netloc
user = find_user(app.db, 'admin') user = find_user(app.db, 'admin')
if user is None: if user is None:
@@ -352,15 +352,19 @@ def test_spawn(app, io_loop):
assert status is None assert status is None
assert user.server.base_url == '/user/%s' % name assert user.server.base_url == '/user/%s' % name
r = requests.get(ujoin(app.proxy.public_server.url, user.server.base_url)) url = user_url(user, app)
print(url)
r = requests.get(url)
assert r.status_code == 200 assert r.status_code == 200
assert r.text == user.server.base_url assert r.text == user.server.base_url
r = requests.get(ujoin(app.proxy.public_server.url, user.server.base_url, 'args')) r = requests.get(ujoin(url, 'args'))
assert r.status_code == 200 assert r.status_code == 200
argv = r.json() argv = r.json()
for expected in ['--user=%s' % name, '--base-url=%s' % user.server.base_url]: for expected in ['--user=%s' % name, '--base-url=%s' % user.server.base_url]:
assert expected in argv assert expected in argv
if app.use_subdomains:
assert '--hub-host=//%s' % app.subdomain_host in argv
r = api_request(app, 'users', name, 'server', method='delete') r = api_request(app, 'users', name, 'server', method='delete')
assert r.status_code == 204 assert r.status_code == 204

View File

@@ -8,12 +8,11 @@ from ..utils import url_path_join as ujoin
from .. import orm from .. import orm
import mock import mock
from .mocking import FormSpawner from .mocking import FormSpawner, public_url, public_host, user_url
from .test_api import api_request from .test_api import api_request
def get_page(path, app, **kw): def get_page(path, app, **kw):
base_url = ujoin(app.proxy.public_server.host, app.hub.server.base_url) base_url = ujoin(public_url(app), app.hub.server.base_url)
print(base_url) print(base_url)
return requests.get(ujoin(base_url, path), **kw) return requests.get(ujoin(base_url, path), **kw)
@@ -22,15 +21,16 @@ def test_root_no_auth(app, io_loop):
routes = io_loop.run_sync(app.proxy.get_routes) routes = io_loop.run_sync(app.proxy.get_routes)
print(routes) print(routes)
print(app.hub.server) print(app.hub.server)
r = requests.get(app.proxy.public_server.host) url = public_url(app)
r = requests.get(url)
r.raise_for_status() r.raise_for_status()
assert r.url == ujoin(app.proxy.public_server.host, app.hub.server.base_url, 'login') assert r.url == ujoin(url, app.hub.server.base_url, 'login')
def test_root_auth(app): def test_root_auth(app):
cookies = app.login_user('river') cookies = app.login_user('river')
r = requests.get(app.proxy.public_server.host, cookies=cookies) r = requests.get(public_url(app), cookies=cookies)
r.raise_for_status() r.raise_for_status()
assert r.url == ujoin(app.proxy.public_server.host, '/user/river') assert r.url == user_url(app.users['river'], app)
def test_home_no_auth(app): def test_home_no_auth(app):
r = get_page('home', app, allow_redirects=False) r = get_page('home', app, allow_redirects=False)
@@ -100,7 +100,7 @@ def test_spawn_page(app):
def test_spawn_form(app, io_loop): def test_spawn_form(app, io_loop):
with mock.patch.dict(app.users.settings, {'spawner_class': FormSpawner}): with mock.patch.dict(app.users.settings, {'spawner_class': FormSpawner}):
base_url = ujoin(app.proxy.public_server.host, app.hub.server.base_url) base_url = ujoin(public_url(app), app.hub.server.base_url)
cookies = app.login_user('jones') cookies = app.login_user('jones')
orm_u = orm.User.find(app.db, 'jones') orm_u = orm.User.find(app.db, 'jones')
u = app.users[orm_u] u = app.users[orm_u]
@@ -121,7 +121,7 @@ def test_spawn_form(app, io_loop):
def test_spawn_form_with_file(app, io_loop): def test_spawn_form_with_file(app, io_loop):
with mock.patch.dict(app.users.settings, {'spawner_class': FormSpawner}): with mock.patch.dict(app.users.settings, {'spawner_class': FormSpawner}):
base_url = ujoin(app.proxy.public_server.host, app.hub.server.base_url) base_url = ujoin(public_url(app), app.hub.server.base_url)
cookies = app.login_user('jones') cookies = app.login_user('jones')
orm_u = orm.User.find(app.db, 'jones') orm_u = orm.User.find(app.db, 'jones')
u = app.users[orm_u] u = app.users[orm_u]
@@ -149,7 +149,7 @@ def test_spawn_form_with_file(app, io_loop):
def test_static_files(app): def test_static_files(app):
base_url = ujoin(app.proxy.public_server.url, app.hub.server.base_url) base_url = ujoin(public_url(app), app.hub.server.base_url)
print(base_url) print(base_url)
r = requests.get(ujoin(base_url, 'logo')) r = requests.get(ujoin(base_url, 'logo'))
r.raise_for_status() r.raise_for_status()

View File

@@ -34,6 +34,8 @@ def test_external_proxy(request, io_loop):
'--api-port', str(proxy_port), '--api-port', str(proxy_port),
'--default-target', 'http://%s:%i' % (app.hub_ip, app.hub_port), '--default-target', 'http://%s:%i' % (app.hub_ip, app.hub_port),
] ]
if app.use_subdomains:
cmd.append('--host-routing')
proxy = Popen(cmd, env=env) proxy = Popen(cmd, env=env)
def _cleanup_proxy(): def _cleanup_proxy():
if proxy.poll() is None: if proxy.poll() is None:
@@ -60,7 +62,11 @@ def test_external_proxy(request, io_loop):
r.raise_for_status() r.raise_for_status()
routes = io_loop.run_sync(app.proxy.get_routes) routes = io_loop.run_sync(app.proxy.get_routes)
assert sorted(routes.keys()) == ['/', '/user/river'] user_path = '/user/river'
if app.use_subdomains:
domain = app.subdomain_host.rsplit(':', 1)[0]
user_path = '/%s.%s' % (name, domain) + user_path
assert sorted(routes.keys()) == ['/', user_path]
# teardown the proxy and start a new one in the same place # teardown the proxy and start a new one in the same place
proxy.terminate() proxy.terminate()
@@ -76,7 +82,7 @@ def test_external_proxy(request, io_loop):
# check that the routes are correct # check that the routes are correct
routes = io_loop.run_sync(app.proxy.get_routes) routes = io_loop.run_sync(app.proxy.get_routes)
assert sorted(routes.keys()) == ['/', '/user/river'] assert sorted(routes.keys()) == ['/', user_path]
# teardown the proxy again, and start a new one with different auth and port # teardown the proxy again, and start a new one with different auth and port
proxy.terminate() proxy.terminate()
@@ -90,7 +96,8 @@ def test_external_proxy(request, io_loop):
'--api-port', str(proxy_port), '--api-port', str(proxy_port),
'--default-target', 'http://%s:%i' % (app.hub_ip, app.hub_port), '--default-target', 'http://%s:%i' % (app.hub_ip, app.hub_port),
] ]
if app.use_subdomains:
cmd.append('--host-routing')
proxy = Popen(cmd, env=env) proxy = Popen(cmd, env=env)
wait_for_proxy() wait_for_proxy()
@@ -113,7 +120,7 @@ def test_external_proxy(request, io_loop):
# check that the routes are correct # check that the routes are correct
routes = io_loop.run_sync(app.proxy.get_routes) routes = io_loop.run_sync(app.proxy.get_routes)
assert sorted(routes.keys()) == ['/', '/user/river'] assert sorted(routes.keys()) == ['/', user_path]
def test_check_routes(app, io_loop): def test_check_routes(app, io_loop):
proxy = app.proxy proxy = app.proxy
@@ -125,12 +132,12 @@ def test_check_routes(app, io_loop):
assert zoe is not None assert zoe is not None
zoe = app.users[zoe] zoe = app.users[zoe]
before = sorted(io_loop.run_sync(app.proxy.get_routes)) before = sorted(io_loop.run_sync(app.proxy.get_routes))
assert '/user/zoe' in before assert zoe.proxy_path in before
io_loop.run_sync(lambda : app.proxy.check_routes(app.users)) io_loop.run_sync(lambda : app.proxy.check_routes(app.users))
io_loop.run_sync(lambda : proxy.delete_user(zoe)) io_loop.run_sync(lambda : proxy.delete_user(zoe))
during = sorted(io_loop.run_sync(app.proxy.get_routes)) during = sorted(io_loop.run_sync(app.proxy.get_routes))
assert '/user/zoe' not in during assert zoe.proxy_path not in during
io_loop.run_sync(lambda : app.proxy.check_routes(app.users)) io_loop.run_sync(lambda : app.proxy.check_routes(app.users))
after = sorted(io_loop.run_sync(app.proxy.get_routes)) after = sorted(io_loop.run_sync(app.proxy.get_routes))
assert '/user/zoe' in after assert zoe.proxy_path in after
assert before == after assert before == after