Skip to content

Commit 5bd5898

Browse files
authored
Merge pull request #376 from OpenMS/claude/demo-workspace-storage-k8s-azhkG
Support configurable demo workspace source directories
2 parents 64f43e2 + 4ab1288 commit 5bd5898

5 files changed

Lines changed: 53 additions & 2 deletions

File tree

clean-up-workspaces.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
remaining_directories = []
2424
# Iterate through directories in workspaces_directory
2525
for directory in workspaces_directory.iterdir():
26+
# Skip hidden top-level directories (e.g. .demos/ holds seeded demo workspaces)
27+
if directory.name.startswith("."):
28+
continue
2629
# Check if it's a directory
2730
if directory.is_dir():
2831
# Get the directory's modification time

docs/kubernetes-deployment.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,21 @@ PersistentVolumeClaim `workspaces-pvc`:
107107
- `storageClassName: cinder-csi`
108108
- `resources.requests.storage: 500Gi`
109109

110+
Demo workspaces live under a hidden `.demos/` subdirectory of this PVC (see [Demo workspaces](#demo-workspaces) below). User workspaces live at the PVC root, one directory per session UUID.
111+
112+
### Demo workspaces
113+
Demo workspaces are seeded onto the `workspaces-pvc` at `/workspaces-streamlit-template/.demos/` by the `seed-demos` initContainer on the Streamlit Deployment. The init runs `cp -rn /app/example-data/workspaces/. /workspaces-streamlit-template/.demos/` — new demos shipped in an image appear after redeploy, but existing entries on the PV (including admin-saved demos and edits) are preserved.
114+
115+
The ConfigMap override points `demo_workspaces.source_dirs` at `/workspaces-streamlit-template/.demos`, so both Streamlit pods and RQ workers read demos from the PV. The "Save as Demo" admin flow writes to the same path.
116+
117+
To force a re-seed of a specific demo, delete it on the PV and restart the Streamlit Deployment:
118+
```
119+
kubectl exec deploy/streamlit -- rm -rf /workspaces-streamlit-template/.demos/<name>
120+
kubectl rollout restart deploy/streamlit
121+
```
122+
123+
`clean-up-workspaces.py` skips any top-level directory whose name starts with `.`, so the nightly cleanup cron does not touch `.demos/`.
124+
110125
### `streamlit-deployment.yaml`
111126
Main Streamlit Deployment. Key fields:
112127
- `replicas: 2` (scales to N)
@@ -116,6 +131,7 @@ Main Streamlit Deployment. Key fields:
116131
- Mounts `settings-overrides.json` from the ConfigMap as a `subPath`
117132
- Readiness and liveness probes hit `/_stcore/health`
118133
- Pod affinity: `volume-group: workspaces`
134+
- `seed-demos` initContainer merges image-shipped demos into `.demos/` on the PVC (see [Demo workspaces](#demo-workspaces))
119135

120136
### `streamlit-service.yaml`
121137
ClusterIP Service exposing Streamlit on port 8501.

k8s/base/configmap.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,9 @@ metadata:
55
data:
66
settings-overrides.json: |
77
{
8-
"online_deployment": true
8+
"online_deployment": true,
9+
"demo_workspaces": {
10+
"enabled": true,
11+
"source_dirs": ["/workspaces-streamlit-template/.demos"]
12+
}
913
}

k8s/base/streamlit-deployment.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@ spec:
2525
values:
2626
- workspaces
2727
topologyKey: kubernetes.io/hostname
28+
initContainers:
29+
- name: seed-demos
30+
image: openms-streamlit
31+
imagePullPolicy: Always
32+
command: ["/bin/sh", "-c"]
33+
args:
34+
- |
35+
set -eu
36+
mkdir -p /workspaces-streamlit-template/.demos
37+
cp -rn /app/example-data/workspaces/. /workspaces-streamlit-template/.demos/
38+
volumeMounts:
39+
- name: workspaces
40+
mountPath: /workspaces-streamlit-template
2841
containers:
2942
- name: streamlit
3043
image: openms-streamlit

src/common/admin.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,25 @@ def get_demo_target_dir() -> Path:
5151
"""
5252
Get the directory where demo workspaces are stored.
5353
54+
Reads from settings.demo_workspaces.source_dirs (first entry wins),
55+
supporting both the list form and the legacy string form. Falls back
56+
to example-data/workspaces when settings are unavailable (e.g. in tests).
57+
5458
Returns:
5559
Path: The demo workspaces directory.
5660
"""
57-
return Path("example-data/workspaces")
61+
default = Path("example-data/workspaces")
62+
try:
63+
demo_config = st.session_state.settings.get("demo_workspaces", {})
64+
except (AttributeError, KeyError):
65+
return default
66+
67+
dirs = demo_config.get("source_dirs", demo_config.get("source_dir"))
68+
if isinstance(dirs, str):
69+
return Path(dirs)
70+
if isinstance(dirs, list) and dirs:
71+
return Path(dirs[0])
72+
return default
5873

5974

6075
def demo_exists(demo_name: str) -> bool:

0 commit comments

Comments
 (0)