diff --git a/src/main/java/com/github/dockerjava/api/model/VolumeBind.java b/src/main/java/com/github/dockerjava/api/model/VolumeBind.java index d662f2b8f..41028b6dc 100644 --- a/src/main/java/com/github/dockerjava/api/model/VolumeBind.java +++ b/src/main/java/com/github/dockerjava/api/model/VolumeBind.java @@ -16,4 +16,9 @@ public String getContainerPath() { public String getHostPath() { return hostPath; } + + @Override + public String toString() { + return hostPath + ":" + containerPath; + } } diff --git a/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java index 8a6509bc6..8a4607c26 100644 --- a/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java @@ -41,7 +41,6 @@ public class CreateContainerCmdImpl extends AbstrDockerCmd.Volumes) + * has {@link VolumeBind}s for the given {@link Volume}s + */ + public static void assertContainerHasVolumes(InspectContainerResponse inspectContainerResponse, + Volume ... expectedVolumes) { + VolumeBind[] volumeBinds = inspectContainerResponse.getVolumes(); + LOG.info("Inspect .Volumes = [{}]", Joiner.on(", ").join(volumeBinds)); + + List volumes = new ArrayList(); + for (VolumeBind bind : volumeBinds) { + volumes.add(new Volume(bind.getContainerPath())); + } + assertThat(volumes, contains(expectedVolumes)); + } + } diff --git a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java index 321c3a1f9..ac3db5eaa 100644 --- a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java @@ -6,6 +6,7 @@ import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItemInArray; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.not; @@ -13,6 +14,7 @@ import java.lang.reflect.Method; import java.security.SecureRandom; import java.util.Arrays; +import java.util.UUID; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; @@ -25,6 +27,7 @@ import com.github.dockerjava.api.DockerException; import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.command.InspectContainerResponse; +import com.github.dockerjava.api.model.Bind; import com.github.dockerjava.api.model.HostConfig; import com.github.dockerjava.api.model.Link; import com.github.dockerjava.api.model.Links; @@ -96,6 +99,55 @@ public void createContainerWithVolume() throws DockerException { contains("/var/log")); } + @Test + public void createContainerWithVolumesFrom() throws DockerException { + + Volume volume1 = new Volume("/opt/webapp1"); + Volume volume2 = new Volume("/opt/webapp2"); + + String container1Name = UUID.randomUUID().toString(); + + // create a running container with bind mounts + CreateContainerResponse container1 = dockerClient + .createContainerCmd("busybox").withCmd("sleep", "9999") + .withName(container1Name).exec(); + LOG.info("Created container1 {}", container1.toString()); + + dockerClient.startContainerCmd(container1.getId()).withBinds( + new Bind("/src/webapp1", volume1), new Bind("/src/webapp2", volume2)).exec(); + LOG.info("Started container1 {}", container1.toString()); + + InspectContainerResponse inspectContainerResponse1 = dockerClient.inspectContainerCmd( + container1.getId()).exec(); + + assertContainerHasVolumes(inspectContainerResponse1, volume1, volume2); + + // create a second container with volumes from first container + CreateContainerResponse container2 = dockerClient + .createContainerCmd("busybox").withCmd("sleep", "9999") + .withVolumesFrom(container1Name).exec(); + LOG.info("Created container2 {}", container2.toString()); + + InspectContainerResponse inspectContainerResponse2 = dockerClient + .inspectContainerCmd(container2.getId()).exec(); + + // No volumes are created, the information is just stored in .HostConfig.VolumesFrom + assertThat(inspectContainerResponse2.getHostConfig().getVolumesFrom(), hasItemInArray(container1Name)); + + // To ensure that the information stored in VolumesFrom really is considered + // when starting the container, we start it and verify that it has the same + // bind mounts as the first container. + // This is somehow out of scope here, but it helped me to understand how the + // VolumesFrom feature really works. + dockerClient.startContainerCmd(container2.getId()).exec(); + LOG.info("Started container2 {}", container2.toString()); + + inspectContainerResponse2 = dockerClient.inspectContainerCmd(container2.getId()).exec(); + + assertThat(inspectContainerResponse2.getHostConfig().getVolumesFrom(), hasItemInArray(container1Name)); + assertContainerHasVolumes(inspectContainerResponse2, volume1, volume2); + } + @Test public void createContainerWithEnv() throws DockerException { diff --git a/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java index 486f03b31..de744b59a 100644 --- a/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java @@ -84,18 +84,49 @@ public void startContainerWithVolumes() throws DockerException { inspectContainerResponse = dockerClient.inspectContainerCmd(container .getId()).exec(); - VolumeBind[] volumeBinds = inspectContainerResponse.getVolumes(); - List volumes = new ArrayList(); - for(VolumeBind bind :volumeBinds){ - volumes.add(bind.getContainerPath()); - } - assertThat(volumes, contains(volume1.getPath(), volume2.getPath())); + assertContainerHasVolumes(inspectContainerResponse, volume1, volume2); assertThat(Arrays.asList(inspectContainerResponse.getVolumesRW()), contains(volume1, volume2)); } + @Test + public void startContainerWithVolumesFrom() throws DockerException { + + Volume volume1 = new Volume("/opt/webapp1"); + Volume volume2 = new Volume("/opt/webapp2"); + + String container1Name = UUID.randomUUID().toString(); + + CreateContainerResponse container1 = dockerClient + .createContainerCmd("busybox").withCmd("sleep", "9999") + .withName(container1Name).exec(); + LOG.info("Created container1 {}", container1.toString()); + + dockerClient.startContainerCmd(container1.getId()).withBinds( + new Bind("/src/webapp1", volume1), new Bind("/src/webapp2", volume2)).exec(); + LOG.info("Started container1 {}", container1.toString()); + + InspectContainerResponse inspectContainerResponse1 = dockerClient.inspectContainerCmd( + container1.getId()).exec(); + + assertContainerHasVolumes(inspectContainerResponse1, volume1, volume2); + + + CreateContainerResponse container2 = dockerClient + .createContainerCmd("busybox").withCmd("sleep", "9999").exec(); + LOG.info("Created container2 {}", container2.toString()); + + dockerClient.startContainerCmd(container2.getId()).withVolumesFrom(container1Name).exec(); + LOG.info("Started container2 {}", container2.toString()); + + InspectContainerResponse inspectContainerResponse2 = dockerClient + .inspectContainerCmd(container2.getId()).exec(); + + assertContainerHasVolumes(inspectContainerResponse2, volume1, volume2); + } + @Test public void startContainerWithDns() throws DockerException {