Skip to content
This repository has been 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
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
90 changes: 57 additions & 33 deletions src/graderservice/graderservice/graderservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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")
Expand Down Expand Up @@ -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"""
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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(
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Up @@ -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")
Expand Down
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
Expand Down
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
Expand All @@ -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")

Expand Down
2 changes: 1 addition & 1 deletion src/illumidesk/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Expand Down