feat: Add a way to mount PVCs into Pipeline - #907
Conversation
|
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
a1c40e0 to
977adef
Compare
|
Had a read through the Python side of this (I've been in 1. The field says: # When True the compiler injects a KALE_VOLUME_<NAME> env var into every
# pipeline step alongside the mount_pvc call, making the mount path
# discoverable at runtime without hard-coding it.
expose_as_env_var = Field(type=bool, default=False)but {%- for volume in volumes %}
{%- if volume.type == 'pvc' %}
kubernetes.mount_pvc({{ step.name }}_task, pvc_name="{{ volume.name }}", mount_path="{{ volume.mount_point }}")
{%- endif %}
{%- endfor %}and If it's deliberately staged like the snapshot fields, it'd help to say so the same way — those carry an explicit "parsed and stored but have no effect on compilation" note, and this one reads as implemented. Otherwise it's a missing 2. except Exception as e:
... # returns []The docstring is upfront that this is for graceful degradation, which is fair for a combobox. The part I'd push on: a It's also the opposite direction from #906, which is currently making the other silent RPC failure (unreachable KFP) visible and actionable. Would it be worth letting a permission error through — or returning something the UI can distinguish — so the two RPC paths behave consistently? Small note: Happy to take another pass once the later commits land. |
|
hi @harshhh817 thanks for the review, I want to add most of this in other commits, I am just doing this in smaller parts in draft PR so the CI gets triggered on every commit and I can check that nothing breaks. I will let you know when this PR is ready for full review. |
ddd451a to
b74cb3a
Compare
|
Preview of the mounting volumes functionality: Untitled.video.mp4 |
|
hi @Fruchix @jesuino @StefanoFioravanzo @hmtosi @harshhh817 the PR for mounting volumes in Kale is ready for review! |
There was a problem hiding this comment.
Pull request overview
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Implements PVC selection and mounting support for KFP v2 pipelines, including a new JupyterLab “Volumes” panel to configure PVC mounts and optional env-var exposure, while removing legacy ROK/KFP v1 volume machinery.
Changes:
- Add Volumes panel UI (add/edit/select-from-notebook) and persist
volumesin notebook metadata. - Add RPC endpoints to list PVCs and notebook pod PVC mounts; add compiler-time warning for ReadWriteOnce PVCs.
- Update pipeline template to emit
kubernetes.mount_pvc(...)per step and optionally injectKALE_VOLUME_*env vars; add/adjust tests and fixtures.
Reviewed changes
Copilot reviewed 31 out of 31 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| labextension/style/index.css | Adds dedicated styling for the new Volumes panel UI. |
| labextension/src/widgets/hooks/useNotebookMetadata.ts | Adds updateVolumes metadata updater for persistence. |
| labextension/src/widgets/LeftPanelTypes.ts | Introduces IVolumeConfig and volumes metadata field + default. |
| labextension/src/widgets/LeftPanel.tsx | Renders the new VolumesPanel in the left panel. |
| labextension/src/lib/RPCUtils.tsx | Removes legacy Rok tooltip helper (ROK deprecation). |
| labextension/src/lib/Commands.ts | Adds RPC wrappers listPvcs and listNotebookVolumes. |
| labextension/src/components/volumes/volumeUtils.ts | Adds env-var name derivation and shared volume form types. |
| labextension/src/components/volumes/VolumeRow.tsx | Adds row UI for a configured volume + optional copy env-var. |
| labextension/src/components/volumes/NotebookVolumesDialog.tsx | Adds dialog to select existing notebook pod PVC mounts. |
| labextension/src/components/volumes/AddVolumeDialog.tsx | Adds add/edit dialog with PVC suggestions and validation. |
| labextension/src/components/VolumesPanel.tsx | Adds top-level volumes list management + dialogs + copy behavior. |
| labextension/src/components/AnnotationInput.tsx | Deletes legacy volume annotation UI component. |
| labextension/src/components/AdvancedSettings.tsx | Removes volumes panel embedding and related styled wrappers. |
| kale/tests/unit_tests/test_rpc_nb.py | Adds unit tests for list_pvcs and get_pvc_access_modes. |
| kale/tests/unit_tests/test_config.py | Updates marshal-path tests and adds expose_as_env_var coverage. |
| kale/tests/unit_tests/test_compiler.py | Adds test for the Jinja to_kale_env_var_name filter. |
| kale/tests/e2e/test_e2e.py | Extends e2e goldens to include mount_pvc scenarios. |
| kale/tests/assets/notebooks/mount_pvc.ipynb | Adds notebook fixture for PVC mount compilation. |
| kale/tests/assets/notebooks/mount_pvc_env_var.ipynb | Adds notebook fixture for PVC mount + env-var exposure. |
| kale/tests/assets/kfp_dsl/titanic.py | Removes legacy golden referencing old snapshot/volumes API. |
| kale/tests/assets/kfp_dsl/mount_pvc.py | Adds golden compiled DSL output for PVC mounting. |
| kale/tests/assets/kfp_dsl/mount_pvc_env_var.py | Adds golden compiled DSL output for PVC + env-var exposure. |
| kale/templates/pipeline_template.jinja2 | Emits mount_pvc and optional env vars per step; conditional import. |
| kale/rpc/nb.py | Adds list_pvcs / list_volumes RPCs and removes snapshot env handling. |
| kale/processors/nbprocessor.py | Clarifies snapshot_volumes as forward-compatible/no-op for v2. |
| kale/pipeline.py | Removes marshal volume logic and adds expose_as_env_var to VolumeConfig. |
| kale/compiler.py | Adds RWO PVC warning and registers to_kale_env_var_name Jinja filter. |
| kale/common/podutils.py | Adds env-var fallbacks for namespace/pod name to support local dev. |
| kale/common/k8sutils.py | Adds best-effort helper to fetch PVC access modes. |
| kale/cli.py | Removes old CLI flags tied to legacy volume machinery. |
| FAQ.md | Removes outdated Rok and RWX/RWO guidance tied to old volume approach. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Took another pass now that it's ready. One thing on the derivation: template_env.filters["to_kale_env_var_name"] = lambda s: (
"KALE_VOLUME_" + re.sub(r"[^A-Z0-9]", "_", s.upper())
)Every non-alphanumeric collapses to
If two such volumes are both mounted with Low probability (you'd need two PVCs differing only in separator), but it's the silent kind. You already guard the analogous case for mount paths — Separately, The rest reads well to me: |
Signed-off-by: Adam Maly <amaly@redhat.com>
…nja template + tests Signed-off-by: Adam Maly <amaly@redhat.com>
Signed-off-by: Adam Maly <amaly@redhat.com>
Signed-off-by: Adam Maly <amaly@redhat.com>
Signed-off-by: Adam Maly <amaly@redhat.com>
Signed-off-by: Adam Maly <amaly@redhat.com>
Signed-off-by: Adam Maly <amaly@redhat.com>
9a7212e to
4601173
Compare
Signed-off-by: Adam Maly <amaly@redhat.com>
016d89f to
8073dd1
Compare
hey @harshhh817 thanks for your review! Good point with the env vars, I think it is not likely to happen but I added safeguard (both in UI and compile) to ensure that the PVCs do not have same env vars. For list_pvcs I decided to leave it as it is for now - there is still UI text saying that no PVC was found which I think is enough. If it causes trouble for users we can create an issue and add some better error message later. |
There was a problem hiding this comment.
Thanks for your work on this! Please see my comments and here are some UI suggestions:
- I would keep the advanced settings message always on the bottom. Volumes being after it is just strange:
- If I understand correctly the "Select from Notebook" will only make sense when Kale is running on a Notebook that is running on Kubernetes, correct? I would rethink the form in a way that the add from notebook is not this big not proportional button and perhaps disable it if Kale is not running on a pod or if there's no volume available
Finally I missed the steps to test this in your PR. I did the following and I can say that the feature is working well!
- Created this PVC on Kubernetes:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myvolume
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Mi
storageClassName: standard
- Then I created the following pipeline in Kale:
- I can see that the volume was mounted,
But HTML reports are all empty and it is happening for other pipelines too. I wonder if this broke here or if it was broken after the KFP update to 2.17and it worked as expected:
…er button.. Signed-off-by: Adam Maly <amaly@redhat.com>
|
@jesuino thanks for review! I agree with all the points and I added them to PR |
Signed-off-by: Adam Maly <amaly@redhat.com>
jesuino
left a comment
There was a problem hiding this comment.
Thanks for your work on this!
This is working correctly and do improve performance for pipelines, especially when does heavily uses storage.
|
/approve |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: ederign The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Summary
This PR implements issue #843: users can now select PersistentVolumeClaims (PVCs) from the Kale JupyterLab panel and have them automatically mounted into every step of the compiled KFP v2 pipeline via
kubernetes.mount_pvc(...).What was deleted and why
ROK / KFP v1 volume machinery — the entire legacy volume system (ROK snapshot integration, KFP v1
VolumeOp/dsl.PipelineVolumewrappers, and the CLI flags that drove them) was removed. ROK is not used with KFP v2 and the old code was dead weight that made the config model harder to extend.marshal_volumewas cleaned out fromVolumeConfigentirely (onlymarshal_pathas a plain field remains, used for the artifact-based data-passing path). Also golden test file titanic.py was deleted since it was referencing old snapshot and volumes API.Backend changes
kale/common/podutils.pyget_namespace()now also acceptsKALE_NAMESPACEenv var (for local dev);get_pod_name()now also acceptsKALE_POD_NAME. This lets the Volumes panel work when runningmake jupyteroutside a cluster.kale/rpc/nb.pylist_pvcs(request)— lists all PVCs in the current namespace, returns sorted names; degrades to[]on any error. Addedlist_notebook_volumes(request)— introspects the notebook pod spec to return all PVC mounts as{"name", "mount_point"}dicts; also degrades to[]on error. Removed the now-deadfinal_snapshotfield fromexplore_notebook()'s response (leftover from the ROK snapshot cleanup).kale/common/k8sutils.pyget_pvc_access_modes()— best-effort helper to read a PVC'saccessModes, returns[]on error.kale/templates/pipeline_template.jinja2volumes: emitskubernetes.mount_pvc(…)for everytype == 'pvc'entry, and additionally emitstask.set_env_variable(name="KALE_VOLUME_<NAME>", value="<mount_path>")whenexpose_as_env_varisTrue. Theto_kale_env_var_nameJinja filter is registered incompiler.pyto handle name normalisation (my-data→KALE_VOLUME_MY_DATA).kale/compiler.py_warn_rwo_volumes()— checks each PVC'saccessModesat compile time and emits a[KALE WARNING]log if any volume isReadWriteOnce, because concurrent mounts across nodes will fail at runtime. Added_check_unique_volume_env_vars()— fails the compile with a clear error if two PVCs would derive the sameKALE_VOLUME_*env var name, instead of silently letting the second overwrite the first at runtime.kale/tests/assets/kfp_dsl/mount_pvc.pyraw-dataPVC mounted at/dataon every step, no env var.kale/tests/assets/kfp_dsl/mount_pvc_env_var.pyexpose_as_env_var=True, so each step also hasset_env_variable(name="KALE_VOLUME_RAW_DATA", value="/data").kale/tests/unit_tests/test_rpc_nb.pylist_pvcs,list_notebook_volumes(sorted mounts, non-PVC volumes ignored, dedup across containers, empty pod, namespace/pod read errors) andget_pvc_access_modes.Frontend changes
labextension/src/widgets/LeftPanelTypes.tsIVolumeConfigtype (name,mount_point,type: 'pvc',expose_as_env_var?) and thevolumesfield toIKaleNotebookMetadata.labextension/src/components/volumes/volumeUtils.tsderiveEnvVarName()(mirrors the backend Jinja filter),getMountPathError()(POSIX path validation — must be absolute, no trailing slash, no./..traversal segments, only[A-Za-z0-9._-]per segment),IAddFormState,INotebookVolume.labextension/src/components/volumes/VolumeRow.tsxKALE_VOLUME_*env var name with a one-click copy button.labextension/src/components/volumes/AddVolumeDialog.tsxnb.list_pvcsfor suggestions, validation for duplicate volume names, duplicate mount paths, and POSIX-invalid mount paths, and an "Expose mount path as env var" checkbox with a live preview + duplicate-env-var check. The "Select from notebook" button (which opensNotebookVolumesDialog) is now sized to its content instead of stretching full-width. Helper text under the PVC name / Mount path fields now uses the same readable color as the rest of the form instead of the default (too-dark-for-dark-theme) MUI text color.labextension/src/components/volumes/NotebookVolumesDialog.tsxnb.list_notebook_volumesto show PVCs currently mounted on the notebook pod. Each row has a checkbox to include it and a second "env" toggle to setexpose_as_env_var. Supports "Select all".labextension/src/components/VolumesPanel.tsxVolumeRows, tracks duplicate mount paths, drives the add/edit dialogs, and handles clipboard copy with a 2-second "Copied!" feedback.labextension/src/widgets/hooks/useNotebookMetadata.tsupdateVolumescallback wired to notebook metadata persistence.labextension/src/widgets/LeftPanel.tsxVolumesPanelin the "Volumes" section of the left panel, passingvolumesfrom metadata and theupdateVolumessetter. The "Advanced Kale settings live in JupyterLab Settings" notice is now always rendered last (after Pipeline Metadata and Volumes), instead of being sandwiched in between them.labextension/src/lib/Commands.tslistPvcs()andlistNotebookVolumes()— thin RPC wrappers overnb.list_pvcsandnb.list_notebook_volumes. Removed a stale reference toexploration.final_snapshot(that field no longer exists on the backend response, so the "Resuming notebook before/after step" message was always silently wrong — it now just says "Resuming notebook at step").Testing steps
Automated tests
pytest kale/tests/unit_tests/test_rpc_nb.py—list_pvcs,list_notebook_volumes,get_pvc_access_modes.pytest kale/tests/unit_tests/test_compiler.py—_check_unique_volume_env_vars,to_kale_env_var_namefilter.pytest kale/tests/unit_tests/test_config.py—VolumeConfig/expose_as_env_varround-trip throughNotebookConfig.pytest kale/tests/e2e/test_e2e.py— golden-file DSL compilation for themount_pvc/mount_pvc_env_varnotebook fixtures.Manual UI/e2e testing
myvolume./data) and, optionally, check "Expose mount path as env var" and confirm theKALE_VOLUME_MYVOLUMEpreview.data(not absolute),/my data(space), or/../etc/passwd(traversal) → the POSIX validation error should appear and block submission.kubernetes.mount_pvc(...)for every step, andtask.set_env_variable(name="KALE_VOLUME_...", ...)if "expose as env var" was checked.ReadWriteOnce, the Kale compile output logs[KALE WARNING] PVC '...' has accessMode ReadWriteOnce....What still needs to be done
docs/proposals/0843-mount-volumes/README.md).