diff --git a/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java b/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java index ac98db2f9..06f4cb0cd 100644 --- a/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/BuildImageCmd.java @@ -1,16 +1,16 @@ package com.github.dockerjava.api.command; +import com.github.dockerjava.api.model.AuthConfigurations; +import com.github.dockerjava.api.model.BuildResponseItem; +import com.github.dockerjava.core.RemoteApiVersion; + +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; import java.io.File; import java.io.InputStream; import java.net.URI; import java.util.Map; - -import javax.annotation.CheckForNull; -import javax.annotation.Nonnull; - -import com.github.dockerjava.api.model.AuthConfigurations; -import com.github.dockerjava.api.model.BuildResponseItem; -import com.github.dockerjava.core.RemoteApiVersion; +import java.util.Set; /** * Build an image from Dockerfile. @@ -34,7 +34,11 @@ public interface BuildImageCmd extends AsyncDockerCmd getLabels(); + /** + * @since {@link RemoteApiVersion#VERSION_1_21} + */ + @CheckForNull + Set getTags(); + // setters + /** + * @deprecated since docker API version 1.21 there can be multiple tags + * specified so use {@link #withTags(Set)} + * @param tag + * @return + */ + @Deprecated BuildImageCmd withTag(String tag); + BuildImageCmd withTags(Set tags); + BuildImageCmd withRemote(URI remote); BuildImageCmd withBaseDirectory(File baseDirectory); diff --git a/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java index c34b05155..87df8ecbb 100644 --- a/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java @@ -1,6 +1,10 @@ package com.github.dockerjava.core.command; -import static com.google.common.base.Preconditions.checkNotNull; +import com.github.dockerjava.api.command.BuildImageCmd; +import com.github.dockerjava.api.model.AuthConfigurations; +import com.github.dockerjava.api.model.BuildResponseItem; +import com.github.dockerjava.core.dockerfile.Dockerfile; +import com.github.dockerjava.core.util.FilePathUtil; import java.io.File; import java.io.IOException; @@ -8,17 +12,12 @@ import java.net.URI; import java.util.HashMap; import java.util.Map; +import java.util.Set; -import com.github.dockerjava.api.command.BuildImageCmd; -import com.github.dockerjava.api.model.AuthConfigurations; -import com.github.dockerjava.api.model.BuildResponseItem; -import com.github.dockerjava.core.dockerfile.Dockerfile; -import com.github.dockerjava.core.util.FilePathUtil; +import static com.google.common.base.Preconditions.checkNotNull; /** - * * Build an image from Dockerfile. - * */ public class BuildImageCmdImpl extends AbstrAsyncDockerCmd implements BuildImageCmd { @@ -26,6 +25,8 @@ public class BuildImageCmdImpl extends AbstrAsyncDockerCmd tags; + private Boolean noCache; private Boolean remove = true; @@ -156,6 +157,11 @@ public Map getLabels() { return labels; } + @Override + public Set getTags() { + return tags; + } + // getter lib specific @Override @@ -185,6 +191,12 @@ public BuildImageCmdImpl withTag(String tag) { return this; } + @Override + public BuildImageCmd withTags(Set tags) { + this.tags = tags; + return this; + } + @Override public BuildImageCmd withRemote(URI remote) { this.remote = remote; diff --git a/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java index 2a7aea40e..f014a2817 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/BuildImageCmdExec.java @@ -65,9 +65,14 @@ protected AbstractCallbackNotifier callbackNotifier(BuildImag if (dockerFilePath != null && command.getRemote() == null && !"Dockerfile".equals(dockerFilePath)) { webTarget = webTarget.queryParam("dockerfile", dockerFilePath); } - if (command.getTag() != null) { + if (command.getTags() != null && !command.getTags().isEmpty()) { + for (String t : command.getTags()) { + webTarget = webTarget.queryParam("t", t); + } + } else if (command.getTag() != null) { webTarget = webTarget.queryParam("t", command.getTag()); } + if (command.getRemote() != null) { webTarget = webTarget.queryParam("remote", command.getRemote().toString()); } diff --git a/src/main/java/com/github/dockerjava/netty/WebTarget.java b/src/main/java/com/github/dockerjava/netty/WebTarget.java index ef1510f5c..d8273b55a 100644 --- a/src/main/java/com/github/dockerjava/netty/WebTarget.java +++ b/src/main/java/com/github/dockerjava/netty/WebTarget.java @@ -22,17 +22,17 @@ public class WebTarget { private final ImmutableList path; - private final ImmutableMap queryParams; + private final ImmutableMap queryParams; private static final String PATH_SEPARATOR = "/"; public WebTarget(ChannelProvider channelProvider) { - this(channelProvider, ImmutableList.of(), ImmutableMap.of()); + this(channelProvider, ImmutableList.of(), ImmutableMap.of()); } private WebTarget(ChannelProvider channelProvider, ImmutableList path, - ImmutableMap queryParams) { + ImmutableMap queryParams) { this.channelProvider = channelProvider; this.path = path; this.queryParams = queryParams; @@ -52,8 +52,14 @@ public InvocationBuilder request() { String resource = PATH_SEPARATOR + StringUtils.join(path, PATH_SEPARATOR); List params = new ArrayList<>(); - for (Map.Entry entry : queryParams.entrySet()) { - params.add(entry.getKey() + "=" + entry.getValue()); + for (Map.Entry entry : queryParams.entrySet()) { + if (entry.getValue() instanceof Iterable) { + for (Object i : (Iterable) entry.getValue()) { + params.add(entry.getKey() + "=" + i.toString()); + } + } else { + params.add(entry.getKey() + "=" + entry.getValue().toString()); + } } if (!params.isEmpty()) { @@ -73,9 +79,9 @@ public WebTarget resolveTemplate(String name, Object value) { } public WebTarget queryParam(String name, Object value) { - ImmutableMap.Builder builder = ImmutableMap.builder().putAll(queryParams); + ImmutableMap.Builder builder = ImmutableMap.builder().putAll(queryParams); if (value != null) { - builder.put(name, value.toString()); + builder.put(name, value); } return new WebTarget(channelProvider, path, builder.build()); } diff --git a/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java b/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java index 43152570e..e83da0445 100644 --- a/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java +++ b/src/main/java/com/github/dockerjava/netty/exec/BuildImageCmdExec.java @@ -55,7 +55,9 @@ protected Void execute0(BuildImageCmd command, ResultCallback if (dockerFilePath != null && command.getRemote() == null && !"Dockerfile".equals(dockerFilePath)) { webTarget = webTarget.queryParam("dockerfile", dockerFilePath); } - if (command.getTag() != null) { + if (command.getTags() != null && !command.getTags().isEmpty()) { + webTarget = webTarget.queryParam("t", command.getTags()); + } else if (command.getTag() != null) { webTarget = webTarget.queryParam("t", command.getTag()); } if (command.getRemote() != null) { diff --git a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java index cb4c1b2a8..9ba283732 100644 --- a/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/BuildImageCmdImplTest.java @@ -7,13 +7,16 @@ import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.Matchers.containsInAnyOrder; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.UUID; import org.apache.commons.io.FileUtils; @@ -274,6 +277,28 @@ public void labels() throws Exception { assertThat(inspectImageResponse.getConfig().getLabels().get("test"), equalTo("abc")); } + @Test + public void multipleTags() throws Exception { + if (!getVersion(dockerClient).isGreaterOrEqual(RemoteApiVersion.VERSION_1_21)) { + throw new SkipException("API version should be >= 1.21"); + } + + File baseDir = fileFromBuildTestResource("labels"); + + String imageId = dockerClient.buildImageCmd(baseDir).withNoCache(true) + .withTag("fallback-when-withTags-not-called") + .withTags(new HashSet<>(Arrays.asList("docker-java-test:tag1", "docker-java-test:tag2"))) + .exec(new BuildImageResultCallback()) + .awaitImageId(); + + InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec(); + assertThat(inspectImageResponse, not(nullValue())); + LOG.info("Image Inspect: {}", inspectImageResponse.toString()); + + assertThat(inspectImageResponse.getRepoTags().size(), equalTo(2)); + assertThat(inspectImageResponse.getRepoTags(), containsInAnyOrder("docker-java-test:tag1", "docker-java-test:tag2")); + } + public void dockerfileNotInBaseDirectory() throws Exception { File baseDirectory = fileFromBuildTestResource("dockerfileNotInBaseDirectory"); File dockerfile = fileFromBuildTestResource("dockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile"); diff --git a/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java b/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java index f567dcfc8..55dcf353b 100644 --- a/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java +++ b/src/test/java/com/github/dockerjava/netty/exec/BuildImageCmdExecTest.java @@ -7,13 +7,16 @@ import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.Matchers.containsInAnyOrder; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.UUID; import org.apache.commons.io.FileUtils; @@ -279,6 +282,28 @@ public void labels() throws Exception { assertThat(inspectImageResponse.getConfig().getLabels().get("test"), equalTo("abc")); } + @Test + public void multipleTags() throws Exception { + if (!getVersion(dockerClient).isGreaterOrEqual(RemoteApiVersion.VERSION_1_21)) { + throw new SkipException("API version should be >= 1.21"); + } + + File baseDir = fileFromBuildTestResource("labels"); + + String imageId = dockerClient.buildImageCmd(baseDir).withNoCache(true) + .withTag("fallback-when-withTags-not-called") + .withTags(new HashSet<>(Arrays.asList("docker-java-test:tag1", "docker-java-test:tag2"))) + .exec(new BuildImageResultCallback()) + .awaitImageId(); + + InspectImageResponse inspectImageResponse = dockerClient.inspectImageCmd(imageId).exec(); + assertThat(inspectImageResponse, not(nullValue())); + LOG.info("Image Inspect: {}", inspectImageResponse.toString()); + + assertThat(inspectImageResponse.getRepoTags().size(), equalTo(2)); + assertThat(inspectImageResponse.getRepoTags(), containsInAnyOrder("docker-java-test:tag1", "docker-java-test:tag2")); + } + public void dockerfileNotInBaseDirectory() throws Exception { File baseDirectory = fileFromBuildTestResource("dockerfileNotInBaseDirectory"); File dockerfile = fileFromBuildTestResource("dockerfileNotInBaseDirectory/dockerfileFolder/Dockerfile");