# KubeKosh Configuration Schema Reference KubeKosh uses two primary JSON files to define its curriculum, learning paths, and exam configurations: 1. **Bundles (`scenarios/bundles.json`)**: Defines the high-level study bundles (e.g., CKA, CKAD, CKS), active highlights, durations for exams, and lists of included scenarios. 2. **Scenarios (`scenarios/scenarios.json`)**: Defines individual exercises, hands-on tasks, multiple-choice questions (MCQs), environment preparations, and automated validation scripts. --- ## 1. Bundles Schema (`scenarios/bundles.json`) Bundles are defined as a JSON array of objects. Each bundle organizes a learning track or mock exam. ### Schema Fields * **`id`** *(string, required)*: A unique, kebab-case identifier for the bundle (e.g., `k8s-basics`). * **`name`** *(string, required)*: The human-readable name of the bundle shown in navigation (e.g., `Kubernetes Basics`). * **`icon`** *(string, required)*: An emoji or glyph representing the bundle (e.g., `🌱`). * **`tagline`** *(string, required)*: A short summary of the bundle's objectives. * **`color`** *(string, required)*: Hex color code representing the bundle's UI identity/accent color (e.g., `#3fb950`). * **`colorDim`** *(string, required)*: Translucent RGBA color matching the accent color at low opacity, used for UI row highlighting (e.g., `rgba(63,185,80,0.12)`). * **`exam_minutes`** *(number, required)*: The time limit allocated for the mock exam in minutes (e.g., `60`). * **`scenario_ids`** *(array of strings, required)*: List of scenario IDs belonging to this bundle in the order they should appear. ### Example Bundle ```json { "id": "k8s-basics", "name": "Kubernetes Basics", "icon": "🌱", "tagline": "Core concepts for beginners", "color": "#3fb950", "colorDim": "rgba(63,185,80,0.12)", "exam_minutes": 60, "scenario_ids": [ "pod-basics-mcq", "kubectl-essentials-mcq", "namespaces-basics", "deploy-nginx" ] } ``` --- ## 2. Scenarios Schema (`scenarios/scenarios.json`) Scenarios are defined as a JSON array of objects. A scenario can be either a hands-on console challenge (`"task"`) or a multiple-choice question (`"mcq"`). ### Common Fields (All Types) ```jsonc { "id": "unique-kebab-case-id", // string — unique scenario identifier "title": "Human-readable Title", // string — shown in sidebar list "category": "Workloads", // string — groups scenarios in sidebar accordion "difficulty": "Easy", // "Easy" | "Medium" | "Hard" "type": "task", // "task" | "mcq" "weight": 7, // number — points value (used for final grade scoring) "description": "## Markdown...", // string — problem statement supporting GitHub-flavored Markdown "hints": [...], // array — see Hints schema below "setup_commands": [...], // array — commands run on environment preparation "teardown_commands": [...], // array — optional — cleanup commands run after scenario completes "default_namespace": "default" // string — optional — default active namespace for the terminal } ``` --- ### Hints Schema Each hint is rendered as a collapsible card inside the Hints tab of the UI: ```jsonc { "title": "Short title for the hint card", "body": "Explanation text (plain text, no markdown format).", "command": "kubectl run nginx --image=nginx" // optional — renders a copyable code block } ``` --- ### Setup & Teardown Commands * **`setup_commands`**: Executed sequentially on the Kubernetes cluster when the user starts a scenario or clicks **"Prepare Environment"**. Useful for pre-deploying resources or injecting bugs. * **`teardown_commands`**: Optional cleanup commands run when moving away from or resetting a scenario. * Commands must be **objects** with a `command` key: ```jsonc "setup_commands": [ { "command": "kubectl create namespace debug" }, { "command": "kubectl create deployment broken-app --image=nginx:1.25 -n debug" } ] ``` * *Note:* Non-zero exit codes are tolerated (e.g., "namespace already exists" errors won't halt the pipeline). All commands execute as `root`. --- ### Type: `"task"` — Hands-On Scenario Requires the user to run shell commands in the interactive terminal. The system runs an automated validation sequence to check the cluster state. ```jsonc { "type": "task", "validation": { "description": "Check that deployment has been correctly configured", "commands": [ { "description": "Checks the running pods count", "command": "kubectl get deploy nginx -o jsonpath='{.status.readyReplicas}'", "expected_output": "3", "match": "exact" // "exact" | "contains" | "regex" } ] } } ``` #### Match Modes | Mode | Behaviour | | :--- | :--- | | `exact` | Trimmed stdout must exactly equal `expected_output`. | | `contains` | stdout must contain `expected_output` as a substring. | | `not_contains` | stdout must **not** contain `expected_output` as a substring. | | `regex` | stdout must match the regular expression in `expected_output`. | --- ### Type: `"mcq"` — Multiple Choice Question Renders a questionnaire block. No terminal is shown. The user answers by selecting an option. ```jsonc { "type": "mcq", "options": [ { "id": "a", "text": "Option A explanation" }, { "id": "b", "text": "Option B explanation" }, { "id": "c", "text": "Option C explanation" }, { "id": "d", "text": "Option D explanation" } ], "correct_option": "c", // must match one of the option IDs "explanation": "Detailed explanation of why C is the correct answer." // shown after submitting } ``` --- ## 3. Full Examples ### Full Example — Hands-On Task Scenario ```json { "id": "scale-deployment", "title": "Scale a Deployment", "category": "Workloads", "difficulty": "Easy", "type": "task", "weight": 4, "description": "## Scale the Deployment\n\nA deployment named `myapp` exists in the `default` namespace.\n\n**Scale it to 5 replicas.**", "hints": [ { "title": "Using kubectl scale", "body": "The scale subcommand lets you change the replica count imperatively.", "command": "kubectl scale deployment myapp --replicas=5" } ], "setup_commands": [ { "command": "kubectl create deployment myapp --image=nginx:1.25 --replicas=1" } ], "teardown_commands": [ { "command": "kubectl delete deployment myapp --ignore-not-found" } ], "default_namespace": "default", "validation": { "description": "Checks that myapp has 5 ready replicas.", "commands": [ { "description": "myapp has 5 ready replicas", "command": "kubectl get deployment myapp -o jsonpath='{.status.readyReplicas}'", "expected_output": "5", "match": "exact" } ] } } ``` ### Full Example — MCQ Scenario ```json { "id": "service-types-mcq", "title": "Kubernetes Service Types", "category": "Networking", "difficulty": "Easy", "type": "mcq", "weight": 3, "description": "## Kubernetes Service Types\n\nWhich `kubectl` command creates a ClusterIP service named `my-svc` exposing port 80 for a deployment named `my-app`?", "options": [ { "id": "a", "text": "kubectl expose deployment my-app --name=my-svc --port=80 --type=ClusterIP" }, { "id": "b", "text": "kubectl create service my-svc --port=80" }, { "id": "c", "text": "kubectl apply service my-app --port=80" }, { "id": "d", "text": "kubectl expose pod my-app --name=my-svc --port=80 --type=NodePort" } ], "correct_option": "a", "explanation": "`kubectl expose deployment` is the correct imperative command. It creates a Service targeting the deployment's pods. `--type=ClusterIP` is the default but explicit here for clarity.", "hints": [ { "title": "kubectl expose syntax", "body": "Use kubectl expose to create a Service from an existing resource. Specify the resource type, name, port, and service type.", "command": "kubectl expose deployment my-app --name=my-svc --port=80 --type=ClusterIP" } ], "setup_commands": [], "teardown_commands": [], "default_namespace": "default" } ```