mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-11 12:03:00 +00:00
API: pass 'server_state' through to admin clients only
- This will allow, for example, cull_idle_servers to be more intelligent when culling servers. - This is only given to admin API users, because we don't know if all spawners expect their state to be made available to users.
This commit is contained in:
@@ -652,6 +652,9 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
description: UTC timestamp last-seen activity on this server.
|
description: UTC timestamp last-seen activity on this server.
|
||||||
|
state:
|
||||||
|
type: object
|
||||||
|
description: Arbitrary internal state from this server's spawner. Only available on the hub's users list or get-user-by-name method, and only if a hub admin. None otherwise.
|
||||||
Group:
|
Group:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@@ -90,7 +90,7 @@ class APIHandler(BaseHandler):
|
|||||||
'message': message or status_message,
|
'message': message or status_message,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def server_model(self, spawner):
|
def server_model(self, spawner, include_state=False):
|
||||||
"""Get the JSON model for a Spawner"""
|
"""Get the JSON model for a Spawner"""
|
||||||
return {
|
return {
|
||||||
'name': spawner.name,
|
'name': spawner.name,
|
||||||
@@ -98,6 +98,7 @@ class APIHandler(BaseHandler):
|
|||||||
'started': isoformat(spawner.orm_spawner.started),
|
'started': isoformat(spawner.orm_spawner.started),
|
||||||
'pending': spawner.pending,
|
'pending': spawner.pending,
|
||||||
'ready': spawner.ready,
|
'ready': spawner.ready,
|
||||||
|
'state': spawner.get_state() if include_state else None,
|
||||||
'url': url_path_join(spawner.user.url, spawner.name, '/'),
|
'url': url_path_join(spawner.user.url, spawner.name, '/'),
|
||||||
'progress_url': spawner._progress_url,
|
'progress_url': spawner._progress_url,
|
||||||
}
|
}
|
||||||
@@ -137,7 +138,7 @@ class APIHandler(BaseHandler):
|
|||||||
model.update(extra)
|
model.update(extra)
|
||||||
return model
|
return model
|
||||||
|
|
||||||
def user_model(self, user, include_servers=False):
|
def user_model(self, user, include_servers=False, include_state=False):
|
||||||
"""Get the JSON model for a User object"""
|
"""Get the JSON model for a User object"""
|
||||||
if isinstance(user, orm.User):
|
if isinstance(user, orm.User):
|
||||||
user = self.users[user.id]
|
user = self.users[user.id]
|
||||||
@@ -164,7 +165,7 @@ class APIHandler(BaseHandler):
|
|||||||
# include 'active' servers, not just ready
|
# include 'active' servers, not just ready
|
||||||
# (this includes pending events)
|
# (this includes pending events)
|
||||||
if spawner.active:
|
if spawner.active:
|
||||||
servers[name] = self.server_model(spawner)
|
servers[name] = self.server_model(spawner, include_state=include_state)
|
||||||
return model
|
return model
|
||||||
|
|
||||||
def group_model(self, group):
|
def group_model(self, group):
|
||||||
|
@@ -36,7 +36,7 @@ class UserListAPIHandler(APIHandler):
|
|||||||
@admin_only
|
@admin_only
|
||||||
def get(self):
|
def get(self):
|
||||||
data = [
|
data = [
|
||||||
self.user_model(u, include_servers=True)
|
self.user_model(u, include_servers=True, include_state=True)
|
||||||
for u in self.db.query(orm.User)
|
for u in self.db.query(orm.User)
|
||||||
]
|
]
|
||||||
self.write(json.dumps(data))
|
self.write(json.dumps(data))
|
||||||
@@ -116,7 +116,7 @@ class UserAPIHandler(APIHandler):
|
|||||||
@admin_or_self
|
@admin_or_self
|
||||||
async def get(self, name):
|
async def get(self, name):
|
||||||
user = self.find_user(name)
|
user = self.find_user(name)
|
||||||
model = self.user_model(user, include_servers=True)
|
model = self.user_model(user, include_servers=True, include_state=self.get_current_user().admin)
|
||||||
# auth state will only be shown if the requestor is an admin
|
# auth state will only be shown if the requestor is an admin
|
||||||
# this means users can't see their own auth state unless they
|
# this means users can't see their own auth state unless they
|
||||||
# are admins, Hub admins often are also marked as admins so they
|
# are admins, Hub admins often are also marked as admins so they
|
||||||
|
@@ -207,6 +207,9 @@ def normalize_user(user):
|
|||||||
for key in ('started', 'last_activity'):
|
for key in ('started', 'last_activity'):
|
||||||
server[key] = normalize_timestamp(server[key])
|
server[key] = normalize_timestamp(server[key])
|
||||||
server['progress_url'] = re.sub(r'.*/hub/api', 'PREFIX/hub/api', server['progress_url'])
|
server['progress_url'] = re.sub(r'.*/hub/api', 'PREFIX/hub/api', server['progress_url'])
|
||||||
|
if (isinstance(server['state'], dict)
|
||||||
|
and isinstance(server['state'].get('pid', None), int)):
|
||||||
|
server['state']['pid'] = 0
|
||||||
return user
|
return user
|
||||||
|
|
||||||
def fill_user(model):
|
def fill_user(model):
|
||||||
|
@@ -43,6 +43,7 @@ def test_default_server(app, named_servers):
|
|||||||
'pending': None,
|
'pending': None,
|
||||||
'ready': True,
|
'ready': True,
|
||||||
'progress_url': 'PREFIX/hub/api/users/{}/server/progress'.format(username),
|
'progress_url': 'PREFIX/hub/api/users/{}/server/progress'.format(username),
|
||||||
|
'state': {'pid': 0},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -102,6 +103,7 @@ def test_create_named_server(app, named_servers):
|
|||||||
'ready': True,
|
'ready': True,
|
||||||
'progress_url': 'PREFIX/hub/api/users/{}/servers/{}/progress'.format(
|
'progress_url': 'PREFIX/hub/api/users/{}/servers/{}/progress'.format(
|
||||||
username, servername),
|
username, servername),
|
||||||
|
'state': {'pid': 0},
|
||||||
}
|
}
|
||||||
for name in [servername]
|
for name in [servername]
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user