Merge pull request #842 from yuvipanda/upgrade-things

update: jupyterhub 3, oauthenticator 15, systemdspawner 0.17 (user env: ipywidgets 8)
This commit is contained in:
Simon Li
2023-04-04 19:20:19 +01:00
committed by GitHub
3 changed files with 60 additions and 44 deletions

View File

@@ -346,12 +346,12 @@ async def test_idle_server_culled():
) )
).wait() ).wait()
) )
# Check every 10s for idle servers to cull # Check every 5s for idle servers to cull
assert ( assert (
0 0
== await ( == await (
await asyncio.create_subprocess_exec( await asyncio.create_subprocess_exec(
*TLJH_CONFIG_PATH, "set", "services.cull.every", "10" *TLJH_CONFIG_PATH, "set", "services.cull.every", "5"
) )
).wait() ).wait()
) )
@@ -364,12 +364,12 @@ async def test_idle_server_culled():
) )
).wait() ).wait()
) )
# Cull servers and users after 60s of activity # Cull servers and users after 30s, regardless of activity
assert ( assert (
0 0
== await ( == await (
await asyncio.create_subprocess_exec( await asyncio.create_subprocess_exec(
*TLJH_CONFIG_PATH, "set", "services.cull.max_age", "60" *TLJH_CONFIG_PATH, "set", "services.cull.max_age", "30"
) )
).wait() ).wait()
) )
@@ -388,25 +388,50 @@ async def test_idle_server_culled():
assert pwd.getpwnam(f"jupyter-{username}") is not None assert pwd.getpwnam(f"jupyter-{username}") is not None
# Check that we can get to the user's server # Check that we can get to the user's server
r = await u.session.get( user_url = u.notebook_url / "api/status"
u.hub_url / "hub/api/users" / username, r = await u.session.get(user_url, allow_redirects=False)
headers={"Referer": str(u.hub_url / "hub/")},
)
assert r.status == 200 assert r.status == 200
async def _check_culling_done(): # Check that we can talk to JupyterHub itself
# Check that after 60s, the user and server have been culled and are not reacheable anymore # use this as a proxy for whether the user still exists
async def hub_api_request():
r = await u.session.get( r = await u.session.get(
u.hub_url / "hub/api/users" / username, u.hub_url / "hub/api/user",
headers={"Referer": str(u.hub_url / "hub/")}, headers={"Referer": str(u.hub_url / "hub/")},
allow_redirects=False,
) )
print(r.status) return r
r = await hub_api_request()
assert r.status == 200
# Wait for culling
# step 1: check if the server is still running
timeout = 100
async def server_stopped():
"""Has the server been stopped?"""
r = await u.session.get(user_url, allow_redirects=False)
print(f"{r.status} {r.url}")
return r.status != 200
await exponential_backoff(
server_stopped,
"Server still running!",
timeout=timeout,
)
# step 2. wait for user to be deleted
async def user_removed():
# Check that after 60s, the user has been culled
r = await hub_api_request()
print(f"{r.status} {r.url}")
return r.status == 403 return r.status == 403
await exponential_backoff( await exponential_backoff(
_check_culling_done, user_removed,
"Server culling failed!", "User still exists!",
timeout=100, timeout=timeout,
) )
@@ -429,12 +454,12 @@ async def test_active_server_not_culled():
) )
).wait() ).wait()
) )
# Check every 10s for idle servers to cull # Check every 5s for idle servers to cull
assert ( assert (
0 0
== await ( == await (
await asyncio.create_subprocess_exec( await asyncio.create_subprocess_exec(
*TLJH_CONFIG_PATH, "set", "services.cull.every", "10" *TLJH_CONFIG_PATH, "set", "services.cull.every", "5"
) )
).wait() ).wait()
) )
@@ -447,7 +472,7 @@ async def test_active_server_not_culled():
) )
).wait() ).wait()
) )
# Cull servers and users after 60s of activity # Cull servers and users after 30s, regardless of activity
assert ( assert (
0 0
== await ( == await (
@@ -471,27 +496,24 @@ async def test_active_server_not_culled():
assert pwd.getpwnam(f"jupyter-{username}") is not None assert pwd.getpwnam(f"jupyter-{username}") is not None
# Check that we can get to the user's server # Check that we can get to the user's server
r = await u.session.get( user_url = u.notebook_url / "api/status"
u.hub_url / "hub/api/users" / username, r = await u.session.get(user_url, allow_redirects=False)
headers={"Referer": str(u.hub_url / "hub/")},
)
assert r.status == 200 assert r.status == 200
async def _check_culling_done(): async def server_has_stopped():
# Check that after 30s, we can still reach the user's server # Check that after 30s, we can still reach the user's server
r = await u.session.get( r = await u.session.get(user_url, allow_redirects=False)
u.hub_url / "hub/api/users" / username, print(f"{r.status} {r.url}")
headers={"Referer": str(u.hub_url / "hub/")},
)
print(r.status)
return r.status != 200 return r.status != 200
try: try:
await exponential_backoff( await exponential_backoff(
_check_culling_done, server_has_stopped,
"User's server is still reacheable!", "User's server is still reachable (good!)",
timeout=30, timeout=30,
) )
except TimeoutError: except asyncio.TimeoutError:
# During the 30s timeout the user's server wasn't culled, which is what we intended. # timeout error means the test passed - the server didn't go away while we were waiting
pass pass
else:
pytest.fail(f"Server at {user_url} got culled prematurely!")

View File

@@ -121,14 +121,13 @@ def ensure_jupyterhub_package(prefix):
conda.ensure_pip_packages( conda.ensure_pip_packages(
prefix, prefix,
[ [
"SQLAlchemy<2.0.0", "jupyterhub==3.*",
"jupyterhub==1.*", "jupyterhub-systemdspawner==0.17.*",
"jupyterhub-systemdspawner==0.16.*",
"jupyterhub-firstuseauthenticator==1.*", "jupyterhub-firstuseauthenticator==1.*",
"jupyterhub-nativeauthenticator==1.*", "jupyterhub-nativeauthenticator==1.*",
"jupyterhub-ldapauthenticator==1.*", "jupyterhub-ldapauthenticator==1.*",
"jupyterhub-tmpauthenticator==0.6.*", "jupyterhub-tmpauthenticator==0.6.*",
"oauthenticator==14.*", "oauthenticator==15.*",
"jupyterhub-idle-culler==1.*", "jupyterhub-idle-culler==1.*",
"git+https://github.com/yuvipanda/jupyterhub-configurator@317759e17c8e48de1b1352b836dac2a230536dba", "git+https://github.com/yuvipanda/jupyterhub-configurator@317759e17c8e48de1b1352b836dac2a230536dba",
], ],

View File

@@ -5,20 +5,15 @@
# the requirements-txt-fixer pre-commit hook that sorted them and made # the requirements-txt-fixer pre-commit hook that sorted them and made
# our integration tests fail. # our integration tests fail.
# #
# For JupyterHub 1.x SQLAlchemy below 2.0.0
SQLAlchemy<2.0.0
# JupyterHub + notebook package are base requirements for user environment # JupyterHub + notebook package are base requirements for user environment
jupyterhub==1.* jupyterhub==3.*
notebook==6.* notebook==6.*
# Install additional notebook frontends! # Install additional notebook frontends!
jupyterlab==3.* jupyterlab==3.*
nteract-on-jupyter==2.* nteract-on-jupyter==2.*
# Install jupyterlab extensions from PyPI
# nbgitpuller for easily pulling in Git repositories # nbgitpuller for easily pulling in Git repositories
nbgitpuller==1.* nbgitpuller==1.*
# jupyter-resource-usage to show people how much RAM they are using # jupyter-resource-usage to show people how much RAM they are using
jupyter-resource-usage==0.6.* jupyter-resource-usage==0.7.*
# Most people consider ipywidgets to be part of the core notebook experience # Most people consider ipywidgets to be part of the core notebook experience
ipywidgets==7.* ipywidgets==8.*
# Pin tornado
tornado>=6.1