Skip to content

Commit ee6248d

Browse files
committed
Merge pull request #70 from albers/bind
Improve instantiation and serialization of Bind
2 parents 5030388 + 74ea00b commit ee6248d

File tree

8 files changed

+144
-21
lines changed

8 files changed

+144
-21
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.github.dockerjava.api.model;
2+
3+
/**
4+
* The access mode of a file system or file: <code>read-write</code>
5+
* or <code>read-only</code>.
6+
*/
7+
public enum AccessMode {
8+
/** read-write */
9+
rw,
10+
11+
/** read-only */
12+
ro;
13+
14+
/**
15+
* The default {@link AccessMode}: {@link #rw}
16+
*/
17+
public static final AccessMode DEFAULT = rw;
18+
19+
}

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

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,40 @@
11
package com.github.dockerjava.api.model;
22

3+
import static com.github.dockerjava.api.model.AccessMode.ro;
4+
import static com.github.dockerjava.api.model.AccessMode.rw;
5+
36
import org.apache.commons.lang.builder.EqualsBuilder;
47
import org.apache.commons.lang.builder.HashCodeBuilder;
58

9+
/**
10+
* Represents a host path being bind mounted as a {@link Volume}
11+
* in a Docker container.
12+
* The Bind can be in read only or read write access mode.
13+
*/
614
public class Bind {
715

816
private String path;
917

1018
private Volume volume;
1119

12-
private boolean readOnly = false;
20+
private AccessMode accessMode;
1321

1422
public Bind(String path, Volume volume) {
15-
this(path, volume, false);
23+
this(path, volume, AccessMode.DEFAULT);
1624
}
1725

18-
public Bind(String path, Volume volume, boolean readOnly) {
26+
public Bind(String path, Volume volume, AccessMode accessMode) {
1927
this.path = path;
2028
this.volume = volume;
21-
this.readOnly = readOnly;
29+
this.accessMode = accessMode;
30+
}
31+
32+
/**
33+
* @deprecated use {@link #Bind(String, Volume, AccessMode)}
34+
*/
35+
@Deprecated
36+
public Bind(String path, Volume volume, boolean readOnly) {
37+
this(path, volume, readOnly ? ro : rw);
2238
}
2339

2440
public String getPath() {
@@ -28,9 +44,17 @@ public String getPath() {
2844
public Volume getVolume() {
2945
return volume;
3046
}
47+
48+
public AccessMode getAccessMode() {
49+
return accessMode;
50+
}
3151

52+
/**
53+
* @deprecated use {@link #getAccessMode()}
54+
*/
55+
@Deprecated
3256
public boolean isReadOnly() {
33-
return readOnly;
57+
return ro.equals(accessMode);
3458
}
3559

3660
/**
@@ -48,12 +72,8 @@ public static Bind parse(String serialized) {
4872
return new Bind(parts[0], Volume.parse(parts[1]));
4973
}
5074
case 3: {
51-
if ("rw".equals(parts[2].toLowerCase()))
52-
return new Bind(parts[0], Volume.parse(parts[1]), false);
53-
else if ("ro".equals(parts[2].toLowerCase()))
54-
return new Bind(parts[0], Volume.parse(parts[1]), true);
55-
else
56-
throw new IllegalArgumentException();
75+
AccessMode accessMode = AccessMode.valueOf(parts[2].toLowerCase());
76+
return new Bind(parts[0], Volume.parse(parts[1]), accessMode);
5777
}
5878
default: {
5979
throw new IllegalArgumentException();
@@ -71,14 +91,28 @@ public boolean equals(Object obj) {
7191
Bind other = (Bind) obj;
7292
return new EqualsBuilder().append(path, other.getPath())
7393
.append(volume, other.getVolume())
74-
.append(readOnly, other.isReadOnly()).isEquals();
94+
.append(accessMode, other.getAccessMode()).isEquals();
7595
} else
7696
return super.equals(obj);
7797
}
7898

7999
@Override
80100
public int hashCode() {
81101
return new HashCodeBuilder().append(path).append(volume)
82-
.append(readOnly).toHashCode();
102+
.append(accessMode).toHashCode();
103+
}
104+
105+
/**
106+
* Returns a string representation of this {@link Bind} suitable
107+
* for inclusion in a JSON message.
108+
* The format is <code>&lt;host path&gt;:&lt;container path&gt;:&lt;access mode&gt;</code>,
109+
* like the argument in {@link #parse(String)}.
110+
*
111+
* @return a string representation of this {@link Bind}
112+
*/
113+
@Override
114+
public String toString() {
115+
return path + ":" + volume.toString() + ":" + accessMode.toString();
83116
}
117+
84118
}

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,7 @@ public void serialize(Binds binds, JsonGenerator jsonGen,
4444
//
4545
jsonGen.writeStartArray();
4646
for (Bind bind : binds.getBinds()) {
47-
String s = bind.getPath() + ":" + bind.getVolume().toString();
48-
if(bind.isReadOnly()) s += ":ro";
49-
jsonGen.writeString(s);
50-
47+
jsonGen.writeString(bind.toString());
5148
}
5249
jsonGen.writeEndArray();
5350
//

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
2020
import com.fasterxml.jackson.databind.node.NullNode;
2121

22+
/**
23+
* Represents a bind mounted volume in a Docker container.
24+
*
25+
* @see Bind
26+
*/
2227
@JsonDeserialize(using = Volume.Deserializer.class)
2328
@JsonSerialize(using = Volume.Serializer.class)
2429
public class Volume {
@@ -43,6 +48,13 @@ public static Volume parse(String serialized) {
4348
return new Volume(serialized);
4449
}
4550

51+
/**
52+
* Returns a string representation of this {@link Volume} suitable
53+
* for inclusion in a JSON message.
54+
* The returned String is simply the container path, {@link #getPath()}.
55+
*
56+
* @return a string representation of this {@link Volume}
57+
*/
4658
@Override
4759
public String toString() {
4860
return getPath();
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.github.dockerjava.api.model;
2+
3+
import static com.github.dockerjava.api.model.AccessMode.rw;
4+
import static org.testng.Assert.assertEquals;
5+
6+
import org.testng.annotations.Test;
7+
8+
public class AccessModeTest {
9+
10+
@Test
11+
public void defaultAccessMode() {
12+
assertEquals(AccessMode.DEFAULT, rw);
13+
}
14+
15+
@Test
16+
public void stringify() {
17+
assertEquals(AccessMode.rw.toString(), "rw");
18+
}
19+
20+
@Test
21+
public void fromString() {
22+
assertEquals(AccessMode.valueOf("rw"), rw);
23+
}
24+
25+
@Test(expectedExceptions = IllegalArgumentException.class,
26+
expectedExceptionsMessageRegExp = "No enum constant.*")
27+
public void fromIllegalString() {
28+
AccessMode.valueOf("xx");
29+
}
30+
31+
}

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

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.github.dockerjava.api.model;
22

3+
import static com.github.dockerjava.api.model.AccessMode.ro;
4+
import static com.github.dockerjava.api.model.AccessMode.rw;
35
import static org.testng.Assert.assertEquals;
46

57
import org.testng.annotations.Test;
@@ -11,23 +13,23 @@ public void parseUsingDefaultAccessMode() {
1113
Bind bind = Bind.parse("/host:/container");
1214
assertEquals(bind.getPath(), "/host");
1315
assertEquals(bind.getVolume().getPath(), "/container");
14-
assertEquals(bind.isReadOnly(), false);
16+
assertEquals(bind.getAccessMode(), AccessMode.DEFAULT);
1517
}
1618

1719
@Test
1820
public void parseReadWrite() {
1921
Bind bind = Bind.parse("/host:/container:rw");
2022
assertEquals(bind.getPath(), "/host");
2123
assertEquals(bind.getVolume().getPath(), "/container");
22-
assertEquals(bind.isReadOnly(), false);
24+
assertEquals(bind.getAccessMode(), rw);
2325
}
2426

2527
@Test
2628
public void parseReadOnly() {
2729
Bind bind = Bind.parse("/host:/container:ro");
2830
assertEquals(bind.getPath(), "/host");
2931
assertEquals(bind.getVolume().getPath(), "/container");
30-
assertEquals(bind.isReadOnly(), true);
32+
assertEquals(bind.getAccessMode(), ro);
3133
}
3234

3335
@Test(expectedExceptions = IllegalArgumentException.class,
@@ -48,4 +50,19 @@ public void parseNull() {
4850
Bind.parse(null);
4951
}
5052

53+
@Test
54+
public void toStringReadOnly() {
55+
assertEquals(Bind.parse("/host:/container:ro").toString(), "/host:/container:ro");
56+
}
57+
58+
@Test
59+
public void toStringReadWrite() {
60+
assertEquals(Bind.parse("/host:/container:rw").toString(), "/host:/container:rw");
61+
}
62+
63+
@Test
64+
public void toStringDefaultAccessMode() {
65+
assertEquals(Bind.parse("/host:/container").toString(), "/host:/container:rw");
66+
}
67+
5168
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.github.dockerjava.api.model;
2+
3+
import static org.testng.Assert.assertEquals;
4+
5+
import org.testng.annotations.Test;
6+
7+
public class VolumeTest {
8+
@Test
9+
public void stringify() {
10+
assertEquals(Volume.parse("/path").toString(), "/path");
11+
}
12+
}

src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.github.dockerjava.core.command;
22

3+
import static com.github.dockerjava.api.model.AccessMode.ro;
34
import static org.hamcrest.MatcherAssert.assertThat;
45
import static org.hamcrest.Matchers.contains;
56
import static org.hamcrest.Matchers.equalTo;
@@ -72,7 +73,7 @@ public void startContainerWithVolumes() throws DockerException {
7273
assertThat(inspectContainerResponse.getConfig().getVolumes().keySet(),
7374
contains("/opt/webapp1", "/opt/webapp2"));
7475

75-
dockerClient.startContainerCmd(container.getId()).withBinds(new Bind("/src/webapp1", volume1, true), new Bind("/src/webapp2", volume2)).exec();
76+
dockerClient.startContainerCmd(container.getId()).withBinds(new Bind("/src/webapp1", volume1, ro), new Bind("/src/webapp2", volume2)).exec();
7677

7778
dockerClient.waitContainerCmd(container.getId()).exec();
7879

0 commit comments

Comments
 (0)