From b35dad37c6b057a41df3f64682e0b32bcb25258f Mon Sep 17 00:00:00 2001 From: machine424 Date: Wed, 8 Mar 2023 15:46:11 +0100 Subject: [PATCH] chore: upgrade some dependencies --- README.md | 1 - deploy/notebook-on-kube/Chart.yaml | 2 +- pyproject.toml | 4 +-- requirements.txt | 16 ++++----- src/notebook_on_kube/main.py | 1 - tests/test_api.py | 57 ++++++++++++++++-------------- 6 files changed, 41 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 5aec9c0..071c08f 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,6 @@ You can check out this [post](http://ouba.online/blog/2023/3/8/you_probably_dont `notebook-on-kube` provides the following features: -It provides the following features: - Authn/authz based on `Kubernetes'`. - Customize and create notebooks. - Connect to notebooks. diff --git a/deploy/notebook-on-kube/Chart.yaml b/deploy/notebook-on-kube/Chart.yaml index 52a23ef..07c4e0b 100644 --- a/deploy/notebook-on-kube/Chart.yaml +++ b/deploy/notebook-on-kube/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: notebook-on-kube description: A Helm chart to deploy notebook-on-kube type: application -version: 0.2.1 +version: 0.2.2 home: https://github.com/machine424/notebook-on-kube dependencies: - name: ingress-nginx diff --git a/pyproject.toml b/pyproject.toml index 7e45694..a184039 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "notebook-on-kube" -version = "0.2.1" +version = "0.2.2" description = "A tool to deploy Notebooks on Kubernetes." readme = "README.md" authors = [ @@ -25,7 +25,7 @@ dependencies = [ notebook-on-kube = "notebook_on_kube.main:run" [project.optional-dependencies] -test = ["black", "isort", "flake8", "mypy", "pytest", "pytest-mock", "requests"] +test = ["black", "isort", "flake8", "mypy", "pytest", "pytest-mock", "httpx"] [project.urls] "Homepage" = "https://github.com/machine424/notebook-on-kube" diff --git a/requirements.txt b/requirements.txt index 413980b..037f3df 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,7 @@ anyio==3.6.2 # via starlette click==8.1.3 # via uvicorn -fastapi==0.85.1 +fastapi==0.93.0 # via notebook-on-kube (pyproject.toml) h11==0.14.0 # via uvicorn @@ -16,25 +16,23 @@ idna==3.4 # via anyio jinja2==3.1.2 # via notebook-on-kube (pyproject.toml) -markupsafe==2.1.1 +markupsafe==2.1.2 # via jinja2 -pydantic==1.10.2 +pydantic==1.10.5 # via fastapi pyjwt==2.6.0 # via notebook-on-kube (pyproject.toml) -python-multipart==0.0.5 +python-multipart==0.0.6 # via notebook-on-kube (pyproject.toml) ruamel-yaml==0.17.21 # via notebook-on-kube (pyproject.toml) ruamel-yaml-clib==0.2.7 # via ruamel-yaml -six==1.16.0 - # via python-multipart sniffio==1.3.0 # via anyio -starlette==0.20.4 +starlette==0.25.0 # via fastapi -typing-extensions==4.4.0 +typing-extensions==4.5.0 # via pydantic -uvicorn==0.19.0 +uvicorn==0.20.0 # via notebook-on-kube (pyproject.toml) diff --git a/src/notebook_on_kube/main.py b/src/notebook_on_kube/main.py index 930094f..422a9fb 100644 --- a/src/notebook_on_kube/main.py +++ b/src/notebook_on_kube/main.py @@ -278,7 +278,6 @@ def form_data_to_values_file(cls, *, form_data: FormData) -> IO | None: class NotebookStatus: class Notebook(BaseModel, extra=Extra.forbid): - missing_statefulset: ClassVar[str] = "StatefulSet Missing" not_running: ClassVar[str] = "Not Running" error: ClassVar[str] = "Error" diff --git a/tests/test_api.py b/tests/test_api.py index b066fb5..fb96784 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -28,7 +28,10 @@ ) FAKE_NOTEBOOK = "my-notebook" -client = TestClient(app) + +@pytest.fixture() +def test_client(): + return TestClient(app) @pytest.fixture() @@ -131,30 +134,32 @@ def test_complete_notebook_name_from_form(mocker, notebook_name, username, compl assert complete_notebook_name_from_form(notebook_name=notebook_name, username=username) == complete_notebook_name -def test_healthz(): - response = client.get("api/healthz") +def test_healthz(test_client): + response = test_client.get("api/healthz") assert response.status_code == 200 assert response.json()["status"] == "Seems healthy" -def test_root(): - response = client.get("/") +def test_root(test_client): + response = test_client.get("/") assert response.status_code == 200 assert response.template.name == "index.html" assert response.context["kube_cluster_name"] is None -def test_login(validate_kube_token_mock): - response = client.post("api/login/", data={"kube_token": FAKE_OIDC_TOKEN}, allow_redirects=False) +def test_login(validate_kube_token_mock, test_client): + response = test_client.post("api/login/", data={"kube_token": FAKE_OIDC_TOKEN}, follow_redirects=False) assert response.status_code == 303 assert response.headers["location"] == "/api/notebooks/" - # We do not send the cookie when connecting to Notebooks (non /api) - assert response.cookies.get_dict(path="/api")["kube_token"] == FAKE_OIDC_TOKEN + # Assert we only set the cookie on /api) + assert len(response.cookies) == 1 + assert response.cookies.get(name="kube_token", path="/api") == FAKE_OIDC_TOKEN def test_notebooks(mocker, validate_kube_token_mock): helm = mocker.patch("notebook_on_kube.main.helm", return_value="{}") - response = client.get("api/notebooks/", cookies={"kube_token": FAKE_OIDC_TOKEN}) + client = TestClient(app=app, cookies={"kube_token": FAKE_OIDC_TOKEN}) + response = client.get("api/notebooks/") helm.assert_called_once_with( body=["list", "--filter", f"^nok-{FAKE_USERNAME}-.+$", "--all", "--output", "json"], kube_token=FAKE_OIDC_TOKEN ) @@ -177,9 +182,8 @@ def test_delete_notebook(mocker, validate_kube_token_mock, existing, helm_list_o helm_list_call = mocker.call( body=["list", "--filter", f"^{FAKE_NOTEBOOK}$", "--all", "--output", "json"], kube_token=FAKE_OIDC_TOKEN ) - response = client.post( - f"api/delete_notebook/{FAKE_NOTEBOOK}", cookies={"kube_token": FAKE_OIDC_TOKEN}, allow_redirects=False - ) + client = TestClient(app=app, cookies={"kube_token": FAKE_OIDC_TOKEN}) + response = client.post(f"api/delete_notebook/{FAKE_NOTEBOOK}", follow_redirects=False) assert response.status_code == status_code if existing: assert response.headers["location"] == "/api/notebooks/" @@ -195,7 +199,8 @@ def test_delete_notebook(mocker, validate_kube_token_mock, existing, helm_list_o def test_notebook_events(mocker, validate_kube_token_mock, event): mocker.patch("notebook_on_kube.main.notebook_exists", return_value=True) kubectl = mocker.patch("notebook_on_kube.main.kubectl", return_value=event) - response = client.get(f"api/notebook_events/{FAKE_NOTEBOOK}", cookies={"kube_token": FAKE_OIDC_TOKEN}) + client = TestClient(app=app, cookies={"kube_token": FAKE_OIDC_TOKEN}) + response = client.get(f"api/notebook_events/{FAKE_NOTEBOOK}") assert response.status_code == 200 assert ( response.text @@ -224,10 +229,10 @@ def test_notebook_events(mocker, validate_kube_token_mock, event): def test_scale_notebook(mocker, validate_kube_token_mock, scale): mocker.patch("notebook_on_kube.main.notebook_exists", return_value=True) kubectl = mocker.patch("notebook_on_kube.main.kubectl") + client = TestClient(app=app, cookies={"kube_token": FAKE_OIDC_TOKEN}) response = client.get( f"api/scale_notebook/{FAKE_NOTEBOOK}?scale={scale}", - cookies={"kube_token": FAKE_OIDC_TOKEN}, - allow_redirects=False, + follow_redirects=False, ) assert response.status_code == 303 assert response.headers["location"] == "/api/notebooks/" @@ -245,9 +250,9 @@ def test_scale_notebook(mocker, validate_kube_token_mock, scale): def test_new_notebook(validate_kube_token_mock): + client = TestClient(app=app, cookies={"kube_token": FAKE_OIDC_TOKEN}) response = client.get( "api/new_notebook/", - cookies={"kube_token": FAKE_OIDC_TOKEN}, ) assert response.status_code == 200 assert response.template.name == "new_notebook.html" @@ -270,14 +275,20 @@ def test_create_notebook(mocker, validate_kube_token_mock, existing, helm_values yaml_load = mocker.spy(yaml, "load") yaml_dump = mocker.spy(yaml, "dump") + client = TestClient(app=app, cookies={"kube_token": FAKE_OIDC_TOKEN}) response = client.post( "api/create_notebook/", - cookies={"kube_token": FAKE_OIDC_TOKEN}, data={"notebook_name": FAKE_NOTEBOOK, "helm_values": helm_values}, - allow_redirects=False, + follow_redirects=False, ) assert response.status_code == status_code - if not existing: + if existing: + assert ( + response.json()["detail"] + == f"The Notebook notebook_name='nok-{FAKE_USERNAME}-{FAKE_NOTEBOOK}' already exists." + ) + assert helm.call_count == 0 + else: assert response.headers["location"] == "/api/notebooks/" # helm_values content was retrieved yaml_load.assert_called_once_with(helm_values) @@ -296,9 +307,3 @@ def test_create_notebook(mocker, validate_kube_token_mock, existing, helm_values ], kube_token=FAKE_OIDC_TOKEN, ) - else: - assert ( - response.json()["detail"] - == f"The Notebook notebook_name='nok-{FAKE_USERNAME}-{FAKE_NOTEBOOK}' already exists." - ) - assert helm.call_count == 0