Skip to content

Commit 8af3d6f

Browse files
author
Arthur Tsang
committed
feat(save): add save image to docker client
add saveImageCmd which will return a InputStream. the file is a tar file. https://docs.docker.com/reference/api/docker_remote_api_v1.15/#image-tarball-format
1 parent 1d098f8 commit 8af3d6f

File tree

9 files changed

+228
-102
lines changed

9 files changed

+228
-102
lines changed

src/main/java/com/github/dockerjava/api/DockerClient.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ public CreateImageCmd createImageCmd(String repository,
3939
public ListImagesCmd listImagesCmd();
4040

4141
public InspectImageCmd inspectImageCmd(String imageId);
42+
43+
public SaveImageCmd saveImageCmd(String name);
4244

4345
/**
4446
* * CONTAINER API *

src/main/java/com/github/dockerjava/api/command/DockerCmdExecFactory.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ public interface DockerCmdExecFactory extends Closeable {
2222
public PullImageCmd.Exec createPullImageCmdExec();
2323

2424
public PushImageCmd.Exec createPushImageCmdExec();
25+
26+
public SaveImageCmd.Exec createSaveImageCmdExec();
2527

2628
public CreateImageCmd.Exec createCreateImageCmdExec();
2729

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.github.dockerjava.api.command;
2+
3+
import com.github.dockerjava.api.NotFoundException;
4+
import com.github.dockerjava.api.model.AuthConfig;
5+
import com.github.dockerjava.api.model.PushEventStreamItem;
6+
7+
import java.io.IOException;
8+
import java.io.InputStream;
9+
10+
public interface SaveImageCmd extends DockerCmd<InputStream>{
11+
12+
public String getName();
13+
14+
public String getTag();
15+
16+
/**
17+
* @param name The name, e.g. "alexec/busybox" or just "busybox" if you want to default. Not null.
18+
*/
19+
public SaveImageCmd withName(String name);
20+
21+
/**
22+
* @param tag The image's tag. Not null.
23+
*/
24+
public SaveImageCmd withTag(String tag);
25+
26+
public AuthConfig getAuthConfig();
27+
28+
public SaveImageCmd withAuthConfig(AuthConfig authConfig);
29+
30+
/**
31+
* @throws com.github.dockerjava.api.NotFoundException No such image
32+
*/
33+
public InputStream exec() throws NotFoundException;
34+
35+
public static interface Exec extends DockerCmdExec<SaveImageCmd, InputStream> {
36+
}
37+
38+
39+
}

src/main/java/com/github/dockerjava/core/DockerClientImpl.java

Lines changed: 9 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -8,75 +8,9 @@
88
import java.io.InputStream;
99

1010
import com.github.dockerjava.api.DockerClient;
11-
import com.github.dockerjava.api.command.AttachContainerCmd;
12-
import com.github.dockerjava.api.command.AuthCmd;
13-
import com.github.dockerjava.api.command.BuildImageCmd;
14-
import com.github.dockerjava.api.command.CommitCmd;
15-
import com.github.dockerjava.api.command.ContainerDiffCmd;
16-
import com.github.dockerjava.api.command.CopyFileFromContainerCmd;
17-
import com.github.dockerjava.api.command.CreateContainerCmd;
18-
import com.github.dockerjava.api.command.CreateImageCmd;
19-
import com.github.dockerjava.api.command.DockerCmdExecFactory;
20-
import com.github.dockerjava.api.command.EventCallback;
21-
import com.github.dockerjava.api.command.EventsCmd;
22-
import com.github.dockerjava.api.command.ExecCreateCmd;
23-
import com.github.dockerjava.api.command.ExecStartCmd;
24-
import com.github.dockerjava.api.command.InfoCmd;
25-
import com.github.dockerjava.api.command.InspectContainerCmd;
26-
import com.github.dockerjava.api.command.InspectImageCmd;
27-
import com.github.dockerjava.api.command.KillContainerCmd;
28-
import com.github.dockerjava.api.command.ListContainersCmd;
29-
import com.github.dockerjava.api.command.ListImagesCmd;
30-
import com.github.dockerjava.api.command.LogContainerCmd;
31-
import com.github.dockerjava.api.command.PauseContainerCmd;
32-
import com.github.dockerjava.api.command.PingCmd;
33-
import com.github.dockerjava.api.command.PullImageCmd;
34-
import com.github.dockerjava.api.command.PushImageCmd;
35-
import com.github.dockerjava.api.command.RemoveContainerCmd;
36-
import com.github.dockerjava.api.command.RemoveImageCmd;
37-
import com.github.dockerjava.api.command.RestartContainerCmd;
38-
import com.github.dockerjava.api.command.SearchImagesCmd;
39-
import com.github.dockerjava.api.command.StartContainerCmd;
40-
import com.github.dockerjava.api.command.StopContainerCmd;
41-
import com.github.dockerjava.api.command.TagImageCmd;
42-
import com.github.dockerjava.api.command.TopContainerCmd;
43-
import com.github.dockerjava.api.command.UnpauseContainerCmd;
44-
import com.github.dockerjava.api.command.VersionCmd;
45-
import com.github.dockerjava.api.command.WaitContainerCmd;
11+
import com.github.dockerjava.api.command.*;
4612
import com.github.dockerjava.api.model.AuthConfig;
47-
import com.github.dockerjava.core.command.AttachContainerCmdImpl;
48-
import com.github.dockerjava.core.command.AuthCmdImpl;
49-
import com.github.dockerjava.core.command.BuildImageCmdImpl;
50-
import com.github.dockerjava.core.command.CommitCmdImpl;
51-
import com.github.dockerjava.core.command.ContainerDiffCmdImpl;
52-
import com.github.dockerjava.core.command.CopyFileFromContainerCmdImpl;
53-
import com.github.dockerjava.core.command.CreateContainerCmdImpl;
54-
import com.github.dockerjava.core.command.CreateImageCmdImpl;
55-
import com.github.dockerjava.core.command.EventsCmdImpl;
56-
import com.github.dockerjava.core.command.ExecCreateCmdImpl;
57-
import com.github.dockerjava.core.command.ExecStartCmdImpl;
58-
import com.github.dockerjava.core.command.InfoCmdImpl;
59-
import com.github.dockerjava.core.command.InspectContainerCmdImpl;
60-
import com.github.dockerjava.core.command.InspectImageCmdImpl;
61-
import com.github.dockerjava.core.command.KillContainerCmdImpl;
62-
import com.github.dockerjava.core.command.ListContainersCmdImpl;
63-
import com.github.dockerjava.core.command.ListImagesCmdImpl;
64-
import com.github.dockerjava.core.command.LogContainerCmdImpl;
65-
import com.github.dockerjava.core.command.PauseContainerCmdImpl;
66-
import com.github.dockerjava.core.command.PingCmdImpl;
67-
import com.github.dockerjava.core.command.PullImageCmdImpl;
68-
import com.github.dockerjava.core.command.PushImageCmdImpl;
69-
import com.github.dockerjava.core.command.RemoveContainerCmdImpl;
70-
import com.github.dockerjava.core.command.RemoveImageCmdImpl;
71-
import com.github.dockerjava.core.command.RestartContainerCmdImpl;
72-
import com.github.dockerjava.core.command.SearchImagesCmdImpl;
73-
import com.github.dockerjava.core.command.StartContainerCmdImpl;
74-
import com.github.dockerjava.core.command.StopContainerCmdImpl;
75-
import com.github.dockerjava.core.command.TagImageCmdImpl;
76-
import com.github.dockerjava.core.command.TopContainerCmdImpl;
77-
import com.github.dockerjava.core.command.UnpauseContainerCmdImpl;
78-
import com.github.dockerjava.core.command.VersionCmdImpl;
79-
import com.github.dockerjava.core.command.WaitContainerCmdImpl;
13+
import com.github.dockerjava.core.command.*;
8014

8115
/**
8216
* @author Konstantin Pelykh (kpelykh@gmail.com)
@@ -195,6 +129,13 @@ public PushImageCmd pushImageCmd(String name) {
195129
return new PushImageCmdImpl(getDockerCmdExecFactory()
196130
.createPushImageCmdExec(), name).withAuthConfig(dockerClientConfig.effectiveAuthConfig(name));
197131
}
132+
133+
@Override
134+
public SaveImageCmd saveImageCmd(String name) {
135+
return new SaveImageCmdImpl(getDockerCmdExecFactory()
136+
.createSaveImageCmdExec(), name).withAuthConfig(dockerClientConfig.effectiveAuthConfig(name));
137+
138+
}
198139

199140
@Override
200141
public CreateImageCmd createImageCmd(String repository,
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.github.dockerjava.core.command;
2+
3+
import com.github.dockerjava.api.NotFoundException;
4+
import com.github.dockerjava.api.command.SaveImageCmd;
5+
6+
import java.io.InputStream;
7+
8+
import static jersey.repackaged.com.google.common.base.Preconditions.checkNotNull;
9+
10+
public class SaveImageCmdImpl extends AbstrAuthCfgDockerCmd<SaveImageCmd, InputStream> implements SaveImageCmd {
11+
private String name;
12+
private String tag;
13+
14+
public SaveImageCmdImpl(SaveImageCmd.Exec exec, String name) {
15+
super(exec);
16+
withName(name);
17+
}
18+
19+
@Override
20+
public String getName() {
21+
return name;
22+
}
23+
24+
@Override
25+
public String getTag() {
26+
return tag;
27+
}
28+
29+
/**
30+
* @param name The name, e.g. "alexec/busybox" or just "busybox" if you want to default. Not null.
31+
*/
32+
@Override
33+
public SaveImageCmd withName(String name) {
34+
checkNotNull(name, "name was not specified");
35+
this.name = name;
36+
return this;
37+
}
38+
39+
/**
40+
* @param tag The image's tag. Can be null or empty.
41+
*/
42+
@Override
43+
public SaveImageCmd withTag(String tag) {
44+
checkNotNull(tag, "tag was not specified");
45+
this.tag = tag;
46+
return this;
47+
}
48+
49+
@Override
50+
public String toString() {
51+
return new StringBuilder("get ")
52+
.append(name)
53+
.toString();
54+
}
55+
56+
/**
57+
* @throws com.github.dockerjava.api.NotFoundException No such image
58+
*/
59+
@Override
60+
public InputStream exec() throws NotFoundException {
61+
return super.exec();
62+
}
63+
}

src/main/java/com/github/dockerjava/jaxrs/DockerCmdExecFactoryImpl.java

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.io.IOException;
66
import java.net.URI;
77

8+
import com.github.dockerjava.api.command.*;
89
import org.slf4j.Logger;
910
import org.slf4j.LoggerFactory;
1011

@@ -26,40 +27,6 @@
2627

2728
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
2829
import com.github.dockerjava.api.DockerClientException;
29-
import com.github.dockerjava.api.command.AttachContainerCmd;
30-
import com.github.dockerjava.api.command.AuthCmd;
31-
import com.github.dockerjava.api.command.BuildImageCmd;
32-
import com.github.dockerjava.api.command.CommitCmd;
33-
import com.github.dockerjava.api.command.ContainerDiffCmd;
34-
import com.github.dockerjava.api.command.CopyFileFromContainerCmd;
35-
import com.github.dockerjava.api.command.CreateContainerCmd;
36-
import com.github.dockerjava.api.command.CreateImageCmd;
37-
import com.github.dockerjava.api.command.DockerCmdExecFactory;
38-
import com.github.dockerjava.api.command.EventsCmd;
39-
import com.github.dockerjava.api.command.ExecCreateCmd;
40-
import com.github.dockerjava.api.command.ExecStartCmd;
41-
import com.github.dockerjava.api.command.InfoCmd;
42-
import com.github.dockerjava.api.command.InspectContainerCmd;
43-
import com.github.dockerjava.api.command.InspectImageCmd;
44-
import com.github.dockerjava.api.command.KillContainerCmd;
45-
import com.github.dockerjava.api.command.ListContainersCmd;
46-
import com.github.dockerjava.api.command.ListImagesCmd;
47-
import com.github.dockerjava.api.command.LogContainerCmd;
48-
import com.github.dockerjava.api.command.PauseContainerCmd;
49-
import com.github.dockerjava.api.command.PingCmd;
50-
import com.github.dockerjava.api.command.PullImageCmd;
51-
import com.github.dockerjava.api.command.PushImageCmd;
52-
import com.github.dockerjava.api.command.RemoveContainerCmd;
53-
import com.github.dockerjava.api.command.RemoveImageCmd;
54-
import com.github.dockerjava.api.command.RestartContainerCmd;
55-
import com.github.dockerjava.api.command.SearchImagesCmd;
56-
import com.github.dockerjava.api.command.StartContainerCmd;
57-
import com.github.dockerjava.api.command.StopContainerCmd;
58-
import com.github.dockerjava.api.command.TagImageCmd;
59-
import com.github.dockerjava.api.command.TopContainerCmd;
60-
import com.github.dockerjava.api.command.UnpauseContainerCmd;
61-
import com.github.dockerjava.api.command.VersionCmd;
62-
import com.github.dockerjava.api.command.WaitContainerCmd;
6330
import com.github.dockerjava.core.DockerClientConfig;
6431
import com.github.dockerjava.core.util.JsonClientFilter;
6532
import com.github.dockerjava.core.util.ResponseStatusExceptionFilter;
@@ -170,6 +137,9 @@ public PullImageCmd.Exec createPullImageCmdExec() {
170137
public PushImageCmd.Exec createPushImageCmdExec() {
171138
return new PushImageCmdExec(getBaseResource());
172139
}
140+
141+
@Override
142+
public SaveImageCmd.Exec createSaveImageCmdExec() { return new SaveImageCmdExec(getBaseResource()); }
173143

174144
@Override
175145
public CreateImageCmd.Exec createCreateImageCmdExec() {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.github.dockerjava.jaxrs;
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import com.fasterxml.jackson.databind.ObjectReader;
5+
import com.github.dockerjava.api.command.PushImageCmd;
6+
import com.github.dockerjava.api.command.SaveImageCmd;
7+
import com.github.dockerjava.api.model.AuthConfig;
8+
import com.github.dockerjava.api.model.PushEventStreamItem;
9+
import jersey.repackaged.com.google.common.collect.ImmutableList;
10+
import org.slf4j.Logger;
11+
import org.slf4j.LoggerFactory;
12+
13+
import javax.ws.rs.client.WebTarget;
14+
import javax.ws.rs.core.MediaType;
15+
import java.io.IOException;
16+
import java.io.InputStream;
17+
import java.util.Iterator;
18+
19+
import static javax.ws.rs.client.Entity.entity;
20+
21+
public class SaveImageCmdExec extends AbstrDockerCmdExec<SaveImageCmd, InputStream> implements SaveImageCmd.Exec {
22+
private static final Logger LOGGER = LoggerFactory
23+
.getLogger(PushImageCmdExec.class);
24+
25+
public SaveImageCmdExec(WebTarget baseResource) {
26+
super(baseResource);
27+
}
28+
29+
@Override
30+
protected InputStream execute(SaveImageCmd command) {
31+
WebTarget webResource = getBaseResource().path("/images/" + command.getName() + "/get")
32+
.queryParam("tag", command.getTag());
33+
34+
final String registryAuth = registryAuth(command.getAuthConfig());
35+
LOGGER.trace("GET: {}", webResource);
36+
InputStream is = webResource
37+
.request()
38+
.header("X-Registry-Auth", registryAuth)
39+
.accept(MediaType.APPLICATION_JSON)
40+
.get().readEntity(InputStream.class);
41+
42+
return is;
43+
}
44+
}

src/test/java/com/github/dockerjava/core/TestDockerCmdExecFactory.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ public PullImageCmd.Exec createPullImageCmdExec() {
141141
public PushImageCmd.Exec createPushImageCmdExec() {
142142
return delegate.createPushImageCmdExec();
143143
}
144+
145+
@Override
146+
public SaveImageCmd.Exec createSaveImageCmdExec() { return delegate.createSaveImageCmdExec(); }
144147

145148
@Override
146149
public SearchImagesCmd.Exec createSearchImagesCmdExec() {
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.github.dockerjava.core.command;
2+
3+
import com.github.dockerjava.api.DockerException;
4+
import com.github.dockerjava.api.command.CreateContainerResponse;
5+
import com.github.dockerjava.client.AbstractDockerClientTest;
6+
import org.apache.commons.io.IOUtils;
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
9+
import org.testng.ITestResult;
10+
import org.testng.annotations.AfterMethod;
11+
import org.testng.annotations.AfterTest;
12+
import org.testng.annotations.BeforeMethod;
13+
import org.testng.annotations.BeforeTest;
14+
import org.testng.annotations.Test;
15+
16+
import java.io.BufferedInputStream;
17+
import java.io.DataInputStream;
18+
import java.io.InputStream;
19+
import java.lang.reflect.Method;
20+
21+
import static org.hamcrest.MatcherAssert.assertThat;
22+
import static org.hamcrest.Matchers.containsString;
23+
import static org.hamcrest.Matchers.greaterThan;
24+
import static org.hamcrest.Matchers.isEmptyString;
25+
import static org.hamcrest.Matchers.not;
26+
27+
@Test(groups = "integration")
28+
public class SaveImageCmdImplTest extends AbstractDockerClientTest {
29+
public static final Logger LOG = LoggerFactory
30+
.getLogger(PushImageCmdImplTest.class);
31+
32+
String username;
33+
34+
@BeforeTest
35+
public void beforeTest() throws DockerException {
36+
super.beforeTest();
37+
}
38+
@AfterTest
39+
public void afterTest() {
40+
super.afterTest();
41+
}
42+
43+
@BeforeMethod
44+
public void beforeMethod(Method method) {
45+
super.beforeMethod(method);
46+
}
47+
48+
@AfterMethod
49+
public void afterMethod(ITestResult result) {
50+
super.afterMethod(result);
51+
}
52+
53+
@Test
54+
public void saveImage() throws Exception {
55+
56+
InputStream image = IOUtils.toBufferedInputStream(dockerClient
57+
.saveImageCmd("busybox").exec());
58+
assertThat(image.available(), greaterThan(0));
59+
60+
}
61+
62+
}

0 commit comments

Comments
 (0)