Skip to content

Commit 8047b4b

Browse files
authored
Merge pull request docker-java#808 from jamesnetherton/807-netty-api-version
NettyDockerCmdExecFactory ignores API version configuration
2 parents 57a6109 + 221fff6 commit 8047b4b

2 files changed

Lines changed: 161 additions & 1 deletion

File tree

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: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
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.io.IOException;
27+
import java.net.ServerSocket;
28+
import java.util.ArrayList;
29+
import java.util.List;
30+
31+
import org.testng.annotations.Test;
32+
33+
import com.github.dockerjava.api.DockerClient;
34+
import com.github.dockerjava.core.DefaultDockerClientConfig;
35+
import com.github.dockerjava.core.DefaultDockerClientConfig.Builder;
36+
import com.github.dockerjava.core.DockerClientBuilder;
37+
38+
public class NettyDockerCmdExecFactoryConfigTest {
39+
40+
@Test
41+
public void testNettyDockerCmdExecFactoryConfigWithApiVersion() throws Exception {
42+
int dockerPort = getFreePort();
43+
44+
NettyDockerCmdExecFactory factory = new NettyDockerCmdExecFactory();
45+
Builder configBuilder = DefaultDockerClientConfig.createDefaultConfigBuilder()
46+
.withDockerHost("tcp://localhost:" + dockerPort)
47+
.withApiVersion("1.23");
48+
49+
DockerClient client = DockerClientBuilder.getInstance(configBuilder)
50+
.withDockerCmdExecFactory(factory)
51+
.build();
52+
53+
FakeDockerServer server = new FakeDockerServer(dockerPort);
54+
server.start();
55+
try {
56+
client.versionCmd().exec();
57+
58+
List<HttpRequest> requests = server.getRequests();
59+
60+
assertEquals(requests.size(), 1);
61+
assertEquals(requests.get(0).uri(), "/v1.23/version");
62+
} finally {
63+
server.stop();
64+
}
65+
}
66+
67+
@Test
68+
public void testNettyDockerCmdExecFactoryConfigWithoutApiVersion() throws Exception {
69+
int dockerPort = getFreePort();
70+
71+
NettyDockerCmdExecFactory factory = new NettyDockerCmdExecFactory();
72+
Builder configBuilder = DefaultDockerClientConfig.createDefaultConfigBuilder().withDockerHost("tcp://localhost:" + dockerPort);
73+
74+
DockerClient client = DockerClientBuilder.getInstance(configBuilder)
75+
.withDockerCmdExecFactory(factory)
76+
.build();
77+
78+
FakeDockerServer server = new FakeDockerServer(dockerPort);
79+
server.start();
80+
try {
81+
client.versionCmd().exec();
82+
83+
List<HttpRequest> requests = server.getRequests();
84+
85+
assertEquals(requests.size(), 1);
86+
assertEquals(requests.get(0).uri(), "/version");
87+
} finally {
88+
server.stop();
89+
}
90+
}
91+
92+
private int getFreePort() throws IOException {
93+
ServerSocket socket = new ServerSocket(0);
94+
int freePort = socket.getLocalPort();
95+
socket.close();
96+
return freePort;
97+
}
98+
99+
private class FakeDockerServer {
100+
private final int port;
101+
private final NioEventLoopGroup parent;
102+
private final NioEventLoopGroup child;
103+
private final List<HttpRequest> requests = new ArrayList<>();
104+
private Channel channel;
105+
106+
private FakeDockerServer(int port) {
107+
this.port = port;
108+
this.parent = new NioEventLoopGroup();
109+
this.child = new NioEventLoopGroup();
110+
}
111+
112+
private void start() throws Exception {
113+
ServerBootstrap bootstrap = new ServerBootstrap();
114+
bootstrap.group(parent, child)
115+
.channel(NioServerSocketChannel.class)
116+
.childHandler(new ChannelInitializer<SocketChannel>() {
117+
@Override
118+
protected void initChannel(SocketChannel socketChannel) throws Exception {
119+
ChannelPipeline pipeline = socketChannel.pipeline();
120+
pipeline.addLast("codec", new HttpServerCodec());
121+
pipeline.addLast("httpHandler", new SimpleChannelInboundHandler<Object>() {
122+
@Override
123+
protected void channelRead0(ChannelHandlerContext context, Object message) throws Exception {
124+
if (message instanceof HttpRequest) {
125+
// Keep track of processed requests
126+
HttpRequest request = (HttpRequest) message;
127+
requests.add(request);
128+
}
129+
130+
if (message instanceof HttpContent) {
131+
// Write an empty JSON response back to the client
132+
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.copiedBuffer("{}", CharsetUtil.UTF_8));
133+
response.headers().set(CONTENT_TYPE, "application/json; charset=UTF-8");
134+
response.headers().set(CONTENT_LENGTH, response.content().readableBytes());
135+
context.writeAndFlush(response);
136+
}
137+
}
138+
});
139+
}
140+
});
141+
142+
channel = bootstrap.bind(port).syncUninterruptibly().channel();
143+
}
144+
145+
private void stop() throws Exception {
146+
parent.shutdownGracefully();
147+
child.shutdownGracefully();
148+
channel.closeFuture().sync();
149+
}
150+
151+
private List<HttpRequest> getRequests() {
152+
return requests;
153+
}
154+
}
155+
}

0 commit comments

Comments
 (0)