1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter, Result};
/// Represents different types of mounts that can be attached to a container
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum MountType {
/// Bind mount: mounts a file or directory from the host
Bind {
/// Host path to mount from
source: String,
/// Container path to mount to
target: String,
/// Whether the mount is read-only
read_only: bool,
},
/// Volume mount: uses a Docker-managed volume
Volume {
/// Name of the Docker volume
source: String,
/// Container path to mount to
target: String,
/// Whether the mount is read-only
read_only: bool,
},
/// Anonymous volume: creates a new anonymous volume
AnonymousVolume {
/// Container path to mount to
target: String,
/// Whether the mount is read-only
read_only: bool,
},
}
impl MountType {
/// Creates a new bind mount with read-write access
pub fn bind<S: Into<String>, T: Into<String>>(source: S, target: T) -> Self {
Self::Bind {
source: source.into(),
target: target.into(),
read_only: false,
}
}
/// Creates a new read-only bind mount
pub fn bind_ro<S: Into<String>, T: Into<String>>(source: S, target: T) -> Self {
Self::Bind {
source: source.into(),
target: target.into(),
read_only: true,
}
}
/// Creates a new volume mount with read-write access
pub fn volume<S: Into<String>, T: Into<String>>(source: S, target: T) -> Self {
Self::Volume {
source: source.into(),
target: target.into(),
read_only: false,
}
}
/// Creates a new read-only volume mount
pub fn volume_ro<S: Into<String>, T: Into<String>>(source: S, target: T) -> Self {
Self::Volume {
source: source.into(),
target: target.into(),
read_only: true,
}
}
/// Creates a new anonymous volume with read-write access
pub fn anonymous_volume<T: Into<String>>(target: T) -> Self {
Self::AnonymousVolume {
target: target.into(),
read_only: false,
}
}
/// Creates a new read-only anonymous volume
pub fn anonymous_volume_ro<T: Into<String>>(target: T) -> Self {
Self::AnonymousVolume {
target: target.into(),
read_only: true,
}
}
/// Returns the target path in the container
#[must_use]
pub fn target(&self) -> &str {
match self {
Self::Bind { target, .. } | Self::Volume { target, .. } | Self::AnonymousVolume { target, .. } => target,
}
}
/// Returns the source path (if applicable)
#[must_use]
pub fn source(&self) -> Option<&str> {
match self {
Self::Bind { source, .. } | Self::Volume { source, .. } => Some(source),
Self::AnonymousVolume { .. } => None,
}
}
/// Returns whether the mount is read-only
#[must_use]
pub const fn is_read_only(&self) -> bool {
match self {
Self::Bind { read_only, .. } | Self::Volume { read_only, .. } | Self::AnonymousVolume { read_only, .. } => {
*read_only
}
}
}
/// Returns the mount type as a string for Docker API
#[must_use]
pub const fn mount_type_str(&self) -> &'static str {
match self {
Self::Bind { .. } => "bind",
Self::Volume { .. } | Self::AnonymousVolume { .. } => "volume",
}
}
}
impl Display for MountType {
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
match self {
Self::Bind {
source,
target,
read_only,
}
| Self::Volume {
source,
target,
read_only,
} => {
let mode = if *read_only { "ro" } else { "rw" };
write!(fmt, "{source}:{target}:{mode}")
}
Self::AnonymousVolume { target, read_only } => {
let mode = if *read_only { "ro" } else { "rw" };
write!(fmt, "{target}:{mode}")
}
}
}
}