From ec8f1f9b0e636b5155035a25ebbd3377dcab0d92 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Tue, 24 Feb 2015 15:53:56 +0300 Subject: [PATCH 1/3] Added InspectExec command --- .../github/dockerjava/api/DockerClient.java | 2 + .../api/command/DockerCmdExecFactory.java | 2 + .../api/command/InspectContainerResponse.java | 8 ++ .../api/command/InspectExecCmd.java | 16 ++++ .../api/command/InspectExecResponse.java | 93 +++++++++++++++++++ .../dockerjava/core/DockerClientImpl.java | 7 +- .../core/command/InspectExecCmdImpl.java | 41 ++++++++ .../jaxrs/DockerCmdExecFactoryImpl.java | 5 + .../dockerjava/jaxrs/InspectExecCmdExec.java | 24 +++++ .../core/TestDockerCmdExecFactory.java | 7 +- 10 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/github/dockerjava/api/command/InspectExecCmd.java create mode 100644 src/main/java/com/github/dockerjava/api/command/InspectExecResponse.java create mode 100644 src/main/java/com/github/dockerjava/core/command/InspectExecCmdImpl.java create mode 100644 src/main/java/com/github/dockerjava/jaxrs/InspectExecCmdExec.java diff --git a/src/main/java/com/github/dockerjava/api/DockerClient.java b/src/main/java/com/github/dockerjava/api/DockerClient.java index d905ef105..16e70b6c7 100644 --- a/src/main/java/com/github/dockerjava/api/DockerClient.java +++ b/src/main/java/com/github/dockerjava/api/DockerClient.java @@ -78,6 +78,8 @@ public CreateImageCmd createImageCmd(String repository, public ExecStartCmd execStartCmd(String containerId); + public InspectExecCmd inspectExecCmd(String execId); + public LogContainerCmd logContainerCmd(String containerId); public CopyFileFromContainerCmd copyFileFromContainerCmd( diff --git a/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java b/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java index ca2bbcae0..8b9880747 100644 --- a/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java +++ b/src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java @@ -51,6 +51,8 @@ public interface DockerCmdExecFactory extends Closeable { public ExecStartCmd.Exec createExecStartCmdExec(); + public InspectExecCmd.Exec createInspectExecCmdExec(); + public LogContainerCmd.Exec createLogContainerCmdExec(); public CopyFileFromContainerCmd.Exec createCopyFileFromContainerCmdExec(); diff --git a/src/main/java/com/github/dockerjava/api/command/InspectContainerResponse.java b/src/main/java/com/github/dockerjava/api/command/InspectContainerResponse.java index 80d526342..c86e13c54 100644 --- a/src/main/java/com/github/dockerjava/api/command/InspectContainerResponse.java +++ b/src/main/java/com/github/dockerjava/api/command/InspectContainerResponse.java @@ -1,6 +1,7 @@ package com.github.dockerjava.api.command; +import java.util.List; import java.util.Map; import com.github.dockerjava.api.model.*; @@ -66,6 +67,9 @@ public class InspectContainerResponse { @JsonProperty("ResolvConfPath") private String resolvConfPath; + @JsonProperty("ExecIDs") + private List execIds; + @JsonProperty("State") private ContainerState state; @@ -153,6 +157,10 @@ public String getMountLabel() { return mountLabel; } + public List getExecIds() { + return execIds; + } + @Override public String toString() { return ToStringBuilder.reflectionToString(this); diff --git a/src/main/java/com/github/dockerjava/api/command/InspectExecCmd.java b/src/main/java/com/github/dockerjava/api/command/InspectExecCmd.java new file mode 100644 index 000000000..13882b8f7 --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/command/InspectExecCmd.java @@ -0,0 +1,16 @@ +package com.github.dockerjava.api.command; + +import com.github.dockerjava.api.NotFoundException; + +public interface InspectExecCmd extends DockerCmd { + public String getExecId(); + public InspectExecCmd withExecId(String execId); + + /** + * @throws NotFoundException if no such exec has been found + */ + @Override + public InspectExecResponse exec() throws NotFoundException; + + public static interface Exec extends DockerCmdExec {} +} diff --git a/src/main/java/com/github/dockerjava/api/command/InspectExecResponse.java b/src/main/java/com/github/dockerjava/api/command/InspectExecResponse.java new file mode 100644 index 000000000..2eee14f29 --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/command/InspectExecResponse.java @@ -0,0 +1,93 @@ +package com.github.dockerjava.api.command; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.commons.lang.builder.ToStringBuilder; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class InspectExecResponse { + @JsonProperty("ID") + private String id; + + @JsonProperty("OpenStdin") + private boolean openStdin; + + @JsonProperty("OpenStderr") + private boolean openStderr; + + @JsonProperty("OpenStdout") + private boolean openStdout; + + @JsonProperty("Running") + private boolean running; + + public String getId() { + return id; + } + + public boolean isOpenStdin() { + return openStdin; + } + + public boolean isOpenStderr() { + return openStderr; + } + + public boolean isOpenStdout() { + return openStdout; + } + + public boolean isRunning() { + return running; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public class ProcessConfig { + @JsonProperty("arguments") + private List arguments; + + @JsonProperty("entrypoint") + private String entryPoint; + + @JsonProperty("privileged") + private boolean privileged; + + @JsonProperty("tty") + private boolean tty; + + @JsonProperty("user") + private String user; + + public List getArguments() { + return arguments; + } + + public String getEntryPoint() { + return entryPoint; + } + + public boolean isPrivileged() { + return privileged; + } + + public boolean isTty() { + return tty; + } + + public String getUser() { + return user; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + } +} diff --git a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java index dd9e566da..8f561dffa 100644 --- a/src/main/java/com/github/dockerjava/core/DockerClientImpl.java +++ b/src/main/java/com/github/dockerjava/core/DockerClientImpl.java @@ -224,7 +224,12 @@ public ExecStartCmd execStartCmd(String containerId) { return new ExecStartCmdImpl(getDockerCmdExecFactory().createExecStartCmdExec(), containerId); } - @Override + @Override + public InspectExecCmd inspectExecCmd(String execId) { + return new InspectExecCmdImpl(getDockerCmdExecFactory().createInspectExecCmdExec(), execId); + } + + @Override public LogContainerCmd logContainerCmd(String containerId) { return new LogContainerCmdImpl(getDockerCmdExecFactory() .createLogContainerCmdExec(), containerId); diff --git a/src/main/java/com/github/dockerjava/core/command/InspectExecCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/InspectExecCmdImpl.java new file mode 100644 index 000000000..1fd728622 --- /dev/null +++ b/src/main/java/com/github/dockerjava/core/command/InspectExecCmdImpl.java @@ -0,0 +1,41 @@ +package com.github.dockerjava.core.command; + +import com.github.dockerjava.api.NotFoundException; +import com.github.dockerjava.api.command.DockerCmdExec; +import com.github.dockerjava.api.command.InspectExecCmd; +import com.github.dockerjava.api.command.InspectExecResponse; +import com.google.common.base.Preconditions; + +public class InspectExecCmdImpl extends AbstrDockerCmd implements InspectExecCmd { + private String execId; + + public InspectExecCmdImpl(InspectExecCmd.Exec execution, String execId) { + super(execution); + withExecId(execId); + } + + @Override + public String getExecId() { + return execId; + } + + @Override + public InspectExecCmd withExecId(String execId) { + Preconditions.checkNotNull(execId, "execId was not specified"); + this.execId = execId; + return this; + } + + @Override + public String toString() { + return "inspect " + execId; + } + + /** + * @throws NotFoundException No such exec + */ + @Override + public InspectExecResponse exec() throws NotFoundException { + return super.exec(); + } +} diff --git a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java index 9df09ba78..f1f178dc9 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java +++ b/src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java @@ -221,6 +221,11 @@ public ExecStartCmd.Exec createExecStartCmdExec() { return new ExecStartCmdExec(getBaseResource()); } + @Override + public InspectExecCmd.Exec createInspectExecCmdExec() { + return new InspectExecCmdExec(getBaseResource()); + } + @Override public LogContainerCmd.Exec createLogContainerCmdExec() { return new LogContainerCmdExec(getBaseResource()); diff --git a/src/main/java/com/github/dockerjava/jaxrs/InspectExecCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/InspectExecCmdExec.java new file mode 100644 index 000000000..b9ee33d61 --- /dev/null +++ b/src/main/java/com/github/dockerjava/jaxrs/InspectExecCmdExec.java @@ -0,0 +1,24 @@ +package com.github.dockerjava.jaxrs; + +import com.github.dockerjava.api.command.InspectExecCmd; +import com.github.dockerjava.api.command.InspectExecResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; + +public class InspectExecCmdExec extends AbstrDockerCmdExec implements InspectExecCmd.Exec { + private static final Logger LOGGER = LoggerFactory.getLogger(InspectExecCmdExec.class); + + public InspectExecCmdExec(WebTarget baseResource) { + super(baseResource); + } + + @Override + protected InspectExecResponse execute(InspectExecCmd command) { + WebTarget webResource = getBaseResource().path("/exec/{id}/json").resolveTemplate("id", command.getExecId()); + LOGGER.debug("GET: {}", webResource); + return webResource.request().accept(MediaType.APPLICATION_JSON).get(InspectExecResponse.class); + } +} diff --git a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java index 1c9342dd9..869a12fcf 100644 --- a/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java +++ b/src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java @@ -194,7 +194,12 @@ public ExecStartCmd.Exec createExecStartCmdExec() { return delegate.createExecStartCmdExec(); } - @Override + @Override + public InspectExecCmd.Exec createInspectExecCmdExec() { + return delegate.createInspectExecCmdExec(); + } + + @Override public LogContainerCmd.Exec createLogContainerCmdExec() { return delegate.createLogContainerCmdExec(); } From bcfcb47c479e691ff358bfbdfc59ea86ad096968 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Tue, 24 Feb 2015 16:44:11 +0300 Subject: [PATCH 2/3] Added missing ExitCode field --- .../github/dockerjava/api/command/InspectExecResponse.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/github/dockerjava/api/command/InspectExecResponse.java b/src/main/java/com/github/dockerjava/api/command/InspectExecResponse.java index 2eee14f29..1532f7d55 100644 --- a/src/main/java/com/github/dockerjava/api/command/InspectExecResponse.java +++ b/src/main/java/com/github/dockerjava/api/command/InspectExecResponse.java @@ -23,6 +23,9 @@ public class InspectExecResponse { @JsonProperty("Running") private boolean running; + @JsonProperty("ExitCode") + private int exitCode; + public String getId() { return id; } @@ -43,6 +46,10 @@ public boolean isRunning() { return running; } + public int getExitCode() { + return exitCode; + } + @Override public String toString() { return ToStringBuilder.reflectionToString(this); From 1e2c99acb1123cd358d0bad774d48b14adc9a91a Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 2 Mar 2015 14:13:28 +0300 Subject: [PATCH 3/3] Added a test for InspectExec command --- .../core/command/InspectExecCmdImplTest.java | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/test/java/com/github/dockerjava/core/command/InspectExecCmdImplTest.java diff --git a/src/test/java/com/github/dockerjava/core/command/InspectExecCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/InspectExecCmdImplTest.java new file mode 100644 index 000000000..aacc51f60 --- /dev/null +++ b/src/test/java/com/github/dockerjava/core/command/InspectExecCmdImplTest.java @@ -0,0 +1,96 @@ +package com.github.dockerjava.core.command; + +import com.github.dockerjava.api.DockerException; +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.command.ExecCreateCmdResponse; +import com.github.dockerjava.api.command.InspectExecResponse; +import com.github.dockerjava.client.AbstractDockerClientTest; +import org.testng.ITestResult; +import org.testng.annotations.*; + +import java.io.InputStream; +import java.lang.reflect.Method; +import java.security.SecureRandom; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isEmptyString; +import static org.hamcrest.Matchers.not; + +@Test(groups = "integration") +public class InspectExecCmdImplTest extends AbstractDockerClientTest { + @BeforeTest + public void beforeTest() throws DockerException { + super.beforeTest(); + } + + @AfterTest + public void afterTest() { + super.afterTest(); + } + + @BeforeMethod + public void beforeMethod(Method method) { + super.beforeMethod(method); + } + + @AfterMethod + public void afterMethod(ITestResult result) { + super.afterMethod(result); + } + + @Test + public void inspectExecTest() { + String containerName = "generated_" + new SecureRandom().nextInt(); + + CreateContainerResponse container = dockerClient + .createContainerCmd("busybox") + .withCmd("top") + .withName(containerName).exec(); + LOG.info("Created container {}", container.toString()); + assertThat(container.getId(), not(isEmptyString())); + + dockerClient.startContainerCmd(container.getId()).exec(); + + ExecCreateCmdResponse touchFileCmdCreateResponse = dockerClient.execCreateCmd(container.getId()) + .withAttachStdout() + .withAttachStderr() + .withCmd("touch", "/marker").exec(); + LOG.info("Created exec {}", touchFileCmdCreateResponse.toString()); + assertThat(touchFileCmdCreateResponse.getId(), not(isEmptyString())); + ExecCreateCmdResponse checkFileCmdCreateResponse = dockerClient.execCreateCmd(container.getId()) + .withAttachStdout() + .withAttachStderr() + .withCmd("test", "-e", "/marker").exec(); + LOG.info("Created exec {}", checkFileCmdCreateResponse.toString()); + assertThat(checkFileCmdCreateResponse.getId(), not(isEmptyString())); + + // Check that file does not exist + InputStream response1 = dockerClient.execStartCmd(container.getId()) + .withExecId(checkFileCmdCreateResponse.getId()) + .exec(); + asString(response1); // consume + + InspectExecResponse first = dockerClient.inspectExecCmd(checkFileCmdCreateResponse.getId()).exec(); + assertThat(first.getExitCode(), is(1)); + + // Create the file + InputStream response2 = dockerClient.execStartCmd(container.getId()) + .withExecId(touchFileCmdCreateResponse.getId()) + .exec(); + asString(response2); + + InspectExecResponse second = dockerClient.inspectExecCmd(touchFileCmdCreateResponse.getId()).exec(); + assertThat(second.getExitCode(), is(0)); + + // Check that file does exist now + InputStream response3 = dockerClient.execStartCmd(container.getId()) + .withExecId(checkFileCmdCreateResponse.getId()) + .exec(); + asString(response3); + + InspectExecResponse third = dockerClient.inspectExecCmd(checkFileCmdCreateResponse.getId()).exec(); + assertThat(third.getExitCode(), is(0)); + + } +}