mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-09 11:03:00 +00:00
Merge pull request #675 from minrk/api-info
Add /api/ and /api/info endpoints
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,6 +6,7 @@ node_modules
|
|||||||
build
|
build
|
||||||
dist
|
dist
|
||||||
docs/_build
|
docs/_build
|
||||||
|
docs/source/_static/rest-api
|
||||||
.ipynb_checkpoints
|
.ipynb_checkpoints
|
||||||
# ignore config file at the top-level of the repo
|
# ignore config file at the top-level of the repo
|
||||||
# but not sub-dirs
|
# but not sub-dirs
|
||||||
|
@@ -21,6 +21,60 @@ produces:
|
|||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
paths:
|
paths:
|
||||||
|
/:
|
||||||
|
get:
|
||||||
|
summary: See the version of JupyterHub itself
|
||||||
|
description: |
|
||||||
|
This endpoint is not authenticated,
|
||||||
|
so clients can identify the version of JupyterHub before setting up authentication.
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: The version of JupyterHub itself
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
|
description: The version of JupyterHub itself
|
||||||
|
/info:
|
||||||
|
get:
|
||||||
|
summary: Get detailed info about JupyterHub
|
||||||
|
description: |
|
||||||
|
Detailed information about JupyterHub,
|
||||||
|
including information about Python, JupyterHub's version,
|
||||||
|
and what Authenticators and Spawners are in use.
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
|
description: The version of JupyterHub itself
|
||||||
|
python:
|
||||||
|
type: string
|
||||||
|
description: The version of Python, as returned by sys.version
|
||||||
|
sys_executable:
|
||||||
|
type: string
|
||||||
|
description: The path to sys.executable running JupyterHub
|
||||||
|
authenticator:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
class:
|
||||||
|
type: string
|
||||||
|
description: The Python class currently in use
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
|
description: The version of the package providing the Authenticator class
|
||||||
|
spawner:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
class:
|
||||||
|
type: string
|
||||||
|
description: The Python class currently in use for spawning single-user servers
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
|
description: The version of the package providing the Spawner class
|
||||||
/users:
|
/users:
|
||||||
get:
|
get:
|
||||||
summary: List users
|
summary: List users
|
||||||
@@ -332,6 +386,15 @@ paths:
|
|||||||
/shutdown:
|
/shutdown:
|
||||||
post:
|
post:
|
||||||
summary: Shutdown the Hub
|
summary: Shutdown the Hub
|
||||||
|
parameters:
|
||||||
|
- name: proxy
|
||||||
|
in: body
|
||||||
|
type: bool
|
||||||
|
description: Whether the proxy should be shutdown as well (default from Hub config)
|
||||||
|
- name: servers
|
||||||
|
in: body
|
||||||
|
type: bool
|
||||||
|
description: Whether users's servers should be shutdown as well (default from Hub config)
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Hub has shutdown
|
description: Hub has shutdown
|
||||||
|
@@ -4,12 +4,15 @@
|
|||||||
# Distributed under the terms of the Modified BSD License.
|
# Distributed under the terms of the Modified BSD License.
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
from tornado import web
|
from tornado import web
|
||||||
from tornado.ioloop import IOLoop
|
from tornado.ioloop import IOLoop
|
||||||
|
|
||||||
from ..utils import admin_only
|
from ..utils import admin_only
|
||||||
from .base import APIHandler
|
from .base import APIHandler
|
||||||
|
from ..version import __version__
|
||||||
|
|
||||||
|
|
||||||
class ShutdownAPIHandler(APIHandler):
|
class ShutdownAPIHandler(APIHandler):
|
||||||
|
|
||||||
@@ -49,6 +52,56 @@ class ShutdownAPIHandler(APIHandler):
|
|||||||
loop.add_callback(loop.stop)
|
loop.add_callback(loop.stop)
|
||||||
|
|
||||||
|
|
||||||
|
class RootAPIHandler(APIHandler):
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
"""GET /api/ returns info about the Hub and its API.
|
||||||
|
|
||||||
|
It is not an authenticated endpoint.
|
||||||
|
|
||||||
|
For now, it just returns the version of JupyterHub itself.
|
||||||
|
"""
|
||||||
|
data = {
|
||||||
|
'version': __version__,
|
||||||
|
}
|
||||||
|
self.finish(json.dumps(data))
|
||||||
|
|
||||||
|
|
||||||
|
class InfoAPIHandler(APIHandler):
|
||||||
|
|
||||||
|
@admin_only
|
||||||
|
def get(self):
|
||||||
|
"""GET /api/info returns detailed info about the Hub and its API.
|
||||||
|
|
||||||
|
It is not an authenticated endpoint.
|
||||||
|
|
||||||
|
For now, it just returns the version of JupyterHub itself.
|
||||||
|
"""
|
||||||
|
def _class_info(typ):
|
||||||
|
"""info about a class (Spawner or Authenticator)"""
|
||||||
|
info = {
|
||||||
|
'class': '{mod}.{name}'.format(mod=typ.__module__, name=typ.__name__),
|
||||||
|
}
|
||||||
|
pkg = typ.__module__.split('.')[0]
|
||||||
|
try:
|
||||||
|
version = sys.modules[pkg].__version__
|
||||||
|
except (KeyError, AttributeError):
|
||||||
|
version = 'unknown'
|
||||||
|
info['version'] = version
|
||||||
|
return info
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'version': __version__,
|
||||||
|
'python': sys.version,
|
||||||
|
'sys_executable': sys.executable,
|
||||||
|
'spawner': _class_info(self.settings['spawner_class']),
|
||||||
|
'authenticator': _class_info(self.authenticator.__class__),
|
||||||
|
}
|
||||||
|
self.finish(json.dumps(data))
|
||||||
|
|
||||||
|
|
||||||
default_handlers = [
|
default_handlers = [
|
||||||
(r"/api/shutdown", ShutdownAPIHandler),
|
(r"/api/shutdown", ShutdownAPIHandler),
|
||||||
|
(r"/api/?", RootAPIHandler),
|
||||||
|
(r"/api/info", InfoAPIHandler),
|
||||||
]
|
]
|
||||||
|
@@ -3,12 +3,14 @@
|
|||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
|
import sys
|
||||||
from urllib.parse import urlparse, quote
|
from urllib.parse import urlparse, quote
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from tornado import gen
|
from tornado import gen
|
||||||
|
|
||||||
|
import jupyterhub
|
||||||
from .. import orm
|
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
|
||||||
@@ -657,6 +659,41 @@ def test_group_delete_users(app):
|
|||||||
assert sorted([ u.name for u in group.users ]) == sorted(names[2:])
|
assert sorted([ u.name for u in group.users ]) == sorted(names[2:])
|
||||||
|
|
||||||
|
|
||||||
|
def test_root_api(app):
|
||||||
|
base_url = app.hub.server.url
|
||||||
|
url = ujoin(base_url, 'api')
|
||||||
|
r = requests.get(url)
|
||||||
|
r.raise_for_status()
|
||||||
|
expected = {
|
||||||
|
'version': jupyterhub.__version__
|
||||||
|
}
|
||||||
|
assert r.json() == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_info(app):
|
||||||
|
r = api_request(app, 'info')
|
||||||
|
r.raise_for_status()
|
||||||
|
data = r.json()
|
||||||
|
assert data['version'] == jupyterhub.__version__
|
||||||
|
assert sorted(data) == [
|
||||||
|
'authenticator',
|
||||||
|
'python',
|
||||||
|
'spawner',
|
||||||
|
'sys_executable',
|
||||||
|
'version',
|
||||||
|
]
|
||||||
|
assert data['python'] == sys.version
|
||||||
|
assert data['sys_executable'] == sys.executable
|
||||||
|
assert data['authenticator'] == {
|
||||||
|
'class': 'jupyterhub.tests.mocking.MockPAMAuthenticator',
|
||||||
|
'version': jupyterhub.__version__,
|
||||||
|
}
|
||||||
|
assert data['spawner'] == {
|
||||||
|
'class': 'jupyterhub.tests.mocking.MockSpawner',
|
||||||
|
'version': jupyterhub.__version__,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# general API tests
|
# general API tests
|
||||||
|
|
||||||
def test_options(app):
|
def test_options(app):
|
||||||
|
Reference in New Issue
Block a user