mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-13 21:13:01 +00:00
Add an example simple announcement service
This commit is contained in:
60
examples/service-announcement/README.md
Normal file
60
examples/service-announcement/README.md
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
# Simple Announcement Service Example
|
||||
|
||||
This is a simple service that allows administrators to manage announcements
|
||||
that appear when JupyterHub renders pages.
|
||||
|
||||
To run the service as a hub-managed service simply include in your JupyterHub
|
||||
configuration file something like:
|
||||
|
||||
c.JupyterHub.services = [
|
||||
{
|
||||
'name': 'announcement',
|
||||
'url': 'http://127.0.0.1:8888',
|
||||
'command': ["python", "-m", "announcement"],
|
||||
}
|
||||
]
|
||||
|
||||
This starts the announcements service up at `/services/announcement` when
|
||||
JupyterHub launches. By default the announcement text is empty.
|
||||
|
||||
The `announcement` module has a configurable port (default 8888) and an API
|
||||
prefix setting. By default the API prefix is `JUPYTERHUB_SERVICE_PREFIX` if
|
||||
that environment variable is set or `/` if it is not.
|
||||
|
||||
## Managing the Announcement
|
||||
|
||||
Admin users can set the announcement text with an API token:
|
||||
|
||||
$ curl -X POST -H "Authorization: token <token>" \
|
||||
-d "{'announcement':'JupyterHub will be upgraded on August 14!'}" \
|
||||
https://.../services/announcement
|
||||
|
||||
Anyone can read the announcement:
|
||||
|
||||
$ curl https://.../services/announcement | python -m json.tool
|
||||
{
|
||||
announcement: "JupyterHub will be upgraded on August 14!",
|
||||
timestamp: "...",
|
||||
user: "..."
|
||||
}
|
||||
|
||||
The time the announcement was posted is recorded in the `timestamp` field and
|
||||
the user who posted the announcement is recorded in the `user` field.
|
||||
|
||||
To clear the announcement text, just DELETE. Only admin users can do this.
|
||||
|
||||
$ curl -X POST -H "Authorization: token <token>" \
|
||||
https://.../services/announcement
|
||||
|
||||
## Seeing the Announcement in JupyterHub
|
||||
|
||||
To be able to render the announcement, include the provide `page.html` template
|
||||
that extends the base `page.html` template. Set `c.JupyterHub.template_paths`
|
||||
in JupyterHub's configuration to include the path to the extending template.
|
||||
The template changes the `announcement` element and does a JQuery `$.get()` call
|
||||
to retrieve the announcement text.
|
||||
|
||||
JupyterHub's configurable announcement template variables can be set for various
|
||||
pages like login, logout, spawn, and home. Including the template provided in
|
||||
this example overrides all of those.
|
76
examples/service-announcement/announcement.py
Normal file
76
examples/service-announcement/announcement.py
Normal file
@@ -0,0 +1,76 @@
|
||||
|
||||
import argparse
|
||||
import datetime
|
||||
import json
|
||||
import os
|
||||
|
||||
from jupyterhub.services.auth import HubAuthenticated
|
||||
from tornado import escape, gen, ioloop, web
|
||||
|
||||
|
||||
class AnnouncementRequestHandler(HubAuthenticated, web.RequestHandler):
|
||||
"""Dynamically manage page announcements"""
|
||||
|
||||
def initialize(self, storage):
|
||||
"""Create storage for announcement text"""
|
||||
self.storage = storage
|
||||
|
||||
@web.authenticated
|
||||
def post(self):
|
||||
"""Update announcement"""
|
||||
user = self.get_current_user()
|
||||
if user is None or not user.get("admin", False):
|
||||
raise web.HTTPError(403)
|
||||
doc = escape.json_decode(self.request.body)
|
||||
self.storage["announcement"] = doc["announcement"]
|
||||
self.storage["timestamp"] = datetime.datetime.now().isoformat()
|
||||
self.storage["user"] = user["name"]
|
||||
self.write_to_json(self.storage)
|
||||
|
||||
def get(self):
|
||||
"""Retrieve announcement"""
|
||||
self.write_to_json(self.storage)
|
||||
|
||||
@web.authenticated
|
||||
def delete(self):
|
||||
"""Clear announcement"""
|
||||
user = self.get_current_user()
|
||||
if user is None or not user.get("admin", False):
|
||||
raise web.HTTPError(403)
|
||||
self.storage["announcement"] = ""
|
||||
self.write_to_json(self.storage)
|
||||
|
||||
def write_to_json(self, doc):
|
||||
"""Write dictionary document as JSON"""
|
||||
self.set_header("Content-Type", "application/json; charset=UTF-8")
|
||||
self.write(escape.utf8(json.dumps(doc)))
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_arguments()
|
||||
application = create_application(**vars(args))
|
||||
application.listen(args.port)
|
||||
ioloop.IOLoop.current().start()
|
||||
|
||||
|
||||
def parse_arguments():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--api-prefix", "-a",
|
||||
default=os.environ.get("JUPYTERHUB_SERVICE_PREFIX", "/"),
|
||||
help="application API prefix")
|
||||
parser.add_argument("--port", "-p",
|
||||
default=8888,
|
||||
help="port for API to listen on",
|
||||
type=int)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def create_application(api_prefix="/",
|
||||
handler=AnnouncementRequestHandler,
|
||||
**kwargs):
|
||||
storage = dict(announcement="", timestamp="", user="")
|
||||
return web.Application([(api_prefix, handler, dict(storage=storage))])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
10
examples/service-announcement/jupyterhub_config.py
Normal file
10
examples/service-announcement/jupyterhub_config.py
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
c.JupyterHub.services = [
|
||||
{
|
||||
'name': 'announcement',
|
||||
'url': 'http://127.0.0.1:8888',
|
||||
'command': ["python", "-m", "announcement"],
|
||||
}
|
||||
]
|
||||
|
||||
c.JupyterHub.template_paths = ["templates"]
|
14
examples/service-announcement/templates/page.html
Normal file
14
examples/service-announcement/templates/page.html
Normal file
@@ -0,0 +1,14 @@
|
||||
{% extends "templates/page.html" %}
|
||||
{% block announcement %}
|
||||
<div class="container text-center announcement">
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
{{ super() }}
|
||||
<script>
|
||||
$.get("/services/announcement/", function(data) {
|
||||
$(".announcement").html(data["announcement"]);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
Reference in New Issue
Block a user