133 Commits

Author SHA1 Message Date
Erik Sundell
8e68745e38 Bump to 2.0.0b1 2024-09-30 15:27:34 +02:00
Erik Sundell
a49f0a6889 Merge pull request #1000 from consideRatio/pr/changelog-2.0.0b1
Add changelog for 2.0.0b1
2024-09-30 15:25:48 +02:00
Min RK
bcfb426b5c Merge pull request #1003 from manics/upgrade-1 2024-09-29 08:26:31 +02:00
Simon Li
59fb7fb8a2 Test upgrade from 1.* 2024-09-28 15:38:32 +01:00
Erik Sundell
95b54414ca Add changelog for 2.0.0b1 2024-09-28 11:14:55 +02:00
Erik Sundell
eb5c0e4758 Merge pull request #1001 from consideRatio/pr/traefik-bump
Update traefik from 2.10.1 to 3.1.4
2024-09-28 10:59:38 +02:00
Erik Sundell
92e317d41f Merge pull request #1002 from consideRatio/pr/lower-bound-user-env
Bump the requirements-user-env-extras.txt lower version bounds
2024-09-28 10:59:00 +02:00
Erik Sundell
812be54635 Bump the requirements-user-env-extras.txt lower version bounds
By declaring these lower bounds, it becomes a bit easier to help others
using tljh, because we can know that fresh installations of tljh should
have at least these versions of software etc.
2024-09-28 10:49:03 +02:00
Erik Sundell
3ddc1e8d59 refactor: exctract calling traefik setup from ensure_jupyterhub_package func 2024-09-26 22:32:26 +02:00
Erik Sundell
a059d6ffbb Update traefik from 2.10.1 to 3.1.4 2024-09-26 16:29:51 +02:00
Erik Sundell
856c647e88 Merge pull request #999 from consideRatio/pr/bump-miniforge
Update to install miniforge 24.7.1-2 from 24.7.1-0
2024-09-26 13:42:04 +02:00
Erik Sundell
a89021c49e Update to install miniforge 24.7.1-2 from 24.7.1-0 2024-09-26 13:32:07 +02:00
Erik Sundell
a98299c629 Merge pull request #998 from consideRatio/pr/bump-drop
Drop ubuntu 20.04, require py39, traefik-proxy v2, and ldapauthenticator v2
2024-09-26 13:25:45 +02:00
Erik Sundell
e8602fc4a1 Update lower bounds on dependencies for tljh 2 beta release 2024-09-26 13:16:17 +02:00
Erik Sundell
0de2db365a pre-commit: run hooks 2024-09-20 22:25:46 +02:00
Erik Sundell
436c81f26d tljh package: require python 3.9+ 2024-09-20 22:25:46 +02:00
Erik Sundell
363dc45b52 tljh package: bump to traefik-proxy v2 2024-09-20 22:25:46 +02:00
Erik Sundell
1a9f3d65a4 tljh package: bump to ruamel.yaml==0.18.* 2024-09-20 22:25:46 +02:00
Erik Sundell
3f55ac2912 Drop support for ubuntu 20.04 and Python 3.8 2024-09-20 22:25:46 +02:00
Erik Sundell
92465ade36 Bump to 2.0.0.dev 2024-09-20 22:25:46 +02:00
Erik Sundell
2282e61894 Merge pull request #997 from consideRatio/main
ci: cache pip only when no container is used
2024-09-20 22:14:40 +02:00
Erik Sundell
94a16d6ddd ci: cache pip only when no container is used 2024-09-20 21:57:55 +02:00
Erik Sundell
7be7eb4968 Merge pull request #994 from minrk/consolidate_lock
consolidate lock file handling
2024-09-17 00:55:46 +02:00
Min RK
0c322774e2 filelock is a dependency of tljh 2024-09-05 12:03:26 +02:00
Min RK
13c8946d8c consolidate lock file handling
- adds config_file_lock context manager to re-use
- moves filelock import to module level
- fixes exit codes, stderr messages
2024-09-05 11:58:51 +02:00
Erik Sundell
f7118edf48 Merge pull request #993 from consideRatio/pr/unit-test-24.04
ci: run unit tests in ubuntu-24.04 github actions environment as well
2024-09-05 11:16:36 +02:00
Min RK
b034fc6713 fix calls to assert_called_with
it's not `assert ...called_with`
2024-09-05 11:07:22 +02:00
Erik Sundell
3321a50f31 ci: run unit tests in ubuntu-24.04 github actions environment as well 2024-09-04 16:16:31 +02:00
Erik Sundell
73f8833f0a Merge pull request #992 from minrk/oauth17
update oauthenticator to 17
2024-09-04 16:16:17 +02:00
Erik Sundell
5834f14b83 Merge pull request #942 from yuvipanda/conda-channels
Add the ability to define conda channels in plugins via `tljh_extra_user_conda_channels`
2024-09-04 16:14:10 +02:00
Erik Sundell
9111b73cee tests: reduce a test to only one package per conda channel 2024-09-04 16:04:29 +02:00
Min RK
3bd739e8dc update oauthenticator to 17
azuread no longer has its own dependencies
2024-09-04 13:25:10 +02:00
Erik Sundell
7a491e403c Merge branch 'main' into conda-channels 2024-09-04 13:16:58 +02:00
Erik Sundell
50c1b5f894 Merge pull request #990 from minrk/miniforge
Update base user environment to miniforge 24.7.1-0 (Python 3.12)
2024-09-04 13:08:17 +02:00
Min RK
5c8cb5bb26 Merge pull request #976 from jrdnbradford/add-conf-lockfile
Add TLJH config lockfile
2024-09-04 03:56:12 -07:00
Erik Sundell
8490ef2949 Update lower version bound on filelock, and add comment 2024-09-04 12:21:18 +02:00
Erik Sundell
5172ceb4f9 Update base user environment to miniforge 24.7.1-0 (Python 3.12) 2024-09-04 12:10:29 +02:00
Min RK
634956c33e Update base user environment to miniforge 24.5.0-0 (Python 3.12)
mambaforge is deprecated, mamba has been in miniforge for some time now
2024-08-27 10:54:07 +02:00
Simon Li
5278351eb1 Merge pull request #989 from minrk/hub5
jupyterhub 5
2024-08-25 15:09:36 +01:00
Simon Li
22e08a458b Merge pull request #988 from minrk/fix-launch
fix `-m` invocation of jupyterhub
2024-08-25 14:59:47 +01:00
Min RK
dcbb37688e doc adding users with github, since they won't be allowed by default 2024-08-23 11:40:07 +02:00
Min RK
c492c176bc allow all by default with default FirstUseAuthenticator
doesn't take effect if there's any auth config
2024-08-23 11:40:07 +02:00
Min RK
65c5d78ea5 jupyterhub 5
require 5.1.0 for security fixes
2024-08-23 10:02:58 +02:00
Min RK
5abf657bdf fix -m invocation of jupyterhub
-m jupyterhub.app results in multiple JupyterHub classes being defined
and jupyterhub.app.JupyterHub never being instantiated
2024-08-23 08:32:24 +02:00
Min RK
c49fada1c8 Merge pull request #985 from jupyterhub/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2024-08-06 08:59:46 +02:00
pre-commit-ci[bot]
708bbec2a4 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/asottile/pyupgrade: v3.16.0 → v3.17.0](https://github.com/asottile/pyupgrade/compare/v3.16.0...v3.17.0)
- [github.com/psf/black: 24.4.2 → 24.8.0](https://github.com/psf/black/compare/24.4.2...24.8.0)
- [github.com/pycqa/flake8: 7.1.0 → 7.1.1](https://github.com/pycqa/flake8/compare/7.1.0...7.1.1)
2024-08-05 23:07:01 +00:00
Min RK
729a3ceb28 Merge pull request #984 from jupyterhub/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2024-07-02 09:09:38 +02:00
pre-commit-ci[bot]
9c7427923d [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/asottile/pyupgrade: v3.15.2 → v3.16.0](https://github.com/asottile/pyupgrade/compare/v3.15.2...v3.16.0)
- [github.com/pycqa/flake8: 7.0.0 → 7.1.0](https://github.com/pycqa/flake8/compare/7.0.0...7.1.0)
2024-07-02 00:12:39 +00:00
Yuvi Panda
bcc64e0d8b Merge pull request #983 from josedaudi/patch-1
Added missing details on how to add custom domain from manual HTTPS  configuration
2024-06-10 19:13:05 -07:00
Joseph Daudi
a5f966927f Added missing details on how to add custom domain form manual HTTPS configuration 2024-05-23 21:49:15 +03:00
Erik Sundell
d0fb92eda5 Merge pull request #981 from jupyterhub/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2024-05-07 07:39:17 +02:00
pre-commit-ci[bot]
52478abb65 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 24.3.0 → 24.4.2](https://github.com/psf/black/compare/24.3.0...24.4.2)
- [github.com/pre-commit/pre-commit-hooks: v4.5.0 → v4.6.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.5.0...v4.6.0)
2024-05-06 22:03:37 +00:00
Jordan Bradford
96ac0d3538 Add filelock to dev-requirements 2024-04-06 11:03:24 -04:00
Jordan Bradford
13ed32b499 Add lockfile to integration tests 2024-04-06 10:51:51 -04:00
Jordan Bradford
bdbb3adbbc Add config lockfile 2024-04-06 10:49:07 -04:00
Erik Sundell
2b29bd9f0a Merge pull request #975 from consideRatio/pr/fix-tests
tests: fix to catch test failure earlier when they really happen
2024-04-04 22:53:32 +02:00
Erik Sundell
8fd41cc77a tests: strengthen tests to fail earlier on issues 2024-04-04 22:39:33 +02:00
Erik Sundell
7e39e993da Merge pull request #962 from jrdnbradford/validate-config-yaml
Validate tljh specific config
2024-04-04 07:45:42 +02:00
Jordan Bradford
5469e21e74 Fix removal of https.enabled 2024-04-03 16:19:45 -04:00
Jordan Bradford
38a01e8406 Use default true for validate 2024-04-03 16:09:18 -04:00
Jordan
9bcfa70326 Update tljh/config.py
Co-authored-by: Erik Sundell <erik.i.sundell@gmail.com>
2024-04-03 16:05:16 -04:00
Jordan Bradford
7474b876f1 Remove unneeded validate code 2024-04-03 16:04:29 -04:00
Jordan
5ae31ce169 Update tljh/config.py
Co-authored-by: Erik Sundell <erik.i.sundell@gmail.com>
2024-04-03 16:03:14 -04:00
Jordan
b94a281ff8 Update tljh/config.py
Co-authored-by: Erik Sundell <erik.i.sundell@gmail.com>
2024-04-03 16:03:05 -04:00
Jordan
67dd3c8abe Update tljh/config.py
Co-authored-by: Erik Sundell <erik.i.sundell@gmail.com>
2024-04-03 16:02:55 -04:00
Jordan Bradford
c578a7bec0 Update step name 2024-04-03 14:10:16 -04:00
Jordan Bradford
51f8470535 Fix unit tests with pip 2024-04-03 14:05:32 -04:00
Jordan Bradford
196208ae58 Remove argparse.BooleanOptionalAction for Python 3.8 compatibility 2024-04-03 13:30:32 -04:00
Erik Sundell
242dca4376 Merge pull request #973 from jupyterhub/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2024-04-02 09:54:01 +02:00
pre-commit-ci[bot]
5169301a0a [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/asottile/pyupgrade: v3.15.0 → v3.15.2](https://github.com/asottile/pyupgrade/compare/v3.15.0...v3.15.2)
- [github.com/PyCQA/autoflake: v2.2.1 → v2.3.1](https://github.com/PyCQA/autoflake/compare/v2.2.1...v2.3.1)
- [github.com/psf/black: 24.1.1 → 24.3.0](https://github.com/psf/black/compare/24.1.1...24.3.0)
2024-04-01 22:10:42 +00:00
Jordan Bradford
4ddd798928 Add docstring from config_schema.py 2024-03-27 12:08:28 -04:00
Jordan Bradford
f921acc183 Bump ubuntu image to 22.04 2024-03-20 15:09:07 -04:00
Jordan Bradford
46e4045568 Update test_proxy tests 2024-03-20 15:08:21 -04:00
Jordan Bradford
743f729902 Update set_config_value tests 2024-03-20 14:45:36 -04:00
Jordan Bradford
48fe440372 Add --[no-]validation flag for tljh-config 2024-03-20 14:36:49 -04:00
Min RK
8348d4ad96 Merge pull request #968 from consideRatio/pr/fix-tests
Re-install conda/mamba for every tljh upgrade (doesn't imply upgrade)
2024-03-18 09:26:46 +01:00
Erik Sundell
579b7eb5ba Merge pull request #969 from davidalber/fix-install-typo
Fix typo and replace word
2024-03-09 19:38:05 +01:00
Erik Sundell
0248785aed Merge pull request #970 from davidalber/reword-sg-sentence
Reword documentation sentence
2024-03-09 19:37:18 +01:00
David Alber
beed70060c Reword sentence 2024-03-01 12:09:17 -08:00
David Alber
d9a0a5fc7a Fix typo and replace word: "disitnguishing" --> "distinctive"
The typo is of "distinguishing", but "distinctive" makes more sense
to me in the context of the sentence it is in.
2024-03-01 11:50:47 -08:00
Erik Sundell
4e397bc687 Re-install conda/mamba for every tljh upgrade (doesn't imply upgrade) 2024-02-26 16:44:12 +01:00
Erik Sundell
7d8a84860f tests: show mamba list for the user environment before/after upgrade
This can help us check if a package has been installed from PyPI via
pip, or from conda-forge or other channel via conda/mamba.
2024-02-26 16:44:12 +01:00
Erik Sundell
2fe9912333 tests: test pip install plugin with no-dependency package
This is a simplification to help ensure we don't run into issues like
below because requests gets installed via pip.

```
RemoveError: 'requests' is a dependency of conda and cannot be removed from conda's operating environment.
```
2024-02-26 16:44:12 +01:00
Erik Sundell
02c3d7539b Merge pull request #967 from consideRatio/pr/ci-add-tests
ci: add tests for debian 12 and ubuntu 24.04
2024-02-26 16:43:57 +01:00
Erik Sundell
10ba571bde ci: add test for ubuntu 24.04 2024-02-26 16:24:29 +01:00
Erik Sundell
7fa4e2bcec ci: add test for debian 12 2024-02-24 21:47:36 +01:00
Erik Sundell
2faf0d3a5f Merge pull request #963 from jupyterhub/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2024-02-06 08:26:09 +01:00
pre-commit-ci[bot]
b35851f2b7 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2024-02-05 20:29:33 +00:00
pre-commit-ci[bot]
9755938d7d [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 23.12.1 → 24.1.1](https://github.com/psf/black/compare/23.12.1...24.1.1)
- [github.com/pycqa/flake8: 6.1.0 → 7.0.0](https://github.com/pycqa/flake8/compare/6.1.0...7.0.0)
2024-02-05 20:27:06 +00:00
Jordan Bradford
1f7d6d1c55 Add doc string for validate_config 2024-02-05 14:52:31 -05:00
Jordan Bradford
9060267458 Add LetsEncrypt.staging; run pre-commit 2024-02-03 13:39:17 -05:00
Jordan Bradford
4912cffe65 Fix parse_value 2024-02-03 13:27:58 -05:00
Jordan Bradford
d0c9aa263a Remove TLS required properties 2024-02-03 13:18:39 -05:00
Jordan Bradford
fa363658df Update schema based on values in configurer.py 2024-02-03 13:08:27 -05:00
Jordan Bradford
166eba6735 Switch from JSON to py 2024-02-03 12:48:31 -05:00
Jordan Bradford
5a0de137d2 Do not allow additionalProperties for Users 2024-02-02 23:22:57 -05:00
Jordan Bradford
929536de7b Run pre-commit hooks 2024-02-02 23:07:38 -05:00
Jordan Bradford
ef5c6c56b7 print human readable error message 2024-02-02 23:06:31 -05:00
Jordan Bradford
fb01dea5e4 Working schema path 2024-02-02 23:01:36 -05:00
Jordan Bradford
78d4b7fbc4 Test config setup 2024-02-02 22:52:16 -05:00
Jordan Bradford
d292457803 Initial config setup 2024-02-02 21:51:23 -05:00
Erik Sundell
6dd2ee812a Merge pull request #961 from jupyterhub/dependabot/github_actions/actions/cache-4
build(deps): bump actions/cache from 3 to 4
2024-02-01 10:57:26 +01:00
Erik Sundell
641a02ed07 Merge pull request #960 from jupyterhub/dependabot/github_actions/codecov/codecov-action-4
build(deps): bump codecov/codecov-action from 3 to 4
2024-02-01 10:25:36 +01:00
dependabot[bot]
1c9301e4d7 build(deps): bump actions/cache from 3 to 4
Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-01 05:26:48 +00:00
dependabot[bot]
723c4e756d build(deps): bump codecov/codecov-action from 3 to 4
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-01 05:26:45 +00:00
Erik Sundell
eeae5f06be Merge pull request #959 from consideRatio/pr/add-azure-ad-dependency
Add missing oauthenticator dependency for AzureADOAuthenticator
2024-01-25 07:05:32 +01:00
Erik Sundell
4abf3f003f Add optional oauthenticator dependency for AzureAD 2024-01-04 02:28:28 +01:00
Erik Sundell
3da9743640 Merge pull request #956 from jupyterhub/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2024-01-04 01:06:36 +01:00
Erik Sundell
aec331b114 Merge pull request #958 from jupyterhub/dependabot/github_actions/actions/setup-python-5
build(deps): bump actions/setup-python from 4 to 5
2024-01-04 00:51:38 +01:00
pre-commit-ci[bot]
0f5a0ccbe0 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/pycqa/isort: 5.12.0 → 5.13.2](https://github.com/pycqa/isort/compare/5.12.0...5.13.2)
- [github.com/psf/black: 23.10.1 → 23.12.1](https://github.com/psf/black/compare/23.10.1...23.12.1)
- [github.com/pre-commit/mirrors-prettier: v3.0.3 → v4.0.0-alpha.8](https://github.com/pre-commit/mirrors-prettier/compare/v3.0.3...v4.0.0-alpha.8)
2024-01-01 20:22:48 +00:00
dependabot[bot]
f1c7e2d90f build(deps): bump actions/setup-python from 4 to 5
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-01 05:51:55 +00:00
Min RK
5cb6b69020 Merge pull request #949 from pdebuyl/patch-1
Fix URL syntax in nativeauth.md
2023-11-22 14:25:22 +01:00
Min RK
7faf997c7b Merge pull request #953 from jupyterhub/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2023-11-07 10:03:44 +01:00
pre-commit-ci[bot]
79134e3a2f [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/asottile/pyupgrade: v3.14.0 → v3.15.0](https://github.com/asottile/pyupgrade/compare/v3.14.0...v3.15.0)
- [github.com/psf/black: 23.9.1 → 23.10.1](https://github.com/psf/black/compare/23.9.1...23.10.1)
- [github.com/pre-commit/pre-commit-hooks: v4.4.0 → v4.5.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.4.0...v4.5.0)
2023-11-06 20:28:01 +00:00
Pierre de Buyl
e869633871 Fix URL syntax in nativeauth.md 2023-10-27 11:56:22 +02:00
Erik Sundell
793f6237b4 Merge pull request #945 from jupyterhub/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2023-10-03 12:42:12 +02:00
pre-commit-ci[bot]
caab46e08a [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/asottile/pyupgrade: v3.10.1 → v3.14.0](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.14.0)
- [github.com/psf/black: 23.7.0 → 23.9.1](https://github.com/psf/black/compare/23.7.0...23.9.1)
2023-10-03 10:35:43 +00:00
Erik Sundell
dcb91d4e6a Merge pull request #943 from jupyterhub/dependabot/github_actions/actions/checkout-4
build(deps): bump actions/checkout from 3 to 4
2023-10-01 10:12:17 +02:00
dependabot[bot]
ed6ff645c2 build(deps): bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-01 05:45:52 +00:00
YuviPanda
291c096a17 Fix argument name of channels 2023-09-29 14:47:53 -07:00
pre-commit-ci[bot]
eafc10e82a [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2023-09-29 21:39:30 +00:00
YuviPanda
58a679f584 Fix how channels are added to -c command 2023-09-29 14:39:12 -07:00
pre-commit-ci[bot]
9bde7e4680 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2023-09-29 21:35:50 +00:00
YuviPanda
6359bf498c Merge remote-tracking branch 'upstream/main' into conda-channels 2023-09-29 14:27:25 -07:00
Yuvi Panda
44bdaf2fa4 Merge pull request #939 from jupyterhub/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2023-09-29 14:19:34 -07:00
pre-commit-ci[bot]
1d1aefd518 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/PyCQA/autoflake: v2.2.0 → v2.2.1](https://github.com/PyCQA/autoflake/compare/v2.2.0...v2.2.1)
- [github.com/pre-commit/mirrors-prettier: v3.0.0 → v3.0.3](https://github.com/pre-commit/mirrors-prettier/compare/v3.0.0...v3.0.3)
2023-09-05 08:11:29 +00:00
Min RK
542cf4de6b Merge pull request #935 from schwebke/main
adapt install documentation for new /lab default interface
2023-08-14 11:32:15 +02:00
Kai G. Schwebke
46b49c819c adapt install documentation for new /lab default interface 2023-08-12 08:47:23 +02:00
Erik Sundell
c7507fd799 Bump to 1.0.1.dev 2023-08-11 14:46:52 +02:00
Will Dampier
ff1f612d10 adding content to docs 2022-09-02 14:47:41 -04:00
Will Dampier
58181c9671 adjusted integration test to call new hook 2022-09-02 14:47:25 -04:00
Will Dampier
8d1033393c adding tljh_extra_user_conda_channels hook to the hooks and installer 2022-09-02 14:46:55 -04:00
Will Dampier
fc8f70463c Adding the ability to define conda channels 2022-09-02 14:10:43 -04:00
49 changed files with 583 additions and 197 deletions

View File

@@ -10,7 +10,7 @@ GIT_REPO_PATH = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
TEST_IMAGE_NAME = "test-systemd"
@functools.lru_cache()
@functools.lru_cache
def _get_container_runtime_cli():
runtimes = ["docker", "podman"]
for runtime in runtimes:
@@ -167,15 +167,23 @@ def run_test(
command = f"python3 /srv/src/bootstrap/bootstrap.py --version={upgrade_from}"
run_command(container_name, command)
# show user environment
command = "/opt/tljh/user/bin/mamba list"
run_command(container_name, command)
command = f"python3 /srv/src/bootstrap/bootstrap.py {' '.join(installer_args)}"
run_command(container_name, command)
# show user environment (again if upgrade)
command = "/opt/tljh/user/bin/mamba list"
run_command(container_name, command)
# Install pkgs from requirements in hub's pip, where
# the bootstrap script installed the others
command = "/opt/tljh/hub/bin/python3 -m pip install -r /srv/src/integration-tests/requirements.txt"
run_command(container_name, command)
# show environment
# show hub environment
command = "/opt/tljh/hub/bin/python3 -m pip freeze"
run_command(container_name, command)

View File

@@ -36,12 +36,15 @@ jobs:
- name: "Debian 11, Py 3.9"
distro_image: "debian:11"
extra_flags: ""
- name: "Ubuntu 20.04, Py 3.8"
distro_image: "ubuntu:20.04"
- name: "Debian 12, Py 3.11"
distro_image: "debian:12"
extra_flags: ""
- name: "Ubuntu 22.04 Py 3.10"
distro_image: "ubuntu:22.04"
extra_flags: ""
- name: "Ubuntu 24.04 Py 3.12"
distro_image: "ubuntu:24.04"
extra_flags: ""
- name: "Ubuntu 22.04, Py 3.10, from main"
distro_image: "ubuntu:22.04"
extra_flags: --upgrade-from=main
@@ -51,10 +54,13 @@ jobs:
- name: "Ubuntu 22.04, Py 3.10, from 0.2.0"
distro_image: "ubuntu:22.04"
extra_flags: --upgrade-from=0.2.0
- name: "Ubuntu 22.04, Py 3.10, from 1.*"
distro_image: "ubuntu:22.04"
extra_flags: --upgrade-from=1
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.10"
@@ -116,10 +122,13 @@ jobs:
distro_image: "ubuntu:22.04"
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.10"
cache: pip
cache-dependency-path: |
integration-tests/requirements.txt
# FIXME: The test_bootstrap.py script has duplicated logic to run build
# and start images and run things in them. This makes tests slower,

View File

@@ -46,40 +46,29 @@ jobs:
- name: "Ubuntu 22.04, Py 3.10"
ubuntu_version: "22.04"
python_version: "3.10"
- name: "Ubuntu 24.04, Py 3.12"
ubuntu_version: "24.04"
python_version: "3.12"
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "${{ matrix.python_version }}"
- name: Install venv, git and setup venv
- name: Install venv, git, pip and setup venv
run: |
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install --yes \
python3-venv \
python3-pip \
bzip2 \
git
python3 -m venv /srv/venv
echo '/srv/venv/bin' >> $GITHUB_PATH
# WARNING: This action loads a cache of pip dependencies based on the
# declared key, and it will save a cache for that key on job
# completion. Make sure to update the key to bust the cache
# properly if you make a change that should influence it.
- name: Load cached Python dependencies
uses: actions/cache@v3
with:
path: /srv/venv/
key: >-
pip-
${{ matrix.runs_on }}-
${{ matrix.ubuntu_version }}-
${{ matrix.python_version }}-
${{ hashFiles('setup.py', 'dev-requirements.txt', '.github/workflows/unit-test.yaml') }}
- name: Install Python dependencies
run: |
pip install -r dev-requirements.txt
@@ -93,4 +82,4 @@ jobs:
run: pytest tests
timeout-minutes: 15
- uses: codecov/codecov-action@v3
- uses: codecov/codecov-action@v4

View File

@@ -11,18 +11,18 @@
repos:
# Autoformat: Python code, syntax patterns are modernized
- repo: https://github.com/asottile/pyupgrade
rev: v3.10.1
rev: v3.17.0
hooks:
- id: pyupgrade
args:
- --py36-plus
# We need the bootstrap.py script to be parsable with Python 3.5, so we
- --py39-plus
# We need the bootstrap.py script to be parsable with Python 3.8, so we
# exclude it from the pyupgrade hook that will apply f-strings etc.
exclude: bootstrap/bootstrap.py
# Autoformat: Python code
- repo: https://github.com/PyCQA/autoflake
rev: v2.2.0
rev: v2.3.1
hooks:
- id: autoflake
# args ref: https://github.com/PyCQA/autoflake#advanced-usage
@@ -31,25 +31,25 @@ repos:
# Autoformat: Python code
- repo: https://github.com/pycqa/isort
rev: 5.12.0
rev: 5.13.2
hooks:
- id: isort
# Autoformat: Python code
- repo: https://github.com/psf/black
rev: 23.7.0
rev: 24.8.0
hooks:
- id: black
# Autoformat: markdown, yaml
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.0.0
rev: v4.0.0-alpha.8
hooks:
- id: prettier
# Misc...
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.6.0
# ref: https://github.com/pre-commit/pre-commit-hooks#hooks-available
hooks:
# Autoformat: Makes sure files end in a newline and only a newline.
@@ -64,7 +64,7 @@ repos:
# Lint: Python code
- repo: https://github.com/pycqa/flake8
rev: "6.1.0"
rev: "7.1.1"
hooks:
- id: flake8

View File

@@ -9,10 +9,10 @@ This script is run as:
Constraints:
- The entire script should be compatible with Python 3.8, which is the default on
Ubuntu 20.04.
- The script should parse in Python 3.6 as we print error messages for using
Ubuntu 18.04 which comes with Python 3.6 by default.
- The entire script should be compatible with Python 3.9, which is the default on
Debian 11.
- The script should parse in Python 3.8 as we print error messages for using
Ubuntu 20.04 which comes with Python 3.8 by default.
- The script must depend only on stdlib modules, as no previous installation
of dependencies can be assumed.
@@ -42,6 +42,7 @@ Command line flags, from "bootstrap.py --help":
can also pass a branch name such as 'main' or a
commit hash.
"""
import logging
import multiprocessing
import os
@@ -209,22 +210,22 @@ def ensure_host_system_can_install_tljh():
Check if TLJH is installable in current host system and exit with a clear
error message otherwise.
"""
# Require Ubuntu 20.04+ or Debian 11+
# Require Ubuntu 22.04+ or Debian 11+
distro = get_os_release_variable("ID")
version = get_os_release_variable("VERSION_ID")
if distro not in ["ubuntu", "debian"]:
print("The Littlest JupyterHub currently supports Ubuntu or Debian Linux only")
sys.exit(1)
elif distro == "ubuntu" and _parse_version(version) < (20, 4):
print("The Littlest JupyterHub requires Ubuntu 20.04 or higher")
elif distro == "ubuntu" and _parse_version(version) < (22, 4):
print("The Littlest JupyterHub requires Ubuntu 22.04 or higher")
sys.exit(1)
elif distro == "debian" and _parse_version(version) < (11,):
print("The Littlest JupyterHub requires Debian 11 or higher")
sys.exit(1)
# Require Python 3.8+
if sys.version_info < (3, 8):
print(f"bootstrap.py must be run with at least Python 3.8, found {sys.version}")
# Require Python 3.9+
if sys.version_info < (3, 9):
print(f"bootstrap.py must be run with at least Python 3.9, found {sys.version}")
sys.exit(1)
# Require systemd (systemctl is a part of systemd)

View File

@@ -89,6 +89,7 @@ If so, you can tell your deployment to use these files:
sudo tljh-config set https.enabled true
sudo tljh-config set https.tls.key /etc/mycerts/mydomain.key
sudo tljh-config set https.tls.cert /etc/mycerts/mydomain.cert
sudo tljh-config add-item https.tls.domains yourhub.yourdomain.edu
```
Once you have loaded this, your config should look like:
@@ -103,6 +104,8 @@ https:
tls:
key: /etc/mycerts/mydomain.key
cert: /etc/mycerts/mydomain.cert
domains:
- yourhub.yourdomain.edu
```
Finally, you can reload the proxy to load the new configuration:

View File

@@ -23,7 +23,7 @@ PrivateDevices=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
Environment=TLJH_INSTALL_PREFIX=/opt/tljh
ExecStart=/opt/tljh/hub/bin/python3 -m jupyterhub.app -f jupyterhub_config.py --upgrade-db
ExecStart=/opt/tljh/hub/bin/python3 -m jupyterhub -f jupyterhub_config.py --upgrade-db
[Install]
WantedBy=multi-user.target

View File

@@ -149,9 +149,10 @@ If it is not provided as array, there is an easy fix. Just add these lines to
your `awscognito.py`:
```python
def claim_groups_key_func(user_data_resp_json):
return [user_data_resp_json['custom:department']]
def groups_key_func(auth_state):
return [auth_state['oauth_user']['custom:department']]
c.GenericOAuthenticator.claim_groups_key = claim_groups_key_func
c.GenericOAuthenticator.manage_groups = True
c.GenericOAuthenticator.auth_state_groups_key = groups_key_func
c.GenericOAuthenticator.allowed_groups = ["AA BB CC", "AA BB DD"]
```

View File

@@ -91,10 +91,16 @@ For more information on `tljh-config`, see [](/topic/tljh-config).
4. Tell your JupyterHub to _use_ the GitHub OAuthenticator for authentication:
```
sudo tljh-config set auth.type oauthenticator.github.GitHubOAuthenticator
sudo tljh-config set auth.type github
```
5. Restart your JupyterHub so that new users see these changes:
5. Tell JupyterHub which users to allow, if you haven't already:
```
sudo tljh-config add-item users.allowed good-user_1
```
6. Restart your JupyterHub so that new users see these changes:
```
sudo tljh-config reload

View File

@@ -42,4 +42,4 @@ tljh-config reload
## Optional features
More optional features are available on the `authenticator documentation <https://native-authenticator.readthedocs.io/en/latest/>`
More optional features are available on the [authenticator documentation](https://native-authenticator.readthedocs.io/en/latest/)

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -1,11 +1,10 @@
Most administration & configuration of the JupyterHub can be done from the
web UI directly. Let's add a few users who can log in!
1. Open the **Control Panel** by clicking the control panel button on the top
right of your JupyterHub.
1. In the File menu select the entry for the **Hub Control Panel**.
```{image} ../images/control-panel-button.png
:alt: Control panel button in notebook, top right
```{image} ../images/control-panel-menu.png
:alt: Hub Control panel entry in lab File menu
```
2. In the control panel, open the **Admin** link in the top left.

View File

@@ -139,10 +139,10 @@ Let's create the server on which we can run JupyterHub.
SSH to connect (port 22).
If you have never used your Amazon account before, you'll have to select
**Create a new security group**. You should give it a disitnguishing name
**Create a new security group**. You should give it a distinctive name
under **Security group name**
such as `ssh_web` for future reference. If you have, one from before you can
select it and adjust it to have the rules you need, if you prefer.
such as `ssh_web` for future reference. If you already have a security group,
you can select it and adjust it to have the rules you need, if you prefer.
The rules will default to include `SSH`. Leave that there, and then click on
the **Add Rule** button. Under **Type** for the new rule, change the field

View File

@@ -2,6 +2,129 @@
# Changelog
## 2.0
### 2.0.0b1 - 2024-09-30
This release bundles with the latest available software from the JupyterHub
ecosystem.
For instructions on how to make an upgrade, see [](howto-admin-upgrade-tljh).
#### Breaking changes
- JupyterHub 4.\* has been upgraded to >=5.1.0,<6
- Refer to the [JupyterHub changelog] for details and pay attention to the
entries for JupyterHub version 5.0.0.
- OAuthenticator 16.0.4 has been upgraded to >=17.0.0,<18
- If you are using an OAuthenticator based authenticator class
(GitHubOAuthenticator, GoogleOAuthenticator, ...), refer to the
[OAuthenticator changelog] for details and pay attention to the entries for
JupyterHub version 17.0.0.
- LDAPAuthenticator 1.3.2 has been upgraded to >=2.0.0,<3
- If you are using this authenticator class, refer to the [LDAPAuthenticator
changelog] for details and pay attention to the entries for
LDAPAuthenticator version 2.0.0.
- The configured JupyterHub Proxy class `traefik-proxy` and the `traefik` server
controlled by JupyterHub via the proxy class has been upgraded to a new major
version, but no breaking change are expected to be noticed for users.
[oauthenticator changelog]: https://oauthenticator.readthedocs.io/en/latest/reference/changelog.html
[ldapauthenticator changelog]: https://github.com/jupyterhub/ldapauthenticator/blob/HEAD/CHANGELOG.md
#### Notable dependencies updated
A TLJH installation provides a Python environment where the software for
JupyterHub itself runs - _the hub environment_, and a Python environment where
the software of users runs - _the user environment_.
If you are installing TLJH for the first time, the user environment will be
setup initially with Python 3.12 and some other packages described in
[tljh/requirements-user-env-extras.txt].
If you are upgrading to this version of TLJH, the bare minimum is changed in the
user environment. The hub environment's dependencies are on the other hand
always upgraded to the latest version within the specified version range defined
in [tljh/requirements-hub-env.txt] and seen below.
[tljh/requirements-user-env-extras.txt]: https://github.com/jupyterhub/the-littlest-jupyterhub/blob/2.0.0b1/tljh/requirements-user-env-extras.txt
[tljh/requirements-hub-env.txt]: https://github.com/jupyterhub/the-littlest-jupyterhub/blob/2.0.0b1/tljh/requirements-hub-env.txt
The changes in the respective environments between TLJH version 1.0.0 and 2.0.0b1
are summarized below.
| Dependency changes in the _hub environment_ | Version in 1.0.0 | Version in 2.0.0b1 | Changelog link | Note |
| ------------------------------------------------------------------------------ | ---------------- | ------------------ | ---------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| [jupyterhub](https://github.com/jupyterhub/jupyterhub) | >=4.0.2,<5 | >=5.1.0,<6 | [Changelog](https://jupyterhub.readthedocs.io/en/stable/reference/changelog.html) | Running in the `jupyterhub` systemd service |
| [traefik](https://github.com/traefik/traefik) | 2.10.1 | 3.1.4 | [Changelog](https://github.com/traefik/traefik/blob/master/CHANGELOG.md) | Running in the `traefik` systemd service |
| [traefik-proxy](https://github.com/jupyterhub/traefik-proxy) | >=1.1.0,<2 | 2.\* | [Changelog](https://jupyterhub-traefik-proxy.readthedocs.io/en/latest/changelog.html) | Run by jupyterhub, controls `traefik` |
| [systemdspawner](https://github.com/jupyterhub/systemdspawner) | >=1.0.1,<2 | >=1.0.1,<2 | [Changelog](https://github.com/jupyterhub/systemdspawner/blob/master/CHANGELOG.md) | Run by jupyterhub, controls user servers via systemd |
| [jupyterhub-idle-culler](https://github.com/jupyterhub/jupyterhub-idle-culler) | >=1.2.1,<2 | >=1.4.0,<2 | [Changelog](https://github.com/jupyterhub/jupyterhub-idle-culler/blob/main/CHANGELOG.md) | Run by jupyterhub, stops inactivate servers etc. |
| [firstuseauthenticator](https://github.com/jupyterhub/firstuseauthenticator) | >=1.0.0,<2 | 1.1.0,<2 | [Changelog](https://oauthenticator.readthedocs.io/en/latest/reference/changelog.html) | An optional way to authenticate users |
| [tmpauthenticator](https://github.com/jupyterhub/tmpauthenticator) | >=1.0.0,<2 | 1.0.0,<2 | [Changelog](https://github.com/jupyterhub/tmpauthenticator/blob/HEAD/CHANGELOG.md) | An optional way to authenticate users |
| [nativeauthenticator](https://github.com/jupyterhub/nativeauthenticator) | >=1.2.0,<2 | >=1.3.0,<2 | [Changelog](https://github.com/jupyterhub/nativeauthenticator/blob/HEAD/CHANGELOG.md) | An optional way to authenticate users |
| [oauthenticator](https://github.com/jupyterhub/oauthenticator) | >=16.0.4,<17 | >=17.0.0,<18 | [Changelog](https://oauthenticator.readthedocs.io/en/latest/reference/changelog.html) | An optional way to authenticate users |
| [ldapauthenticator](https://github.com/jupyterhub/ldapauthenticator) | >=1.3.2,<2 | ==2.0.0b2 | [Changelog](https://github.com/jupyterhub/ldapauthenticator/blob/HEAD/CHANGELOG.md) | An optional way to authenticate users |
| [pip](https://github.com/pypa/pip) | >=23.1.2 | >=23.1.2 | [Changelog](https://pip.pypa.io/en/stable/news/) | - |
| Dependency changes in the _user environment_ | Version in 1.0.0 | Version in upgrade to 2.0.0b1 | Version in fresh install of 2.0.0b1 | Changelog link | Note |
| -------------------------------------------------------- | ---------------- | ----------------------------- | ----------------------------------- | --------------------------------------------------------------------------------- | ------------------------ |
| [jupyterhub](https://github.com/jupyterhub/jupyterhub) | >=4.0.2,<5 | >=5.1.0,<6 | >=5.1.0,<6 | [Changelog](https://jupyterhub.readthedocs.io/en/stable/reference/changelog.html) | Always upgraded. |
| [pip](https://github.com/pypa/pip) | >=23.1.2 | >=23.1.2 | >=24.2 | [Changelog](https://pip.pypa.io/en/stable/news/) | Only upgraded if needed. |
| [conda](https://docs.conda.io/projects/conda/en/stable/) | >=4.10.0 | >=4.10.0 | ==24.7.1 | [Changelog](https://docs.conda.io/projects/conda/en/stable/release-notes.html) | Only upgraded if needed. |
| [mamba](https://mamba.readthedocs.io/en/latest/) | >=0.16.0 | >=0.16.0 | ==1.5.9 | [Changelog](https://github.com/mamba-org/mamba/blob/main/CHANGELOG.md) | Only upgraded if needed. |
#### New features added
- jupyterhub 5 [#989](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/989) ([@minrk](https://github.com/minrk), [@manics](https://github.com/manics))
- Validate tljh specific config [#962](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/962) ([@jrdnbradford](https://github.com/jrdnbradford), [@consideRatio](https://github.com/consideRatio), [@minrk](https://github.com/minrk))
- Add the ability to define conda channels in plugins via `tljh_extra_user_conda_channels` [#942](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/942) ([@yuvipanda](https://github.com/yuvipanda), [@consideRatio](https://github.com/consideRatio))
#### Bugs fixed
- fix `-m` invocation of jupyterhub [#988](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/988) ([@minrk](https://github.com/minrk), [@manics](https://github.com/manics))
- Re-install conda/mamba for every tljh upgrade (doesn't imply upgrade) [#968](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/968) ([@consideRatio](https://github.com/consideRatio), [@minrk](https://github.com/minrk))
- Add missing oauthenticator dependency for AzureADOAuthenticator [#959](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/959) ([@consideRatio](https://github.com/consideRatio))
#### Maintenance and upkeep improvements
- Bump the requirements-user-env-extras.txt lower version bounds [#1002](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/1002) ([@consideRatio](https://github.com/consideRatio))
- Update traefik from 2.10.1 to 3.1.4 [#1001](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/1001) ([@consideRatio](https://github.com/consideRatio))
- Update to install miniforge 24.7.1-2 from 24.7.1-0 [#999](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/999) ([@consideRatio](https://github.com/consideRatio))
- Drop ubuntu 20.04, require py39, traefik-proxy v2, and ldapauthenticator v2 [#998](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/998) ([@consideRatio](https://github.com/consideRatio), [@minrk](https://github.com/minrk))
- consolidate lock file handling [#994](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/994) ([@minrk](https://github.com/minrk), [@consideRatio](https://github.com/consideRatio), [@jrdnbradford](https://github.com/jrdnbradford))
- update oauthenticator to 17 [#992](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/992) ([@minrk](https://github.com/minrk), [@consideRatio](https://github.com/consideRatio))
- Update base user environment to miniforge 24.7.1-0 (Python 3.12) [#990](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/990) ([@minrk](https://github.com/minrk), [@consideRatio](https://github.com/consideRatio))
- Add TLJH config lockfile [#976](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/976) ([@jrdnbradford](https://github.com/jrdnbradford), [@minrk](https://github.com/minrk), [@consideRatio](https://github.com/consideRatio))
- tests: fix to catch test failure earlier when they really happen [#975](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/975) ([@consideRatio](https://github.com/consideRatio), [@minrk](https://github.com/minrk))
#### Documentation improvements
- Added missing details on how to add custom domain from manual HTTPS configuration [#983](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/983) ([@josedaudi](https://github.com/josedaudi), [@yuvipanda](https://github.com/yuvipanda))
- Reword documentation sentence [#970](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/970) ([@davidalber](https://github.com/davidalber), [@consideRatio](https://github.com/consideRatio))
- Fix typo and replace word [#969](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/969) ([@davidalber](https://github.com/davidalber), [@consideRatio](https://github.com/consideRatio))
- Fix URL syntax in nativeauth.md [#949](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/949) ([@pdebuyl](https://github.com/pdebuyl), [@minrk](https://github.com/minrk))
- adapt install documentation for new /lab default interface [#935](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/935) ([@schwebke](https://github.com/schwebke), [@minrk](https://github.com/minrk))
#### Continuous integration improvements
- ci: cache pip only when no container is used [#997](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/997) ([@consideRatio](https://github.com/consideRatio))
- ci: run unit tests in ubuntu-24.04 github actions environment as well [#993](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/993) ([@consideRatio](https://github.com/consideRatio))
- ci: add tests for debian 12 and ubuntu 24.04 [#967](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/967) ([@consideRatio](https://github.com/consideRatio))
- build(deps): bump actions/cache from 3 to 4 [#961](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/961) ([@consideRatio](https://github.com/consideRatio))
- build(deps): bump codecov/codecov-action from 3 to 4 [#960](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/960) ([@consideRatio](https://github.com/consideRatio))
- build(deps): bump actions/setup-python from 4 to 5 [#958](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/958) ([@consideRatio](https://github.com/consideRatio))
- build(deps): bump actions/checkout from 3 to 4 [#943](https://github.com/jupyterhub/the-littlest-jupyterhub/pull/943) ([@consideRatio](https://github.com/consideRatio))
#### Contributors to this release
The following people contributed discussions, new ideas, code and documentation contributions, and review.
See [our definition of contributors](https://github-activity.readthedocs.io/en/latest/#how-does-this-tool-define-contributions-in-the-reports).
([GitHub contributors page for this release](https://github.com/jupyterhub/the-littlest-jupyterhub/graphs/contributors?from=2023-08-11&to=2024-09-30&type=c))
@consideRatio ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fthe-littlest-jupyterhub+involves%3AconsideRatio+updated%3A2023-08-11..2024-09-30&type=Issues)) | @davidalber ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fthe-littlest-jupyterhub+involves%3Adavidalber+updated%3A2023-08-11..2024-09-30&type=Issues)) | @josedaudi ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fthe-littlest-jupyterhub+involves%3Ajosedaudi+updated%3A2023-08-11..2024-09-30&type=Issues)) | @jrdnbradford ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fthe-littlest-jupyterhub+involves%3Ajrdnbradford+updated%3A2023-08-11..2024-09-30&type=Issues)) | @kiliansinger ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fthe-littlest-jupyterhub+involves%3Akiliansinger+updated%3A2023-08-11..2024-09-30&type=Issues)) | @manics ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fthe-littlest-jupyterhub+involves%3Amanics+updated%3A2023-08-11..2024-09-30&type=Issues)) | @minrk ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fthe-littlest-jupyterhub+involves%3Aminrk+updated%3A2023-08-11..2024-09-30&type=Issues)) | @MridulS ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fthe-littlest-jupyterhub+involves%3AMridulS+updated%3A2023-08-11..2024-09-30&type=Issues)) | @pdebuyl ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fthe-littlest-jupyterhub+involves%3Apdebuyl+updated%3A2023-08-11..2024-09-30&type=Issues)) | @schwebke ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fthe-littlest-jupyterhub+involves%3Aschwebke+updated%3A2023-08-11..2024-09-30&type=Issues)) | @yuvipanda ([activity](https://github.com/search?q=repo%3Ajupyterhub%2Fthe-littlest-jupyterhub+involves%3Ayuvipanda+updated%3A2023-08-11..2024-09-30&type=Issues))
## 1.0
### 1.0.0 - 2023-08-11

View File

@@ -26,7 +26,7 @@ sudo rm -rf /opt/tljh/hub
## User environment
By default, a `mambaforge` conda environment is installed in `/opt/tljh/user`. This contains
By default, a `miniforge` conda environment is installed in `/opt/tljh/user`. This contains
the notebook interface used to launch all users, and the various packages available to all
users. The environment is owned by the `root` user. JupyterHub admins may use
to `sudo -E conda install` or `sudo -E pip install` packages into this environment.

View File

@@ -1,5 +1,5 @@
# Systemd inside a Docker container, for CI only
ARG BASE_IMAGE=ubuntu:20.04
ARG BASE_IMAGE=ubuntu:22.04
FROM $BASE_IMAGE
# DEBIAN_FRONTEND is set to avoid being asked for input and hang during build:
@@ -29,8 +29,8 @@ RUN systemctl set-default multi-user.target
STOPSIGNAL SIGRTMIN+3
# Uncomment these lines for a development install
#ENV TLJH_BOOTSTRAP_DEV=yes
#ENV TLJH_BOOTSTRAP_PIP_SPEC=/srv/src
#ENV PATH=/opt/tljh/hub/bin:${PATH}
# ENV TLJH_BOOTSTRAP_DEV=yes
# ENV TLJH_BOOTSTRAP_PIP_SPEC=/srv/src
# ENV PATH=/opt/tljh/hub/bin:${PATH}
CMD ["/bin/bash", "-c", "exec /lib/systemd/systemd --log-target=journal 3>&1"]

View File

@@ -1,17 +1,25 @@
"""
Simplest plugin that exercises all the hooks defined in tljh/hooks.py.
"""
from tljh.hooks import hookimpl
@hookimpl
def tljh_extra_user_conda_packages():
return ["tqdm"]
# tqdm installs from the conda-forge channel (https://conda-forge.org/packages/)
# csvtk installs from the bioconda channel (https://bioconda.github.io/conda-package_index.html)
return ["tqdm", "csvtk"]
@hookimpl
def tljh_extra_user_conda_channels():
return ["conda-forge", "bioconda"]
@hookimpl
def tljh_extra_user_pip_packages():
return ["django"]
return ["simplejson"]
@hookimpl

View File

@@ -9,6 +9,7 @@ FIXME: The last test stands out and could be part of the other tests, and the
first two could be more like unit tests. Ideally, this file is
significantly reduced.
"""
import concurrent.futures
import os
import subprocess
@@ -84,9 +85,9 @@ def test_ubuntu_too_old():
"""
Error with a useful message when running in older Ubuntu
"""
output = _run_bootstrap_in_container("ubuntu:18.04", False)
output = _run_bootstrap_in_container("ubuntu:20.04", False)
_stop_container()
assert output.stdout == "The Littlest JupyterHub requires Ubuntu 20.04 or higher\n"
assert output.stdout == "The Littlest JupyterHub requires Ubuntu 22.04 or higher\n"
assert output.returncode == 1

View File

@@ -29,8 +29,7 @@ def test_labextensions():
# jupyter-labextension writes to stdout and stderr weirdly
proc = subprocess.run(
["/opt/tljh/user/bin/jupyter-labextension", "list"],
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
capture_output=True,
)
extensions = [

View File

@@ -33,7 +33,7 @@ def test_hub_version():
r = requests.get(HUB_URL + "/hub/api")
r.raise_for_status()
info = r.json()
assert V("4") <= V(info["version"]) <= V("5")
assert V("5.1") <= V(info["version"]) <= V("6")
async def test_user_code_execute():
@@ -59,9 +59,9 @@ async def test_user_code_execute():
async with User(username, HUB_URL, partial(login_dummy, password="")) as u:
assert await u.login()
await u.ensure_server_simulate(timeout=60, spawn_refresh_time=5)
await u.start_kernel()
await u.assert_code_output("5 * 4", "20", 5, 5)
assert await u.ensure_server_simulate(timeout=60, spawn_refresh_time=5)
assert await u.start_kernel()
assert await u.assert_code_output("5 * 4", "20", 5, 5)
async def test_user_server_started_with_custom_base_url():

View File

@@ -1,4 +1,5 @@
"""tests for the proxy"""
import os
import shutil
import ssl

View File

@@ -2,6 +2,7 @@
Test the plugin in integration-tests/plugins/simplest that makes use of all tljh
recognized plugin hooks that are defined in tljh/hooks.py.
"""
import os
import subprocess
@@ -19,13 +20,24 @@ def test_tljh_extra_user_conda_packages():
def test_tljh_extra_user_pip_packages():
subprocess.check_call([f"{USER_ENV_PREFIX}/bin/python3", "-c", "import django"])
subprocess.check_call([f"{USER_ENV_PREFIX}/bin/python3", "-c", "import simplejson"])
def test_tljh_extra_hub_pip_packages():
subprocess.check_call([f"{HUB_ENV_PREFIX}/bin/python3", "-c", "import there"])
def test_conda_packages():
"""
Test extra user conda packages are installed from multiple channels.
- tqdm installs from the conda-forge channel (https://conda-forge.org/packages/)
- csvtk installs from the bioconda channel (https://bioconda.github.io/conda-package_index.html)
"""
subprocess.check_call([f"{USER_ENV_PREFIX}/bin/python3", "-c", "import tqdm"])
subprocess.check_call([f"{USER_ENV_PREFIX}/bin/csvtk", "cat", "--help"])
def test_tljh_extra_apt_packages():
assert os.path.exists("/usr/games/sl")

View File

@@ -25,12 +25,10 @@ profile = "black"
# target-version should be all supported versions, see
# https://github.com/psf/black/issues/751#issuecomment-473066811
target_version = [
"py36",
"py37",
"py38",
"py39",
"py310",
"py311",
"py312",
]
@@ -67,7 +65,7 @@ omit = [
github_url = "https://github.com/jupyterhub/the-littlest-jupyterhub"
[tool.tbump.version]
current = "1.0.0"
current = "2.0.0b1"
regex = '''
(?P<major>\d+)
\.

View File

@@ -2,7 +2,7 @@ from setuptools import find_packages, setup
setup(
name="the-littlest-jupyterhub",
version="1.0.0",
version="2.0.0b1",
description="A small JupyterHub distribution",
url="https://github.com/jupyterhub/the-littlest-jupyterhub",
author="Jupyter Development Team",
@@ -10,14 +10,16 @@ setup(
license="3 Clause BSD",
packages=find_packages(),
include_package_data=True,
python_requires=">=3.9",
install_requires=[
"ruamel.yaml==0.17.*",
"ruamel.yaml==0.18.*",
"jinja2",
"pluggy==1.*",
"backoff",
"filelock",
"requests",
"bcrypt",
"jupyterhub-traefik-proxy==1.*",
"jupyterhub-traefik-proxy==2.*",
],
entry_points={
"console_scripts": [

View File

@@ -1,4 +1,5 @@
"""pytest fixtures"""
import os
import types
from importlib import reload

View File

@@ -1,6 +1,7 @@
"""
Test conda commandline wrappers
"""
import os
import subprocess
import tempfile
@@ -13,9 +14,9 @@ from tljh import conda, installer
@pytest.fixture(scope="module")
def prefix():
"""
Provide a temporary directory with a mambaforge conda environment
Provide a temporary directory with a conda environment
"""
installer_url, checksum = installer._mambaforge_url()
installer_url, checksum = installer._miniforge_url()
with tempfile.TemporaryDirectory() as tmpdir:
with conda.download_miniconda_installer(
installer_url, checksum
@@ -33,6 +34,15 @@ def test_ensure_packages(prefix):
subprocess.check_call([os.path.join(prefix, "bin", "python"), "-c", "import numpy"])
def test_ensure_channel_packages(prefix):
"""
Test installing packages in conda environment
"""
conda.ensure_conda_packages(prefix, ["csvtk"], channels=("conda-forge", "bioconda"))
# Throws an error if this fails
subprocess.check_call([os.path.join(prefix, "bin", "csvtk"), "cat", "--help"])
def test_ensure_pip_packages(prefix):
"""
Test installing pip packages in conda environment

View File

@@ -143,21 +143,24 @@ def test_remove_from_config_error():
def test_reload_hub():
with mock.patch("tljh.systemd.restart_service") as restart_service, mock.patch(
"tljh.systemd.check_service_active"
) as check_active, mock.patch("tljh.config.check_hub_ready") as check_ready:
with (
mock.patch("tljh.systemd.restart_service") as restart_service,
mock.patch("tljh.systemd.check_service_active") as check_active,
mock.patch("tljh.config.check_hub_ready") as check_ready,
):
config.reload_component("hub")
assert restart_service.called_with("jupyterhub")
assert check_active.called_with("jupyterhub")
restart_service.assert_called_with("jupyterhub")
check_active.assert_called_with("jupyterhub")
def test_reload_proxy(tljh_dir):
with mock.patch("tljh.systemd.restart_service") as restart_service, mock.patch(
"tljh.systemd.check_service_active"
) as check_active:
with (
mock.patch("tljh.systemd.restart_service") as restart_service,
mock.patch("tljh.systemd.check_service_active") as check_active,
):
config.reload_component("proxy")
assert restart_service.called_with("traefik")
assert check_active.called_with("traefik")
restart_service.assert_called_with("traefik")
check_active.assert_called_with("traefik")
assert os.path.exists(os.path.join(config.STATE_DIR, "traefik.toml"))

View File

@@ -1,6 +1,7 @@
"""
Unit test functions in installer.py
"""
import json
import os
from subprocess import PIPE, run
@@ -45,12 +46,12 @@ def test_ensure_admins(tljh_dir, admins, expected_config):
def setup_conda(distro, version, prefix):
"""Install mambaforge or miniconda in a prefix"""
"""Install miniforge or miniconda in a prefix"""
if distro == "mambaforge":
installer_url, _ = installer._mambaforge_url(version)
installer_url, _ = installer._miniforge_url(version)
installer_url = installer_url.replace("Miniforge3", "Mambaforge")
elif distro == "miniforge":
installer_url, _ = installer._mambaforge_url(version)
installer_url = installer_url.replace("Mambaforge", "Miniforge3")
installer_url, _ = installer._miniforge_url(version)
elif distro == "miniconda":
arch = os.uname().machine
installer_url = (
@@ -123,9 +124,9 @@ def _specifier(version):
None,
None,
{
"python": "3.10.*",
"conda": "23.1.0",
"mamba": "1.4.1",
"python": "3.12.*",
"conda": "24.7.1",
"mamba": "1.5.9",
},
),
# previous install, 1.0

View File

@@ -1,6 +1,7 @@
"""
Unit test functions in installer.py
"""
import os
from datetime import date

View File

@@ -1,6 +1,7 @@
"""
Test functions for normalizing various kinds of values
"""
from tljh.normalize import generate_system_username

View File

@@ -1,4 +1,5 @@
"""Test traefik configuration"""
import os
import pytest

View File

@@ -1,6 +1,7 @@
"""
Test wrappers in tljw.user module
"""
import grp
import os
import os.path

View File

@@ -1,6 +1,7 @@
"""
Utilities for working with the apt package manager
"""
import os
import subprocess

View File

@@ -1,6 +1,7 @@
"""
Wrap conda commandline program
"""
import contextlib
import hashlib
import json
@@ -98,9 +99,11 @@ def install_miniconda(installer_path, prefix):
fix_permissions(prefix)
def ensure_conda_packages(prefix, packages, force_reinstall=False):
def ensure_conda_packages(
prefix, packages, channels=("conda-forge",), force_reinstall=False
):
"""
Ensure packages (from conda-forge) are installed in the conda prefix.
Ensure packages (from channels) are installed in the conda prefix.
Note that conda seem to update dependencies by default, so there is probably
no need to have a update parameter exposed for this function.
@@ -117,13 +120,14 @@ def ensure_conda_packages(prefix, packages, force_reinstall=False):
# avoids problems with RemoveError upgrading conda from old versions
cmd += ["--force-reinstall"]
for channel in channels:
cmd += ["-c", channel]
abspath = os.path.abspath(prefix)
utils.run_subprocess(
cmd
+ [
"-c",
"conda-forge", # Make customizable if we ever need to
"--prefix",
abspath,
]

View File

@@ -18,9 +18,11 @@ import re
import sys
import time
from collections.abc import Mapping, Sequence
from contextlib import contextmanager
from copy import deepcopy
import requests
from filelock import FileLock, Timeout
from .yaml import yaml
@@ -32,6 +34,22 @@ CONFIG_DIR = os.path.join(INSTALL_PREFIX, "config")
CONFIG_FILE = os.path.join(CONFIG_DIR, "config.yaml")
@contextmanager
def config_file_lock(config_path, timeout=1):
"""Context manager to acquire the config file lock"""
lock_file = f"{config_path}.lock"
try:
with FileLock(lock_file).acquire(timeout=timeout):
yield
except Timeout:
print(
f"Another instance of tljh-config holds the lock {lock_file}.",
file=sys.stderr,
)
sys.exit(1)
def set_item_in_config(config, property_path, value):
"""
Set key at property_path to value in config & return new config.
@@ -154,92 +172,102 @@ def remove_item_from_config(config, property_path, value):
return config_copy
def validate_config(config, validate):
"""
Validate changes to the config with tljh-config against the schema
"""
import jsonschema
from .config_schema import config_schema
try:
jsonschema.validate(instance=config, schema=config_schema)
except jsonschema.exceptions.ValidationError as e:
if validate:
print(
f"Config validation error: {e.message}.\n"
"You can still apply this change without validation by re-running your command with the --no-validate flag.\n"
"If you think this validation error is incorrect, please report it to https://github.com/jupyterhub/the-littlest-jupyterhub/issues.",
file=sys.stderr,
)
sys.exit(1)
def show_config(config_path):
"""
Pretty print config from given config_path
"""
try:
with open(config_path) as f:
config = yaml.load(f)
except FileNotFoundError:
config = {}
config = get_current_config(config_path)
yaml.dump(config, sys.stdout)
def set_config_value(config_path, key_path, value):
def set_config_value(config_path, key_path, value, validate=True):
"""
Set key at key_path in config_path to value
"""
# FIXME: Have a file lock here
# FIXME: Validate schema here
try:
with open(config_path) as f:
config = yaml.load(f)
except FileNotFoundError:
config = {}
with config_file_lock(config_path):
config = get_current_config(config_path)
config = set_item_in_config(config, key_path, value)
validate_config(config, validate)
with open(config_path, "w") as f:
yaml.dump(config, f)
def unset_config_value(config_path, key_path):
def unset_config_value(config_path, key_path, validate=True):
"""
Unset key at key_path in config_path
"""
# FIXME: Have a file lock here
# FIXME: Validate schema here
try:
with open(config_path) as f:
config = yaml.load(f)
except FileNotFoundError:
config = {}
with config_file_lock(config_path):
config = get_current_config(config_path)
config = unset_item_from_config(config, key_path)
validate_config(config, validate)
with open(config_path, "w") as f:
yaml.dump(config, f)
def add_config_value(config_path, key_path, value):
def add_config_value(config_path, key_path, value, validate=True):
"""
Add value to list at key_path
"""
# FIXME: Have a file lock here
# FIXME: Validate schema here
try:
with open(config_path) as f:
config = yaml.load(f)
except FileNotFoundError:
config = {}
with config_file_lock(config_path):
config = get_current_config(config_path)
config = add_item_to_config(config, key_path, value)
validate_config(config, validate)
with open(config_path, "w") as f:
yaml.dump(config, f)
def remove_config_value(config_path, key_path, value):
def remove_config_value(config_path, key_path, value, validate=True):
"""
Remove value from list at key_path
"""
# FIXME: Have a file lock here
# FIXME: Validate schema here
try:
with open(config_path) as f:
config = yaml.load(f)
except FileNotFoundError:
config = {}
with config_file_lock(config_path):
config = get_current_config(config_path)
config = remove_item_from_config(config, key_path, value)
validate_config(config, validate)
with open(config_path, "w") as f:
yaml.dump(config, f)
def get_current_config(config_path):
"""
Retrieve the current config at config_path
"""
try:
with open(config_path) as f:
return yaml.load(f)
except FileNotFoundError:
return {}
def check_hub_ready():
"""
Checks that hub is running.
"""
from .configurer import load_config
base_url = load_config()["base_url"]
@@ -336,6 +364,18 @@ def main(argv=None):
argparser.add_argument(
"--config-path", default=CONFIG_FILE, help="Path to TLJH config.yaml file"
)
argparser.add_argument(
"--validate", action="store_true", help="Validate the TLJH config"
)
argparser.add_argument(
"--no-validate",
dest="validate",
action="store_false",
help="Do not validate the TLJH config",
)
argparser.set_defaults(validate=True)
subparsers = argparser.add_subparsers(dest="action")
show_parser = subparsers.add_parser("show", help="Show current configuration")
@@ -383,13 +423,19 @@ def main(argv=None):
if args.action == "show":
show_config(args.config_path)
elif args.action == "set":
set_config_value(args.config_path, args.key_path, parse_value(args.value))
set_config_value(
args.config_path, args.key_path, parse_value(args.value), args.validate
)
elif args.action == "unset":
unset_config_value(args.config_path, args.key_path)
unset_config_value(args.config_path, args.key_path, args.validate)
elif args.action == "add-item":
add_config_value(args.config_path, args.key_path, parse_value(args.value))
add_config_value(
args.config_path, args.key_path, parse_value(args.value), args.validate
)
elif args.action == "remove-item":
remove_config_value(args.config_path, args.key_path, parse_value(args.value))
remove_config_value(
args.config_path, args.key_path, parse_value(args.value), args.validate
)
elif args.action == "reload":
reload_component(args.component)
else:

117
tljh/config_schema.py Normal file
View File

@@ -0,0 +1,117 @@
"""
The schema against which the TLJH config file can be validated.
Validation occurs when changing values with tljh-config.
"""
config_schema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Littlest JupyterHub YAML config file",
"definitions": {
"BaseURL": {
"type": "string",
},
"Users": {
"type": "object",
"additionalProperties": False,
"properties": {
"extra_user_groups": {"type": "object", "items": {"type": "string"}},
"allowed": {"type": "array", "items": {"type": "string"}},
"banned": {"type": "array", "items": {"type": "string"}},
"admin": {"type": "array", "items": {"type": "string"}},
},
},
"Services": {
"type": "object",
"properties": {
"cull": {
"type": "object",
"additionalProperties": False,
"properties": {
"enabled": {"type": "boolean"},
"timeout": {"type": "integer"},
"every": {"type": "integer"},
"concurrency": {"type": "integer"},
"users": {"type": "boolean"},
"max_age": {"type": "integer"},
"remove_named_servers": {"type": "boolean"},
},
}
},
},
"HTTP": {
"type": "object",
"additionalProperties": False,
"properties": {
"address": {"type": "string", "format": "ipv4"},
"port": {"type": "integer"},
},
},
"HTTPS": {
"type": "object",
"additionalProperties": False,
"properties": {
"enabled": {"type": "boolean"},
"address": {"type": "string", "format": "ipv4"},
"port": {"type": "integer"},
"tls": {"$ref": "#/definitions/TLS"},
"letsencrypt": {"$ref": "#/definitions/LetsEncrypt"},
},
},
"LetsEncrypt": {
"type": "object",
"additionalProperties": False,
"properties": {
"email": {"type": "string", "format": "email"},
"domains": {
"type": "array",
"items": {"type": "string", "format": "hostname"},
},
"staging": {"type": "boolean"},
},
},
"TLS": {
"type": "object",
"additionalProperties": False,
"properties": {"key": {"type": "string"}, "cert": {"type": "string"}},
},
"Limits": {
"description": "User CPU and memory limits.",
"type": "object",
"additionalProperties": False,
"properties": {"memory": {"type": "string"}, "cpu": {"type": "integer"}},
},
"UserEnvironment": {
"type": "object",
"additionalProperties": False,
"properties": {
"default_app": {
"type": "string",
"enum": ["jupyterlab", "classic"],
"default": "jupyterlab",
}
},
},
"TraefikAPI": {
"type": "object",
"additionalProperties": False,
"properties": {
"ip": {"type": "string", "format": "ipv4"},
"port": {"type": "integer"},
"username": {"type": "string"},
"password": {"type": "string"},
},
},
},
"properties": {
"additionalProperties": False,
"base_url": {"$ref": "#/definitions/BaseURL"},
"user_environment": {"$ref": "#/definitions/UserEnvironment"},
"users": {"$ref": "#/definitions/Users"},
"limits": {"$ref": "#/definitions/Limits"},
"https": {"$ref": "#/definitions/HTTPS"},
"http": {"$ref": "#/definitions/HTTP"},
"traefik_api": {"$ref": "#/definitions/TraefikAPI"},
"services": {"$ref": "#/definitions/Services"},
},
}

View File

@@ -199,6 +199,14 @@ def update_userlists(c, config):
"""
users = config["users"]
if (
not users["allowed"]
and config["auth"]["type"] == default["auth"]["type"]
and "allow_all" not in c.FirstUseAuthenticator
):
# _default_ authenticator, enable allow_all if no users specified
c.FirstUseAuthenticator.allow_all = True
c.Authenticator.allowed_users = set(users["allowed"])
c.Authenticator.blocked_users = set(users["banned"])
c.Authenticator.admin_users = set(users["admin"])

View File

@@ -1,6 +1,7 @@
"""
Hook specifications that pluggy plugins can override
"""
import pluggy
hookspec = pluggy.HookspecMarker("tljh")
@@ -14,6 +15,13 @@ def tljh_extra_user_conda_packages():
"""
@hookspec
def tljh_extra_user_conda_channels():
"""
Return a list of conda channels to be used during user environment installation.
"""
@hookspec
def tljh_extra_user_pip_packages():
"""

View File

@@ -115,7 +115,6 @@ def ensure_jupyterhub_package(prefix):
os.path.join(HERE, "requirements-hub-env.txt"),
upgrade=True,
)
traefik.ensure_traefik_binary(prefix)
def ensure_usergroups():
@@ -136,13 +135,13 @@ def ensure_usergroups():
f.write("Defaults exempt_group = jupyterhub-admins\n")
# Install mambaforge using an installer from
# Install miniforge using an installer from
# https://github.com/conda-forge/miniforge/releases
MAMBAFORGE_VERSION = "23.1.0-1"
MINIFORGE_VERSION = "24.7.1-2"
# sha256 checksums
MAMBAFORGE_CHECKSUMS = {
"aarch64": "d9d89c9e349369702171008d9ee7c5ce80ed420e5af60bd150a3db4bf674443a",
"x86_64": "cfb16c47dc2d115c8b114280aa605e322173f029fdb847a45348bf4bd23c62ab",
MINIFORGE_CHECKSUMS = {
"aarch64": "7bf60bce50f57af7ea4500b45eeb401d9350011ab34c9c45f736647d8dba9021",
"x86_64": "636f7faca2d51ee42b4640ce160c751a46d57621ef4bf14378704c87c5db4fe3",
}
# minimum versions of packages
@@ -156,22 +155,22 @@ MINIMUM_VERSIONS = {
}
def _mambaforge_url(version=MAMBAFORGE_VERSION, arch=None):
"""Return (URL, checksum) for mambaforge download for a given version and arch
def _miniforge_url(version=MINIFORGE_VERSION, arch=None):
"""Return (URL, checksum) for miniforge download for a given version and arch
Default values provided for both version and arch
"""
if arch is None:
arch = os.uname().machine
installer_url = "https://github.com/conda-forge/miniforge/releases/download/{v}/Mambaforge-{v}-Linux-{arch}.sh".format(
installer_url = "https://github.com/conda-forge/miniforge/releases/download/{v}/Miniforge3-{v}-Linux-{arch}.sh".format(
v=version,
arch=arch,
)
# Check system architecture, set appropriate installer checksum
checksum = MAMBAFORGE_CHECKSUMS.get(arch)
checksum = MINIFORGE_CHECKSUMS.get(arch)
if not checksum:
raise ValueError(
f"Unsupported architecture: {arch}. TLJH only supports {','.join(MAMBAFORGE_CHECKSUMS.keys())}"
f"Unsupported architecture: {arch}. TLJH only supports {','.join(MINIFORGE_CHECKSUMS.keys())}"
)
return installer_url, checksum
@@ -198,7 +197,7 @@ def ensure_user_environment(user_requirements_txt_file):
raise OSError(msg)
logger.info("Downloading & setting up user environment...")
installer_url, installer_sha256 = _mambaforge_url()
installer_url, installer_sha256 = _miniforge_url()
with conda.download_miniconda_installer(
installer_url, installer_sha256
) as installer_path:
@@ -242,11 +241,10 @@ def ensure_user_environment(user_requirements_txt_file):
)
to_upgrade.append(pkg)
# force reinstall conda/mamba to ensure a basically consistent env
# avoids issues with RemoveError: 'requests' is a dependency of conda
# only do this for 'old' conda versions known to have a problem
# we don't know how old, but we know 4.10 is affected and 23.1 is not
if not is_fresh_install and V(package_versions.get("conda", "0")) < V("23.1"):
# force reinstall conda/mamba to ensure conda doesn't raise error
# "RemoveError: 'requests' is a dependency of conda" later on when
# conda/mamba is used to install/upgrade something
if not is_fresh_install:
# force-reinstall doesn't upgrade packages
# it reinstalls them in-place
# only reinstall packages already present
@@ -450,13 +448,18 @@ def run_plugin_actions(plugin_manager):
# Install conda packages
conda_packages = list(set(itertools.chain(*hook.tljh_extra_user_conda_packages())))
conda_channels = list(itertools.chain(*hook.tljh_extra_user_conda_channels()))
if len(conda_channels) == 0:
conda_channels = ("conda-forge",)
if conda_packages:
logger.info(
"Installing {} user conda packages collected from plugins: {}".format(
len(conda_packages), " ".join(conda_packages)
)
)
conda.ensure_conda_packages(USER_ENV_PREFIX, conda_packages)
conda.ensure_conda_packages(
USER_ENV_PREFIX, conda_packages, channels=conda_channels
)
# Install pip packages
user_pip_packages = list(set(itertools.chain(*hook.tljh_extra_user_pip_packages())))
@@ -532,6 +535,7 @@ def main():
logger.info("Setting up JupyterHub...")
ensure_jupyterhub_package(HUB_ENV_PREFIX)
traefik.ensure_traefik_binary(HUB_ENV_PREFIX)
# Stop the http server with the progress page before traefik starts
if args.progress_page_server_pid:

View File

@@ -1,4 +1,5 @@
"""Setup tljh logging"""
import logging
import os

View File

@@ -1,6 +1,7 @@
"""
Functions to normalize various inputs
"""
import hashlib

View File

@@ -8,14 +8,14 @@
# If a dependency is bumped to a new major version, we should make a major
# version release of tljh.
#
jupyterhub>=4.0.2,<5
jupyterhub>=5.1.0,<6
jupyterhub-systemdspawner>=1.0.1,<2
jupyterhub-firstuseauthenticator>=1.0.0,<2
jupyterhub-nativeauthenticator>=1.2.0,<2
jupyterhub-ldapauthenticator>=1.3.2,<2
jupyterhub-firstuseauthenticator>=1.1.0,<2
jupyterhub-nativeauthenticator>=1.3.0,<2
jupyterhub-ldapauthenticator==2.0.0b2 # FIXME: update to >=2.0.0,<3
jupyterhub-tmpauthenticator>=1.0.0,<2
oauthenticator>=16.0.4,<17
jupyterhub-idle-culler>=1.2.1,<2
oauthenticator>=17,<18
jupyterhub-idle-culler>=1.4.0,<2
# pycurl is installed to improve reliability and performance for when JupyterHub
# makes web requests. JupyterHub will use tornado's CurlAsyncHTTPClient when
@@ -25,4 +25,4 @@ jupyterhub-idle-culler>=1.2.1,<2
# ref: https://www.tornadoweb.org/en/stable/httpclient.html#module-tornado.simple_httpclient
# ref: https://github.com/jupyterhub/the-littlest-jupyterhub/issues/289
#
pycurl>=7.45.2,<8
pycurl>=7.45.3,<8

View File

@@ -8,11 +8,20 @@
# the requirements-txt-fixer pre-commit hook that sorted them and made
# our integration tests fail.
#
notebook==7.*
jupyterlab==4.*
# ref: https://github.com/jupyter/notebook
notebook>=7.2.2,<8
# ref: https://github.com/jupyterlab/jupyterlab
jupyterlab>=4.2.5,<5
# nbgitpuller for easily pulling in Git repositories
nbgitpuller==1.*
# ref: https://github.com/jupyterhub/nbgitpuller
nbgitpuller>=1.2.1,<2
# jupyter-resource-usage to show people how much RAM they are using
jupyter-resource-usage==1.*
# ref: https://github.com/jupyter-server/jupyter-resource-usage
jupyter-resource-usage>=1.1.0,<2
# Most people consider ipywidgets to be part of the core notebook experience
ipywidgets==8.*
# ref: https://github.com/jupyter-widgets/ipywidgets
ipywidgets>=8.1.5,<9

View File

@@ -18,7 +18,7 @@ Environment=TLJH_INSTALL_PREFIX={install_prefix}
Environment=PATH={install_prefix}/hub/bin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Run upgrade-db before starting, in case Hub version has changed
# This is a no-op when no db exists or no upgrades are needed
ExecStart={python_interpreter_path} -m jupyterhub.app -f {jupyterhub_config_path} --upgrade-db
ExecStart={python_interpreter_path} -m jupyterhub -f {jupyterhub_config_path} --upgrade-db
[Install]
# Start service when system boots

View File

@@ -3,6 +3,7 @@ Wraps systemctl to install, uninstall, start & stop systemd services.
If we use a debian package instead, we can get rid of all this code.
"""
import os
import subprocess

View File

@@ -1,4 +1,5 @@
"""Traefik installation and setup"""
import hashlib
import io
import logging
@@ -28,13 +29,13 @@ else:
plat = None
# Traefik releases: https://github.com/traefik/traefik/releases
traefik_version = "2.10.1"
traefik_version = "3.1.4"
# record sha256 hashes for supported platforms here
# checksums are published in the checksums.txt of each release
checksums = {
"linux_amd64": "8d9bce0e6a5bf40b5399dbb1d5e3e5c57b9f9f04dd56a2dd57cb0713130bc824",
"linux_arm64": "260a574105e44901f8c9c562055936d81fbd9c96a21daaa575502dc69bfe390a",
"linux_amd64": "eb7227b1b235195355904839c514a9ed6a0aecdcf5dab02ad48db21b05c5e700",
"linux_arm64": "e5d970a7f11267b70a8e308cb80f859bba4f420f24789f7393fdf3f4cd031631",
}
_tljh_path = Path(__file__).parent.resolve()
@@ -90,7 +91,10 @@ def check_traefik_version(traefik_bin):
@backoff.on_exception(backoff.expo, Exception, max_tries=2, giveup=fatal_error)
def ensure_traefik_binary(prefix):
"""Download and install the traefik binary to a location identified by a prefix path such as '/opt/tljh/hub/'"""
"""
Ensure that a traefik binary of a hardcoded version is made available at a
prefix path such as '/opt/tljh/hub/'.
"""
if plat is None:
raise OSError(
f"Error. Platform: {os.uname().sysname} / {machine} Not supported."

View File

@@ -3,6 +3,7 @@ User management for tljh.
Supports minimal user & group management
"""
import grp
import pwd
import subprocess

View File

@@ -1,6 +1,7 @@
"""
Miscellaneous functions useful in at least two places unrelated to each other
"""
import logging
import re
import subprocess

View File

@@ -3,6 +3,7 @@
ensures the same yaml settings for reading/writing
throughout tljh
"""
from ruamel.yaml import YAML
from ruamel.yaml.composer import Composer