Skip to content

Commit 2d418a8

Browse files
authored
Merge pull request #19 from brendandburns/ws
Web socket support.
2 parents 782a947 + 380928a commit 2d418a8

File tree

9 files changed

+265
-22
lines changed

9 files changed

+265
-22
lines changed

examples/src/main/java/io/kubernetes/client/examples/Example.java

+12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
/*
2+
Copyright 2017 The Kubernetes Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
113
package io.kubernetes.client.examples;
214

315
import io.kubernetes.client.ApiClient;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
Copyright 2017 The Kubernetes Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
package io.kubernetes.client.examples;
14+
15+
import io.kubernetes.client.ApiClient;
16+
import io.kubernetes.client.ApiException;
17+
import io.kubernetes.client.util.Config;
18+
import io.kubernetes.client.util.WebSockets;
19+
20+
import java.io.BufferedReader;
21+
import java.io.IOException;
22+
import java.io.InputStream;
23+
import java.io.Reader;
24+
25+
public class WebSocketsExample {
26+
public static void main(String... args) throws ApiException, IOException {
27+
final ApiClient client = Config.defaultClient();
28+
WebSockets.stream(args[0], "GET", client, new WebSockets.SocketListener() {
29+
public void open() {}
30+
public void close() {
31+
// Trigger shutdown of the dispatcher's executor so this process can exit cleanly.
32+
client.getHttpClient().getDispatcher().getExecutorService().shutdown();
33+
}
34+
public void bytesMessage(InputStream is) {}
35+
public void textMessage(Reader in) {
36+
try {
37+
BufferedReader reader = new BufferedReader(in);
38+
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
39+
System.out.println(line);
40+
}
41+
} catch (IOException ex) {
42+
ex.printStackTrace();
43+
}
44+
}
45+
});
46+
}
47+
}

kubernetes/.swagger-codegen-ignore

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
.gitignore
22
git_push.sh
33
# Remove this once swagger-codegen 2.2.3 is released and we update.
4-
# We want https://github.com/swagger-api/swagger-codegen/pull/5629
5-
# in the release.
4+
# Verify the following PRs are in the release:
5+
# * https://github.com/swagger-api/swagger-codegen/pull/5629
6+
# * https://github.com/swagger-api/swagger-codegen/pull/5648
67
src/main/java/io/kubernetes/client/ApiClient.java
78

kubernetes/src/main/java/io/kubernetes/client/ApiClient.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,12 @@ public <T> T handleResponse(Response response, Type returnType) throws ApiExcept
10691069
* @throws ApiException If fail to serialize the request body object
10701070
*/
10711071
public Call buildCall(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String[] authNames, ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException {
1072+
Request request = buildRequest(path, method, queryParams, body, headerParams, formParams, authNames, progressRequestListener);
1073+
1074+
return httpClient.newCall(request);
1075+
}
1076+
1077+
public Request buildRequest(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String[] authNames, ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException {
10721078
updateParamsForAuth(authNames, queryParams, headerParams);
10731079

10741080
final String url = buildUrl(path, queryParams);
@@ -1108,8 +1114,7 @@ public Call buildCall(String path, String method, List<Pair> queryParams, Object
11081114
} else {
11091115
request = reqBuilder.method(method, reqBody).build();
11101116
}
1111-
1112-
return httpClient.newCall(request);
1117+
return request;
11131118
}
11141119

11151120
/**

util/pom.xml

+31-17
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,23 @@
2424
<artifactId>commons-codec</artifactId>
2525
<version>1.10</version>
2626
</dependency>
27+
<dependency>
28+
<groupId>com.squareup.okhttp</groupId>
29+
<artifactId>okhttp-ws</artifactId>
30+
<version>2.7.5</version>
31+
</dependency>
32+
<dependency>
33+
<groupId>com.google.guava</groupId>
34+
<artifactId>guava</artifactId>
35+
<version>22.0</version>
36+
</dependency>
2737
<!-- test dependencies -->
2838
<dependency>
2939
<groupId>junit</groupId>
3040
<artifactId>junit</artifactId>
3141
<version>4.12</version>
3242
<scope>test</scope>
3343
</dependency>
34-
<!-- https://mvnrepository.com/artifact/com.github.stefanbirkner/system-rules -->
3544
<dependency>
3645
<groupId>com.github.stefanbirkner</groupId>
3746
<artifactId>system-rules</artifactId>
@@ -49,22 +58,27 @@
4958
<target>1.7</target>
5059
</configuration>
5160
</plugin>
52-
<plugin>
53-
<groupId>org.apache.maven.plugins</groupId>
54-
<artifactId>maven-surefire-plugin</artifactId>
55-
<version>2.12</version>
56-
<configuration>
57-
<systemProperties>
58-
<property>
59-
<name>loggerPath</name>
60-
<value>conf/log4j.properties</value>
61-
</property>
62-
</systemProperties>
63-
<argLine>-Xms512m -Xmx1500m</argLine>
64-
<parallel>methods</parallel>
65-
<forkMode>pertest</forkMode>
66-
</configuration>
67-
</plugin>
61+
<plugin>
62+
<groupId>org.apache.maven.plugins</groupId>
63+
<artifactId>maven-surefire-plugin</artifactId>
64+
<version>2.12</version>
65+
<configuration>
66+
<systemProperties>
67+
<property>
68+
<name>loggerPath</name>
69+
<value>conf/log4j.properties</value>
70+
</property>
71+
</systemProperties>
72+
<argLine>-Xms512m -Xmx1500m</argLine>
73+
<parallel>methods</parallel>
74+
<forkMode>pertest</forkMode>
75+
</configuration>
76+
</plugin>
6877
</plugins>
6978
</build>
79+
<properties>
80+
<java.version>1.7</java.version>
81+
<maven.compiler.source>${java.version}</maven.compiler.source>
82+
<maven.compiler.target>${java.version}</maven.compiler.target>
83+
</properties>
7084
</project>

util/src/main/java/io/kubernetes/client/util/Config.java

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
/*
2+
Copyright 2017 The Kubernetes Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
113
package io.kubernetes.client.util;
214

315
import io.kubernetes.client.ApiClient;
@@ -163,4 +175,4 @@ public static ApiClient defaultClient() throws IOException {
163175
client.setBasePath(DEFAULT_FALLBACK_HOST);
164176
return client;
165177
}
166-
}
178+
}

util/src/main/java/io/kubernetes/client/util/KubeConfig.java

+12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
/*
2+
Copyright 2017 The Kubernetes Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
113
package io.kubernetes.client.util;
214

315
import java.io.File;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
Copyright 2017 The Kubernetes Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
package io.kubernetes.client.util;
14+
15+
import io.kubernetes.client.ApiClient;
16+
import io.kubernetes.client.ApiException;
17+
import io.kubernetes.client.Pair;
18+
19+
import com.google.common.net.HttpHeaders;
20+
import com.squareup.okhttp.MediaType;
21+
import com.squareup.okhttp.Request;
22+
import com.squareup.okhttp.Response;
23+
import com.squareup.okhttp.ResponseBody;
24+
import com.squareup.okhttp.ws.WebSocket;
25+
import com.squareup.okhttp.ws.WebSocketCall;
26+
import com.squareup.okhttp.ws.WebSocketListener;
27+
import okio.Buffer;
28+
29+
import static com.squareup.okhttp.ws.WebSocket.BINARY;
30+
import static com.squareup.okhttp.ws.WebSocket.TEXT;
31+
32+
import java.io.IOException;
33+
import java.io.InputStream;
34+
import java.io.Reader;
35+
import java.util.ArrayList;
36+
import java.util.HashMap;
37+
38+
public class WebSockets {
39+
public static final String V4_STREAM_PROTOCOL = "v4.channel.k8s.io";
40+
public static final String V3_STREAM_PROTOCOL = "v3.channel.k8s.io";
41+
public static final String V2_STREAM_PROTOCOL = "v2.channel.k8s.io";
42+
public static final String V1_STREAM_PROTOCOL = "channel.k8s.io";
43+
public static final String STREAM_PROTOCOL_HEADER = "X-Stream-Protocol-Version";
44+
public static final String SPDY_3_1 = "SPDY/3.1";
45+
46+
/**
47+
* A simple interface for a listener on a web socket
48+
*/
49+
public interface SocketListener {
50+
/**
51+
* Called when the socket is opened
52+
*/
53+
public void open();
54+
55+
/**
56+
* Callled when a binary media type message is received
57+
* @param in The input stream containing the binary data
58+
*/
59+
public void bytesMessage(InputStream in);
60+
61+
/**
62+
* Called when a text media type message is received
63+
* @param in The character stream containing the message
64+
*/
65+
public void textMessage(Reader in);
66+
67+
/**
68+
* Called when the stream is closed.
69+
*/
70+
public void close();
71+
}
72+
73+
/**
74+
* Create a new WebSocket stream
75+
* @param path The HTTP Path to request from the API
76+
* @param method The HTTP method to use for the call
77+
* @param client The ApiClient for communicating with the API
78+
* @param listener The socket listener to handle socket events
79+
*/
80+
public static void stream(String path, String method, ApiClient client, SocketListener listener) throws ApiException, IOException {
81+
HashMap<String, String> headers = new HashMap<String, String>();
82+
String allProtocols = String.format("%s,%s,%s,%s", V4_STREAM_PROTOCOL, V3_STREAM_PROTOCOL, V2_STREAM_PROTOCOL, V1_STREAM_PROTOCOL);
83+
headers.put(STREAM_PROTOCOL_HEADER, allProtocols);
84+
headers.put(HttpHeaders.CONNECTION, HttpHeaders.UPGRADE);
85+
headers.put(HttpHeaders.UPGRADE, SPDY_3_1);
86+
87+
Request request = client.buildRequest(path, method, new ArrayList<Pair>(), null, headers, new HashMap<String, Object>(), new String[0], null);
88+
WebSocketCall.create(client.getHttpClient(), request).enqueue(new Listener(listener));
89+
}
90+
91+
private static class Listener implements WebSocketListener {
92+
private SocketListener listener;
93+
94+
public Listener(SocketListener listener) {
95+
this.listener = listener;
96+
}
97+
98+
@Override
99+
public void onOpen(WebSocket webSocket, Response response) {
100+
listener.open();
101+
}
102+
103+
@Override
104+
public void onMessage(ResponseBody body) throws IOException {
105+
if (body.contentType() == TEXT) {
106+
listener.bytesMessage(body.byteStream());
107+
} else if (body.contentType() == BINARY) {
108+
listener.textMessage(body.charStream());
109+
}
110+
body.close();
111+
}
112+
113+
@Override
114+
public void onPong(Buffer payload) {
115+
}
116+
117+
@Override
118+
public void onClose(int code, String reason) {
119+
listener.close();
120+
}
121+
122+
@Override
123+
public void onFailure(IOException e, Response res) {
124+
e.printStackTrace();
125+
listener.close();
126+
}
127+
}
128+
}

util/src/test/java/io/kuberentes/client/util/ConfigTest.java

+12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
/*
2+
Copyright 2017 The Kubernetes Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
113
package io.kubernetes.client.util;
214

315
import io.kubernetes.client.ApiClient;

0 commit comments

Comments
 (0)