lmrc_docker/volumes/mod.rs
1//! Volume management operations.
2
3use crate::DockerClient;
4use crate::error::{DockerError, Result};
5use bollard::models::*;
6use bollard::volume::*;
7use tracing::{debug, info};
8
9/// Volume operations manager.
10pub struct Volumes<'a> {
11 client: &'a DockerClient,
12}
13
14impl<'a> Volumes<'a> {
15 pub(crate) fn new(client: &'a DockerClient) -> Self {
16 Self { client }
17 }
18
19 /// Create a new volume.
20 ///
21 /// # Example
22 ///
23 /// ```no_run
24 /// use lmrc_docker::DockerClient;
25 ///
26 /// #[tokio::main]
27 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
28 /// let client = DockerClient::new()?;
29 /// let volume = client.volumes()
30 /// .create("my-volume")
31 /// .await?;
32 /// println!("Created volume: {}", volume.name);
33 /// Ok(())
34 /// }
35 /// ```
36 pub async fn create(&self, name: impl Into<String>) -> Result<Volume> {
37 let name = name.into();
38 info!("Creating volume: {}", name);
39
40 let config = CreateVolumeOptions {
41 name: name.clone(),
42 ..Default::default()
43 };
44
45 self.client
46 .docker
47 .create_volume(config)
48 .await
49 .map_err(|e| DockerError::Other(format!("Failed to create volume: {}", e)))
50 }
51
52 /// List all volumes.
53 ///
54 /// # Example
55 ///
56 /// ```no_run
57 /// use lmrc_docker::DockerClient;
58 ///
59 /// #[tokio::main]
60 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
61 /// let client = DockerClient::new()?;
62 /// let volumes = client.volumes().list().await?;
63 /// for volume in volumes {
64 /// println!("{}", volume.name);
65 /// }
66 /// Ok(())
67 /// }
68 /// ```
69 pub async fn list(&self) -> Result<Vec<Volume>> {
70 let response = self
71 .client
72 .docker
73 .list_volumes(Some(
74 bollard::query_parameters::ListVolumesOptions::default(),
75 ))
76 .await
77 .map_err(|e| DockerError::Other(format!("Failed to list volumes: {}", e)))?;
78
79 Ok(response.volumes.unwrap_or_default())
80 }
81
82 /// Get a reference to a specific volume.
83 pub fn get(&self, name: impl Into<String>) -> VolumeRef<'a> {
84 VolumeRef::new(self.client, name.into())
85 }
86
87 /// Prune unused volumes.
88 pub async fn prune(&self) -> Result<VolumePruneResponse> {
89 info!("Pruning unused volumes...");
90 self.client
91 .docker
92 .prune_volumes(Some(
93 bollard::query_parameters::PruneVolumesOptions::default(),
94 ))
95 .await
96 .map_err(|e| DockerError::Other(format!("Failed to prune volumes: {}", e)))
97 }
98}
99
100/// Reference to a specific volume.
101pub struct VolumeRef<'a> {
102 client: &'a DockerClient,
103 name: String,
104}
105
106impl<'a> VolumeRef<'a> {
107 pub(crate) fn new(client: &'a DockerClient, name: String) -> Self {
108 Self { client, name }
109 }
110
111 /// Get the volume name.
112 pub fn name(&self) -> &str {
113 &self.name
114 }
115
116 /// Inspect the volume to get detailed information.
117 ///
118 /// # Example
119 ///
120 /// ```no_run
121 /// use lmrc_docker::DockerClient;
122 ///
123 /// #[tokio::main]
124 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
125 /// let client = DockerClient::new()?;
126 /// let info = client.volumes().get("my-volume").inspect().await?;
127 /// println!("Mountpoint: {}", info.mountpoint);
128 /// Ok(())
129 /// }
130 /// ```
131 pub async fn inspect(&self) -> Result<Volume> {
132 debug!("Inspecting volume: {}", self.name);
133 self.client
134 .docker
135 .inspect_volume(&self.name)
136 .await
137 .map_err(|e| DockerError::VolumeNotFound(format!("{}: {}", self.name, e)))
138 }
139
140 /// Remove the volume.
141 ///
142 /// # Arguments
143 ///
144 /// * `force` - Force removal even if volume is in use
145 pub async fn remove(&self, force: bool) -> Result<()> {
146 info!("Removing volume: {}", self.name);
147
148 let options = if force {
149 Some(RemoveVolumeOptions { force })
150 } else {
151 None
152 };
153
154 self.client
155 .docker
156 .remove_volume(&self.name, options)
157 .await
158 .map_err(|e| DockerError::Other(format!("Failed to remove volume: {}", e)))
159 }
160}
161
162impl DockerClient {
163 /// Access volume operations.
164 ///
165 /// # Example
166 ///
167 /// ```no_run
168 /// use lmrc_docker::DockerClient;
169 ///
170 /// #[tokio::main]
171 /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
172 /// let client = DockerClient::new()?;
173 /// let volumes = client.volumes().list().await?;
174 /// Ok(())
175 /// }
176 /// ```
177 pub fn volumes(&self) -> Volumes<'_> {
178 Volumes::new(self)
179 }
180}