feat (volumes): voeg volumes router toe aan backend
Nieuw bestand control/app_volumes.py met Libpod volume operaties:
- GET /volumes — lijst alle volumes (optioneel ?filters=key=value)
- POST /volumes — volume aanmaken (name, driver, labels, driverOpts)
- GET /volumes/{name} — details van één volume
- GET /volumes/{name}/exists — bestaanskontrolle (204 → true, 404 → false)
- DELETE /volumes/{name} — volume verwijderen (?force=true optioneel)
- POST /volumes/prune — ⚠️ verwijdert alle ongebruikte volumes
Filters: key=value formaat wordt automatisch omgezet naar
{"key":["value"]} JSON dat de Libpod API verwacht.
Containerfile: COPY app_volumes.py toegevoegd.
app.py: init_volumes_router geregistreerd.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from typing import Dict, Optional
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Query
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
def _normalize_filters(filters: str) -> str:
|
||||
"""Zet key=value formaat om naar {"key":["value"]} JSON dat Libpod verwacht.
|
||||
Als de waarde al met '{' begint, wordt hij ongewijzigd doorgegeven."""
|
||||
if filters.startswith("{"):
|
||||
return filters
|
||||
# key=value → {"key": ["value"]}
|
||||
if "=" in filters:
|
||||
key, _, value = filters.partition("=")
|
||||
return json.dumps({key.strip(): [value.strip()]})
|
||||
# Alleen een key zonder waarde → {"key": ["true"]}
|
||||
return json.dumps({filters.strip(): ["true"]})
|
||||
|
||||
|
||||
class VolumeCreateRequest(BaseModel):
|
||||
name: str
|
||||
driver: str = "local"
|
||||
driverOpts: Optional[Dict[str, str]] = None
|
||||
labels: Optional[Dict[str, str]] = None
|
||||
|
||||
|
||||
def _raise_on_error(resp):
|
||||
if 200 <= resp.status_code < 300:
|
||||
return
|
||||
raise HTTPException(status_code=resp.status_code, detail=resp.text)
|
||||
|
||||
|
||||
def init_volumes_router(session, podman_api_base: str) -> APIRouter:
|
||||
router = APIRouter(prefix="/volumes", tags=["volumes"])
|
||||
|
||||
@router.get("")
|
||||
def list_volumes(filters: Optional[str] = Query(None)):
|
||||
url = f"{podman_api_base}/libpod/volumes/json"
|
||||
params = {}
|
||||
if filters is not None:
|
||||
params["filters"] = _normalize_filters(filters)
|
||||
resp = session.get(url, params=params)
|
||||
_raise_on_error(resp)
|
||||
return resp.json()
|
||||
|
||||
@router.post("")
|
||||
def create_volume(req: VolumeCreateRequest):
|
||||
url = f"{podman_api_base}/libpod/volumes/create"
|
||||
body: dict = {"name": req.name, "driver": req.driver}
|
||||
if req.driverOpts:
|
||||
body["driverOpts"] = req.driverOpts
|
||||
if req.labels:
|
||||
body["labels"] = req.labels
|
||||
resp = session.post(url, json=body)
|
||||
_raise_on_error(resp)
|
||||
return resp.json()
|
||||
|
||||
@router.post("/prune")
|
||||
def prune_volumes():
|
||||
"""⚠️ Destructief: verwijdert alle ongebruikte volumes permanent. Niet terug te draaien."""
|
||||
url = f"{podman_api_base}/libpod/volumes/prune"
|
||||
resp = session.post(url)
|
||||
_raise_on_error(resp)
|
||||
return resp.json()
|
||||
|
||||
@router.get("/{name}/exists")
|
||||
def volume_exists(name: str):
|
||||
url = f"{podman_api_base}/libpod/volumes/{name}/exists"
|
||||
resp = session.get(url)
|
||||
if resp.status_code == 204:
|
||||
return {"exists": True}
|
||||
if resp.status_code == 404:
|
||||
return {"exists": False}
|
||||
_raise_on_error(resp)
|
||||
|
||||
@router.get("/{name}")
|
||||
def get_volume(name: str):
|
||||
url = f"{podman_api_base}/libpod/volumes/{name}/json"
|
||||
resp = session.get(url)
|
||||
_raise_on_error(resp)
|
||||
return resp.json()
|
||||
|
||||
@router.delete("/{name}")
|
||||
def remove_volume(name: str, force: bool = Query(False)):
|
||||
"""⚠️ Destructief: verwijdert een volume permanent. Niet terug te draaien als het volume data bevat."""
|
||||
url = f"{podman_api_base}/libpod/volumes/{name}"
|
||||
params = {"force": str(force).lower()}
|
||||
resp = session.delete(url, params=params)
|
||||
if resp.status_code == 204:
|
||||
return {"ok": True}
|
||||
_raise_on_error(resp)
|
||||
|
||||
return router
|
||||
Reference in New Issue
Block a user