Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/pre-commit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: pre-commit/action@v2.0.0
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- uses: pre-commit/action@v3.0.1
59 changes: 58 additions & 1 deletion docs/source/kbatch-proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,63 @@ kbatch-proxy:
- user
```

## Namespace customization

```{versionadded} 0.5
```

The `kbatch_namespace_manifests_file` setting can point to a yaml file containing any number of kubernetes manifests to create within a given kbatch namespace.
This allows creation of ResourceQuotas, LimitRanges, NetworkPolicies, and other per-namespace resources you might want to have in every user namespace.
The manifests are created using kubernetes [server-side apply](https://kubernetes.io/docs/reference/using-api/server-side-apply/).

For example, the resource quota:

```yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: mem-cpu-demo
spec:
hard:
count.pods: "10"
requests.cpu: "5"
requests.memory: 5Gi
limits.cpu: "20"
limits.memory: 20Gi
---
# it's a good idea to include default resource requests/limits
# if you have a ResourceQuota, otherwise pods can't be created without them
apiVersion: v1
kind: LimitRange
metadata:
name: default-resources
spec:
limits:
# default resources.limit
- default:
cpu: "1"
memory: "1Gi"
# default resources.request
defaultRequest:
cpu: "1"
memory: "1Gi"
type: Container
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Egress
- Ingress
```

would limit the number of pods in _each_ kbatch namespace to 10,
limit resource requests and limits,
set a default resource request/limit for all containers that don't specify,
and deny _all_ network traffic into and out of the namespace.
so jobs would not have permission to access the network.

[jhub-service]: https://z2jh.jupyter.org/en/latest/administrator/services.html
[jhub-service]: https://z2jh.jupyter.org/en/latest/administrator/services.html
36 changes: 24 additions & 12 deletions integration-tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
from pathlib import Path

import pytest
from fastapi.testclient import TestClient
Expand All @@ -7,6 +8,8 @@
# make sure this happens before kbatch_proxy.main is imported
os.environ["kbatch_init_logging"] = "0"

integration_tests = Path(__file__).parent.resolve()


@pytest.fixture(scope="session", autouse=True)
def check_cluster():
Expand All @@ -27,8 +30,25 @@ def check_cluster():


@pytest.fixture(autouse=True)
def mock_hub_auth(mocker):
def side_effect(token):
def kbatch_proxy_settings(mocker):
"""apply kbatch_proxy settings"""
# make sure this happens before kbatch_proxy.main is imported
mocker.patch.dict(
os.environ,
{
"kbatch_init_logging": "0",
"JUPYTERHUB_SERVICE_NAME": "kbatch",
},
)
import kbatch_proxy.main

kbatch_proxy.main.settings = settings = kbatch_proxy.main.Settings(
kbatch_namespace_manifests_file=str(
integration_tests / "data" / "namespace-manifests.yaml"
),
)

def mock_auth(token):
if token == "abc":
return {
"name": "testuser",
Expand All @@ -44,19 +64,11 @@ def side_effect(token):
else:
return None

# env patch must be before module patch to avoid logging setup
mocker.patch.dict(
os.environ,
{
"kbatch_init_logging": "0",
"JUPYTERHUB_SERVICE_NAME": "kbatch",
},
)
mocker.patch("kbatch_proxy.main.auth.user_for_token", side_effect=side_effect)
mocker.patch.object(settings.auth, "user_for_token", mock_auth)


@pytest.fixture
def client(mock_hub_auth, mocker):
def client(kbatch_proxy_settings, mocker):
# import kbatch_proxy.main must be after mock_hub_auth
from kbatch_proxy.main import app

Expand Down
44 changes: 44 additions & 0 deletions integration-tests/data/namespace-manifests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
apiVersion: v1
kind: ResourceQuota
metadata:
name: mem-cpu-demo
spec:
hard:
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
---
apiVersion: v1
kind: LimitRange
metadata:
name: default-resources
spec:
limits:
# default is default limit
- default:
cpu: 500m
memory: 500M
# default request
defaultRequest:
cpu: 500m
memory: 100M
# bounds
max:
cpu: "1"
memory: 1Gi
min:
cpu: 100m
memory: 64M
type: Container
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ns-config-map
data:
key: value
---

# trailing --- to test empty-element handling
---
2 changes: 2 additions & 0 deletions integration-tests/test_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ def _wrapped_invoke(*args, **kwargs):
# always write stderr on error so it shows up in captured test output
if result.exit_code:
sys.stderr.write(result.stderr)
if result.exception and isinstance(result.exception, Exception):
raise result.exception
return result

runner.invoke = _wrapped_invoke
Expand Down
Loading
Loading