Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new marimo notebook that walks ARENA users through Kubernetes basics (namespace, ConfigMap, Deployment, Service, Job, cleanup) by applying real manifests against a CKS cluster, either via in-cluster service-account credentials or a local kubectl context.
Changes:
- New
arena/notebooks/cks_kubernetes.pynotebook with helper functions for shelling out tokubectl, applying YAML manifests via stdin, and rendering imperative/declarative step cells with Run buttons. - In-cluster kubeconfig generation from the mounted service-account token, written to
/tmp/arena-incluster-kubectl.yamland exported viaKUBECONFIG. - Lab content covering ConfigMap CRUD, Deployment scaling/self-healing/rolling update, Service + Endpoints, Job to completion, and namespace cleanup.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
c09ff02 to
0453cfb
Compare
|
@MYanello Ready for another look, I've been through it a dozen times now and I think I've hit anything I can refactor to. No rush, we can pick this up another day. |
| """Treat failed commands as false while preserving string truthiness for stdout.""" | ||
| return self.ok and len(self) > 0 |
There was a problem hiding this comment.
I don't think this is correct. What happens for a failed command that produces non empty stdout?
| current-context: in-cluster | ||
| """ | ||
| with open(kubeconfig_path, "w", encoding="utf-8") as file: | ||
| file.write(kubeconfig) |
There was a problem hiding this comment.
nit: make this file 600 perms
| "2. List Namespaces", | ||
| "kubectl get namespace", | ||
| env_b2, | ||
| env_b2.value > 0, |
There was a problem hiding this comment.
All of these >0 buttons will stay permanently true so reclicking won't work. this may be no big deal, but worth mentioning
There was a problem hiding this comment.
Also means that on any rerun to the cell (due to cm_editor changing I think), it will re-click all the buttons since .value will always be >0 after first click. Maybe inconsequential but should be considered
There was a problem hiding this comment.
I think if you use a mo.ui.form for this it will only run on form submission, so closer to what you probably intend
| dep_b5 = mo.ui.button(**RUN_BUTTON) | ||
| dep_b6 = mo.ui.button(**RUN_BUTTON) | ||
| dep_b7 = mo.ui.button(**RUN_BUTTON) | ||
| dep_b8 = mo.ui.button(**RUN_BUTTON) |
| if result.returncode == 0: | ||
| if not quiet: | ||
| print(f"✓ {cmd_display}") | ||
| if result.stdout.strip(): | ||
| print(result.stdout.rstrip()) |
| check: bool = False, | ||
| stream: bool = False, | ||
| timeout: int | None = None, | ||
| input: str | None = None, |
| def shell( # noqa: C901 | ||
| command: str | list, | ||
| quiet: bool = False, | ||
| check: bool = False, | ||
| stream: bool = False, | ||
| timeout: int | None = None, | ||
| input: str | None = None, | ||
| ) -> ShellResult: |
| local_context = shell("kubectl config current-context", quiet=True) | ||
| cluster_probe = None | ||
| if local_context.ok: | ||
| cluster_probe = shell("kubectl cluster-info", quiet=True, timeout=15) | ||
| if cluster_probe.ok: | ||
| # Non-fatal Python-side connectivity probe — kubectl will still work even if this fails. | ||
| try: | ||
| K8s().validate_config() | ||
| except KubernetesConfigError: | ||
| pass | ||
| return True, f"Using local kubectl context `{local_context.strip()}`." | ||
|
|
||
| # No local kubectl context — try in-cluster. `load_incluster_config()` is the canonical | ||
| # detection: it succeeds only when the SA token + CA + service env vars are all in place. | ||
| try: | ||
| config.load_incluster_config() | ||
| except config.ConfigException as e: | ||
| details = ( | ||
| cluster_probe.stderr.strip() if cluster_probe is not None else local_context.stderr.strip() | ||
| ) or str(e) | ||
| return ( | ||
| False, | ||
| "kubectl is installed but no cluster context is usable. " | ||
| "If running locally, set a context with `kubectl config use-context <name>`. " | ||
| f"Details: `{details}`", | ||
| ) | ||
|
|
||
| _write_incluster_kubeconfig(KUBECTL_INCLUSTER_KUBECONFIG_PATH) | ||
| os.environ["KUBECONFIG"] = KUBECTL_INCLUSTER_KUBECONFIG_PATH | ||
| return True, f"Using in-cluster service-account context via `{KUBECTL_INCLUSTER_KUBECONFIG_PATH}`." |
| LAB_NAMESPACE = "arena-k8s-lab" | ||
| LAB_LABEL_KEY = "app.kubernetes.io/part-of" | ||
| LAB_LABEL_VALUE = "arena-k8s-lab" |
| reconcile_cmd = ( | ||
| f"echo '=== pods BEFORE delete ==='; " | ||
| f"kubectl -n {LAB_NAMESPACE} get pods -l app={DEPLOYMENT_NAME} -o wide; " | ||
| f"POD=$(kubectl -n {LAB_NAMESPACE} get pods -l app={DEPLOYMENT_NAME} " | ||
| f"-o jsonpath='{{.items[0].metadata.name}}'); " | ||
| f'echo; echo "=== deleting pod: $POD ==="; ' | ||
| f'kubectl -n {LAB_NAMESPACE} delete pod "$POD" --wait=false; ' | ||
| f"echo; echo '=== waiting 6s for the ReplicaSet controller to react ==='; sleep 6; " | ||
| f"echo; echo '=== pods AFTER delete ==='; " | ||
| f"kubectl -n {LAB_NAMESPACE} get pods -l app={DEPLOYMENT_NAME} -o wide" | ||
| ) |
No description provided.