opencode_cloud_core/docker/
volume.rs1use super::{DockerClient, DockerError};
7use bollard::volume::CreateVolumeOptions;
8use std::collections::HashMap;
9use tracing::debug;
10
11pub const VOLUME_SESSION: &str = "opencode-data";
13
14pub const VOLUME_STATE: &str = "opencode-state";
16
17pub const VOLUME_CACHE: &str = "opencode-cache";
19
20pub const VOLUME_PROJECTS: &str = "opencode-workspace";
22
23pub const VOLUME_CONFIG: &str = "opencode-config";
25
26pub const VOLUME_USERS: &str = "opencode-users";
28
29pub const VOLUME_NAMES: [&str; 6] = [
31 VOLUME_SESSION,
32 VOLUME_STATE,
33 VOLUME_CACHE,
34 VOLUME_PROJECTS,
35 VOLUME_CONFIG,
36 VOLUME_USERS,
37];
38
39pub const MOUNT_SESSION: &str = "/home/opencode/.local/share/opencode";
41
42pub const MOUNT_STATE: &str = "/home/opencode/.local/state/opencode";
44
45pub const MOUNT_CACHE: &str = "/home/opencode/.cache/opencode";
47
48pub const MOUNT_PROJECTS: &str = "/home/opencode/workspace";
50
51pub const MOUNT_CONFIG: &str = "/home/opencode/.config/opencode";
53
54pub const MOUNT_USERS: &str = "/var/lib/opencode-users";
56
57pub async fn ensure_volumes_exist(client: &DockerClient) -> Result<(), DockerError> {
62 debug!("Ensuring all required volumes exist");
63
64 for volume_name in VOLUME_NAMES {
65 ensure_volume_exists(client, volume_name).await?;
66 }
67
68 debug!("All volumes verified/created");
69 Ok(())
70}
71
72async fn ensure_volume_exists(client: &DockerClient, name: &str) -> Result<(), DockerError> {
74 debug!("Checking volume: {}", name);
75
76 let options = CreateVolumeOptions {
78 name,
79 driver: "local",
80 driver_opts: HashMap::new(),
81 labels: HashMap::from([("managed-by", "opencode-cloud")]),
82 };
83
84 client
86 .inner()
87 .create_volume(options)
88 .await
89 .map_err(|e| DockerError::Volume(format!("Failed to create volume {name}: {e}")))?;
90
91 debug!("Volume {} ready", name);
92 Ok(())
93}
94
95pub async fn volume_exists(client: &DockerClient, name: &str) -> Result<bool, DockerError> {
97 debug!("Checking if volume exists: {}", name);
98
99 match client.inner().inspect_volume(name).await {
100 Ok(_) => Ok(true),
101 Err(bollard::errors::Error::DockerResponseServerError {
102 status_code: 404, ..
103 }) => Ok(false),
104 Err(e) => Err(DockerError::Volume(format!(
105 "Failed to inspect volume {name}: {e}"
106 ))),
107 }
108}
109
110pub async fn remove_volume(client: &DockerClient, name: &str) -> Result<(), DockerError> {
115 debug!("Removing volume: {}", name);
116
117 client
118 .inner()
119 .remove_volume(name, None)
120 .await
121 .map_err(|e| DockerError::Volume(format!("Failed to remove volume {name}: {e}")))?;
122
123 debug!("Volume {} removed", name);
124 Ok(())
125}
126
127pub async fn remove_all_volumes(client: &DockerClient) -> Result<(), DockerError> {
131 debug!("Removing all opencode-cloud volumes");
132
133 for volume_name in VOLUME_NAMES {
134 if volume_exists(client, volume_name).await? {
136 remove_volume(client, volume_name).await?;
137 }
138 }
139
140 debug!("All volumes removed");
141 Ok(())
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn volume_constants_are_correct() {
150 assert_eq!(VOLUME_SESSION, "opencode-data");
151 assert_eq!(VOLUME_STATE, "opencode-state");
152 assert_eq!(VOLUME_CACHE, "opencode-cache");
153 assert_eq!(VOLUME_PROJECTS, "opencode-workspace");
154 assert_eq!(VOLUME_CONFIG, "opencode-config");
155 assert_eq!(VOLUME_USERS, "opencode-users");
156 }
157
158 #[test]
159 fn volume_names_array_has_all_volumes() {
160 assert_eq!(VOLUME_NAMES.len(), 6);
161 assert!(VOLUME_NAMES.contains(&VOLUME_SESSION));
162 assert!(VOLUME_NAMES.contains(&VOLUME_STATE));
163 assert!(VOLUME_NAMES.contains(&VOLUME_CACHE));
164 assert!(VOLUME_NAMES.contains(&VOLUME_PROJECTS));
165 assert!(VOLUME_NAMES.contains(&VOLUME_CONFIG));
166 assert!(VOLUME_NAMES.contains(&VOLUME_USERS));
167 }
168
169 #[test]
170 fn mount_points_are_correct() {
171 assert_eq!(MOUNT_SESSION, "/home/opencode/.local/share/opencode");
172 assert_eq!(MOUNT_STATE, "/home/opencode/.local/state/opencode");
173 assert_eq!(MOUNT_CACHE, "/home/opencode/.cache/opencode");
174 assert_eq!(MOUNT_PROJECTS, "/home/opencode/workspace");
175 assert_eq!(MOUNT_CONFIG, "/home/opencode/.config/opencode");
176 assert_eq!(MOUNT_USERS, "/var/lib/opencode-users");
177 }
178}