Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OCP4 Workshop Grading Dashboard

A live grading dashboard for the OCP4 Getting Started Workshop. It monitors participant namespaces in real time and displays progress on a gamified leaderboard.

Architecture

Browser (instructor laptop / projector)
    |
  Route (edge TLS)
    |
  Service :8080
    |
  Pod (Python FastAPI)
    |
  Kubernetes API (read-only ClusterRole)
    |
  wksp-user1, wksp-user2, ... wksp-userN namespaces

The grading app runs inside the OpenShift cluster with a ServiceAccount that has read-only access to all user namespaces. It checks for specific Kubernetes objects (Deployments, Routes, Secrets, Pipelines, etc.) that participants create during the workshop and scores their progress.

Dashboard Features

  • Dark "mission control" themed UI designed for projecting in a classroom
  • Real-time leaderboard ranked by completion percentage
  • Per-module completion bars showing class-wide progress
  • Click any student row to expand detailed per-check pass/fail status
  • Auto-refresh every 30 seconds (configurable, with toggle)
  • Trophy and medal icons for top finishers
  • Sortable columns (rank, username, progress)

What Gets Graded

Module Exercise What's Checked
3 Parksmap Deployment Deployment parksmap with >= 1 replica
4 Scaling Deployment parksmap with >= 2 replicas
5 Routes Route parksmap exists
7 Permissions RoleBinding granting view to default SA
9 Nationalparks Backend Deployment + BuildConfig + labeled Route
10 Database MongoDB Deployment + Secret + Service
11 Health Checks Readiness & liveness probes on nationalparks
12 Pipelines Pipeline + successful PipelineRun + Tasks
13 Triggers TriggerTemplate + TriggerBinding + EventListener

Modules 1-2 (login/projects), 6 (logging), and 8 (remote shell) have no gradeable objects and are skipped.

Prerequisites

  • OpenShift 4.x cluster with workshop namespaces provisioned (wksp-user1, wksp-user2, ...)
  • oc CLI authenticated as a user with cluster-admin privileges (needed to create ClusterRole/ClusterRoleBinding)
  • podman or docker for building the container image
  • A container registry (e.g., quay.io) to push the image

Quick Start

# 1. Clone and enter the repo
git clone <repo-url>
cd OCP4StarterWorkshopGrading

# 2. Log into OpenShift as cluster-admin
oc login --token=<token> --server=<api-url>

# 3. Create namespace and RBAC
oc apply -f manifests/namespace.yaml
oc apply -f manifests/serviceaccount.yaml
oc apply -f manifests/clusterrole.yaml
oc apply -f manifests/clusterrolebinding.yaml

# 4. Deploy the ConfigMap (edit modules.yaml section if needed)
oc apply -f manifests/configmap.yaml

# 5. Build and push the container image
podman build -t quay.io/<your-org>/ocp4-workshop-grader:latest -f Containerfile .
podman push quay.io/<your-org>/ocp4-workshop-grader:latest

# 6. Update the image in manifests/deployment.yaml, then deploy
oc apply -f manifests/deployment.yaml
oc apply -f manifests/service.yaml
oc apply -f manifests/route.yaml

# 7. Get the dashboard URL
echo "https://$(oc get route workshop-grader -n workshop-grading -o jsonpath='{.spec.host}')"

Deploy Everything at Once

If you prefer a single command after building and pushing the image:

oc apply -f manifests/

Project Structure

OCP4StarterWorkshopGrading/
├── Containerfile               # Multi-stage build (Hummingbird Python 3.12, distroless)
├── requirements.txt            # Python dependencies
├── README.md
├── app/
│   ├── main.py                 # FastAPI app and API endpoints
│   ├── config.py               # Configuration from env vars + YAML
│   ├── grader.py               # Grading orchestration, caching, parallel queries
│   ├── checks.py               # Individual grading check functions
│   ├── k8s_client.py           # Kubernetes API client wrapper
│   ├── models.py               # Pydantic response models
│   └── static/
│       └── index.html          # Single-page dashboard (HTML + CSS + JS)
└── manifests/
    ├── namespace.yaml           # workshop-grading namespace
    ├── serviceaccount.yaml      # grader-sa ServiceAccount
    ├── clusterrole.yaml         # Read-only ClusterRole (least privilege)
    ├── clusterrolebinding.yaml  # Binds ClusterRole to grader-sa
    ├── configmap.yaml           # Runtime config + module/check definitions
    ├── deployment.yaml          # App Deployment (1 replica, health probes)
    ├── service.yaml             # ClusterIP Service on port 8080
    └── route.yaml               # Edge-terminated TLS Route

Configuration

All configuration is in the grader-config ConfigMap (manifests/configmap.yaml).

Runtime Settings (config.yaml key in ConfigMap)

Setting Default Description
namespace_prefix wksp-user Prefix to match user namespaces (matches wksp-user1, wksp-user2, ...)
cache_ttl_seconds 30 How long to cache K8s API results before re-querying
refresh_interval_seconds 30 How often the browser auto-refreshes (sent to frontend)

Module Definitions (modules.yaml key in ConfigMap)

Each module has a list of checks. Available check types:

Check Type Parameters Description
deployment_exists name, min_replicas Deployment exists with N available replicas
deployment_has_probes name Deployment has readiness + liveness probes
route_exists name, required_labels (optional) Route exists, optionally with specific labels
rolebinding_view_default (none) RoleBinding granting view to default SA
secret_exists name_pattern (regex) Secret matching the name pattern
service_exists name Service exists
buildconfig_exists name_substring BuildConfig with name containing substring
pipeline_exists (none) At least one Tekton Pipeline
pipelinerun_succeeded (none) At least one successful PipelineRun
task_exists (none) At least one Tekton Task
resource_exists group, version, plural Generic CRD existence check

Customizing Checks

To add, remove, or modify grading checks without rebuilding the image:

oc edit configmap grader-config -n workshop-grading
oc rollout restart deployment workshop-grader -n workshop-grading

For example, to change the scaling check from 2 replicas to 3, find the module 4 section in the modules.yaml data key and update min_replicas: 3.

API Endpoints

Method Path Description
GET / Dashboard UI
GET /api/grades Full grading results for all users (JSON)
GET /api/grades/{username} Single user results (e.g., /api/grades/1 for namespace wksp-user1)
GET /api/config Module names and refresh interval (used by frontend)
GET /api/health Liveness/readiness probe endpoint

Local Development

Run the dashboard locally against a remote OpenShift cluster using your kubeconfig:

# Install dependencies
pip install -r requirements.txt

# Point to your cluster (uses ~/.kube/config by default)
export IN_CLUSTER=false
export NAMESPACE_PREFIX=wksp-user

# Start the dev server with hot reload
uvicorn app.main:app --reload --port 8080

Open http://localhost:8080 in your browser.

When running locally without the ConfigMap volume mount, the app uses built-in default module definitions. To customize modules locally, create a standalone modules.yaml file and set MODULES_CONFIG_PATH to point to it:

export MODULES_CONFIG_PATH=./modules.yaml

Troubleshooting

"No user namespaces found" Check that namespace_prefix in the ConfigMap matches your namespace naming convention. The default is wksp-user, which matches wksp-user1, wksp-user2, etc. If your namespaces use a different convention like lab-user1, lab-user2, set the prefix to lab-user.

403 Forbidden errors in pod logs The ServiceAccount doesn't have the required permissions. Re-apply the ClusterRole and ClusterRoleBinding:

oc apply -f manifests/clusterrole.yaml
oc apply -f manifests/clusterrolebinding.yaml

Tekton/Pipeline checks all show "not found" The OpenShift Pipelines operator may not be installed on the cluster. Pipeline and Trigger checks gracefully degrade — they report "not found" instead of crashing when the Tekton CRDs don't exist.

Pod won't start (ImagePullBackOff) Check that the image in manifests/deployment.yaml matches the tag you pushed to your registry. Verify the image is accessible from the cluster.

Dashboard loads but shows stale data The backend caches results for cache_ttl_seconds (default 30s). If you need immediate updates, you can lower this value in the ConfigMap and restart the pod.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages