docker_pyo3/
volume.rs

1use std::collections::HashMap;
2
3use docker_api::{
4    models::VolumeListResponse,
5    models::VolumePrune200Response,
6    opts::{VolumeCreateOpts, VolumeListOpts, VolumePruneOpts},
7    Volume, Volumes,
8};
9use pyo3::prelude::*;
10
11use crate::Pyo3Docker;
12use pyo3::exceptions;
13use pyo3::types::PyDict;
14use pythonize::pythonize;
15
16#[pymodule]
17pub fn volume(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
18    m.add_class::<Pyo3Volumes>()?;
19    m.add_class::<Pyo3Volume>()?;
20    Ok(())
21}
22
23/// Interface for managing Docker volumes collection.
24#[derive(Debug)]
25#[pyclass(name = "Volumes")]
26pub struct Pyo3Volumes(pub Volumes);
27
28/// Represents an individual Docker volume.
29#[derive(Debug)]
30#[pyclass(name = "Volume")]
31pub struct Pyo3Volume(pub Volume);
32
33#[pymethods]
34impl Pyo3Volumes {
35    #[new]
36    pub fn new(docker: Pyo3Docker) -> Self {
37        Pyo3Volumes(Volumes::new(docker.0))
38    }
39
40    /// Get a specific volume by name.
41    ///
42    /// Args:
43    ///     name: Volume name
44    ///
45    /// Returns:
46    ///     Volume: Volume instance
47    pub fn get(&self, name: &str) -> Pyo3Volume {
48        Pyo3Volume(self.0.get(name))
49    }
50
51    /// Remove unused volumes.
52    ///
53    /// Returns:
54    ///     dict: Prune results including volumes deleted and space reclaimed
55    pub fn prune(&self) -> PyResult<Py<PyAny>> {
56        let rv = __volumes_prune(&self.0, &Default::default());
57
58        match rv {
59            Ok(rv) => Ok(pythonize_this!(rv)),
60            Err(rv) => Err(py_sys_exception!(rv)),
61        }
62    }
63
64    /// List all volumes.
65    ///
66    /// Returns:
67    ///     dict: Volume list information
68    pub fn list(&self) -> PyResult<Py<PyAny>> {
69        let rv = __volumes_list(&self.0, &Default::default());
70
71        match rv {
72            Ok(rv) => Ok(pythonize_this!(rv)),
73            Err(rv) => Err(py_sys_exception!(rv)),
74        }
75    }
76
77    /// Create a new volume.
78    ///
79    /// Args:
80    ///     name: Volume name
81    ///     driver: Volume driver (e.g., "local")
82    ///     driver_opts: Driver-specific options as dict
83    ///     labels: Labels as dict (e.g., {"env": "prod"})
84    ///
85    /// Returns:
86    ///     dict: Created volume information
87    #[pyo3(signature = (name=None, driver=None, driver_opts=None, labels=None))]
88    pub fn create(
89        &self,
90        name: Option<&str>,
91        driver: Option<&str>,
92        driver_opts: Option<&Bound<'_, PyDict>>,
93        labels: Option<&Bound<'_, PyDict>>,
94    ) -> PyResult<Py<PyAny>> {
95        let mut opts = VolumeCreateOpts::builder();
96
97        let driver_opts_map: Option<HashMap<String, String>> = if driver_opts.is_some() {
98            Some(driver_opts.unwrap().extract().unwrap())
99        } else {
100            None
101        };
102        let driver_opts: Option<HashMap<&str, &str>> = driver_opts_map
103            .as_ref()
104            .map(|m| m.iter().map(|(k, v)| (k.as_str(), v.as_str())).collect());
105
106        let labels_map: Option<HashMap<String, String>> = if labels.is_some() {
107            Some(labels.unwrap().extract().unwrap())
108        } else {
109            None
110        };
111        let labels: Option<HashMap<&str, &str>> = labels_map
112            .as_ref()
113            .map(|m| m.iter().map(|(k, v)| (k.as_str(), v.as_str())).collect());
114
115        bo_setter!(name, opts);
116        bo_setter!(driver, opts);
117        bo_setter!(driver_opts, opts);
118        bo_setter!(labels, opts);
119
120        let rv = __volumes_create(&self.0, &opts.build());
121
122        match rv {
123            Ok(rv) => Ok(pythonize_this!(rv)),
124            Err(rv) => Err(py_sys_exception!(rv)),
125        }
126    }
127}
128
129#[tokio::main]
130async fn __volumes_prune(
131    volumes: &Volumes,
132    opts: &VolumePruneOpts,
133) -> Result<VolumePrune200Response, docker_api::Error> {
134    volumes.prune(opts).await
135}
136
137#[tokio::main]
138async fn __volumes_list(
139    volumes: &Volumes,
140    opts: &VolumeListOpts,
141) -> Result<VolumeListResponse, docker_api::Error> {
142    volumes.list(opts).await
143}
144
145#[tokio::main]
146async fn __volumes_create(
147    volumes: &Volumes,
148    opts: &VolumeCreateOpts,
149) -> Result<docker_api::models::Volume, docker_api::Error> {
150    volumes.create(opts).await
151}
152
153#[pymethods]
154impl Pyo3Volume {
155    #[new]
156    pub fn new(docker: Pyo3Docker, name: &str) -> Self {
157        Pyo3Volume(Volume::new(docker.0, name))
158    }
159
160    /// Get the volume name.
161    ///
162    /// Returns:
163    ///     str: Volume name
164    pub fn name(&self) -> String {
165        self.0.name().to_string()
166    }
167
168    /// Inspect the volume to get detailed information.
169    ///
170    /// Returns:
171    ///     dict: Detailed volume information including driver, mountpoint, etc.
172    pub fn inspect(&self) -> PyResult<Py<PyAny>> {
173        let rv = __volume_inspect(&self.0);
174
175        match rv {
176            Ok(rv) => Ok(pythonize_this!(rv)),
177            Err(rv) => Err(py_sys_exception!(rv)),
178        }
179    }
180
181    /// Delete the volume.
182    ///
183    /// Returns:
184    ///     None
185    pub fn delete(&self) -> PyResult<()> {
186        let rv = __volume_delete(&self.0);
187
188        match rv {
189            Ok(rv) => Ok(rv),
190            Err(rv) => Err(py_sys_exception!(rv)),
191        }
192    }
193}
194
195#[tokio::main]
196async fn __volume_inspect(
197    volume: &Volume,
198) -> Result<docker_api::models::Volume, docker_api::Error> {
199    volume.inspect().await
200}
201
202#[tokio::main]
203async fn __volume_delete(volume: &Volume) -> Result<(), docker_api::Error> {
204    volume.delete().await
205}