Skip to content
This repository was archived by the owner on Sep 5, 2023. It is now read-only.

[WIP] Add/db percent encoding #643

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
90 changes: 57 additions & 33 deletions src/graderservice/graderservice/graderservice.py
Original file line number Diff line number Diff line change
@@ -6,10 +6,14 @@
from os import path
from pathlib import Path
from secrets import token_hex
import urllib.parse
from distutils.util import strtobool

from kubernetes import client
from kubernetes import config
from kubernetes.config import ConfigException
from kubernetes.client.rest import ApiException


from .templates import NBGRADER_COURSE_CONFIG_TEMPLATE
from .templates import NBGRADER_HOME_CONFIG_TEMPLATE
@@ -30,14 +34,12 @@
GRADER_IMAGE_PULL_POLICY = os.environ.get("GRADER_IMAGE_PULL_POLICY", "IfNotPresent")
# mount root path for grader and course home directories
MNT_ROOT = os.environ.get("ILLUMIDESK_MNT_ROOT", "/illumidesk-courses")

GRADER_PVC = os.environ.get("GRADER_PVC", "grader-setup-pvc")
# shared directory to use with students and instructors
EXCHANGE_MNT_ROOT = os.environ.get(
"ILLUMIDESK_NB_EXCHANGE_MNT_ROOT", "/illumidesk-nb-exchange"
)
GRADER_PVC = os.environ.get("GRADER_PVC", "grader-setup-pvc")
GRADER_EXCHANGE_SHARED_PVC = os.environ.get(
"GRADER_SHARED_PVC", "exchange-shared-volume"
)

# user UI and GID to use within the grader container
NB_UID = os.environ.get("NB_UID", 10001)
@@ -55,7 +57,7 @@

# NBGrader database settings to save in nbgrader_config.py file
nbgrader_db_host = os.environ.get("POSTGRES_NBGRADER_HOST")
nbgrader_db_password = os.environ.get("POSTGRES_NBGRADER_PASSWORD")
nbgrader_db_password = urllib.parse.quote(os.environ.get("POSTGRES_NBGRADER_PASSWORD"), safe='')
nbgrader_db_user = os.environ.get("POSTGRES_NBGRADER_USER")
nbgrader_db_port = os.environ.get("POSTGRES_NBGRADER_PORT")
nbgrader_db_name = os.environ.get("POSTGRES_NBGRADER_DB_NAME")
@@ -92,8 +94,8 @@ def __init__(self, org_name: str, course_id: str):
self.course_dir = Path(
f"{MNT_ROOT}/{self.org_name}/home/grader-{self.course_id}/{self.course_id}"
)
# set the exchange directory path
self.exchange_dir = Path(EXCHANGE_MNT_ROOT, self.org_name, "exchange")


def grader_deployment_exists(self) -> bool:
"""Check if there is a deployment for the grader service name"""
@@ -123,6 +125,7 @@ def create_grader_deployment(self):
"""Deploy the grader service"""
# first create the home directories for grader/course
try:

self._create_exchange_directory()
self._create_grader_directories()
self._create_nbgrader_files()
@@ -224,9 +227,34 @@ def _create_deployment_object(self):
V1Deployment: a valid kubernetes deployment object
"""
# Configureate Pod template container
# Volumes to mount as subPaths of PV
# sub path for grader home volume mount
sub_path_grader_home = str(self.course_dir.parent).strip("/")
# sub path for exchange directory
sub_path_exchange = str(self.exchange_dir.relative_to(EXCHANGE_MNT_ROOT))
# Volume mounts for grader
grader_notebook_volume_mounts = [
client.V1VolumeMount(
mount_path=f"/home/{self.grader_name}",
name=GRADER_PVC,
sub_path=sub_path_grader_home,
),
client.V1VolumeMount(
mount_path="/srv/nbgrader/exchange",
name=GRADER_PVC,
sub_path=sub_path_exchange,
),
]
#Persistent Volume for grader
grader_notebook_volumes = [
client.V1Volume(
name=GRADER_PVC,
persistent_volume_claim=client.V1PersistentVolumeClaimVolumeSource(
claim_name=GRADER_PVC
),
),
]


# define the container to launch
container = client.V1Container(
name="grader-notebook",
@@ -270,18 +298,7 @@ def _create_deployment_object(self):
client.V1EnvVar(name="NB_GID", value=str(NB_GID)),
client.V1EnvVar(name="NB_USER", value=self.grader_name),
],
volume_mounts=[
client.V1VolumeMount(
mount_path=f"/home/{self.grader_name}",
name=GRADER_PVC,
sub_path=sub_path_grader_home,
),
client.V1VolumeMount(
mount_path="/srv/nbgrader/exchange",
name=GRADER_EXCHANGE_SHARED_PVC,
sub_path=sub_path_exchange,
),
],
volume_mounts=grader_notebook_volume_mounts,
)
# Create and configure a spec section
template = client.V1PodTemplateSpec(
@@ -291,20 +308,7 @@ def _create_deployment_object(self):
spec=client.V1PodSpec(
containers=[container],
security_context=client.V1PodSecurityContext(run_as_user=0),
volumes=[
client.V1Volume(
name=GRADER_PVC,
persistent_volume_claim=client.V1PersistentVolumeClaimVolumeSource(
claim_name=GRADER_PVC
),
),
client.V1Volume(
name=GRADER_EXCHANGE_SHARED_PVC,
persistent_volume_claim=client.V1PersistentVolumeClaimVolumeSource(
claim_name=GRADER_EXCHANGE_SHARED_PVC
),
),
],
volumes=grader_notebook_volumes,
),
)
# Create the specification of deployment
@@ -358,3 +362,23 @@ def update_jhub_deployment(self):
name="hub", namespace=NAMESPACE, body=deployment
)
logger.info(f"Jhub patch response:{api_response}")

# Restarts deployment in namespace
def restart_deployment(v1_apps, deployment, namespace):
now = datetime.datetime.utcnow()
now = str(now.isoformat("T") + "Z")
body = {
'spec': {
'template':{
'metadata': {
'annotations': {
'kubectl.kubernetes.io/restartedAt': now
}
}
}
}
}
try:
v1_apps.patch_namespaced_deployment(deployment, namespace, body, pretty='true')
except ApiException as e:
print("Exception when calling AppsV1Api->read_namespaced_deployment_status: %s\n" % e)
1 change: 1 addition & 0 deletions src/graderservice/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -77,6 +77,7 @@ def grader_setup_environ(monkeypatch):
monkeypatch.setenv("MNT_ROOT", "/illumidesk-courses")
monkeypatch.setenv("NB_UID", "10001")
monkeypatch.setenv("NB_GID", "100")



@pytest.fixture(scope="function")
4 changes: 2 additions & 2 deletions src/illumidesk/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# for kubernetes, use the --build-arg when building image or uncomment
# ARG BASE_IMAGE=jupyterhub/k8s-hub:1.1.2
ARG BASE_IMAGE=jupyterhub/jupyterhub:1.4.2
ARG BASE_IMAGE=jupyterhub/k8s-hub:1.1.2
#ARG BASE_IMAGE=jupyterhub/jupyterhub:1.4.2
FROM "${BASE_IMAGE}"

USER root
3 changes: 2 additions & 1 deletion src/illumidesk/illumidesk/apis/nbgrader_service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging
import os
import urllib.parse

from nbgrader.api import Assignment
from nbgrader.api import Course
@@ -16,7 +17,7 @@

nbgrader_db_host = os.environ.get("POSTGRES_NBGRADER_HOST")
nbgrader_db_port = os.environ.get("POSTGRES_NBGRADER_PORT") or 5432
nbgrader_db_password = os.environ.get("POSTGRES_NBGRADER_PASSWORD")
nbgrader_db_password = urllib.parse.quote(os.environ.get("POSTGRES_NBGRADER_PASSWORD"), safe='')
nbgrader_db_user = os.environ.get("POSTGRES_NBGRADER_USER")
mnt_root = os.environ.get("ILLUMIDESK_MNT_ROOT", "/illumidesk-courses")

2 changes: 1 addition & 1 deletion src/illumidesk/requirements.txt
Original file line number Diff line number Diff line change
@@ -102,6 +102,6 @@ wcwidth==0.2.5 # via prompt-toolkit
webencodings==0.5.1 # via bleach
websocket-client==0.59.0 # via kubernetes
widgetsnbextension==3.5.1 # via ipywidgets

boto3==1.21.9
# The following packages are considered to be unsafe in a requirements file:
# setuptools
5 changes: 3 additions & 2 deletions src/illumideskdummyauthenticator/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# for kubernetes, use the --build-arg when building image or uncomment
# ARG BASE_IMAGE=illumidesk/k8s-hub:1.1.2
ARG BASE_IMAGE=illumidesk/jupyterhub:1.4.2
#ARG BASE_IMAGE=illumidesk/k8s-hub:1.1.2
#ARG BASE_IMAGE=illumidesk/k8s-hub:03022022
#ARG BASE_IMAGE=illumidesk/jupyterhub:1.4.2
FROM "${BASE_IMAGE}"

USER "${NB_UID}"