X Tutup
Skip to content

Commit 8140c47

Browse files
committed
Make BuildImage and PushImage return an object that can be iterated
over in a typed fashion so that clients can read out the responses. Use Iterable so the response does not have to be 'complete' before consuming. Derive from InputStream to maintain backwards compatibility and for clients that don't want to parse the response. Signed-off-by: Nigel Magnay <nigel.magnay@gmail.com>
1 parent 602008c commit 8140c47

File tree

7 files changed

+119
-35
lines changed

7 files changed

+119
-35
lines changed

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

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

3+
import com.github.dockerjava.api.model.EventStreamItem;
4+
import com.github.dockerjava.api.model.PushEventStreamItem;
5+
6+
import java.io.IOException;
37
import java.io.InputStream;
48

59
/**
@@ -9,7 +13,7 @@
913
* TODO: http://docs.docker.com/reference/builder/#dockerignore
1014
*
1115
*/
12-
public interface BuildImageCmd extends DockerCmd<InputStream>{
16+
public interface BuildImageCmd extends DockerCmd<BuildImageCmd.Response>{
1317

1418
public BuildImageCmd withTag(String tag);
1519

@@ -37,7 +41,10 @@ public interface BuildImageCmd extends DockerCmd<InputStream>{
3741

3842
public BuildImageCmd withQuiet(boolean quiet);
3943

40-
public static interface Exec extends DockerCmdExec<BuildImageCmd, InputStream> {
44+
public static interface Exec extends DockerCmdExec<BuildImageCmd, BuildImageCmd.Response> {
4145
}
4246

47+
public static abstract class Response extends InputStream {
48+
public abstract Iterable<EventStreamItem> getItems() throws IOException;
49+
}
4350
}

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
package com.github.dockerjava.api.command;
22

3+
import java.io.IOException;
34
import java.io.InputStream;
45

56
import com.github.dockerjava.api.NotFoundException;
67
import com.github.dockerjava.api.model.AuthConfig;
8+
import com.github.dockerjava.api.model.PushEventStreamItem;
79

810
/**
911
* Push the latest image to the repository.
1012
*
1113
* @param name The name, e.g. "alexec/busybox" or just "busybox" if you want to default. Not null.
1214
*/
13-
public interface PushImageCmd extends DockerCmd<InputStream>{
15+
public interface PushImageCmd extends DockerCmd<PushImageCmd.Response>{
1416

1517
public String getName();
1618

@@ -33,10 +35,13 @@ public interface PushImageCmd extends DockerCmd<InputStream>{
3335
/**
3436
* @throws NotFoundException No such image
3537
*/
36-
@Override
37-
public InputStream exec() throws NotFoundException;
38+
public Response exec() throws NotFoundException;
3839

39-
public static interface Exec extends DockerCmdExec<PushImageCmd, InputStream> {
40+
public static interface Exec extends DockerCmdExec<PushImageCmd, Response> {
41+
}
42+
43+
public static abstract class Response extends InputStream {
44+
public abstract Iterable<PushEventStreamItem> getItems() throws IOException;
4045
}
4146

4247
}

src/main/java/com/github/dockerjava/core/command/BuildImageCmdImpl.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@
3232
* Build an image from Dockerfile.
3333
*
3434
*/
35-
public class BuildImageCmdImpl extends
36-
AbstrDockerCmd<BuildImageCmd, InputStream> implements BuildImageCmd {
35+
public class BuildImageCmdImpl extends AbstrDockerCmd<BuildImageCmd, BuildImageCmd.Response> implements BuildImageCmd {
3736

3837
private static final Pattern ADD_OR_COPY_PATTERN = Pattern
3938
.compile("^(ADD|COPY)\\s+(.*)\\s+(.*)$");

src/main/java/com/github/dockerjava/core/command/PushImageCmdImpl.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
import static jersey.repackaged.com.google.common.base.Preconditions.checkNotNull;
44

5-
import java.io.InputStream;
6-
75
import com.github.dockerjava.api.NotFoundException;
86
import com.github.dockerjava.api.command.PushImageCmd;
97

@@ -12,7 +10,7 @@
1210
*
1311
* @param name The name, e.g. "alexec/busybox" or just "busybox" if you want to default. Not null.
1412
*/
15-
public class PushImageCmdImpl extends AbstrAuthCfgDockerCmd<PushImageCmd, InputStream> implements PushImageCmd {
13+
public class PushImageCmdImpl extends AbstrAuthCfgDockerCmd<PushImageCmd, PushImageCmd.Response> implements PushImageCmd {
1614

1715
private String name;
1816
private String tag;
@@ -63,7 +61,7 @@ public String toString() {
6361
* @throws NotFoundException No such image
6462
*/
6563
@Override
66-
public InputStream exec() throws NotFoundException {
64+
public Response exec() throws NotFoundException {
6765
return super.exec();
6866
}
6967
}

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

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package com.github.dockerjava.jaxrs;
22

3+
import com.google.common.collect.ImmutableList;
4+
35
import static javax.ws.rs.client.Entity.entity;
46

7+
import java.io.IOException;
58
import java.io.InputStream;
9+
import java.util.Iterator;
610

711
import javax.ws.rs.client.WebTarget;
812
import javax.ws.rs.core.MediaType;
@@ -13,9 +17,14 @@
1317
import org.slf4j.Logger;
1418
import org.slf4j.LoggerFactory;
1519

20+
import com.fasterxml.jackson.databind.ObjectMapper;
21+
import com.fasterxml.jackson.databind.ObjectReader;
1622
import com.github.dockerjava.api.command.BuildImageCmd;
23+
import com.github.dockerjava.api.command.PushImageCmd;
24+
import com.github.dockerjava.api.model.EventStreamItem;
25+
import com.github.dockerjava.api.model.PushEventStreamItem;
1726

18-
public class BuildImageCmdExec extends AbstrDockerCmdExec<BuildImageCmd, InputStream> implements BuildImageCmd.Exec {
27+
public class BuildImageCmdExec extends AbstrDockerCmdExec<BuildImageCmd, BuildImageCmd.Response> implements BuildImageCmd.Exec {
1928

2029
private static final Logger LOGGER = LoggerFactory
2130
.getLogger(BuildImageCmdExec.class);
@@ -25,7 +34,7 @@ public BuildImageCmdExec(WebTarget baseResource) {
2534
}
2635

2736
@Override
28-
protected InputStream execute(BuildImageCmd command) {
37+
protected ResponseImpl execute(BuildImageCmd command) {
2938
WebTarget webResource = getBaseResource().path("/build");
3039

3140
if(command.getTag() != null) {
@@ -45,12 +54,38 @@ protected InputStream execute(BuildImageCmd command) {
4554
webResource.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.CHUNKED);
4655
webResource.property(ClientProperties.CHUNKED_ENCODING_SIZE, 1024*1024);
4756

48-
LOGGER.debug("POST: {}", webResource);
49-
return webResource
50-
.request()
51-
.accept(MediaType.TEXT_PLAIN)
52-
.post(entity(command.getTarInputStream(), "application/tar"), Response.class).readEntity(InputStream.class);
57+
58+
LOGGER.debug("POST: {}", webResource);
59+
InputStream is = webResource
60+
.request()
61+
.accept(MediaType.TEXT_PLAIN)
62+
.post(entity(command.getTarInputStream(), "application/tar"), Response.class).readEntity(InputStream.class);
63+
64+
return new ResponseImpl(is);
5365

5466
}
67+
public static class ResponseImpl extends BuildImageCmd.Response {
68+
69+
private final InputStream proxy;
70+
71+
public ResponseImpl(InputStream proxy) {
72+
this.proxy = proxy;
73+
}
74+
75+
@Override
76+
public Iterable<EventStreamItem> getItems() throws IOException {
77+
ObjectMapper mapper = new ObjectMapper();
78+
// we'll be reading instances of MyBean
79+
ObjectReader reader = mapper.reader(EventStreamItem.class);
80+
// and then do other configuration, if any, and read:
81+
Iterator<EventStreamItem> items = reader.readValues(proxy);
82+
83+
return ImmutableList.copyOf(items);
84+
}
5585

86+
@Override
87+
public int read() throws IOException {
88+
return proxy.read();
89+
}
90+
}
5691
}
Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,83 @@
11
package com.github.dockerjava.jaxrs;
22

3+
import com.google.common.collect.ImmutableList;
4+
5+
import static javax.ws.rs.client.Entity.entity;
6+
7+
import java.io.IOException;
38
import java.io.InputStream;
9+
import java.util.Iterator;
410

511
import javax.ws.rs.client.WebTarget;
612
import javax.ws.rs.core.MediaType;
713

814
import org.slf4j.Logger;
915
import org.slf4j.LoggerFactory;
1016

17+
import com.fasterxml.jackson.databind.ObjectMapper;
18+
import com.fasterxml.jackson.databind.ObjectReader;
1119
import com.github.dockerjava.api.command.PushImageCmd;
20+
import com.github.dockerjava.api.command.PushImageCmd.Response;
1221
import com.github.dockerjava.api.model.AuthConfig;
22+
import com.github.dockerjava.api.model.PushEventStreamItem;
1323

14-
public class PushImageCmdExec extends
15-
AbstrDockerCmdExec<PushImageCmd, InputStream> implements
16-
PushImageCmd.Exec {
1724

25+
public class PushImageCmdExec extends AbstrDockerCmdExec<PushImageCmd, Response> implements PushImageCmd.Exec {
26+
1827
private static final Logger LOGGER = LoggerFactory
1928
.getLogger(PushImageCmdExec.class);
20-
29+
2130
public PushImageCmdExec(WebTarget baseResource) {
2231
super(baseResource);
2332
}
2433

2534
@Override
26-
protected InputStream execute(PushImageCmd command) {
27-
WebTarget webResource = getBaseResource().path(
28-
"/images/" + name(command) + "/push").queryParam("tag",
29-
command.getTag());
35+
protected ResponseImpl execute(PushImageCmd command) {
36+
WebTarget webResource = getBaseResource().path("/images/" + name(command) + "/push")
37+
.queryParam("tag", command.getTag());
3038

3139
final String registryAuth = registryAuth(command.getAuthConfig());
3240
LOGGER.trace("POST: {}", webResource);
33-
return webResource.request().header("X-Registry-Auth", registryAuth)
34-
.accept(MediaType.APPLICATION_JSON).post(null)
35-
.readEntity(InputStream.class);
36-
}
41+
InputStream is = webResource
42+
.request()
43+
.header("X-Registry-Auth", registryAuth)
44+
.accept(MediaType.APPLICATION_JSON)
45+
.post(
46+
entity(Response.class, MediaType.APPLICATION_JSON)).readEntity(
47+
InputStream.class);
3748

49+
return new ResponseImpl(is);
50+
}
51+
3852
private String name(PushImageCmd command) {
3953
String name = command.getName();
4054
AuthConfig authConfig = command.getAuthConfig();
4155
return name.contains("/") ? name : authConfig.getUsername();
4256
}
4357

58+
59+
public static class ResponseImpl extends Response {
60+
61+
private final InputStream proxy;
62+
63+
ResponseImpl(InputStream proxy) {
64+
this.proxy = proxy;
65+
}
66+
67+
@Override
68+
public Iterable<PushEventStreamItem> getItems() throws IOException {
69+
ObjectMapper mapper = new ObjectMapper();
70+
// we'll be reading instances of MyBean
71+
ObjectReader reader = mapper.reader(PushEventStreamItem.class);
72+
// and then do other configuration, if any, and read:
73+
Iterator<PushEventStreamItem> items = reader.readValues(proxy);
74+
75+
return ImmutableList.copyOf(items);
76+
}
77+
78+
@Override
79+
public int read() throws IOException {
80+
return proxy.read();
81+
}
82+
}
4483
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import com.github.dockerjava.api.command.*;
1010
import com.github.dockerjava.api.command.AuthCmd.Exec;
11+
import com.github.dockerjava.jaxrs.BuildImageCmdExec;
1112

1213
/**
1314
* Special {@link DockerCmdExecFactory} implementation that collects container and image creations
@@ -92,18 +93,18 @@ public Void exec(RemoveImageCmd command) {
9293
public BuildImageCmd.Exec createBuildImageCmdExec() {
9394
return new BuildImageCmd.Exec() {
9495
@Override
95-
public InputStream exec(BuildImageCmd command) {
96+
public BuildImageCmd.Response exec(BuildImageCmd command) {
9697
// can't detect image id here so tagging it
9798
String tag = command.getTag();
9899
if(tag == null || "".equals(tag.trim())) {
99100
tag = "" + new SecureRandom().nextInt(Integer.MAX_VALUE);
100101
command.withTag(tag);
101102
}
102-
InputStream inputStream = delegate.createBuildImageCmdExec().exec(command);
103+
InputStream inputStream = delegate.createBuildImageCmdExec().exec(command);
103104
imageNames.add(tag);
104-
return inputStream;
105+
return new BuildImageCmdExec.ResponseImpl(inputStream);
105106
}
106-
};
107+
};
107108
}
108109

109110
@Override

0 commit comments

Comments
 (0)
X Tutup