diff --git a/backend/__pycache__/k8s_utils.cpython-313.pyc b/backend/__pycache__/k8s_utils.cpython-313.pyc index f659c94..06e2aff 100644 Binary files a/backend/__pycache__/k8s_utils.cpython-313.pyc and b/backend/__pycache__/k8s_utils.cpython-313.pyc differ diff --git a/backend/__pycache__/main.cpython-313.pyc b/backend/__pycache__/main.cpython-313.pyc index 50ff6b0..ed4509a 100644 Binary files a/backend/__pycache__/main.cpython-313.pyc and b/backend/__pycache__/main.cpython-313.pyc differ diff --git a/backend/k8s_utils.py b/backend/k8s_utils.py index cc4c116..7791aac 100644 --- a/backend/k8s_utils.py +++ b/backend/k8s_utils.py @@ -1,5 +1,6 @@ import subprocess import json +import re def get_namespaces(): output = subprocess.check_output(["kubectl", "get", "ns", "-o", "json"]) @@ -10,3 +11,18 @@ def get_pvcs(namespace: str): output = subprocess.check_output(["kubectl", "get", "pvc", "-n", namespace, "-o", "json"]) data = json.loads(output) return [item["metadata"]["name"] for item in data["items"]] + +def get_all_backup_pvcs(): + output = subprocess.check_output(["kubectl", "get", "pvc", "-A", "-o", "json"]) + data = json.loads(output) + + backup_pvcs = [] + for item in data["items"]: + name = item["metadata"]["name"] + namespace = item["metadata"]["namespace"] + if re.match(r"^snapix-bkp-temp-", name): + backup_pvcs.append({ + "name": name, + "namespace": namespace + }) + return backup_pvcs \ No newline at end of file diff --git a/backend/main.py b/backend/main.py index 5beb868..2cf658d 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,7 +1,7 @@ from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from models import BackupRequest, RestoreRequest -from k8s_utils import get_namespaces, get_pvcs +from k8s_utils import get_namespaces, get_pvcs, get_all_backup_pvcs from backup_manager import create_backup, restore_backup app = FastAPI() @@ -33,6 +33,11 @@ def restore_pvc(request: RestoreRequest): return {"message": "Restore job created."} +@app.get("/backup-pvcs") +def list_backup_pvcs(): + return get_all_backup_pvcs() + + if __name__ == "__main__": import uvicorn uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True) \ No newline at end of file diff --git a/frontend/src/api/snapix.js b/frontend/src/api/snapix.js index 3232d23..00cda1c 100644 --- a/frontend/src/api/snapix.js +++ b/frontend/src/api/snapix.js @@ -8,3 +8,5 @@ export const getNamespaces = () => api.get('/namespaces'); export const getPVCs = (namespace) => api.get(`/pvcs/${namespace}`); export const createBackup = (payload) => api.post('/backup', payload); export const restoreBackup = (payload) => api.post('/restore', payload); +export const getBackupPVCs = () => api.get('/backup-pvcs'); + diff --git a/frontend/src/components/RestoreForm.jsx b/frontend/src/components/RestoreForm.jsx index 3438e90..7751662 100644 --- a/frontend/src/components/RestoreForm.jsx +++ b/frontend/src/components/RestoreForm.jsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react'; -import { restoreBackup, getNamespaces, getPVCs } from '../api/snapix'; -import { Button, Input } from '@mui/base'; +import { restoreBackup, getNamespaces, getBackupPVCs } from '../api/snapix'; +import { Button } from '@mui/base'; import '../style/RestoreForm.css'; export default function RestoreForm() { @@ -8,7 +8,7 @@ export default function RestoreForm() { const [targetNs, setTargetNs] = useState(''); const [targetPvc, setTargetPvc] = useState(''); const [namespaces, setNamespaces] = useState([]); - const [pvcs, setPvcs] = useState([]); + const [backupPvcs, setBackupPvcs] = useState([]); useEffect(() => { getNamespaces().then(res => setNamespaces(res.data)); @@ -16,9 +16,13 @@ export default function RestoreForm() { useEffect(() => { if (targetNs) { - getPVCs(targetNs).then(res => setPvcs(res.data)); + getBackupPVCs().then(res => { + // Filter backup PVCs only for the selected namespace + const filtered = res.data.filter(pvc => pvc.namespace === targetNs); + setBackupPvcs(filtered); + }); } else { - setPvcs([]); + setBackupPvcs([]); } }, [targetNs]); @@ -38,43 +42,38 @@ export default function RestoreForm() {

🔁 Restore PVC

-
- - setBackupName(e.target.value)} - className="restore-input" - placeholder="The exact name of the backup to restore" - /> -
-
+
+ +
+ +
- + placeholder="the exact name of the pvc of your app" + />