Skip to content

Commit 32e1116

Browse files
Fixes #807. NettyDockerCmdExecFactory ignores API version configuration
1 parent 0a3ac8d commit 32e1116

File tree

2 files changed

+148
-1
lines changed

2 files changed

+148
-1
lines changed

src/main/java/com/github/dockerjava/netty/NettyDockerCmdExecFactory.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ public class NettyDockerCmdExecFactory implements DockerCmdExecFactory {
172172

173173
private NettyInitializer nettyInitializer;
174174

175+
private WebTarget baseResource;
176+
175177
private ChannelProvider channelProvider = new ChannelProvider() {
176178
@Override
177179
public DuplexChannel getChannel() {
@@ -199,6 +201,8 @@ public void init(DockerClientConfig dockerClientConfig) {
199201
}
200202

201203
eventLoopGroup = nettyInitializer.init(bootstrap, dockerClientConfig);
204+
205+
baseResource = new WebTarget(channelProvider).path(dockerClientConfig.getApiVersion().asWebPathPart());
202206
}
203207

204208
private DuplexChannel connect() {
@@ -619,6 +623,7 @@ private <T extends Channel> T configure(T channel) {
619623
}
620624

621625
private WebTarget getBaseResource() {
622-
return new WebTarget(channelProvider);
626+
checkNotNull(baseResource, "Factory not initialized, baseResource not set. You probably forgot to call init()!");
627+
return baseResource;
623628
}
624629
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package com.github.dockerjava.netty;
2+
3+
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH;
4+
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE;
5+
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
6+
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
7+
import static org.testng.Assert.assertEquals;
8+
9+
import io.netty.bootstrap.ServerBootstrap;
10+
import io.netty.buffer.Unpooled;
11+
import io.netty.channel.Channel;
12+
import io.netty.channel.ChannelHandlerContext;
13+
import io.netty.channel.ChannelInitializer;
14+
import io.netty.channel.ChannelPipeline;
15+
import io.netty.channel.SimpleChannelInboundHandler;
16+
import io.netty.channel.nio.NioEventLoopGroup;
17+
import io.netty.channel.socket.SocketChannel;
18+
import io.netty.channel.socket.nio.NioServerSocketChannel;
19+
import io.netty.handler.codec.http.DefaultFullHttpResponse;
20+
import io.netty.handler.codec.http.FullHttpResponse;
21+
import io.netty.handler.codec.http.HttpContent;
22+
import io.netty.handler.codec.http.HttpRequest;
23+
import io.netty.handler.codec.http.HttpServerCodec;
24+
import io.netty.util.CharsetUtil;
25+
26+
import java.util.ArrayList;
27+
import java.util.List;
28+
29+
import org.testng.annotations.Test;
30+
31+
import com.github.dockerjava.api.DockerClient;
32+
import com.github.dockerjava.core.DefaultDockerClientConfig;
33+
import com.github.dockerjava.core.DefaultDockerClientConfig.Builder;
34+
import com.github.dockerjava.core.DockerClientBuilder;
35+
36+
public class NettyDockerCmdExecFactoryConfigTest {
37+
38+
@Test
39+
public void testNettyDockerCmdExecFactoryConfigWithApiVersion() throws Exception {
40+
NettyDockerCmdExecFactory factory = new NettyDockerCmdExecFactory();
41+
Builder configBuilder = DefaultDockerClientConfig.createDefaultConfigBuilder()
42+
.withDockerHost("tcp://localhost:2378")
43+
.withApiVersion("1.23");
44+
45+
DockerClient client = DockerClientBuilder.getInstance(configBuilder)
46+
.withDockerCmdExecFactory(factory)
47+
.build();
48+
49+
FakeDockerServer server = new FakeDockerServer(2378);
50+
server.start();
51+
try {
52+
client.versionCmd().exec();
53+
54+
List<HttpRequest> requests = server.getRequests();
55+
56+
assertEquals(requests.size(), 1);
57+
assertEquals(requests.get(0).uri(), "/v1.23/version");
58+
} finally {
59+
server.stop();
60+
}
61+
}
62+
63+
@Test
64+
public void testNettyDockerCmdExecFactoryConfigWithoutApiVersion() throws Exception {
65+
NettyDockerCmdExecFactory factory = new NettyDockerCmdExecFactory();
66+
Builder configBuilder = DefaultDockerClientConfig.createDefaultConfigBuilder().withDockerHost("tcp://localhost:2378");
67+
68+
DockerClient client = DockerClientBuilder.getInstance(configBuilder)
69+
.withDockerCmdExecFactory(factory)
70+
.build();
71+
72+
FakeDockerServer server = new FakeDockerServer(2378);
73+
server.start();
74+
try {
75+
client.versionCmd().exec();
76+
77+
List<HttpRequest> requests = server.getRequests();
78+
79+
assertEquals(requests.size(), 1);
80+
assertEquals(requests.get(0).uri(), "/version");
81+
} finally {
82+
server.stop();
83+
}
84+
}
85+
86+
private class FakeDockerServer {
87+
private final int port;
88+
private final NioEventLoopGroup parent;
89+
private final NioEventLoopGroup child;
90+
private final List<HttpRequest> requests = new ArrayList<>();
91+
private Channel channel;
92+
93+
private FakeDockerServer(int port) {
94+
this.port = port;
95+
this.parent = new NioEventLoopGroup();
96+
this.child = new NioEventLoopGroup();
97+
}
98+
99+
private void start() throws Exception {
100+
ServerBootstrap bootstrap = new ServerBootstrap();
101+
bootstrap.group(parent, child)
102+
.channel(NioServerSocketChannel.class)
103+
.childHandler(new ChannelInitializer<SocketChannel>() {
104+
@Override
105+
protected void initChannel(SocketChannel socketChannel) throws Exception {
106+
ChannelPipeline pipeline = socketChannel.pipeline();
107+
pipeline.addLast("codec", new HttpServerCodec());
108+
pipeline.addLast("httpHandler", new SimpleChannelInboundHandler<Object>() {
109+
@Override
110+
protected void channelRead0(ChannelHandlerContext context, Object message) throws Exception {
111+
if (message instanceof HttpRequest) {
112+
// Keep track of processed requests
113+
HttpRequest request = (HttpRequest) message;
114+
requests.add(request);
115+
}
116+
117+
if (message instanceof HttpContent) {
118+
// Write an empty JSON response back to the client
119+
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.copiedBuffer("{}", CharsetUtil.UTF_8));
120+
response.headers().set(CONTENT_TYPE, "application/json; charset=UTF-8");
121+
response.headers().set(CONTENT_LENGTH, response.content().readableBytes());
122+
context.writeAndFlush(response);
123+
}
124+
}
125+
});
126+
}
127+
});
128+
129+
channel = bootstrap.bind(port).syncUninterruptibly().channel();
130+
}
131+
132+
private void stop() throws Exception {
133+
parent.shutdownGracefully();
134+
child.shutdownGracefully();
135+
channel.closeFuture().sync();
136+
}
137+
138+
private List<HttpRequest> getRequests() {
139+
return requests;
140+
}
141+
}
142+
}

0 commit comments

Comments
 (0)