Skip to content

Commit 88e63d4

Browse files
authored
Merge pull request #69 from brendandburns/proto
initial protobuf client.
2 parents b6a1928 + dd3a485 commit 88e63d4

File tree

6 files changed

+176
-1
lines changed

6 files changed

+176
-1
lines changed

examples/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424
<artifactId>client-java-util</artifactId>
2525
<version>0.2-SNAPSHOT</version>
2626
</dependency>
27+
<dependency>
28+
<groupId>io.kubernetes</groupId>
29+
<artifactId>client-java-proto</artifactId>
30+
<version>0.2-SNAPSHOT</version>
31+
</dependency>
2732
<dependency>
2833
<groupId>com.google.guava</groupId>
2934
<artifactId>guava</artifactId>
Lines changed: 47 additions & 0 deletions
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.Configuration;
18+
import io.kubernetes.client.ProtoClient;
19+
import io.kubernetes.client.proto.V1.Pod;
20+
import io.kubernetes.client.proto.V1.PodList;
21+
import io.kubernetes.client.util.Config;
22+
23+
import java.io.IOException;
24+
25+
26+
/**
27+
* A simple example of how to use the Java API
28+
*
29+
* Easiest way to run this:
30+
* mvn exec:java -Dexec.mainClass="io.kubernetes.client.examples.ProtoExample"
31+
*
32+
* From inside $REPO_DIR/examples
33+
*/
34+
public class ProtoExample {
35+
public static void main(String[] args) throws IOException, ApiException, InterruptedException {
36+
ApiClient client = Config.defaultClient();
37+
Configuration.setDefaultApiClient(client);
38+
39+
ProtoClient pc = new ProtoClient(client);
40+
PodList list = pc.list(PodList.newBuilder(), "/api/v1/namespaces/default/pods");
41+
42+
if (list.getItemsCount() > 0) {
43+
Pod p = list.getItems(0);
44+
System.out.println(p.toString());
45+
}
46+
}
47+
}

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<module>util</module>
1313
<module>examples</module>
1414
<module>kubernetes</module>
15+
<module>proto</module>
1516
</modules>
1617

1718
<scm>

proto/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<modelVersion>4.0.0</modelVersion>
33
<groupId>io.kubernetes</groupId>
44
<artifactId>client-java-proto</artifactId>
5-
<version>0.1-SNAPSHOT</version>
5+
<version>0.2-SNAPSHOT</version>
66
<packaging>jar</packaging>
77
<name>client-java-proto</name>
88
<url>https://github.com/kubernetes-client/java</url>

util/pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717
<artifactId>client-java-api</artifactId>
1818
<version>0.2-SNAPSHOT</version>
1919
</dependency>
20+
<dependency>
21+
<groupId>io.kubernetes</groupId>
22+
<artifactId>client-java-proto</artifactId>
23+
<version>0.2-SNAPSHOT</version>
24+
</dependency>
2025
<dependency>
2126
<groupId>org.yaml</groupId>
2227
<artifactId>snakeyaml</artifactId>
@@ -59,6 +64,11 @@
5964
<artifactId>system-rules</artifactId>
6065
<version>1.16.1</version>
6166
</dependency>
67+
<dependency>
68+
<groupId>com.google.protobuf</groupId>
69+
<artifactId>protobuf-java</artifactId>
70+
<version>3.4.0</version>
71+
</dependency>
6272
</dependencies>
6373
<build>
6474
<plugins>
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package io.kubernetes.client;
2+
3+
import io.kubernetes.client.ApiException;
4+
import io.kubernetes.client.Configuration;
5+
import io.kubernetes.client.proto.Runtime.Unknown;
6+
7+
import com.google.common.io.ByteStreams;
8+
import com.google.protobuf.Message;
9+
import com.squareup.okhttp.Request;
10+
import com.squareup.okhttp.Response;
11+
import com.squareup.okhttp.ResponseBody;
12+
13+
import java.io.IOException;
14+
import java.io.InputStream;
15+
import java.util.ArrayList;
16+
import java.util.HashMap;
17+
18+
public class ProtoClient {
19+
private ApiClient apiClient;
20+
// Magic number for the beginning of proto encoded.
21+
// https://github.com/kubernetes/apimachinery/blob/master/pkg/runtime/serializer/protobuf/protobuf.go#L42
22+
private static final byte[] MAGIC = new byte[] { 0x6b, 0x38, 0x73, 0x00 };
23+
24+
/**
25+
* Simple Protocol Budder API client constructor, uses default configuration
26+
*/
27+
public ProtoClient() {
28+
this(Configuration.getDefaultApiClient());
29+
}
30+
31+
/**
32+
* ProtocolBuffer Client Constructor
33+
* @param apiClient The api client to use.
34+
*/
35+
public ProtoClient(ApiClient apiClient) {
36+
this.apiClient = apiClient;
37+
}
38+
39+
/**
40+
* Get the API client for these ProtocolBuffer operations.
41+
* @return The API client that will be used.
42+
*/
43+
public ApiClient getApiClient() {
44+
return apiClient;
45+
}
46+
47+
/**
48+
* Set the API client for subsequent ProtocolBuffer operations.
49+
* @param apiClient The new API client to use.
50+
*/
51+
public void setApiClient(ApiClient apiClient) {
52+
this.apiClient = apiClient;
53+
}
54+
55+
/**
56+
* Get a Kubernetes API object using protocol buffer encoding.
57+
* @param builder The appropriate Builder for the object receveived from the request.
58+
* @param path The URL path to call (e.g. /api/v1/namespaces/default/pods/pod-name)
59+
* @return A Message of type T
60+
*/
61+
public <T extends Message> T get(T.Builder builder, String path) throws ApiException, IOException {
62+
return (T) request(builder, path, "GET");
63+
}
64+
65+
/**
66+
* List is fluent, semantic sugar method on top of get, which is intended
67+
* to convey that the object is a List of objects rather than a single object
68+
* @param builder The appropriate Builder for the object receveived from the request.
69+
* @param path The URL path to call (e.g. /api/v1/namespaces/default/pods/pod-name)
70+
* @return A Message of type T
71+
*/
72+
public <T extends Message> T list(T.Builder listObj, String path) throws ApiException, IOException {
73+
return get(listObj, path);
74+
}
75+
76+
/**
77+
* Generic protocol buffer based HTTP request.
78+
* Not intended for general consumption, but public for advance use cases.
79+
* @param builder The appropriate Builder for the object receveived from the request.
80+
* @param method The HTTP method (e.g. GET) for this request.
81+
* @param path The URL path to call (e.g. /api/v1/namespaces/default/pods/pod-name)
82+
* @return A Message of type T
83+
*/
84+
public <T extends Message> T request(T.Builder builder, String path, String method) throws ApiException, IOException {
85+
HashMap<String, String> headers = new HashMap<String, String>();
86+
headers.put("Content-type", "application/vnd.kubernetes.protobuf");
87+
headers.put("Accept", "application/vnd.kubernetes.protobuf");
88+
Request request = apiClient.buildRequest(path, method, new ArrayList<Pair>(), new ArrayList<Pair>(), null,
89+
headers, new HashMap<String, Object>(), new String[0], null);
90+
Response resp = apiClient.getHttpClient().newCall(request).execute();
91+
Unknown u = parse(resp.body().byteStream());
92+
return (T) builder.mergeFrom(u.getRaw()).build();
93+
}
94+
95+
private Unknown parse(InputStream stream) throws ApiException, IOException {
96+
// This isn't really documented anywhere except the code, but
97+
// the proto-buf format is:
98+
// * 4 byte magic number
99+
// * Protocol Buffer encoded object of type runtime.Unknown
100+
// * the 'raw' field in that object contains a Protocol Buffer
101+
// encoding of the actual object.
102+
// TODO: Document this somewhere proper.
103+
byte[] magic = new byte[4];
104+
stream.read(magic);
105+
for (int i = 0; i < MAGIC.length; i++) {
106+
if (magic[i] != MAGIC[i]) {
107+
throw new ApiException("Unexpected magic number: " + magic);
108+
}
109+
}
110+
return Unknown.parseFrom(stream);
111+
}
112+
}

0 commit comments

Comments
 (0)