Compare commits

...

1389 Commits

Author SHA1 Message Date
Min RK
e4d4e059bd Merge pull request #2545 from minrk/changelog-1.0
releasing 1.0
2019-05-03 16:12:51 +02:00
Min RK
2967383654 release 1.0.0 2019-05-03 13:50:45 +02:00
Min RK
85f5ae1a37 Merge pull request #2544 from minrk/autodoc-link-targets
[autodoc] move config sample to annotation
2019-05-03 13:49:31 +02:00
Min RK
ecafe4add9 [autodoc] move config sample to annotation
preserves link targets, which mangling the directive header does not
2019-05-03 13:00:25 +02:00
Min RK
9462511aa5 Merge pull request #2543 from minrk/pin-mysql-connector
pin mysql-connector-python on travis
2019-05-03 10:55:34 +02:00
Min RK
31736eea9a pin mysql-connector-python on travis
avoids bug in latest connector decoding: https://bugs.mysql.com/bug.php?id=94944
2019-05-03 10:33:28 +02:00
Min RK
f97ef7eaac Merge pull request #2534 from distortedsignal/refactor-logout-handler
Refactor Logout Handler
2019-05-03 10:11:43 +02:00
Min RK
2065099338 Merge pull request #2524 from minrk/fix-db-redact
test postgres with url-encoded password
2019-05-03 09:48:57 +02:00
Carol Willing
d4df579fa6 Merge pull request #2538 from labarba/patch-1
Update gallery-jhub-deployments.md
2019-05-02 12:14:58 -04:00
Lorena A. Barba
4378603e83 Update gallery-jhub-deployments.md 2019-04-26 07:32:35 -04:00
Min RK
40db4edc6d remove todo
order should be preserved between multiple steps
2019-04-25 13:51:27 +02:00
Min RK
ccf13979e9 Merge pull request #2536 from jcrist/add-jhub-hadoop-links
Add a few links for JupyterHub on Hadoop
2019-04-25 10:23:01 +02:00
Jim Crist
76f134c393 Add a few links for JupyterHub on Hadoop [skip ci]
- JupyterHub on Hadoop Guide: https://github.com/jcrist/jupyterhub-on-hadoop
- YarnSpawner: https://github.com/jcrist/yarnspawner
- KerberosAuthenticator: https://github.com/jcrist/kerberosauthenticator
2019-04-24 14:40:50 -05:00
Tom Kelley
77d4c1f23d Changes after CR Comments
Big thanks to Erik, Tim, and Min for the great comments!

Change names to be more clear, add function doc comments,
change scoping on some functions, add handle_logout to let
people take custom logout actions, extract
render_logout_page from get method, add TODO.
2019-04-23 09:59:56 -07:00
Min RK
5856f46e1d Merge pull request #2519 from dfeich/asyncio_signal_cleanup
asyncio signal handling and loop cleanup by task cancelling
2019-04-23 15:13:08 +02:00
Min RK
edfd1eb6cf Merge pull request #2526 from minrk/debug-entrypoints
demote entrypoint-loading warning to debug-level
2019-04-23 15:12:21 +02:00
Tom Kelley
1ae6678360 Refactor Logout Handler
AS A developer of a Logout handler
I WANT to be able to call a function to kill spawners and
do other backend logout stuff and a separate function to
forward the user along the logout chain.

I believe this PR adds (moderately private) methods to the
Logout Handler to do just that.
2019-04-22 12:14:55 -07:00
Min RK
7794eea3fb demote entrypoint-loading warning to debug-level 2019-04-16 15:30:04 +02:00
Derek Feichtinger
f51e6a1ca0 move event_loop closing to shutdown_cancel_tasks 2019-04-16 13:04:11 +02:00
Min RK
ab00a19be1 test postgres with url-encoded username+password 2019-04-16 12:57:49 +02:00
Min RK
7742bfdda5 Merge pull request #2514 from minrk/user-redirect-test
fix flaky test_user_redirect
2019-04-16 12:52:24 +02:00
Erik Sundell
f3878d8216 Merge pull request #2518 from leportella/add-new-jhub-fluxogram
Add new introduction to jhub on docs
2019-04-15 21:13:25 +02:00
Tim Head
d17cb637fe Merge pull request #2520 from parente/vul-reporting
Add vulnerability reporting info to docs
2019-04-15 16:38:58 +02:00
Peter Parente
5b63efe63c Add a newline for the linter 2019-04-15 07:52:55 -04:00
Peter Parente
54816b0a7c Add vulnerability reporting info
https://discourse.jupyter.org/t/responsible-vulnerability-reporting/655
2019-04-14 22:10:58 -04:00
Leticia Portella
41fc73db42 Add new introduction to jhub on docs 2019-04-13 20:55:36 +01:00
Derek Feichtinger
984d6be542 asyncio signal handling and loop cleanup by task cancelling
Also:
- No longer exits with 143 (128+15) on SIGTERM, but with 0
- Allows SIGUSR1 in addition to SIGINFO for dumping status
2019-04-13 20:17:53 +02:00
Min RK
d7d8459edb 1.0.0b2 2019-04-09 10:45:31 +02:00
Min RK
39a7116d16 npm run fmt
with latest prettier
2019-04-09 10:45:31 +02:00
Min RK
d27c970cc4 rev js dependencies 2019-04-09 10:45:31 +02:00
Min RK
cf56dbb97b latest changes in changelog 2019-04-09 10:36:33 +02:00
Min RK
a4ccfe4e11 Merge pull request #2511 from ryogesh/do-not-show-db-password
Redact DB password before logging connection string
2019-04-09 10:19:48 +02:00
Min RK
f1871bbe24 Merge pull request #2510 from minrk/fix-delete-named
ensure spawner for named servers is fully deleted
2019-04-09 10:17:07 +02:00
bdmon
1cc9153a91 Redact DB password before logging connection string 2019-04-09 09:26:54 +02:00
Tim Head
4258254c39 Merge pull request #2509 from minrk/sec-doc
Add security-reporting to docs
2019-04-05 17:33:44 +02:00
Min RK
f3aee9bd16 ensure spawner for named servers is fully deleted
if spawner wasn't running, the wrapper could have been left in the user.spawners dict
2019-04-05 16:50:55 +02:00
Min RK
5cb8ccf8b2 Merge pull request #2494 from minrk/retry-better
include retry link after failed spawn
2019-04-05 15:29:40 +02:00
Tim Head
1d63e417ca Merge pull request #2508 from minrk/discourse-link
add discourse link to communication doc
2019-04-05 12:06:02 +02:00
Min RK
ee0020e8fa add security-reporting to docs 2019-04-05 11:51:02 +02:00
Min RK
2d83575a24 add discourse link to communication docs 2019-04-05 11:46:44 +02:00
Min RK
33c168530e Merge pull request #2496 from minrk/all-users-admin
ensure default server exists in the db at user creation
2019-04-05 10:29:20 +02:00
Min RK
5d4d34b24d Merge pull request #2498 from minrk/oauthlib-3
allow oauthlib 3
2019-04-05 10:25:59 +02:00
Min RK
49cc794937 include exception in template vars
for custom templates
2019-04-05 10:25:40 +02:00
Min RK
7f9e77ce5b Allow Spawners to customize spawn-failed message
by raising an exception with a `jupyterhub_message` attribute.
This will be a string displayed as escaped HTML (HTML is not allowed).
2019-04-05 10:22:47 +02:00
Min RK
6fa3b429db include retry link after failed spawn 2019-04-01 17:05:58 +02:00
Min RK
e89836c035 Merge pull request #2495 from minrk/service-oauth-state-typo
typo raising error on missing oauth state
2019-04-01 17:05:44 +02:00
Min RK
784b5cb6f0 ensure default server exists in the db at user creation
avoids issues in e.g. all_spawners being empty
2019-04-01 17:05:23 +02:00
Min RK
daaa763c3b allow oauthlib 3
requires updating our is_absolute_uri check
2019-04-01 17:04:59 +02:00
Min RK
2b18c64081 Merge pull request #2497 from minrk/mysql-connector-python
[travis] trade mysql-connector for mysql-connector-python
2019-04-01 17:04:30 +02:00
Min RK
785addc245 mysql-connector-python in test_db 2019-04-01 16:47:46 +02:00
Min RK
b4758db017 specify native auth plugin for mysql testing
sha2 plugin isn't available on travis
2019-04-01 16:31:36 +02:00
Min RK
10fbfee157 travis: install mysql-connector-python
instead of mysql-connector, which is deprecated
2019-04-01 15:06:43 +02:00
Min RK
c58a251dbd typo raising error on missing oauth state
need to specify a status code
2019-04-01 14:53:35 +02:00
Min RK
27be5e4847 Changelog for 0.9.6
replace 0.9.5 which has only a partial fix

issue is now confirmed to affect all browsers
2019-04-01 12:30:16 +02:00
Min RK
be97a0c95b Further login redirect validation 2019-04-01 12:29:29 +02:00
Min RK
689a312756 Merge pull request #2490 from mathematicalmichael/patch-1
Fix 1.0 date in changelog
2019-03-29 17:08:49 +01:00
Michael Pilosov
1484869ee3 Update changelog.md
fix date
2019-03-29 08:16:55 -06:00
Min RK
74a457f6b5 guard against using get_page with full urls
since that was hard to debug
2019-03-28 17:02:41 +01:00
Min RK
137a044f96 fix flaky test_user_redirect
when re-fetching the same url, use `requests.get`, not `get_page`
2019-03-28 17:01:00 +01:00
Min RK
a090632a48 Merge pull request #2488 from minrk/post_push
Docker hook fixes
2019-03-28 16:02:50 +01:00
Min RK
451a16c57e changelog for 0.9.5 2019-03-28 13:34:22 +01:00
Min RK
6e14e86a1a protect against some browsers' buggy handling of backslash as slash 2019-03-28 13:33:23 +01:00
Min RK
a142f543ba [docker] tag stable releases with :latest 2019-03-28 13:06:18 +01:00
Min RK
0bb3996c30 [docker] fix unbound variable in post_push hook for stable releases 2019-03-28 13:05:05 +01:00
Min RK
2a23e8afea 1.0.0b1 2019-03-27 15:58:07 +01:00
Min RK
071e375d5f Merge pull request #2440 from minrk/changelog-1.0
changelog for 1.0
2019-03-27 14:45:11 +01:00
Min RK
ca2d0a58b9 add documentation for Hub page urls
with screenshots!
2019-03-27 12:03:26 +01:00
Min RK
1cfeee8808 Merge pull request #2484 from rcthomas/master
Fix server name parsing in UserUrlHandler
2019-03-27 10:40:09 +01:00
Rollin Thomas
6ff421061d Strip leading / and get server name 2019-03-26 08:17:39 -07:00
Min RK
2d049c39fc Merge pull request #2485 from bitnik/patch-1
fix dev-requirements file extension in contributing.md
2019-03-26 13:51:58 +01:00
Kenan Erdogan
5535804acb fix dev-requirements file extension in contributing.md 2019-03-26 13:45:25 +01:00
Rollin Thomas
0901fa255f Remove log testing messages 2019-03-25 15:05:45 -07:00
Rollin Thomas
3e5b272b80 Server name is second element 2019-03-25 14:50:39 -07:00
Rollin Thomas
693446dba9 Log messages 2019-03-25 13:35:29 -07:00
Min RK
12d6a744df documentation for named server UI 2019-03-25 14:14:01 +01:00
Min RK
45dcb3bd17 recommonmark 0.5
update several links (html targets don't work anymore)

had to add rest-api redirect so link would resolve,
since there isn't a ref for files in _static
2019-03-25 14:08:37 +01:00
Min RK
6de9414c2f Merge branch 'master' into changelog-1.0 2019-03-25 11:20:05 +01:00
Min RK
b1f8c31c80 More changes 2019-03-25 11:19:57 +01:00
Min RK
8032f874af Merge pull request #2434 from rkdarst/separate-proxy-docs
Add documentation on running the proxy separate from the hub [wip]
2019-03-25 10:01:23 +01:00
Min RK
c869bc34af Merge pull request #2460 from rcthomas/master
Fix to use `get_current_user()`
2019-03-25 10:00:20 +01:00
Rollin Thomas
d1c06ab603 Fix to use get_current_user() 2019-03-07 20:02:35 -08:00
Carol Willing
7653f75310 Update docs/source/changelog.md
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 16:44:13 +01:00
Carol Willing
de4ea150c0 Update docs/source/changelog.md
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 16:44:04 +01:00
Carol Willing
0fdb0df176 Update docs/source/changelog.md
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 16:43:38 +01:00
Carol Willing
6cefdba515 Update docs/source/changelog.md
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 16:43:31 +01:00
Carol Willing
b3bd236e15 Update docs/source/changelog.md
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 16:43:23 +01:00
Carol Willing
79a06fd9ac Update docs/source/changelog.md
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 16:43:13 +01:00
Carol Willing
3249574744 Update docs/source/changelog.md
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 16:42:58 +01:00
Carol Willing
7e04d1d756 Update docs/source/changelog.md
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 16:42:51 +01:00
Carol Willing
d63083bc17 Update docs/source/changelog.md
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 16:42:45 +01:00
Carol Willing
b93ec84822 Update docs/source/changelog.md
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 16:42:27 +01:00
Carol Willing
b1606f21e6 Merge pull request #2446 from minrk/persist-user-options
persist user_options
2019-03-07 07:09:52 -08:00
Min RK
437eb18dd2 Note that user_options shall be JSON+bytes
and document persistence, and no-side effects
2019-03-07 15:35:39 +01:00
Min RK
82c889861d limit special handling to bytes in user_options
uploaded form data can be bytes, which we base64-encode

don't persist any other unsupported data types, persist None instead
2019-03-07 15:30:00 +01:00
Carol Willing
6ba45ee389 Merge pull request #2457 from minrk/gitignore
ignore pip-wheel-metadata
2019-03-07 06:14:50 -08:00
Carol Willing
af0082a16b Merge pull request #2435 from minrk/named-options-form
Rework handling of /hub/user/:name
2019-03-07 05:52:48 -08:00
Min RK
4bdca83c94 ignore pip-wheel-metadata
a new temp file pip is creating
2019-03-07 10:38:14 +01:00
Min RK
4183d45ab3 create _upgrade_094 database for testing upgrades from 0.9.4 2019-03-07 10:37:16 +01:00
Min RK
674ae9b4fc Merge pull request #2455 from javabrett/javabrett-patch-1
Added -p 8000:8000 to jupyterhub Docker quick start command.
2019-03-07 10:35:37 +01:00
Min RK
ff283ae636 address review
and fix a mis-applied GitHub suggestion

suggestions can only replace one line
2019-03-07 10:33:37 +01:00
Carol Willing
76eabb2de8 comment
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 10:30:36 +01:00
Carol Willing
2fbcb16190 docstring formatting
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 10:27:54 +01:00
Carol Willing
5d5ebb2583 docstring clarification
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 10:27:20 +01:00
Carol Willing
49b9a9f017 spacing
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 10:26:53 +01:00
Carol Willing
aa60d948bb docstring formatting
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 10:26:19 +01:00
Carol Willing
37d4d0e140 Update jupyterhub/handlers/pages.py
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 10:25:28 +01:00
Carol Willing
e86622b921 quote options_form
Co-Authored-By: minrk <benjaminrk@gmail.com>
2019-03-07 10:24:01 +01:00
Min RK
0d86c4ecf5 allow arbitrary data types in JSONDicts in the db
via json default encoder and object hooks
2019-03-06 13:48:12 +01:00
Min RK
249f39cf46 Merge pull request #2447 from mpetroff/patch-1
Allow for proper logging of IP addresses when using separate TLS termination
2019-03-06 13:21:45 +01:00
Matthew Petroff
8f3532e191 Make list of trusted downstream IP addresses configurable. 2019-03-05 17:56:09 -05:00
Min RK
27d0f62cd2 Merge pull request #2444 from rkdarst/contributing-docs
Contributing: hint on pre-commiting commits that are already there
2019-03-05 09:42:16 +01:00
Matthew Petroff
a31dadacb2 Trust localhost X-headers.
Trusting localhost X-headers allows for properly logging IP addresses while
using separate TLS termination. Otherwise, they're recorded as 127.0.0.1.
2019-02-28 13:58:07 -05:00
Min RK
59fa95acf4 add 0.9.4 to list of old jupyterhub database versions to test 2019-02-28 14:42:14 +01:00
Min RK
32c3fb01d4 handle long upgrade (spawner table doesn't exist) 2019-02-28 14:41:02 +01:00
Min RK
ddc852d658 persist user_options
remember user_options from the previous run

this allows user options set via spawn form to be re-used when restarting e.g. a named server via the api
2019-02-28 14:27:47 +01:00
Brett Randall
01bc8584a2 Added -p 8000:8000 to jupyterhub Docker quick start command. 2019-02-28 11:27:54 +11:00
Richard Darst
6524f38125 Contributing: hint on pre-commiting commits that are already there 2019-02-27 19:38:04 +02:00
Richard Darst
50c16239d2 Fix extraneous bullet point at end of separate-proxy.mb 2019-02-27 19:29:36 +02:00
Richard Darst
bfdec8f22e Fix file ending, pre-commit check 2019-02-27 19:27:20 +02:00
Min RK
25aa892f86 Merge pull request #2443 from rcthomas/erase-link-on-stop
Hide/unhide link
2019-02-27 18:11:52 +01:00
Rollin Thomas
5dedfe2629 Hide/unhide link 2019-02-27 08:49:34 -08:00
Tim Head
699b317d54 Merge pull request #2438 from minrk/check-lists
suppress deprecation warnings when testing deprecations
2019-02-27 17:05:19 +01:00
Tim Head
b1622ec745 Merge pull request #2439 from minrk/catch-entrypoints
catch errors loading entrypoints when generating config
2019-02-27 16:55:52 +01:00
Min RK
3cbcddad83 [WIP] changelog for 1.0 2019-02-27 16:47:56 +01:00
Min RK
35d888e91e make sure new spawner methods are documented 2019-02-27 16:47:46 +01:00
Min RK
20be7f98f7 [doc] enable autostructify 2019-02-27 16:47:32 +01:00
Min RK
a39d8aca30 catch errors loading entrypoints when generating config
avoids an entrypoint with missing dependencies preventing help output / config file generation
2019-02-27 15:56:27 +01:00
Min RK
453ae6e97b one more wait through spawn-pending 2019-02-27 15:31:10 +01:00
Min RK
89c85aca37 if no referer is given, assume the worst
only way to avoid redirect loops if referers are not set (e.g. python requests)
2019-02-27 15:21:22 +01:00
Min RK
87c276f425 suppress deprecation warnings when testing deprecations 2019-02-27 15:09:48 +01:00
Richard Darst
4ec92f9f14 Add the separate-proxy documentation 2019-02-27 12:21:21 +02:00
Min RK
8d01b0356b test spawn-pending page 2019-02-27 11:15:15 +01:00
Min RK
81a43a588b enable debug logging in mocksu
for tests
2019-02-27 11:13:34 +01:00
Min RK
8ea5a957a6 only start ?redirects counter if we are starting from a /user/:name -> /hub/user/:name redirect 2019-02-27 11:13:10 +01:00
Min RK
fee81c7d33 handle spawn-pending in user-redirect tests 2019-02-27 09:57:58 +01:00
Min RK
0dd291ae5c one more time for the consistent test_login_redirect cases 2019-02-26 15:47:21 +01:00
Min RK
db3f62b79a try harder to make a useful error message when API requests are made to a not-running server
include link to spawn page
2019-02-26 11:57:36 +01:00
Min RK
f8add6ae6d fix local-redirect check for subdomains 2019-02-26 11:56:28 +01:00
Min RK
d1f115d951 wait for spawner to start before talking to it 2019-02-25 16:55:53 +01:00
Min RK
fab5c33796 handle spawn-pending redirects in some tests
avoids issues with assuming that spawn is quick
2019-02-25 16:10:51 +01:00
Min RK
4ab525ab5f test spawn form with named server 2019-02-25 15:57:32 +01:00
Min RK
1185619bf6 update tests for changed redirects
- handle 503 on not running /hub/user/:name
- handle new spawn-redirect page
2019-02-25 15:43:50 +01:00
Min RK
4b1d80203e redact cookie headers in error logs 2019-02-25 14:49:13 +01:00
Min RK
d8cabdb90f Merge pull request #2433 from Carreau/document_admin_group
document admin_group
2019-02-25 14:32:38 +01:00
Min RK
947b9b1a9e rework handing of /user/:name
- /user/:name no longer triggers implicit spawn at any point
- add /spawn-pending/:user/:server handler for pending page. This page has no side effects.
- spawn links point to /spawn/:user/:server to finish hooking up links for named servers and options_form handling
2019-02-25 14:21:34 +01:00
Min RK
6f63ac7831 simplify start-server links as pure links to /spawn/:user/:server
instead of API requests

this gets better progress-page loading and options form rendering
2019-02-25 13:45:02 +01:00
Min RK
0c028c7186 import parsing of Accept header
used to determine if a request expects JSON or not
2019-02-25 13:44:10 +01:00
Min RK
1498707ac9 nicer repr of Server objects
we had a nice repr on orm.Server, let's bring it back
2019-02-25 13:42:48 +01:00
Min RK
de20c3f3a7 accept default argument in get_next_url
allows different defaults for different contexts
2019-02-25 13:41:38 +01:00
Richard Darst
0df552e2a1 Add documentation on running the proxy separate from the hub.
- It took me a bit longer than I would have liked for me to figure out
  how to run the proxy separate from the hub.  When I had to do this a
  second time for a different hub, it also took me too long.
- This adds a page dedicated to running the proxy separate from the
  hub, since it is relatively easy and has a high usability
  improvement.
- Currently work in progress.
2019-02-22 16:30:14 +02:00
Matthias Bussonnier
b4c53a29a9 document admin_group 2019-02-21 21:53:29 -08:00
Matthias Bussonnier
ca67757269 Merge pull request #2432 from Carreau/entrypointsplural
Entrypoints is plural
2019-02-21 17:21:22 -08:00
Matthias Bussonnier
aaa4deeed0 Entrypoints is plural
Of course both package exists...
2019-02-21 17:19:59 -08:00
Matthias Bussonnier
bda8671807 Merge pull request #2431 from Carreau/fix-docs-builds
Entrypoint is necessary to build the API docs of most authenticators
2019-02-21 17:05:54 -08:00
Matthias Bussonnier
4d75c16335 Entrypoint is necessary to build the API docs of most authenticators 2019-02-21 11:28:02 -08:00
Min RK
b5f6547e64 Merge remote-tracking branch 'origin/master' into named-options-form 2019-02-21 13:25:20 +01:00
Carol Willing
17aee17c5f Merge pull request #2418 from minrk/autoformat
Adopt black, pre-commit
2019-02-21 02:50:04 -08:00
Min RK
2f99104f57 a couple fixups after autoformatting 2019-02-19 17:04:37 +01:00
Min RK
80519f4fd0 consistency in CONTRIBUTING.md 2019-02-19 17:01:09 +01:00
Min RK
1531e94cc7 pre-commit is a dev requirement 2019-02-19 17:00:13 +01:00
Min RK
43c3ac78fc run lint test early 2019-02-19 17:00:13 +01:00
Min RK
9cc6aa9b6d describe pre-commit setup in CONTRIBUTING.md 2019-02-19 17:00:13 +01:00
Min RK
031cb6076a run pre-commit on travis
to verify that autoformatting has been run

include hopefully helpful message if it fails
2019-02-19 17:00:13 +01:00
Min RK
5e60582ef3 run autoformat
apologies to anyone finding this commit via git blame or log

run the autoformatting by

    pre-commit run --all-files
2019-02-19 17:00:10 +01:00
Min RK
ca198e0363 add pre-commit config
various simple fixes (space, newlines), plus two big ones:

- reorder imports
- run black
2019-02-19 16:59:11 +01:00
Min RK
d14a4bbe2c add black configuration 2019-02-19 16:59:11 +01:00
Min RK
ada8582768 pass flake8 on examples
define flake8 builtins for config files (c, get_config)
2019-02-19 16:59:11 +01:00
Min RK
856923b35f Merge pull request #2308 from vilhelmen/post_auth_hook
post_auth_hook processor
2019-02-19 16:56:27 +01:00
Min RK
39902a7140 async fixes in post_auth_hook 2019-02-19 16:07:32 +01:00
Will Starms
8524556b33 Add croutine support, force dict return
Also fix weird typo in example code
2019-02-15 15:37:23 +01:00
Will Starms
7c36ac93ba post_auth_hook processor
Does what it sounds like, allows an arbitrary function to be called right before the return in `get_authenticated_user`
2019-02-15 15:36:03 +01:00
Min RK
fec3d959f2 Merge pull request #2268 from vilhelmen/auth_data_sharing
Share authenticated dict with auth functions
2019-02-15 15:33:36 +01:00
Min RK
52d8f74eb1 Merge pull request #2397 from rkdarst/pam_normalize_username
pam_normalize_username option: round-trip usernames through PAM to normalize
2019-02-15 15:17:28 +01:00
Min RK
701b93d226 check_group_whitelist is optional 2019-02-15 15:09:56 +01:00
Min RK
bb83bb47d8 auth: apply adaptation to deprecated signature in init
applies/warns in init, ensures compatibility with a wrapper

rather than warning/calling differently at call time, which won't take effect everywhere
2019-02-15 13:22:06 +01:00
Min RK
1ba47d4a3d Merge branch 'master' into auth_data_sharing 2019-02-15 13:03:09 +01:00
Min RK
8c76f2b30c Merge pull request #2414 from minrk/threads
add an additional case for idle ThreadPoolExecutor threads
2019-02-15 11:16:30 +01:00
Min RK
a7c3ea0906 Merge pull request #2346 from minrk/push-activity
push last_activity to the hub
2019-02-15 11:16:12 +01:00
Min RK
fa2cb33b27 Merge pull request #2415 from consideRatio/async-options-form
Allow callable options_form to return an empty form
2019-02-15 10:49:32 +01:00
Erik Sundell
32706963ae Add test for falsy callable options_form 2019-02-14 16:50:07 +01:00
Erik Sundell
fb4c920996 Allow callable options_form to return an empty form
Closes #2390

This is meant to allow us dynamically decide to bypass the option form
even though it is a async function that in itself evaluates truthy.
2019-02-14 16:49:27 +01:00
Min RK
370ec4f5c7 remove unused sp
we need to ensure the spawners exist,
but we do that when we set last_activity
2019-02-14 16:01:51 +01:00
Min RK
5e77e448bd add an additional case for idle ThreadPoolExecutor threads
this is what they look like in Python 3.7
2019-02-12 16:00:07 +01:00
Min RK
7c46fe74a5 Merge pull request #2413 from minrk/redirect
add missing trailing slash in / -> /hub/ redirect
2019-02-12 15:04:47 +01:00
Min RK
dcdb8d8a89 add missing trailing slash in / -> /hub/ redirect 2019-02-11 17:29:45 +01:00
Min RK
087dd0fcd2 Merge pull request #2330 from Deepakdubey90/jupyterhub-oracle-integration
Modified JSON-DICT Implementation from TEXT to Text
2019-02-11 16:41:47 +01:00
Min RK
33a139861b notmybestwork: avoid updating user activity with server api access
this isn't the most important metric (server.last_activity is),
but avoid *probable* server api access incrementing user.last_activity
2019-02-11 16:18:37 +01:00
Min RK
d8d1b6c149 test activity api 2019-02-11 16:17:23 +01:00
Min RK
a2f5a0bea9 tolerate mocks for user.name
lots of testing uses mock Users, so tolerate the absence of user.escaped_name
2019-02-11 15:34:46 +01:00
Min RK
0063752a7f push activity to hub via api
servers publish activity on a regular interval (default: 5m)
2019-02-11 15:03:17 +01:00
Min RK
297f6988bd debug logs at beginning/end of user.stop 2019-02-11 15:03:17 +01:00
Richard Darst
a6d217d113 pam_normalize_username: add docs 2019-02-07 01:35:18 +02:00
Min RK
e51ea3f2be s/TEXT/Text/ 2019-02-06 14:02:08 +01:00
Min RK
bf36f9fc9a use Text instead of TEXT
TEXT is wrong on Oracle, LargeBinary is wrong everywhere else.

Text seems to be the high-level type that maps to the right thing both places.
This results in no change on supported implementations, as Text == TEXT there.
2019-02-06 13:47:40 +01:00
Min RK
b196dd2bea add activity spec to rest api 2019-02-06 13:15:42 +01:00
Min RK
10191f43fe add alabaster_jupyterhub to docs/requirements.txt 2019-02-06 13:15:11 +01:00
Min RK
342f40c8d7 Merge pull request #2404 from minrk/deprecations
fix some deprecation warnings in tests
2019-02-05 13:49:12 +01:00
Min RK
895bc378df Merge branch 'master' into deprecations 2019-02-05 13:06:28 +01:00
Min RK
00cafc8392 Merge pull request #2342 from minrk/expire-auth
allow auth to expire
2019-02-05 13:05:00 +01:00
Min RK
a6d0c36594 allow bypassing proxy in api_request
needed when testing that the proxy is down
2019-02-05 12:40:55 +01:00
Min RK
71a8573fdb fix some deprecation warnings in tests
Calling HasTraits(attr=value) doesn't work for non-traits

1. remove one redundant assignment for a non-trait
2. make one attribute a trait
2019-02-05 11:38:42 +01:00
Min RK
2715607361 make api requests via public url
to ensure cookies are properly set
2019-02-05 11:27:49 +01:00
Min RK
f2bfe6cd96 set Referer when testing cookie-authenticated api requests
Referer is checked for cookie-authenticated requests
2019-02-04 16:10:09 +01:00
Min RK
9008d5eea4 import mock from stdlib 2019-02-04 15:46:12 +01:00
Min RK
d340fc056e import mock from stdlib 2019-02-04 15:45:47 +01:00
Min RK
f3e1b95147 Merge pull request #2402 from consideRatio/readme-badge
Opinionated update of badges
2019-02-04 15:42:48 +01:00
Min RK
b5aa53fe7b only refresh auth of Users 2019-02-04 12:57:10 +01:00
Min RK
96c16bfb85 missing escape in normalize_timestamp 2019-02-04 12:56:53 +01:00
Richard Darst
d33226f3c2 Don't use super() when normalizing username using PAM
- We don't need the extra normalization of that function.
- Also add in username_map support here.  It probably isn't needed
  most of the time with PAM, but it keeps things consistent and is
  easier than documenting an exception.
2019-02-03 00:37:06 +02:00
Erik Sundell
78fe52bfb8 Remove google group badge 2019-02-02 14:59:28 +01:00
Erik Sundell
383cd6e73d Add github/discourse/gitter badges 2019-02-02 14:59:16 +01:00
Erik Sundell
25fa0f739f Remove 0.7.2 docs badge 2019-02-02 14:58:45 +01:00
Min RK
919b6a8d6c Merge pull request #2375 from dtaniwaki/limit-nb-num-per-user
Limit max named server per user
2019-01-31 13:33:14 +00:00
Richard Darst
92223b1dde pam_normalize_username option: round-trip usernames through PAM to normalize 2019-01-28 13:43:29 +02:00
Daisuke Taniwaki
9a0f7286bc Add tests for named server limit 2019-01-19 16:27:30 +09:00
Daisuke Taniwaki
71f2b73c36 Update error message of named server limit 2019-01-19 15:48:35 +09:00
Daisuke Taniwaki
b34bdd2846 Limit max named server per user 2019-01-19 15:48:35 +09:00
Min RK
392e432071 Merge pull request #2377 from minrk/travis-upgrade
add upgrade to pip install
2019-01-16 16:40:10 +01:00
Min RK
09e48546ab pin oauthlib < 3
while we work out why 3 doesn't work anymore
2019-01-16 15:54:58 +01:00
Min RK
77ecdbe12a add upgrade to pip install
to ensure version compatibility
2019-01-08 14:38:39 +01:00
Min RK
1431c5a21a test coverage for auth expiry 2019-01-04 11:54:20 +01:00
Min RK
8c63f669a9 consolidate some test utilities in utils
instead of in test_api, test_pages

since they are used in a few places

also add user, username fixtures for generating test users
2019-01-04 11:03:20 +01:00
Min RK
c009b39795 auth_refresh_age is on Authenticator 2019-01-03 12:36:47 +01:00
Min RK
dfd808b90e Merge pull request #2344 from adelcast/dev/adelcast/quotes_fix
Spawner.py: do not quote Popen args
2019-01-03 11:58:34 +01:00
Min RK
75e46fc111 Merge pull request #2370 from dnelson86/patch-1
Update docs: deployments
2019-01-03 11:57:43 +01:00
Min RK
337a0118c0 Merge pull request #2365 from rcthomas/change-id-to-class-named-servers
Change id selector to class selector for named servers
2019-01-03 11:56:34 +01:00
Dylan Nelson
2ee355d6a4 Update docs: deployments
Add IllustrisTNG public data release deployment.

Also add link for MIT, and delete jcloud.io (seems to no longer exist).
2018-12-30 15:04:21 +01:00
Min RK
4fa0876d91 implement refresh_pre_spawn
- redirect to login if vanlig user spawn
- fail with 400 otherwise
2018-12-21 15:32:58 +01:00
Alejandro del Castillo
46d4e2898d get_args: only quote if necessary
Traitlets require quotes around literals, to avoid interpreting them as
as datatypes other than string. However, quotes are problematic on the
notebook_dir case. On Windows, Popen will mis-interpret the quotes and
escape them, which trips the process spawn. To avoid problems, only
quote if necessary.

Signed-off-by: Alejandro del Castillo <alejandro.delcastillo@ni.com>
2018-12-20 17:24:47 -06:00
Rollin Thomas
4e410473cb Fix to find element 2018-12-20 13:35:36 -08:00
Rollin Thomas
fdddd7d58c Change select from id to class for multiple choice 2018-12-20 13:03:36 -08:00
Min RK
563106c0d2 allow auth to expire
adds Authenticator.auth_refresh_age and Authenticator.refresh_pre_spawn config

- auth_refresh_age allows auth to expire (default: 5 minutes) before calling Authenticator.refresh_user.
- refresh_pre_spawn forces refresh prior to spawn (in case of auth tokens, etc.)
2018-12-14 15:27:38 +01:00
Min RK
b6d8db5259 Merge pull request #2322 from ausecocloud/master
UserTokenListAPIHandler support Authenticator.authenticate returning a dict
2018-12-14 12:43:46 +01:00
Min RK
5e67bd773f Merge pull request #2205 from willingc/bump-dep
bump bootstrap version
2018-12-14 12:43:16 +01:00
Min RK
aaab44090d bootstrap 3.4.0 2018-12-14 10:58:21 +01:00
Min RK
7b154fcc45 Merge branch 'master' into master 2018-12-14 10:51:47 +01:00
Min RK
d2779061b0 Merge pull request #2358 from minrk/rm-pytest-tornado
switch from pytest-tornado to pytest-asyncio
2018-12-14 10:44:24 +01:00
Min RK
3e20642b31 Merge pull request #2359 from minrk/deprecated-event.listen
use non-deprecated event to register foreign_keys connection listener
2018-12-14 10:44:09 +01:00
Min RK
a46032b549 use non-deprecated event to register foreign_keys connection listener 2018-12-12 15:41:09 +01:00
Min RK
8ca8225cef Python 3.5-friendly async context manager 2018-12-12 13:45:36 +01:00
Min RK
0e6cf6a485 Merge pull request #2353 from vilhelmen/pam_admin_groups_fix
Fix PAMAuthenticator is_admin
2018-12-12 13:43:38 +01:00
Min RK
37cdba370f update tests for pytest-asyncio
- remove gen_test marker
- use async def
- find/replace yield->await approximately one million times
2018-12-12 13:06:10 +01:00
Min RK
d5f87fe09f update fixtures for pytest-asyncio
instead of pytest-tornado

verify that we don't make any async generator tests
which would pass silently without running any tests
2018-12-12 12:49:54 +01:00
Min RK
2930fa9cc9 Merge pull request #2355 from chang-zhijie/master
accept token in Authorization header in services, not just url
2018-12-11 15:34:48 +01:00
chang-zhijie
53c3201c17 store tokens passed via url or header, not only url. 2018-12-11 17:00:16 +08:00
Will Starms
4229d68d23 Fix bad tester/code 2018-12-06 15:32:49 -06:00
Tim Head
8b0bdc71bc Merge pull request #2347 from minrk/one-flakey-flake
Don’t mix no_patience and bad_spawn
2018-12-04 17:54:31 +01:00
Min RK
47e66580db Don’t mix no_patience and bad_spawn
this introduces a race between the early RuntimeError being tested
and the no_patience causing handlers to return early if async start isn’t complete.

With tornado coroutines, an early RuntimeError could be guaranteed to resolve promptly, but asyncio isn’t as consistent,
possibly causing some of the recent flaky tests.
2018-12-04 15:02:53 +01:00
Tim Head
c360777ee0 Merge pull request #2345 from jupyterhub/willingc-patch-1
Update incorrect anchor
2018-12-04 08:08:03 +01:00
Carol Willing
05874e9f81 Update incorrect anchor
Closes #2338
2018-12-03 20:33:22 -08:00
Tim Head
c3e1d5313d Merge pull request #2343 from clemens-tolboom/patch-1
Fix markdown link into rst
2018-12-03 22:09:54 +01:00
Clemens Tolboom
4b36dce29f Fix markdown link into rst 2018-12-03 19:05:50 +01:00
Chia-liang Kao
d84ad44b74 actually spawn with server_name 2018-12-02 21:28:05 +08:00
Chia-liang Kao
b60468d2b6 _render_form requires server_name as well 2018-12-02 21:07:45 +08:00
Chia-liang Kao
35d041a701 fix regex 2018-12-02 20:14:50 +08:00
Chia-liang Kao
045ba0671b Support named server with option form 2018-12-02 16:07:38 +08:00
Min RK
bbc2847530 Merge pull request #2297 from minrk/check-url-startup
handle partial launches on startup
2018-11-30 15:11:27 +01:00
Min RK
887f2a2c24 it's spawner.name 2018-11-29 17:14:29 +01:00
Min RK
2b265b2529 Check if a Spawner is running at the given URL on startup
avoids assuming partial spawns that may have resulted in running processes but not actually available servers
are treated as fully working servers.
2018-11-28 12:44:58 +01:00
Min RK
f0da8a75b0 Merge pull request #2333 from kinow/remove-auth-unused-dependency
Remove unused import
2018-11-28 12:43:29 +01:00
Bruno P. Kinoshita
9aa2110409 Remove unused dependency 2018-11-28 14:41:48 +13:00
pydeepak
047bd4e7cc Fixed incorrect import 2018-11-27 08:42:28 +05:30
pydeepak
10d781c570 Modified Json Implementation from Text to LargeBinary. 2018-11-27 08:39:46 +05:30
Gerhard Weis
c2aa7f1748 call base handler self.authenticate instead of accessing authenticator directly 2018-11-27 06:41:36 +10:00
Min RK
4ace113965 Merge pull request #2326 from minrk/document-api-options
Document specifying spawn options via api
2018-11-26 14:26:16 +01:00
Min RK
69933e240f document specifying options via rest api 2018-11-23 16:06:38 +01:00
Gerhard Weis
9ac6ed344c UserTokenListAPIHandler should support Authenticator.authenticate returning a dict 2018-11-22 14:33:48 +10:00
Min RK
c9c0d3723b Merge pull request #2309 from adelcast/dev/adelcast/refresh_user
refresh_user: add handler parameter
2018-11-16 14:52:55 +01:00
Min RK
c09876cbe2 Merge pull request #2315 from adelcast/dev/adelcast/move_pwd
LocalSpawner: move pwd module import inside functions
2018-11-16 14:52:38 +01:00
Min RK
6bb4d27a3f Merge pull request #2313 from adelcast/dev/adelcast/entry_points
setuptools entrypoints instead of scripts
2018-11-16 14:45:10 +01:00
Min RK
48c3a3a834 Merge pull request #2307 from vilhelmen/getpwnam_dedupe
getgrnam/getpwnam/getgrouplist refactor
2018-11-16 14:44:12 +01:00
Alejandro del Castillo
24dcb4b783 LocalSpawner: move pwd module import inside functions
Windows doesn't have a pwd module. To avoid an import error on Windows,
move import statement inside functions that use pwd.

Signed-off-by: Alejandro del Castillo <alejandro.delcastillo@ni.com>
2018-11-15 16:08:30 -06:00
Will Starms
22d6f48bb8 Make functions private 2018-11-15 15:20:34 -06:00
Alejandro del Castillo
df98fb012e refresh_user: add handler parameter
The current request handler might be needed to determine if the auth
data needs to be refreshed.

Signed-off-by: Alejandro del Castillo <alejandro.delcastillo@ni.com>
2018-11-15 13:21:24 -06:00
Min RK
ea44ab0c85 Merge pull request #2312 from choldgraf/roadmap
[MRG] moving the roadmap to this repo
2018-11-15 19:55:35 +01:00
Alejandro del Castillo
b1759c8882 setup.py: add automatic script generation
Use setuptools console_scripts functionality to create top level jupyter
& jupyterhub-single user entry point scripts on *nix, and executables on
Windows.

Signed-off-by: Alejandro del Castillo <alejandro.delcastillo@ni.com>
2018-11-15 09:53:29 -06:00
Min RK
c633d87f1e Merge pull request #2296 from pelson/logo_in_page_template
Add a logo block, and update the docs regarding base.html.
2018-11-15 12:44:15 +01:00
Min RK
680e829824 Merge pull request #2303 from minrk/check-in-cache
HubAuth: allow caching None responses
2018-11-15 12:26:38 +01:00
Chris Holdgraf
891a352f42 updating circle for docs and adding a roadmap 2018-11-14 21:20:26 -08:00
Will Starms
df829e8927 Move getpwnam/grnam/grouplist to LocalAuthenticator
Also fix up an old test of mine
2018-11-13 14:48:12 -06:00
Will Starms
f2ae3af90e Switch to existing getpwnam function
To be honest, `getgrouplist`, `getpwnam`, and `getgrnam` should be static methods in LocalAuthenticator
2018-11-13 13:53:54 -06:00
Will Starms
62b991649b Share authenticated dict with auth functions
Adds a compatibility fix to be removed at a future date for the check_x functions.
2018-11-13 11:44:49 -06:00
Min RK
767dce29f4 Merge pull request #2301 from DataVictorEngineer/patch-1
Apache reverse proxy customization for jupyterhub
2018-11-12 14:41:19 +01:00
Min RK
7f1c91d8f4 Clear the auth cache when testing the same url twice with different results 2018-11-12 14:35:47 +01:00
Min RK
3a0bacde3a HubAuth: allow caching None responses
when a token doesn't identify a user, the response is None.
These results are cached, but the cache checked for `is None`,
causing failed-auth responses to effectively not be cached.
2018-11-12 12:56:41 +01:00
DataVictorEngineer
7f12418e4c Apache reverse proxy customization for jupyterhub
This is the modification to run the Jupyterhub using the custom url: http://127.0.0.1:8000/jhub/.
2018-11-11 22:45:30 +02:00
Min RK
40013f7292 Merge pull request #2298 from katsar0v/master
improve condition when failing api request, check if user exists, aft…
2018-11-09 20:56:07 +01:00
Kristiyan
2070c8c102 improve condition when failing api request, check if user exists, afterwards check if user is not active 2018-11-09 18:17:40 +01:00
Min RK
eb19a73044 add Spawner.get_url
for retrieving the spawner url. Occurs on startup.

Default is a no-op and no Spawner needs to implement this.
2018-11-09 13:22:08 +01:00
Phil Elson
87ce499840 Add a logo block, and update the docs regarding base.html. 2018-11-09 06:36:17 +00:00
Min RK
9a3dbedc52 Merge pull request #2290 from katsar0v/master
add configuration for shutting down all user spawners on logout
2018-11-08 14:50:47 +01:00
Min RK
0cebb4c9d7 disable pytest minversion check
because it doesn't work with current pytest
2018-11-08 14:36:00 +01:00
Yuvi Panda
fc25b0e10d Merge pull request #2289 from minrk/move-simple
make simplespawner importable
2018-11-07 10:44:17 -08:00
Min RK
006b89746a use stop_single_user wrapper to stop user servers
rather than lower-level spawner.stop
2018-11-06 14:31:42 +01:00
Min RK
1f7838ba5f ensure async-requests is awaitable
so we can use await, not just yield
2018-11-06 14:30:51 +01:00
Min RK
e5e6876cef test shutdown_on_logout 2018-11-06 14:30:26 +01:00
Kristiyan
2686615304 add configuration for shutting down all user spawners on logout 2018-11-05 11:47:46 +01:00
Min RK
e512847652 use simplespawner as base for testing 2018-11-05 11:01:21 +01:00
Min RK
4fb158933e no-op move_certs in simplespawner 2018-11-05 11:01:06 +01:00
Min RK
575af23e23 register simplespawner in setup.py 2018-11-05 10:57:10 +01:00
Min RK
52c468d89c make home_dir a traitlet
so the property is only evaluated once and overrideable via hooks
2018-11-05 10:57:02 +01:00
Min RK
80e241c86f move simplespawner into jupyterhub.spawner 2018-11-05 10:55:40 +01:00
Min RK
c8199c6303 Merge pull request #2244 from vilhelmen/pam_admin_groups
admin_groups for PAMAuthenticator
2018-11-05 10:49:38 +01:00
Min RK
090f68bb21 Merge pull request #2264 from minrk/better-local-error
explain create_system_users when system users do not exist
2018-11-05 10:47:14 +01:00
Tim Head
5b4f0d4304 Merge pull request #2282 from yuvipanda/real-async-pre-spawn-hook
Document that pre_spawn_hook maybe a coroutine
2018-11-03 08:38:42 +01:00
yuvipanda
1efb8c765b Document that pre_spawn_hook maybe a coroutine 2018-11-02 17:19:16 -07:00
Will Starms
1c0d0daef8 admin_groups for PAMAuthenticator
Hoist admin status determination from authentication to a secondary function called by get_authenticated_user
Create mock objects for struct_group and struct_passwd, migrate existing mock group objects to it
Remove old admin mock stuff for authenticate
2018-10-30 11:26:37 -05:00
Min RK
302573e860 Merge pull request #2224 from tuhina2020/jupyter_2105
add metrics_authentication decorator to /metrics API #2105
2018-10-26 10:47:36 +02:00
Min RK
5e58fc60d4 Merge pull request #2260 from madmax2012/master
[docker] Bumped Miniconda to 4.5.11
2018-10-26 10:47:12 +02:00
Min RK
1322926d9b explain create_system_user when system users do not exist 2018-10-26 10:05:23 +02:00
Max Mensing
a64fa15fee Bumped Miniconda to 4.5.11 2018-10-24 09:36:55 +02:00
Min RK
71c620f38f Merge branch 'master' into jupyter_2105 2018-10-23 10:10:31 +02:00
Min RK
65d9ac3c61 Merge pull request #2257 from tmshn/health-check
Added health check endpoint
2018-10-23 09:52:14 +02:00
tmshn
f752e6df1e Added health check endpoint 2018-10-20 15:41:52 +09:00
Carol Willing
19bcb9cea0 Merge pull request #2255 from minrk/parallel-coverage
unpin coverage
2018-10-19 10:28:53 -07:00
Min RK
7b22330583 unpin coverage
need run.parallel = True in coveragerc to fix database errors with coverage 5

exclude the resulting .coverage.host.pid files in gitignore
2018-10-19 14:03:13 +02:00
Min RK
1be2b3721a Merge pull request #2243 from vilhelmen/write_error_log_fix
Try to create exception str before logging
2018-10-19 10:27:16 +02:00
Min RK
e53488cd64 Merge pull request #2253 from Carreau/sudo-selinux
Cleanup the sudo/selinux section
2018-10-19 09:33:47 +02:00
Min RK
fe5ca1a67e Merge branch 'master' into jupyter_2105 2018-10-19 09:31:45 +02:00
Matthias Bussonnier
0670423a3d Cleanup the sudo/selinux section 2018-10-18 14:03:00 -07:00
Min RK
e9620df5b5 Merge pull request #2249 from adibaba/master
Added Paderborn University
2018-10-18 10:39:36 +02:00
tuhina2020
2a425f4344 fix tests for unauthorised call to metrics API 2018-10-18 12:42:24 +05:30
Adrian Wilke
ee63002f21 Added Paderborn University 2018-10-17 21:28:38 +02:00
Min RK
2d94b2999f Merge pull request #2055 from LLNL/end-to-end-ssl
End-to-end SSL
2018-10-17 13:27:03 +02:00
Min RK
7a055e65db Catch and print errors stopping hub
in case it failed to fully start
2018-10-17 13:05:20 +02:00
Min RK
e385214121 empty groups, too 2018-10-17 13:04:42 +02:00
Min RK
b0116ee539 avoid cleaning users when we are testing resume 2018-10-17 11:02:06 +02:00
Min RK
301fed30b2 Delete users in MockHub
avoids pollution from one test module to the next
2018-10-17 10:38:19 +02:00
tuhina2020
e449b9c193 fix the condiiton for authentation 2018-10-17 10:39:00 +05:30
Will Starms
bafcf6bd23 Try to create exception str before logging
The str() method of an InterfaceError can raise when trying to iterate over an integer, causing the logger to act up.
2018-10-16 14:00:03 -05:00
Min RK
15788bec67 ensure user's own subdomain is in trusted alt names 2018-10-16 15:57:45 +02:00
Min RK
e921354544 run internal-ssl tests with external http
to cover any protocol mismatches
2018-10-16 15:57:45 +02:00
Min RK
eb7648abc2 consolidate trusted alt names
- trust subdomain_host by default
- JupyterHub.trusted_alt_names is inherited by Spawners by default. Do we need Spawner.ssl_alt_names to be separately configurable?
2018-10-16 15:46:50 +02:00
Min RK
9a45f4a8c9 add user- prefix to user cert dirs
avoids possible conflict e.g. if a user had the name 'hub-internal'
2018-10-16 15:45:49 +02:00
Min RK
1f3165859f avoid unnecessarily recreating proxy certs 2018-10-16 15:45:20 +02:00
Min RK
2d6e7186aa Merge pull request #2240 from GeorgianaElena/master
Small improvement of test coverage
2018-10-16 13:58:29 +02:00
GeorgianaElena
efde40cbbd Small improvement of test coverage 2018-10-16 12:40:18 +03:00
Min RK
f3c2a15e53 ensure AsyncIOMainLoop is registered in tests 2018-10-15 16:29:00 +02:00
Min RK
d64853a6f5 fix ssl tmpdir in tests
must be module-scoped, not session-scoped, or it will get reused inconsistently
2018-10-15 15:35:21 +02:00
Min RK
b72d887dd7 register cleanup before start
avoids leaving lingering proxy if app fails to start
2018-10-15 15:33:59 +02:00
Min RK
49ebf969c1 Merge pull request #2237 from spacetelescope/master
Add handler to spawner so you can access query params in form
2018-10-15 13:56:41 +02:00
tuhina2020
1a6b16d493 fix metrics_authentication method 2018-10-15 11:27:11 +05:30
Carol Willing
6fd7e27e95 Merge pull request #2234 from minrk/proxy-entrypoint
add entrypoint for configuring proxies
2018-10-12 10:49:34 -07:00
Min RK
28c6377db7 avoid modifying headers in-place
can have consequences if args are re-used
2018-10-12 17:05:59 +02:00
Min RK
67f21bb518 ssl tests can use configproxy 2018-10-12 16:26:42 +02:00
Min RK
7c0e113fbc Revert "Set change-origin so certs behind proxy work"
This reverts commit bcebf0ee7b.

Setting change-origin introduces CORS problems
2018-10-12 16:24:10 +02:00
Min RK
bc3ace60dc Merge branch 'master' into end-to-end-ssl 2018-10-12 16:17:26 +02:00
Min RK
ce2310b1ae update proxy docs to mention entrypoints 2018-10-12 11:11:13 +02:00
Min RK
6979a11bfa Merge pull request #2236 from mpolidori/master
Fix missing spaces in if statement in bootstrap-script and README
2018-10-12 11:10:10 +02:00
mpolidori
10a4ac4809 Update README.md 2018-10-12 00:50:30 -04:00
mpolidori
34341e7aac Update bootstrap.sh 2018-10-12 00:48:49 -04:00
tuhina2020
ac7ff491e1 Add tests for metrics API 2018-10-12 09:26:52 +05:30
Min RK
abd3bc13d2 add entrypoint for proxy implementations 2018-10-11 16:54:25 +02:00
Jacob Matuskey
ebed5c2f4b Add handler to spawner here so you can access query params in form rendering 2018-10-10 20:25:14 -04:00
Thomas Mendoza
bcebf0ee7b Set change-origin so certs behind proxy work 2018-10-09 16:25:23 -07:00
Min RK
95ee2cb709 Merge pull request #2220 from tuhina2020/master
Add server_stop_duration_seconds prometheus metric #14
2018-10-09 11:23:18 +02:00
Min RK
9faecccc9c Merge pull request #2223 from DeepHorizons/process_options_form
Let the options_from_form function be async
2018-10-08 16:03:59 +02:00
Min RK
49babdcae9 Merge branch 'master' into 2220 2018-10-08 16:02:27 +02:00
Min RK
ef3b29bc5d Merge pull request #2226 from minrk/pin-coverage
pin coverage due to bug in coveragepy 5 prerelease
2018-10-08 13:34:40 +02:00
Min RK
a2da7a5080 pin coverage due to bug in coveragepy 5 prerelease 2018-10-08 13:22:37 +02:00
Min RK
f37e44a6f7 Merge pull request #2225 from kuriakinzeng/master
correcting time.pref_counter to time.perf_counter in proxy.py
2018-10-08 13:01:43 +02:00
Kuriakin Zeng
d45b2a7c70 change time.pref_counter to time.perf_counter in proxy.py as pref_counter is invalid 2018-10-07 21:53:35 +08:00
tuhina2020
b0b7e8d25d add metrics_authentication decorator to /metrics API 2018-10-07 13:38:32 +05:30
Joshua Milas
7eba029d1f Let the options_from_form function be async
This commit lets users who interact with spawners and use options_form
to use an async function to process the form.
2018-10-05 23:18:27 -04:00
Thomas Mendoza
82d12b3eeb Merge branch 'end-to-end-ssl' of github.com:LLNL/jupyterhub into end-to-end-ssl 2018-10-05 16:02:31 -07:00
Thomas Mendoza
dd07495624 Fix public_url call with ssl testing enabled 2018-10-05 15:59:10 -07:00
tuhina2020
8783df8d8d binary statuses for SERVER_STOP_DURATION_SECONDS metric 2018-10-06 00:01:03 +05:30
Min RK
d4cce8cdff Merge pull request #2219 from kshitija08/metric_addition
Adding CHECK_ROUTES_DURATION_SECONDS metric #2183
2018-10-05 14:18:02 +02:00
Min RK
8a17afb6e3 Merge pull request #2221 from minrk/html5lib
add html5lib to test requirements
2018-10-05 14:12:33 +02:00
Min RK
2bbfde40f0 add html5lib
this is needed for bs4.
I'm not sure why it was there before, but not anymore
2018-10-05 14:03:27 +02:00
Min RK
7cf230ec1f Merge pull request #2218 from Carreau/no-backticks-commands-substitution
Use $() for command substitution instead of backticks/quotes.
2018-10-05 14:01:56 +02:00
tuhina2020
c5e2789324 Add SERVER_STOP_SECONDS metric 2018-10-05 10:33:58 +05:30
kshitija08
5d96076587 metrics.py 2018-10-05 10:25:07 +05:30
Matthias Bussonnier
2e872069fb Use $() for command substitution instead of backticks/quotes.
One of the example was using quotes instead of backticks.
Backticks are the "older" way of doing things, which has a number of
disadvantes:

    http://mywiki.wooledge.org/BashFAQ/082

Here I'm more worried about readability as depending on font and "smart"
editor helping on the web, many people may confuse ` with ', it could
end up modifying formatting on makrdown powered website... etc...
2018-10-04 13:44:16 -07:00
kshitija08
ae51870db5 user.py 2018-10-04 20:29:30 +05:30
kshitija08
7409ccad66 base.py 2018-10-03 22:02:10 +05:30
Min RK
cff066a7be Merge pull request #2210 from nils-werner/service-sys-executable
Replace python with sys.executable in most service examples
2018-10-03 10:43:56 +02:00
Min RK
a198124894 ssl tests need CHP master for now 2018-10-02 18:40:01 +02:00
Min RK
58f6659e40 implement .move_certs in dummy MockSpawner 2018-10-02 18:16:47 +02:00
Min RK
bd16299ffb Merge pull request #2207 from GeorgianaElena/master
add server_poll_duration_seconds prometheus metric
2018-10-02 13:41:29 +02:00
Min RK
7656adc8b0 expand logging of ssl cert creation 2018-10-02 13:11:40 +02:00
Min RK
4b3f9e5f42 more descriptive 'internal-ssl' certs location
and update/clarify ssl-related docstrings
2018-10-02 11:23:26 +02:00
Min RK
febb7c32c1 make alt names attributes on Spawner instead of args to create_certs 2018-10-02 11:21:38 +02:00
Min RK
94bb9ed00d remove NOTEBOOK from internal ssl env 2018-10-02 11:20:36 +02:00
Min RK
5fbd4f2d4e call make/move certs at a higher level
mostly to allow them to be async
2018-10-02 11:20:36 +02:00
Min RK
50f1decee7 move local-process move_certs implementation to LocalProcessSpawner 2018-10-02 11:20:36 +02:00
Min RK
c3176b0ca3 Do not set ownership in create_certs
Most Authenticators do not have local users, so this doesn't make sense at this stage
2018-10-02 11:20:36 +02:00
Min RK
f29354e0f4 Merge branch 'master' into end-to-end-ssl 2018-10-02 11:15:53 +02:00
GeorgianaElena
67b774faca fix missing import and resolve class attributes 2018-10-02 11:58:33 +03:00
Nils Werner
a08a839385 Replace python with sys.executable in most service examples 2018-10-02 09:42:54 +02:00
GeorgianaElena
425078652e add status as a label for server_poll_duration_seconds metric 2018-10-02 09:38:00 +03:00
Thomas Mendoza
76a6959cf0 Test to ensure connections with improper certs fail 2018-10-01 16:48:03 -07:00
Thomas Mendoza
b7b5cf2f2d Fix spawner tests for running with internal_ssl 2018-10-01 16:48:03 -07:00
Thomas Mendoza
2ff067be6d Formatting change only 2018-10-01 16:48:03 -07:00
Thomas Mendoza
2cd6a9e720 Supply certs to individual async_requests 2018-10-01 16:48:03 -07:00
Thomas Mendoza
ca33692459 Only test internal_ssl if the value is set in request 2018-10-01 16:48:03 -07:00
Thomas Mendoza
32bd8aa105 Verify the self-signed certs for the proxy 2018-10-01 16:48:03 -07:00
Thomas Mendoza
080ff7043e Set appropriate protocol for bind_url 2018-10-01 16:48:03 -07:00
Thomas Mendoza
c5102452e4 Move turning ssl on into __init__ 2018-10-01 16:48:03 -07:00
Thomas Mendoza
99f2905cab Use certs if available for test_api 2018-10-01 16:48:03 -07:00
Thomas Mendoza
34d59f66d9 Setup mock services to use certs from env 2018-10-01 16:48:03 -07:00
Thomas Mendoza
88b2954c90 Missed change in mocksu to pick up certs from env 2018-10-01 16:48:03 -07:00
Thomas Mendoza
d1aeff7bbf Fix issue where Mockub was not seeing ssl_enabled flag 2018-10-01 16:48:03 -07:00
Thomas Mendoza
371ef6cad8 Spawn under name 'service' if no username exists 2018-10-01 16:48:03 -07:00
GeorgianaElena
053b038e74 Merge branch 'master' of https://github.com/jupyterhub/jupyterhub 2018-10-01 18:31:18 +03:00
Min RK
acdd9bb674 Merge pull request #2203 from minrk/entrypoints
allow spawners and authenticators to register via entry points
2018-10-01 17:22:11 +02:00
Tim Head
bc4844df3f Merge pull request #2208 from choldgraf/pip
pip command update
2018-10-01 10:29:39 +02:00
Chris Holdgraf
372af86250 rst code syntax in docs 2018-09-29 09:09:31 -07:00
Thomas Mendoza
a13f4197d4 Move proxy cert creation into .init_internal_ssl 2018-09-28 16:33:18 -07:00
Yuvi Panda
356e71709a Merge pull request #2197 from minrk/rm-null-string
Expand DummyAuthenticator docstring
2018-09-28 16:00:49 -07:00
Chris Holdgraf
c48988afcb pip command update 2018-09-28 12:00:28 -07:00
GeorgianaElena
48b0658a52 add server_poll_duration_seconds prometheus metric 2018-09-28 20:20:14 +03:00
Carol Willing
9fa4106c04 bump bootstrap version 2018-09-28 07:45:22 -07:00
Min RK
8a7ab7bc78 Merge pull request #2198 from kshitija08/master
spawners/simplespawner.py
2018-09-28 13:47:18 +02:00
Min RK
d3ae59eea6 Merge branch 'master' into master 2018-09-28 13:46:24 +02:00
kshitija08
6a7cb3dcc8 jupyterhub_config.py 2018-09-28 17:14:05 +05:30
Min RK
7f2050b522 expand docstring for DummyAuthenticator 2018-09-28 10:12:15 +02:00
Min RK
3c35aeb9a8 remove null password
preserve password type by using Falsy empty string for no password set
2018-09-28 10:11:03 +02:00
Min RK
c02ab23b3d allow spawners and authenticators to register via entrypoints
jupyterhub.authenticators for authenticators, jupyterhub.spawners for spawners

This has the effect that authenticators and spawners can be selected by name instead of full import string (e.g. 'github' or 'dummy' or 'kubernetes')
and, perhaps more importantly, the autogenerated configuration file will include a section for each installed and registered class.
2018-09-28 10:08:10 +02:00
Min RK
3a06310d37 Merge pull request #2201 from kyla-harper/master
Add DummyAuthenticator documentation
2018-09-28 10:05:27 +02:00
Kyla Harper
22b9a5e5dc Add DummyAuthenticator tests 2018-09-27 21:36:45 -05:00
kshitija08
75fd4b2525 jupyterhub_config.py 2018-09-27 23:04:36 +05:30
Kyla Harper
a78655c5a7 Add DummyAuthenticator documentation 2018-09-27 11:42:06 -05:00
Min RK
fa79e233b7 Merge pull request #2196 from choldgraf/copybutton
add a copy button to code cells
2018-09-27 14:13:56 +02:00
kshitija08
1e174e1abc tetsing/ 2018-09-27 16:48:22 +05:30
kshitija08
a87b2e680c init.py 2018-09-27 16:44:28 +05:30
Min RK
ec6123d39d include sphinx-copybutton in docs/requirements.txt 2018-09-27 12:58:51 +02:00
kshitija08
f381c2e649 spawners/simplespawner.py 2018-09-27 16:17:37 +05:30
Tim Head
5c3530cc7f Merge pull request #2195 from yuvipanda/better-upgrade
Expand & update documentation on upgrading JupyterHub
2018-09-27 09:56:08 +02:00
yuvipanda
6ca5b3aa70 Fixup upgrade toctree in index.rst 2018-09-27 00:16:24 -07:00
yuvipanda
e6a5dd1273 Fixes per @betatim & @choldgraf 2018-09-27 00:13:07 -07:00
yuvipanda
358b830747 Expand & consolidate upgrade documentation
- Expands the previous documentation on upgrading JupyterHub
  to include more information.
- Remove specific documentation on 0.7 -> 0.8 upgrade, since
  this seems to be a straight copy of the markdown version of
  upgrading docs. The important thing about the 0.7 -> 0.8 upgrade
  (requiring versions of JupyterHub to match) is now in the
  main document.
- Move from markdown to rst
2018-09-26 23:53:51 -07:00
yuvipanda
a91e94dd16 Re-order 'upgrading' section in main documentation page
Info on upgrading is important & relevant. This consolidates
the index to be a bit better. Next step is to consolidate the
documentation into one page.

Removes the 'tutorials' index page as well, since that only
had a reference to z2jh (which is now referenced from the
'distribution' section). The distribution section has
better visibility too
2018-09-26 23:53:19 -07:00
Chris Holdgraf
26f31a11f7 Merge pull request #2194 from yuvipanda/pip-cleanup
Use python3 -m pip explicitly in docs
2018-09-26 23:20:10 -04:00
Chris Holdgraf
3dc0a8388b copy button 2018-09-26 18:34:51 -04:00
Yuvi Panda
acc1fe9274 Merge pull request #2193 from kyla-harper/master
Add DummyAuthenticator
2018-09-26 12:17:08 -07:00
yuvipanda
7c273296c2 Use python3 -m pip explicitly in docs
- Add a documentation convention listing this too.

Fixes #2191
2018-09-26 12:14:43 -07:00
Kyla Harper
815034f0f1 Merge branch 'master' of https://github.com/jupyterhub/jupyterhub 2018-09-26 14:04:15 -05:00
Min RK
c8c39aa40d Merge pull request #2154 from minrk/named-ui
named-server UI
2018-09-26 14:28:30 +02:00
Min RK
b34119c908 Merge pull request #2190 from yuvipanda/contributing-docs
Expand contributing docs
2018-09-26 13:24:52 +02:00
yuvipanda
b9331dbd57 Reformat index.rst to get linkable sections
Currently, the sections in index.rst are using ** for bold,
rather than true section headers. This prevents them from being
linkable. Since we'd like to link to the 'contributing' section
from CONTRIBUTING.md, we change this by moving everything to
section headers. We also move to the toctree directive, since
it keeps the bullets aligned properly (they were hanging if
we used simple * markers)

This also replaces CONTRIBUTING.md content with a link to
the docs.
2018-09-25 18:35:38 -07:00
yuvipanda
c928d10316 Expand contributor documentation
- Move from CONTRIBUTING.md to a subdirectory in docs, so
  we can expand and add more documentation.
- Move from markdown to reStructuredTest
- Add a direct blurb in the JupyterHub docs index page on
  how contribution.
- More prominent link to the Code of Conduct
- Add section on getting in touch with the JupyterHub community
2018-09-25 18:19:09 -07:00
Kyla Harper
b43125e9e8 Add DummyAuthenticator 2018-09-25 15:44:05 -05:00
Min RK
451dccfbf4 Merge pull request #2181 from minrk/docs-ci
move docs to their own CI matrix
2018-09-24 16:49:05 +02:00
Min RK
eb8b9c4d98 implement server deletion client-side 2018-09-24 16:21:40 +02:00
Min RK
e79b43e906 support removing named servers 2018-09-24 16:21:40 +02:00
Min RK
a1dc73882a move helper properties onto orm.Spawner
since that's where they belong
2018-09-24 16:21:40 +02:00
Min RK
0fb78f19ec return future from stop_single_user
allows chaining actions when stop finally resolves via `spawner._stop_future`
2018-09-24 16:21:40 +02:00
Min RK
81a410db91 simplify admin UI for named servers 2018-09-24 16:21:40 +02:00
Min RK
924aeb4abb only include named spawners in all_spawner is named servers allowed 2018-09-24 16:21:40 +02:00
Min RK
b966258849 Simplify named-servers on home
- use a table for the list of servers
- support adding new servers
2018-09-24 16:21:40 +02:00
Min RK
9031b9aa57 add some re-usable APIs
define some pending/ready helpers as static constants on orm.Spawner

allows treating orm.Spawner the same as Spawner wrappers,
as long as `.active` etc. checks are performed first
2018-09-24 16:21:40 +02:00
Min RK
cbe4095533 use var instead of let
for better js compatibility
2018-09-24 16:21:40 +02:00
Min RK
1be278779d add npm run fmt for autoformatting js 2018-09-24 16:21:40 +02:00
Min RK
8c9d2f0c4f npm run fmt 2018-09-24 16:21:40 +02:00
Min RK
76fc077e3b Merge pull request #2180 from minrk/progress-cleanup
Fix intermittent failures in progress_bad_slow
2018-09-24 16:20:24 +02:00
Min RK
8e6d9de536 move docs to their own CI matrix
rather than building the docs after every test
2018-09-24 16:02:27 +02:00
Min RK
93045957a0 Warn instead of raising if spawner._generate_progress is called while spawn is not pending
and generate no events if not pending

Reason: race condition is unavoidable between first pending check and check inside _generate_progress.
In this event, return immediately.
2018-09-24 15:54:01 +02:00
Min RK
e71d181a23 slow down slow_bad_spawn
reduces likelihood of race condition in test
2018-09-24 15:54:01 +02:00
Min RK
fcbc6e06c8 stop keepalive loop promptly on finish
rather than waiting until keepalive_interval, which leaves idle coroutines for at least 8 seconds
2018-09-24 15:54:01 +02:00
Min RK
33c6e68b5e update changelog for 0.9.4 2018-09-24 14:01:23 +02:00
Min RK
a4d241524c Merge pull request #2177 from nils-werner/patch-1
Example homedir bootstrapping using `mkhomedir_helper`
2018-09-24 13:36:24 +02:00
Min RK
af1c71f7ff Merge pull request #2179 from minrk/disable-pdf
back to conda on rtd
2018-09-24 12:56:37 +02:00
Min RK
78c57805d5 omit pdf builds on rtd due to bug in sphinx 2018-09-24 12:48:11 +02:00
Min RK
cc324a6d4b back to conda for docs 2018-09-24 12:47:47 +02:00
Min RK
8437f47f36 Merge pull request #2165 from minrk/fix-content-type
Fix content-type on API endpoints
2018-09-24 11:03:19 +02:00
Min RK
89bde5db17 Merge pull request #2176 from GeorgianaElena/master
Issue #13 Outreachy: add running_servers metric
2018-09-24 10:37:20 +02:00
GeorgianaElena
f43ebe8d51 Rename metric 2018-09-24 11:05:01 +03:00
Nils Werner
341bc42d95 Example homedir bootstrapping using mkhomedir_helper 2018-09-24 10:01:57 +02:00
GeorgianaElena
493f9ab331 Issue #13 Outreachy: add running_servers metric 2018-09-23 18:31:37 +03:00
Yuvi Panda
e9753fd65d Merge pull request #2174 from jmfcodes/typofix
fixed a typo
2018-09-22 15:14:00 -07:00
Jennifer
3b136339af fixed a typo 2018-09-22 14:57:24 -07:00
Yuvi Panda
1821c21243 Merge pull request #2166 from minrk/testing-config
add sample configuration that loads dummyauthenticator and simplespawner
2018-09-21 10:58:44 -07:00
Min RK
e675ab85c7 Merge pull request #2164 from sashafierce/add-name-controlpanel
Add user name to control panel in JupyterHub
2018-09-21 15:16:19 +02:00
Min RK
58f005eea2 Fix content-type on API endpoints
and includes content-type header checks in tests to catch regressions
2018-09-21 15:12:53 +02:00
Min RK
d34e84ae9d add sample configuration that loads dummyauthenticator and simplespawner 2018-09-21 15:12:41 +02:00
Akanksha Bhardwaj
981ef2ca3b display username in control panel 2018-09-21 18:08:34 +05:30
Min RK
c87fcd9b71 Merge pull request #2155 from minrk/cleanup-client-fix
fix oauth client cleanup
2018-09-21 10:10:34 +02:00
Min RK
c69adfb506 Merge pull request #2161 from yuvipanda/better-contrib
Add notes on simplespawner & dummyauthenticator
2018-09-21 10:10:04 +02:00
Min RK
ac82f0f437 apply willingc's text proposals 2018-09-21 10:07:21 +02:00
Carol Willing
c975f7eb4a Merge pull request #2162 from yuvipanda/other-auth-cleanup
Link additional authenticators to wiki
2018-09-21 02:13:50 -04:00
yuvipanda
07b590e2c3 Link additional authenticators to wiki
The current list in the docs is out of date. The list
in the wiki is more up-to-date, and easier for folks
to change over time. In the long run, we should decide
where lists like this belong.
2018-09-20 22:49:00 -07:00
Erik Sundell
0b98be05fd Add links to default spawner & authenticator 2018-09-20 22:11:48 +00:00
yuvipanda
0a54b1aa99 Add notes on simplespawner & dummyauthenticator 2018-09-20 13:01:49 -07:00
Erik Sundell
e114f79e44 Merge pull request #2159 from yuvipanda/better-contrib
Expand 'Setting up Developer Environment' in CONTRIBUTING.md
2018-09-20 20:43:48 +02:00
yuvipanda
3ff046affa Expand 'Setting up Developer Environment' in CONTRIBUTING.md 2018-09-20 11:31:00 -07:00
Carol Willing
e26229c0b4 Merge pull request #2156 from willingc/pin-sphinx
Build docs with pip not conda
2018-09-19 20:25:39 -07:00
Carol Willing
6c000968c9 reset dependencies 2018-09-19 14:46:56 -07:00
Carol Willing
8d79be7cfb switch to requirements and pip 2018-09-19 14:46:36 -07:00
Carol Willing
25264a43cf update oauthlib dependency in docs 2018-09-19 14:45:00 -07:00
Min RK
4cd4fd1dff changelog for 0.9.4 2018-09-19 12:48:21 +02:00
Min RK
e2a899327f fix oauth client cleanup
- delete oauth clients for servers when they shutdown
- avoid deleting oauth clients for servers still running across an 0.8 -> 0.9 upgrade, when the oauth client ids changed from `user-NAME` to `jupyterhub-user-NAME`
2018-09-19 12:45:41 +02:00
Carol Willing
56601d93c3 Merge pull request #2149 from minrk/deprecate-maybe-future
stop using deprecated `gen.maybe_future`
2018-09-17 20:08:57 -07:00
Min RK
f2fa067025 Merge pull request #2089 from krinsman/master
UI for Named Servers (Home and Admin Pages)
2018-09-17 13:04:42 +02:00
William Krinsman
02cb5ec076 Handle named servers in UserSpawnHandler, home, admin pages
Made CSS and HTML (and Jinja2) of admin page compatible with named servers.
2018-09-17 11:54:51 +02:00
Min RK
571ca2dec6 Merge pull request #2142 from minrk/async-current-user-2
make `.get_current_user` async
2018-09-17 10:49:25 +02:00
Min RK
35a95b5f0c stop using deprecated gen.maybe_future
we already covered supported cases since we are using tornado 5,
so handle the scalar case ourselves, as recommended in the deprecation
2018-09-14 14:13:31 +02:00
Min RK
ce9d9fd26d clarify docstrings, comments in refresh_user
- refresh_user may return True in the common case, identifying that everything is up-to-date
- return False for "needs login"
- return auth_data dict when an update can be performed without logging in again
2018-09-13 10:28:10 +02:00
Min RK
d79a99323e make .get_current_user async
- `.get_current_user` is called in the `prepare` stage for all handlers
- use `.current_user` to access current user in methods
- adds Authenticator.refresh_user for refreshing user auth (unused at this point)
2018-09-13 10:16:13 +02:00
Thomas Mendoza
a81972067a Stop servers that don't get cleaned up
Running all tests (including internal_ssl
monkey-patched ones) leaves behind some
spawned servers. Stop them.
2018-09-12 17:48:31 -07:00
Thomas Mendoza
67f19a65b7 Use Certipy's trust graph to set up internal_ssl
With changes to CHP requiring a second, different
authority, the complexity of managing trust within
JupyterHub has risen. To solve this, Certipy now
has a feature to specify what components should
trust what and builds trust bundles accordingly.
2018-09-12 17:46:39 -07:00
Carol Willing
a21b496d48 Merge pull request #2144 from willingc/comm-guide
Add link to Jupyter Community Guide
2018-09-12 10:12:35 -07:00
Carol Willing
7ff49705bc fix typo 2018-09-12 08:41:05 -07:00
Carol Willing
6dc43dd70b add link to community guide reference 2018-09-12 08:39:07 -07:00
Min RK
42c78a8ba7 Merge pull request #2143 from minrk/fixup-progress
remove spurious print from keepalive code
2018-09-12 09:45:14 +02:00
Min RK
54449562bd remove spurious print from keepalive code
and send keepalive every 8 seconds

to protect against possibly aggressive proxies dropping connections after 10 seconds of inactivity
2018-09-11 16:50:48 +02:00
Min RK
e29fad06ed write needs no await 2018-09-11 16:41:27 +02:00
Matthias Bussonnier
f1a5c7da55 Merge pull request #2141 from minrk/093
changelog for 0.9.3
2018-09-11 13:41:50 +02:00
Min RK
0239ff8646 changelog for 0.9.3
Mainly small fixes, but the token page could be completely broken

This release will include the spawner.handler addition,
but not the oauthlib change currently in master
2018-09-11 11:06:31 +02:00
Min RK
e4a64bd129 Merge pull request #2127 from minrk/oauthlib
switch to oauthlib from python-oauth2
2018-09-11 11:01:51 +02:00
Min RK
a0354de3c1 Merge pull request #2139 from minrk/token-page
token expiry fixes
2018-09-11 11:01:37 +02:00
Min RK
2e4e1ce82f test token page with html parsing 2018-09-11 10:16:36 +02:00
Min RK
1f0ea679e5 clarify messages per review 2018-09-11 09:00:19 +02:00
Min RK
06f646099f token expiry fixes
typos in token expiry:

- omitted from token model (it's in the spec in docs, but wasn't in the model)
- wrong type when sorting oauth tokens on token page could cause token page to not render
2018-09-11 08:54:12 +02:00
Min RK
3360817cb6 Merge pull request #2138 from SivaMaplelabs/undefined-variable
Fix undefined variable 'datetime' error
2018-09-11 08:52:59 +02:00
Min RK
b84e929e8c skip oauthlib absolute-uri check
because we want to allow relative redirect uri for internal oauth
2018-09-10 17:12:08 +02:00
Min RK
df74ff68ab better error messages on oauth errors 2018-09-10 17:12:08 +02:00
SivaMaplelabs
e042ad0b4a Fix undefined variable 'datetime' error 2018-09-10 20:04:54 +05:30
Min RK
246f9f9044 Merge pull request #2135 from adelcast/dev/adelcast/fix_chp
add Windows case when stopping the CHP
2018-09-10 15:19:14 +02:00
Min RK
03aa48a88c update tests with oauth confirmation
cross-user / service oauth tests must submit oauth confirmation form
to complete authorization
2018-09-10 15:18:12 +02:00
Min RK
de54056005 add oauth confirmation page
users accessing their own servers still don't require confirmation,
but accessing other users' servers or services shows a confirmation page.
2018-09-10 14:31:19 +02:00
Min RK
5e2c133669 flesh out oauth provider
- avoid logging credentials
- implement some missing methods
2018-09-10 14:26:40 +02:00
Min RK
4fc4cfe2cc move oauth.store to oauth.provider
since it defines the provider!
2018-09-10 11:09:52 +02:00
Alejandro del Castillo
bc08f4de34 proxy: add Windows case when zombie proxy is still running
Windows doesn't support signal.SIGKILL, which is used by
_check_previous_process to kill the CHP if still running. Use existing
implementation to kill the CHP and children processes on Windows
instead.

Signed-off-by: Alejandro del Castillo <alejandro.delcastillo@ni.com>
2018-09-06 18:06:16 -05:00
Alejandro del Castillo
12904ecc32 _check_previous_process: use signal list as input to os.kill
Previously, signal.SIGTERM was using 3 times, instead of using it 2
times, then signal.SIGKILL.

Signed-off-by: Alejandro del Castillo <alejandro.delcastillo@ni.com>
2018-09-06 16:15:56 -05:00
Matthias Bussonnier
601d371796 Merge pull request #2132 from willingc/iss204
fix link
2018-09-06 10:16:17 +02:00
Carol Willing
30d9e09390 fix link 2018-09-05 11:27:19 -07:00
Thomas Mendoza
ca33ccd66d Add longer internal_ssl documentation to main docs 2018-09-04 15:51:26 -07:00
Thomas Mendoza
84deb1fa7a Update doc strings for create_certs and move_certs 2018-09-04 15:50:45 -07:00
Thomas Mendoza
2a0e5d90e6 Add the ability to generate JupyterHub's certificates
This is used to be able to access JupyterHub's CA
information and (manually) move it to components
that need them (like externally managed proxies).
2018-09-04 15:22:49 -07:00
Thomas Mendoza
3c05033481 Update cert generation to use Certipy's new API
To better accommodate external certificate management
as well as building of trust, Certipy was refactored.
This included general improvements to file and
record handling. In the process, some of Certipy's
APIs changed slightly, but should be more stable now
going forward.
2018-09-04 15:08:12 -07:00
Min RK
7850a5d478 Merge pull request #2036 from minrk/pass-handler
pass requesting handler to spawner
2018-09-04 18:27:02 +02:00
Min RK
f84c73eb15 [wip] switch to oauthlib from python-oauth2
lower-level implementation, but more robust and gives us more control
2018-09-04 15:10:58 +02:00
Min RK
f5a3b1bc5a Merge pull request #2122 from SivaMaplelabs/pylint-fix
Address the pylint warnings
2018-09-04 09:58:13 +02:00
SivaMaplelabs
b2fe8e5691 Address the pylint warnings 2018-09-03 21:35:46 +05:30
Min RK
9d4c410996 include params in redirect from /spawn -> /user/:name 2018-09-03 09:57:00 +02:00
Min RK
dcae92ce4a test passing url params to spawner 2018-09-03 09:56:42 +02:00
Carol Willing
29957b8cd8 Merge pull request #2112 from minrk/disable-quit
disable quit button
2018-08-30 22:47:13 -07:00
Carol Willing
6299e0368c Merge pull request #2119 from Carreau/typoes
Fix some typos using `codespell`.
2018-08-30 15:44:55 -07:00
Carol Willing
c862b6062d Merge pull request #2121 from minrk/progress-keepalive
add keepalive to progress eventstream
2018-08-30 15:43:18 -07:00
Min RK
146587ffff add keepalive to progress eventstream
avoids issues with proxies dropping connections when no data passes through

Progress behavior should already be resilient to dropped connections,
as the progress ought to just resume anew.
2018-08-30 19:03:14 +02:00
Matthias Bussonnier
077d8dec9a Fix some typos using codespell.
And checking each manually. It's funny because one of the words in the
sphinx custom dictionary was wrong :-)
2018-08-29 21:24:28 -07:00
Min RK
af8d6086fc disable quit button
quit button (new in recent notebook 5.x) shuts down the server, which we want to happen via the JupyterHub control panel
2018-08-27 16:18:53 +02:00
Min RK
18f8661d73 publish singleuser x.y.z.dev from master 2018-08-20 10:42:46 +02:00
Min RK
bd70f66c70 Merge pull request #2094 from minrk/image-dev-tag
add .dev suffix to development x.y image tags
2018-08-20 10:38:02 +02:00
Min RK
ac213fc4b5 add .dev suffix to development x.y image tags
instead of publishing "1.0" for a development version.
2018-08-20 10:37:43 +02:00
Min RK
db33549173 Merge pull request #2092 from minrk/stable-0.9
fix jupyterhub/singleuser tagging
2018-08-17 16:44:37 +02:00
Min RK
e985e2b84c singleuser stable version is 0.9 2018-08-17 16:33:42 +02:00
Min RK
1d9abf7528 back to dev 2018-08-17 16:30:24 +02:00
Min RK
935baa8bc6 Merge pull request #2080 from minrk/rel-0.9.2
prepare to release 0.9.2
2018-08-11 14:50:15 +02:00
Min RK
9b77732319 Merge pull request #2078 from minrk/fix-pin-attrs
move attrs pinning to dev-requirements
2018-08-10 13:59:09 +02:00
Min RK
85aac0fa2d prepare to release 0.9.2 2018-08-10 13:56:58 +02:00
Min RK
abd6f35638 Merge pull request #2067 from NERSC/announcement-service-example
Add an example simple announcement service
2018-08-10 12:25:24 +02:00
Min RK
ba4700b3f3 move attrs pinning to dev-requirements
it shouldn’t be in the package’s own requirements, which are propagated to users
2018-08-10 11:51:24 +02:00
Min RK
05b11bd47a Merge pull request #2072 from gesiscss/master
fix links in services doc
2018-08-10 11:40:58 +02:00
Kenan Erdogan
71cb628563 fix links in services doc 2018-08-06 11:11:14 +02:00
Rollin Thomas
0d664355f0 Some explanatory comments 2018-08-03 12:15:50 -07:00
R. C. Thomas
dd6261d031 Merge pull request #1 from NERSC/test-announcement-service-example
Use `hub_users=[]` and `allow_admin=True`
2018-08-02 09:55:23 -07:00
Rollin Thomas
f3f5b69e49 Try hub_users=[] and allow_admin=True 2018-08-02 09:00:46 -07:00
Tim Head
9ea4ca3646 Merge pull request #2065 from minrk/cull-named-servers
cull-idle: fix deletion of named servers
2018-08-02 07:55:27 +01:00
Rollin Thomas
8ee9869ca0 Add an example simple announcement service 2018-08-01 16:11:30 -07:00
Min RK
6cedd73d2a Merge pull request #2062 from chaoleili/master
Ensure request uri with trailing slash
2018-08-01 10:17:58 +02:00
Min RK
59145ca0f7 fix deletion of named servers
first submitted to zero-to-jupyterhub
2018-08-01 10:07:02 +02:00
Thomas Mendoza
9607edcc23 Return a dict instead of a tuple from move_certs 2018-07-27 17:03:12 -07:00
Thomas Mendoza
e082b923e0 Clarify output directory name for user certs 2018-07-27 16:44:24 -07:00
Thomas Mendoza
dd4df873b4 Move internal_ssl init into an init function 2018-07-27 16:41:33 -07:00
Chaolei Li
ab02f9c568 Ensure request uri with trailing slash
When request uri matching with base_url in PrefixRedirectHandler,
it's better to ensure uri with tariling slash. That's will avoid
redirecting /foobar to /foobar/hub/foobar.
2018-07-27 17:17:26 +08:00
Thomas Mendoza
3adbfe315e Pass certfile info via env instead of args 2018-07-26 17:05:50 -07:00
Thomas Mendoza
6000a84ffc Remove certs from the Server orm 2018-07-26 14:29:58 -07:00
Min RK
a2f003ed31 Merge pull request #2060 from betatim/docs-env-update
Update dependencies used by ReadTheDocs
2018-07-26 15:35:59 +02:00
Tim Head
7b6dd9f5cf Update dependencies used by ReadTheDocs 2018-07-26 12:53:19 +02:00
Min RK
0fa5c20f89 Merge pull request #2042 from minrk/abort-failures
add Spawner.consecutive_failure_limit
2018-07-26 10:33:36 +02:00
Min RK
204399ee2c Merge pull request #2040 from minrk/sigterm-fix
fix SIGTERM handling
2018-07-26 10:32:25 +02:00
Min RK
5e68dce02f Merge pull request #2057 from adelcast/dev/adelcast/fix_pid_removal
proxy: make process existance check Windows friendly
2018-07-26 10:32:00 +02:00
Alejandro del Castillo
952bbea039 proxy: make process existance check Windows friendly
Currently, to check if the proxy is running, os.kill(pid,0) is used,
which doesn't work on Windows. Wrapped call into a new function that
adds a Windows case.

Signed-off-by: Alejandro del Castillo <alejandro.delcastillo@ni.com>
2018-07-24 15:47:40 -05:00
Tim Head
630e85bfec Merge pull request #2050 from Carreau/https
Switch protocols to https in docs links
2018-07-24 06:09:26 +01:00
Matthias Bussonnier
26f7bb51bd Pin attrs to version greater than 17.4 or jsonschema 3.0.0a fails.
This is strange as JsonSchema already pin to higher than that.
2018-07-23 14:57:45 -07:00
Thomas Mendoza
d429433bb2 Add Certipy to requirements now that its in PyPI 2018-07-23 13:41:34 -07:00
Thomas Mendoza
5de870be41 Fix docstring 2018-07-23 13:41:20 -07:00
Thomas Mendoza
1fc75086aa Remove vague try-catch 2018-07-23 13:41:20 -07:00
Thomas Mendoza
fa3437c09a Add db migration for ssl changes to servers 2018-07-23 13:41:20 -07:00
Thomas Mendoza
01b27645fb Set http[s] as appropriate for the singleuser url 2018-07-23 13:41:19 -07:00
Thomas Mendoza
373c3f82dd SSL setup for testing
Setup general ssl request, not just to api

Basic tests comprised of non-ssl test copies

Create the context only when request is http

Refactor ssl key, cert, ca names

Configure the AsyncHTTPClient at app start

Change tests to import existing ones with ssl on

Override __new__ in MockHub to turn on SSL
2018-07-23 13:41:09 -07:00
Matthias Bussonnier
a1c2a50810 Switch protocols to https in docs links
Chrome will start to show insecure website for http next week
2018-07-22 18:58:22 -07:00
Thomas Mendoza
5c39325104 Only import certipy if internal_ssl is turned on 2018-07-18 16:02:57 -07:00
Thomas Mendoza
0304dd0040 Allow option to specify ssl_context in wait_up 2018-07-18 16:02:57 -07:00
Thomas Mendoza
a549edfd75 Testing internal ssl modifications 2018-07-18 16:02:57 -07:00
Thomas Mendoza
25e6b31a5f Only internal_ssl kwargs if internal_ssl is enabled 2018-07-18 16:02:57 -07:00
Thomas Mendoza
3c21e7d45b Server cert info into objects and orm 2018-07-18 16:02:57 -07:00
Thomas Mendoza
7c6972df7e Remove unnecessary flag, forward-ssl
Import socket when needed

Move pwd import since more than one thing uses it.
2018-07-18 16:02:57 -07:00
Thomas Mendoza
753bd0701f Create and move certs for use with spawned notebooks
Add Localhost to trusted alt names

Update to match refactored certipy names

Add the FQDN to cert alt names for hub

Ensure notebooks do not trust each other

Drop certs in user's home directory

Refactor cert creation and movement

Make alt names configurable

Make attaching alt names more generic

Setup ssl_context for the singleuser hub check
2018-07-18 16:02:57 -07:00
Thomas Mendoza
c5faf2c5ea Use certipy to automate cert creation 2018-07-18 16:02:57 -07:00
Thomas Mendoza
c50cd1ba7f Propagate certs to everything that needs them 2018-07-18 16:02:57 -07:00
Thomas Mendoza
a69e906c6e Add config and wiring for enabling internal ssl in app 2018-07-18 16:02:57 -07:00
Thomas Mendoza
f7f4759bde Build ssl_context as util, wait_up with context 2018-07-18 16:02:57 -07:00
Min RK
906abcc2f3 add Spawner.consecutive_failure_limit
The Hub will exit if consecutive failure count reaches this threshold

Any successful spawn will reset the count to 0

useful for auto-restarting / self-healing deployments such as kubernetes/systemd/docker where restarting the Hub

default is disabled, since it would bring down the Hub if it’s not an auto-restarting deployment
2018-07-16 12:07:26 -07:00
Min RK
5269370e4a fix SIGTERM handling
raise SystemExit on sigterm instead of calling atexit directly

- ensure fresh asyncio eventloop is created (not just IOLoop)
- makes cleanup more likely to run (one source of orphaned proxies)
2018-07-16 11:49:40 -07:00
Min RK
897f5f62d5 pass requesting handler to spawner
allows Spawners to implement logic such as processing GET params to select inputs

USE WITH CARE because this gives authors of links the ability to pass parameters to spawn without user knowledge or input.

This should only be used for things like selecting from a list of all known-good choices, e.g. a profile list.
2018-07-13 17:23:19 -05:00
Min RK
727356870a Merge pull request #2027 from adelcast/dev/adelcast/fix_services_windows
_ServiceSpawner: add 'SYSTEMROOT' to environment if Windows
2018-07-13 13:24:49 -05:00
Alejandro del Castillo
39aed3a5a0 _ServiceSpawner: add 'SYSTEMROOT' to environment if Windows
Python 3 cannot be started without SYSTEMROOT environment variable.
Otherwise, CryptAcquireContext() is unable to find a dll.

https://bugs.python.org/issue20614

Signed-off-by: Alejandro del Castillo <alejandro.delcastillo@ni.com>
2018-07-06 14:47:19 -05:00
Min RK
ed26578717 back to dev 2018-07-04 11:59:43 +02:00
Min RK
22863f765f 0.9.1 2018-07-04 11:55:42 +02:00
Min RK
b500bd002b Merge pull request #2014 from willingc/bump-testing
add python 3.7 to travis
2018-07-04 11:02:55 +02:00
Carol Willing
aca40b24c3 remove env 2018-07-03 16:32:05 -07:00
Carol Willing
b5fe5a80c6 remove 3.7 from python list but leave in matrix 2018-07-03 14:57:58 -07:00
Carol Willing
ad073dd5dd add 3.7 to travis matrix 2018-07-03 14:44:09 -07:00
Carol Willing
7b815558c6 Merge pull request #2021 from minrk/091-changes
Prepare changelog for 0.9.1
2018-07-03 14:27:01 -07:00
Min RK
55f58b3ba7 review, note proxy prefix fix 2018-07-03 15:12:30 +02:00
Min RK
e1f93a4721 Merge pull request #2009 from BerserkerTroll/patch-2
proxy.py: Respect base_url in add_hub_route
2018-07-03 13:36:48 +02:00
Min RK
2e95f3c039 Merge branch 'master' into patch-2 2018-07-03 13:29:54 +02:00
Min RK
b0ba51f209 host-based routing doesn't support wildcards 2018-07-03 12:27:24 +02:00
Min RK
89e6c2110e add hub.routespec
this is the routespec for sending requests to the hub

It is [host]/prefix/ (not /hub/) so it receives all
requests, not just those destined for the hub
2018-07-03 12:05:21 +02:00
Min RK
7dfdc23b4e Prepare changelog for 0.9.1 2018-07-03 11:44:37 +02:00
Min RK
4c7df53a8a Merge pull request #2020 from weatherforce/master
Fix a couple of typos in the technical reference documentation
2018-07-03 11:23:36 +02:00
Alex Marandon
678afd3783 Fix a couple of typos 2018-07-03 11:16:55 +02:00
Carol Willing
0185a08f32 Merge pull request #2015 from minrk/allow_remote
disable host checking in upcoming notebook app
2018-07-02 08:45:41 -07:00
Tim Head
f3787dd2c8 Merge pull request #2016 from minrk/spawner-docs
mention get_env and get_args in spawner reference
2018-06-30 09:59:38 +02:00
Min RK
30f19cfc8c mention get_env and get_args in spawner reference
these are important and usually required (especially get_env) for custom Spawner implementations
2018-06-29 14:46:08 +02:00
Min RK
a84fa38c6b ensure prefix is on next_url in test_pages 2018-06-29 14:21:32 +02:00
Min RK
867ce4c213 use app.base_url in Proxy.check_routes
rather than assuming '/'
2018-06-29 14:19:20 +02:00
Min RK
005118e09d disable upcoming host checking in single-user notebook application 2018-06-29 11:55:47 +02:00
Carol Willing
04ce67ee71 add python 3.7 to travis 2018-06-28 08:47:04 -07:00
Min RK
31807929cb update test expectations for proxy state
expect app.base_url instead of unconditional ‘/‘
2018-06-27 12:46:13 +02:00
Min RK
cb4105b53e Merge pull request #2012 from josemonsalve2/master
c.LocalProcessSpawner.shell_cmd configuration option does not work
2018-06-27 12:39:19 +02:00
Carol Willing
151887dd56 Merge pull request #2008 from minrk/services-localhost
managed services always talk to hub on localhost
2018-06-26 12:07:29 -07:00
Carol Willing
5f97487184 Merge pull request #2001 from minrk/auto-spawn-api
avoid triggering a spawn from API requests to a not-running server
2018-06-26 12:04:10 -07:00
Carol Willing
4d2d677777 Merge pull request #1996 from minrk/proxy-cleanup
use pid file to check for previous proxy instances
2018-06-26 12:02:54 -07:00
Jose M Monsalve Diaz
6a3b3807c9 fixing shell_cmd attribute of the LocalProcessSpawner that was not tag for configuration 2018-06-25 17:07:39 -04:00
Min RK
02a52a0289 Merge pull request #1997 from gesiscss/master
fix wrong/missing closing tags in templates
2018-06-25 12:54:36 +02:00
BerserkerTroll
7bd1e387df proxy.py: Respect base_url in add_hub_route 2018-06-24 17:22:43 +03:00
Min RK
edc0d7901f services always talk to hub on localhost
When the Hub listens on all ips by default, the connection ip is the hostname.

in some cases (e.g. certain kubernetes deployments) the hub’s container’s hostname is not connectable from itself, preventing managed services from connecting to the hub.

This ensures that managed service processes talk to the hub over localhost in this case, rather than via the hostname.
2018-06-22 13:48:34 +02:00
Min RK
8e561f1c12 avoid triggering a spawn from API requests to a not-running server
this avoids left-open notebook tabs from respawning a culled server indefinitely
2018-06-20 14:57:41 +02:00
Kenan Erdogan
24d87c882f fix wrong/missing closing tags in templates 2018-06-19 09:15:18 +02:00
Min RK
1e333e2f29 Merge pull request #1992 from willingc/doc-toc
add templates and user env docs to home page index
2018-06-18 15:45:52 +02:00
Carol Willing
a507fa1c8a add templates and user env docs to home page index 2018-06-16 10:21:33 -07:00
Min RK
90cc03b3ec back to dev 2018-06-15 15:39:02 +02:00
Min RK
6f15113e2a link and date for 0.9.0 2018-06-15 15:36:48 +02:00
Min RK
f3f08c9caa 0.9.0 2018-06-15 15:23:25 +02:00
Min RK
c495c4731a Merge pull request #1983 from willingc/test-tilde
add test case for user with tilde
2018-06-15 14:48:49 +02:00
Min RK
e08a50ef66 Merge pull request #1988 from gesiscss/redirects
fix AddSlashHandler for hub_prefix without trailing /
2018-06-15 14:48:14 +02:00
Min RK
fbcd792062 Merge pull request #1984 from chicocvenancio/tilde_safe_in_proxy
mark tilde as safe in proxy routespec quoting FIX:#1982
2018-06-15 14:38:38 +02:00
Min RK
bb81ce0160 also test @ handling in proxy.check_routes
@ and ~ should be the same
2018-06-15 14:33:31 +02:00
Kenan Erdogan
315087d67c fix AddSlashHandler for hub_prefix without trailing / 2018-06-15 13:36:05 +02:00
Chico Venancio
31e6a15a85 mark tilde as safe in proxy routespec quoting FIX:#1982 2018-06-14 18:18:52 -03:00
Carol Willing
aed99d8d19 add test case for user with tilde 2018-06-14 13:24:05 -07:00
Min RK
ec83708892 use pid file to check for previous proxy instances
avoids failure to start when the previous proxy wasn't cleaned up properly
2018-06-14 17:50:33 +02:00
Min RK
bedac5f148 Merge pull request #1980 from willingc/pypi-meta
Add info to display at pypi site
2018-06-14 11:51:29 +02:00
Carol Willing
376aa13981 correct link 2018-06-13 14:37:27 -07:00
Carol Willing
4bc8b48763 add info to display at pypi site 2018-06-13 14:35:23 -07:00
Carol Willing
21496890f6 Remove stray bullet that I missed in review 2018-06-13 11:10:41 -07:00
Carol Willing
70dcd50e44 Merge pull request #1976 from minrk/changelog-more
last few things in changelog
2018-06-13 11:09:30 -07:00
Min RK
24094567e5 Merge pull request #1977 from kpfleming/patch-1
Correct 'conda' installation instructions
2018-06-13 15:44:27 +02:00
Kevin P. Fleming
6bd0febbe1 Correct 'conda' installation instructions
JupyterHub packages are in the 'conda-forge' channel of Anaconda packages; if the Anaconda installation doesn't already have 'conda-forge' enabled, `conda install jupyterhub` fails.

Rather than adding instructions to enable 'conda-forge' in Anaconda, this patch modifies the installation command to specify that channel.
2018-06-13 09:42:05 -04:00
Min RK
57075aba52 Add last few entries in changelog for 0.9 2018-06-13 15:15:18 +02:00
Min RK
f0260aae52 add missing expiry fields in rest-api doc 2018-06-13 15:15:09 +02:00
Min RK
edd8e21f71 Merge pull request #1969 from willingc/edit-userenv
Edit and reflow user environment reference
2018-06-13 09:49:23 +02:00
Min RK
681d3ce2d8 Merge pull request #1971 from willingc/contributor-list
Update contributor list for 0.9 release
2018-06-13 09:45:37 +02:00
Carol Willing
97e792ccde Update issue templates 2018-06-12 15:47:05 -07:00
Carol Willing
a5a0543b2a Delete old issue template 2018-06-12 15:42:46 -07:00
Carol Willing
5a810ccba3 Update issue templates 2018-06-12 15:41:30 -07:00
Carol Willing
0a6b2cdadc Merge pull request #1973 from jupyterhub/willingc-patch-1
Create CODE_OF_CONDUCT.md
2018-06-12 15:33:37 -07:00
Carol Willing
08903e7af8 Create PULL_REQUEST_TEMPLATE.md 2018-06-12 15:29:54 -07:00
Carol Willing
78439329c0 Merge pull request #1972 from willingc/insights
Move issue template one level down in .github directory
2018-06-12 15:28:34 -07:00
Carol Willing
4dfd6bc4b9 Create CODE_OF_CONDUCT.md 2018-06-12 15:25:27 -07:00
Carol Willing
574cc39b5f set up pull request template directory 2018-06-12 15:16:02 -07:00
Carol Willing
6fb43a8241 update issue templaate location to current github recommendation 2018-06-12 15:13:39 -07:00
Carol Willing
84c82fe382 update the contributor list for 0.9 2018-06-12 14:51:51 -07:00
Carol Willing
5e45e76f5b update contributors for 0.9 2018-06-12 14:36:00 -07:00
Carol Willing
92fd819cd6 Merge pull request #1970 from JasonJWilliamsNY/hub-not-found-at-localhost
Hub not found at localhost
2018-06-12 14:04:09 -07:00
Jason Williams
cb5ef0c302 Update troubleshooting.md 2018-06-12 17:01:37 -04:00
Jason Williams
34fab033fe Jupyterhub on Docker add workaround for unable to connect to localhost
Added a command that worked for me to fix the situation that localhost:8000 is unable to reach the hub even though the published command for Docker exposes the correct port.
2018-06-12 16:59:17 -04:00
Carol Willing
37f4c4429e edit and reflow user environment reference 2018-06-12 08:47:22 -07:00
Carol Willing
293410ec94 Merge pull request #1967 from minrk/config-docs
docs: configuring user environments
2018-06-12 07:55:53 -07:00
Min RK
ed6ee27dcd docs: configuring user environments
covers system-wide installation, kernelspec registration, and the differences between containers and host systems
2018-06-12 14:34:26 +02:00
Min RK
ca16ddb7ad back to dev 2018-06-12 14:21:16 +02:00
Min RK
2102c1fd1c 0.9.0rc1 2018-06-12 14:19:59 +02:00
Min RK
aa9676ec5e Merge pull request #1913 from rkdarst/announcement_text
Add customizable announcement text on home,login,logout,spawn
2018-06-12 14:14:21 +02:00
Min RK
5e93c7de4c announcement doc language
per willingc review
2018-06-12 13:48:42 +02:00
Min RK
d22626906b multiline conditionals setting announcement variable in templates
for readability per review by willingc
2018-06-12 13:48:24 +02:00
Min RK
5f91ed044e parametrize test_announcements 2018-06-12 13:47:55 +02:00
Min RK
5c3c7493c1 Merge pull request #1963 from willingc/hooks-doc
add a small section for pre/post spawn hooks
2018-06-11 15:27:39 +02:00
Carol Willing
1b7965092e remove backticks and long for rst format 2018-06-08 14:21:31 -07:00
Carol Willing
ef60be5a99 put backticks outside of link 2018-06-08 14:19:43 -07:00
Carol Willing
f78d652cd6 fix missing brackets 2018-06-08 14:18:14 -07:00
Carol Willing
3650575797 add a small section for pre/post spawn hooks 2018-06-08 14:13:45 -07:00
Tim Head
0f000f6d41 Merge pull request #1961 from willingc/doc-shib
Add link to authenticators used with Shibboleth
2018-06-08 18:17:08 +02:00
Carol Willing
643729ac0c Merge pull request #1962 from chicocvenancio/docs_mysql_dynamic
database docs utfmb4 collation and some versions of mysql/mariadb
2018-06-08 09:14:04 -07:00
Chico Venancio
91a67bf580 database docs: fix formatting 2018-06-08 13:09:09 -03:00
Chico Venancio
c75eddb730 database docs utfmb4 collation and some versions of mysql/mariadb 2018-06-08 12:55:02 -03:00
Carol Willing
0f5888ad6c Add link to authenticators used with Shibboleth 2018-06-08 08:22:11 -07:00
Carol Willing
8c48f3b856 Merge pull request #1960 from willingc/db-doc
add database doc section and edits to upgrading db
2018-06-08 08:08:51 -07:00
Carol Willing
6e7e18bc3c add @minrk review comments 2018-06-08 07:34:09 -07:00
Tim Head
3dfd7e5a84 Merge pull request #1958 from willingc/proxy-error
Add error message text
2018-06-08 15:19:27 +02:00
Carol Willing
19ecbf3734 add note about why no sqlite and nfs 2018-06-08 06:06:15 -07:00
Carol Willing
eac3e8ba90 add database doc section and edits to upgrading db 2018-06-08 05:51:00 -07:00
Carol Willing
a7a6829b69 add additional reference per @betatim review 2018-06-08 05:01:32 -07:00
Carol Willing
61299113c8 add error message text 2018-06-07 21:44:18 -07:00
Tim Head
21a57dfa0b Merge pull request #1949 from willingc/npm-doc
clarify that conda installs npm and proxy
2018-06-07 19:52:00 +02:00
Carol Willing
a7226a8231 changes per @minrk review 2018-06-07 09:10:04 -07:00
Min RK
6e3dd21f60 Merge pull request #1952 from willingc/docker-conda
bump miniconda to 4.5.1 in Dockerfile
2018-06-07 10:24:33 +02:00
Min RK
cf049730d4 Merge pull request #1954 from willingc/black-test
Blacken python doc build files
2018-06-07 10:24:14 +02:00
Min RK
cb9ce4d3af Merge pull request #1955 from dtaniwaki/handle-fatal-error
only relay headers from HTTPErrors
2018-06-07 10:22:38 +02:00
Daisuke Taniwaki
925ee1dfb2 Do not refer spawner on fatal errors 2018-06-07 14:53:46 +09:00
Daisuke Taniwaki
5d9122b26c Avoid setting unexpected headers 2018-06-07 14:53:34 +09:00
Carol Willing
6821ad0c59 blacken autodoc sphinx extension 2018-06-06 12:57:14 -07:00
Carol Willing
ff7851ee2e blacken conf.py 2018-06-06 12:52:30 -07:00
Carol Willing
6940ed85b1 bump miniconda to 4.5.1 2018-06-06 08:25:28 -07:00
Carol Willing
3d497a7f43 clarify that conda installs npm and proxy 2018-06-06 06:56:22 -07:00
Carol Willing
cc6968e225 Merge pull request #1942 from minrk/nginx-file
note where nginx config files are typically created.
2018-06-06 06:02:30 -07:00
Carol Willing
a6c517c344 Merge pull request #1947 from minrk/progress-stopping
Avoid showing spawn-pending page when user is stopping
2018-06-06 06:00:58 -07:00
Carol Willing
a3e08b7f52 Merge pull request #1948 from minrk/aclosing
Python 3.5.1 cannot close async iterators
2018-06-06 05:56:00 -07:00
Min RK
14c8d7dc46 Merge pull request #1946 from dtaniwaki/configure-max-inactive-duration
Configure max inactive duration
2018-06-06 12:54:55 +02:00
Daisuke Taniwaki
ac2590c679 Add active_user_window configuration 2018-06-06 19:00:34 +09:00
Min RK
ead13c6a11 further clarify that we are creating a new file, not editing nginx.confg 2018-06-06 12:00:21 +02:00
Min RK
5002ab2990 Python 3.5.1 cannot close async iterators
so provide a null aclosing async context manager that does nothing
2018-06-06 11:43:33 +02:00
Min RK
ab3e7293a4 disable my server link while stop is pending
makes it a little harder to request a spawn while stop is pending
2018-06-06 10:53:50 +02:00
Min RK
062af5e5cb Avoid showing spawn_pending page when pending action is stop
Separate stop_pending page when this occurs,
similar to the old spawn pending spinner without progress events
2018-06-06 10:53:05 +02:00
Carol Willing
92088570ea Merge pull request #1943 from minrk/getuser-delayed
delay call to getuser in token app
2018-06-05 10:18:08 -07:00
Min RK
604ccf515d delay call to getuser in token app
avoids issues with getuser preventing launch, e.g. in weird containers where the current user doesn’t exist
2018-06-05 17:52:00 +02:00
Min RK
ec9b244990 note where nginx config files are typically created. 2018-06-04 11:10:21 +02:00
Min RK
09acdc23b5 Merge pull request #1940 from dtaniwaki/fix-created-columne-error
Handle NULL created column of tokens table
2018-06-04 10:55:20 +02:00
Richard Darst
e7808b50af Add tests of page announcements
- Adds test_pages.py:test_page_contents, which currently tests just
  the page annoucement variables.
2018-06-03 01:18:48 +03:00
Richard Darst
9c27095744 Add customizable announcement text on home,login,logout,spawn
- Using the new template_vars setting (#1872), allow the variable
  `announcement` to create a header message on all the pages in the
  title, or the variables `announcement_{home,login,logout,spawn}` to
  set variables on these single pages.
- This is not the most powerful method of putting an announcement into
  the templates, because it requires a server restart to change.  But
  the invasiveness is very low, and allows minimal message
  without having to touch the templates themselves.
- Closes: #1836
2018-06-03 01:18:48 +03:00
Daisuke Taniwaki
690b07982e Handle NULL created column of api_tokens table 2018-06-02 23:55:21 +09:00
Min RK
784e5aa4ee Merge pull request #1926 from minrk/tilde-safe
tilde is a safe character in user URLs
2018-05-30 14:48:35 +02:00
Min RK
29187cab3a Merge pull request #1929 from minrk/pgbin
install psycopg2 from binary
2018-05-29 11:03:41 +02:00
Min RK
43a72807c6 install psycopg2 from binary
it has a new package name for the binary wheel
2018-05-29 10:41:53 +02:00
Min RK
1d1f6f1870 Merge pull request #1923 from nxg/doc-changes-1747
Documentation clarifications (adding explicitness).
2018-05-29 10:21:42 +02:00
Min RK
505a6eb4e3 ensure user subdomains are valid
escape with `_` instead of `%`.

This is not technically rigorous, as collisions are possible (users foo_40 and foo@ have the same domain)
and other domain restrictions are not applied (length, starting characters, etc.).
Username normalization can be used to apply stricter, more rigorous structure.
2018-05-29 10:19:21 +02:00
Min RK
cc49df8147 Merge pull request #1852 from summerswallow-whi/service-info
Attach an info field to the service
2018-05-28 14:57:10 +02:00
Min RK
98d60402b5 add service.info to rest api docs 2018-05-28 14:09:53 +02:00
Min RK
319e8a1062 update service models in tests 2018-05-28 14:09:44 +02:00
Min RK
0c5d564830 tilde is a safe character in user URLs
Chrome unconditionally reverts any not-strictly-necessary escaping in URLs (this seems wrong?)
2018-05-28 13:46:52 +02:00
Norman Gray
c0404cf9d9 Documentation clarifications (adding explicitness).
Addresses issue #1747.

These additions aren't perfect -- it's unfortunate that I've added
mention of reverse proxies on two separate pages.  I don't _think_
these can reasonably be put on the same page -- perhaps a cross
reference?
2018-05-27 18:49:40 +01:00
Min RK
f364661363 Merge pull request #1899 from adelcast/dev/adelcast/kill_proxy_tree
ConfigurableHTTPProxy.stop: kill child processes on Windows case
2018-05-25 15:25:53 +02:00
Min RK
f92d77b06d Merge pull request #1915 from rkdarst/respawn_error_msg
Clarify error message on implicit respawns.
2018-05-25 10:09:35 +02:00
Haw-minn Lu
2cf00e6aae Add info field to service model 2018-05-24 11:19:18 -07:00
Richard Darst
dfdb0cff2b Clarify error message on implicit respawns.
- This message is presented when the last spawn failed, along with a
  HTTP 500.  The current text is quite confusing, especially when the
  problem may just be solvable by trying to respawn again.
2018-05-24 16:07:26 +03:00
Alejandro del Castillo
d0dad84ffa ConfigurableHTTPProxy.stop: kill child processes on Windows case
On the Windows case, the configurable-http-proxy is spwaned using a
shell. To stop the proxy, we need to terminate both the main process
(shell) and its child (proxy).

Signed-off-by: Alejandro del Castillo <alejandro.delcastillo@ni.com>
2018-05-23 10:10:50 -05:00
Min RK
1745937f1a back to dev 2018-05-23 16:47:56 +02:00
Min RK
e7eb674a89 0.9.0b3 2018-05-23 16:30:07 +02:00
Min RK
b232633100 Merge pull request #1894 from minrk/db-rollback
Rollback database sessions on SQLAlchemy errors
2018-05-23 16:09:51 +02:00
Carol Willing
6abd19c149 Merge pull request #1911 from minrk/log-classes
log Authenticator and Spawner classes at startup
2018-05-22 11:50:59 -07:00
Min RK
0aa0ff8db7 Merge pull request #1912 from minrk/double-slash
Fix login redirect checking for `//` urls
2018-05-22 15:56:29 +02:00
Min RK
a907429fd4 more test cases for login redirects 2018-05-22 15:40:27 +02:00
Min RK
598b550a67 fix query/hash login redirect handling 2018-05-22 15:40:14 +02:00
Min RK
92bb442494 more robust checking for login redirects outside jupyterhub 2018-05-22 15:40:00 +02:00
Min RK
2d41f6223e log Authenticator and Spawner classes at startup
for better diagnostics
2018-05-22 13:52:41 +02:00
Min RK
791dd5fb9f Merge pull request #1895 from minrk/oauth-commits
avoid creating one huge transaction cleaning up oauth clients
2018-05-22 13:37:56 +02:00
Carol Willing
9a0ccf4c98 Merge pull request #1910 from minrk/ip-typo
default bind url should be on all ips
2018-05-22 01:26:35 -07:00
Min RK
ad2abc5771 default bind url should be on all ips
preserves jupyterhub default behavior

typo introduced in new bind_url config
2018-05-22 09:55:01 +02:00
Min RK
2d99b3943f enable pessimistic connection handling
from the sqlalchemy docs

checks if a connection is valid via `SELECT 1` prior to using it.

Since we have long-running connections, this helps us survive database restarts, disconnects, etc.
2018-05-21 22:14:11 +02:00
Min RK
a358132f95 remove --rm from docker-db.sh
for easier stop/start testing
2018-05-21 22:12:30 +02:00
Tim Head
09cd37feee Merge pull request #1896 from thoralf-gutierrez/fix-typos-in-config
Fix typos in auth config documentation
2018-05-16 22:37:51 +02:00
Thoralf Gutierrez
0f3610e81d Fix typos in auth config documentation 2018-05-16 10:58:02 -07:00
Min RK
3f97c438e2 avoid creating one huge transaction cleaning up oauth clients 2018-05-15 16:33:50 +02:00
Min RK
42351201d2 back to dev 2018-05-15 16:32:24 +02:00
Min RK
907bbb8e9d 0.9.0b2 2018-05-15 14:03:10 +02:00
Min RK
63f3d8b621 catch database errors in update_last_activity 2018-05-15 13:53:05 +02:00
Min RK
47d6e841fd cache get_current_user result
avoids raising an error rendering templates, etc.
2018-05-15 13:49:38 +02:00
Min RK
e3bb09fabe rollback database session on db errors
ensures reconnect will occur when database connection is lost
2018-05-15 13:49:14 +02:00
Carol Willing
d4e0c01189 Merge pull request #1893 from minrk/version
ensure jupyterhub version matches pep440
2018-05-15 07:40:24 -04:00
Min RK
50370d42b0 ensure jupyterhub version matches pep440
avoids mismatch jupyterhub version and tag in docker builds
2018-05-15 13:19:43 +02:00
Min RK
aa190a80b7 Merge pull request #1891 from minrk/base_url
fix and test bind_url / base_url interactions
2018-05-15 12:07:44 +01:00
Min RK
e48bae77aa Merge pull request #1890 from minrk/default-url
test default_url handling
2018-05-15 10:51:17 +01:00
Min RK
96cf0f99ed fix and test bind_url / base_url interactions 2018-05-15 10:51:11 +02:00
Min RK
f380968049 test default_url handling
- default_url is used even if not logged in
- flesh out docstrings
- pass via settings
2018-05-15 10:15:33 +02:00
Min RK
02468f4625 Merge pull request #1854 from summerswallow-whi/extra_handler
Add custom handlers and allow setting of defaults
2018-05-15 08:55:15 +01:00
Haw-minn Lu
24611f94cf Remove base_url from default_url
Add help to new traits
change extra_page_handler to extra_handler
2018-05-14 11:53:22 -07:00
Min RK
dc75a9a4b7 Merge pull request #1881 from paccorsi/check-post-stop-hook
Check the value of post stop hook
2018-05-14 13:31:33 +01:00
Min RK
33f459a23a Merge pull request #1878 from ausecocloud/master
fix listing of OAuth tokens on tokens page
2018-05-14 13:31:06 +01:00
Min RK
bdcc251002 Merge pull request #1882 from dhirschfeld/patch-1
Allow configuring the heading in spawn.html
2018-05-14 13:30:47 +01:00
Pierre Accorsi
86052ba7b4 Check the value of post stop hook 2018-05-11 10:12:45 -04:00
Dave Hirschfeld
62ebcf55c9 Allow configuring the heading in spawn.html 2018-05-11 13:34:17 +10:00
Haw-minn Lu
80ac2475a0 Restore whitespacing to original 2018-05-10 11:25:02 -07:00
Haw-minn Lu
5179d922f5 Clean up extra handler defaults 2018-05-10 11:22:50 -07:00
Gerhard Weis
26f085a8ed add test for oauth tokens on tokens page 2018-05-10 08:46:28 +10:00
Gerhard Weis
b7d302cc72 fix listing of OAuth tokens on tokens page 2018-05-10 08:46:28 +10:00
Carol Willing
f2941e3631 Merge pull request #1873 from minrk/apitoken-expiry
implement API token expiry
2018-05-09 11:45:41 -04:00
Carol Willing
26a6401af4 Merge pull request #1876 from willingc/sudo-section
refactor sudo example config
2018-05-08 09:23:28 -07:00
Carol Willing
5c8ce338a1 edit per @minrk review 2018-05-08 11:54:38 -04:00
Carol Willing
5addc7bbaf correct directive 2018-05-07 21:03:13 -07:00
Carol Willing
da095170bf remove toctree item 2018-05-07 20:38:15 -07:00
Carol Willing
1aab0a69bd fix typo 2018-05-07 20:31:20 -07:00
Carol Willing
fc8e04b62f reflow templates file 2018-05-07 20:29:13 -07:00
Carol Willing
c6c53b4e10 update index 2018-05-07 20:28:55 -07:00
Carol Willing
9b0219a2d8 break up configuration examples 2018-05-07 20:18:02 -07:00
Carol Willing
6e212fa476 reflow proxy doc 2018-05-07 20:17:14 -07:00
Carol Willing
58f9237b12 refactor sudo example config 2018-05-07 15:38:16 -07:00
Carol Willing
74fd925219 Merge pull request #1864 from datalayer-contrib/docs-sudo
Add Docs about sudo (and remove it from the wiki)
2018-05-07 23:29:08 +02:00
Carol Willing
2696bb97d2 Merge pull request #1875 from willingc/api-redux
add packages to environment.yml
2018-05-07 23:16:53 +02:00
Haw-minn Lu
9cefb27704 Move extra_handlers to fall below builtins in priority 2018-05-07 14:06:34 -07:00
Carol Willing
5e75357b06 add packages to environment.yml 2018-05-07 13:54:06 -07:00
Min RK
79bebb4bc9 Merge pull request #1872 from thedataincubator/template-vars
Allow extra variables to be passed into templates
2018-05-07 20:33:44 +02:00
Eric Charles
0ed88f212b add sudo.md 2018-05-07 19:49:26 +02:00
Eric Charles
a8c1cab5fe add sudo doc 2018-05-07 19:49:26 +02:00
Min RK
e1a6b1a70f Merge pull request #1856 from minrk/whoami-users
note about hub_users in whoami example
2018-05-07 19:47:45 +02:00
Robert Schroll
c95ed16786 Allow extra variables to be passed into templates 2018-05-07 10:47:27 -07:00
Min RK
ec784803b4 remove duplicate whoami-oauth.py from external-oauth example 2018-05-07 15:35:05 +02:00
Min RK
302d7a22d3 leave user-whitelist example in a comment
allow all users by default because default whitelist is confusing
2018-05-07 15:34:33 +02:00
Min RK
eccd5a460b 0.9.0b1 2018-05-07 14:43:59 +02:00
Min RK
80437229a1 include package-lock in sdists 2018-05-07 14:43:59 +02:00
Min RK
237ffba641 Merge pull request #1871 from minrk/fix-hub-bind-url
fix and test constructing objects from bind_url
2018-05-07 14:40:39 +02:00
Dave Hirschfeld
2695c5e49f Add missing import 2018-05-07 14:13:36 +02:00
Min RK
b7a608fdfd soften deprecation messages about ip/ports in favor of URLs
These are not deprecated, bind_url is only a potentially more convenient/powerful alternative.
2018-05-07 14:13:36 +02:00
Min RK
c3413bad78 ensure hub_prefix is part of hub bind/connect URLs 2018-05-07 14:13:36 +02:00
Min RK
dceb244e5b ensure connect_url includes base_url prefix 2018-05-07 14:13:36 +02:00
Min RK
cb31a0b162 fix and test constructing objects from bind_url 2018-05-07 14:13:36 +02:00
Min RK
7ced657d79 Merge pull request #1863 from jamescurtin/add-post-spawn-hook
Add post spawn hook
2018-05-07 13:15:21 +02:00
James Curtin
8dd9168077 Refactor method name to post_stop_hook 2018-05-07 07:07:29 -04:00
Min RK
7c6591aefe add token expiry to token model 2018-05-07 13:02:26 +02:00
Min RK
58c91e3fd4 implement API token expiry 2018-05-07 13:00:37 +02:00
Min RK
db4cf7ae62 note about hub_users in whoami example
explain what hub_users does and the value in the example
2018-05-07 10:55:39 +02:00
Min RK
a17f5e4f1b Merge pull request #1870 from dhirschfeld/patch-3
Allow `hub_connect_url` to be configured
2018-05-07 10:49:44 +02:00
Min RK
6cf7f2b0a7 Merge pull request #1866 from chicocvenancio/mysql_large_prefix
Mysql large prefix
2018-05-07 10:49:03 +02:00
Min RK
7e21ea9a48 Merge pull request #1867 from dhirschfeld/patch-1
Fix typo
2018-05-07 10:46:30 +02:00
Min RK
3f29198bae Merge pull request #1868 from dhirschfeld/patch-2
Fix ImportError on Windows
2018-05-07 10:45:57 +02:00
Dave Hirschfeld
d4293650ff Allow hub_connect_url to be configured 2018-05-07 18:43:58 +10:00
Dave Hirschfeld
d65dd16881 Fix ImportError on Windows
Delay importing unix-specific functionality until required
2018-05-07 13:27:44 +10:00
Dave Hirschfeld
f36e163581 Fix typo 2018-05-07 12:54:25 +10:00
Chico Venancio
f215adcfa2 move check after engine creation 2018-05-06 04:39:26 +00:00
Chico Venancio
1549af6f56 move large_prefix_check to previous mysql if 2018-05-06 04:29:37 +00:00
Chico Venancio
c553f82580 add comment 2018-05-06 04:27:16 +00:00
Chico Venancio
196b4ebc9f fix py syntax 2018-05-06 04:27:16 +00:00
Chico Venancio
8710ce1687 fixing py syntax 2018-05-06 04:27:16 +00:00
Chico Venancio
f65e8d7369 add ROW_FORMAT=DYNAMIC if server is configured to need it for large collums 2018-05-06 04:27:16 +00:00
Carol Willing
dc5d9f02c7 Merge pull request #1861 from minrk/0.9-changelog
Changelog for 0.9
2018-05-05 02:00:05 +02:00
James Curtin
2f3f8d7826 Add post-spawn hook 2018-05-04 19:56:34 -04:00
Carol Willing
297da070fc Merge pull request #1859 from minrk/auth-token
Allow Authenticators to authenticate requests for API tokens
2018-05-05 01:53:37 +02:00
Carol Willing
10ea92dcea Merge pull request #1850 from minrk/connect_url
Use URLs for config
2018-05-05 01:30:35 +02:00
Min RK
2e5f01f232 changelog for 0.9 2018-05-04 17:25:04 +02:00
Min RK
1a080c4261 test retrieving a token with auth in the body 2018-05-04 17:22:47 +02:00
Min RK
0e08963355 suppress auth errors on authenticated token request
since Authenticators may not be prepared for this
2018-05-04 17:18:32 +02:00
Min RK
cd9e39bf54 allow authenticators to authenticate API requests for tokens
gives Authenticators the ability to authenticate token requests,
e.g. with an existing OAuth token from the upstream provider
2018-05-04 17:18:32 +02:00
Min RK
580e840165 Merge pull request #1709 from yuvipanda/retry-suggest
Suggest retry timing when we throttle server starts
2018-05-04 16:33:35 +02:00
Min RK
09a8fd5254 address review in spawn-throttle-retry
- update config to single tuple instead of two integers
- call it spawn_throttle_retry_range
- fix setting Retry-After header without disabling error pages
2018-05-04 13:44:32 +02:00
yuvipanda
8898faa141 Suggest retry timing when we throttle server starts
Fixes #1706
2018-05-04 12:38:11 +02:00
Min RK
fdbb1dad79 use bind_url in tests 2018-05-04 12:36:59 +02:00
Min RK
c39244168b note deprecations for ip/port
in favor of bind_url
2018-05-04 11:03:47 +02:00
Min RK
9591fd88c5 add JupyterHub.bind_url for public bind URL 2018-05-04 11:02:16 +02:00
Min RK
3558ce958e Merge pull request #1848 from willingc/docs-theme
Switch docs theme to be consistent with z2jh and binderhub
2018-05-04 10:27:44 +02:00
Min RK
804a9b7be8 Spawner.start can return a URL
enables internal HTTPS, if setup by the Spawner
2018-05-03 16:41:02 +02:00
Min RK
3cae550b13 remove redundant "Adding default route" log
the same message is logged immediately after with the URL
2018-05-03 16:32:56 +02:00
Min RK
138bad5913 add connect_url, bind_url overrides
enables `c.JupyterHub.bind_url = 'unix+http://%2Fsrv%2Fjupyterhub%2Fjupyterhub.sock'`
for listening on a bsd socket.

Similarly, bind_url and connect_url work as overrides everywhere
2018-05-03 16:32:31 +02:00
Carol Willing
09011815af Good catch @betatim 2018-05-03 15:54:51 +02:00
Matthias Bussonnier
7b0c845c3a Allow Hub to listen on a unix-socket
Add the hub_socket option to the JupyterHub class, which takes
precedence over the hub_ip and hub_port setting. It does not forward
this setting to the Hub class though, and a few log messages still say
the hub is listening on `http://:8000` that works fine when testing with
netcat:

```
$ nc -U /tmp/jhub.sock
GET /login HTTP/1.1

HTTP/1.1 302 Found
Server: TornadoServer/4.5.1
Content-Type: text/html; charset=UTF-8
Date: Fri, 28 Jul 2017 02:05:36 GMT
X-Jupyterhub-Version: 0.8.0.dev
Content-Security-Policy: frame-ancestors 'self'; report-uri /hub/security/csp-report
Location: /hub/login
Content-Length: 0
```

Should still be better documented I guess.
2018-05-03 15:49:17 +02:00
Min RK
6a47123ec9 Merge pull request #1847 from willingc/update-contributing
Update the contributing instructions for running tests.
2018-05-03 14:56:01 +02:00
Carol Willing
19fab6bbf8 fix typo 2018-05-03 04:42:06 +02:00
Carol Willing
90e6b63e59 bump tornado and sphinx versions 2018-05-03 04:37:33 +02:00
Carol Willing
bd78217cf3 remove jupyter alabaster theme from requirements 2018-05-03 04:34:56 +02:00
Carol Willing
b0833985e6 fix wording from spawn to launch 2018-05-03 04:32:22 +02:00
Carol Willing
a6f73b035f updates to theme 2018-05-03 04:26:02 +02:00
Carol Willing
251440ec64 add templates for theme 2018-05-03 03:34:48 +02:00
Carol Willing
22a1df6fa0 update conf.py for theme 2018-05-03 03:34:16 +02:00
Carol Willing
6389751c22 move to alabaster theme 2018-05-03 03:22:26 +02:00
Carol Willing
8498691763 Update the contributing instructions for running tests. 2018-05-02 22:25:45 +02:00
Carol Willing
1750ff0324 Merge pull request #1846 from minrk/log-typo
ensure changed is defined
2018-05-02 20:53:08 +02:00
Carol Willing
2ce4c46afd Merge pull request #1845 from minrk/colorblind-friendly
pick colorblind-friendly alternatives for success/danger
2018-05-02 20:22:46 +02:00
Carol Willing
a20f5e44d1 Merge pull request #1819 from minrk/test-tornado-45
require tornado 5
2018-05-02 20:12:59 +02:00
Min RK
cd746d72d4 scrub redirect urls as well 2018-05-02 12:58:50 +02:00
Min RK
f7eaff0828 ensure changed is defined
avoids UnboundLocal error when no change has occurred
2018-05-02 12:52:58 +02:00
Min RK
849f119a47 Merge pull request #1835 from minrk/secret-logs
further scrub potentially sensitive url params
2018-05-02 11:58:40 +02:00
Min RK
52b68381f6 require tornado 5 2018-05-02 11:56:26 +02:00
Min RK
46d495e1e2 use btn-primary instead of btn-success
avoid references to formerly-green color
2018-05-02 11:19:46 +02:00
Min RK
acc6c22355 eliminate distinction between 'primary' and 'success'
since we don't use them both on the same screen
2018-05-02 11:16:56 +02:00
Min RK
8143182971 pick colorblind-friendly alternatives for success/danger
danger is still red, success is now blue

picked from color brewer 2 RdYlBu
2018-05-02 11:14:19 +02:00
Carol Willing
04a22cd482 Merge pull request #1841 from rkdarst/run_same_service_culling
cull_idle_servers: Add note about running with different timeouts
2018-05-02 05:41:13 +02:00
Richard Darst
4376224084 cull_idle_servers: Add note about running with different timeouts
- Instead of creating many options for different timeouts of users and
  servers, just add a note that the whole culler can be run multiple
  times with different options.  See discussion in #1834.
- Closes: #1834
2018-05-02 01:11:29 +03:00
Min RK
a9fe88c343 Merge pull request #1838 from tklever/moment-upgrade
chore: bump moment.js version
2018-04-30 14:59:43 +02:00
Carol Willing
6eb95e1c66 Merge pull request #1839 from jupyterhub/spawner-as-noun
Use verb spawn in README to refer to things related to spawner
2018-04-30 14:36:27 +02:00
J Forde
a46287c4a6 Update README.md
We should probably use the verb spawn to refer to the spawner since the spawner is the name of a specific part of JHub
2018-04-30 13:27:25 +02:00
Haw-minn Lu
bc86ee1c31 Add custom handlers and allow setting of defaults 2018-04-27 15:58:59 -07:00
Haw-minn Lu
a73e6f0bf8 Attach an info field to the service 2018-04-27 14:51:55 -07:00
Tim Klever
10a6c5144d chore: bump moment.js version
Moving to 2.19.3 or higher to clear some regex issues
2018-04-27 09:53:51 -07:00
Carol Willing
4e5f43aeae Merge pull request #1832 from minrk/dockerfiles
Docker updates
2018-04-27 06:10:59 -07:00
Min RK
ff56db0c8b Merge pull request #1828 from rkdarst/authenthicator_blacklist
Authenthicator blacklist
2018-04-26 17:59:44 +02:00
Richard Darst
95a9b97649 Add tests for authentication blacklist 2018-04-26 17:51:25 +03:00
Min RK
a5b5208823 add build context to alpine dir 2018-04-26 16:43:56 +02:00
Min RK
783295fabd fix tags in post_push 2018-04-26 16:43:56 +02:00
Min RK
1c942ec97c ubuntu base image has utf8 locale 2018-04-26 16:43:56 +02:00
Min RK
3b6d2655ab fix onbuild build arg 2018-04-26 16:43:56 +02:00
Min RK
8a18d0daab move onbuild hook to post_build 2018-04-26 16:43:56 +02:00
Min RK
e9f7ccbd25 make build hooks exit on failure 2018-04-26 16:43:56 +02:00
Min RK
68d9f35c0b build all our docker images on circleci 2018-04-26 16:43:56 +02:00
Min RK
28d78134c1 remove push from circle
building directly on docker cloud now, no credentials needed
2018-04-26 16:43:56 +02:00
Min RK
fd92ac852d add docker cloud hooks for onbuild 2018-04-26 16:43:56 +02:00
Min RK
8399f5288e add BASE_IMAGE build arg for onbuild
for easier automated building
2018-04-26 16:43:56 +02:00
Min RK
f99b7cb7eb update Python, conda, ubuntu in Dockerfile 2018-04-26 16:43:56 +02:00
Min RK
bb5166077f further scrub potentially sensitive url params
include oauth codes, state, and tokens
2018-04-26 16:42:24 +02:00
Carol Willing
b72e4b66ca Merge pull request #1831 from minrk/service-stop
service.stop is a coroutine
2018-04-26 07:28:55 -07:00
Carol Willing
ed85cd25d6 Merge pull request #1827 from minrk/circle
simplify circle2 config
2018-04-26 07:23:52 -07:00
Carol Willing
3f90697e18 Merge pull request #1820 from minrk/test-db-upgrade
test database upgrades
2018-04-26 07:22:58 -07:00
Tim Head
73271a3e55 Merge pull request #1833 from rkdarst/cull_idle_py36
Note cull-idle needs python3
2018-04-26 15:44:35 +02:00
Richard Darst
6f9ea712de Note cull-idle needs python3
- Closes: #1825
2018-04-26 16:30:51 +03:00
Min RK
6ee244e7cb Merge pull request #1829 from rkdarst/cull_idle_py36
cull_idle_servers.py: py<3.6 compatibility
2018-04-26 14:42:24 +02:00
Min RK
d66a4af79b service.stop is a coroutine
fixes waiting for services to stop on shutdown
2018-04-26 14:29:50 +02:00
Richard Darst
ea7b1caa4e Add blacklist to auth.py
- Introduce blacklist to supplement white list
- Original code by github:ndiy, updated by github:rkdarst
2018-04-26 15:22:41 +03:00
Richard Darst
9cd880fb35 cull_idle_servers.py: Remove f-string for py3.4 compatibility 2018-04-26 15:05:49 +03:00
Min RK
658c152707 simplify circleci 2 config 2018-04-26 10:49:22 +02:00
Min RK
6f1ba77608 Merge pull request #1813 from rkdarst/api_server_state
add server.state to server model if requester is an admin
2018-04-26 10:33:22 +02:00
Richard Darst
2344d696ca 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.
2018-04-24 16:52:18 +03:00
Min RK
bd816310cb Merge pull request #1817 from minrk/server-model
Always include server sub-models in user api requests
2018-04-24 14:12:58 +02:00
Min RK
2bcf759a9f Don't forget to install db libs in upgrade env 2018-04-24 11:44:08 +02:00
Min RK
82a04f7032 Merge pull request #1823 from willingc/test-time
Add a pytest ini file for running marked tests and edit testing mock files
2018-04-24 11:38:57 +02:00
Min RK
4281babee4 make server-model inclusion opt-in
so only certain API endpoints include server info:

- user list
- get named user

The rest exclude running servers
2018-04-24 11:35:51 +02:00
Min RK
d89f2965cf handle updated server models in culler
- servers sub-models model always defined in 0.9
- explicit 'ready' key added, use user.url fallback only when needed
2018-04-24 11:35:15 +02:00
Min RK
e2a2a9903a spawner.pending is None when nothing is pending
rather than False, which is a bit less convenient since we turn it to None in APIs anyway
2018-04-24 11:35:15 +02:00
Min RK
4401cdc16a Always have .servers model on users
rather than only when named_servers is enabled.

Put new-in-0.9 state there, rather than continuing to add server fields to top-level user model.
2018-04-24 11:35:15 +02:00
Carol Willing
e8d3fb2920 Document the mock service and mock single user servers 2018-04-23 17:38:02 -07:00
Carol Willing
f7ccc137ea add comments to header docstring 2018-04-23 17:06:44 -07:00
Carol Willing
07bbb4ea02 add comments to test file header docstring 2018-04-23 17:06:15 -07:00
Carol Willing
b189e70c9b add a minimal ini file for pytest 2018-04-23 15:31:34 -07:00
Carol Willing
de4c9c1463 mark some api tests as slow 2018-04-23 15:31:00 -07:00
Carol Willing
8bdb73ced4 Merge pull request #1809 from minrk/no-expire-again
don't expire objects on commit
2018-04-23 09:26:57 -07:00
Min RK
dee9050939 require virtualenv package for tests 2018-04-23 15:44:21 +02:00
Min RK
ae3c214708 remove unused old-jupyterhub.sqlite 2018-04-23 15:23:26 +02:00
Min RK
d6e81867bf remove upgrade-db step from travis.yml
it's now in the test itself
2018-04-23 15:22:45 +02:00
Min RK
d30a5ee0a5 add populate_db.py script to populate a database for upgrading 2018-04-23 15:22:45 +02:00
Min RK
88bb80be0f ALTER TABLE is required to add foreign key constraints
skip this for sqlite upgrade
2018-04-23 15:22:45 +02:00
Min RK
bba1ba1678 create additional test databases
for upgrading from multiple base hub versions
2018-04-23 15:22:45 +02:00
Min RK
b50daf20d0 IS NOT NULL typo in upgrade 2018-04-23 15:22:45 +02:00
Min RK
5c6c7cdff5 require tornado 4.5 2018-04-23 13:42:42 +02:00
Min RK
3f9b2a0c28 test with tornado 4.5 on travis 2018-04-23 13:42:34 +02:00
Min RK
453e119808 don't bypass spawner.server to delete server
this shouldn't happen, it's just breaking things
2018-04-23 12:54:22 +02:00
Min RK
a021f910c8 expose expire_on_commit option
conservative deployments may set

    c.JupyterHub.db_kwargs['expire_on_commit'] = True

as an escape if the optimization is causing problems.
2018-04-23 12:54:22 +02:00
Min RK
e6c2afc4db fix oauth lookup use of relationships
have to lookup orm client/user by id

client/user attributes don't exist on oauth objects, which aren't orm objects
2018-04-23 12:54:20 +02:00
Min RK
e6c7b28057 expire before re-running init_services
seems to be required, not sure why
2018-04-23 12:53:38 +02:00
Min RK
b1840e8be7 use relationships everywhere
in order to use sqlalchemy's expire_on_commit=False optimization,
we need to make sure that objects are kept up to date.

This means we cannot rely on ForeignKey ondelete/onupdate behavior,
we must use sqlalchemy's local relationship cascades

The main key here is that we must use relationships to set foreign-key relations,
e.g. APIToken.user = user instead of APIToken.user_id = user.id.

It also means that we cannot use passive_deletes,
which allows sqlalchemy to defer to the database's more efficient ON DELETE behavior.

This makes deletions more expensive in particular,
but should improve db performance overall.
2018-04-23 12:53:38 +02:00
yuvipanda
15e4b1ad8b Don't expire objects on commit 2018-04-23 12:53:38 +02:00
Min RK
2517afcee0 Merge pull request #1800 from minrk/token-api
API for managing tokens
2018-04-23 12:52:34 +02:00
Min RK
15c7ba3078 Merge pull request #1788 from NERSC/options-template-variables
Options form template variables
2018-04-23 12:49:41 +02:00
Rollin Thomas
f2cb24781a Pass for_user.spawner to templating namespace
Give access to spawner fields from the spawner form template.
2018-04-20 08:25:13 -07:00
Min RK
e1d346b8c3 add set -e to script
to prevent proceeding to docs after failure
2018-04-20 15:34:52 +02:00
Min RK
97bdf4811c update expected default token note 2018-04-20 15:34:52 +02:00
Min RK
45c871d779 add some description of API and OAuth tokens 2018-04-20 15:34:52 +02:00
Min RK
976fa9c907 update default note for API-requested tokens 2018-04-20 15:34:52 +02:00
Min RK
771c60ca37 update default token page note 2018-04-20 15:34:52 +02:00
Min RK
e15eeccd35 match oauth client description and sever token note
for spawner api tokens: "Server at /user/:name"
2018-04-20 15:34:52 +02:00
Min RK
ce535b55bc Revoking one oauth token revokes all oauth tokens for that client 2018-04-20 15:34:52 +02:00
Min RK
33cb62c2ee support revoking tokens from token page 2018-04-20 15:34:52 +02:00
Min RK
32fe3cf61d support adding note to new tokens on token page
turn token request into a form
2018-04-20 15:34:52 +02:00
Min RK
73a05498ce support new token API in jhapi.js 2018-04-20 15:34:52 +02:00
Min RK
034147f604 add token lists to token page 2018-04-20 15:34:52 +02:00
Min RK
b629e520a9 add token api to rest yaml 2018-04-20 15:34:52 +02:00
Min RK
30280cc6a4 add token.api_id
id key used in rest api
2018-04-20 15:34:52 +02:00
Min RK
f7f0b72776 retrieve tokens by id in REST API, not full token in URL 2018-04-20 15:34:52 +02:00
Min RK
251289fc05 add new token management to REST API
- list tokens
- create new tokens
- delete tokens
2018-04-20 15:34:52 +02:00
Min RK
6437093a67 add token_model method
for returning the model of an API or OAuth token
2018-04-20 15:34:52 +02:00
Min RK
be5a878da5 add description to oauth clients for services and user servers 2018-04-20 15:34:52 +02:00
Min RK
8dc73a852d add oauth client description 2018-04-20 15:34:42 +02:00
Min RK
e37d82951e Merge pull request #1814 from dhirschfeld/cookie-secret-permissions
Skip checking cookie secret permissions on Windows
2018-04-20 12:34:08 +02:00
dhirschf
acc311830e Skip checking cookie secret permissions on Windows
The existing checks are posix specific
2018-04-19 09:47:57 +10:00
Min RK
6b1046697a Merge pull request #1807 from rkdarst/cull_idle_unknown_times
cull_idle_servers.py: Fix problem when age/inactive undefined
2018-04-17 18:15:38 +02:00
Carol Willing
c5befc5b2a Merge pull request #1810 from minrk/service-stop
service.stop is not async
2018-04-17 05:18:37 -07:00
Min RK
e743a5733b add debug-logging for stopping proxy and services 2018-04-17 14:07:13 +02:00
Richard Darst
5f98801c99 cull_idle_servers.py: Don't try to delete non-running servers
- Only run the server handler if a server is actually running.  A bug
  could occur with non-named servers.
2018-04-17 13:52:13 +03:00
Richard Darst
9858a3db9d cull_idle_servers.py: Fix problem when age/inactive undefined
- Sometimes the inactive or age can be undefined instead of timedelta.
  Handle this case.
2018-04-17 13:51:40 +03:00
Min RK
65c1a525b9 service.stop is not async 2018-04-17 11:43:42 +02:00
Min RK
8bd055d4bd Merge pull request #1804 from consideRatio/query-string-memory-pr
/user/someone-else redirection retain query strings
2018-04-16 10:11:11 +02:00
Erik Sundell
5ee14db1f9 /user/someone-else redirection retain query strings 2018-04-15 05:03:56 +02:00
Carol Willing
58069d015b Merge pull request #1801 from minrk/cascades
fix and test deletion cascades
2018-04-13 13:47:27 -07:00
Carol Willing
f2684b59ec Merge pull request #1802 from minrk/dbutil-shell
add `python -m jupyterhub.dbutil shell`
2018-04-13 12:54:23 -07:00
Min RK
e0c0d03c5f define client_id in oauth token test 2018-04-13 21:52:17 +02:00
Min RK
1ac47d2bb0 consolidate stale client_id check to AccessToken.find 2018-04-13 21:49:57 +02:00
Min RK
bc75c71ca3 ensure oauth tokens with no client id aren’t accepted
these should have been deleted by deleting oauth clients
2018-04-13 21:42:38 +02:00
Min RK
c49fc14528 move oauth token relation to user
for symmetry with APIToken
2018-04-13 21:26:18 +02:00
Min RK
078bd8c627 fix and test deletion cascades
- ensure foreign keys are enabled on sqlite
- fix deletion cascades where relationships were causing dissociation instead of deletion
2018-04-13 21:23:58 +02:00
Min RK
33ba9fb5cf ensure foreign keys are enabled on sqlite 2018-04-13 21:23:58 +02:00
Min RK
4e7e586cb9 add python -m jupyterhub.dbutil shell
allows opening an IPython shell with a connection to your database

alembic moved from `python -m jupyterhub.dbutil` to `python -m jupyterhub.dbutil alembic` subcommand
2018-04-13 21:23:36 +02:00
Min RK
62fa795052 Merge pull request #1803 from minrk/status-code-typeyo
typo catching 404 in proxy.delete_route
2018-04-13 21:22:54 +02:00
Min RK
b6d9f89518 typo in test_multi_groups
add multiple groups, not users
2018-04-13 21:01:48 +02:00
Min RK
afbf867169 typo catching 404 in proxy.delete_route
status code is .code, not .status_code
2018-04-13 20:54:15 +02:00
Carol Willing
dace6ac156 Merge pull request #1793 from minrk/server.port
check if server is defined before accessing server.port
2018-04-13 10:31:05 -07:00
Carol Willing
cbf2b8cb78 Merge pull request #1790 from minrk/409-conflict
raise 409 conflict on duplicate actions
2018-04-13 10:29:52 -07:00
Carol Willing
96c5de63d8 Merge pull request #1775 from minrk/proxy-perf
proxy performance tweaks
2018-04-13 09:48:59 -07:00
Carol Willing
b8b57843a6 Merge pull request #1771 from minrk/progress
Progress on spawn-pending page
2018-04-12 16:16:37 -07:00
Min RK
e3fd4ad77d check if server is defined before accessing server.port
avoids error on premature access of Spawner.get_args if port is not set
2018-04-12 14:34:18 +02:00
Min RK
c08148266a raise 409 conflict on duplicate actions
Makes it easier for upstream clients to retry failed actions and ignore failure due to duplicate transactions
2018-04-11 10:52:05 +02:00
Min RK
a6a2d04c46 Merge pull request #1768 from sangramga/master
Added Post groups API in group list handlers
2018-04-10 13:11:05 +02:00
Min RK
8f7061fb9b Merge pull request #1779 from minrk/cull-semaphore
limit concurrent cull requests
2018-04-10 13:10:45 +02:00
Min RK
7b5235138f commit changes after stopping in cleanup 2018-04-09 16:00:04 +02:00
Min RK
7e3fa8c38d Don't double-check _stop_pending flag
could cause spurious raises of Timeout errors
2018-04-09 15:58:39 +02:00
Min RK
151acd5bec catch errors in cleanup 2018-04-09 15:16:05 +02:00
Min RK
23ca2039f6 run cleanup_after on ioloop
instead of directly on asyncio
2018-04-09 15:09:50 +02:00
Min RK
b291103592 fixup cleanup 2018-04-09 14:51:20 +02:00
Min RK
e962c9993b don't ask for exception is Future is not done 2018-04-09 14:47:50 +02:00
Min RK
955b769d3f add missing commits for deprecated ip/port
consider for removal
2018-04-09 14:47:34 +02:00
Min RK
9b914e8f01 fix waiting for spawner to fail in progress 2018-04-09 14:46:28 +02:00
Min RK
307ad636dc test spawner failure mid-progress 2018-04-09 14:46:08 +02:00
Min RK
2952f62726 add cleanup_after fixture
function-scoped fixture for shutting down servers

avoids servers leaking into neighbor tests without having to teardown the app itself after every test
2018-04-09 14:24:29 +02:00
Min RK
6d6e48f434 test native async generator on Python 3.6 2018-04-09 13:03:29 +02:00
Min RK
a189196855 ensure async generators are properly closed
only terminate with iterate_until in handler, not Spawner._generate_events
2018-04-09 13:03:18 +02:00
Min RK
d30e62a205 test spawn progress 2018-04-09 11:39:07 +02:00
Min RK
e56d416210 Don't delete failed spawners
They preserve error messages that are useful

only delete spawners that shutdown cleanly
2018-04-09 11:38:29 +02:00
Min RK
c0f37c48a1 fix wait for spawn future
asyncio.wait takes a list
2018-04-09 11:16:17 +02:00
Min RK
a3ed387455 move get_content_type up one level to BaseHandler
so all handlers get it
2018-04-09 10:38:02 +02:00
Min RK
beedc94179 delete the spinner
no need for a spinner when we have a progress bar
2018-04-09 10:32:28 +02:00
Tim Head
5229604782 Merge pull request #1781 from consideRatio/link-in-doc-fix-pr
links in docs corrected
2018-04-08 14:06:57 +02:00
Erik Sundell
cf665517dd links in docs corrected 2018-04-08 09:10:09 +02:00
sangramga
4663edd8a7 removed comments 2018-04-07 13:09:12 +05:30
Min RK
312e7974d9 limit concurrency of cull requests
avoids simultaneous request for deletion of lots of users, which can slow down the Hub
2018-04-06 16:03:48 +02:00
Min RK
ca8aa53b32 remove 'missing' from default route message
avoids indication that something went wrong
since this occurs during normal hub startup
2018-04-05 12:12:03 +02:00
Min RK
7122ca1c24 add lock to prevent concurrent calls to check_routes 2018-04-05 12:09:06 +02:00
Min RK
97cdb1a5d8 handle progress_url in user model tests 2018-04-05 11:46:47 +02:00
Min RK
31d3f7a20b allow isoformat(None)
simplifies "if timestamp is None" cases when we are just using it to serialize nullable timestamps to JSON
2018-04-05 11:32:34 +02:00
Min RK
6f8a34127b consolidate progress url
and include it in server models
2018-04-05 11:28:52 +02:00
Min RK
ee1a86d192 progress url is at server/progress
instead of server-progress
2018-04-05 11:22:00 +02:00
Min RK
707b300bd6 add iterate_until utility
allows iterating through an async generator, yielding items until another Future resolves

if/when that deadline Future resolves, ready items will continue to be yielded until there is one that actually needs to wait
at which point the iteration will halt
2018-04-05 11:22:00 +02:00
Min RK
c9e12182a2 halt progress iteration on completed spawn
requires calling `__aiter__` and `__anext__` instead of `async for`
2018-04-05 11:22:00 +02:00
Min RK
9b7186e9b8 close eventstream on success 2018-04-05 11:22:00 +02:00
Min RK
4eb07f9d48 stop spinner on failure 2018-04-05 11:22:00 +02:00
Min RK
4f78cbbd1b implement progress on spawn_pending page
- add Spawner.progress method. Must be an async generator of JSON-able progress events
- add /api/users/:user/server-progress eventstream endpoint
- use eventstream to fill progress bar on the spawn pending page
2018-04-05 11:22:00 +02:00
Min RK
d962e8bcbc Merge pull request #1748 from minrk/cookie-options
expose cookie options and pass them down to spawners
2018-04-05 10:28:46 +02:00
Min RK
ba695a0230 Merge pull request #1750 from minrk/warn-should-start
remove warning when generating proxy token if Proxy.should_start
2018-04-05 10:28:18 +02:00
Min RK
dfed2437a8 Merge pull request #1746 from minrk/activity-tracking
expand user activity timestamps
2018-04-05 10:27:55 +02:00
Min RK
ecfcb4ec64 Merge pull request #1745 from minrk/rm-redirects
clear ?redirects from URL once single-user pages load successfully
2018-04-05 10:25:24 +02:00
Min RK
b9335311de Merge pull request #1774 from dhirschfeld/patch-1
Fix Windows build
2018-04-05 10:24:41 +02:00
Dave Hirschfeld
354468db0a Fix Windows build
Closes #1773
2018-04-05 16:35:29 +10:00
Min RK
340a736722 use age instead of time cutoff
gets nicely formatted timedeltas in logging
instead of absolute times
2018-04-03 15:24:10 +02:00
Min RK
7bf93cb7e6 update cull_idle_servers for 0.9
- adds max-age
- handle named servers
- refactor culling a bit
2018-04-03 15:24:10 +02:00
Min RK
4fa9535fd4 get upstream changes from cull_idle_servers.py in zero-to-jupyterhub 2018-04-03 15:24:10 +02:00
Min RK
1abd3217aa always run test_auth_api with 'admin' user
avoids inconsistent subsequent state based on db behavior
2018-04-03 15:24:10 +02:00
Min RK
d0360d5c98 update tests with new user models
add normalize_user and fill_user utilities
2018-04-03 15:24:08 +02:00
Min RK
74365ad05e starting a server updates last_activity and started for user and spawner 2018-04-03 15:14:47 +02:00
Min RK
9dc24c0995 add user.created, spawner.started
- alembic revision
- in user/spawner models
2018-04-03 15:14:47 +02:00
Min RK
fd40e27be4 indicate that REST API timestamps are UTC
use iso8601 Z suffix for UTC timestamps

use dateutil to parse dates from proxy, as well

even though CHP uses iso8601 UTC timestamps, we no longer assume CHP, so use more general parsing

in our db we are stuck with naïve datetime objects, so use those internally.
But ensure we put 'Z' on timestamps we ship externally
2018-04-03 15:14:47 +02:00
Min RK
05b2bf4c96 ensure user.created is defined during app startup
avoids user.created being null after upgrade
2018-04-03 15:14:47 +02:00
Min RK
a0fcbcbc7d do not consider stopping a user's server activity 2018-04-03 15:14:47 +02:00
Min RK
3117ea9d34 handle user.last_activity being None 2018-04-03 15:14:47 +02:00
Min RK
8973dea33e add user.created and start last_activity as None
need to handle last_activity being None throughout
2018-04-03 15:14:47 +02:00
Min RK
3e7d0dbd23 update user.last_activity whenever we see activity on API tokens / cookies 2018-04-03 15:14:47 +02:00
Min RK
b26b1bc038 Merge pull request #1720 from glenak1911/gk/update-circleci-config-v2
Updated CircleCI config file to 2.0
2018-04-03 13:14:14 +02:00
Glen A Knight
74b1102dea Delete package-lock.json 2018-04-02 09:06:57 -04:00
Glen A Knight
a89226279f remove checkout step from deploy and release jobs 2018-04-02 09:03:50 -04:00
Glen A Knight
8b490c8ef0 add package-lock.json to gitignore 2018-04-02 09:03:09 -04:00
Min RK
77a98e7875 Merge pull request #1753 from minrk/check-pending
avoid deleting routes for spawners in a pending state
2018-04-02 09:31:29 +02:00
sangramga
c02592d5ba Merge remote-tracking branch 'origin/master' 2018-03-31 16:24:08 +05:30
sangramga
52d7dacbaa post groups api added
Added post groups list api

Added test for  Multi groups post API

Added Post  multiple groups API
2018-03-31 16:20:51 +05:30
sangramga
9a8457deff Added Post multiple groups API 2018-03-31 15:42:58 +05:30
sangramga
5039b3ac6f Added test for Multi groups post API 2018-03-31 14:46:49 +05:30
sangramga
00705223b6 Added post groups list api 2018-03-31 13:10:48 +05:30
Glen Knight
9f6ab4c419 make workflows in line with jobs 2018-03-30 11:39:25 -04:00
Glen Knight
9012c7310d update workflows 2018-03-29 01:53:37 -04:00
Glen Knight
a3edebcad9 update run commands 2018-03-29 01:49:50 -04:00
Glen Knight
f2abb6a73f update indentation 2018-03-29 01:40:35 -04:00
Glen Knight
e96e5b740a update indentation 2018-03-29 01:38:57 -04:00
Glen Knight
ee067ad97a update indentation 2018-03-29 01:36:44 -04:00
Glen Knight
d01b3a88b6 update workflow 2018-03-29 01:34:59 -04:00
Glen Knight
5a22c978cf update workflows 2018-03-29 01:26:14 -04:00
Glen Knight
f8a0e7d1be update workflows 2018-03-29 01:25:23 -04:00
Glen Knight
25a65564b1 update workflows 2018-03-29 01:24:00 -04:00
Glen Knight
c858023c88 update config and add workflows 2018-03-29 01:19:17 -04:00
sangramga
c3e470db26 post groups api added 2018-03-28 18:50:35 +05:30
Min RK
5908c4da7a clarify pending exception comment 2018-03-27 17:49:03 +02:00
Min RK
b08dbbd106 handle that auth_token is checked now at startup 2018-03-27 17:46:37 +02:00
Min RK
3b320c75e9 remove warning when generating proxy token if Proxy.should_start
Now that it's unambiguous whether the proxy should start or not,
we don't need a warning about generating tokens causing issues for hub restart.

We can raise a strict, early error if proxy s external and token is still unspecified,
rather than running into a 403 error due to a generated token
2018-03-27 17:46:25 +02:00
Min RK
1aa6dc6686 use semaphore to limit concurrent requests to the proxy
should limit timeout errors in case of flooding the proxy with requests

default concurrency is 10
2018-03-27 14:30:03 +02:00
Min RK
fdc4385e62 a bit more debug logging in proxy.check_routes
- log (info) that check_routes is starting
- log (debug) when fetching routes
2018-03-27 14:25:49 +02:00
Min RK
5094448762 Merge pull request #1743 from betatim/user-api
[MRG] Expose `auth_state` via /api/users/<name>
2018-03-27 10:56:39 +02:00
Min RK
98c7fa919f avoid deleting routes for spawners
we previously checked if spawn_pending, but *any* transitional state should exclude them from the check
2018-03-27 10:43:43 +02:00
Tim Head
5b9f51417f Fix permission check when handing out auth state 2018-03-27 10:02:59 +02:00
Tim Head
7a91f89474 Use user's token for auth when using API 2018-03-27 10:02:59 +02:00
Tim Head
bf7afa16e5 Remove auth state from user's self handler 2018-03-27 10:02:59 +02:00
Tim Head
0d57baae82 Modify user API wrt auth_state
A user can not get their own auth state via the REST API. Only admins
can fetch and update the auth state this way.
2018-03-27 10:02:59 +02:00
Tim Head
446d197cf7 Move auth state fixture to conftest 2018-03-27 10:02:59 +02:00
Tim Head
2582f0bbe6 Modify auth_state API test to use mocked crypto 2018-03-27 10:02:59 +02:00
Tim Head
1ee993c664 Add ability to modify auth_state via the REST API 2018-03-27 10:02:59 +02:00
Tim Head
542c20065f Reduce the number of endpoints that expose auth_state 2018-03-27 10:02:59 +02:00
Tim Head
39f663d03c Expose auth_state via user API 2018-03-27 10:02:59 +02:00
Min RK
6474a55302 Merge pull request #1749 from minrk/await-fixes
fix await of default authenticate
2018-03-26 13:34:01 +02:00
Min RK
8566d4c5ab fix await of default authenticate 2018-03-23 10:57:47 +01:00
Min RK
e374e93cfb expose cookie options and pass them down to spawners
enables forcing all-session cookies with:

```python
c.JupyterHub.tornado_settings['cookie_options'] = {
    'expires_days': None,
}
```
2018-03-23 10:38:50 +01:00
Min RK
7bd4f6490c Merge pull request #1731 from vilhelmen/pam_account_check
Allow checking PAM account stack during PAM auth
2018-03-23 09:19:20 +01:00
Unknown
25373f510d Allow and enable PAM account stack checking
JH can now differentiate between authenticated and authorized users via PAM
This allows JH to respect PAM-accessible user access controls.

This also fixes missing PAMAuthenticator.encoding usages.
2018-03-22 15:53:28 -05:00
Min RK
82cab39e1c Merge pull request #1722 from minrk/login-spawn
Simplify root/login redirect behavior
2018-03-21 13:20:49 +01:00
Min RK
22507cc1cd clear ?redirects from URL once single-user pages load successfully 2018-03-21 13:01:29 +01:00
Min RK
2bded65c7e update singleuser auth test url check
handle `?redirects`
2018-03-21 12:58:59 +01:00
Min RK
a3a0c60804 update redirect tests
now that redirects are not sensitive to state
2018-03-21 11:15:40 +01:00
Min RK
704b172887 update tests to reflect that login no longer implies spawn 2018-03-21 10:51:49 +01:00
Min RK
135717f8cb Merge pull request #1733 from willingc/spawner-comment
Add a spawner_class option to the reference example
2018-03-21 10:38:33 +01:00
Glen Knight
1d87ba8534 updated run? 2018-03-19 23:59:14 -04:00
Glen Knight
97cd27775b updated run command 2018-03-19 23:56:45 -04:00
Glen Knight
fe2e9c282e removed checkout 2018-03-19 23:44:53 -04:00
Glen Knight
fab125975b re-added build step 2018-03-19 23:39:50 -04:00
Glen Knight
cefd7e3b1b remove cicle.yml 2018-03-19 23:38:37 -04:00
Carol Willing
344a3e7b24 Add a spawner_class option to the reference example 2018-03-19 14:23:14 -07:00
Min RK
a0ee237ada Simplify root/login redirect behavior
- ignore spawner state when determining redirect destination
- remove implicit spawn from login handler (rely on redirect to user.url for spawn)
- settings.redirect_to_server determines if login sends users to /user/:name vs /hub/home
- visiting `/hub/` should result in the same destination regardless of login state or spawner state
2018-03-14 15:37:25 +01:00
Min RK
e81eb9a5f8 Merge pull request #1687 from minrk/external-oauth-basic
fix /api/user with oauth tokens
2018-03-13 16:11:28 +01:00
Min RK
98d3b538af Further clarifications in external-oauth example 2018-03-13 10:03:01 +01:00
Min RK
3614a0e368 move get_self test after get_users
to avoid changing expected state
2018-03-13 10:03:01 +01:00
Min RK
0421497b1e remove web.authenticated from /api/user handler
which prevents it from being used with oauth tokens
2018-03-13 10:03:01 +01:00
Min RK
8b3c2fa12f add whoami-oauth-basic example
implements oauth without inheriting from HubOAuthenticated

should be easier to parse for users with alternate oauth implementations
2018-03-13 10:03:01 +01:00
Min RK
a58bea6d93 Merge pull request #1696 from minrk/async-def
async/await syntax
2018-03-12 18:40:34 +01:00
Min RK
c7c41cd761 remove bad yield in test_api 2018-03-12 18:32:00 +01:00
Min RK
b282ec73c7 no_patience doesn't quite work with zero timeout anymore
thanks to asyncio always waiting a finite time on any await
2018-03-12 18:18:47 +01:00
Min RK
dad26be2c6 call it our own maybe_future
our version of gen.maybe_future that's fully tornado- and asyncio-compatible
2018-03-12 18:18:47 +01:00
Min RK
58d602e549 require Python 3.5 for async/await syntax 2018-03-12 18:18:46 +01:00
Min RK
5e14904205 fix a few unawaited calls to coroutines
asyncio is less forgiving about these than tornado
2018-03-12 18:18:46 +01:00
Min RK
97293ab7ce use asyncio.ensure_future to start coroutines immediately
asyncio has different coroutine start mechanics than tornado

tornado starts coroutines immediately,
whereas asyncio doesn't until they are scheduled with either ensure_future or waited upon.
2018-03-12 18:18:46 +01:00
Min RK
b6f634368c add utils.awaitable replacement for gen.maybe_future
gen.maybe_future doesn't accept asyncio coroutines
and asyncio.ensure_future doesn't accept *tornado* coroutines, so do our own thing
2018-03-12 18:18:46 +01:00
Min RK
7b4de150cc add awaitable wrapper
to replace gen.maybe_future
2018-03-12 18:18:46 +01:00
Min RK
7a268c94b0 bulk find/replace async def and await
- `@gen.coroutine def` -> `async def`
- `yield future` -> `await future`

needs some fine tuning, but this is the big one
2018-03-12 18:18:46 +01:00
Carol Willing
7a1fa78632 Merge pull request #1660 from minrk/spawn-form-access
expand admin[-access] support
2018-03-12 07:34:07 -07:00
Min RK
19f02da64d should_spawn=False when current_user is None (not logged in) 2018-03-12 14:23:57 +01:00
Min RK
5bf1aac9cb get the right render form when spawning for another user 2018-03-12 14:23:57 +01:00
Min RK
0ae034083c fix spawn admin tests 2018-03-12 14:23:57 +01:00
Min RK
5010af941b 'start server' on admin page opens spawn form
if spawn form is registered and admin access is enabled

cannot use spawn form on behalf of users without admin_access
2018-03-12 14:23:52 +01:00
Min RK
015df7e060 unify mocking of tornado_settings
ensures that everywhere we access settings, it's the same dict
and not a copy
2018-03-12 14:23:00 +01:00
Min RK
e025d58f6e fix mocks for spawner config 2018-03-12 14:23:00 +01:00
Min RK
b151d333d3 show who you're spawning for if it's not yourself
on the spawn page
2018-03-12 14:23:00 +01:00
Min RK
304c005a85 fix priority of template namespace
allow overrides
2018-03-12 14:23:00 +01:00
Min RK
e2591e8e36 fix user construction in add_user test function
ensures same construction is used as the real app
2018-03-12 14:23:00 +01:00
Min RK
f3c22cb6d0 test spawn-form for other users 2018-03-12 14:23:00 +01:00
Min RK
b2527984bc use find_user in POST /spawn/:user
so we get a 404 for missing users
2018-03-12 14:23:00 +01:00
Min RK
b8d2271191 add /spawn/:user for spawning servers for a specific user
part of admin-access
2018-03-12 14:23:00 +01:00
Min RK
b8978b0235 allow admin-access to launch servers via /user/:name
rather than checking if user.name == name,
check more directly if user should have access to :name's server
2018-03-12 14:23:00 +01:00
Min RK
63ef6419cd add admin_access fixture 2018-03-12 14:23:00 +01:00
Min RK
25dc429455 ensure app.tornado_settings is the real tornado settings in mocking
enables updates to settings during testing
2018-03-12 14:23:00 +01:00
Carol Willing
7550e63fd0 Merge pull request #1700 from minrk/cookie-name
cleanup some cookie names
2018-03-07 08:34:25 -08:00
Carol Willing
0561968fac Merge pull request #1694 from minrk/sigusr
add SIGINFO handler
2018-03-07 08:32:08 -08:00
Min RK
7811bf518b cleanup some cookie names
In part to cleanup a few remnants of early design where jupyterhub was ‘jupyter-hub’ instead of ‘jupyterhub’.
Should also clarify to some degree what the cookies are for.

- hub login cookie is now ‘jupyterhub-hub-login’ instead of ‘jupyter-hub-token’
- user server cookie is now ‘jupyterhub-user-<name>’ instead of ‘user-name’ to keep jupyterhub prefix on all cookies

All cookies at this point:

- jupyterhub-session-id on /
- jupyterhub-hub-login on /hub/ (the main login cookie)
- jupyterhub-services on /services/
- jupyterhub-user-<name> on /user/:name
- jupyterhub-user-<name>-oauth-state on /user/:name during oauth
2018-03-05 10:55:07 +01:00
Min RK
bc7116ad94 Merge pull request #1691 from minrk/async-pam-auth
talk to PAM in a thread
2018-03-02 11:40:18 +01:00
Carol Willing
70eec33d06 Merge pull request #1692 from minrk/gitignore
gitignore some more files
2018-03-01 09:05:53 -08:00
Min RK
773973825f also show asyncio task stacks
which are nicely formatted on their own

there won't be many yet, but if we transition to async def,
we will get lots more useful info
2018-03-01 14:39:11 +01:00
Min RK
a184d372f4 add SIGINFO handler
send SIGINFO (ctrl-T) to jupyterhub and it will dump
process info

- if psutil is available, show cpu, memory, FD counts
- always show stacks of non-idle threads
2018-03-01 14:37:46 +01:00
Min RK
ca1606a021 factor-out coroutine_frames filtering
so it can be used on stacks, not just tracebacks
2018-03-01 14:23:26 +01:00
Min RK
5c6d7eb309 gitignore some more files
static files have moved
2018-03-01 11:26:35 +01:00
Min RK
4de6b39788 talk to PAM in a thread
since PAM can be slow, we don't want to block the rest of the application
2018-03-01 11:22:01 +01:00
Carol Willing
f0494cc7d6 Merge pull request #1688 from minrk/no-trash
disable send2trash by default
2018-02-28 09:01:19 -08:00
Min RK
9d98d1ee63 disable send2trash by default
avoids filling up hidden .Trash directory when files are deleted

since there's no UI for trash in a jupyterhub deployment, this mainly results in files never being deleted and possibly filling up disks
2018-02-28 16:19:17 +01:00
Min RK
f1238e17b1 Merge pull request #1667 from minrk/templates
move static resources to share/jupyterhub
2018-02-28 15:57:10 +01:00
Min RK
4201c8a6f3 missing share_jupyterhub 2018-02-28 15:41:58 +01:00
Min RK
53396ed454 bower-lite, too 2018-02-28 15:41:58 +01:00
Min RK
8695823165 move static resources to share/jupyterhub
from share/jupyter/hub

to be consistent with use of etc/jupyterhub etc.
2018-02-28 15:41:58 +01:00
Min RK
ec8d008678 Merge pull request #1684 from emmanuel/support_async_options_form
Add `Spawner.get_options_form` for async support.
2018-02-28 11:08:51 +01:00
Emmanuel Gomez
a949ad14f8 Correct versionchanged annotation based on review. 2018-02-27 09:17:50 -08:00
Emmanuel Gomez
48e7bd4f10 Add Spawner.get_options_form for async support. 2018-02-26 16:50:40 -08:00
Min RK
4b11f8f26b Merge pull request #1670 from thedataincubator/nav-blocks
Add blocks for navbar components in the page template
2018-02-26 13:28:15 +01:00
Robert Schroll
b056444863 Add blocks for navbar components in the page template 2018-02-23 12:15:35 -08:00
Carol Willing
872f021ddc Merge pull request #1590 from minrk/external-oauth
enable external oauth clients
2018-02-23 06:35:59 -08:00
Min RK
079b0c1b91 feedback in README 2018-02-23 13:44:07 +01:00
Min RK
2664b50a18 Merge pull request #1678 from minrk/fix-stop
fix stop of singleuser with tornado 5
2018-02-23 09:29:02 +01:00
Min RK
6970df4dda add external oauth example 2018-02-22 17:01:00 +01:00
Min RK
22c3064ec4 pass note arg in User.new_api_token 2018-02-22 15:10:13 +01:00
Min RK
d6ab65a2e7 remove alembic autogenerate statements 2018-02-22 15:06:52 +01:00
Min RK
aa23b01a57 add notes on API tokens when they are allocated 2018-02-22 15:06:01 +01:00
Min RK
d82de98001 add alembic revision for token tracking
via alembic autogenerate
2018-02-22 15:06:01 +01:00
Min RK
7df8597484 cleanup oauth clients at startup
avoids leaving stale oauth clients in db

- cascade oauth access token, code deletion on delete of oauth client
2018-02-22 15:06:01 +01:00
Min RK
1b99b1275c allow service redirect uri to come from config
for external services

- ensure Spawner.oauth_client_id is always defined, not just for running Spawners
2018-02-22 15:05:53 +01:00
Min RK
d16461052b track activity of individual tokens 2018-02-22 15:05:18 +01:00
Min RK
9640364713 Merge pull request #1665 from thedataincubator/templates-doc
Add documentation for new templates system
2018-02-22 15:03:10 +01:00
Min RK
18e0600727 Merge pull request #1627 from minrk/logging-unicode
Fix unicode errors with extra_log_file
2018-02-22 15:01:34 +01:00
Min RK
17fffda74e fix stop of singleuser with tornado 5
Updates call to match notebook application itself

calling IOLoop.instance() is deprecated, and won't work from a background thread with tornado 5.
2018-02-22 14:48:36 +01:00
Robert Schroll
3ac4f48f82 Add version information to templates doc 2018-02-21 15:13:47 -08:00
Min RK
6f8ae98ed0 Merge pull request #1661 from GladysNalvarte/ports
Additional information about which ports can be used and which are reserved for internal use only.
2018-02-19 15:16:19 +01:00
Min RK
47b2ce6180 Merge pull request #1601 from thedataincubator/base-template
Base template mechanism
2018-02-19 14:42:40 +01:00
Gladys Nalvarte
d18d84e187 Includes suggestions to make more clear to the end user which port/ip is public. 2018-02-16 15:30:15 +01:00
Robert Schroll
c1dcdf49e5 Add doc page on templates 2018-02-15 16:18:15 -08:00
Min RK
079005eab1 Merge pull request #1643 from minrk/startup-lite
avoid instantiating idle Spawner objects during startup
2018-02-15 15:25:22 +01:00
Robert Schroll
dc8cea3a3e Change base template flag to "templates/" 2018-02-14 16:55:22 -08:00
Robert Schroll
efca88cf8b Always enable the base templates feature 2018-02-14 16:49:11 -08:00
Gladys Nalvarte
c05a6b96b7 Additional information about which ports can be used and which are reserved for internal use only. 2018-02-14 11:06:08 +01:00
Min RK
a831ff3b61 Merge pull request #1653 from dhirschfeld/patch-1
Add PyCharm folder to gitignore
2018-02-12 13:27:02 +01:00
Dave Hirschfeld
b814a09fe6 Add PyCharm folder to gitignore 2018-02-09 12:51:57 +10:00
Min RK
fb48c8626a fix reuse token test now that Spawners are cleaned up after stopping
put the Spawner instance back so it can reuse the token

'real' reuse cases don't need this because the info is stored in their own storage,
e.g. a stopped container.
2018-02-07 11:31:59 +01:00
Min RK
fbdeb4c386 move add_user call for new users to login_user
previous location was in a non-awaitable call
2018-02-07 11:22:47 +01:00
Min RK
4cf9ecc819 spawners are deleted during shutdown 2018-02-06 17:09:59 +01:00
Min RK
e9573b6e24 fixup test_orm with new User wrapper
user.db is evaluated immediately, rather than on first request,
which means we can't do User(orm.User) before adding the orm.User to the db
2018-02-06 17:02:23 +01:00
Min RK
d5f0137052 revert computing user_model from orm.User
always instantiate User wrapper
2018-02-06 15:38:32 +01:00
Min RK
d9f5adb1fb instantiate all User objects during application startup
still avoid instantiating Spawners
2018-02-06 15:38:30 +01:00
Min RK
0c6aa064ac Make User not a HasTraits
HasTraits are expensive to instantiate, so make Users as light as possible

Removes immediate instantiation of Spawners during User init. Spawners will only be instantiated while running
2018-02-06 15:38:08 +01:00
Min RK
646c853cf4 Merge pull request #1648 from thedataincubator/login-redirect
Add option to redirect to running Jupyter server
2018-02-06 15:16:45 +01:00
Min RK
fb3bc95623 Remove expunges from startup 2018-02-06 12:04:14 +01:00
Min RK
c8b4cab022 support getting user models from orm-only User objects
avoids instantiating User wrappers for inactive users in get_all_users
2018-02-06 12:04:14 +01:00
Min RK
06fb94b4ea Delay instantiation of User and Spawner objects
Avoids instantiating too many objects before they are used

- deletes Spawner instances after they stop to avoid lingering instances
- use user_dict cache more often instead of db queries
- check for empty spawners dict to avoid a few Spawner instantiations
2018-02-06 12:04:14 +01:00
Robert Schroll
9f6cef4fb4 Add option to redirect to running Jupyter server
This is how the system used to behave, but now it can be turned off, always
showing the control panel on login.  Adjustment is needed in two places.
2018-02-05 18:12:07 -08:00
Min RK
0315dd5612 avoid instantiating idle Spawner objects during startup
only instantiate Spawners when they are requested
2018-02-02 00:22:47 +01:00
Min RK
e4e5bebc1a Merge pull request #1638 from minrk/404-ok
avoid raising on 404 deleting proxy route
2018-02-01 21:32:52 +01:00
Min RK
c688e9ebad avoid raising on 404 deleting proxy route
deleting a route that doesn't exist should only warn, not error
2018-02-01 20:18:13 +01:00
Min RK
6d6041a3c1 parallelize startup poll
puts each check for a running spawner in a coroutine and runs them all concurrently.

Note: this will only improve performance when a large number of Spawners are running and `yield spawner.poll()` takes a nontrivial amount of time.
This is because these are coroutines, not threads. If instantiating Spawners themselves takes a long time, performance will not be affected.
2018-02-01 20:17:47 +01:00
Min RK
dde7b5ea68 Merge pull request #1642 from minrk/tornado-5-b
Fixes for tests with tornado 5
2018-02-01 19:57:59 +01:00
Min RK
9bf533b340 fixes when tests are run on asyncio
- need to explicitly instantiate asyncio eventloops in background threads
- remove some now-obsolete initialized checks in teardown
2018-02-01 14:56:40 +01:00
Min RK
f1a105abec register tornado's asyncio support at launch time, not import time
avoids other imports from overriding this
2018-02-01 14:49:55 +01:00
Carol Willing
e6587b5dc8 Merge pull request #1631 from minrk/bumps
bump jupyterhub version to 0.9.0.dev
2018-01-24 08:17:54 -08:00
Min RK
b2ad045a2d update docker build hooks
stable is 0.8 (and has been for some time now)
2018-01-24 16:50:49 +01:00
Min RK
89734d8c5f master is 0.9.0.dev
now that we've started making db changes
2018-01-24 16:46:46 +01:00
Min RK
53736099ba specify extra_log_file encoding as utf8
even if locale is ascii

extra_log_file can fail with encoding errors, where stdout logging will escape safely.
2018-01-22 07:39:09 +01:00
Carol Willing
2fcfa136c1 Merge pull request #1625 from jupyterhub/ellisonbg-patch-1
Remove unicode character in favor of plain ->
2018-01-18 15:40:05 -08:00
Brian E. Granger
9f85209a1b Remove unicode character in favor of plain ->
This is still causing problems in all fresh deployments we are doing. I am fine with another solution, but at least wanted to proposed this as a fix for now.
2018-01-18 12:31:17 -08:00
Carol Willing
cea1b2fd4d Merge pull request #1623 from BerserkerTroll/patch-1
Fix Authentication state documentation
2018-01-17 09:28:22 -08:00
BerserkerTroll
312252b670 Fix Authentication state documentation
This — is how it actually works!
2018-01-17 05:45:47 +03:00
Min RK
4d6b30c17b Merge pull request #1621 from consideRatio/master
Fix spawner/service typo in proxy.py
2018-01-13 13:20:44 -08:00
Erik Sundell
0beb9c2670 fix spawner/service typo in proxy.py 2018-01-13 21:43:09 +01:00
Min RK
a0289af59f Merge pull request #1615 from yuvipanda/hub_connect_ip
Add note about hub_connect_ip restrictions
2018-01-12 17:38:16 -08:00
Carol Willing
40363834c8 Merge pull request #1619 from timfreund/linkupdate
Update docker volumes link
2018-01-12 09:08:47 -08:00
Tim Freund
0c9e5fd10b Update docker volumes link
The old link now returns 404.
2018-01-11 21:28:24 -05:00
yuvipanda
3d90e5cdf6 Add note about hub_connect_ip restrictions
Kubernets Ingress Proxy requires IPs, and I suspect other
proxies in the future might have DNS restrictions too.
This causes confusion, in cases like
https://github.com/jupyterhub/kubespawner/issues/116.
2018-01-10 18:35:58 -08:00
Robert Schroll
8e3f1f0955 Add a block around the message in the spawn_pending page
This makes it easier for users to add or substitute custom messages on
this page.
2018-01-04 15:34:59 -08:00
Robert Schroll
7c64415096 Add base_template option
If true, the user can have custom templates (specified in
template_paths) that extend the default templates, by referencing them
as "BASE:filename.html".  This makes it easier to add information to
exising templates.
2018-01-04 15:34:59 -08:00
Min RK
e3fd1dba0e Merge pull request #1609 from minrk/tornado-5
tornado 5 fixes
2018-01-03 18:24:07 +01:00
Min RK
9866a0fadc avoid raising HTTPError in get_current_user
it can cause issues, e.g. with upcoming notebook releases .get_current_user may be called in set_default_headers,
which doesn't catch HTTPErrors.
2018-01-03 14:58:42 +01:00
Min RK
f87f24d9e5 unpin tornado 2018-01-03 14:12:29 +01:00
Min RK
4729ae4769 tornado 5 fixes
- ._running private attribute is removed. We don't need it anymore,
  since we were only using it while the application was run in a background thread.
- call blocking cleanup in a thread because asyncio doesn't allow multiple loops in one thread.
2018-01-03 14:12:23 +01:00
Min RK
691c4c158f Merge pull request #1606 from willingc/test-readme
Add CHP to dev install and move to CONTRIBUTING
2018-01-03 11:52:27 +01:00
Carol Willing
3c597339ba Add CHP to dev install and move to CONTRIBUTING 2018-01-03 11:52:01 +01:00
Min RK
e5fe174e03 Merge pull request #1607 from willingc/travis-tornado
pin tornado requirement to less than 5.0
2018-01-03 11:50:18 +01:00
Carol Willing
1c25a9d026 pin tornado requirement to less than 5.0 2018-01-02 15:19:35 -08:00
Min RK
2db378e9c1 Merge pull request #1577 from minrk/session-cookie
add session-id cookie
2017-12-19 15:18:02 +01:00
Min RK
a4067ee681 clarify alembic's autogenerated comments [ci skip]
with reformatting
2017-12-19 15:13:44 +01:00
Min RK
edb0831028 check for table before upgrading
avoids raising error, which aborts transactions on postgres
2017-12-19 14:19:49 +01:00
Min RK
dac3b0a6f5 clear cookies for the right domain 2017-12-19 11:05:02 +01:00
Min RK
9a180cc8ad relax failed-upgrade check
since each backend raises a different error, only check that the errors are the same.
2017-12-19 10:54:05 +01:00
Min RK
e81764610e Merge pull request #1588 from willingc/doc-spawner
Clarify resource limits/guarantees in docs and docstrings
2017-12-19 10:50:04 +01:00
Carol Willing
e4e2b627fe add formatting to clarify spawners' limits 2017-12-18 04:43:26 -08:00
Carol Willing
ec55f56725 clarify resource limits in docstrings 2017-12-18 04:33:41 -08:00
Carol Willing
1e4f871bcc update documentation on resource limits 2017-12-18 04:33:01 -08:00
Matthias Bussonnier
69f72919bd Merge pull request #1587 from darky2004/master
Request to add a new JupyterHub service provider
2017-12-15 21:20:32 +01:00
darky2004
dc0336fa45 Update gallery-jhub-deployments.md 2017-12-13 20:36:04 +00:00
darky2004
8c341d262e Update gallery-jhub-deployments.md 2017-12-13 20:35:34 +00:00
Min RK
2b15464e12 make add_columns conditional on table presence
in database upgrade.

For multi-version upgrades (e.g. 0.7 -> 0.9)
2017-12-12 14:38:06 +01:00
Min RK
a686235ffb alembic: add target_metadata
needed for `python -m jupyterhub.dbutil revision --autogenerate -m 'note'`
2017-12-12 10:54:08 +01:00
Min RK
29171a4d05 test logout
verify that:

1. auth is cached
2. oauth tokens are revoked on logout
3. clearing session id avoids cached auth data
2017-12-11 14:20:25 +01:00
Min RK
e9123f55e0 make HubAuth a singleton
allows cache re-use in default case

otherwise, default behavior is to instantiate anew on each request, eliminating cache
2017-12-11 14:20:25 +01:00
Min RK
ee004486bd include session id in cache key
if session id is defined, clearing the session id clears the cache,
allowing immediate revocation of tokens by the Hub.
2017-12-11 14:20:25 +01:00
Min RK
498e234c37 add cache repr for debugging 2017-12-11 14:20:25 +01:00
Min RK
b29f19e206 add session_id for OAuth tokens
allows tracking and revoking tokens for a login session
2017-12-11 12:15:36 +01:00
Min RK
1e00343262 Merge pull request #1581 from yuvipanda/prometheus
Add RED prometheus metrics for all requests
2017-12-11 12:00:25 +01:00
yuvipanda
3cd526c019 Make sure our metrics don't appear & disappear intermittently
Create all timeseries from the beginning, regardless of wether
they happen or not. Also rename metric objects for consistency.
2017-12-10 21:23:32 -08:00
yuvipanda
ea99c58da5 Clarify custom bucket sizes for spawn time histogram 2017-12-10 17:04:44 -08:00
yuvipanda
c64f23a64a Add note about metric naming conventions 2017-12-10 17:04:10 -08:00
yuvipanda
2099cd37fa s/starttime/start_time/ 2017-12-10 17:00:15 -08:00
yuvipanda
2559632079 Expand prometheus related docstrings a bit more 2017-12-10 16:59:35 -08:00
yuvipanda
352df39454 Add version requirement for prometheus_client 2017-12-10 16:52:19 -08:00
yuvipanda
ce3a940b11 Add histogram metric for proxy route addition 2017-12-10 15:01:47 -08:00
yuvipanda
6594e88390 Add metric recording spawn durations
Try to hit every possible exit point from the spawn_single_server
method, with an appropriate status code.

The default histogram buckets are also meant for request latencies,
but spawning usually takes longer so we use custom buckets
2017-12-10 14:54:34 -08:00
yuvipanda
339758ec42 Add RED prometheus metrics for all requests
This patch introduces Prometheus for exposing metrics
about JupyterHub's operation. We expose a standard /metrics
endpoint that can be queried without authentication. We
take on prometheus_client as an unconditional dependency
to both simplify code & because it is a pure python package
with no dependencies itself.

The first pass adds 'RED' style metrics for all HTTP requests.
http://rancher.com/red-method-for-prometheus-3-key-metrics-for-monitoring/
has some info on the RED method, but to summarize:

  For each request type, record at least the following metrics

   Rate – the number of requests, per second, your services are serving.
   Errors – the number of failed requests per second.
   Duration – The amount of time each request takes expressed as a time interval.

This instantly gives us a lot of useful metrics in a very
compact form.
2017-12-10 14:40:11 -08:00
Carol Willing
0b4c7defd4 Merge pull request #1578 from johnkpark/fix-static-file-caching
remove , which was turning timestamp into tuple
2017-12-07 19:55:24 -06:00
John Park
6d71e9065b remove , which was turning timestamp into tuple 2017-12-07 11:28:40 -08:00
Carol Willing
631ab4d4eb Merge pull request #1575 from minrk/rm-catchlog
remove pytest-catchlog in favor of recent pytest
2017-12-07 08:31:46 -06:00
Min RK
589ff47ae6 Merge pull request #1555 from ankitml/docker-compose-file
base dockerfile on alpine linux
2017-12-07 10:23:08 +01:00
Min RK
877034d012 remove pytest-catchlog in favor of recent pytest
pytest-catchlog has been merged into pytest as of pytest 3.3
2017-12-07 10:21:04 +01:00
Carol Willing
3d440bf8f5 Merge pull request #1570 from minrk/sigterm
stop polling proxy process during shutdown
2017-12-04 18:43:09 -06:00
Ankit
138b2be010 updated CMD and jupyterhub version is put into argument 2017-12-04 11:41:56 -05:00
Min RK
b729944480 Merge pull request #1564 from jkinkead/admin_from_authenticator
Allow Authenticators to return an `admin` flag for users.
2017-12-04 10:47:42 +01:00
Min RK
870afd9fac stop polling proxy process during shutdown
avoids proxy being restarted by `.check_running` during cleanup
2017-12-04 10:40:08 +01:00
Carol Willing
e808814725 Merge pull request #1567 from danielballan/build-docs
CI: Verify that the docs build without warnings.
2017-12-01 17:14:40 -06:00
danielballan
122cf2250d CI: Require the docs to build without warnings. 2017-12-01 11:18:47 -05:00
danielballan
fa1d962507 CI: Verify that the documentation builds. 2017-12-01 11:18:46 -05:00
Jesse Kinkead
6504692c5c Commit when setting admin, but only if the field changed. 2017-11-30 11:21:09 -08:00
Carol Willing
bd36962643 Merge pull request #1563 from jkinkead/patch-2
Include instructions for increasing test timeout.
2017-11-29 16:57:55 -06:00
Jesse Kinkead
f5ccfc3f8a Use travis timeout; expand documentation on timeout. 2017-11-29 14:46:18 -08:00
Jesse Kinkead
c1a7e0513b Allow Authenticators to return an admin flag for users. 2017-11-29 14:07:08 -08:00
Jesse Kinkead
af71e79371 Include instructions for increasing test timeout. 2017-11-29 13:05:01 -08:00
Min RK
bf911cf3a5 Merge pull request #1545 from ankitksharma/patch-1
Publish exposed port in docker run command
2017-11-29 18:15:46 +01:00
Carol Willing
6059a1c444 Merge pull request #1562 from minrk/external-proxy-test
wait for proxy to exit in test_external_proxy
2017-11-29 09:03:22 -06:00
Min RK
c4966a4bf2 Merge pull request #1561 from GladysNalvarte/master
test token and error pages
2017-11-29 15:24:44 +01:00
Min RK
cb9f356a69 wait for proxy to exit in test_external_proxy
.terminate() only sends the signal,
it doesn't wait for the process to exit.

If the process doesn't exit promptly,
the next instance may try to grab the port before the previous process has released it,
causing failure with EADDRINUSE.
2017-11-29 15:22:45 +01:00
Gladys Nalvarte
9d02f6a408 test_token and error pages 2017-11-28 10:09:39 +01:00
Min RK
ee76772e1b Merge pull request #1560 from GladysNalvarte/version-test
Version test
2017-11-27 12:56:42 +01:00
Min RK
f0a030a86d Merge pull request #1531 from thedataincubator/start_all_button
"Start All" button on admin page
2017-11-27 12:52:26 +01:00
Min RK
1a31e56f33 Merge pull request #1532 from minrk/npm-permissions
setup.py: run npm with --unsafe-perm
2017-11-27 12:52:06 +01:00
Gladys Nalvarte
04e9e0e687 test check_version
add coverage for different cases
2017-11-23 15:14:57 +01:00
Min RK
cec917c2a2 scaffolding for testing version checking 2017-11-23 10:55:35 +01:00
Carol Willing
08989a8797 Merge pull request #1557 from minrk/extra-log-file-warning
deprecate extra_log_file
2017-11-22 08:19:40 -08:00
Min RK
b734c331e4 deprecate extra_log_file
and add loud warning about discarding information

this has been the cause of many debugging difficulties,
when redirecting output seems to be a better option in ~all cases.
2017-11-22 17:02:43 +01:00
Matthias Bussonnier
fe477a6809 Merge pull request #1554 from smiller5678/remove-redirect-url-param-from-error-pages
Remove redirect url parameter from error pages
2017-11-21 23:05:47 +01:00
Carol Willing
6391a4a7f7 Merge pull request #1552 from cfournie/extendable_script_block
Add super() calls to child script blocks
2017-11-21 12:35:08 -08:00
Carol Willing
e68220d4b3 Merge pull request #1553 from syutbai/master
Add doc for building docs locally.
2017-11-21 12:21:28 -08:00
Ankit
b873149f9b updated alpine according to PR comments 2017-11-21 14:04:25 -05:00
Seak Pek Chhan
86aebbcaea Switch to python3 -m pip install instead of calling pip directly, move cd docs closer to make commands. 2017-11-21 14:02:07 -05:00
Ankit
fd260cf32f updated base name 2017-11-21 13:58:22 -05:00
Min RK
69101a5b14 Merge pull request #1533 from DerekHeldtWerle/master
If spawner is pending, always route to /hub/home/:user to resolve iss…
2017-11-21 19:54:51 +01:00
Ankit
151d6cbc48 updated readme 2017-11-21 13:53:39 -05:00
Ankit
04675e5fcb removed compose and env file 2017-11-21 13:50:43 -05:00
Ankit
b38c6fe06a added readme and started working on config image 2017-11-21 13:42:50 -05:00
Ankit
089a12bdc9 adding a readme 2017-11-21 13:32:59 -05:00
Ankit
d9a0a2003f moving base dockerfile into a directory 2017-11-21 13:23:21 -05:00
Derek Heldt-Werle
ad704d9925 No longer force a redirect when pending, simply set url to allow users access to home page during a pending spawn 2017-11-21 10:17:42 -08:00
Ankit
0cca79eeee auth token instructions updated 2017-11-21 13:03:25 -05:00
Ankit
457bea7c34 Base dockerfile 2017-11-21 13:01:21 -05:00
semiller
2479679eeb Remove redirect url parameter from error pages
Issue #1365
2017-11-21 12:59:02 -05:00
Chris Fournier
937405d2d8 Add super() calls to child script blocks 2017-11-21 12:24:58 -05:00
Seak Pek Chhan
d1bed1b9cc Add doc for building docs locally. 2017-11-21 12:15:30 -05:00
Ankit
acc60bce57 wip 2017-11-21 11:35:58 -05:00
Carol Willing
43807ff06b Merge pull request #1550 from syutbai/master
add jupyter-alabaster-theme to doc requirements.txt
2017-11-21 07:48:03 -08:00
Ankit
b8a63bcc0c auth env blank file 2017-11-21 10:26:28 -05:00
Ankit
66c1815a78 creating a simple docker compose environment to isolate jupyterhub notebook from other parts like configurable proxy 2017-11-21 10:25:06 -05:00
Matthias Bussonnier
4e5cfa2077 Merge pull request #1540 from minrk/cookie-secure
allow override of cookie options
2017-11-21 10:58:25 +01:00
Seak Pek Chhan
ebaf5d31b7 add jupyter-alabaster-theme to doc requirements.txt 2017-11-18 04:04:28 -05:00
Christian Moscardi
760a640c6a alternate, horizontal layout 2017-11-17 19:19:13 -05:00
Ankit Sharma
4fc06e9504 Publish exposed port in docker run command 2017-11-18 00:14:38 +05:30
Carol Willing
c283ccb122 Merge pull request #1539 from minrk/cors-fix
fix headers for CORS
2017-11-16 10:58:26 -08:00
Carol Willing
80df842b2b Merge pull request #1541 from jupyterhub/takluyver-patch-1
Clarify how to enable/disable statsd collection
2017-11-16 10:49:45 -08:00
Thomas Kluyver
f1a8a72a9f Clarify how to enable/disable statsd collection 2017-11-16 14:33:08 +00:00
Min RK
0296e16232 allow override of cookie options
via `tornado_settings['cookie_options']`

for cases where default options are incorrect or insufficient (e.g. expiry or https detection fails)
2017-11-16 13:53:27 +01:00
Min RK
f6f7081483 adjust headers for CORS
- add `authorization` to default Access-Control-Allow-Headers
- allow overriding `Access-Control-Allow-Headers` just like everything else in case default is inappropriate
- ensure case-insensitive comparison for proper header checks
2017-11-16 11:46:40 +01:00
Derek Heldt-Werle
7f7cd0a314 If spawner is pending, always route to /hub/home/:user to resolve issues with form options 2017-11-13 15:22:49 -08:00
Min RK
5ffb5763a5 setup.py: run npm with --unsafe-perm
this is the equivalent to bower's `--allow-root` that we had in bower-proper

fixes issues when installing jupyterhub from source with sudo
2017-11-13 11:09:25 +01:00
Christian Moscardi
4382037110 start all button 2017-11-10 16:57:48 -05:00
Carol Willing
963cd88440 Merge pull request #1526 from minrk/form-control
don't apply form-control unconditionally to spawn form
2017-11-08 05:40:55 -08:00
Min RK
885f99ac08 back to dev 2017-11-08 14:14:05 +01:00
Min RK
7c3919980a don't apply form-control unconditionally to spawn form
leave it to users to build their own form
2017-11-08 14:13:26 +01:00
Carol Willing
d8860d6f24 Merge pull request #1525 from minrk/thread-hangs
avoid waiting forever for threads to exit
2017-11-07 06:47:06 -08:00
Carol Willing
6b992e37e3 Merge pull request #1521 from jupyterhub/its-jupyter-now
strike mention of IPython notebook in README
2017-11-07 06:41:39 -08:00
Min RK
a3424355fa back to dev 2017-11-07 15:32:13 +01:00
Min RK
569a91296d avoid waiting forever for threads to exit
- call loop.stop via `.add_callback`
- add 30s timeout to `thread.join()` to avoid hanging forever if thread fails to exit
- assert that threads exit
2017-11-07 15:17:42 +01:00
Min RK
8b583cb445 release 0.8.1 2017-11-07 13:39:10 +01:00
Min RK
038a85af43 add removal of bower to changelog for 0.8.1 2017-11-07 13:39:10 +01:00
Min RK
9165beb41c Merge pull request #1306 from minrk/bower-lite
remove bower
2017-11-07 13:35:08 +01:00
Min RK
b285de4412 npm install with unsafe-perm on docker
npm doesn't like to run postinstall as root
2017-11-07 13:01:31 +01:00
Min RK
5826035fe9 node when css building starts 2017-11-07 12:59:57 +01:00
Min RK
b953ac295b check for built css as well in data-files lookup
avoids serving incomplete files
2017-11-07 11:40:24 +01:00
Min RK
8a95066b2e run lessc via npm 2017-11-07 11:39:53 +01:00
Min RK
00a4aef607 remove bower
use npm to fetch dependencies and a simple postinstall script to copy into components
2017-11-07 11:38:47 +01:00
Min RK
9e2663491e strike mention of IPython notebook in README
It's been long enough that we can call it Jupyter notebook, I think
2017-11-07 10:01:14 +01:00
Carol Willing
e01ce7b665 Merge pull request #1516 from minrk/0.8.1-changes
changelog for 0.8.1
2017-11-06 14:23:03 -08:00
Min RK
a57df48f28 changelog for 0.8.1 2017-11-03 11:07:08 +01:00
Min RK
5d7e008055 Merge pull request #1512 from DeepHorizons/update-service-doc
Update docs and examples for the slash at the end of the prefix
2017-11-03 10:31:46 +01:00
Min RK
ba31b3ecb7 Merge pull request #1497 from DeepHorizons/update-docs
[doc] Updated the rest docs to about change in 0.8
2017-11-01 11:49:41 +01:00
Joshua Milas
3c5eb934bf Update docs and examples for the slash at the end of the prefix 2017-10-31 14:04:37 -04:00
Joshua Milas
82e15df6e9 Added that you can also access the notebook if you are the owner 2017-10-31 10:15:02 -04:00
Yuvi Panda
e3c83c0c29 Merge pull request #1509 from minrk/stacky
copy exception before reraising
2017-10-30 17:50:37 -07:00
Min RK
94542334c4 Merge pull request #1507 from minrk/upgrade-db
add `jupyterhub --upgrade-db` to trigger upgrade on launch
2017-10-30 15:34:31 +01:00
Min RK
95494b3ace only sqlite 2017-10-30 09:58:55 +01:00
Min RK
a131cfb79e add jupyterhub --upgrade-db to trigger upgrade on launch
Upgrades the database (if needed) on start.

This is opt-in, for uses like the helm chart where explicit 'upgrade-db' steps are hard to insert.

This ought to be safe for sqlite users, where an automatic backup file is created *if an upgrade will occur*.
2017-10-27 15:35:17 +02:00
Min RK
f002c67343 add dbutil.upgrade_if_needed
so it's reusable now that we want to use it in more than one place
2017-10-27 15:35:17 +02:00
Min RK
b9caf95c72 copy exception before reraising
avoids growing traceback on each raise
2017-10-27 15:29:16 +02:00
Min RK
5356954240 Merge pull request #1493 from schon/rendering-logout
Rendering logout page when auto login is true
2017-10-27 14:42:22 +02:00
Joshua Milas
126c73002e Updated the rest docs to about change in 0.8
In 0.8, the jupyterhub api token can also be used to make requests to
hte jupyter notebook given some conditions. This commit updates that
documentation
2017-10-21 09:18:08 -04:00
Seongduk Cheon
65b4502a78 Rendering logout page when auto login is true 2017-10-19 12:14:20 +09:00
Min RK
3406161d75 Merge pull request #1460 from DeepHorizons/asyncio_event_loop
Enable the asyncio event loop to run with tornado
2017-10-13 11:18:02 +02:00
Yuvi Panda
e45f00f0f7 Merge pull request #1475 from minrk/disallow-slash
disallow '/' in usernames
2017-10-11 08:54:58 -07:00
Min RK
71f4a30562 Merge pull request #1473 from franga2000/patch-1
Change username input type to "text" to fix auto-filling
2017-10-11 16:01:45 +02:00
Min RK
20ba414b41 disallow / in usernames 2017-10-11 11:46:50 +02:00
Miha Frangez
f5250f04c5 Change username input type to "text"
<input type="username"> isn't allowed according to the spec and causes problems with autofill in Firefox.
2017-10-10 22:30:20 +02:00
Carol Willing
c2ea20a87a Merge pull request #1466 from minrk/auth_state_username
[doc] typo in auth_state structure
2017-10-04 16:57:27 -04:00
Carol Willing
b14989d4a5 Merge pull request #1465 from minrk/outerjoin
use outerjoin to join User with Spawner for admin page
2017-10-04 16:56:52 -04:00
Min RK
04578e329c typo in auth_state structure
it's 'name' not 'username'
2017-10-04 14:18:14 +02:00
Min RK
be05e438ca use outerjoin to join User with Spawner for admin page
avoids excluding users from admin page if they haven't instantiated their first Spawner yet
2017-10-04 13:58:08 +02:00
Min RK
24d9215029 back to dev 2017-10-03 21:49:23 +02:00
Min RK
8892270c24 0.8.0 2017-10-03 21:35:24 +02:00
Min RK
b928df6cba update changelog links for 0.8.0 release 2017-10-03 21:35:24 +02:00
Carol Willing
3fc74bd79e Merge pull request #1462 from minrk/proxy-docs
Document custom proxy implementations
2017-10-03 08:36:02 -07:00
Carol Willing
b34be77fec Merge pull request #1463 from minrk/auth-docs
Document auth_state
2017-10-03 08:29:45 -07:00
Joshua Milas
54dcca7ba9 Install the AsyncIOMainLoop instead of configuring it.
Installing the loop instructs the tornado loop to point to the ayncio loop and use
that. IOLoop.configure told the tornado loop to create a new ioloop when
a loop was needed, which is not what we want.
2017-10-03 08:30:49 -04:00
Min RK
d991c06098 document auth_state 2017-10-03 13:08:10 +02:00
Min RK
01a67ba156 document custom proxies 2017-10-03 12:42:52 +02:00
Min RK
8831573b6c typos in services.auth headings 2017-10-03 12:42:52 +02:00
Min RK
c5bc5411fb ignore docs/build 2017-10-03 12:42:52 +02:00
Carol Willing
a13ccd7530 Merge pull request #1461 from minrk/apache-docs
Update reverse proxy config examples
2017-10-03 02:46:27 -07:00
Min RK
e9a744e8b7 further clarify config-examples comments
per review
2017-10-03 10:19:43 +02:00
Min RK
582d43c153 add apache reverse proxy to config-examples 2017-10-02 18:18:03 +02:00
Min RK
7b5550928f mention how to generate dhparams
since we use them
2017-10-02 18:17:39 +02:00
Min RK
83920a3258 remove websocket-path-awareness from nginx config
using map, knowledge of the path is no longer necessary
2017-10-02 17:20:09 +02:00
Min RK
d1670aa443 fix mixed tabs and spaces 2017-10-02 16:19:21 +02:00
Min RK
c6f589124e Merge pull request #1458 from ryanlovett/master
Conditionally substitute $http_host for $host.
2017-09-29 16:06:56 +02:00
Carol Willing
35991e5194 Merge pull request #1455 from minrk/db-upgrade-test
Add db-upgrade test
2017-09-28 10:08:27 -07:00
Ryan Lovett
b956190393 Conditionally substitute $http_host for $host.
Necessary when using non-standard port. Closes #1457.
2017-09-28 09:40:51 -07:00
Min RK
122c989b7a specify mysql host and port explicitly
seems to be preferring MYSQL_UNIX_PORT
2017-09-28 18:20:57 +02:00
Min RK
5602575099 move db scripts to general ci directory
- remove shell test-db-upgrade test
- run mysql with docker on Travis because the version there is too old (< 5.7)
2017-09-28 16:20:15 +02:00
Min RK
4534499aad make db scripts accept one db at a time 2017-09-28 16:20:15 +02:00
Min RK
f733a91d7c avoid key length errors with old mysql + jupyterhub 0.7 2017-09-28 16:20:15 +02:00
Min RK
bf3fa30a01 load upgrade_db_url in test 2017-09-28 16:20:15 +02:00
Min RK
2625229847 note about venv 2017-09-28 16:20:15 +02:00
Min RK
2c3eb6d0d6 only count sqlite files when using sqlite 2017-09-28 15:09:17 +02:00
Min RK
5ff98fd1a5 run upgrade-tests on travis via pytest 2017-09-28 15:09:17 +02:00
Joshua Milas
056a7351a3 Enable the asyncio event loop to run with tornado
This allows packages written to use asyncio to work with tornado
2017-09-27 23:04:00 -04:00
Carol Willing
f79b71727b Merge pull request #1454 from minrk/auto-login-logout
typo rendering logout page when auto_login=True
2017-09-27 10:33:42 -07:00
Min RK
d3a3b8ca19 test db-upgrade on travis 2017-09-27 19:06:54 +02:00
Min RK
df9e002b9a separate docker-db from init-db
so we don't need docker on Travis
2017-09-27 19:05:55 +02:00
Min RK
a4a2c9d068 add tests for db upgrade with mysql, postgres 2017-09-27 18:41:08 +02:00
Min RK
c453e5ad20 mysql needs an extra step to drop _server_id 2017-09-27 18:34:54 +02:00
Min RK
617b879c2a stamp version before performing upgrade-db 2017-09-27 18:34:54 +02:00
Min RK
a0042e9302 typo rendering logout page when auto_login=True
and include it in test coverage
2017-09-27 14:29:56 +02:00
Min RK
6bbfcdfe4f 0.8.0rc2 2017-09-25 11:20:01 +02:00
Min RK
25662285af Merge pull request #1442 from DeepHorizons/add_more_spawner_statsd
[WIP] Added additional statsd collection for the spawner
2017-09-25 10:43:33 +02:00
Joshua Milas
84d12e8d72 Mock out the statsd object for testing 2017-09-22 12:57:41 -04:00
Joshua Milas
c317cbce36 Added additional statsd info for the spawner
spawner.failure coutner collects the number of failures for various reasons:
spawner.stop timer for seeing how long it takes a user server to stop
2017-09-22 12:13:15 -04:00
Min RK
d279604fac Merge pull request #1439 from minrk/oauth-state-cookie
avoid oauth state cookie collisions
2017-09-22 17:33:27 +02:00
Min RK
70fc4ef886 test concurrent oauth login state 2017-09-21 14:38:10 +02:00
Min RK
24ff91eef5 avoid oauth state cookie collisions
in case of multiple simultaneous

- state arg is strictly required now
- default cookie name in case of no collision is unchanged
- in case of collision, randomize cookie name with a suffix and store cookie_name in state
- expire state cookies after 10 minutes, not 1 day
2017-09-21 14:32:47 +02:00
Min RK
afc6789c74 Merge pull request #1441 from minrk/test-trailing-slash-wtf
debug intermittent failure on Travis
2017-09-21 14:18:08 +02:00
Min RK
819e5e222a stop server before testing trailing-slash handling
ensures `/user/name` is handled by the Hub without relying on CHP bug that was fixed in 3.0
2017-09-21 14:08:08 +02:00
Min RK
e1a4f37bbc cache pip packages on travis 2017-09-21 14:08:08 +02:00
Carol Willing
a73477feed Merge pull request #1435 from Analect/named-server-docs
Adding a short description ref starting/stopping named-servers via API
2017-09-20 21:29:11 -07:00
analect
89722ee2f3 Added in necessity to set c.JupyterHub.allow_named_servers = True 2017-09-20 10:27:28 +01:00
analect
ca4fce7ffb Add Analect to contributor list 2017-09-19 16:18:09 +01:00
analect
018b2daace Fixing typo. 2017-09-19 16:17:54 +01:00
analect
fd01165cf6 Adding a short description ref starting/stopping named-servers via API 2017-09-19 14:33:20 +01:00
256 changed files with 19719 additions and 5708 deletions

View File

@@ -1,3 +0,0 @@
{
"directory": "share/jupyter/hub/static/components"
}

21
.circleci/config.yml Normal file
View File

@@ -0,0 +1,21 @@
# Python CircleCI 2.0 configuration file
# Updating CircleCI configuration from v1 to v2
# Check https://circleci.com/docs/2.0/language-python/ for more details
#
version: 2
jobs:
build:
machine: true
steps:
- checkout
- run:
name: build images
command: |
docker build -t jupyterhub/jupyterhub .
docker build -t jupyterhub/jupyterhub-onbuild onbuild
docker build -t jupyterhub/jupyterhub:alpine -f dockerfiles/Dockerfile.alpine .
docker build -t jupyterhub/singleuser singleuser
- run:
name: smoke test jupyterhub
command: |
docker run --rm -it jupyterhub/jupyterhub jupyterhub --help

View File

@@ -1,4 +1,5 @@
[run]
parallel = True
branch = False
omit =
jupyterhub/tests/*

View File

@@ -10,13 +10,12 @@
# E402: module level import not at top of file
# I100: Import statements are in the wrong order
# I101: Imported names are in the wrong order. Should be
ignore = E, C, W, F401, F403, F811, F841, E402, I100, I101
ignore = E, C, W, F401, F403, F811, F841, E402, I100, I101, D400
builtins = c, get_config
exclude =
.cache,
.github,
docs,
examples,
jupyterhub/alembic*,
onbuild,
scripts,

37
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,37 @@
---
name: Bug report
about: Create a report to help us improve
---
Hi! Thanks for using JupyterHub.
If you are reporting an issue with JupyterHub, please use the [GitHub issue](https://github.com/jupyterhub/jupyterhub/issues) search feature to check if your issue has been asked already. If it has, please add your comments to the existing issue.
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.
- Running `jupyter troubleshoot` from the command line, if possible, and posting
its output would also be helpful.
- Running in `--debug` mode can also be helpful for troubleshooting.

View File

@@ -0,0 +1,7 @@
---
name: Installation and configuration issues
about: Installation and configuration assistance
---
If you are having issues with installation or configuration, you may ask for help on the JupyterHub gitter channel or file an issue here.

0
.github/PULL_REQUEST_TEMPLATE/.keep vendored Normal file
View File

View File

@@ -1,29 +0,0 @@
Hi! Thanks for using JupyterHub.
If you are reporting an issue with JupyterHub:
- Please use the [GitHub issue](https://github.com/jupyterhub/jupyterhub/issues)
search feature to check if your issue has been asked already. If it has,
please add your comments to the existing issue.
- Where applicable, please fill out the details below to help us troubleshoot
the issue that you are facing. Please be as thorough as you are able to
provide details on the issue.
**How to reproduce the issue**
**What you expected to happen**
**What actually happens**
**Share what version of JupyterHub you are using**
Running `jupyter troubleshoot` from the command line, if possible, and posting
its output would also be helpful.
```
Insert jupyter troubleshoot output here
```

13
.gitignore vendored
View File

@@ -6,6 +6,7 @@ node_modules
/build
dist
docs/_build
docs/build
docs/source/_static/rest-api
.ipynb_checkpoints
# ignore config file at the top-level of the repo
@@ -13,11 +14,15 @@ docs/source/_static/rest-api
/jupyterhub_config.py
jupyterhub_cookie_secret
jupyterhub.sqlite
share/jupyter/hub/static/components
share/jupyter/hub/static/css/style.min.css
share/jupyter/hub/static/css/style.min.css.map
package-lock.json
share/jupyterhub/static/components
share/jupyterhub/static/css/style.min.css
share/jupyterhub/static/css/style.min.css.map
*.egg-info
MANIFEST
.coverage
.coverage.*
htmlcov
.idea/
.pytest_cache
pip-wheel-metadata

20
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,20 @@
repos:
- repo: https://github.com/asottile/reorder_python_imports
rev: v1.3.5
hooks:
- id: reorder-python-imports
language_version: python3.6
- repo: https://github.com/ambv/black
rev: 18.9b0
hooks:
- id: black
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.1.0
hooks:
- id: end-of-file-fixer
- id: check-json
- id: check-yaml
- id: check-case-conflict
- id: check-executables-have-shebangs
- id: requirements-txt-fixer
- id: flake8

View File

@@ -1,49 +1,100 @@
language: python
sudo: false
cache:
- pip
python:
- nightly
- 3.6
- 3.5
- 3.4
- nightly
env:
global:
- ASYNC_TEST_TIMEOUT=15
- MYSQL_HOST=127.0.0.1
- MYSQL_TCP_PORT=13306
services:
- mysql
- postgresql
- postgres
- docker
# installing dependencies
before_install:
- set -e
- nvm install 6; nvm use 6
- npm install
- npm install -g configurable-http-proxy
- |
# setup database
if [[ $JUPYTERHUB_TEST_DB_URL == mysql* ]]; then
mysql -e 'CREATE DATABASE jupyterhub CHARACTER SET utf8 COLLATE utf8_general_ci;'
pip install 'mysql-connector<2.2'
unset MYSQL_UNIX_PORT
DB=mysql bash ci/docker-db.sh
DB=mysql bash ci/init-db.sh
# FIXME: mysql-connector-python 8.0.16 incorrectly decodes bytes to str
# ref: https://bugs.mysql.com/bug.php?id=94944
pip install 'mysql-connector-python==8.0.15'
elif [[ $JUPYTERHUB_TEST_DB_URL == postgresql* ]]; then
psql -c 'create database jupyterhub;' -U postgres
pip install psycopg2
psql -c "CREATE USER $PGUSER WITH PASSWORD '$PGPASSWORD';" -U postgres
DB=postgres bash ci/init-db.sh
pip install psycopg2-binary
fi
install:
- pip install -U pip
- pip install --pre -r dev-requirements.txt .
- pip install --upgrade pip
- pip install --upgrade --pre -r dev-requirements.txt .
- pip freeze
# running tests
script:
- pytest -v --maxfail=2 --cov=jupyterhub jupyterhub/tests
- |
# run tests
if [[ -z "$TEST" ]]; then
pytest -v --maxfail=2 --cov=jupyterhub jupyterhub/tests
fi
- |
# run autoformat
if [[ "$TEST" == "lint" ]]; then
pre-commit run --all-files
fi
- |
# build docs
if [[ "$TEST" == "docs" ]]; then
pushd docs
pip install --upgrade -r requirements.txt
pip install --upgrade alabaster_jupyterhub
make html
popd
fi
after_success:
- codecov
after_failure:
- |
# point to auto-lint-fix
if [[ "$TEST" == "lint" ]]; then
echo "You can install pre-commit hooks to automatically run formatting"
echo "on each commit with:"
echo " pre-commit install"
echo "or you can run by hand on staged files with"
echo " pre-commit run"
echo "or after-the-fact on already committed files with"
echo " pre-commit run --all-files"
fi
matrix:
fast_finish: true
include:
- python: 3.6
env: TEST=lint
- python: 3.6
env: TEST=docs
- python: 3.6
env: JUPYTERHUB_TEST_SUBDOMAIN_HOST=http://localhost.jovyan.org:8000
- python: 3.6
env: JUPYTERHUB_TEST_DB_URL=mysql+mysqlconnector://root@127.0.0.1/jupyterhub
env:
- JUPYTERHUB_TEST_DB_URL=mysql+mysqlconnector://root@127.0.0.1:$MYSQL_TCP_PORT/jupyterhub
- python: 3.6
env: JUPYTERHUB_TEST_DB_URL=postgresql://postgres@127.0.0.1/jupyterhub
env:
- PGUSER=jupyterhub
- PGPASSWORD=hub[test/:?
# password in url is url-encoded (urllib.parse.quote($PGPASSWORD, safe=''))
- JUPYTERHUB_TEST_DB_URL=postgresql://jupyterhub:hub%5Btest%2F%3A%3F@127.0.0.1/jupyterhub
- python: 3.7
dist: xenial
allow_failures:
- python: nightly

1
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1 @@
Please refer to [Project Jupyter's Code of Conduct](https://github.com/jupyter/governance/blob/master/conduct/code_of_conduct.md).

View File

@@ -1,3 +1,102 @@
# Contributing
# Contributing to JupyterHub
Welcome! As a [Jupyter](https://jupyter.org) project, we follow the [Jupyter contributor guide](https://jupyter.readthedocs.io/en/latest/contributor/content-contributor.html).
Welcome! As a [Jupyter](https://jupyter.org) project,
you can follow the [Jupyter contributor guide](https://jupyter.readthedocs.io/en/latest/contributor/content-contributor.html).
Make sure to also follow [Project Jupyter's Code of Conduct](https://github.com/jupyter/governance/blob/master/conduct/code_of_conduct.md)
for a friendly and welcoming collaborative environment.
## Setting up a development environment
JupyterHub requires Python >= 3.5 and nodejs.
As a Python project, a development install of JupyterHub follows standard practices for the basics (steps 1-2).
1. clone the repo
```bash
git clone https://github.com/jupyterhub/jupyterhub
```
2. do a development install with pip
```bash
cd jupyterhub
python3 -m pip install --editable .
```
3. install the development requirements,
which include things like testing tools
```bash
python3 -m pip install -r dev-requirements.txt
```
4. install configurable-http-proxy with npm:
```bash
npm install -g configurable-http-proxy
```
5. set up pre-commit hooks for automatic code formatting, etc.
```bash
pre-commit install
```
You can also invoke the pre-commit hook manually at any time with
```bash
pre-commit run
```
## Contributing
JupyterHub has adopted automatic code formatting so you shouldn't
need to worry too much about your code style.
As long as your code is valid,
the pre-commit hook should take care of how it should look.
You can invoke the pre-commit hook by hand at any time with:
```bash
pre-commit run
```
which should run any autoformatting on your code
and tell you about any errors it couldn't fix automatically.
You may also install [black integration](https://github.com/ambv/black#editor-integration)
into your text editor to format code automatically.
If you have already committed files before setting up the pre-commit
hook with `pre-commit install`, you can fix everything up using
`pre-commit run --all-files`. You need to make the fixing commit
yourself after that.
## Testing
It's a good idea to write tests to exercise any new features,
or that trigger any bugs that you have fixed to catch regressions.
You can run the tests with:
```bash
pytest -v
```
in the repo directory. If you want to just run certain tests,
check out the [pytest docs](https://pytest.readthedocs.io/en/latest/usage.html)
for how pytest can be called.
For instance, to test only spawner-related things in the REST API:
```bash
pytest -v -k spawn jupyterhub/tests/test_api.py
```
The tests live in `jupyterhub/tests` and are organized roughly into:
1. `test_api.py` tests the REST API
2. `test_pages.py` tests loading the HTML pages
and other collections of tests for different components.
When writing a new test, there should usually be a test of
similar functionality already written and related tests should
be added nearby.
When in doubt, feel free to ask.
TODO: describe some details about fixtures, etc.

View File

@@ -21,29 +21,25 @@
# your jupyterhub_config.py will be added automatically
# from your docker directory.
FROM debian:jessie
MAINTAINER Jupyter Project <jupyter@googlegroups.com>
FROM ubuntu:18.04
LABEL maintainer="Jupyter Project <jupyter@googlegroups.com>"
# install nodejs, utf8 locale, set CDN because default httpredir is unreliable
ENV DEBIAN_FRONTEND noninteractive
RUN REPO=http://cdn-fastly.deb.debian.org && \
echo "deb $REPO/debian jessie main\ndeb $REPO/debian-security jessie/updates main" > /etc/apt/sources.list && \
apt-get -y update && \
RUN apt-get -y update && \
apt-get -y upgrade && \
apt-get -y install wget locales git bzip2 &&\
/usr/sbin/update-locale LANG=C.UTF-8 && \
locale-gen C.UTF-8 && \
apt-get remove -y locales && \
apt-get -y install wget git bzip2 && \
apt-get purge && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
ENV LANG C.UTF-8
# install Python + NodeJS with conda
RUN wget -q https://repo.continuum.io/miniconda/Miniconda3-4.2.12-Linux-x86_64.sh -O /tmp/miniconda.sh && \
echo 'd0c7c71cc5659e54ab51f2005a8d96f3 */tmp/miniconda.sh' | md5sum -c - && \
RUN wget -q https://repo.continuum.io/miniconda/Miniconda3-4.5.11-Linux-x86_64.sh -O /tmp/miniconda.sh && \
echo 'e1045ee415162f944b6aebfe560b8fee */tmp/miniconda.sh' | md5sum -c - && \
bash /tmp/miniconda.sh -f -b -p /opt/conda && \
/opt/conda/bin/conda install --yes -c conda-forge \
python=3.5 sqlalchemy tornado jinja2 traitlets requests pip pycurl \
python=3.6 sqlalchemy tornado jinja2 traitlets requests pip pycurl \
nodejs configurable-http-proxy && \
/opt/conda/bin/pip install --upgrade pip && \
rm /tmp/miniconda.sh
@@ -52,7 +48,7 @@ ENV PATH=/opt/conda/bin:$PATH
ADD . /src/jupyterhub
WORKDIR /src/jupyterhub
RUN python setup.py js && pip install . && \
RUN pip install . && \
rm -rf $PWD ~/.cache ~/.npm
RUN mkdir -p /srv/jupyterhub/

View File

@@ -1,8 +1,9 @@
include README.md
include COPYING.md
include setupegg.py
include bower.json
include bower-lite
include package.json
include package-lock.json
include *requirements.txt
include Dockerfile
@@ -11,20 +12,22 @@ graft jupyterhub
graft scripts
graft share
graft singleuser
graft ci
# Documentation
graft docs
prune docs/node_modules
# prune some large unused files from components
prune share/jupyter/hub/static/components/bootstrap/css
exclude share/jupyter/hub/static/components/components/fonts/*.svg
exclude share/jupyter/hub/static/components/bootstrap/less/*.js
exclude share/jupyter/hub/static/components/font-awesome/css
exclude share/jupyter/hub/static/components/font-awesome/fonts/*.svg
exclude share/jupyter/hub/static/components/jquery/*migrate*.js
prune share/jupyter/hub/static/components/moment/lang
prune share/jupyter/hub/static/components/moment/min
prune share/jupyterhub/static/components/bootstrap/dist/css
exclude share/jupyterhub/static/components/bootstrap/dist/fonts/*.svg
prune share/jupyterhub/static/components/font-awesome/css
prune share/jupyterhub/static/components/font-awesome/scss
exclude share/jupyterhub/static/components/font-awesome/fonts/*.svg
prune share/jupyterhub/static/components/jquery/external
prune share/jupyterhub/static/components/jquery/src
prune share/jupyterhub/static/components/moment/lang
prune share/jupyterhub/static/components/moment/min
# Patterns to exclude from any directory
global-exclude *~

0
PULL_REQUEST_TEMPLATE.md Normal file
View File

107
README.md
View File

@@ -11,16 +11,17 @@
[![PyPI](https://img.shields.io/pypi/v/jupyterhub.svg)](https://pypi.python.org/pypi/jupyterhub)
[![Documentation Status](https://readthedocs.org/projects/jupyterhub/badge/?version=latest)](http://jupyterhub.readthedocs.org/en/latest/?badge=latest)
[![Documentation Status](http://readthedocs.org/projects/jupyterhub/badge/?version=0.7.2)](http://jupyterhub.readthedocs.io/en/0.7.2/?badge=0.7.2)
[![Documentation Status](https://readthedocs.org/projects/jupyterhub/badge/?version=latest)](https://jupyterhub.readthedocs.org/en/latest/?badge=latest)
[![Build Status](https://travis-ci.org/jupyterhub/jupyterhub.svg?branch=master)](https://travis-ci.org/jupyterhub/jupyterhub)
[![Circle CI](https://circleci.com/gh/jupyterhub/jupyterhub.svg?style=shield&circle-token=b5b65862eb2617b9a8d39e79340b0a6b816da8cc)](https://circleci.com/gh/jupyterhub/jupyterhub)
[![codecov.io](https://codecov.io/github/jupyterhub/jupyterhub/coverage.svg?branch=master)](https://codecov.io/github/jupyterhub/jupyterhub?branch=master)
[![Google Group](https://img.shields.io/badge/google-group-blue.svg)](https://groups.google.com/forum/#!forum/jupyter)
[![GitHub](https://img.shields.io/badge/issue_tracking-github-blue.svg)](https://github.com/jupyterhub/jupyterhub/issues)
[![Discourse](https://img.shields.io/badge/help_forum-discourse-blue.svg)](https://discourse.jupyter.org/c/jupyterhub)
[![Gitter](https://img.shields.io/badge/social_chat-gitter-blue.svg)](https://gitter.im/jupyterhub/jupyterhub)
With [JupyterHub](https://jupyterhub.readthedocs.io) you can create a
**multi-user Hub** which spawns, manages, and proxies multiple instances of the
single-user [Jupyter notebook (IPython notebook)](https://jupyter-notebook.readthedocs.io)
single-user [Jupyter notebook](https://jupyter-notebook.readthedocs.io)
server.
[Project Jupyter](https://jupyter.org) created JupyterHub to support many
@@ -34,11 +35,11 @@ Three main actors make up JupyterHub:
- multi-user **Hub** (tornado process)
- configurable http **proxy** (node-http-proxy)
- multiple **single-user Jupyter notebook servers** (Python/IPython/tornado)
- multiple **single-user Jupyter notebook servers** (Python/Jupyter/tornado)
Basic principles for operation are:
- Hub spawns a proxy.
- Hub launches a proxy.
- Proxy forwards all requests to Hub by default.
- Hub handles login, and spawns single-user servers on demand.
- Hub configures proxy to forward url prefixes to the single-user notebook
@@ -50,37 +51,62 @@ for administration of the Hub and its users.
## Installation
### Check prerequisites
A Linux/Unix based system with the following:
- A Linux/Unix based system
- [Python](https://www.python.org/downloads/) 3.5 or greater
- [nodejs/npm](https://www.npmjs.com/)
- [Python](https://www.python.org/downloads/) 3.4 or greater
- [nodejs/npm](https://www.npmjs.com/) Install a recent version of
[nodejs/npm](https://docs.npmjs.com/getting-started/installing-node)
For example, install it on Linux (Debian/Ubuntu) using:
* If you are using **`conda`**, the nodejs and npm dependencies will be installed for
you by conda.
sudo apt-get install npm nodejs-legacy
* If you are using **`pip`**, install a recent version of
[nodejs/npm](https://docs.npmjs.com/getting-started/installing-node).
For example, install it on Linux (Debian/Ubuntu) using:
The `nodejs-legacy` package installs the `node` executable and is currently
required for npm to work on Debian/Ubuntu.
```
sudo apt-get install npm nodejs-legacy
```
The `nodejs-legacy` package installs the `node` executable and is currently
required for npm to work on Debian/Ubuntu.
- TLS certificate and key for HTTPS communication
- Domain name
### Install packages
#### Using `conda`
To install JupyterHub along with its dependencies including nodejs/npm:
```bash
conda install -c conda-forge jupyterhub
```
If you plan to run notebook servers locally, install the Jupyter notebook
or JupyterLab:
```bash
conda install notebook
conda install jupyterlab
```
#### Using `pip`
JupyterHub can be installed with `pip`, and the proxy with `npm`:
```bash
npm install -g configurable-http-proxy
pip3 install jupyterhub
python3 -m pip install jupyterhub
```
If you plan to run notebook servers locally, you will need to install the
[Jupyter notebook](https://jupyter.readthedocs.io/en/latest/install.html)
package:
pip3 install --upgrade notebook
python3 -m pip install --upgrade notebook
### Run the Hub server
@@ -99,7 +125,7 @@ more configuration of the system.
## Configuration
The [Getting Started](http://jupyterhub.readthedocs.io/en/latest/getting-started/index.html) section of the
The [Getting Started](https://jupyterhub.readthedocs.io/en/latest/getting-started/index.html) section of the
documentation explains the common steps in setting up JupyterHub.
The [**JupyterHub tutorial**](https://github.com/jupyterhub/jupyterhub-tutorial)
@@ -124,7 +150,7 @@ To start the Hub on a specific url and port ``10.0.1.2:443`` with **https**:
| PAMAuthenticator | Default, built-in authenticator |
| [OAuthenticator](https://github.com/jupyterhub/oauthenticator) | OAuth + JupyterHub Authenticator = OAuthenticator |
| [ldapauthenticator](https://github.com/jupyterhub/ldapauthenticator) | Simple LDAP Authenticator Plugin for JupyterHub |
| [kdcAuthenticator](https://github.com/bloomberg/jupyterhub-kdcauthenticator)| Kerberos Authenticator Plugin for JupyterHub |
| [kerberosauthenticator](https://github.com/jcrist/kerberosauthenticator) | Kerberos Authenticator Plugin for JupyterHub |
### Spawners
@@ -136,6 +162,7 @@ To start the Hub on a specific url and port ``10.0.1.2:443`` with **https**:
| [sudospawner](https://github.com/jupyterhub/sudospawner) | Spawn single-user servers without being root |
| [systemdspawner](https://github.com/jupyterhub/systemdspawner) | Spawn single-user notebook servers using systemd |
| [batchspawner](https://github.com/jupyterhub/batchspawner) | Designed for clusters using batch scheduling software |
| [yarnspawner](https://github.com/jcrist/yarnspawner) | Spawn single-user notebook servers distributed on a Hadoop cluster |
| [wrapspawner](https://github.com/jupyterhub/wrapspawner) | WrapSpawner and ProfilesSpawner enabling runtime configuration of spawners |
## Docker
@@ -151,7 +178,7 @@ not, Jupyter Notebook version 4 or greater must be installed.
The JupyterHub docker image can be started with the following command:
docker run -d --name jupyterhub jupyterhub/jupyterhub jupyterhub
docker run -p 8000:8000 -d --name jupyterhub jupyterhub/jupyterhub jupyterhub
This command will create a container named `jupyterhub` that you can
**stop and resume** with `docker stop/start`.
@@ -163,7 +190,7 @@ If you want to run docker on a computer that has a public IP then you should
(as in MUST) **secure it with ssl** by adding ssl options to your docker
configuration or by using a ssl enabled proxy.
[Mounting volumes](https://docs.docker.com/engine/userguide/containers/dockervolumes/) will
[Mounting volumes](https://docs.docker.com/engine/admin/volumes/volumes/) will
allow you to **store data outside the docker image (host system) so it will be persistent**, even when you start
a new image.
@@ -175,38 +202,12 @@ These accounts will be used for authentication in JupyterHub's default configura
If you would like to contribute to the project, please read our
[contributor documentation](http://jupyter.readthedocs.io/en/latest/contributor/content-contributor.html)
and the [`CONTRIBUTING.md`](CONTRIBUTING.md).
and the [`CONTRIBUTING.md`](CONTRIBUTING.md). The `CONTRIBUTING.md` file
explains how to set up a development installation, how to run the test suite,
and how to contribute to documentation.
For a **development install**, clone the [repository](https://github.com/jupyterhub/jupyterhub)
and then install from source:
```bash
git clone https://github.com/jupyterhub/jupyterhub
cd jupyterhub
pip3 install -r dev-requirements.txt -e .
```
If the `pip3 install` command fails and complains about `lessc` being
unavailable, you may need to explicitly install some additional JavaScript
dependencies:
npm install
This will fetch client-side JavaScript dependencies necessary to compile CSS.
You may also need to manually update JavaScript and CSS after some development
updates, with:
```bash
python3 setup.py js # fetch updated client-side js
python3 setup.py css # recompile CSS from LESS sources
```
We use [pytest](http://doc.pytest.org/en/latest/) for **running tests**:
```bash
pytest jupyterhub/tests
```
For a high-level view of the vision and next directions of the project, see the
[JupyterHub community roadmap](docs/source/contributing/roadmap.md).
### A note about platform support
@@ -237,11 +238,13 @@ our JupyterHub [Gitter](https://gitter.im/jupyterhub/jupyterhub) channel.
- [Reporting Issues](https://github.com/jupyterhub/jupyterhub/issues)
- [JupyterHub tutorial](https://github.com/jupyterhub/jupyterhub-tutorial)
- [Documentation for JupyterHub](http://jupyterhub.readthedocs.io/en/latest/) | [PDF (latest)](https://media.readthedocs.org/pdf/jupyterhub/latest/jupyterhub.pdf) | [PDF (stable)](https://media.readthedocs.org/pdf/jupyterhub/stable/jupyterhub.pdf)
- [Documentation for JupyterHub](https://jupyterhub.readthedocs.io/en/latest/) | [PDF (latest)](https://media.readthedocs.org/pdf/jupyterhub/latest/jupyterhub.pdf) | [PDF (stable)](https://media.readthedocs.org/pdf/jupyterhub/stable/jupyterhub.pdf)
- [Documentation for JupyterHub's REST API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/jupyterhub/master/docs/rest-api.yml#/default)
- [Documentation for Project Jupyter](http://jupyter.readthedocs.io/en/latest/index.html) | [PDF](https://media.readthedocs.org/pdf/jupyter/latest/jupyter.pdf)
- [Project Jupyter website](https://jupyter.org)
JupyterHub follows the Jupyter [Community Guides](https://jupyter.readthedocs.io/en/latest/community/content-community.html).
---
**[Technical Overview](#technical-overview)** |

33
bower-lite Executable file
View File

@@ -0,0 +1,33 @@
#!/usr/bin/env python
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
"""
bower-lite
Since Bower's on its way out,
stage frontend dependencies from node_modules into components
"""
import json
import os
import shutil
from os.path import join
HERE = os.path.abspath(os.path.dirname(__file__))
components = join(HERE, "share", "jupyterhub", "static", "components")
node_modules = join(HERE, "node_modules")
if os.path.exists(components):
shutil.rmtree(components)
os.mkdir(components)
with open(join(HERE, 'package.json')) as f:
package_json = json.load(f)
dependencies = package_json['dependencies']
for dep in dependencies:
src = join(node_modules, dep)
dest = join(components, dep)
print("%s -> %s" % (src, dest))
shutil.copytree(src, dest)

View File

@@ -1,11 +0,0 @@
{
"name": "jupyterhub-deps",
"version": "0.0.0",
"dependencies": {
"bootstrap": "components/bootstrap#~3.3",
"font-awesome": "components/font-awesome#~4.7",
"jquery": "components/jquery#~3.2",
"moment": "~2.18",
"requirejs": "~2.3"
}
}

59
ci/docker-db.sh Executable file
View File

@@ -0,0 +1,59 @@
#!/usr/bin/env bash
# source this file to setup postgres and mysql
# for local testing (as similar as possible to docker)
set -eu
export MYSQL_HOST=127.0.0.1
export MYSQL_TCP_PORT=${MYSQL_TCP_PORT:-13306}
export PGHOST=127.0.0.1
NAME="hub-test-$DB"
DOCKER_RUN="docker run -d --name $NAME"
docker rm -f "$NAME" 2>/dev/null || true
case "$DB" in
"mysql")
RUN_ARGS="-e MYSQL_ALLOW_EMPTY_PASSWORD=1 -p $MYSQL_TCP_PORT:3306 mysql:5.7"
CHECK="mysql --host $MYSQL_HOST --port $MYSQL_TCP_PORT --user root -e \q"
;;
"postgres")
RUN_ARGS="-p 5432:5432 postgres:9.5"
CHECK="psql --user postgres -c \q"
;;
*)
echo '$DB must be mysql or postgres'
exit 1
esac
$DOCKER_RUN $RUN_ARGS
echo -n "waiting for $DB "
for i in {1..60}; do
if $CHECK; then
echo 'done'
break
else
echo -n '.'
sleep 1
fi
done
$CHECK
case "$DB" in
"mysql")
;;
"postgres")
# create the user
psql --user postgres -c "CREATE USER $PGUSER WITH PASSWORD '$PGPASSWORD';"
;;
*)
esac
echo -e "
Set these environment variables:
export MYSQL_HOST=127.0.0.1
export MYSQL_TCP_PORT=$MYSQL_TCP_PORT
export PGHOST=127.0.0.1
"

27
ci/init-db.sh Executable file
View File

@@ -0,0 +1,27 @@
#!/usr/bin/env bash
# initialize jupyterhub databases for testing
set -eu
MYSQL="mysql --user root --host $MYSQL_HOST --port $MYSQL_TCP_PORT -e "
PSQL="psql --user postgres -c "
case "$DB" in
"mysql")
EXTRA_CREATE='CHARACTER SET utf8 COLLATE utf8_general_ci'
SQL="$MYSQL"
;;
"postgres")
SQL="$PSQL"
;;
*)
echo '$DB must be mysql or postgres'
exit 1
esac
set -x
for SUFFIX in '' _upgrade_072 _upgrade_081 _upgrade_094; do
$SQL "DROP DATABASE jupyterhub${SUFFIX};" 2>/dev/null || true
$SQL "CREATE DATABASE jupyterhub${SUFFIX} ${EXTRA_CREATE:-};"
done

View File

@@ -1,24 +0,0 @@
machine:
services:
- docker
dependencies:
override:
- ls
test:
override:
- docker build -t jupyterhub/jupyterhub .
- docker build -t jupyterhub/jupyterhub-onbuild:${CIRCLE_TAG:-latest} onbuild
deployment:
hub:
branch: master
commands:
- docker login -u $DOCKER_USER -p $DOCKER_PASS -e unused@example.com
- docker push jupyterhub/jupyterhub-onbuild
release:
tag: /.*/
commands:
- docker login -u $DOCKER_USER -p $DOCKER_PASS -e unused@example.com
- docker push jupyterhub/jupyterhub-onbuild:$CIRCLE_TAG

View File

@@ -1,9 +1,17 @@
-r requirements.txt
mock
# temporary pin of attrs for jsonschema 0.3.0a1
# seems to be a pip bug
attrs>=17.4.0
beautifulsoup4
codecov
coverage
cryptography
pytest-cov
pytest-tornado
pytest>=2.8
html5lib # needed for beautifulsoup
mock
notebook
pre-commit
pytest-asyncio
pytest-cov
pytest>=3.3
requests-mock
virtualenv

View File

@@ -0,0 +1,9 @@
FROM python:3.6.3-alpine3.6
ARG JUPYTERHUB_VERSION=0.8.1
RUN pip3 install --no-cache jupyterhub==${JUPYTERHUB_VERSION}
ENV LANG=en_US.UTF-8
USER nobody
CMD ["jupyterhub"]

20
dockerfiles/README.md Normal file
View File

@@ -0,0 +1,20 @@
## What is Dockerfile.alpine
Dockerfile.alpine contains base image for jupyterhub. It does not work independently, but only as part of a full jupyterhub cluster
## How to use it?
1. A running configurable-http-proxy, whose API is accessible.
2. A jupyterhub_config file.
3. Authentication and other libraries required by the specific jupyterhub_config file.
## Steps to test it outside a cluster
* start configurable-http-proxy in another container
* specify CONFIGPROXY_AUTH_TOKEN env in both containers
* put both containers on the same network (e.g. docker create network jupyterhub; docker run ... --net jupyterhub)
* tell jupyterhub where CHP is (e.g. c.ConfigurableHTTPProxy.api_url = 'http://chp:8001')
* tell jupyterhub not to start the proxy itself (c.ConfigurableHTTPProxy.should_start = False)
* Use dummy authenticator for ease of testing. Update following in jupyterhub_config file
- c.JupyterHub.authenticator_class = 'dummyauthenticator.DummyAuthenticator'
- c.DummyAuthenticator.password = "your strong password"

View File

@@ -2,7 +2,7 @@
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXOPTS = "-W"
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = build

View File

@@ -1,19 +1,25 @@
# ReadTheDocs uses the `environment.yaml` so make sure to update that as well
# if you change the dependencies of JupyterHub in the various `requirements.txt`
name: jhub_docs
channels:
- conda-forge
dependencies:
- nodejs
- python=3.5
- python=3.6
- alembic
- jinja2
- pamela
- requests
- sqlalchemy>=1
- tornado>=4.1
- tornado>=5.0
- traitlets>=4.1
- sphinx>=1.4, !=1.5.4
- sphinx_rtd_theme
- sphinx>=1.7
- pip:
- jupyter_alabaster_theme
- python-oauth2
- recommonmark==0.4.0
- entrypoints
- oauthlib>=2.0
- recommonmark==0.5.0
- async_generator
- prometheus_client
- attrs>=17.4.0
- sphinx-copybutton
- alabaster_jupyterhub

View File

@@ -1,3 +1,7 @@
# ReadTheDocs uses the `environment.yaml` so make sure to update that as well
# if you change this file
-r ../requirements.txt
sphinx>=1.4
recommonmark==0.4.0
alabaster_jupyterhub
recommonmark==0.5.0
sphinx-copybutton
sphinx>=1.7

View File

@@ -3,7 +3,7 @@ swagger: '2.0'
info:
title: JupyterHub
description: The REST API for JupyterHub
version: 0.8.0dev
version: 0.9.0dev
license:
name: BSD-3-Clause
schemes:
@@ -89,7 +89,7 @@ paths:
post:
summary: Create multiple users
parameters:
- name: data
- name: body
in: body
required: true
schema:
@@ -147,7 +147,7 @@ paths:
in: path
required: true
type: string
- name: data
- name: body
in: body
required: true
description: Updated user info. At least one key to be updated (name or admin) is required.
@@ -176,6 +176,60 @@ paths:
responses:
'204':
description: The user has been deleted
/users/{name}/activity:
post:
summary:
Notify Hub of activity for a given user.
description:
Notify the Hub of activity by the user,
e.g. accessing a service or (more likely)
actively using a server.
parameters:
- name: name
description: username
in: path
required: true
type: string
- body:
in: body
schema:
type: object
properties:
last_activity:
type: string
format: date-time
description: |
Timestamp of last-seen activity for this user.
Only needed if this is not activity associated
with using a given server.
required: false
servers:
description: |
Register activity for specific servers by name.
The keys of this dict are the names of servers.
The default server has an empty name ('').
required: false
type: object
properties:
'<server name>':
description: |
Activity for a single server.
type: object
properties:
last_activity:
required: true
type: string
format: date-time
description: |
Timestamp of last-seen activity on this server.
example:
last_activity: '2019-02-06T12:54:14Z'
servers:
'':
last_activity: '2019-02-06T12:54:14Z'
gpu:
last_activity: '2019-02-06T12:54:14Z'
/users/{name}/server:
post:
summary: Start a user's single-user notebook server
@@ -185,6 +239,15 @@ paths:
in: path
required: true
type: string
- options:
description: |
Spawn options can be passed as a JSON body
when spawning via the API instead of spawn form.
The structure of the options
will depend on the Spawner's configuration.
in: body
required: false
type: object
responses:
'201':
description: The user's notebook server has started
@@ -217,6 +280,15 @@ paths:
in: path
required: true
type: string
- options:
description: |
Spawn options can be passed as a JSON body
when spawning via the API instead of spawn form.
The structure of the options
will depend on the Spawner's configuration.
in: body
required: false
type: object
responses:
'201':
description: The user's notebook named-server has started
@@ -235,23 +307,59 @@ paths:
in: path
required: true
type: string
- name: remove
description: |
Whether to fully remove the server, rather than just stop it.
Removing a server deletes things like the state of the stopped server.
in: body
required: false
type: boolean
responses:
'204':
description: The user's notebook named-server has stopped
'202':
description: The user's notebook named-server has not yet stopped as it is taking a while to stop
/users/{name}/admin-access:
post:
summary: Grant admin access to this user's notebook server
parameters:
- name: name
description: username
in: path
required: true
type: string
/users/{name}/tokens:
get:
summary: List tokens for the user
responses:
'200':
description: Sets a cookie granting the requesting administrator access to the user's notebook server
description: The list of tokens
schema:
type: array
items:
$ref: '#/definitions/Token'
post:
summary: Create a new token for the user
parameters:
- name: expires_in
type: number
required: false
in: body
description: lifetime (in seconds) after which the requested token will expire.
- name: note
type: string
required: false
in: body
description: A note attached to the token for future bookkeeping
responses:
'201':
description: The newly created token
schema:
$ref: '#/definitions/Token'
/users/{name}/tokens/{token_id}:
get:
summary: Get the model for a token by id
responses:
'200':
description: The info for the new token
schema:
$ref: '#/definitions/Token'
delete:
summary: Delete (revoke) a token by id
responses:
'204':
description: The token has been deleted
/user:
summary: Return authenticated user's model
description:
@@ -316,7 +424,7 @@ paths:
in: path
required: true
type: string
- name: data
- name: body
in: body
required: true
description: The users to add to the group
@@ -341,7 +449,7 @@ paths:
in: path
required: true
type: string
- name: data
- name: body
in: body
required: true
description: The users to remove from the group
@@ -399,7 +507,7 @@ paths:
summary: Notify the Hub about a new proxy
description: Notifies the Hub of a new proxy to use.
parameters:
- name: data
- name: body
in: body
required: true
description: Any values that have changed for the new proxy. All keys are optional.
@@ -588,12 +696,55 @@ definitions:
description: The user's notebook server's base URL, if running; null if not.
pending:
type: string
enum: ["spawn", "stop"]
enum: ["spawn", "stop", null]
description: The currently pending action, if any
last_activity:
type: string
format: date-time
description: Timestamp of last-seen activity from the user
servers:
type: object
description: The active servers for this user.
items:
schema:
$ref: '#/definitions/Server'
Server:
type: object
properties:
name:
type: string
description: The server's name. The user's default server has an empty name ('')
ready:
type: boolean
description: |
Whether the server is ready for traffic.
Will always be false when any transition is pending.
pending:
type: string
enum: ["spawn", "stop", null]
description: |
The currently pending action, if any.
A server is not ready if an action is pending.
url:
type: string
description: |
The URL where the server can be accessed
(typically /user/:name/:server.name/).
progress_url:
type: string
description: |
The URL for an event-stream to retrieve events during a spawn.
started:
type: string
format: date-time
description: UTC timestamp when the server was last started.
last_activity:
type: string
format: date-time
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:
type: object
properties:
@@ -628,3 +779,40 @@ definitions:
description: The command used to start the service (if managed)
items:
type: string
info:
type: object
description: |
Additional information a deployment can attach to a service.
JupyterHub does not use this field.
Token:
type: object
properties:
token:
type: string
description: The token itself. Only present in responses to requests for a new token.
id:
type: string
description: The id of the API token. Used for modifying or deleting the token.
user:
type: string
description: The user that owns a token (undefined if owned by a service)
service:
type: string
description: The service that owns the token (undefined of owned by a user)
note:
type: string
description: A note about the token, typically describing what it was created for.
created:
type: string
format: date-time
description: Timestamp when this token was created
expires_at:
type: string
format: date-time
description: Timestamp when this token expires. Null if there is no expiry.
last_activity:
type: string
format: date-time
description: |
Timestamp of last-seen activity using this token.
Can be null if token has never been used.

View File

@@ -0,0 +1,106 @@
div#helm-chart-schema h2,
div#helm-chart-schema h3,
div#helm-chart-schema h4,
div#helm-chart-schema h5,
div#helm-chart-schema h6 {
font-family: courier new;
}
h3, h3 ~ * {
margin-left: 3% !important;
}
h4, h4 ~ * {
margin-left: 6% !important;
}
h5, h5 ~ * {
margin-left: 9% !important;
}
h6, h6 ~ * {
margin-left: 12% !important;
}
h7, h7 ~ * {
margin-left: 15% !important;
}
img.logo {
width:100%
}
.right-next {
float: right;
max-width: 45%;
overflow: auto;
text-overflow: ellipsis;
white-space: nowrap;
}
.right-next::after{
content: ' »';
}
.left-prev {
float: left;
max-width: 45%;
overflow: auto;
text-overflow: ellipsis;
white-space: nowrap;
}
.left-prev::before{
content: '« ';
}
.prev-next-bottom {
margin-top: 3em;
}
.prev-next-top {
margin-bottom: 1em;
}
/* Sidebar TOC and headers */
div.sphinxsidebarwrapper div {
margin-bottom: .8em;
}
div.sphinxsidebar h3 {
font-size: 1.3em;
padding-top: 0px;
font-weight: 800;
margin-left: 0px !important;
}
div.sphinxsidebar p.caption {
font-size: 1.2em;
margin-bottom: 0px;
margin-left: 0px !important;
font-weight: 900;
color: #767676;
}
div.sphinxsidebar ul {
font-size: .8em;
margin-top: 0px;
padding-left: 3%;
margin-left: 0px !important;
}
div.relations ul {
font-size: 1em;
margin-left: 0px !important;
}
div#searchbox form {
margin-left: 0px !important;
}
/* body elements */
.toctree-wrapper span.caption-text {
color: #767676;
font-style: italic;
font-weight: 300;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -0,0 +1,16 @@
{# Custom template for navigation.html
alabaster theme does not provide blocks for titles to
be overridden so this custom theme handles title and
toctree for sidebar
#}
<h3>{{ _('Table of Contents') }}</h3>
{{ toctree(includehidden=theme_sidebar_includehidden, collapse=theme_sidebar_collapse) }}
{% if theme_extra_nav_links %}
<hr />
<ul>
{% for text, uri in theme_extra_nav_links.items() %}
<li class="toctree-l1"><a href="{{ uri }}">{{ text }}</a></li>
{% endfor %}
</ul>
{% endif %}

View File

@@ -0,0 +1,30 @@
{% extends '!page.html' %}
{# Custom template for page.html
Alabaster theme does not provide blocks for prev/next at bottom of each page.
This is _in addition_ to the prev/next in the sidebar. The "Prev/Next" text
or symbols are handled by CSS classes in _static/custom.css
#}
{% macro prev_next(prev, next, prev_title='', next_title='') %}
{%- if prev %}
<a class='left-prev' href="{{ prev.link|e }}" title="{{ _('previous chapter')}}">{{ prev_title or prev.title }}</a>
{%- endif %}
{%- if next %}
<a class='right-next' href="{{ next.link|e }}" title="{{ _('next chapter')}}">{{ next_title or next.title }}</a>
{%- endif %}
<div style='clear:both;'></div>
{% endmacro %}
{% block body %}
<div class='prev-next-top'>
{{ prev_next(prev, next, 'Previous', 'Next') }}
</div>
{{super()}}
<div class='prev-next-bottom'>
{{ prev_next(prev, next) }}
</div>
{% endblock %}

View File

@@ -0,0 +1,17 @@
{# Custom template for relations.html
alabaster theme does not provide previous/next page by default
#}
<div class="relations">
<h3>Navigation</h3>
<ul>
<li><a href="{{ pathto(master_doc) }}">Documentation Home</a><ul>
{%- if prev %}
<li><a href="{{ prev.link|e }}" title="Previous">Previous topic</a></li>
{%- endif %}
{%- if next %}
<li><a href="{{ next.link|e }}" title="Next">Next topic</a></li>
{%- endif %}
</ul>
</ul>
</div>

View File

@@ -0,0 +1,159 @@
.. _admin/upgrading:
====================
Upgrading JupyterHub
====================
JupyterHub offers easy upgrade pathways between minor versions. This
document describes how to do these upgrades.
If you are using :ref:`a JupyterHub distribution <index/distributions>`, you
should consult the distribution's documentation on how to upgrade. This
document is if you have set up your own JupyterHub without using a
distribution.
It is long because is pretty detailed! Most likely, upgrading
JupyterHub is painless, quick and with minimal user interruption.
Read the Changelog
==================
The `changelog <changelog.html>`_ contains information on what has
changed with the new JupyterHub release, and any deprecation warnings.
Read these notes to familiarize yourself with the coming changes. There
might be new releases of authenticators & spawners you are using, so
read the changelogs for those too!
Notify your users
=================
If you are using the default configuration where ``configurable-http-proxy``
is managed by JupyterHub, your users will see service disruption during
the upgrade process. You should notify them, and pick a time to do the
upgrade where they will be least disrupted.
If you are using a different proxy, or running ``configurable-http-proxy``
independent of JupyterHub, your users will be able to continue using notebook
servers they had already launched, but will not be able to launch new servers
nor sign in.
Backup database & config
========================
Before doing an upgrade, it is critical to back up:
#. Your JupyterHub database (sqlite by default, or MySQL / Postgres
if you used those). If you are using sqlite (the default), you
should backup the ``jupyterhub.sqlite`` file.
#. Your ``jupyterhub_config.py`` file.
#. Your user's home directories. This is unlikely to be affected directly by
a JupyterHub upgrade, but we recommend a backup since user data is very
critical.
Shutdown JupyterHub
===================
Shutdown the JupyterHub process. This would vary depending on how you
have set up JupyterHub to run. Most likely, it is using a process
supervisor of some sort (``systemd`` or ``supervisord`` or even ``docker``).
Use the supervisor specific command to stop the JupyterHub process.
Upgrade JupyterHub packages
===========================
There are two environments where the ``jupyterhub`` package is installed:
#. The *hub environment*, which is where the JupyterHub server process
runs. This is started with the ``jupyterhub`` command, and is what
people generally think of as JupyterHub.
#. The *notebook user environments*. This is where the user notebook
servers are launched from, and is probably custom to your own
installation. This could be just one environment (different from the
hub environment) that is shared by all users, one environment
per user, or same environment as the hub environment. The hub
launched the ``jupyterhub-singleuser`` command in this environment,
which in turn starts the notebook server.
You need to make sure the version of the ``jupyterhub`` package matches
in both these environments. If you installed ``jupyterhub`` with pip,
you can upgrade it with:
.. code-block:: bash
python3 -m pip install --upgrade jupyterhub==<version>
Where ``<version>`` is the version of JupyterHub you are upgrading to.
If you used ``conda`` to install ``jupyterhub``, you should upgrade it
with:
.. code-block:: bash
conda install -c conda-forge jupyterhub==<version>
Where ``<version>`` is the version of JupyterHub you are upgrading to.
You should also check for new releases of the authenticator & spawner you
are using. You might wish to upgrade those packages too along with JupyterHub,
or upgrade them separately.
Upgrade JupyterHub database
===========================
Once new packages are installed, you need to upgrade the JupyterHub
database. From the hub environment, in the same directory as your
``jupyterhub_config.py`` file, you should run:
.. code-block:: bash
jupyterhub upgrade-db
This should find the location of your database, and run necessary upgrades
for it.
SQLite database disadvantages
-----------------------------
SQLite has some disadvantages when it comes to upgrading JupyterHub. These
are:
- ``upgrade-db`` may not work, and you may need delete your database
and start with a fresh one.
- ``downgrade-db`` **will not** work if you want to rollback to an
earlier version, so backup the ``jupyterhub.sqlite`` file before
upgrading
What happens if I delete my database?
-------------------------------------
Losing the Hub database is often not a big deal. Information that
resides only in the Hub database includes:
- active login tokens (user cookies, service tokens)
- users added via JupyterHub UI, instead of config files
- info about running servers
If the following conditions are true, you should be fine clearing the
Hub database and starting over:
- users specified in config file, or login using an external
authentication provider (Google, GitHub, LDAP, etc)
- user servers are stopped during upgrade
- don't mind causing users to login again after upgrade
Start JupyterHub
================
Once the database upgrade is completed, start the ``jupyterhub``
process again.
#. Log-in and start the server to make sure things work as
expected.
#. Check the logs for any errors or deprecation warnings. You
might have to update your ``jupyterhub_config.py`` file to
deal with any deprecated options.
Congratulations, your JupyterHub has been upgraded!

View File

@@ -13,4 +13,3 @@ Module: :mod:`jupyterhub.app`
-------------------
.. autoconfigurable:: JupyterHub

View File

@@ -26,3 +26,7 @@ Module: :mod:`jupyterhub.auth`
.. autoconfigurable:: PAMAuthenticator
:class:`DummyAuthenticator`
---------------------------
.. autoconfigurable:: DummyAuthenticator

View File

@@ -20,4 +20,3 @@ Module: :mod:`jupyterhub.proxy`
.. autoconfigurable:: ConfigurableHTTPProxy
:members: debug, auth_token, check_running_interval, api_url, command

View File

@@ -14,4 +14,3 @@ Module: :mod:`jupyterhub.services.service`
.. autoconfigurable:: Service
:members: name, admin, url, api_token, managed, kind, command, cwd, environment, user, oauth_client_id, server, prefix, proxy_spec

View File

@@ -17,7 +17,7 @@ Module: :mod:`jupyterhub.services.auth`
:members:
:class:`HubOAuth`
----------------
-----------------
.. autoconfigurable:: HubOAuth
:members:
@@ -30,7 +30,7 @@ Module: :mod:`jupyterhub.services.auth`
:members:
:class:`HubOAuthenticated`
-------------------------
--------------------------
.. autoclass:: HubOAuthenticated
@@ -38,4 +38,3 @@ Module: :mod:`jupyterhub.services.auth`
--------------------------------
.. autoclass:: HubOAuthCallbackHandler

View File

@@ -13,10 +13,9 @@ Module: :mod:`jupyterhub.spawner`
----------------
.. autoconfigurable:: Spawner
:members: options_from_form, poll, start, stop, get_args, get_env, get_state, template_namespace, format_string
:members: options_from_form, poll, start, stop, get_args, get_env, get_state, template_namespace, format_string, create_certs, move_certs
:class:`LocalProcessSpawner`
----------------------------
.. autoconfigurable:: LocalProcessSpawner

View File

@@ -34,4 +34,3 @@ Module: :mod:`jupyterhub.user`
.. attribute:: spawner
The user's :class:`~.Spawner` instance.

View File

@@ -5,7 +5,350 @@ its link will bring up a GitHub listing of changes. Use `git log` on the
command line for details.
## [Unreleased] 0.8
## [Unreleased]
## 1.0
### [1.0.0] 2019-05-03
JupyterHub 1.0 is a major milestone for JupyterHub.
Huge thanks to the many people who have contributed to this release,
whether it was through discussion, testing, documentation, or development.
#### Major new features
- Support TLS encryption and authentication of all internal communication.
Spawners must implement `.move_certs` method to make certificates available
to the notebook server if it is not local to the Hub.
- There is now full UI support for managing named servers.
With named servers, each jupyterhub user may have access to more than one named server. For example, a professor may access a server named `research` and another named `teaching`.
![named servers on the home page](./images/named-servers-home.png)
- Authenticators can now expire and refresh authentication data by implementing
`Authenticator.refresh_user(user)`.
This allows things like OAuth data and access tokens to be refreshed.
When used together with `Authenticator.refresh_pre_spawn = True`,
auth refresh can be forced prior to Spawn,
allowing the Authenticator to *require* that authentication data is fresh
immediately before the user's server is launched.
```eval_rst
.. seealso::
- :meth:`.Authenticator.refresh_user`
- :meth:`.Spawner.create_certs`
- :meth:`.Spawner.move_certs`
```
#### New features
- allow custom spawners, authenticators, and proxies to register themselves via 'entry points', enabling more convenient configuration such as:
```python
c.JupyterHub.authenticator_class = 'github'
c.JupyterHub.spawner_class = 'docker'
c.JupyterHub.proxy_class = 'traefik_etcd'
```
- Spawners are passed the tornado Handler object that requested their spawn (as `self.handler`),
so they can do things like make decisions based on query arguments in the request.
- SimpleSpawner and DummyAuthenticator, which are useful for testing, have been merged into JupyterHub itself:
```python
# For testing purposes only. Should not be used in production.
c.JupyterHub.authenticator_class = 'dummy'
c.JupyterHub.spawner_class = 'simple'
```
These classes are **not** appropriate for production use. Only testing.
- Add health check endpoint at `/hub/health`
- Several prometheus metrics have been added (thanks to [Outreachy](https://www.outreachy.org/) applicants!)
- A new API for registering user activity.
To prepare for the addition of [alternate proxy implementations](https://github.com/jupyterhub/traefik-proxy),
responsibility for tracking activity is taken away from the proxy
and moved to the notebook server (which already has activity tracking features).
Activity is now tracked by pushing it to the Hub from user servers instead of polling the
proxy API.
- Dynamic `options_form` callables may now return an empty string
which will result in no options form being rendered.
- `Spawner.user_options` is persisted to the database to be re-used,
so that a server spawned once via the form can be re-spawned via the API
with the same options.
- Added `c.PAMAuthenticator.pam_normalize_username` option for round-tripping
usernames through PAM to retrieve the normalized form.
- Added `c.JupyterHub.named_server_limit_per_user` configuration to limit
the number of named servers each user can have.
The default is 0, for no limit.
- API requests to HubAuthenticated services (e.g. single-user servers)
may pass a token in the `Authorization` header,
matching authentication with the Hub API itself.
- Added `Authenticator.is_admin(handler, authentication)` method
and `Authenticator.admin_groups` configuration for automatically
determining that a member of a group should be considered an admin.
- New `c.Authenticator.post_auth_hook` configuration
that can be any callable of the form `async def hook(authenticator, handler, authentication=None):`.
This hook may transform the return value of `Authenticator.authenticate()`
and return a new authentication dictionary,
e.g. specifying admin privileges, group membership,
or custom white/blacklisting logic.
This hook is called *after* existing normalization and whitelist checking.
- `Spawner.options_from_form` may now be async
- Added `JupyterHub.shutdown_on_logout` option to trigger shutdown of a user's
servers when they log out.
- When `Spawner.start` raises an Exception,
a message can be passed on to the user if the exception has a `.jupyterhub_message` attribute.
#### Changes
- Authentication methods such as `check_whitelist` should now take an additional
`authentication` argument
that will be a dictionary (default: None) of authentication data,
as returned by `Authenticator.authenticate()`:
```python
def check_whitelist(self, username, authentication=None):
...
```
`authentication` should have a default value of None
for backward-compatibility with jupyterhub < 1.0.
- Prometheus metrics page is now authenticated.
Any authenticated user may see the prometheus metrics.
To disable prometheus authentication,
set `JupyterHub.authenticate_prometheus = False`.
- Visits to `/user/:name` no longer trigger an implicit launch of the user's server.
Instead, a page is shown indicating that the server is not running
with a link to request the spawn.
- API requests to `/user/:name` for a not-running server will have status 503 instead of 404.
- OAuth includes a confirmation page when attempting to visit another user's server,
so that users can choose to cancel authentication with the single-user server.
Confirmation is still skipped when accessing your own server.
#### Fixed
- Various fixes to improve Windows compatibility
(default Authenticator and Spawner still do not support Windows, but other Spawners may)
- Fixed compatibility with Oracle db
- Fewer redirects following a visit to the default `/` url
- Error when progress is requested before progress is ready
- Error when API requests are made to a not-running server without authentication
- Avoid logging database password on connect if password is specified in `JupyterHub.db_url`.
#### Development changes
There have been several changes to the development process that shouldn't
generally affect users of JupyterHub, but may affect contributors.
In general, see `CONTRIBUTING.md` for contribution info or ask if you have questions.
- JupyterHub has adopted `black` as a code autoformatter and `pre-commit`
as a tool for automatically running code formatting on commit.
This is meant to make it *easier* to contribute to JupyterHub,
so let us know if it's having the opposite effect.
- JupyterHub has switched its test suite to using `pytest-asyncio` from `pytest-tornado`.
- OAuth is now implemented internally using `oauthlib` instead of `python-oauth2`. This should have no effect on behavior.
## 0.9
### [0.9.6] 2019-04-01
JupyterHub 0.9.6 is a security release.
- Fixes an Open Redirect vulnerability (CVE-2019-10255).
JupyterHub 0.9.5 included a partial fix for this issue.
### [0.9.4] 2018-09-24
JupyterHub 0.9.4 is a small bugfix release.
- Fixes an issue that required all running user servers to be restarted
when performing an upgrade from 0.8 to 0.9.
- Fixes content-type for API endpoints back to `application/json`.
It was `text/html` in 0.9.0-0.9.3.
### [0.9.3] 2018-09-12
JupyterHub 0.9.3 contains small bugfixes and improvements
- Fix token page and model handling of `expires_at`.
This field was missing from the REST API model for tokens
and could cause the token page to not render
- Add keep-alive to progress event stream to avoid proxies dropping
the connection due to inactivity
- Documentation and example improvements
- Disable quit button when using notebook 5.6
- Prototype new feature (may change prior to 1.0):
pass requesting Handler to Spawners during start,
accessible as `self.handler`
### [0.9.2] 2018-08-10
JupyterHub 0.9.2 contains small bugfixes and improvements.
- Documentation and example improvements
- Add `Spawner.consecutive_failure_limit` config for aborting the Hub if too many spawns fail in a row.
- Fix for handling SIGTERM when run with asyncio (tornado 5)
- Windows compatibility fixes
### [0.9.1] 2018-07-04
JupyterHub 0.9.1 contains a number of small bugfixes on top of 0.9.
- Use a PID file for the proxy to decrease the likelihood that a leftover proxy process will prevent JupyterHub from restarting
- `c.LocalProcessSpawner.shell_cmd` is now configurable
- API requests to stopped servers (requests to the hub for `/user/:name/api/...`) fail with 404 rather than triggering a restart of the server
- Compatibility fix for notebook 5.6.0 which will introduce further
security checks for local connections
- Managed services always use localhost to talk to the Hub if the Hub listening on all interfaces
- When using a URL prefix, the Hub route will be `JupyterHub.base_url` instead of unconditionally `/`
- additional fixes and improvements
### [0.9.0] 2018-06-15
JupyterHub 0.9 is a major upgrade of JupyterHub.
There are several changes to the database schema,
so make sure to backup your database and run:
jupyterhub upgrade-db
after upgrading jupyterhub.
The biggest change for 0.9 is the switch to asyncio coroutines everywhere
instead of tornado coroutines. Custom Spawners and Authenticators are still
free to use tornado coroutines for async methods, as they will continue to
work. As part of this upgrade, JupyterHub 0.9 drops support for Python < 3.5
and tornado < 5.0.
#### Changed
- Require Python >= 3.5
- Require tornado >= 5.0
- Use asyncio coroutines throughout
- Set status 409 for conflicting actions instead of 400,
e.g. creating users or groups that already exist.
- timestamps in REST API continue to be UTC, but now include 'Z' suffix
to identify them as such.
- REST API User model always includes `servers` dict,
not just when named servers are enabled.
- `server` info is no longer available to oauth identification endpoints,
only user info and group membership.
- `User.last_activity` may be None if a user has not been seen,
rather than starting with the user creation time
which is now separately stored as `User.created`.
- static resources are now found in `$PREFIX/share/jupyterhub` instead of `share/jupyter/hub` for improved consistency.
- Deprecate `.extra_log_file` config. Use pipe redirection instead:
jupyterhub &>> /var/log/jupyterhub.log
- Add `JupyterHub.bind_url` config for setting the full bind URL of the proxy.
Sets ip, port, base_url all at once.
- Add `JupyterHub.hub_bind_url` for setting the full host+port of the Hub.
`hub_bind_url` supports unix domain sockets, e.g.
`unix+http://%2Fsrv%2Fjupyterhub.sock`
- Deprecate `JupyterHub.hub_connect_port` config in favor of `JupyterHub.hub_connect_url`. `hub_connect_ip` is not deprecated
and can still be used in the common case where only the ip address of the hub differs from the bind ip.
#### Added
- Spawners can define a `.progress` method which should be an async generator.
The generator should yield events of the form:
```python
{
"message": "some-state-message",
"progress": 50,
}
```
These messages will be shown with a progress bar on the spawn-pending page.
The `async_generator` package can be used to make async generators
compatible with Python 3.5.
- track activity of individual API tokens
- new REST API for managing API tokens at `/hub/api/user/tokens[/token-id]`
- allow viewing/revoking tokens via token page
- User creation time is available in the REST API as `User.created`
- Server start time is stored as `Server.started`
- `Spawner.start` may return a URL for connecting to a notebook instead of `(ip, port)`. This enables Spawners to launch servers that setup their own HTTPS.
- Optimize database performance by disabling sqlalchemy expire_on_commit by default.
- Add `python -m jupyterhub.dbutil shell` entrypoint for quickly
launching an IPython session connected to your JupyterHub database.
- Include `User.auth_state` in user model on single-user REST endpoints for admins only.
- Include `Server.state` in server model on REST endpoints for admins only.
- Add `Authenticator.blacklist` for blacklisting users instead of whitelisting.
- Pass `c.JupyterHub.tornado_settings['cookie_options']` down to Spawners
so that cookie options (e.g. `expires_days`) can be set globally for the whole application.
- SIGINFO (`ctrl-t`) handler showing the current status of all running threads,
coroutines, and CPU/memory/FD consumption.
- Add async `Spawner.get_options_form` alternative to `.options_form`, so it can be a coroutine.
- Add `JupyterHub.redirect_to_server` config to govern whether
users should be sent to their server on login or the JuptyerHub home page.
- html page templates can be more easily customized and extended.
- Allow registering external OAuth clients for using the Hub as an OAuth provider.
- Add basic prometheus metrics at `/hub/metrics` endpoint.
- Add session-id cookie, enabling immediate revocation of login tokens.
- Authenticators may specify that users are admins by specifying the `admin` key when return the user model as a dict.
- Added "Start All" button to admin page for launching all user servers at once.
- Services have an `info` field which is a dictionary.
This is accessible via the REST API.
- `JupyterHub.extra_handlers` allows defining additional tornado RequestHandlers attached to the Hub.
- API tokens may now expire.
Expiry is available in the REST model as `expires_at`,
and settable when creating API tokens by specifying `expires_in`.
#### Fixed
- Remove green from theme to improve accessibility
- Fix error when proxy deletion fails due to route already being deleted
- clear `?redirects` from URL on successful launch
- disable send2trash by default, which is rarely desirable for jupyterhub
- Put PAM calls in a thread so they don't block the main application
in cases where PAM is slow (e.g. LDAP).
- Remove implicit spawn from login handler,
instead relying on subsequent request for `/user/:name` to trigger spawn.
- Fixed several inconsistencies for initial redirects,
depending on whether server is running or not and whether the user is logged in or not.
- Admin requests for `/user/:name` (when admin-access is enabled) launch the right server if it's not running instead of redirecting to their own.
- Major performance improvement starting up JupyterHub with many users,
especially when most are inactive.
- Various fixes in race conditions and performance improvements with the default proxy.
- Fixes for CORS headers
- Stop setting `.form-control` on spawner form inputs unconditionally.
- Better recovery from database errors and database connection issues
without having to restart the Hub.
- Fix handling of `~` character in usernames.
- Fix jupyterhub startup when `getpass.getuser()` would fail,
e.g. due to missing entry in passwd file in containers.
## 0.8
### [0.8.1] 2017-11-07
JupyterHub 0.8.1 is a collection of bugfixes and small improvements on 0.8.
#### Added
- Run tornado with AsyncIO by default
- Add `jupyterhub --upgrade-db` flag for automatically upgrading the database as part of startup.
This is useful for cases where manually running `jupyterhub upgrade-db`
as a separate step is unwieldy.
- Avoid creating backups of the database when no changes are to be made by
`jupyterhub upgrade-db`.
#### Fixed
- Add some further validation to usernames - `/` is not allowed in usernames.
- Fix empty logout page when using auto_login
- Fix autofill of username field in default login form.
- Fix listing of users on the admin page who have not yet started their server.
- Fix ever-growing traceback when re-raising Exceptions from spawn failures.
- Remove use of deprecated `bower` for javascript client dependencies.
### [0.8.0] 2017-10-03
JupyterHub 0.8 is a big release!
@@ -23,7 +366,7 @@ in your Dockerfile is sufficient.
#### Added
- JupyterHub now defined a `.Proxy` API for custom
- JupyterHub now defined a `Proxy` API for custom
proxy implementations other than the default.
The defaults are unchanged,
but configuration of the proxy is now done on the `ConfigurableHTTPProxy` class instead of the top-level JupyterHub.
@@ -32,11 +375,11 @@ in your Dockerfile is sufficient.
(anything that uses HubAuth)
can now accept token-authenticated requests via the Authentication header.
- Authenticators can now store state in the Hub's database.
To do so, the `.authenticate` method should return a dict of the form
To do so, the `authenticate` method should return a dict of the form
```python
{
'username': 'name'
'username': 'name',
'state': {}
}
```
@@ -233,7 +576,16 @@ Fix removal of `/login` page in 0.4.0, breaking some OAuth providers.
First preview release
[Unreleased]: https://github.com/jupyterhub/jupyterhub/compare/0.7.2...HEAD
[Unreleased]: https://github.com/jupyterhub/jupyterhub/compare/1.0.0...HEAD
[1.0.0]: https://github.com/jupyterhub/jupyterhub/compare/0.9.6...1.0.0
[0.9.6]: https://github.com/jupyterhub/jupyterhub/compare/0.9.4...0.9.6
[0.9.4]: https://github.com/jupyterhub/jupyterhub/compare/0.9.3...0.9.4
[0.9.3]: https://github.com/jupyterhub/jupyterhub/compare/0.9.2...0.9.3
[0.9.2]: https://github.com/jupyterhub/jupyterhub/compare/0.9.1...0.9.2
[0.9.1]: https://github.com/jupyterhub/jupyterhub/compare/0.9.0...0.9.1
[0.9.0]: https://github.com/jupyterhub/jupyterhub/compare/0.8.1...0.9.0
[0.8.1]: https://github.com/jupyterhub/jupyterhub/compare/0.8.0...0.8.1
[0.8.0]: https://github.com/jupyterhub/jupyterhub/compare/0.7.2...0.8.0
[0.7.2]: https://github.com/jupyterhub/jupyterhub/compare/0.7.1...0.7.2
[0.7.1]: https://github.com/jupyterhub/jupyterhub/compare/0.7.0...0.7.1
[0.7.0]: https://github.com/jupyterhub/jupyterhub/compare/0.6.1...0.7.0

View File

@@ -1,11 +1,8 @@
# -*- coding: utf-8 -*-
#
import sys
import os
import shlex
# For conversion from markdown to html
import recommonmark.parser
import sys
# Set paths
sys.path.insert(0, os.path.abspath('.'))
@@ -21,7 +18,7 @@ extensions = [
'sphinx.ext.intersphinx',
'sphinx.ext.napoleon',
'autodoc_traits',
'jupyter_alabaster_theme',
'sphinx_copybutton',
]
templates_path = ['_templates']
@@ -36,12 +33,14 @@ author = u'Project Jupyter team'
# Autopopulate version
from os.path import dirname
docs = dirname(dirname(__file__))
root = dirname(docs)
sys.path.insert(0, root)
sys.path.insert(0, os.path.join(docs, 'sphinxext'))
import jupyterhub
# The short X.Y version.
version = '%i.%i' % jupyterhub.version_info[:2]
# The full version, including alpha/beta/rc tags.
@@ -57,81 +56,99 @@ default_role = 'literal'
# -- Source -------------------------------------------------------------
source_parsers = {
'.md': 'recommonmark.parser.CommonMarkParser',
}
import recommonmark
from recommonmark.transform import AutoStructify
def setup(app):
app.add_config_value('recommonmark_config', {'enable_eval_rst': True}, True)
app.add_stylesheet('custom.css')
app.add_transform(AutoStructify)
source_parsers = {'.md': 'recommonmark.parser.CommonMarkParser'}
source_suffix = ['.rst', '.md']
#source_encoding = 'utf-8-sig'
# source_encoding = 'utf-8-sig'
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages.
html_theme = 'jupyter_alabaster_theme'
import alabaster_jupyterhub
#html_theme_options = {}
#html_theme_path = []
#html_title = None
#html_short_title = None
#html_logo = None
#html_favicon = None
html_theme = 'alabaster_jupyterhub'
html_theme_path = [alabaster_jupyterhub.get_html_theme_path()]
html_logo = '_static/images/logo/logo.png'
html_favicon = '_static/images/logo/favicon.ico'
# Paths that contain custom static files (such as style sheets)
html_static_path = ['_static']
#html_extra_path = []
#html_last_updated_fmt = '%b %d, %Y'
#html_use_smartypants = True
#html_sidebars = {}
#html_additional_pages = {}
#html_domain_indices = True
#html_use_index = True
#html_split_index = False
#html_show_sourcelink = True
#html_show_sphinx = True
#html_show_copyright = True
#html_use_opensearch = ''
#html_file_suffix = None
#html_search_language = 'en'
#html_search_options = {'type': 'default'}
#html_search_scorer = 'scorer.js'
html_theme_options = {
'show_related': True,
'description': 'Documentation for JupyterHub',
'github_user': 'jupyterhub',
'github_repo': 'jupyterhub',
'github_banner': False,
'github_button': True,
'github_type': 'star',
'show_powered_by': False,
'extra_nav_links': {
'GitHub Repo': 'http://github.com/jupyterhub/jupyterhub',
'Issue Tracker': 'http://github.com/jupyterhub/jupyterhub/issues',
},
}
html_sidebars = {
'**': [
'about.html',
'searchbox.html',
'navigation.html',
'relations.html',
'sourcelink.html',
]
}
htmlhelp_basename = 'JupyterHubdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
#'papersize': 'letterpaper',
#'pointsize': '10pt',
#'preamble': '',
#'figure_align': 'htbp',
# 'papersize': 'letterpaper',
# 'pointsize': '10pt',
# 'preamble': '',
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'JupyterHub.tex', u'JupyterHub Documentation',
u'Project Jupyter team', 'manual'),
(
master_doc,
'JupyterHub.tex',
u'JupyterHub Documentation',
u'Project Jupyter team',
'manual',
)
]
#latex_logo = None
#latex_use_parts = False
#latex_show_pagerefs = False
#latex_show_urls = False
#latex_appendices = []
#latex_domain_indices = True
# latex_logo = None
# latex_use_parts = False
# latex_show_pagerefs = False
# latex_show_urls = False
# latex_appendices = []
# latex_domain_indices = True
# -- manual page output -------------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'jupyterhub', u'JupyterHub Documentation',
[author], 1)
]
man_pages = [(master_doc, 'jupyterhub', u'JupyterHub Documentation', [author], 1)]
#man_show_urls = False
# man_show_urls = False
# -- Texinfo output -----------------------------------------------------
@@ -140,15 +157,21 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'JupyterHub', u'JupyterHub Documentation',
author, 'JupyterHub', 'One line description of project.',
'Miscellaneous'),
(
master_doc,
'JupyterHub',
u'JupyterHub Documentation',
author,
'JupyterHub',
'One line description of project.',
'Miscellaneous',
)
]
#texinfo_appendices = []
#texinfo_domain_indices = True
#texinfo_show_urls = 'footnote'
#texinfo_no_detailmenu = False
# texinfo_appendices = []
# texinfo_domain_indices = True
# texinfo_show_urls = 'footnote'
# texinfo_no_detailmenu = False
# -- Epub output --------------------------------------------------------
@@ -170,13 +193,12 @@ intersphinx_mapping = {'https://docs.python.org/3/': None}
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
if not on_rtd:
import jupyter_alabaster_theme
html_theme = 'jupyter_alabaster_theme'
html_theme_path = [jupyter_alabaster_theme.get_path()]
html_theme = 'alabaster'
else:
# readthedocs.org uses their theme by default, so no need to specify it
# build rest-api, since RTD doesn't run make
from subprocess import check_call as sh
sh(['make', 'rest-api'], cwd=docs)
# -- Spell checking -------------------------------------------------------
@@ -188,4 +210,4 @@ except ImportError:
else:
extensions.append("sphinxcontrib.spelling")
spelling_word_list_filename='spelling_wordlist.txt'
spelling_word_list_filename = 'spelling_wordlist.txt'

View File

@@ -0,0 +1,30 @@
.. _contributing/community:
================================
Community communication channels
================================
We use `Discourse <https://discourse.jupyter.org>` for online discussion.
Everyone in the Jupyter community is welcome to bring ideas and questions there.
In addition, we use `Gitter <https://gitter.im>`_ for online, real-time text chat,
a place for more ephemeral discussions.
The primary Gitter channel for JupyterHub is `jupyterhub/jupyterhub <https://gitter.im/jupyterhub/jupyterhub>`_.
Gitter isn't archived or searchable, so we recommend going to discourse first
to make sure that discussions are most useful and accessible to the community.
Remember that our community is distributed across the world in various
timezones, so be patient if you do not get an answer immediately!
GitHub issues are used for most long-form project discussions, bug reports
and feature requests. Issues related to a specific authenticator or
spawner should be directed to the appropriate repository for the
authenticator or spawner. If you are using a specific JupyterHub
distribution (such as `Zero to JupyterHub on Kubernetes <http://github.com/jupyterhub/zero-to-jupyterhub-k8s>`_
or `The Littlest JupyterHub <http://github.com/jupyterhub/the-littlest-jupyterhub/>`_),
you should open issues directly in their repository. If you can not
find a repository to open your issue in, do not worry! Create it in the `main
JupyterHub repository <https://github.com/jupyterhub/jupyterhub/>`_ and our
community will help you figure it out.
A `mailing list <https://groups.google.com/forum/#!forum/jupyter>`_ for all
of Project Jupyter exists, along with one for `teaching with Jupyter
<https://groups.google.com/forum/#!forum/jupyter-education>`_.

View File

@@ -0,0 +1,78 @@
.. _contributing/docs:
==========================
Contributing Documentation
==========================
Documentation is often more important than code. This page helps
you get set up on how to contribute documentation to JupyterHub.
Building documentation locally
==============================
We use `sphinx <http://sphinx-doc.org>`_ to build our documentation. It takes
our documentation source files (written in `markdown
<https://daringfireball.net/projects/markdown/>`_ or `reStructuredText
<http://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html>`_ &
stored under the ``docs/source`` directory) and converts it into various
formats for people to read. To make sure the documentation you write or
change renders correctly, it is good practice to test it locally.
#. Make sure you have successfuly completed :ref:`contributing/setup`.
#. Install the packages required to build the docs.
.. code-block:: bash
python3 -m pip install -r docs/requirements.txt
#. Build the html version of the docs. This is the most commonly used
output format, so verifying it renders as you should is usually good
enough.
.. code-block:: bash
cd docs
make html
This step will display any syntax or formatting errors in the documentation,
along with the filename / line number in which they occurred. Fix them,
and re-run the ``make html`` command to re-render the documentation.
#. View the rendered documentation by opening ``build/html/index.html`` in
a web browser.
.. tip::
On macOS, you can open a file from the terminal with ``open <path-to-file>``.
On Linux, you can do the same with ``xdg-open <path-to-file>``.
.. _contributing/docs/conventions:
Documentation conventions
=========================
This section lists various conventions we use in our documentation. This is a
living document that grows over time, so feel free to add to it / change it!
Our entire documentation does not yet fully conform to these conventions yet,
so help in making it so would be appreciated!
``pip`` invocation
------------------
There are many ways to invoke a ``pip`` command, we recommend the following
approach:
.. code-block:: bash
python3 -m pip
This invokes pip explicitly using the python3 binary that you are
currently using. This is the **recommended way** to invoke pip
in our documentation, since it is least likely to cause problems
with python3 and pip being from different environments.
For more information on how to invoke ``pip`` commands, see
`the pip documentation <https://pip.pypa.io/en/stable/>`_.

View File

@@ -0,0 +1,98 @@
# The JupyterHub roadmap
This roadmap collects "next steps" for JupyterHub. It is about creating a
shared understanding of the project's vision and direction amongst
the community of users, contributors, and maintainers.
The goal is to communicate priorities and upcoming release plans.
It is not a aimed at limiting contributions to what is listed here.
## Using the roadmap
### Sharing Feedback on the Roadmap
All of the community is encouraged to provide feedback as well as share new
ideas with the community. Please do so by submitting an issue. If you want to
have an informal conversation first use one of the other communication channels.
After submitting the issue, others from the community will probably
respond with questions or comments they have to clarify the issue. The
maintainers will help identify what a good next step is for the issue.
### What do we mean by "next step"?
When submitting an issue, think about what "next step" category best describes
your issue:
* **now**, concrete/actionable step that is ready for someone to start work on.
These might be items that have a link to an issue or more abstract like
"decrease typos and dead links in the documentation"
* **soon**, less concrete/actionable step that is going to happen soon,
discussions around the topic are coming close to an end at which point it can
move into the "now" category
* **later**, abstract ideas or tasks, need a lot of discussion or
experimentation to shape the idea so that it can be executed. Can also
contain concrete/actionable steps that have been postponed on purpose
(these are steps that could be in "now" but the decision was taken to work on
them later)
### Reviewing and Updating the Roadmap
The roadmap will get updated as time passes (next review by 1st December) based
on discussions and ideas captured as issues.
This means this list should not be exhaustive, it should only represent
the "top of the stack" of ideas. It should
not function as a wish list, collection of feature requests or todo list.
For those please create a
[new issue](https://github.com/jupyterhub/jupyterhub/issues/new).
The roadmap should give the reader an idea of what is happening next, what needs
input and discussion before it can happen and what has been postponed.
## The roadmap proper
### Project vision
JupyterHub is a dependable tool used by humans that reduces the complexity of
creating the environment in which a piece of software can be executed.
### Now
These "Now" items are considered active areas of focus for the project:
* HubShare - a sharing service for use with JupyterHub.
* Users should be able to:
- Push a project to other users.
- Get a checkout of a project from other users.
- Push updates to a published project.
- Pull updates from a published project.
- Manage conflicts/merges by simply picking a version (our/theirs)
- Get a checkout of a project from the internet. These steps are completely different from saving notebooks/files.
- Have directories that are managed by git completely separately from our stuff.
- Look at pushed content that they have access to without an explicit pull.
- Define and manage teams of users.
- Adding/removing a user to/from a team gives/removes them access to all projects that team has access to.
- Build other services, such as static HTML publishing and dashboarding on top of these things.
### Soon
These "Soon" items are under discussion. Once an item reaches the point of an
actionable plan, the item will be moved to the "Now" section. Typically,
these will be moved at a future review of the roadmap.
* resource monitoring and management:
- (prometheus?) API for resource monitoring
- tracking activity on single-user servers instead of the proxy
- notes and activity tracking per API token
- UI for managing named servers
### Later
The "Later" items are things that are at the back of the project's mind. At this
time there is no active plan for an item. The project would like to find the
resources and time to discuss these ideas.
- real-time collaboration
- Enter into real-time collaboration mode for a project that starts a shared execution context.
- Once the single-user notebook package supports realtime collaboration,
implement sharing mechanism integrated into the Hub.

View File

@@ -0,0 +1,10 @@
Reporting security issues in Jupyter or JupyterHub
==================================================
If you find a security vulnerability in Jupyter or JupyterHub,
whether it is a failure of the security model described in :doc:`../reference/websecurity`
or a failure in implementation,
please report it to security@ipython.org.
If you prefer to encrypt your security reports,
you can use :download:`this PGP public key </ipython_security.asc>`.

View File

@@ -0,0 +1,177 @@
.. _contributing/setup:
================================
Setting up a development install
================================
System requirements
===================
JupyterHub can only run on MacOS or Linux operating systems. If you are
using Windows, we recommend using `VirtualBox <https://virtualbox.org>`_
or a similar system to run `Ubuntu Linux <https://ubuntu.com>`_ for
development.
Install Python
--------------
JupyterHub is written in the `Python <https://python.org>`_ programming language, and
requires you have at least version 3.5 installed locally. If you havent
installed Python before, the recommended way to install it is to use
`miniconda <https://conda.io/miniconda.html>`_. Remember to get the Python 3 version,
and **not** the Python 2 version!
Install nodejs
--------------
``configurable-http-proxy``, the default proxy implementation for
JupyterHub, is written in Javascript to run on `NodeJS
<https://nodejs.org/en/>`_. If you have not installed nodejs before, we
recommend installing it in the ``miniconda`` environment you set up for
Python. You can do so with ``conda install nodejs``.
Install git
-----------
JupyterHub uses `git <https://git-scm.com>`_ & `GitHub <https://github.com>`_
for development & collaboration. You need to `install git
<https://git-scm.com/book/en/v2/Getting-Started-Installing-Git>`_ to work on
JupyterHub. We also recommend getting a free account on GitHub.com.
Setting up a development install
================================
When developing JupyterHub, you need to make changes to the code & see
their effects quickly. You need to do a developer install to make that
happen.
1. Clone the `JupyterHub git repository <https://github.com/jupyterhub/jupyterhub>`_
to your computer.
.. code:: bash
git clone https://github.com/jupyterhub/jupyterhub
cd jupyterhub
2. Make sure the ``python`` you installed and the ``npm`` you installed
are available to you on the command line.
.. code:: bash
python -V
This should return a version number greater than or equal to 3.5.
.. code:: bash
npm -v
This should return a version number greater than or equal to 5.0.
3. Install ``configurable-http-proxy``. This is required to run
JupyterHub.
.. code:: bash
npm install -g configurable-http-proxy
If you get an error that says ``Error: EACCES: permission denied``,
you might need to prefix the command with ``sudo``. If you do not
have access to sudo, you may instead run the following commands:
.. code:: bash
npm install configurable-http-proxy
export PATH=$PATH:$(pwd)/node_modules/.bin
The second line needs to be run every time you open a new terminal.
4. Install the python packages required for JupyterHub development.
.. code:: bash
python3 -m pip install -r dev-requirements.txt
python3 -m pip install -r requirements.txt
5. Install the development version of JupyterHub. This lets you edit
JupyterHub code in a text editor & restart the JupyterHub process to
see your code changes immediately.
.. code:: bash
python3 -m pip install --editable .
6. You are now ready to start JupyterHub!
.. code:: bash
jupyterhub
7. You can access JupyterHub from your browser at
``http://localhost:8000`` now.
Happy developing!
Using DummyAuthenticator & SimpleSpawner
========================================
To simplify testing of JupyterHub, its helpful to use
:class:`~jupyterhub.auth.DummyAuthenticator` instead of the default JupyterHub
authenticator and `SimpleSpawner <https://github.com/jupyterhub/simplespawner>`_
instead of the default spawner.
There is a sample configuration file that does this in
``testing/jupyterhub_config.py``. To launch jupyterhub with this
configuration:
.. code:: bash
pip install jupyterhub-simplespawner
jupyterhub -f testing/jupyterhub_config.py
The default JupyterHub `authenticator
<https://jupyterhub.readthedocs.io/en/stable/reference/authenticators.html#the-default-pam-authenticator>`_
& `spawner
<https://jupyterhub.readthedocs.io/en/stable/api/spawner.html#localprocessspawner>`_
require your system to have user accounts for each user you want to log in to
JupyterHub as.
DummyAuthenticator allows you to log in with any username & password,
while SimpleSpawner allows you to start servers without having to
create a unix user for each JupyterHub user. Together, these make it
much easier to test JupyterHub.
Tip: If you are working on parts of JupyterHub that are common to all
authenticators & spawners, we recommend using both DummyAuthenticator &
SimpleSpawner. If you are working on just authenticator related parts,
use only SimpleSpawner. Similarly, if you are working on just spawner
related parts, use only DummyAuthenticator.
Troubleshooting
===============
This section lists common ways setting up your development environment may
fail, and how to fix them. Please add to the list if you encounter yet
another way it can fail!
``lessc`` not found
-------------------
If the ``python3 -m pip install --editable .`` command fails and complains about
``lessc`` being unavailable, you may need to explicitly install some
additional JavaScript dependencies:
.. code:: bash
npm install
This will fetch client-side JavaScript dependencies necessary to compile
CSS.
You may also need to manually update JavaScript and CSS after some
development updates, with:
.. code:: bash
python3 setup.py js # fetch updated client-side js
python3 setup.py css # recompile CSS from LESS sources

View File

@@ -0,0 +1,78 @@
.. _contributing/tests:
==================
Testing JupyterHub
==================
Unit test help validate that JupyterHub works the way we think it does,
and continues to do so when changes occur. They also help communicate
precisely what we expect our code to do.
JupyterHub uses `pytest <https://pytest.org>`_ for all our tests. You
can find them under ``jupyterhub/tests`` directory in the git repository.
Running the tests
==================
#. Make sure you have completed :ref:`contributing/setup`. You should be able
to start ``jupyterhub`` from the commandline & access it from your
web browser. This ensures that the dev environment is properly set
up for tests to run.
#. You can run all tests in JupyterHub
.. code-block:: bash
pytest --async-test-timeout 15 -v jupyterhub/tests
This should display progress as it runs all the tests, printing
information about any test failures as they occur.
The ``--async-test-timeout`` parameter is used by `pytest-tornado
<https://github.com/eugeniy/pytest-tornado#markers>`_ to set the
asynchronous test timeout to 15 seconds rather than the default 5,
since some of our tests take longer than 5s to execute.
#. You can also run tests in just a specific file:
.. code-block:: bash
pytest --async-test-timeout 15 -v jupyterhub/tests/<test-file-name>
#. To run a specific test only, you can do:
.. code-block:: bash
pytest --async-test-timeout 15 -v jupyterhub/tests/<test-file-name>::<test-name>
This runs the test with function name ``<test-name>`` defined in
``<test-file-name>``. This is very useful when you are iteratively
developing a single test.
For example, to run the test ``test_shutdown`` in the file ``test_api.py``,
you would run:
.. code-block:: bash
pytest -v jupyterhub/tests/test_api.py::test_shutdown
Troubleshooting Test Failures
=============================
All the tests are failing
-------------------------
Make sure you have completed all the steps in :ref:`contributing/setup` sucessfully, and
can launch ``jupyterhub`` from the terminal.
Tests are timing out
--------------------
The ``--async-test-timeout`` parameter to ``pytest`` is used by
`pytest-tornado <https://github.com/eugeniy/pytest-tornado#markers>`_ to set
the asynchronous test timeout to a higher value than the default of 5s,
since some of our tests take longer than 5s to execute. If the tests
are still timing out, try increasing that value even more. You can
also set an environment variable ``ASYNC_TEST_TIMEOUT`` instead of
passing ``--async-test-timeout`` to each invocation of pytest.

View File

@@ -3,37 +3,65 @@
Project Jupyter thanks the following people for their help and
contribution on JupyterHub:
- adelcast
- Analect
- anderbubble
- anikitml
- ankitksharma
- apetresc
- athornton
- barrachri
- BerserkerTroll
- betatim
- Carreau
- cfournie
- charnpreetsingh
- chicovenancio
- cikao
- ckald
- cmoscardi
- consideRatio
- cqzlxl
- CRegenschein
- cwaldbieser
- danielballen
- danoventa
- daradib
- darky2004
- datapolitan
- dblockow-d2dcrc
- DeepHorizons
- DerekHeldtWerle
- dhirschfeld
- dietmarw
- dingc3
- dmartzol
- DominicFollettSmith
- dsblank
- dtaniwaki
- echarles
- ellisonbg
- emmanuel
- evanlinde
- Fokko
- fperez
- franga2000
- GladysNalvarte
- glenak1911
- gweis
- iamed18
- jamescurtin
- JamiesHQ
- JasonJWilliamsNY
- jbweston
- jdavidheiser
- jencabral
- jhamrick
- jkinkead
- johnkpark
- josephtate
- jzf2101
- karfai
- kinuax
- KrishnaPG
- kroq-gar78
@@ -43,27 +71,44 @@ contribution on JupyterHub:
- minrk
- mistercrunch
- Mistobaan
- mpacer
- mwmarkland
- ndly
- nthiery
- nxg
- ObiWahn
- ozancaglayan
- paccorsi
- parente
- PeterDaveHello
- peterruppel
- phill84
- pjamason
- prasadkatti
- rafael-ladislau
- rcthomas
- rgbkrk
- rkdarst
- robnagler
- rschroll
- ryanlovett
- sangramga
- Scrypy
- schon
- shreddd
- Siecje
- smiller5678
- spoorthyv
- ssanderson
- summerswallow
- syutbai
- takluyver
- temogen
- ThomasMChen
- Thoralf Gutierrez
- timfreund
- TimShawver
- tklever
- Todd-Z-Li
- toobaz
- tsaeger

View File

@@ -66,7 +66,7 @@ easy to do with RStudio too.
### University of Colorado Boulder
- (CU Research Computing) CURC
- (CU Research Computing) CURC
- [JupyterHub User Guide](https://www.rc.colorado.edu/support/user-guide/jupyterhub.html)
- Slurm job dispatched on Crestone compute cluster
- log troubleshooting
@@ -77,16 +77,25 @@ easy to do with RStudio too.
- Earth Lab at CU
- [Tutorial on Parallel R on JupyterHub](https://earthdatascience.org/tutorials/parallel-r-on-jupyterhub/)
### George Washington University
- [Jupyter Hub](http://go.gwu.edu/jupyter) with university single-sign-on. Deployed early 2017.
### HTCondor
- [HTCondor Python Bindings Tutorial from HTCondor Week 2017 includes information on their JupyterHub tutorials](https://research.cs.wisc.edu/htcondor/HTCondorWeek2017/presentations/TueBockelman_Python.pdf)
### University of Illinois
- https://datascience.business.illinois.edu
- https://datascience.business.illinois.edu (currently down; checked 04/26/19)
### IllustrisTNG Simulation Project
- [JupyterHub/Lab-based analysis platform, part of the TNG public data release](http://www.tng-project.org/data/)
### MIT and Lincoln Labs
- https://supercloud.mit.edu/
### Michigan State University
@@ -100,7 +109,16 @@ easy to do with RStudio too.
- https://dsa.missouri.edu/faq/
### University of Rochester CIRC
### Paderborn University
- [Data Science (DICE) group](https://dice.cs.uni-paderborn.de/)
- [nbgraderutils](https://github.com/dice-group/nbgraderutils): Use JupyterHub + nbgrader + iJava kernel for online Java exercises. Used in lecture Statistical Natural Language Processing.
### Penn State University
- [Press release](https://news.psu.edu/story/523093/2018/05/24/new-open-source-web-apps-available-students-and-faculty): "New open-source web apps available for students and faculty" (but Hub is currently down; checked 04/26/19)
### University of Rochester CIRC
- [JupyterHub Userguide](https://info.circ.rochester.edu/Web_Applications/JupyterHub.html) - Slurm, beehive
@@ -116,7 +134,7 @@ easy to do with RStudio too.
- Educational Technology Services - Paul Jamason
- [jupyterhub.ucsd.edu](https://jupyterhub.ucsd.edu)
### TACC University of Texas
### Texas A&M
@@ -141,7 +159,6 @@ easy to do with RStudio too.
[Everware](https://github.com/everware) Reproducible and reusable science powered by jupyterhub and docker. Like nbviewer, but executable. CERN, Geneva [website](http://everware.xyz/)
### Microsoft Azure
- https://docs.microsoft.com/en-us/azure/machine-learning/machine-learning-data-science-linux-dsvm-intro
@@ -151,7 +168,9 @@ easy to do with RStudio too.
- https://getcarina.com/blog/learning-how-to-whale/
- http://carolynvanslyck.com/talk/carina/jupyterhub/#/
### Red Hat
### Hadoop
- [Deploying JupyterHub on Hadoop](https://jcrist.github.io/jupyterhub-on-hadoop/)
## Miscellaneous

View File

@@ -31,6 +31,15 @@ c.Authenticator.admin_users = {'mal', 'zoe'}
Users in the admin list are automatically added to the user `whitelist`,
if they are not already present.
Each authenticator may have different ways of determining whether a user is an
administrator. By default JupyterHub use the PAMAuthenticator which provide the
`admin_groups` option and can determine administrator status base on a user
groups. For example we can let any users in the `wheel` group be admin:
```python
c.PAMAuthenticator.admin_groups = {'wheel'}
```
## Give admin access to other users' notebook servers (`admin_access`)
Since the default `JupyterHub.admin_access` setting is False, the admins
@@ -95,5 +104,16 @@ popular services:
A generic implementation, which you can use for OAuth authentication
with any provider, is also available.
## Use DummyAuthenticator for testing
The :class:`~jupyterhub.auth.DummyAuthenticator` is a simple authenticator that
allows for any username/password unless if a global password has been set. If
set, it will allow for any username as long as the correct password is provided.
To set a global password, add this to the config file:
```python
c.DummyAuthenticator.password = "some_password"
```
[PAM]: https://en.wikipedia.org/wiki/Pluggable_authentication_module
[OAuthenticator]: https://github.com/jupyterhub/oauthenticator
[OAuthenticator]: https://github.com/jupyterhub/oauthenticator

View File

@@ -1,7 +1,7 @@
# Configuration Basics
The section contains basic information about configuring settings for a JupyterHub
deployment. The [Technical Reference](../reference/index.html)
deployment. The [Technical Reference](../reference/index)
documentation provides additional details.
This section will help you learn how to:
@@ -44,7 +44,7 @@ jupyterhub -f /etc/jupyterhub/jupyterhub_config.py
```
The IPython documentation provides additional information on the
[config system](http://ipython.readthedocs.io/en/stable/development/config.html)
[config system](http://ipython.readthedocs.io/en/stable/development/config)
that Jupyter uses.
## Configure using command line options
@@ -61,7 +61,7 @@ would enter:
```bash
jupyterhub --ip 10.0.1.2 --port 443 --ssl-key my_ssl.key --ssl-cert my_ssl.cert
```
```
All configurable options may technically be set on the command-line,
though some are inconvenient to type. To set a particular configuration
@@ -77,11 +77,24 @@ jupyterhub --Spawner.notebook_dir='~/assignments'
## Configure for various deployment environments
The default authentication and process spawning mechanisms can be replaced, and
specific [authenticators](./authenticators-users-basics.html) and
[spawners](./spawners-basics.html) can be set in the configuration file.
specific [authenticators](./authenticators-users-basics) and
[spawners](./spawners-basics) can be set in the configuration file.
This enables JupyterHub to be used with a variety of authentication methods or
process control and deployment environments. [Some examples](../reference/config-examples.html),
process control and deployment environments. [Some examples](../reference/config-examples),
meant as illustration, are:
- Using GitHub OAuth instead of PAM with [OAuthenticator](https://github.com/jupyterhub/oauthenticator)
- Spawning single-user servers with Docker, using the [DockerSpawner](https://github.com/jupyterhub/dockerspawner)
## Run the proxy separately
This is *not* strictly necessary, but useful in many cases. If you
use a custom proxy (e.g. Traefik), this also not needed.
Connections to user servers go through the proxy, and *not* the hub
itself. If the proxy stays running when the hub restarts (for
maintenance, re-configuration, etc.), then use connections are not
interrupted. For simplicity, by default the hub starts the proxy
automatically, so if the hub restarts, the proxy restarts, and user
connections are interrupted. It is easy to run the proxy separately,
for information see [the separate proxy page](../reference/separate-proxy).

View File

@@ -35,6 +35,10 @@ Configuring only the main IP and port of JupyterHub should be sufficient for
most deployments of JupyterHub. However, more customized scenarios may need
additional networking details to be configured.
Note that `c.JupyterHub.ip` and `c.JupyterHub.port` are single values,
not tuples or lists JupyterHub listens to only a single IP address and
port.
## Set the Proxy's REST API communication URL (optional)
By default, this REST API listens on port 8081 of `localhost` only.
@@ -86,3 +90,12 @@ configuration for, e.g. docker, is:
c.JupyterHub.hub_ip = '0.0.0.0' # listen on all interfaces
c.JupyterHub.hub_connect_ip = '10.0.1.4' # ip as seen on the docker network. Can also be a hostname.
```
## Adjusting the hub's URL
The hub will most commonly be running on a hostname of its own. If it
is not for example, if the hub is being reverse-proxied and being
exposed at a URL such as `https://proxy.example.org/jupyter/` then
you will need to tell JupyterHub the base URL of the service. In such
a case, it is both necessary and sufficient to set
`c.JupyterHub.base_url = '/jupyter/'` in the configuration.

View File

@@ -45,7 +45,7 @@ is important that these files be put in a secure location on your server, where
they are not readable by regular users.
If you are using a **chain certificate**, see also chained certificate for SSL
in the JupyterHub `troubleshooting FAQ <troubleshooting>`_.
in the JupyterHub `Troubleshooting FAQ <../troubleshooting.html>`_.
Using letsencrypt
~~~~~~~~~~~~~~~~~
@@ -72,8 +72,13 @@ would be the needed configuration:
If SSL termination happens outside of the Hub
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In certain cases, e.g. behind `SSL termination in NGINX <https://www.nginx.com/resources/admin-guide/nginx-ssl-termination/>`_,
allowing no SSL running on the hub may be the desired configuration option.
In certain cases, for example if the hub is running behind a reverse proxy, and
`SSL termination is being provided by NGINX <https://www.nginx.com/resources/admin-guide/nginx-ssl-termination/>`_,
it is reasonable to run the hub without SSL.
To achieve this, simply omit the configuration settings
``c.JupyterHub.ssl_key`` and ``c.JupyterHub.ssl_cert``
(setting them to ``None`` does not have the same effect, and is an error).
.. _cookie-secret:
@@ -119,7 +124,7 @@ hex-encoded string. You can set it this way:
.. code-block:: bash
export JPY_COOKIE_SECRET=`openssl rand -hex 32`
export JPY_COOKIE_SECRET=$(openssl rand -hex 32)
For security reasons, this environment variable should only be visible to the
Hub. If you set it dynamically as above, all users will be logged out each time
@@ -168,7 +173,7 @@ using the ``CONFIGPROXY_AUTH_TOKEN`` environment variable:
.. code-block:: bash
export CONFIGPROXY_AUTH_TOKEN='openssl rand -hex 32'
export CONFIGPROXY_AUTH_TOKEN=$(openssl rand -hex 32)
This environment variable needs to be visible to the Hub and Proxy.

View File

@@ -14,7 +14,7 @@ document will:
- explain some basic information about API tokens
- clarify that API tokens can be used to authenticate to
single-user servers as of [version 0.8.0](../changelog.html)
single-user servers as of [version 0.8.0](../changelog)
- show how the [cull_idle_servers][] script can be:
- used in a Hub-managed service
- run as a standalone script
@@ -29,14 +29,14 @@ Hub via the REST API.
To run such an external service, an API token must be created and
provided to the service.
As of [version 0.6.0](../changelog.html), the preferred way of doing
As of [version 0.6.0](../changelog), the preferred way of doing
this is to first generate an API token:
```bash
openssl rand -hex 32
```
In [version 0.8.0](../changelog.html), a TOKEN request page for
In [version 0.8.0](../changelog), a TOKEN request page for
generating an API token is available from the JupyterHub user interface:
![Request API TOKEN page](../images/token-request.png)
@@ -88,7 +88,7 @@ c.JupyterHub.services = [
{
'name': 'cull-idle',
'admin': True,
'command': 'python cull_idle_servers.py --timeout=3600'.split(),
'command': [sys.executable, 'cull_idle_servers.py', '--timeout=3600'],
}
]
```
@@ -115,7 +115,7 @@ variable. Run `cull_idle_servers.py` manually.
```bash
export JUPYTERHUB_API_TOKEN='token'
python cull_idle_servers.py [--timeout=900] [--url=http://127.0.0.1:8081/hub/api]
python3 cull_idle_servers.py [--timeout=900] [--url=http://127.0.0.1:8081/hub/api]
```
[cull_idle_servers]: https://github.com/jupyterhub/jupyterhub/blob/master/examples/cull-idle/cull_idle_servers.py

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

View File

@@ -1,25 +1,42 @@
==========
JupyterHub
==========
`JupyterHub`_, a multi-user **Hub**, spawns, manages, and proxies multiple
`JupyterHub`_ is the best way to serve `Jupyter notebook`_ for multiple users.
It can be used in a classes of students, a corporate data science group or scientific
research group. It is a multi-user **Hub** that spawns, manages, and proxies multiple
instances of the single-user `Jupyter notebook`_ server.
JupyterHub can be used to serve notebooks to a class of students, a corporate
data science group, or a scientific research group.
.. image:: images/jhub-parts.png
To make life easier, JupyterHub have distributions. Be sure to
take a look at them before continuing with the configuration of the broad
original system of `JupyterHub`_. Today, you can find two main cases:
1. If you need a simple case for a small amount of users (0-100) and single server
take a look at
`The Littlest JupyterHub <https://github.com/jupyterhub/the-littlest-jupyterhub>`__ distribution.
2. If you need to allow for even more users, a dynamic amount of servers can be used on a cloud,
take a look at the `Zero to JupyterHub with Kubernetes <https://github.com/jupyterhub/zero-to-jupyterhub-k8s>`__ .
Four subsystems make up JupyterHub:
* a **Hub** (tornado process) that is the heart of JupyterHub
* a **configurable http proxy** (node-http-proxy) that receives the requests from the client's browser
* multiple **single-user Jupyter notebook servers** (Python/IPython/tornado) that are monitored by Spawners
* an **authentication class** that manages how users can access the system
Besides these central pieces, you can add optional configurations through a `config.py` file and manage users kernels on an admin panel. A simplification of the whole system can be seen in the figure below:
.. image:: images/jhub-fluxogram.jpeg
:alt: JupyterHub subsystems
:width: 40%
:align: right
:width: 80%
:align: center
Three subsystems make up JupyterHub:
* a multi-user **Hub** (tornado process)
* a **configurable http proxy** (node-http-proxy)
* multiple **single-user Jupyter notebook servers** (Python/IPython/tornado)
JupyterHub performs the following functions:
- The Hub spawns a proxy
- The Hub launches a proxy
- The proxy forwards all requests to the Hub by default
- The Hub handles user login and spawns single-user servers on demand
- The Hub configures the proxy to forward URL prefixes to the single-user
@@ -28,70 +45,141 @@ JupyterHub performs the following functions:
For convenient administration of the Hub, its users, and services,
JupyterHub also provides a `REST API`_.
The JupyterHub team and Project Jupyter value our community, and JupyterHub
follows the Jupyter `Community Guides <https://jupyter.readthedocs.io/en/latest/community/content-community.html>`_.
Contents
--------
========
**Installation Guide**
.. _index/distributions:
* :doc:`installation-guide`
* :doc:`quickstart`
* :doc:`quickstart-docker`
* :doc:`installation-basics`
Distributions
-------------
**Getting Started**
A JupyterHub **distribution** is tailored towards a particular set of
use cases. These are generally easier to set up than setting up
JupyterHub from scratch, assuming they fit your use case.
* :doc:`getting-started/index`
* :doc:`getting-started/config-basics`
* :doc:`getting-started/networking-basics`
* :doc:`getting-started/security-basics`
* :doc:`getting-started/authenticators-users-basics`
* :doc:`getting-started/spawners-basics`
* :doc:`getting-started/services-basics`
The two popular ones are:
**Technical Reference**
* `Zero to JupyterHub on Kubernetes <http://z2jh.jupyter.org>`_, for
running JupyterHub on top of `Kubernetes <https://k8s.io>`_. This
can scale to large number of machines & users.
* `The Littlest JupyterHub <http://tljh.jupyter.org>`_, for an easy
to set up & run JupyterHub supporting 1-100 users on a single machine.
* :doc:`reference/index`
* :doc:`reference/technical-overview`
* :doc:`reference/websecurity`
* :doc:`reference/authenticators`
* :doc:`reference/spawners`
* :doc:`reference/services`
* :doc:`reference/rest`
* :doc:`reference/upgrading`
* :doc:`reference/config-examples`
Installation Guide
------------------
**API Reference**
.. toctree::
:maxdepth: 1
* :doc:`api/index`
installation-guide
quickstart
quickstart-docker
installation-basics
**Tutorials**
Getting Started
---------------
* :doc:`tutorials/index`
* :doc:`tutorials/upgrade-dot-eight`
* `Zero to JupyterHub with Kubernetes <https://zero-to-jupyterhub.readthedocs.io/en/latest/>`_
.. toctree::
:maxdepth: 1
**Troubleshooting**
getting-started/index
getting-started/config-basics
getting-started/networking-basics
getting-started/security-basics
getting-started/authenticators-users-basics
getting-started/spawners-basics
getting-started/services-basics
* :doc:`troubleshooting`
Technical Reference
-------------------
**About JupyterHub**
.. toctree::
:maxdepth: 1
* :doc:`contributor-list`
* :doc:`gallery-jhub-deployments`
reference/index
reference/technical-overview
reference/websecurity
reference/authenticators
reference/spawners
reference/services
reference/rest
reference/templates
reference/config-user-env
reference/config-examples
reference/config-ghoauth
reference/config-proxy
reference/config-sudo
**Changelog**
Contributing
------------
* :doc:`changelog`
We want you to contribute to JupyterHub in ways that are most exciting
& useful to you. We value documentation, testing, bug reporting & code equally,
and are glad to have your contributions in whatever form you wish :)
Our `Code of Conduct <https://github.com/jupyter/governance/blob/master/conduct/code_of_conduct.md>`_
(`reporting guidelines <https://github.com/jupyter/governance/blob/master/conduct/reporting_online.md>`_)
helps keep our community welcoming to as many people as possible.
.. toctree::
:maxdepth: 1
contributing/community
contributing/setup
contributing/docs
contributing/tests
contributing/roadmap
contributing/security
Upgrading JupyterHub
--------------------
We try to make upgrades between minor versions as painless as possible.
.. toctree::
:maxdepth: 1
admin/upgrading
changelog
API Reference
-------------
.. toctree::
:maxdepth: 1
api/index
Troubleshooting
---------------
.. toctree::
:maxdepth: 1
troubleshooting
About JupyterHub
----------------
.. toctree::
:maxdepth: 1
contributor-list
changelog
gallery-jhub-deployments
Indices and tables
------------------
==================
* :ref:`genindex`
* :ref:`modindex`
Questions? Suggestions?
-----------------------
=======================
- `Jupyter mailing list <https://groups.google.com/forum/#!forum/jupyter>`_
- `Jupyter website <https://jupyter.org>`_
@@ -99,7 +187,7 @@ Questions? Suggestions?
.. _contents:
Full Table of Contents
----------------------
======================
.. toctree::
:maxdepth: 2
@@ -108,7 +196,6 @@ Full Table of Contents
getting-started/index
reference/index
api/index
tutorials/index
troubleshooting
contributor-list
gallery-jhub-deployments

View File

@@ -6,7 +6,7 @@ JupyterHub is supported on Linux/Unix based systems. To use JupyterHub, you need
a Unix server (typically Linux) running somewhere that is accessible to your
team on the network. The JupyterHub server can be on an internal network at your
organization, or it can run on the public internet (in which case, take care
with the Hub's [security](./security-basics.html)).
with the Hub's [security](./getting-started/security-basics)).
JupyterHub officially **does not** support Windows. You may be able to use
JupyterHub on Windows if you use a Spawner and Authenticator that work on
@@ -28,7 +28,7 @@ Prior to beginning installation, it's helpful to consider some of the following:
- Spawner of singleuser notebook servers (Docker, Batch, etc.)
- Services (nbgrader, etc.)
- JupyterHub database (default SQLite; traditional RDBMS such as PostgreSQL,)
MySQL, or other databases supported by [SQLAlchemy](http://www.sqlalchemy.org))
MySQL, or other databases supported by [SQLAlchemy](http://www.sqlalchemy.org))
## Folders and File Locations

View File

@@ -0,0 +1,52 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.22 (GNU/Linux)
mQINBFMx2LoBEAC9xU8JiKI1VlCJ4PT9zqhU5nChQZ06/bj1BBftiMJG07fdGVO0
ibOn4TrCoRYaeRlet0UpHzxT4zDa5h3/usJaJNTSRwtWePw2o7Lik8J+F3LionRf
8Jz81WpJ+81Klg4UWKErXjBHsu/50aoQm6ZNYG4S2nwOmMVEC4nc44IAA0bb+6kW
saFKKzEDsASGyuvyutdyUHiCfvvh5GOC2h9mXYvl4FaMW7K+d2UgCYERcXDNy7C1
Bw+uepQ9ELKdG4ZpvonO6BNr1BWLln3wk93AQfD5qhfsYRJIyj0hJlaRLtBU3i6c
xs+gQNF4mPmybpPSGuOyUr4FYC7NfoG7IUMLj+DYa6d8LcMJO+9px4IbdhQvzGtC
qz5av1TX7/+gnS4L8C9i1g8xgI+MtvogngPmPY4repOlK6y3l/WtxUPkGkyYkn3s
RzYyE/GJgTwuxFXzMQs91s+/iELFQq/QwmEJf+g/QYfSAuM+lVGajEDNBYVAQkxf
gau4s8Gm0GzTZmINilk+7TxpXtKbFc/Yr4A/fMIHmaQ7KmJB84zKwONsQdVv7Jjj
0dpwu8EIQdHxX3k7/Q+KKubEivgoSkVwuoQTG15X9xrOsDZNwfOVQh+JKazPvJtd
SNfep96r9t/8gnXv9JI95CGCQ8lNhXBUSBM3BDPTbudc4b6lFUyMXN0mKQARAQAB
tCxJUHl0aG9uIFNlY3VyaXR5IFRlYW0gPHNlY3VyaXR5QGlweXRob24ub3JnPokC
OAQTAQIAIgUCUzHYugIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQEwJc
LcmZYkjuXg//R/t6nMNQmf9W1h52IVfUbRAVmvZ5d063hQHKV2dssxtnA2dRm/x5
JZu8Wz7ZrEZpyqwRJO14sxN1/lC3v+zs9XzYXr2lBTZuKCPIBypYVGIynCuWJBQJ
rWnfG4+u1RHahnjqlTWTY1C/le6v7SjAvCb6GbdA6k4ZL2EJjQlRaHDmzw3rV/+l
LLx6/tYzIsotuflm/bFumyOMmpQQpJjnCkWIVjnRICZvuAn97jLgtTI0+0Rzf4Zb
k2BwmHwDRqWCTTcRI9QvTl8AzjW+dNImN22TpGOBPfYj8BCZ9twrpKUbf+jNqJ1K
THQzFtpdJ6SzqiFVm74xW4TKqCLkbCQ/HtVjTGMGGz/y7KTtaLpGutQ6XE8SSy6P
EffSb5u+kKlQOWaH7Mc3B0yAojz6T3j5RSI8ts6pFi6pZhDg9hBfPK2dT0v/7Mkv
E1Z7q2IdjZnhhtGWjDAMtDDn2NbY2wuGoa5jAWAR0WvIbEZ3kOxuLE5/ZOG1FyYm
noJRliBz7038nT92EoD5g1pdzuxgXtGCpYyyjRZwaLmmi4CvA+oThKmnqWNY5lyY
ricdNHDiyEXK0YafJL1oZgM86MSb0jKJMp5U11nUkUGzkroFfpGDmzBwAzEPgeiF
40+qgsKB9lqwb3G7PxvfSi3XwxfXgpm1cTyEaPSzsVzve3d1xeqb7Yq5Ag0EUzHY
ugEQALQ5FtLdNoxTxMsgvrRr1ejLiUeRNUfXtN1TYttOfvAhfBVnszjtkpIW8DCB
JF/bA7ETiH8OYYn/Fm6MPI5H64IHEncpzxjf57jgpXd9CA9U2OMk/P1nve5zYchP
QmP2fJxeAWr0aRH0Mse5JS5nCkh8Xv4nAjsBYeLTJEVOb1gPQFXOiFcVp3gaKAzX
GWOZ/mtG/uaNsabH/3TkcQQEgJefd11DWgMB7575GU+eME7c6hn3FPITA5TC5HUX
azvjv/PsWGTTVAJluJ3fUDvhpbGwYOh1uV0rB68lPpqVIro18IIJhNDnccM/xqko
4fpJdokdg4L1wih+B04OEXnwgjWG8OIphR/oL/+M37VV2U7Om/GE6LGefaYccC9c
tIaacRQJmZpG/8RsimFIY2wJ07z8xYBITmhMmOt0bLBv0mU0ym5KH9Dnru1m9QDO
AHwcKrDgL85f9MCn+YYw0d1lYxjOXjf+moaeW3izXCJ5brM+MqVtixY6aos3YO29
J7SzQ4aEDv3h/oKdDfZny21jcVPQxGDui8sqaZCi8usCcyqWsKvFHcr6vkwaufcm
3Knr2HKVotOUF5CDZybopIz1sJvY/5Dx9yfRmtivJtglrxoDKsLi1rQTlEQcFhCS
ACjf7txLtv03vWHxmp4YKQFkkOlbyhIcvfPVLTvqGerdT2FHABEBAAGJAh8EGAEC
AAkFAlMx2LoCGwwACgkQEwJcLcmZYkgK0BAAny0YUugpZldiHzYNf8I6p2OpiDWv
ZHaguTTPg2LJSKaTd+5UHZwRFIWjcSiFu+qTGLNtZAdcr0D5f991CPvyDSLYgOwb
Jm2p3GM2KxfECWzFbB/n/PjbZ5iky3+5sPlOdBR4TkfG4fcu5GwUgCkVe5u3USAk
C6W5lpeaspDz39HAPRSIOFEX70+xV+6FZ17B7nixFGN+giTpGYOEdGFxtUNmHmf+
waJoPECyImDwJvmlMTeP9jfahlB6Pzaxt6TBZYHetI/JR9FU69EmA+XfCSGt5S+0
Eoc330gpsSzo2VlxwRCVNrcuKmG7PsFFANok05ssFq1/Djv5rJ++3lYb88b8HSP2
3pQJPrM7cQNU8iPku9yLXkY5qsoZOH+3yAia554Dgc8WBhp6fWh58R0dIONQxbbo
apNdwvlI8hKFB7TiUL6PNShE1yL+XD201iNkGAJXbLMIC1ImGLirUfU267A3Cop5
hoGs179HGBcyj/sKA3uUIFdNtP+NndaP3v4iYhCitdVCvBJMm6K3tW88qkyRGzOk
4PW422oyWKwbAPeMk5PubvEFuFAIoBAFn1zecrcOg85RzRnEeXaiemmmH8GOe1Xu
Kh+7h8XXyG6RPFy8tCcLOTk+miTqX+4VWy+kVqoS2cQ5IV8WsJ3S7aeIy0H89Z8n
5vmLc+Ibz+eT+rM=
=XVDe
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -25,7 +25,7 @@ Starting JupyterHub with docker
The JupyterHub docker image can be started with the following command::
docker run -d --name jupyterhub jupyterhub/jupyterhub jupyterhub
docker run -d -p 8000:8000 --name jupyterhub jupyterhub/jupyterhub jupyterhub
This command will create a container named ``jupyterhub`` that you can
**stop and resume** with ``docker stop/start``.
@@ -37,7 +37,7 @@ If you want to run docker on a computer that has a public IP then you should
(as in MUST) **secure it with ssl** by adding ssl options to your docker
configuration or using a ssl enabled proxy.
`Mounting volumes <https://docs.docker.com/engine/userguide/containers/dockervolumes/>`_
`Mounting volumes <https://docs.docker.com/engine/admin/volumes/volumes/>`_
will allow you to store data outside the docker image (host system) so it will
be persistent, even when you start a new image.

View File

@@ -5,20 +5,27 @@
Before installing JupyterHub, you will need:
- a Linux/Unix based system
- [Python](https://www.python.org/downloads/) 3.4 or greater. An understanding
- [Python](https://www.python.org/downloads/) 3.5 or greater. An understanding
of using [`pip`](https://pip.pypa.io/en/stable/) or
[`conda`](https://conda.io/docs/get-started.html) for
installing Python packages is helpful.
- [nodejs/npm](https://www.npmjs.com/). [Install nodejs/npm](https://docs.npmjs.com/getting-started/installing-node),
using your operating system's package manager. For example, install on Linux
Debian/Ubuntu using:
using your operating system's package manager.
```bash
sudo apt-get install npm nodejs-legacy
```
* If you are using **`conda`**, the nodejs and npm dependencies will be installed for
you by conda.
* If you are using **`pip`**, install a recent version of
[nodejs/npm](https://docs.npmjs.com/getting-started/installing-node).
For example, install it on Linux (Debian/Ubuntu) using:
```
sudo apt-get install npm nodejs-legacy
```
The `nodejs-legacy` package installs the `node` executable and is currently
required for npm to work on Debian/Ubuntu.
The `nodejs-legacy` package installs the `node` executable and is currently
required for `npm` to work on Debian/Ubuntu.
- TLS certificate and key for HTTPS communication
- Domain name

View File

@@ -5,8 +5,8 @@ Hub and single user notebook servers.
## The default PAM Authenticator
JupyterHub ships only with the default [PAM][]-based Authenticator,
for logging in with local user accounts via a username and password.
JupyterHub ships with the default [PAM][]-based Authenticator, for
logging in with local user accounts via a username and password.
## The OAuthenticator
@@ -34,10 +34,17 @@ popular services:
A generic implementation, which you can use for OAuth authentication
with any provider, is also available.
## The Dummy Authenticator
When testing, it may be helpful to use the
:class:`~jupyterhub.auth.DummyAuthenticator`. This allows for any username and
password unless if a global password has been set. Once set, any username will
still be accepted but the correct password will need to be provided.
## Additional Authenticators
- ldapauthenticator for LDAP
- tmpauthenticator for temporary accounts
A partial list of other authenticators is available on the
[JupyterHub wiki](https://github.com/jupyterhub/jupyterhub/wiki/Authenticators).
## Technical Overview of Authentication
@@ -68,7 +75,6 @@ Writing an Authenticator that looks up passwords in a dictionary
requires only overriding this one method:
```python
from tornado import gen
from IPython.utils.traitlets import Dict
from jupyterhub.auth import Authenticator
@@ -78,12 +84,12 @@ class DictionaryAuthenticator(Authenticator):
help="""dict of username:password for authentication"""
)
@gen.coroutine
def authenticate(self, handler, data):
async def authenticate(self, handler, data):
if self.passwords.get(data['username']) == data['password']:
return data['username']
```
#### Normalize usernames
Since the Authenticator and Spawner both use the same username,
@@ -100,6 +106,16 @@ c.Authenticator.username_map = {
}
```
When using `PAMAuthenticator`, you can set
`c.PAMAuthenticator.pam_normalize_username = True`, which will
normalize usernames using PAM (basically round-tripping them: username
to uid to username), which is useful in case you use some external
service that allows multiple usernames mapping to the same user (such
as ActiveDirectory, yes, this really happens). When
`pam_normalize_username` is on, usernames are *not* normalized to
lowercase.
#### Validate usernames
In most cases, there is a very limited set of acceptable usernames.
@@ -116,6 +132,7 @@ To only allow usernames that start with 'w':
c.Authenticator.username_pattern = r'w.*'
```
### How to write a custom authenticator
You can use custom Authenticator subclasses to enable authentication
@@ -134,6 +151,118 @@ See a list of custom Authenticators [on the wiki](https://github.com/jupyterhub/
If you are interested in writing a custom authenticator, you can read
[this tutorial](http://jupyterhub-tutorial.readthedocs.io/en/latest/authenticators.html).
### Registering custom Authenticators via entry points
As of JupyterHub 1.0, custom authenticators can register themselves via
the `jupyterhub.authenticators` entry point metadata.
To do this, in your `setup.py` add:
```python
setup(
...
entry_points={
'jupyterhub.authenticators': [
'myservice = mypackage:MyAuthenticator',
],
},
)
```
If you have added this metadata to your package,
users can select your authenticator with the configuration:
```python
c.JupyterHub.authenticator_class = 'myservice'
```
instead of the full
```python
c.JupyterHub.authenticator_class = 'mypackage:MyAuthenticator'
```
previously required.
Additionally, configurable attributes for your authenticator will
appear in jupyterhub help output and auto-generated configuration files
via `jupyterhub --generate-config`.
### Authentication state
JupyterHub 0.8 adds the ability to persist state related to authentication,
such as auth-related tokens.
If such state should be persisted, `.authenticate()` should return a dictionary of the form:
```python
{
'name': username,
'auth_state': {
'key': 'value',
}
}
```
where `username` is the username that has been authenticated,
and `auth_state` is any JSON-serializable dictionary.
Because `auth_state` may contain sensitive information,
it is encrypted before being stored in the database.
To store auth_state, two conditions must be met:
1. persisting auth state must be enabled explicitly via configuration
```python
c.Authenticator.enable_auth_state = True
```
2. encryption must be enabled by the presence of `JUPYTERHUB_CRYPT_KEY` environment variable,
which should be a hex-encoded 32-byte key.
For example:
```bash
export JUPYTERHUB_CRYPT_KEY=$(openssl rand -hex 32)
```
JupyterHub uses [Fernet](https://cryptography.io/en/latest/fernet/) to encrypt auth_state.
To facilitate key-rotation, `JUPYTERHUB_CRYPT_KEY` may be a semicolon-separated list of encryption keys.
If there are multiple keys present, the **first** key is always used to persist any new auth_state.
#### Using auth_state
Typically, if `auth_state` is persisted it is desirable to affect the Spawner environment in some way.
This may mean defining environment variables, placing certificate in the user's home directory, etc.
The `Authenticator.pre_spawn_start` method can be used to pass information from authenticator state
to Spawner environment:
```python
class MyAuthenticator(Authenticator):
@gen.coroutine
def authenticate(self, handler, data=None):
username = yield identify_user(handler, data)
upstream_token = yield token_for_user(username)
return {
'name': username,
'auth_state': {
'upstream_token': upstream_token,
},
}
@gen.coroutine
def pre_spawn_start(self, user, spawner):
"""Pass upstream_token to spawner via environment variable"""
auth_state = yield user.get_auth_state()
if not auth_state:
# auth_state not enabled
return
spawner.environment['UPSTREAM_TOKEN'] = auth_state['upstream_token']
```
## pre_spawn_start and post_spawn_stop hooks
Authenticators uses two hooks, [pre_spawn_start(user, spawner)][] and
[post_spawn_stop(user, spawner)][] to add pass additional state information
between the authenticator and a spawner. These hooks are typically used auth-related
startup, i.e. opening a PAM session, and auth-related cleanup, i.e. closing a
PAM session.
## JupyterHub as an OAuth provider
@@ -145,5 +274,5 @@ Beginning with version 0.8, JupyterHub is an OAuth provider.
[OAuth]: https://en.wikipedia.org/wiki/OAuth
[GitHub OAuth]: https://developer.github.com/v3/oauth/
[OAuthenticator]: https://github.com/jupyterhub/oauthenticator
[pre_spawn_start(user, spawner)]: http://jupyterhub.readthedocs.io/en/latest/api/auth.html#jupyterhub.auth.Authenticator.pre_spawn_start
[post_spawn_stop(user, spawner)]: http://jupyterhub.readthedocs.io/en/latest/api/auth.html#jupyterhub.auth.Authenticator.post_spawn_stop
[pre_spawn_start(user, spawner)]: https://jupyterhub.readthedocs.io/en/latest/api/auth.html#jupyterhub.auth.Authenticator.pre_spawn_start
[post_spawn_stop(user, spawner)]: https://jupyterhub.readthedocs.io/en/latest/api/auth.html#jupyterhub.auth.Authenticator.post_spawn_stop

View File

@@ -1,209 +1,8 @@
# Configuration examples
This section provides examples, including configuration files and tips, for the
following configurations:
The following sections provide examples, including configuration files and tips, for the
following:
- Using GitHub OAuth
- Using nginx reverse proxy
## Using GitHub OAuth
In this example, we show a configuration file for a fairly standard JupyterHub
deployment with the following assumptions:
* Running JupyterHub on a single cloud server
* Using SSL on the standard HTTPS port 443
* Using GitHub OAuth (using oauthenticator) for login
* Users exist locally on the server
* Users' notebooks to be served from `~/assignments` to allow users to browse
for notebooks within other users' home directories
* You want the landing page for each user to be a `Welcome.ipynb` notebook in
their assignments directory.
* All runtime files are put into `/srv/jupyterhub` and log files in `/var/log`.
The `jupyterhub_config.py` file would have these settings:
```python
# jupyterhub_config.py file
c = get_config()
import os
pjoin = os.path.join
runtime_dir = os.path.join('/srv/jupyterhub')
ssl_dir = pjoin(runtime_dir, 'ssl')
if not os.path.exists(ssl_dir):
os.makedirs(ssl_dir)
# Allows multiple single-server per user
c.JupyterHub.allow_named_servers = True
# https on :443
c.JupyterHub.port = 443
c.JupyterHub.ssl_key = pjoin(ssl_dir, 'ssl.key')
c.JupyterHub.ssl_cert = pjoin(ssl_dir, 'ssl.cert')
# put the JupyterHub cookie secret and state db
# in /var/run/jupyterhub
c.JupyterHub.cookie_secret_file = pjoin(runtime_dir, 'cookie_secret')
c.JupyterHub.db_url = pjoin(runtime_dir, 'jupyterhub.sqlite')
# or `--db=/path/to/jupyterhub.sqlite` on the command-line
# use GitHub OAuthenticator for local users
c.JupyterHub.authenticator_class = 'oauthenticator.LocalGitHubOAuthenticator'
c.GitHubOAuthenticator.oauth_callback_url = os.environ['OAUTH_CALLBACK_URL']
# create system users that don't exist yet
c.LocalAuthenticator.create_system_users = True
# specify users and admin
c.Authenticator.whitelist = {'rgbkrk', 'minrk', 'jhamrick'}
c.Authenticator.admin_users = {'jhamrick', 'rgbkrk'}
# start single-user notebook servers in ~/assignments,
# with ~/assignments/Welcome.ipynb as the default landing page
# this config could also be put in
# /etc/jupyter/jupyter_notebook_config.py
c.Spawner.notebook_dir = '~/assignments'
c.Spawner.args = ['--NotebookApp.default_url=/notebooks/Welcome.ipynb']
```
Using the GitHub Authenticator requires a few additional
environment variable to be set prior to launching JupyterHub:
```bash
export GITHUB_CLIENT_ID=github_id
export GITHUB_CLIENT_SECRET=github_secret
export OAUTH_CALLBACK_URL=https://example.com/hub/oauth_callback
export CONFIGPROXY_AUTH_TOKEN=super-secret
# append log output to log file /var/log/jupyterhub.log
jupyterhub -f /etc/jupyterhub/jupyterhub_config.py &>> /var/log/jupyterhub.log
```
## Using nginx reverse proxy
In the following example, we show configuration files for a JupyterHub server
running locally on port `8000` but accessible from the outside on the standard
SSL port `443`. This could be useful if the JupyterHub server machine is also
hosting other domains or content on `443`. The goal in this example is to
satisfy the following:
* JupyterHub is running on a server, accessed *only* via `HUB.DOMAIN.TLD:443`
* On the same machine, `NO_HUB.DOMAIN.TLD` strictly serves different content,
also on port `443`
* `nginx` is used to manage the web servers / reverse proxy (which means that
only nginx will be able to bind two servers to `443`)
* After testing, the server in question should be able to score an A+ on the
Qualys SSL Labs [SSL Server Test](https://www.ssllabs.com/ssltest/)
Let's start out with needed JupyterHub configuration in `jupyterhub_config.py`:
```python
# Force the proxy to only listen to connections to 127.0.0.1
c.JupyterHub.ip = '127.0.0.1'
```
The **`nginx` server config file** is fairly standard fare except for the two
`location` blocks within the `HUB.DOMAIN.TLD` config file:
```bash
# HTTP server to redirect all 80 traffic to SSL/HTTPS
server {
listen 80;
server_name HUB.DOMAIN.TLD;
# Tell all requests to port 80 to be 302 redirected to HTTPS
return 302 https://$host$request_uri;
}
# HTTPS server to handle JupyterHub
server {
listen 443;
ssl on;
server_name HUB.DOMAIN.TLD;
ssl_certificate /etc/letsencrypt/live/HUB.DOMAIN.TLD/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/HUB.DOMAIN.TLD/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security max-age=15768000;
# Managing literal requests to the JupyterHub front end
location / {
proxy_pass https://127.0.0.1:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Managing WebHook/Socket requests between hub user servers and external proxy
location ~* /(api/kernels/[^/]+/(channels|iopub|shell|stdin)|terminals/websocket)/? {
proxy_pass https://127.0.0.1:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
# Managing requests to verify letsencrypt host
location ~ /.well-known {
allow all;
}
}
```
`nginx` will now be the front facing element of JupyterHub on `443` which means
it is also free to bind other servers, like `NO_HUB.DOMAIN.TLD` to the same port
on the same machine and network interface. In fact, one can simply use the same
server blocks as above for `NO_HUB` and simply add line for the root directory
of the site as well as the applicable location call:
```bash
server {
listen 80;
server_name NO_HUB.DOMAIN.TLD;
# Tell all requests to port 80 to be 302 redirected to HTTPS
return 302 https://$host$request_uri;
}
server {
listen 443;
ssl on;
# INSERT OTHER SSL PARAMETERS HERE AS ABOVE
# Set the appropriate root directory
root /var/www/html
# Set URI handling
location / {
try_files $uri $uri/ =404;
}
# Managing requests to verify letsencrypt host
location ~ /.well-known {
allow all;
}
}
```
Now just restart `nginx`, restart the JupyterHub, and enjoy accessing
`https://HUB.DOMAIN.TLD` while serving other content securely on
`https://NO_HUB.DOMAIN.TLD`.
- Configuring GitHub OAuth
- Using reverse proxy (nginx and Apache)
- Run JupyterHub without root privileges using `sudo`

View File

@@ -0,0 +1,82 @@
# Configure GitHub OAuth
In this example, we show a configuration file for a fairly standard JupyterHub
deployment with the following assumptions:
* Running JupyterHub on a single cloud server
* Using SSL on the standard HTTPS port 443
* Using GitHub OAuth (using oauthenticator) for login
* Using the default spawner (to configure other spawners, uncomment and edit
`spawner_class` as well as follow the instructions for your desired spawner)
* Users exist locally on the server
* Users' notebooks to be served from `~/assignments` to allow users to browse
for notebooks within other users' home directories
* You want the landing page for each user to be a `Welcome.ipynb` notebook in
their assignments directory.
* All runtime files are put into `/srv/jupyterhub` and log files in `/var/log`.
The `jupyterhub_config.py` file would have these settings:
```python
# jupyterhub_config.py file
c = get_config()
import os
pjoin = os.path.join
runtime_dir = os.path.join('/srv/jupyterhub')
ssl_dir = pjoin(runtime_dir, 'ssl')
if not os.path.exists(ssl_dir):
os.makedirs(ssl_dir)
# Allows multiple single-server per user
c.JupyterHub.allow_named_servers = True
# https on :443
c.JupyterHub.port = 443
c.JupyterHub.ssl_key = pjoin(ssl_dir, 'ssl.key')
c.JupyterHub.ssl_cert = pjoin(ssl_dir, 'ssl.cert')
# put the JupyterHub cookie secret and state db
# in /var/run/jupyterhub
c.JupyterHub.cookie_secret_file = pjoin(runtime_dir, 'cookie_secret')
c.JupyterHub.db_url = pjoin(runtime_dir, 'jupyterhub.sqlite')
# or `--db=/path/to/jupyterhub.sqlite` on the command-line
# use GitHub OAuthenticator for local users
c.JupyterHub.authenticator_class = 'oauthenticator.LocalGitHubOAuthenticator'
c.GitHubOAuthenticator.oauth_callback_url = os.environ['OAUTH_CALLBACK_URL']
# create system users that don't exist yet
c.LocalAuthenticator.create_system_users = True
# specify users and admin
c.Authenticator.whitelist = {'rgbkrk', 'minrk', 'jhamrick'}
c.Authenticator.admin_users = {'jhamrick', 'rgbkrk'}
# uses the default spawner
# To use a different spawner, uncomment `spawner_class` and set to desired
# spawner (e.g. SudoSpawner). Follow instructions for desired spawner
# configuration.
# c.JupyterHub.spawner_class = 'sudospawner.SudoSpawner'
# start single-user notebook servers in ~/assignments,
# with ~/assignments/Welcome.ipynb as the default landing page
# this config could also be put in
# /etc/jupyter/jupyter_notebook_config.py
c.Spawner.notebook_dir = '~/assignments'
c.Spawner.args = ['--NotebookApp.default_url=/notebooks/Welcome.ipynb']
```
Using the GitHub Authenticator requires a few additional
environment variable to be set prior to launching JupyterHub:
```bash
export GITHUB_CLIENT_ID=github_id
export GITHUB_CLIENT_SECRET=github_secret
export OAUTH_CALLBACK_URL=https://example.com/hub/oauth_callback
export CONFIGPROXY_AUTH_TOKEN=super-secret
# append log output to log file /var/log/jupyterhub.log
jupyterhub -f /etc/jupyterhub/jupyterhub_config.py &>> /var/log/jupyterhub.log
```

View File

@@ -0,0 +1,212 @@
# Using a reverse proxy
In the following example, we show configuration files for a JupyterHub server
running locally on port `8000` but accessible from the outside on the standard
SSL port `443`. This could be useful if the JupyterHub server machine is also
hosting other domains or content on `443`. The goal in this example is to
satisfy the following:
* JupyterHub is running on a server, accessed *only* via `HUB.DOMAIN.TLD:443`
* On the same machine, `NO_HUB.DOMAIN.TLD` strictly serves different content,
also on port `443`
* `nginx` or `apache` is used as the public access point (which means that
only nginx/apache will bind to `443`)
* After testing, the server in question should be able to score at least an A on the
Qualys SSL Labs [SSL Server Test](https://www.ssllabs.com/ssltest/)
Let's start out with needed JupyterHub configuration in `jupyterhub_config.py`:
```python
# Force the proxy to only listen to connections to 127.0.0.1
c.JupyterHub.ip = '127.0.0.1'
```
For high-quality SSL configuration, we also generate Diffie-Helman parameters.
This can take a few minutes:
```bash
openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
```
## nginx
This **`nginx` config file** is fairly standard fare except for the two
`location` blocks within the main section for HUB.DOMAIN.tld.
To create a new site for jupyterhub in your nginx config, make a new file
in `sites.enabled`, e.g. `/etc/nginx/sites.enabled/jupyterhub.conf`:
```bash
# top-level http config for websocket headers
# If Upgrade is defined, Connection = upgrade
# If Upgrade is empty, Connection = close
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# HTTP server to redirect all 80 traffic to SSL/HTTPS
server {
listen 80;
server_name HUB.DOMAIN.TLD;
# Tell all requests to port 80 to be 302 redirected to HTTPS
return 302 https://$host$request_uri;
}
# HTTPS server to handle JupyterHub
server {
listen 443;
ssl on;
server_name HUB.DOMAIN.TLD;
ssl_certificate /etc/letsencrypt/live/HUB.DOMAIN.TLD/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/HUB.DOMAIN.TLD/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security max-age=15768000;
# Managing literal requests to the JupyterHub front end
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# websocket headers
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
# Managing requests to verify letsencrypt host
location ~ /.well-known {
allow all;
}
}
```
If `nginx` is not running on port 443, substitute `$http_host` for `$host` on
the lines setting the `Host` header.
`nginx` will now be the front facing element of JupyterHub on `443` which means
it is also free to bind other servers, like `NO_HUB.DOMAIN.TLD` to the same port
on the same machine and network interface. In fact, one can simply use the same
server blocks as above for `NO_HUB` and simply add line for the root directory
of the site as well as the applicable location call:
```bash
server {
listen 80;
server_name NO_HUB.DOMAIN.TLD;
# Tell all requests to port 80 to be 302 redirected to HTTPS
return 302 https://$host$request_uri;
}
server {
listen 443;
ssl on;
# INSERT OTHER SSL PARAMETERS HERE AS ABOVE
# SSL cert may differ
# Set the appropriate root directory
root /var/www/html
# Set URI handling
location / {
try_files $uri $uri/ =404;
}
# Managing requests to verify letsencrypt host
location ~ /.well-known {
allow all;
}
}
```
Now restart `nginx`, restart the JupyterHub, and enjoy accessing
`https://HUB.DOMAIN.TLD` while serving other content securely on
`https://NO_HUB.DOMAIN.TLD`.
## Apache
As with nginx above, you can use [Apache](https://httpd.apache.org) as the reverse proxy.
First, we will need to enable the apache modules that we are going to need:
```bash
a2enmod ssl rewrite proxy proxy_http proxy_wstunnel
```
Our Apache configuration is equivalent to the nginx configuration above:
- Redirect HTTP to HTTPS
- Good SSL Configuration
- Support for websockets on any proxied URL
- JupyterHub is running locally at http://127.0.0.1:8000
```bash
# redirect HTTP to HTTPS
Listen 80
<VirtualHost HUB.DOMAIN.TLD:80>
ServerName HUB.DOMAIN.TLD
Redirect / https://HUB.DOMAIN.TLD/
</VirtualHost>
Listen 443
<VirtualHost HUB.DOMAIN.TLD:443>
ServerName HUB.DOMAIN.TLD
# configure SSL
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/HUB.DOMAIN.TLD/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/HUB.DOMAIN.TLD/privkey.pem
SSLProtocol All -SSLv2 -SSLv3
SSLOpenSSLConfCmd DHParameters /etc/ssl/certs/dhparam.pem
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
# Use RewriteEngine to handle websocket connection upgrades
RewriteEngine On
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteRule /(.*) ws://127.0.0.1:8000/$1 [P,L]
<Location "/">
# preserve Host header to avoid cross-origin problems
ProxyPreserveHost on
# proxy to JupyterHub
ProxyPass http://127.0.0.1:8000/
ProxyPassReverse http://127.0.0.1:8000/
</Location>
</VirtualHost>
```
In case of the need to run the jupyterhub under /jhub/ or other location please use the below configurations:
- JupyterHub running locally at http://127.0.0.1:8000/jhub/ or other location
httpd.conf amendments:
```bash
RewriteRule /jhub/(.*) ws://127.0.0.1:8000/jhub/$1 [P,L]
RewriteRule /jhub/(.*) http://127.0.0.1:8000/jhub/$1 [P,L]
ProxyPass /jhub/ http://127.0.0.1:8000/jhub/
ProxyPassReverse /jhub/ http://127.0.0.1:8000/jhub/
```
jupyterhub_config.py amendments:
```bash
--The public facing URL of the whole JupyterHub application.
--This is the address on which the proxy will bind. Sets protocol, ip, base_url
c.JupyterHub.bind_url = 'http://127.0.0.1:8000/jhub/'
```

View File

@@ -0,0 +1,254 @@
# Run JupyterHub without root privileges using `sudo`
**Note:** Setting up `sudo` permissions involves many pieces of system
configuration. It is quite easy to get wrong and very difficult to debug.
Only do this if you are very sure you must.
## Overview
There are many Authenticators and Spawners available for JupyterHub. Some, such
as DockerSpawner or OAuthenticator, do not need any elevated permissions. This
document describes how to get the full default behavior of JupyterHub while
running notebook servers as real system users on a shared system without
running the Hub itself as root.
Since JupyterHub needs to spawn processes as other users, the simplest way
is to run it as root, spawning user servers with [setuid](http://linux.die.net/man/2/setuid).
But this isn't especially safe, because you have a process running on the
public web as root.
A **more prudent way** to run the server while preserving functionality is to
create a dedicated user with `sudo` access restricted to launching and
monitoring single-user servers.
## Create a user
To do this, first create a user that will run the Hub:
```bash
sudo useradd rhea
```
This user shouldn't have a login shell or password (possible with -r).
## Set up sudospawner
Next, you will need [sudospawner](https://github.com/jupyter/sudospawner)
to enable monitoring the single-user servers with sudo:
```bash
sudo python3 -m pip install sudospawner
```
Now we have to configure sudo to allow the Hub user (`rhea`) to launch
the sudospawner script on behalf of our hub users (here `zoe` and `wash`).
We want to confine these permissions to only what we really need.
## Edit `/etc/sudoers`
To do this we add to `/etc/sudoers` (use `visudo` for safe editing of sudoers):
- specify the list of users `JUPYTER_USERS` for whom `rhea` can spawn servers
- set the command `JUPYTER_CMD` that `rhea` can execute on behalf of users
- give `rhea` permission to run `JUPYTER_CMD` on behalf of `JUPYTER_USERS`
without entering a password
For example:
```bash
# comma-separated whitelist of users that can spawn single-user servers
# this should include all of your Hub users
Runas_Alias JUPYTER_USERS = rhea, zoe, wash
# the command(s) the Hub can run on behalf of the above users without needing a password
# the exact path may differ, depending on how sudospawner was installed
Cmnd_Alias JUPYTER_CMD = /usr/local/bin/sudospawner
# actually give the Hub user permission to run the above command on behalf
# of the above users without prompting for a password
rhea ALL=(JUPYTER_USERS) NOPASSWD:JUPYTER_CMD
```
It might be useful to modify `secure_path` to add commands in path.
As an alternative to adding every user to the `/etc/sudoers` file, you can
use a group in the last line above, instead of `JUPYTER_USERS`:
```bash
rhea ALL=(%jupyterhub) NOPASSWD:JUPYTER_CMD
```
If the `jupyterhub` group exists, there will be no need to edit `/etc/sudoers`
again. A new user will gain access to the application when added to the group:
```bash
$ adduser -G jupyterhub newuser
```
## Test `sudo` setup
Test that the new user doesn't need to enter a password to run the sudospawner
command.
This should prompt for your password to switch to rhea, but *not* prompt for
any password for the second switch. It should show some help output about
logging options:
```bash
$ sudo -u rhea sudo -n -u $USER /usr/local/bin/sudospawner --help
Usage: /usr/local/bin/sudospawner [OPTIONS]
Options:
--help show this help information
...
```
And this should fail:
```bash
$ sudo -u rhea sudo -n -u $USER echo 'fail'
sudo: a password is required
```
## Enable PAM for non-root
By default, [PAM authentication](http://en.wikipedia.org/wiki/Pluggable_authentication_module)
is used by JupyterHub. To use PAM, the process may need to be able to read
the shadow password database.
### Shadow group (Linux)
```bash
$ ls -l /etc/shadow
-rw-r----- 1 root shadow 2197 Jul 21 13:41 shadow
```
If there's already a shadow group, you are set. If its permissions are more like:
```bash
$ ls -l /etc/shadow
-rw------- 1 root wheel 2197 Jul 21 13:41 shadow
```
Then you may want to add a shadow group, and make the shadow file group-readable:
```bash
$ sudo groupadd shadow
$ sudo chgrp shadow /etc/shadow
$ sudo chmod g+r /etc/shadow
```
We want our new user to be able to read the shadow passwords, so add it to the shadow group:
```bash
$ sudo usermod -a -G shadow rhea
```
If you want jupyterhub to serve pages on a restricted port (such as port 80 for http),
then you will need to give `node` permission to do so:
```bash
sudo setcap 'cap_net_bind_service=+ep' /usr/bin/node
```
However, you may want to further understand the consequences of this.
You may also be interested in limiting the amount of CPU any process can use
on your server. `cpulimit` is a useful tool that is available for many Linux
distributions' packaging system. This can be used to keep any user's process
from using too much CPU cycles. You can configure it accoring to [these
instructions](http://ubuntuforums.org/showthread.php?t=992706).
### Shadow group (FreeBSD)
**NOTE:** This has not been tested and may not work as expected.
```bash
$ ls -l /etc/spwd.db /etc/master.passwd
-rw------- 1 root wheel 2516 Aug 22 13:35 /etc/master.passwd
-rw------- 1 root wheel 40960 Aug 22 13:35 /etc/spwd.db
```
Add a shadow group if there isn't one, and make the shadow file group-readable:
```bash
$ sudo pw group add shadow
$ sudo chgrp shadow /etc/spwd.db
$ sudo chmod g+r /etc/spwd.db
$ sudo chgrp shadow /etc/master.passwd
$ sudo chmod g+r /etc/master.passwd
```
We want our new user to be able to read the shadow passwords, so add it to the
shadow group:
```bash
$ sudo pw user mod rhea -G shadow
```
## Test that PAM works
We can verify that PAM is working, with:
```bash
$ sudo -u rhea python3 -c "import pamela, getpass; print(pamela.authenticate('$USER', getpass.getpass()))"
Password: [enter your unix password]
```
## Make a directory for JupyterHub
JupyterHub stores its state in a database, so it needs write access to a directory.
The simplest way to deal with this is to make a directory owned by your Hub user,
and use that as the CWD when launching the server.
```bash
$ sudo mkdir /etc/jupyterhub
$ sudo chown rhea /etc/jupyterhub
```
## Start jupyterhub
Finally, start the server as our newly configured user, `rhea`:
```bash
$ cd /etc/jupyterhub
$ sudo -u rhea jupyterhub --JupyterHub.spawner_class=sudospawner.SudoSpawner
```
And try logging in.
## Troubleshooting: SELinux
If you still get a generic `Permission denied` `PermissionError`, it's possible SELinux is blocking you.
Here's how you can make a module to allow this.
First, put this in a file named `sudo_exec_selinux.te`:
```bash
module sudo_exec_selinux 1.1;
require {
type unconfined_t;
type sudo_exec_t;
class file { read entrypoint };
}
#============= unconfined_t ==============
allow unconfined_t sudo_exec_t:file entrypoint;
```
Then run all of these commands as root:
```bash
$ checkmodule -M -m -o sudo_exec_selinux.mod sudo_exec_selinux.te
$ semodule_package -o sudo_exec_selinux.pp -m sudo_exec_selinux.mod
$ semodule -i sudo_exec_selinux.pp
```
## Troubleshooting: PAM session errors
If the PAM authentication doesn't work and you see errors for
`login:session-auth`, or similar, considering updating to a more recent version
of jupyterhub and disabling the opening of PAM sessions with
`c.PAMAuthenticator.open_sessions=False`.

View File

@@ -0,0 +1,181 @@
# Configuring user environments
Deploying JupyterHub means you are providing Jupyter notebook environments for
multiple users. Often, this includes a desire to configure the user
environment in some way.
Since the `jupyterhub-singleuser` server extends the standard Jupyter notebook
server, most configuration and documentation that applies to Jupyter Notebook
applies to the single-user environments. Configuration of user environments
typically does not occur through JupyterHub itself, but rather through system-
wide configuration of Jupyter, which is inherited by `jupyterhub-singleuser`.
**Tip:** When searching for configuration tips for JupyterHub user
environments, try removing JupyterHub from your search because there are a lot
more people out there configuring Jupyter than JupyterHub and the
configuration is the same.
This section will focus on user environments, including:
- Installing packages
- Configuring Jupyter and IPython
- Installing kernelspecs
- Using containers vs. multi-user hosts
## Installing packages
To make packages available to users, you generally will install packages
system-wide or in a shared environment.
This installation location should always be in the same environment that
`jupyterhub-singleuser` itself is installed in, and must be *readable and
executable* by your users. If you want users to be able to install additional
packages, it must also be *writable* by your users.
If you are using a standard system Python install, you would use:
```bash
sudo python3 -m pip install numpy
```
to install the numpy package in the default system Python 3 environment
(typically `/usr/local`).
You may also use conda to install packages. If you do, you should make sure
that the conda environment has appropriate permissions for users to be able to
run Python code in the env.
## Configuring Jupyter and IPython
[Jupyter](https://jupyter-notebook.readthedocs.io/en/stable/config_overview.html)
and [IPython](https://ipython.readthedocs.io/en/stable/development/config.html)
have their own configuration systems.
As a JupyterHub administrator, you will typically want to install and configure
environments for all JupyterHub users. For example, you wish for each student in
a class to have the same user environment configuration.
Jupyter and IPython support **"system-wide"** locations for configuration, which
is the logical place to put global configuration that you want to affect all
users. It's generally more efficient to configure user environments "system-wide",
and it's a good idea to avoid creating files in users' home directories.
The typical locations for these config files are:
- **system-wide** in `/etc/{jupyter|ipython}`
- **env-wide** (environment wide) in `{sys.prefix}/etc/{jupyter|ipython}`.
### Example: Enable an extension system-wide
For example, to enable the `cython` IPython extension for all of your users,
create the file `/etc/ipython/ipython_config.py`:
```python
c.InteractiveShellApp.extensions.append("cython")
```
### Example: Enable a Jupyter notebook configuration setting for all users
To enable Jupyter notebook's internal idle-shutdown behavior (requires
notebook ≥ 5.4), set the following in the `/etc/jupyter/jupyter_notebook_config.py`
file:
```python
# shutdown the server after no activity for an hour
c.NotebookApp.shutdown_no_activity_timeout = 60 * 60
# shutdown kernels after no activity for 20 minutes
c.MappingKernelManager.cull_idle_timeout = 20 * 60
# check for idle kernels every two minutes
c.MappingKernelManager.cull_interval = 2 * 60
```
## Installing kernelspecs
You may have multiple Jupyter kernels installed and want to make sure that
they are available to all of your users. This means installing kernelspecs
either system-wide (e.g. in /usr/local/) or in the `sys.prefix` of JupyterHub
itself.
Jupyter kernelspec installation is system wide by default, but some kernels
may default to installing kernelspecs in your home directory. These will need
to be moved system-wide to ensure that they are accessible.
You can see where your kernelspecs are with:
```bash
jupyter kernelspec list
```
### Example: Installing kernels system-wide
Assuming I have a Python 2 and Python 3 environment that I want to make
sure are available, I can install their specs system-wide (in /usr/local) with:
```bash
/path/to/python3 -m IPython kernel install --prefix=/usr/local
/path/to/python2 -m IPython kernel install --prefix=/usr/local
```
## Multi-user hosts vs. Containers
There are two broad categories of user environments that depend on what
Spawner you choose:
- Multi-user hosts (shared system)
- Container-based
How you configure user environments for each category can differ a bit
depending on what Spawner you are using.
The first category is a **shared system (multi-user host)** where
each user has a JupyterHub account and a home directory as well as being
a real system user. In this example, shared configuration and installation
must be in a 'system-wide' location, such as `/etc/` or `/usr/local`
or a custom prefix such as `/opt/conda`.
When JupyterHub uses **container-based** Spawners (e.g. KubeSpawner or
DockerSpawner), the 'system-wide' environment is really the container image
which you are using for users.
In both cases, you want to *avoid putting configuration in user home
directories* because users can change those configuration settings. Also,
home directories typically persist once they are created, so they are
difficult for admins to update later.
## Named servers
By default, in a JupyterHub deployment each user has exactly one server.
JupyterHub can, however, have multiple servers per user.
This is most useful in deployments where users can configure the environment
in which their server will start (e.g. resource requests on an HPC cluster),
so that a given user can have multiple configurations running at the same time,
without having to stop and restart their one server.
To allow named servers:
```python
c.JupyterHub.allow_named_servers = True
```
Named servers were implemented in the REST API in JupyterHub 0.8,
and JupyterHub 1.0 introduces UI for managing named servers via the user home page:
![named servers on the home page](../images/named-servers-home.png)
as well as the admin page:
![named servers on the admin page](../images/named-servers-admin.png)
Named servers can be accessed, created, started, stopped, and deleted
from these pages. Activity tracking is now per-server as well.
The number of named servers per user can be limited by setting
```python
c.JupyterHub.named_server_limit_per_user = 5
```

View File

@@ -0,0 +1,62 @@
# The Hub's Database
JupyterHub uses a database to store information about users, services, and other
data needed for operating the Hub.
## Default SQLite database
The default database for JupyterHub is a [SQLite](https://sqlite.org) database.
We have chosen SQLite as JupyterHub's default for its lightweight simplicity
in certain uses such as testing, small deployments and workshops.
For production systems, SQLite has some disadvantages when used with JupyterHub:
- `upgrade-db` may not work, and you may need to start with a fresh database
- `downgrade-db` **will not** work if you want to rollback to an earlier
version, so backup the `jupyterhub.sqlite` file before upgrading
The sqlite documentation provides a helpful page about [when to use SQLite and
where traditional RDBMS may be a better choice](https://sqlite.org/whentouse.html).
## Using an RDBMS (PostgreSQL, MySQL)
When running a long term deployment or a production system, we recommend using
a traditional RDBMS database, such as [PostgreSQL](https://www.postgresql.org)
or [MySQL](https://www.mysql.com), that supports the SQL `ALTER TABLE`
statement.
## Notes and Tips
### SQLite
The SQLite database should not be used on NFS. SQLite uses reader/writer locks
to control access to the database. This locking mechanism might not work
correctly if the database file is kept on an NFS filesystem. This is because
`fcntl()` file locking is broken on many NFS implementations. Therefore, you
should avoid putting SQLite database files on NFS since it will not handle well
multiple processes which might try to access the file at the same time.
### PostgreSQL
We recommend using PostgreSQL for production if you are unsure whether to use
MySQL or PostgreSQL or if you do not have a strong preference. There is
additional configuration required for MySQL that is not needed for PostgreSQL.
### MySQL / MariaDB
- You should use the `pymysql` sqlalchemy provider (the other one, MySQLdb,
isn't available for py3).
- You also need to set `pool_recycle` to some value (typically 60 - 300)
which depends on your MySQL setup. This is necessary since MySQL kills
connections serverside if they've been idle for a while, and the connection
from the hub will be idle for longer than most connections. This behavior
will lead to frustrating 'the connection has gone away' errors from
sqlalchemy if `pool_recycle` is not set.
- If you use `utf8mb4` collation with MySQL earlier than 5.7.7 or MariaDB
earlier than 10.2.1 you may get an `1709, Index column size too large` error.
To fix this you need to set `innodb_large_prefix` to enabled and
`innodb_file_format` to `Barracuda` to allow for the index sizes jupyterhub
uses. `row_format` will be set to `DYNAMIC` as long as those options are set
correctly. Later versions of MariaDB and MySQL should set these values by
default, as well as have a default `DYNAMIC` `row_format` and pose no trouble
to users.

View File

@@ -5,10 +5,18 @@ Technical Reference
:maxdepth: 2
technical-overview
urls
websecurity
authenticators
spawners
services
proxy
separate-proxy
rest
upgrading
database
templates
config-user-env
config-examples
config-ghoauth
config-proxy
config-sudo

View File

@@ -0,0 +1,222 @@
# Writing a custom Proxy implementation
JupyterHub 0.8 introduced the ability to write a custom implementation of the
proxy. This enables deployments with different needs than the default proxy,
configurable-http-proxy (CHP). CHP is a single-process nodejs proxy that the
Hub manages by default as a subprocess (it can be run externally, as well, and
typically is in production deployments).
The upside to CHP, and why we use it by default, is that it's easy to install
and run (if you have nodejs, you are set!). The downsides are that it's a
single process and does not support any persistence of the routing table. So
if the proxy process dies, your whole JupyterHub instance is inaccessible
until the Hub notices, restarts the proxy, and restores the routing table. For
deployments that want to avoid such a single point of failure, or leverage
existing proxy infrastructure in their chosen deployment (such as Kubernetes
ingress objects), the Proxy API provides a way to do that.
In general, for a proxy to be usable by JupyterHub, it must:
1. support websockets without prior knowledge of the URL where websockets may
occur
2. support trie-based routing (i.e. allow different routes on `/foo` and
`/foo/bar` and route based on specificity)
3. adding or removing a route should not cause existing connections to drop
Optionally, if the JupyterHub deployment is to use host-based routing,
the Proxy must additionally support routing based on the Host of the request.
## Subclassing Proxy
To start, any Proxy implementation should subclass the base Proxy class,
as is done with custom Spawners and Authenticators.
```python
from jupyterhub.proxy import Proxy
class MyProxy(Proxy):
"""My Proxy implementation"""
...
```
## Starting and stopping the proxy
If your proxy should be launched when the Hub starts, you must define how
to start and stop your proxy:
```python
class MyProxy(Proxy):
...
async def start(self):
"""Start the proxy"""
async def stop(self):
"""Stop the proxy"""
```
These methods **may** be coroutines.
`c.Proxy.should_start` is a configurable flag that determines whether the
Hub should call these methods when the Hub itself starts and stops.
## Encryption
When using `internal_ssl` to encrypt traffic behind the proxy, at minimum,
your `Proxy` will need client ssl certificates which the `Hub` must be made
aware of. These can be generated with the command `jupyterhub --generate-certs`
which will write them to the `internal_certs_location` in folders named
`proxy_api` and `proxy_client`. Alternatively, these can be provided to the
hub via the `jupyterhub_config.py` file by providing a `dict` of named paths
to the `external_authorities` option. The hub will include all certificates
provided in that `dict` in the trust bundle utilized by all internal
components.
### Purely external proxies
Probably most custom proxies will be externally managed,
such as Kubernetes ingress-based implementations.
In this case, you do not need to define `start` and `stop`.
To disable the methods, you can define `should_start = False` at the class level:
```python
class MyProxy(Proxy):
should_start = False
```
## Routes
At its most basic, a Proxy implementation defines a mechanism to add, remove,
and retrieve routes. A proxy that implements these three methods is complete.
Each of these methods **may** be a coroutine.
**Definition:** routespec
A routespec, which will appear in these methods, is a string describing a
route to be proxied, such as `/user/name/`. A routespec will:
1. always end with `/`
2. always start with `/` if it is a path-based route `/proxy/path/`
3. precede the leading `/` with a host for host-based routing, e.g.
`host.tld/proxy/path/`
### Adding a route
When adding a route, JupyterHub may pass a JSON-serializable dict as a `data`
argument that should be attacked to the proxy route. When that route is
retrieved, the `data` argument should be returned as well. If your proxy
implementation doesn't support storing data attached to routes, then your
Python wrapper may have to handle storing the `data` piece itself, e.g in a
simple file or database.
```python
async def add_route(self, routespec, target, data):
"""Proxy `routespec` to `target`.
Store `data` associated with the routespec
for retrieval later.
"""
```
Adding a route for a user looks like this:
```python
await proxy.add_route('/user/pgeorgiou/', 'http://127.0.0.1:1227',
{'user': 'pgeorgiou'})
```
### Removing routes
`delete_route()` is given a routespec to delete. If there is no such route,
`delete_route` should still succeed, but a warning may be issued.
```python
async def delete_route(self, routespec):
"""Delete the route"""
```
### Retrieving routes
For retrieval, you only *need* to implement a single method that retrieves all
routes. The return value for this function should be a dictionary, keyed by
`routespect`, of dicts whose keys are the same three arguments passed to
`add_route` (`routespec`, `target`, `data`)
```python
async def get_all_routes(self):
"""Return all routes, keyed by routespec"""
```
```python
{
'/proxy/path/': {
'routespec': '/proxy/path/',
'target': 'http://...',
'data': {},
},
}
```
## Note on activity tracking
JupyterHub can track activity of users, for use in services such as culling
idle servers. As of JupyterHub 0.8, this activity tracking is the
responsibility of the proxy. If your proxy implementation can track activity
to endpoints, it may add a `last_activity` key to the `data` of routes
retrieved in `.get_all_routes()`. If present, the value of `last_activity`
should be an [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) UTC date
string:
```python
{
'/user/pgeorgiou/': {
'routespec': '/user/pgeorgiou/',
'target': 'http://127.0.0.1:1227',
'data': {
'user': 'pgeourgiou',
'last_activity': '2017-10-03T10:33:49.570Z',
},
},
}
```
If the proxy does not track activity, then only activity to the Hub itself is
tracked, and services such as cull-idle will not work.
Now that `notebook-5.0` tracks activity internally, we can retrieve activity
information from the single-user servers instead, removing the need to track
activity in the proxy. But this is not yet implemented in JupyterHub 0.8.0.
### Registering custom Proxies via entry points
As of JupyterHub 1.0, custom proxy implementations can register themselves via
the `jupyterhub.proxies` entry point metadata.
To do this, in your `setup.py` add:
```python
setup(
...
entry_points={
'jupyterhub.proxies': [
'mything = mypackage:MyProxy',
],
},
)
```
If you have added this metadata to your package,
users can select your authenticator with the configuration:
```python
c.JupyterHub.proxy_class = 'mything'
```
instead of the full
```python
c.JupyterHub.proxy_class = 'mypackage:MyProxy'
```
previously required.
Additionally, configurable attributes for your proxy will
appear in jupyterhub help output and auto-generated configuration files
via `jupyterhub --generate-config`.

View File

@@ -0,0 +1,14 @@
:orphan:
===================
JupyterHub REST API
===================
.. this doc exists as a resolvable link target
.. which _static files are not
.. meta::
:http-equiv=refresh: 0;url=../_static/rest-api/index.html
The rest API docs are `here <../_static/rest-api/index.html>`_
if you are not redirected automatically.

View File

@@ -27,7 +27,7 @@ Hub.
To send requests using JupyterHub API, you must pass an API token with
the request.
As of [version 0.6.0](../changelog.html), the preferred way of
As of [version 0.6.0](../changelog.md), the preferred way of
generating an API token is:
```bash
@@ -48,7 +48,7 @@ jupyterhub token <username>
This command generates a random string to use as a token and registers
it for the given user with the Hub's database.
In [version 0.8.0](../changelog.html), a TOKEN request page for
In [version 0.8.0](../changelog.md), a TOKEN request page for
generating an API token is available from the JupyterHub user interface:
![Request API TOKEN page](../images/token-request.png)
@@ -114,10 +114,55 @@ r.raise_for_status()
r.json()
```
Note that the API token authorizes **JupyterHub** REST API requests. The same
token does **not** authorize access to the [Jupyter Notebook REST API][]
provided by notebook servers managed by JupyterHub. A different token is used
to access the **Jupyter Notebook** API.
The same API token can also authorize access to the [Jupyter Notebook REST API][]
provided by notebook servers managed by JupyterHub if one of the following is true:
1. The token is for the same user as the owner of the notebook
2. The token is tied to an admin user or service **and** `c.JupyterHub.admin_access` is set to `True`
## Enabling users to spawn multiple named-servers via the API
With JupyterHub version 0.8, support for multiple servers per user has landed.
Prior to that, each user could only launch a single default server via the API
like this:
```bash
curl -X POST -H "Authorization: token <token>" "http://127.0.0.1:8081/hub/api/users/<user>/server"
```
With the named-server functionality, it's now possible to launch more than one
specifically named servers against a given user. This could be used, for instance,
to launch each server based on a different image.
First you must enable named-servers by including the following setting in the `jupyterhub_config.py` file.
`c.JupyterHub.allow_named_servers = True`
If using the [zero-to-jupyterhub-k8s](https://github.com/jupyterhub/zero-to-jupyterhub-k8s) set-up to run JupyterHub,
then instead of editing the `jupyterhub_config.py` file directly, you could pass
the following as part of the `config.yaml` file, as per the [tutorial](https://zero-to-jupyterhub.readthedocs.io/en/latest/):
```bash
hub:
extraConfig: |
c.JupyterHub.allow_named_servers = True
```
With that setting in place, a new named-server is activated like this:
```bash
curl -X POST -H "Authorization: token <token>" "http://127.0.0.1:8081/hub/api/users/<user>/servers/<serverA>"
curl -X POST -H "Authorization: token <token>" "http://127.0.0.1:8081/hub/api/users/<user>/servers/<serverB>"
```
The same servers can be stopped by substituting `DELETE` for `POST` above.
### Some caveats for using named-servers
For named-servers via the API to work, the spawner used to spawn these servers
will need to be able to handle the case of multiple servers per user and ensure
uniqueness of names, particularly if servers are spawned via docker containers
or kubernetes pods.
## Learn more about the API
@@ -128,5 +173,5 @@ Note: The Swagger specification is being renamed the [OpenAPI Initiative][].
[interactive style on swagger's petstore]: http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyterhub/jupyterhub/master/docs/rest-api.yml#!/default
[OpenAPI Initiative]: https://www.openapis.org/
[JupyterHub REST API]: ../_static/rest-api/index.html
[JupyterHub REST API]: ./rest-api
[Jupyter Notebook REST API]: http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml

View File

@@ -0,0 +1,80 @@
# Running proxy separately from the hub
## Background
The thing which users directly connect to is the proxy, by default
`configurable-http-proxy`. The proxy either redirects users to the
hub (for login and managing servers), or to their own single-user
servers. Thus, as long as the proxy stays running, access to existing
servers continues, even if the hub itself restarts or goes down.
When you first configure the hub, you may not even realize this
because the proxy is automatically managed by the hub. This is great
for getting started and even most use, but everytime you restart the
hub, all user connections also get restarted. But it's also simple to
run the proxy as a service separate from the hub, so that you are free
to reconfigure the hub while only interrupting users who are currently
actively starting the hub.
The default JupyterHub proxy is
[configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy),
and that page has some docs. If you are using a different proxy, such
as Traefik, these instructions are probably not relevant to you.
## Configuration options
`c.JupyterHub.cleanup_servers = False` should be set, which tells the
hub to not stop servers when the hub restarts (this is useful even if
you don't run the proxy separately).
`c.ConfigurableHTTPProxy.should_start = False` should be set, which
tells the hub that the proxy should not be started (because you start
it yourself).
`c.ConfigurableHTTPProxy.auth_token = "CONFIGPROXY_AUTH_TOKEN"` should be set to a
token for authenticating communication with the proxy.
`c.ConfigurableHTTPProxy.api_url = 'http://localhost:8001'` should be
set to the URL which the hub uses to connect *to the proxy's API*.
## Proxy configuration
You need to configure a service to start the proxy. An example
command line for this is `configurable-http-proxy --ip=127.0.0.1
--port=8000 --api-ip=127.0.0.1 --api-port=8001
--default-target=http://localhost:8081
--error-target=http://localhost:8081/hub/error`. (Details for how to
do this is out of scope for this tutorial - for example it might be a
systemd service on within another docker cotainer). The proxy has no
configuration files, all configuration is via the command line and
environment variables.
`--api-ip` and `--api-port` (which tells the proxy where to listen) should match the hub's `ConfigurableHTTPProxy.api_url`.
`--ip`, `-port`, and other options configure the *user* connections to the proxy.
`--default-target` and `--error-target` should point to the hub, and used when users navigate to the proxy originally.
You must define the environment variable `CONFIGPROXY_AUTH_TOKEN` to
match the token given to `c.ConfigurableHTTPProxy.auth_token`.
You should check the [configurable-http-proxy
options](https://github.com/jupyterhub/configurable-http-proxy) to see
what other options are needed, for example SSL options. Note that
these are configured in the hub if the hub is starting the proxy - you
need to move the options to here.
## Docker image
You can use [jupyterhub configurable-http-proxy docker
image](https://hub.docker.com/r/jupyterhub/configurable-http-proxy/)
to run the proxy.
## See also
* [jupyterhub configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy)

View File

@@ -15,7 +15,7 @@ This section provides the following information about Services:
## Definition of a Service
When working with JupyterHub, a **Service** is defined as a process that interacts
with the Hub's REST API. A Service may perform a specific or
with the Hub's REST API. A Service may perform a specific
action or task. For example, the following tasks can each be a unique Service:
- shutting down individuals' single user notebook servers that have been idle
@@ -93,7 +93,7 @@ c.JupyterHub.services = [
{
'name': 'cull-idle',
'admin': True,
'command': ['python', '/path/to/cull-idle.py', '--timeout']
'command': [sys.executable, '/path/to/cull-idle.py', '--timeout']
}
]
```
@@ -178,7 +178,13 @@ When you run a service that has a url, it will be accessible under a
your service to route proxied requests properly, it must take
`JUPYTERHUB_SERVICE_PREFIX` into account when routing requests. For example, a
web service would normally service its root handler at `'/'`, but the proxied
service would need to serve `JUPYTERHUB_SERVICE_PREFIX + '/'`.
service would need to serve `JUPYTERHUB_SERVICE_PREFIX`.
Note that `JUPYTERHUB_SERVICE_PREFIX` will contain a trailing slash. This must
be taken into consideration when creating the service routes. If you include an
extra slash you might get unexpected behavior. For example if your service has a
`/foo` endpoint, the route would be `JUPYTERHUB_SERVICE_PREFIX + foo`, and
`/foo/bar` would be `JUPYTERHUB_SERVICE_PREFIX + foo/bar`.
## Hub Authentication and Services
@@ -198,10 +204,10 @@ which implements the requests to the Hub.
To use HubAuth, you must set the `.api_token`, either programmatically when constructing the class,
or via the `JUPYTERHUB_API_TOKEN` environment variable.
Most of the logic for authentication implementation is found in the
[`HubAuth.user_for_cookie`](services.auth.html#jupyterhub.services.auth.HubAuth.user_for_cookie)
and in the
[`HubAuth.user_for_token`](services.auth.html#jupyterhub.services.auth.HubAuth.user_for_token)
Most of the logic for authentication implementation is found in the
[`HubAuth.user_for_cookie`][HubAuth.user_for_cookie]
and in the
[`HubAuth.user_for_token`][HubAuth.user_for_token]
methods, which makes a request of the Hub, and returns:
- None, if no user could be identified, or
@@ -269,7 +275,7 @@ def authenticated(f):
return decorated
@app.route(prefix + '/')
@app.route(prefix)
@authenticated
def whoami(user):
return Response(
@@ -353,14 +359,16 @@ and taking note of the following process:
```
An example of using an Externally-Managed Service and authentication is
in [nbviewer README]_ section on securing the notebook viewer,
in [nbviewer README][nbviewer example] section on securing the notebook viewer,
and an example of its configuration is found [here](https://github.com/jupyter/nbviewer/blob/master/nbviewer/providers/base.py#L94).
nbviewer can also be run as a Hub-Managed Service as described [nbviewer README]_
nbviewer can also be run as a Hub-Managed Service as described [nbviewer README][nbviewer example]
section on securing the notebook viewer.
[requests]: http://docs.python-requests.org/en/master/
[services_auth]: ../api/services.auth.html
[HubAuth]: ../api/services.auth.html#jupyterhub.services.auth.HubAuth
[HubAuth.user_for_cookie]: ../api/services.auth.html#jupyterhub.services.auth.HubAuth.user_for_cookie
[HubAuth.user_for_token]: ../api/services.auth.html#jupyterhub.services.auth.HubAuth.user_for_token
[HubAuthenticated]: ../api/services.auth.html#jupyterhub.services.auth.HubAuthenticated
[nbviewer example]: https://github.com/jupyter/nbviewer#securing-the-notebook-viewer

View File

@@ -10,6 +10,7 @@ and a custom Spawner needs to be able to take three actions:
## Examples
Custom Spawners for JupyterHub can be found on the [JupyterHub wiki](https://github.com/jupyterhub/jupyterhub/wiki/Spawners).
Some examples include:
@@ -24,6 +25,8 @@ Some examples include:
run without being root, by spawning an intermediate process via `sudo`
- [BatchSpawner](https://github.com/jupyterhub/batchspawner) for spawning remote
servers using batch systems
- [YarnSpawner](https://github.com/jcrist/yarnspawner) for spawning notebook
servers in YARN containers on a Hadoop cluster
- [RemoteSpawner](https://github.com/zonca/remotespawner) to spawn notebooks
and a remote server and tunnel the port via SSH
@@ -46,7 +49,16 @@ Most `Spawner.start` functions will look similar to this example:
def start(self):
self.ip = '127.0.0.1'
self.port = random_port()
yield self._actually_start_server_somehow()
# get environment variables,
# several of which are required for configuring the single-user server
env = self.get_env()
cmd = []
# get jupyterhub command to run,
# typically ['jupyterhub-singleuser']
cmd.extend(self.cmd)
cmd.extend(self.get_args())
yield self._actually_start_server_somehow(cmd, env)
return (self.ip, self.port)
```
@@ -165,14 +177,53 @@ When `Spawner.start` is called, this dictionary is accessible as `self.user_opti
If you are interested in building a custom spawner, you can read [this tutorial](http://jupyterhub-tutorial.readthedocs.io/en/latest/spawners.html).
### Registering custom Spawners via entry points
As of JupyterHub 1.0, custom Spawners can register themselves via
the `jupyterhub.spawners` entry point metadata.
To do this, in your `setup.py` add:
```python
setup(
...
entry_points={
'jupyterhub.spawners': [
'myservice = mypackage:MySpawner',
],
},
)
```
If you have added this metadata to your package,
users can select your authenticator with the configuration:
```python
c.JupyterHub.spawner_class = 'myservice'
```
instead of the full
```python
c.JupyterHub.spawner_class = 'mypackage:MySpawner'
```
previously required.
Additionally, configurable attributes for your spawner will
appear in jupyterhub help output and auto-generated configuration files
via `jupyterhub --generate-config`.
## Spawners, resource limits, and guarantees (Optional)
Some spawners of the single-user notebook servers allow setting limits or
guarantees on resources, such as CPU and memory. To provide a consistent
experience for sysadmins and users, we provide a standard way to set and
discover these resource limits and guarantees, such as for memory and CPU. For
the limits and guarantees to be useful, the spawner must implement support for
them.
discover these resource limits and guarantees, such as for memory and CPU.
For the limits and guarantees to be useful, **the spawner must implement
support for them**. For example, LocalProcessSpawner, the default
spawner, does not support limits and guarantees. One of the spawners
that supports limits and guarantees is the `systemdspawner`.
### Memory Limits & Guarantees
@@ -184,14 +235,14 @@ allocate. Attempting to use more memory than this limit will cause errors. The
single-user notebook server can discover its own memory limit by looking at
the environment variable `MEM_LIMIT`, which is specified in absolute bytes.
`c.Spawner.mem_guarantee`: Sometimes, a **guarantee** of a *minumum amount of
`c.Spawner.mem_guarantee`: Sometimes, a **guarantee** of a *minimum amount of
memory* is desirable. In this case, you can set `c.Spawner.mem_guarantee` to
to provide a guarantee that at minimum this much memory will always be
available for the single-user notebook server to use. The environment variable
`MEM_GUARANTEE` will also be set in the single-user notebook server.
The spawner's underlying system or cluster is responsible for enforcing these
limits and providing these guarantees. If these values are set to `None`, no
**The spawner's underlying system or cluster is responsible for enforcing these
limits and providing these guarantees.** If these values are set to `None`, no
limits or guarantees are provided, and no environment values are set.
### CPU Limits & Guarantees
@@ -208,6 +259,33 @@ higher priority applications might be taking up CPU.
guarantee for CPU usage. The environment variable `CPU_GUARANTEE` will be set
in the single-user notebook server when a guarantee is being provided.
The spawner's underlying system or cluster is responsible for enforcing these
limits and providing these guarantees. If these values are set to `None`, no
**The spawner's underlying system or cluster is responsible for enforcing these
limits and providing these guarantees.** If these values are set to `None`, no
limits or guarantees are provided, and no environment values are set.
### Encryption
Communication between the `Proxy`, `Hub`, and `Notebook` can be secured by
turning on `internal_ssl` in `jupyterhub_config.py`. For a custom spawner to
utilize these certs, there are two methods of interest on the base `Spawner`
class: `.create_certs` and `.move_certs`.
The first method, `.create_certs` will sign a key-cert pair using an internally
trusted authority for notebooks. During this process, `.create_certs` can
apply `ip` and `dns` name information to the cert via an `alt_names` `kwarg`.
This is used for certificate authentication (verification). Without proper
verification, the `Notebook` will be unable to communicate with the `Hub` and
vice versa when `internal_ssl` is enabled. For example, given a deployment
using the `DockerSpawner` which will start containers with `ips` from the
`docker` subnet pool, the `DockerSpawner` would need to instead choose a
container `ip` prior to starting and pass that to `.create_certs` (TODO: edit).
In general though, this method will not need to be changed and the default
`ip`/`dns` (localhost) info will suffice.
When `.create_certs` is run, it will `.create_certs` in a default, central
location specified by `c.JupyterHub.internal_certs_location`. For `Spawners`
that need access to these certs elsewhere (i.e. on another host altogether),
the `.move_certs` method can be overridden to move the certs appropriately.
Again, using `DockerSpawner` as an example, this would entail moving certs
to a directory that will get mounted into the container this spawner starts.

View File

@@ -28,7 +28,7 @@ by the `jupyterhub` command line program:
- **Single-User Notebook Server** (Python/Tornado): a dedicated,
single-user, Jupyter Notebook server is started for each user on the system
when the user logs in. The object that starts the single-user notebook
servers is called a **Spawner**.
servers is called a **Spawner**.
![JupyterHub subsystems](../images/jhub-parts.png)
@@ -49,14 +49,14 @@ The proxy is the only process that listens on a public interface. The Hub sits
behind the proxy at `/hub`. Single-user servers sit behind the proxy at
`/user/[username]`.
Different **[authenticators](./authenticators.html)** control access
Different **[authenticators](./authenticators.md)** control access
to JupyterHub. The default one (PAM) uses the user accounts on the server where
JupyterHub is running. If you use this, you will need to create a user account
on the system for each user on your team. Using other authenticators, you can
allow users to sign in with e.g. a GitHub account, or with any single-sign-on
system your organization has.
Next, **[spawners](./spawners.html)** control how JupyterHub starts
Next, **[spawners](./spawners.md)** control how JupyterHub starts
the individual notebook server for each user. The default spawner will
start a notebook server on the same machine running under their system username.
The other main option is to start each server in a separate container, often
@@ -66,10 +66,10 @@ using Docker.
When a user accesses JupyterHub, the following events take place:
- Login data is handed to the [Authenticator](./authenticators.html) instance for
- Login data is handed to the [Authenticator](./authenticators.md) instance for
validation
- The Authenticator returns the username if the login information is valid
- A single-user notebook server instance is [spawned](./spawners.html) for the
- A single-user notebook server instance is [spawned](./spawners.md) for the
logged-in user
- When the single-user notebook server starts, the proxy is notified to forward
requests to `/user/[username]/*` to the single-user notebook server.
@@ -111,7 +111,7 @@ working directory:
This file needs to persist so that a **Hub** server restart will avoid
invalidating cookies. Conversely, deleting this file and restarting the server
effectively invalidates all login cookies. The cookie secret file is discussed
in the [Cookie Secret section of the Security Settings document](../getting-started/security-basics.html).
in the [Cookie Secret section of the Security Settings document](../getting-started/security-basics.md).
The location of these files can be specified via configuration settings. It is
recommended that these files be stored in standard UNIX filesystem locations,
@@ -122,9 +122,9 @@ all security and runtime files.
There are two basic extension points for JupyterHub:
- How users are authenticated by [Authenticators](./authenticators.html)
- How users are authenticated by [Authenticators](./authenticators.md)
- How user's single-user notebook server processes are started by
[Spawners](./spawners.html)
[Spawners](./spawners.md)
Each is governed by a customizable class, and JupyterHub ships with basic
defaults for each.

View File

@@ -0,0 +1,93 @@
# Working with templates and UI
The pages of the JupyterHub application are generated from
[Jinja](http://jinja.pocoo.org/) templates. These allow the header, for
example, to be defined once and incorporated into all pages. By providing
your own templates, you can have complete control over JupyterHub's
appearance.
## Custom Templates
JupyterHub will look for custom templates in all of the paths in the
`JupyterHub.template_paths` configuration option, falling back on the
[default templates](https://github.com/jupyterhub/jupyterhub/tree/master/share/jupyterhub/templates)
if no custom template with that name is found. This fallback
behavior is new in version 0.9; previous versions searched only those paths
explicitly included in `template_paths`. You may override as many
or as few templates as you desire.
## Extending Templates
Jinja provides a mechanism to [extend templates](http://jinja.pocoo.org/docs/2.10/templates/#template-inheritance).
A base template can define a `block`, and child templates can replace or
supplement the material in the block. The
[JupyterHub templates](https://github.com/jupyterhub/jupyterhub/tree/master/share/jupyterhub/templates)
make extensive use of blocks, which allows you to customize parts of the
interface easily.
In general, a child template can extend a base template, `page.html`, by beginning with:
```html
{% extends "page.html" %}
```
This works, unless you are trying to extend the default template for the same
file name. Starting in version 0.9, you may refer to the base file with a
`templates/` prefix. Thus, if you are writing a custom `page.html`, start the
file with this block:
```html
{% extends "templates/page.html" %}
```
By defining `block`s with same name as in the base template, child templates
can replace those sections with custom content. The content from the base
template can be included with the `{{ super() }}` directive.
### Example
To add an additional message to the spawn-pending page, below the existing
text about the server starting up, place this content in a file named
`spawn_pending.html` in a directory included in the
`JupyterHub.template_paths` configuration option.
```html
{% extends "templates/spawn_pending.html" %}
{% block message %}
{{ super() }}
<p>Patience is a virtue.</p>
{% endblock %}
```
## Page Announcements
To add announcements to be displayed on a page, you have two options:
- Extend the page templates as described above
- Use configuration variables
### Announcement Configuration Variables
If you set the configuration variable `JupyterHub.template_vars =
{'announcement': 'some_text}`, the given `some_text` will be placed on
the top of all pages. The more specific variables
`announcement_login`, `announcement_spawn`, `announcement_home`, and
`announcement_logout` are more specific and only show on their
respective pages (overriding the global `announcement` variable).
Note that changing these variables require a restart, unlike direct
template extension.
You can get the same effect by extending templates, which allows you
to update the messages without restarting. Set
`c.JupyterHub.template_paths` as mentioned above, and then create a
template (for example, `login.html`) with:
```html
{% extends "templates/login.html" %}
{% set announcement = 'some message' %}
```
Extending `page.html` puts the message on all pages, but note that
extending `page.html` take precedence over an extension of a specific
page (unlike the variable-based approach above).

View File

@@ -1,106 +0,0 @@
# Upgrading JupyterHub and its database
From time to time, you may wish to upgrade JupyterHub to take advantage
of new releases. Much of this process is automated using scripts,
such as those generated by alembic for database upgrades. Before upgrading a
JupyterHub deployment, it's critical to backup your data and configurations
before shutting down the JupyterHub process and server.
## Databases: SQLite (default) or RDBMS (PostgreSQL, MySQL)
The default database for JupyterHub is a [SQLite](https://sqlite.org) database.
We have chosen SQLite as JupyterHub's default for its lightweight simplicity
in certain uses such as testing, small deployments and workshops.
When running a long term deployment or a production system, we recommend using
a traditional RDBMS database, such as [PostgreSQL](https://www.postgresql.org)
or [MySQL](https://www.mysql.com), that supports the SQL `ALTER TABLE`
statement.
For production systems, SQLite has some disadvantages when used with JupyterHub:
- `upgrade-db` may not work, and you may need to start with a fresh database
- `downgrade-db` **will not** work if you want to rollback to an earlier
version, so backup the `jupyterhub.sqlite` file before upgrading
The sqlite documentation provides a helpful page about [when to use sqlite and
where traditional RDBMS may be a better choice](https://sqlite.org/whentouse.html).
## The upgrade process
Five fundamental process steps are needed when upgrading JupyterHub and its
database:
1. Backup JupyterHub database
2. Backup JupyterHub configuration file
3. Shutdown the Hub
4. Upgrade JupyterHub
5. Upgrade the database using run `jupyterhub upgrade-db`
Let's take a closer look at each step in the upgrade process as well as some
additional information about JupyterHub databases.
### Backup JupyterHub database
To prevent unintended loss of data or configuration information, you should
back up the JupyterHub database (the default SQLite database or a RDBMS
database using PostgreSQL, MySQL, or others supported by SQLAlchemy):
- If using the default SQLite database, back up the `jupyterhub.sqlite`
database.
- If using an RDBMS database such as PostgreSQL, MySQL, or other supported by
SQLAlchemy, back up the JupyterHub database.
Losing the Hub database is often not a big deal. Information that resides only
in the Hub database includes:
- active login tokens (user cookies, service tokens)
- users added via GitHub UI, instead of config files
- info about running servers
If the following conditions are true, you should be fine clearing the Hub
database and starting over:
- users specified in config file
- user servers are stopped during upgrade
- don't mind causing users to login again after upgrade
### Backup JupyterHub configuration file
Additionally, backing up your configuration file, `jupyterhub_config.py`, to
a secure location.
### Shutdown JupyterHub
Prior to shutting down JupyterHub, you should notify the Hub users of the
scheduled downtime. This gives users the opportunity to finish any outstanding
work in process.
Next, shutdown the JupyterHub service.
### Upgrade JupyterHub
Follow directions that correspond to your package manager, `pip` or `conda`,
for the new JupyterHub release. These directions will guide you to the
specific command. In general, `pip install -U jupyterhub` or
`conda upgrade jupyterhub`
### Upgrade JupyterHub databases
To run the upgrade process for JupyterHub databases, enter:
```
jupyterhub upgrade-db
```
## Upgrade checklist
1. Backup JupyterHub database:
- `jupyterhub.sqlite` when using the default sqlite database
- Your JupyterHub database when using an RDBMS
2. Backup JupyterHub configuration file: `jupyterhub_config.py`
3. Shutdown the Hub
4. Upgrade JupyterHub
- `pip install -U jupyterhub` when using `pip`
- `conda upgrade jupyterhub` when using `conda`
5. Upgrade the database using run `jupyterhub upgrade-db`

View File

@@ -0,0 +1,255 @@
# JupyterHub URL scheme
This document describes how JupyterHub routes requests.
This does not include the [REST API](./rest.md) urls.
In general, all URLs can be prefixed with `c.JupyterHub.base_url` to
run the whole JupyterHub application on a prefix.
All authenticated handlers redirect to `/hub/login` to login users
prior to being redirected back to the originating page.
The returned request should preserve all query parameters.
## `/`
The top-level request is always a simple redirect to `/hub/`,
to be handled by the default JupyterHub handler.
In general, all requests to `/anything` that do not start with `/hub/`
but are routed to the Hub, will be redirected to `/hub/anything` before being handled by the Hub.
## `/hub/`
This is an authenticated URL.
This handler redirects users to the default URL of the application,
which defaults to the user's default server.
That is, it redirects to `/hub/spawn` if the user's server is not running,
or the server itself (`/user/:name`) if the server is running.
This default url behavior can be customized in two ways:
To redirect users to the JupyterHub home page (`/hub/home`)
instead of spawning their server,
set `redirect_to_server` to False:
```python
c.JupyterHub.redirect_to_server = False
```
This might be useful if you have a Hub where you expect
users to be managing multiple server configurations
and automatic spawning is not desirable.
Second, you can customise the landing page to any page you like,
such as a custom service you have deployed e.g. with course information:
```python
c.JupyterHub.default_url = '/services/my-landing-service'
```
## `/hub/home`
![The Hub home page with named servers enabled](../images/named-servers-home.png)
By default, the Hub home page has just one or two buttons
for starting and stopping the user's server.
If named servers are enabled, there will be some additional
tools for management of named servers.
*Version added: 1.0* named server UI is new in 1.0.
## `/hub/login`
This is the JupyterHub login page.
If you have a form-based username+password login,
such as the default PAMAuthenticator,
this page will render the login form.
![A login form](../images/login-form.png)
If login is handled by an external service,
e.g. with OAuth, this page will have a button,
declaring "Login with ..." which users can click
to login with the chosen service.
![A login redirect button](../images/login-button.png)
If you want to skip the user-interaction to initiate logging in
via the button, you can set
```python
c.Authenticator.auto_login = True
```
This can be useful when the user is "already logged in" via some mechanism,
but a handshake via redirects is necessary to complete the authentication with JupyterHub.
## `/hub/logout`
Visiting `/hub/logout` clears cookies from the current browser.
Note that **logging out does not stop a user's server(s)** by default.
If you would like to shutdown user servers on logout,
you can enable this behavior with:
```python
c.JupyterHub.shutdown_on_logout = True
```
Be careful with this setting because logging out one browser
does not mean the user is no longer actively using their server from another machine.
## `/user/:username[/:servername]`
If a user's server is running, this URL is handled by the user's given server,
not the Hub.
The username is the first part and, if using named servers,
the server name is the second part.
If the user's server is *not* running, this will be redirected to `/hub/user/:username/...`
## `/hub/user/:username[/:servername]`
This URL indicates a request for a user server that is not running
(because `/user/...` would have been handled by the notebook server
if the specified server were running).
Handling this URL is the most complicated condition in JupyterHub,
because there can be many states:
1. server is not active
a. user matches
b. user doesn't match
2. server is ready
3. server is pending, but not ready
If the server is pending spawn,
the browser will be redirected to `/hub/spawn-pending/:username/:servername`
to see a progress page while waiting for the server to be ready.
If the server is not active at all,
a page will be served with a link to `/hub/spawn/:username/:servername`.
Following that link will launch the requested server.
The HTTP status will be 503 in this case because a request has been made for a server that is not running.
If the server is ready, it is assumed that the proxy has not yet registered the route.
Some checks are performed and a delay is added before redirecting back to `/user/:username/:servername/...`.
If something is really wrong, this can result in a redirect loop.
Visiting this page will never result in triggering the spawn of servers
without additional user action (i.e. clicking the link on the page)
![Visiting a URL for a server that's not running](../images/not-running.png)
*Version changed: 1.0*
Prior to 1.0, this URL itself was responsible for spawning servers,
and served the progress page if it was pending,
redirected to running servers, and
This was useful because it made sure that requested servers were restarted after they stopped,
but could also be harmful because unused servers would continuously be restarted if e.g.
an idle JupyterLab frontend were open pointed at it,
which constantly makes polling requests.
### Special handling of API requests
Requests to `/user/:username[/:servername]/api/...` are assumed to be
from applications connected to stopped servers.
These are failed with 503 and an informative JSON error message
indicating how to spawn the server.
This is meant to help applications such as JupyterLab
that are connected to a server that has stopped.
*Version changed: 1.0*
JupyterHub 0.9 failed these API requests with status 404,
but 1.0 uses 503.
## `/user-redirect/...`
This URL is for sharing a URL that will redirect a user
to a path on their own default server.
This is useful when users have the same file at the same URL on their servers,
and you want a single link to give to any user that will open that file on their server.
e.g. a link to `/user-redirect/notebooks/Index.ipynb`
will send user `hortense` to `/user/hortense/notebooks/Index.ipynb`
**DO NOT** share links to your own server with other users.
This will not work in general,
unless you grant those users access to your server.
**Contributions welcome:** The JupyterLab "shareable link" should share this link
when run with JupyterHub, but it does not.
See [jupyterlab-hub](https://github.com/jupyterhub/jupyterlab-hub)
where this should probably be done and
[this issue in JupyterLab](https://github.com/jupyterlab/jupyterlab/issues/5388)
that is intended to make it possible.
## Spawning
### `/hub/spawn[/:username[/:servername]]`
Requesting `/hub/spawn` will spawn the default server for the current user.
If `username` and optionally `servername` are specified,
then the specified server for the specified user will be spawned.
Once spawn has been requested,
the browser is redirected to `/hub/spawn-pending/...`.
If `Spawner.options_form` is used,
this will render a form,
and a POST request will trigger the actual spawn and redirect.
![The spawn form](../images/spawn-form.png)
*Version added: 1.0*
1.0 adds the ability to specify username and servername.
Prior to 1.0, only `/hub/spawn` was recognized for the default server.
*Version changed: 1.0*
Prior to 1.0, this page redirected back to `/hub/user/:username`,
which was responsible for triggering spawn and rendering progress, etc.
### `/hub/spawn-pending[/:username[/:servername]]`
![The spawn pending page](../images/spawn-pending.png)
*Version added: 1.0* this URL is new in JupyterHub 1.0.
This page renders the progress view for the given spawn request.
Once the server is ready,
the browser is redirected to the running server at `/user/:username/:servername/...`.
If this page is requested at any time after the specified server is ready,
the browser will be redirected to the running server.
Requesting this page will never trigger any side effects.
If the server is not running (e.g. because the spawn has failed),
the spawn failure message (if applicable) will be displayed,
and the page will show a link back to `/hub/spawn/...`.
## `/hub/token`
![The token management page](../images/token-page.png)
On this page, users can manage their JupyterHub API tokens.
They can revoke access and request new tokens for writing scripts
against the [JupyterHub REST API](./rest.md).
## `/hub/admin`
![The admin panel](../images/named-servers-admin.png)
Administrators can take various administrative actions from this page:
1. add/remove users
2. grant admin privileges
3. start/stop user servers
4. shutdown JupyterHub itself

View File

@@ -99,6 +99,23 @@ single-user server, and not the environment(s) in which the user's kernel(s)
may run. Installing additional packages in the kernel environment does not
pose additional risk to the web application's security.
### Encrypt internal connections with SSL/TLS
By default, all communication on the server, between the proxy, hub, and single
-user notebooks is performed unencrypted. Setting the `internal_ssl` flag in
`jupyterhub_config.py` secures the aforementioned routes. Turning this
feature on does require that the enabled `Spawner` can use the certificates
generated by the `Hub` (the default `LocalProcessSpawner` can, for instance).
It is also important to note that this encryption **does not** (yet) cover the
`zmq tcp` sockets between the Notebook client and kernel. While users cannot
submit arbitrary commands to another user's kernel, they can bind to these
sockets and listen. When serving untrusted users, this eavesdropping can be
mitigated by setting `KernelManager.transport` to `ipc`. This applies standard
Unix permissions to the communication sockets thereby restricting
communication to the socket owner. The `internal_ssl` option will eventually
extend to securing the `tcp` sockets as well.
## Security audits
We recommend that you do periodic reviews of your deployment's security. It's
@@ -110,3 +127,11 @@ A handy website for testing your deployment is
[configurable-http-proxy]: https://github.com/jupyterhub/configurable-http-proxy
## Vulnerability reporting
If you believe youve found a security vulnerability in JupyterHub, or any
Jupyter project, please report it to
[security@ipython.org](mailto:security@iypthon.org). If you prefer to encrypt
your security reports, you can use [this PGP public
key](https://jupyter-notebook.readthedocs.io/en/stable/_downloads/ipython_security.asc).

View File

@@ -166,7 +166,7 @@ startup
statsd
stdin
stdout
stoppped
stopped
subclasses
subcommand
subdomain
@@ -210,4 +210,4 @@ Wildcards
willingc
wordlist
Workflow
workflow
workflow

View File

@@ -9,6 +9,7 @@ problem and how to resolve it.
- sudospawner fails to run
- What is the default behavior when none of the lists (admin, whitelist,
group whitelist) are set?
- JupyterHub Docker container not accessible at localhost
[*Errors*](#errors)
- 500 error after spawning my single-user server
@@ -63,6 +64,17 @@ this to a particular set of users, and the admin_users lets you specify who
among them may use the admin interface (not necessary, unless you need to do
things like inspect other users' servers, or modify the userlist at runtime).
### JupyterHub Docker container not accessible at localhost
Even though the command to start your Docker container exposes port 8000
(`docker run -p 8000:8000 -d --name jupyterhub jupyterhub/jupyterhub jupyterhub`),
it is possible that the IP address itself is not accessible/visible. As a result
when you try http://localhost:8000 in your browser, you are unable to connect
even though the container is running properly. One workaround is to explicitly
tell Jupyterhub to start at `0.0.0.0` which is visible to everyone. Try this
command:
`docker run -p 8000:8000 -d --name jupyterhub jupyterhub/jupyterhub jupyterhub --ip 0.0.0.0 --port 8000`
## Errors
@@ -89,7 +101,7 @@ check if the cookie corresponds to the right user. This request is logged.
If everything is working, the response logged will be similar to this:
```
200 GET /hub/api/authorizations/cookie/jupyter-hub-token-name/[secret] (@10.0.1.4) 6.10ms
200 GET /hub/api/authorizations/cookie/jupyterhub-token-name/[secret] (@10.0.1.4) 6.10ms
```
You should see a similar 200 message, as above, in the Hub log when you first
@@ -99,7 +111,7 @@ may mean that your single-user notebook server isn't connecting to your Hub.
If you see 403 (forbidden) like this, it's a token problem:
```
403 GET /hub/api/authorizations/cookie/jupyter-hub-token-name/[secret] (@10.0.1.4) 4.14ms
403 GET /hub/api/authorizations/cookie/jupyterhub-token-name/[secret] (@10.0.1.4) 4.14ms
```
Check the logs of the single-user notebook server, which may have more detailed
@@ -192,7 +204,7 @@ from there instead of the internet.
For instance, you can install JupyterHub with pip and configurable-http-proxy
with npmbox:
pip wheel jupyterhub
python3 -m pip wheel jupyterhub
npmbox configurable-http-proxy
### I want access to the whole filesystem, but still default users to their home directory
@@ -224,7 +236,7 @@ then you can change the default URL to `/lab`.
For instance:
pip install jupyterlab
python3 -m pip install jupyterlab
jupyter serverextension enable --py jupyterlab --sys-prefix
The important thing is that jupyterlab is installed and enabled in the

View File

@@ -1,14 +0,0 @@
Tutorials
=========
This section provides links to documentation that helps a user do a specific
task.
* :doc:`upgrade-dot-eight`
* `Zero to JupyterHub with Kubernetes <https://zero-to-jupyterhub.readthedocs.io/en/latest/>`_
.. toctree::
:maxdepth: 1
:hidden:
upgrade-dot-eight

View File

@@ -1,93 +0,0 @@
.. upgrade-dot-eight:
Upgrading to JupyterHub version 0.8
===================================
This document will assist you in upgrading an existing JupyterHub deployment
from version 0.7 to version 0.8.
Upgrade checklist
-----------------
0. Review the release notes. Review any deprecated features and pay attention
to any backwards incompatible changes
1. Backup JupyterHub database:
- ``jupyterhub.sqlite`` when using the default sqlite database
- Your JupyterHub database when using an RDBMS
2. Backup the existing JupyterHub configuration file: ``jupyterhub_config.py``
3. Shutdown the Hub
4. Upgrade JupyterHub
- ``pip install -U jupyterhub`` when using ``pip``
- ``conda upgrade jupyterhub`` when using ``conda``
5. Upgrade the database using run ```jupyterhub upgrade-db``
6. Update the JupyterHub configuration file ``jupyterhub_config.py``
Backup JupyterHub database
--------------------------
To prevent unintended loss of data or configuration information, you should
back up the JupyterHub database (the default SQLite database or a RDBMS
database using PostgreSQL, MySQL, or others supported by SQLAlchemy):
- If using the default SQLite database, back up the ``jupyterhub.sqlite``
database.
- If using an RDBMS database such as PostgreSQL, MySQL, or other supported by
SQLAlchemy, back up the JupyterHub database.
.. note::
Losing the Hub database is often not a big deal. Information that resides only
in the Hub database includes:
- active login tokens (user cookies, service tokens)
- users added via GitHub UI, instead of config files
- info about running servers
If the following conditions are true, you should be fine clearing the Hub
database and starting over:
- users specified in config file
- user servers are stopped during upgrade
- don't mind causing users to login again after upgrade
Backup JupyterHub configuration file
------------------------------------
Backup up your configuration file, ``jupyterhub_config.py``, to a secure
location.
Shutdown JupyterHub
-------------------
- Prior to shutting down JupyterHub, you should notify the Hub users of the
scheduled downtime.
- Shutdown the JupyterHub service.
Upgrade JupyterHub
------------------
Follow directions that correspond to your package manager, ``pip`` or ``conda``,
for the new JupyterHub release:
- ``pip install -U jupyterhub`` for ``pip``
- ``conda upgrade jupyterhub`` for ``conda``
Upgrade the proxy, authenticator, or spawner if needed.
Upgrade JupyterHub database
---------------------------
To run the upgrade process for JupyterHub databases, enter::
jupyterhub upgrade-db
Update the JupyterHub configuration file
----------------------------------------
Create a new JupyterHub configuration file or edit a copy of the existing
file ``jupyterhub_config.py``.
Start JupyterHub
----------------
Start JupyterHub with the same command that you used before the upgrade.

View File

@@ -1,20 +1,25 @@
"""autodoc extension for configurable traits"""
from traitlets import TraitType, Undefined
from sphinx.domains.python import PyClassmember
from sphinx.ext.autodoc import ClassDocumenter, AttributeDocumenter
from sphinx.ext.autodoc import AttributeDocumenter
from sphinx.ext.autodoc import ClassDocumenter
from traitlets import TraitType
from traitlets import Undefined
class ConfigurableDocumenter(ClassDocumenter):
"""Specialized Documenter subclass for traits with config=True"""
objtype = 'configurable'
directivetype = 'class'
def get_object_members(self, want_all):
"""Add traits with .tag(config=True) to members list"""
check, members = super().get_object_members(want_all)
get_traits = self.object.class_own_traits if self.options.inherited_members \
else self.object.class_traits
get_traits = (
self.object.class_own_traits
if self.options.inherited_members
else self.object.class_traits
)
trait_members = []
for name, trait in sorted(get_traits(config=True).items()):
# put help in __doc__ where autodoc will look for it
@@ -33,20 +38,18 @@ class TraitDocumenter(AttributeDocumenter):
def can_document_member(cls, member, membername, isattr, parent):
return isinstance(member, TraitType)
def format_name(self):
return 'config c.' + super().format_name()
def add_directive_header(self, sig):
default = self.object.get_default_value()
if default is Undefined:
default_s = ''
else:
default_s = repr(default)
sig = ' = {}({})'.format(
self.object.__class__.__name__,
default_s,
self.options.annotation = 'c.{name} = {trait}({default})'.format(
name=self.format_name(),
trait=self.object.__class__.__name__,
default=default_s,
)
return super().add_directive_header(sig)
super().add_directive_header(sig)
def setup(app):

View File

@@ -25,8 +25,11 @@ Another use would be to copy initial content, such as tutorial files or referenc
You can define your own bootstrap process by implementing a `pre_spawn_hook` on any spawner.
The Spawner itself is passed as parameter to your hook and you can easily get the contextual information out of the spawning process.
If you implement a hook, make sure that it is *idempotent*. It will be executed every time
a notebook server is spawned to the user. That means you should somehow
Similarly, there may be cases where you would like to clean up after a spawner stops.
You may implement a `post_stop_hook` that is always executed after the spawner stops.
If you implement a hook, make sure that it is *idempotent*. It will be executed every time
a notebook server is spawned to the user. That means you should somehow
ensure that things which should run only once are not running again and again.
For example, before you create a directory, check if it exists.
@@ -56,7 +59,31 @@ def create_dir_hook(spawner):
c.Spawner.pre_spawn_hook = create_dir_hook
```
### Example #2 - Run a shell script
### Example #2 - Run `mkhomedir_helper`
Many Linux distributions provide a script that is responsible for user homedir bootstrapping: `/sbin/mkhomedir_helper`. To make use of it, you can use
```python
def create_dir_hook(spawner):
username = spawner.user.name
if not os.path.exists(os.path.join('/volumes/jupyterhub', username)):
subprocess.call(["sudo", "/sbin/mkhomedir_helper", spawner.user.name])
# attach the hook function to the spawner
c.Spawner.pre_spawn_hook = create_dir_hook
```
and make sure to add
```
jupyterhub ALL = (root) NOPASSWD: /sbin/mkhomedir_helper
```
in a new file in `/etc/sudoers.d`, or simply in `/etc/sudoers`.
All new home directories will be created from `/etc/skel`, so make sure to place any custom homedir-contents in there.
### Example #3 - Run a shell script
You can specify a plain ole' shell script (or any other executable) to be run
by the bootstrap process.
@@ -91,7 +118,7 @@ Here's an example on what you could do in your shell script. See also
# - The first parameter for the Bootstrap Script is the USER.
USER=$1
if ["$USER" == ""]; then
if [ "$USER" == "" ]; then
exit 1
fi
# ----------------------------------------------------------------------------
@@ -127,4 +154,4 @@ else
fi
exit 0
```
```

View File

@@ -6,7 +6,7 @@
# - The first parameter for the Bootstrap Script is the USER.
USER=$1
if ["$USER" == ""]; then
if [ "$USER" == "" ]; then
exit 1
fi
# ----------------------------------------------------------------------------

View File

@@ -1,26 +1,44 @@
# Example for a Spawner.pre_spawn_hook
# create a directory for the user before the spawner starts
"""
Example for a Spawner.pre_spawn_hook
create a directory for the user before the spawner starts
"""
# pylint: disable=import-error
import os
import shutil
from jupyter_client.localinterfaces import public_ips
def create_dir_hook(spawner):
username = spawner.user.name # get the username
""" Create directory """
username = spawner.user.name # get the username
volume_path = os.path.join('/volumes/jupyterhub', username)
if not os.path.exists(volume_path):
os.mkdir(volume_path, 0o755)
# now do whatever you think your user needs
# ...
# attach the hook function to the spawner
def clean_dir_hook(spawner):
""" Delete directory """
username = spawner.user.name # get the username
temp_path = os.path.join('/volumes/jupyterhub', username, 'temp')
if os.path.exists(temp_path) and os.path.isdir(temp_path):
shutil.rmtree(temp_path)
# attach the hook functions to the spawner
# pylint: disable=undefined-variable
c.Spawner.pre_spawn_hook = create_dir_hook
c.Spawner.post_stop_hook = clean_dir_hook
# Use the DockerSpawner to serve your users' notebooks
c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner'
from jupyter_client.localinterfaces import public_ips
c.JupyterHub.hub_ip = public_ips()[0]
c.DockerSpawner.hub_ip_connect = public_ips()[0]
c.DockerSpawner.container_ip = "0.0.0.0"
# You can now mount the volume to the docker container as we've
# made sure the directory exists
c.DockerSpawner.volumes = { '/volumes/jupyterhub/{username}/': '/home/jovyan/work' }
# pylint: disable=bad-whitespace
c.DockerSpawner.volumes = {'/volumes/jupyterhub/{username}/': '/home/jovyan/work'}

View File

@@ -15,7 +15,7 @@ c.JupyterHub.services = [
{
'name': 'cull-idle',
'admin': True,
'command': 'python cull_idle_servers.py --timeout=3600'.split(),
'command': [sys.executable, 'cull_idle_servers.py', '--timeout=3600'],
}
]
```
@@ -36,6 +36,6 @@ Generate an API token and store it in the `JUPYTERHUB_API_TOKEN` environment
variable. Run `cull_idle_servers.py` manually.
```bash
export JUPYTERHUB_API_TOKEN=`jupyterhub token`
python cull_idle_servers.py [--timeout=900] [--url=http://127.0.0.1:8081/hub/api]
export JUPYTERHUB_API_TOKEN=$(jupyterhub token)
python3 cull_idle_servers.py [--timeout=900] [--url=http://127.0.0.1:8081/hub/api]
```

371
examples/cull-idle/cull_idle_servers.py Normal file → Executable file
View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
"""script to monitor and cull idle single-user servers
Caveats:
@@ -16,102 +16,366 @@ You can run this as a service managed by JupyterHub with this in your config::
{
'name': 'cull-idle',
'admin': True,
'command': 'python cull_idle_servers.py --timeout=3600'.split(),
'command': [sys.executable, 'cull_idle_servers.py', '--timeout=3600'],
}
]
Or run it manually by generating an API token and storing it in `JUPYTERHUB_API_TOKEN`:
export JUPYTERHUB_API_TOKEN=`jupyterhub token`
python cull_idle_servers.py [--timeout=900] [--url=http://127.0.0.1:8081/hub/api]
"""
export JUPYTERHUB_API_TOKEN=$(jupyterhub token)
python3 cull_idle_servers.py [--timeout=900] [--url=http://127.0.0.1:8081/hub/api]
import datetime
This script uses the same ``--timeout`` and ``--max-age`` values for
culling users and users' servers. If you want a different value for
users and servers, you should add this script to the services list
twice, just with different ``name``s, different values, and one with
the ``--cull-users`` option.
"""
import json
import os
from datetime import datetime
from datetime import timezone
from functools import partial
from dateutil.parser import parse as parse_date
try:
from urllib.parse import quote
except ImportError:
from urllib import quote
from tornado.gen import coroutine
import dateutil.parser
from tornado.gen import coroutine, multi
from tornado.locks import Semaphore
from tornado.log import app_log
from tornado.httpclient import AsyncHTTPClient, HTTPRequest
from tornado.ioloop import IOLoop, PeriodicCallback
from tornado.options import define, options, parse_command_line
def parse_date(date_string):
"""Parse a timestamp
If it doesn't have a timezone, assume utc
Returned datetime object will always be timezone-aware
"""
dt = dateutil.parser.parse(date_string)
if not dt.tzinfo:
# assume naïve timestamps are UTC
dt = dt.replace(tzinfo=timezone.utc)
return dt
def format_td(td):
"""
Nicely format a timedelta object
as HH:MM:SS
"""
if td is None:
return "unknown"
if isinstance(td, str):
return td
seconds = int(td.total_seconds())
h = seconds // 3600
seconds = seconds % 3600
m = seconds // 60
seconds = seconds % 60
return "{h:02}:{m:02}:{seconds:02}".format(h=h, m=m, seconds=seconds)
@coroutine
def cull_idle(url, api_token, timeout, cull_users=False):
def cull_idle(
url, api_token, inactive_limit, cull_users=False, max_age=0, concurrency=10
):
"""Shutdown idle single-user servers
If cull_users, inactive *users* will be deleted as well.
"""
auth_header = {
'Authorization': 'token %s' % api_token
}
req = HTTPRequest(url=url + '/users',
headers=auth_header,
)
now = datetime.datetime.utcnow()
cull_limit = now - datetime.timedelta(seconds=timeout)
auth_header = {'Authorization': 'token %s' % api_token}
req = HTTPRequest(url=url + '/users', headers=auth_header)
now = datetime.now(timezone.utc)
client = AsyncHTTPClient()
resp = yield client.fetch(req)
if concurrency:
semaphore = Semaphore(concurrency)
@coroutine
def fetch(req):
"""client.fetch wrapped in a semaphore to limit concurrency"""
yield semaphore.acquire()
try:
return (yield client.fetch(req))
finally:
yield semaphore.release()
else:
fetch = client.fetch
resp = yield fetch(req)
users = json.loads(resp.body.decode('utf8', 'replace'))
futures = []
@coroutine
def cull_one(user, last_activity):
"""cull one user"""
def handle_server(user, server_name, server):
"""Handle (maybe) culling a single server
# shutdown server first. Hub doesn't allow deleting users with running servers.
if user['server']:
app_log.info("Culling server for %s (inactive since %s)", user['name'], last_activity)
req = HTTPRequest(url=url + '/users/%s/server' % user['name'],
method='DELETE',
headers=auth_header,
Returns True if server is now stopped (user removable),
False otherwise.
"""
log_name = user['name']
if server_name:
log_name = '%s/%s' % (user['name'], server_name)
if server.get('pending'):
app_log.warning(
"Not culling server %s with pending %s", log_name, server['pending']
)
yield client.fetch(req)
if cull_users:
app_log.info("Culling user %s (inactive since %s)", user['name'], last_activity)
req = HTTPRequest(url=url + '/users/%s' % user['name'],
method='DELETE',
headers=auth_header,
return False
# jupyterhub < 0.9 defined 'server.url' once the server was ready
# as an *implicit* signal that the server was ready.
# 0.9 adds a dedicated, explicit 'ready' field.
# By current (0.9) definitions, servers that have no pending
# events and are not ready shouldn't be in the model,
# but let's check just to be safe.
if not server.get('ready', bool(server['url'])):
app_log.warning(
"Not culling not-ready not-pending server %s: %s", log_name, server
)
yield client.fetch(req)
return False
if server.get('started'):
age = now - parse_date(server['started'])
else:
# started may be undefined on jupyterhub < 0.9
age = None
# check last activity
# last_activity can be None in 0.9
if server['last_activity']:
inactive = now - parse_date(server['last_activity'])
else:
# no activity yet, use start date
# last_activity may be None with jupyterhub 0.9,
# which introduces the 'started' field which is never None
# for running servers
inactive = age
should_cull = (
inactive is not None and inactive.total_seconds() >= inactive_limit
)
if should_cull:
app_log.info(
"Culling server %s (inactive for %s)", log_name, format_td(inactive)
)
if max_age and not should_cull:
# only check started if max_age is specified
# so that we can still be compatible with jupyterhub 0.8
# which doesn't define the 'started' field
if age is not None and age.total_seconds() >= max_age:
app_log.info(
"Culling server %s (age: %s, inactive for %s)",
log_name,
format_td(age),
format_td(inactive),
)
should_cull = True
if not should_cull:
app_log.debug(
"Not culling server %s (age: %s, inactive for %s)",
log_name,
format_td(age),
format_td(inactive),
)
return False
if server_name:
# culling a named server
delete_url = url + "/users/%s/servers/%s" % (
quote(user['name']),
quote(server['name']),
)
else:
delete_url = url + '/users/%s/server' % quote(user['name'])
req = HTTPRequest(url=delete_url, method='DELETE', headers=auth_header)
resp = yield fetch(req)
if resp.code == 202:
app_log.warning("Server %s is slow to stop", log_name)
# return False to prevent culling user with pending shutdowns
return False
return True
@coroutine
def handle_user(user):
"""Handle one user.
Create a list of their servers, and async exec them. Wait for
that to be done, and if all servers are stopped, possibly cull
the user.
"""
# shutdown servers first.
# Hub doesn't allow deleting users with running servers.
# jupyterhub 0.9 always provides a 'servers' model.
# 0.8 only does this when named servers are enabled.
if 'servers' in user:
servers = user['servers']
else:
# jupyterhub < 0.9 without named servers enabled.
# create servers dict with one entry for the default server
# from the user model.
# only if the server is running.
servers = {}
if user['server']:
servers[''] = {
'last_activity': user['last_activity'],
'pending': user['pending'],
'url': user['server'],
}
server_futures = [
handle_server(user, server_name, server)
for server_name, server in servers.items()
]
results = yield multi(server_futures)
if not cull_users:
return
# some servers are still running, cannot cull users
still_alive = len(results) - sum(results)
if still_alive:
app_log.debug(
"Not culling user %s with %i servers still alive",
user['name'],
still_alive,
)
return False
should_cull = False
if user.get('created'):
age = now - parse_date(user['created'])
else:
# created may be undefined on jupyterhub < 0.9
age = None
# check last activity
# last_activity can be None in 0.9
if user['last_activity']:
inactive = now - parse_date(user['last_activity'])
else:
# no activity yet, use start date
# last_activity may be None with jupyterhub 0.9,
# which introduces the 'created' field which is never None
inactive = age
should_cull = (
inactive is not None and inactive.total_seconds() >= inactive_limit
)
if should_cull:
app_log.info("Culling user %s (inactive for %s)", user['name'], inactive)
if max_age and not should_cull:
# only check created if max_age is specified
# so that we can still be compatible with jupyterhub 0.8
# which doesn't define the 'started' field
if age is not None and age.total_seconds() >= max_age:
app_log.info(
"Culling user %s (age: %s, inactive for %s)",
user['name'],
format_td(age),
format_td(inactive),
)
should_cull = True
if not should_cull:
app_log.debug(
"Not culling user %s (created: %s, last active: %s)",
user['name'],
format_td(age),
format_td(inactive),
)
return False
req = HTTPRequest(
url=url + '/users/%s' % user['name'], method='DELETE', headers=auth_header
)
yield fetch(req)
return True
for user in users:
if not user['server'] and not cull_users:
# server not running and not culling users, nothing to do
continue
last_activity = parse_date(user['last_activity'])
if last_activity < cull_limit:
futures.append((user['name'], cull_one(user, last_activity)))
else:
app_log.debug("Not culling %s (active since %s)", user['name'], last_activity)
futures.append((user['name'], handle_user(user)))
for (name, f) in futures:
yield f
app_log.debug("Finished culling %s", name)
try:
result = yield f
except Exception:
app_log.exception("Error processing %s", name)
else:
if result:
app_log.debug("Finished culling %s", name)
if __name__ == '__main__':
define('url', default=os.environ.get('JUPYTERHUB_API_URL'), help="The JupyterHub API URL")
define(
'url',
default=os.environ.get('JUPYTERHUB_API_URL'),
help="The JupyterHub API URL",
)
define('timeout', default=600, help="The idle timeout (in seconds)")
define('cull_every', default=0, help="The interval (in seconds) for checking for idle servers to cull")
define('cull_users', default=False,
define(
'cull_every',
default=0,
help="The interval (in seconds) for checking for idle servers to cull",
)
define(
'max_age',
default=0,
help="The maximum age (in seconds) of servers that should be culled even if they are active",
)
define(
'cull_users',
default=False,
help="""Cull users in addition to servers.
This is for use in temporary-user cases such as tmpnb.""",
)
define(
'concurrency',
default=10,
help="""Limit the number of concurrent requests made to the Hub.
Deleting a lot of users at the same time can slow down the Hub,
so limit the number of API requests we have outstanding at any given time.
""",
)
parse_command_line()
if not options.cull_every:
options.cull_every = options.timeout // 2
api_token = os.environ['JUPYTERHUB_API_TOKEN']
try:
AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient")
except ImportError as e:
app_log.warning(
"Could not load pycurl: %s\n"
"pycurl is recommended if you have a large number of users.",
e,
)
loop = IOLoop.current()
cull = lambda : cull_idle(options.url, api_token, options.timeout, options.cull_users)
# run once before scheduling periodic call
loop.run_sync(cull)
cull = partial(
cull_idle,
url=options.url,
api_token=api_token,
inactive_limit=options.timeout,
cull_users=options.cull_users,
max_age=options.max_age,
concurrency=options.concurrency,
)
# schedule first cull immediately
# because PeriodicCallback doesn't start until the end of the first interval
loop.add_callback(cull)
# schedule periodic cull
pc = PeriodicCallback(cull, 1e3 * options.cull_every)
pc.start()
@@ -119,4 +383,3 @@ if __name__ == '__main__':
loop.start()
except KeyboardInterrupt:
pass

Some files were not shown because too many files have changed in this diff Show More