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