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