Skip to content

Commit 5abe479

Browse files
committed
support volumes propagation flags, fixes #554
1 parent ffc3766 commit 5abe479

3 files changed

Lines changed: 134 additions & 5 deletions

File tree

src/main/java/com/github/dockerjava/api/model/Bind.java

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ public class Bind implements Serializable {
2828
*/
2929
private SELContext secMode;
3030

31+
/**
32+
* @since {@link com.github.dockerjava.core.RemoteApiVersion#VERSION_1_2}
33+
*/
34+
private PropagationMode propagationMode;
35+
3136
public Bind(String path, Volume volume) {
3237
this(path, volume, AccessMode.DEFAULT, SELContext.DEFAULT);
3338
}
@@ -45,11 +50,16 @@ public Bind(String path, Volume volume, AccessMode accessMode, SELContext secMod
4550
}
4651

4752
public Bind(String path, Volume volume, AccessMode accessMode, SELContext secMode, Boolean noCopy) {
53+
this(path, volume, accessMode, secMode, noCopy, PropagationMode.DEFAULT);
54+
}
55+
56+
public Bind(String path, Volume volume, AccessMode accessMode, SELContext secMode, Boolean noCopy, PropagationMode propagationMode) {
4857
this.path = path;
4958
this.volume = volume;
5059
this.accessMode = accessMode;
5160
this.secMode = secMode;
5261
this.noCopy = noCopy;
62+
this.propagationMode = propagationMode;
5363
}
5464

5565
public String getPath() {
@@ -72,6 +82,10 @@ public Boolean getNoCopy() {
7282
return noCopy;
7383
}
7484

85+
public PropagationMode getPropagationMode() {
86+
return propagationMode;
87+
}
88+
7589
/**
7690
* Parses a bind mount specification to a {@link Bind}.
7791
*
@@ -93,17 +107,24 @@ public static Bind parse(String serialized) {
93107
AccessMode accessMode = AccessMode.DEFAULT;
94108
SELContext seMode = SELContext.DEFAULT;
95109
Boolean nocopy = null;
110+
PropagationMode propagationMode = PropagationMode.DEFAULT;
96111
for (String p : flags) {
97112
if (p.length() == 2) {
98113
accessMode = AccessMode.valueOf(p.toLowerCase());
99114
} else if ("nocopy".equals(p)) {
100115
nocopy = true;
116+
} else if (PropagationMode.mount_shared.toString().equals(p)) {
117+
propagationMode = PropagationMode.mount_shared;
118+
} else if (PropagationMode.mount_slave.toString().equals(p)) {
119+
propagationMode = PropagationMode.mount_slave;
120+
} else if (PropagationMode.mount_private.toString().equals(p)) {
121+
propagationMode = PropagationMode.mount_private;
101122
} else {
102123
seMode = SELContext.fromString(p);
103124
}
104125
}
105126

106-
return new Bind(parts[0], new Volume(parts[1]), accessMode, seMode, nocopy);
127+
return new Bind(parts[0], new Volume(parts[1]), accessMode, seMode, nocopy, propagationMode);
107128
}
108129
default: {
109130
throw new IllegalArgumentException();
@@ -124,6 +145,7 @@ public boolean equals(Object obj) {
124145
.append(accessMode, other.getAccessMode())
125146
.append(secMode, other.getSecMode())
126147
.append(noCopy, other.getNoCopy())
148+
.append(propagationMode, other.getPropagationMode())
127149
.isEquals();
128150
} else {
129151
return super.equals(obj);
@@ -138,6 +160,7 @@ public int hashCode() {
138160
.append(accessMode)
139161
.append(secMode)
140162
.append(noCopy)
163+
.append(propagationMode)
141164
.toHashCode();
142165
}
143166

@@ -150,11 +173,12 @@ public int hashCode() {
150173
*/
151174
@Override
152175
public String toString() {
153-
return String.format("%s:%s:%s%s%s",
176+
return String.format("%s:%s:%s%s%s%s",
154177
path,
155178
volume.getPath(),
156179
accessMode.toString(),
157180
secMode != SELContext.none ? "," + secMode.toString() : "",
158-
noCopy != null ? ",nocopy" : "");
181+
noCopy != null ? ",nocopy" : "",
182+
propagationMode != PropagationMode.mount_default ? "," + propagationMode.toString() : "");
159183
}
160184
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.github.dockerjava.api.model;
2+
3+
/**
4+
* The propagation mode of a file system or file: <code>shared</code>, <code>slave</code> or <code>private</code>.
5+
*
6+
* @see https://github.com/docker/docker/pull/17034
7+
* @since 1.22
8+
*/
9+
public enum PropagationMode {
10+
/** default */
11+
mount_default(""),
12+
13+
/** shared */
14+
mount_shared("shared"),
15+
16+
/** slave */
17+
mount_slave("slave"),
18+
19+
/** private */
20+
mount_private("private");
21+
22+
/**
23+
* The default {@link PropagationMode}: {@link #mount_default}
24+
*/
25+
public static final PropagationMode DEFAULT = mount_default;
26+
27+
private String value;
28+
29+
PropagationMode(String v) {
30+
value = v;
31+
}
32+
33+
@Override
34+
public String toString() {
35+
return value;
36+
}
37+
38+
public static PropagationMode fromString(String v) {
39+
switch (v) {
40+
case "shared":
41+
return mount_shared;
42+
case "slave":
43+
return mount_slave;
44+
case "private":
45+
return mount_private;
46+
}
47+
return mount_default;
48+
}
49+
}

src/test/java/com/github/dockerjava/api/model/BindTest.java

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public void parseUsingDefaultAccessMode() {
1818
assertThat(bind.getAccessMode(), is(AccessMode.DEFAULT));
1919
assertThat(bind.getSecMode(), is(SELContext.none));
2020
assertThat(bind.getNoCopy(), nullValue());
21+
assertThat(bind.getPropagationMode(), is(PropagationMode.DEFAULT));
2122
}
2223

2324
@Test
@@ -28,8 +29,9 @@ public void parseReadWrite() {
2829
assertThat(bind.getAccessMode(), is(rw));
2930
assertThat(bind.getSecMode(), is(SELContext.none));
3031
assertThat(bind.getNoCopy(), nullValue());
32+
assertThat(bind.getPropagationMode(), is(PropagationMode.DEFAULT));
3133
}
32-
34+
3335
@Test
3436
public void parseReadWriteNoCopy() {
3537
Bind bind = Bind.parse("/host:/container:rw,nocopy");
@@ -38,6 +40,40 @@ public void parseReadWriteNoCopy() {
3840
assertThat(bind.getAccessMode(), is(rw));
3941
assertThat(bind.getSecMode(), is(SELContext.none));
4042
assertThat(bind.getNoCopy(), is(true));
43+
assertThat(bind.getPropagationMode(), is(PropagationMode.DEFAULT));
44+
}
45+
46+
@Test
47+
public void parseReadWriteShared() {
48+
Bind bind = Bind.parse("/host:/container:rw,shared");
49+
assertThat(bind.getPath(), is("/host"));
50+
assertThat(bind.getVolume().getPath(), is("/container"));
51+
assertThat(bind.getAccessMode(), is(rw));
52+
assertThat(bind.getSecMode(), is(SELContext.none));
53+
assertThat(bind.getNoCopy(), nullValue());
54+
assertThat(bind.getPropagationMode(), is(PropagationMode.mount_shared));
55+
}
56+
57+
@Test
58+
public void parseReadWriteSlave() {
59+
Bind bind = Bind.parse("/host:/container:rw,slave");
60+
assertThat(bind.getPath(), is("/host"));
61+
assertThat(bind.getVolume().getPath(), is("/container"));
62+
assertThat(bind.getAccessMode(), is(rw));
63+
assertThat(bind.getSecMode(), is(SELContext.none));
64+
assertThat(bind.getNoCopy(), nullValue());
65+
assertThat(bind.getPropagationMode(), is(PropagationMode.mount_slave));
66+
}
67+
68+
@Test
69+
public void parseReadWritePrivate() {
70+
Bind bind = Bind.parse("/host:/container:rw,private");
71+
assertThat(bind.getPath(), is("/host"));
72+
assertThat(bind.getVolume().getPath(), is("/container"));
73+
assertThat(bind.getAccessMode(), is(rw));
74+
assertThat(bind.getSecMode(), is(SELContext.none));
75+
assertThat(bind.getNoCopy(), nullValue());
76+
assertThat(bind.getPropagationMode(), is(PropagationMode.mount_private));
4177
}
4278

4379
@Test
@@ -48,6 +84,7 @@ public void parseReadOnly() {
4884
assertThat(bind.getAccessMode(), is(ro));
4985
assertThat(bind.getSecMode(), is(SELContext.none));
5086
assertThat(bind.getNoCopy(), nullValue());
87+
assertThat(bind.getPropagationMode(), is(PropagationMode.DEFAULT));
5188
}
5289

5390
@Test
@@ -58,13 +95,15 @@ public void parseSELOnly() {
5895
assertThat(bind.getAccessMode(), is(AccessMode.DEFAULT));
5996
assertThat(bind.getSecMode(), is(SELContext.single));
6097
assertThat(bind.getNoCopy(), nullValue());
98+
assertThat(bind.getPropagationMode(), is(PropagationMode.DEFAULT));
6199

62100
bind = Bind.parse("/host:/container:z");
63101
assertThat(bind.getPath(), is("/host"));
64102
assertThat(bind.getVolume().getPath(), is("/container"));
65103
assertThat(bind.getAccessMode(), is(AccessMode.DEFAULT));
66104
assertThat(bind.getSecMode(), is(SELContext.shared));
67105
assertThat(bind.getNoCopy(), nullValue());
106+
assertThat(bind.getPropagationMode(), is(PropagationMode.DEFAULT));
68107
}
69108

70109
@Test
@@ -75,6 +114,7 @@ public void parseReadWriteSEL() {
75114
assertThat(bind.getAccessMode(), is(rw));
76115
assertThat(bind.getSecMode(), is(SELContext.single));
77116
assertThat(bind.getNoCopy(), nullValue());
117+
assertThat(bind.getPropagationMode(), is(PropagationMode.DEFAULT));
78118
}
79119

80120
@Test
@@ -85,6 +125,7 @@ public void parseReadOnlySEL() {
85125
assertThat(bind.getAccessMode(), is(ro));
86126
assertThat(bind.getSecMode(), is(SELContext.shared));
87127
assertThat(bind.getNoCopy(), nullValue());
128+
assertThat(bind.getPropagationMode(), is(PropagationMode.DEFAULT));
88129
}
89130

90131
@Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Error parsing Bind.*")
@@ -111,12 +152,27 @@ public void toStringReadOnly() {
111152
public void toStringReadWrite() {
112153
assertThat(Bind.parse("/host:/container:rw").toString(), is("/host:/container:rw"));
113154
}
114-
155+
115156
@Test
116157
public void toStringReadWriteNoCopy() {
117158
assertThat(Bind.parse("/host:/container:rw,nocopy").toString(), is("/host:/container:rw,nocopy"));
118159
}
119160

161+
@Test
162+
public void toStringReadWriteShared() {
163+
assertThat(Bind.parse("/host:/container:rw,shared").toString(), is("/host:/container:rw,shared"));
164+
}
165+
166+
@Test
167+
public void toStringReadWriteSlave() {
168+
assertThat(Bind.parse("/host:/container:rw,slave").toString(), is("/host:/container:rw,slave"));
169+
}
170+
171+
@Test
172+
public void toStringReadWritePrivate() {
173+
assertThat(Bind.parse("/host:/container:rw,private").toString(), is("/host:/container:rw,private"));
174+
}
175+
120176
@Test
121177
public void toStringDefaultAccessMode() {
122178
assertThat(Bind.parse("/host:/container").toString(), is("/host:/container:rw"));

0 commit comments

Comments
 (0)