Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support named servers, not only default ones #84

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 35 additions & 9 deletions jupyterhub_ssh/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,19 @@ async def get_user_server_url(self, session, username):

Else return None
"""
server_name = ""
if "#" in username:
username, server_name = username.split("#", 1)
print("Using username for custom instance", username, server_name)
else:
print("Using username for default instance", username)
async with session.get(self.app.hub_url / "hub/api/users" / username) as resp:
if resp.status != 200:
return None
user = await resp.json()
print(user)
# URLs will have preceding slash, but yarl forbids those
server = user.get("servers", {}).get("", {})
if server.get("ready", False):
return self.app.hub_url / user["servers"][""]["url"][1:]
return self.app.hub_url / user["servers"][server_name]["url"][1:]
else:
return None

Expand All @@ -57,6 +61,14 @@ async def start_user_server(self, session, username):
# REST API reference: https://jupyterhub.readthedocs.io/en/stable/_static/rest-api/index.html#operation--users--name--server-post
# REST API implementation: https://github.com/jupyterhub/jupyterhub/blob/187fe911edce06eb067f736eaf4cc9ea52e69e08/jupyterhub/apihandlers/users.py#L451-L497
create_url = self.app.hub_url / "hub/api/users" / username / "server"
server_name = ""
if "#" in username:
username, server_name = username.split("#", 1)

if server_name:
create_url = self.app.hub_url / "hub/api/users" / username / "servers" / server_name

print("create_url: ", create_url, flush=True)

async with session.post(create_url) as resp:
if resp.status == 201 or resp.status == 400:
Expand All @@ -68,6 +80,10 @@ async def start_user_server(self, session, username):
# We manually generate this, even though it's *bad*
# Mostly because when the server is already running, JupyterHub
# doesn't respond with the whole model!
if server_name:
print("Custom-named server started", username, server_name)
return self.app.hub_url / "user" / username / server_name
print("Server started", username, server_name)
return self.app.hub_url / "user" / username
elif resp.status == 202:
# Server start has been requested, now and potentially earlier,
Expand All @@ -78,24 +94,34 @@ async def start_user_server(self, session, username):
async with timeout(self.app.start_timeout):
notebook_url = None
self._conn.send_auth_banner("Starting your server...")
print("Server start requested", username, server_name)
while notebook_url is None:
# FIXME: Exponential backoff + make this configurable
await asyncio.sleep(0.5)
notebook_url = await self.get_user_server_url(
session, username
)
if server_name:
notebook_url = await self.get_user_server_url(
session, username + "/" + server_name
)
else:
notebook_url = await self.get_user_server_url(
session, username
)
self._conn.send_auth_banner(".")
self._conn.send_auth_banner("done!\n")
print("Server started", username, server_name)
return notebook_url
except asyncio.TimeoutError:
# Server didn't start on time!
self._conn.send_auth_banner("failed to start server on time!\n")
print("Server start timed out", username, server_name)
return None
elif resp.status == 403:
print("The token seems to be wrong for user ", username)
# Token is wrong!
return None
else:
# FIXME: Handle other cases that pop up
print("Unhandled response", resp.status)
resp.raise_for_status()

async def validate_password(self, username, token):
Expand Down Expand Up @@ -225,13 +251,13 @@ class JupyterHubSSH(Application):
debug = Bool(
True,
help="""
Turn on debugg logging
Turn on debug logging
""",
config=True,
)

hub_url = Any(
"",
URL("http://proxy-public.jhub.svc.cluster.local"),
help="""
URL of JupyterHub's proxy to connect to.

Expand Down Expand Up @@ -269,7 +295,7 @@ def _hub_url_cast_string_to_yarl_url(self, proposal):
raise ValueError("hub_url must either be a string or a yarl.URL")

host_key_path = Unicode(
"",
"/etc/jupyterhub-ssh/config/hostKey",
help="""
Path to host's private SSH Key.

Expand Down