Skip to content

Commit 9403f26

Browse files
authored
Merge pull request #519 from brendandburns/parse
Fix some problems with watches that return a v1.Status
2 parents 13740ae + fe678f2 commit 9403f26

File tree

2 files changed

+104
-9
lines changed

2 files changed

+104
-9
lines changed

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

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,17 @@
1212
*/
1313
package io.kubernetes.client.util;
1414

15-
import com.google.gson.JsonParseException;
1615
import com.google.gson.annotations.SerializedName;
1716
import com.google.gson.reflect.TypeToken;
17+
import com.google.gson.stream.JsonReader;
1818
import com.squareup.okhttp.Call;
1919
import com.squareup.okhttp.ResponseBody;
2020
import io.kubernetes.client.ApiClient;
2121
import io.kubernetes.client.ApiException;
2222
import io.kubernetes.client.JSON;
2323
import io.kubernetes.client.models.V1Status;
2424
import java.io.IOException;
25+
import java.io.StringReader;
2526
import java.lang.reflect.Type;
2627
import java.util.Iterator;
2728
import org.slf4j.Logger;
@@ -112,7 +113,7 @@ public static <T> Watch<T> createWatch(ApiClient client, Call call, Type watchTy
112113
}
113114
}
114115

115-
private Watch(JSON json, ResponseBody body, Type watchType, Call call) {
116+
protected Watch(JSON json, ResponseBody body, Type watchType, Call call) {
116117
this.response = body;
117118
this.watchType = watchType;
118119
this.json = json;
@@ -125,18 +126,60 @@ public Response<T> next() {
125126
if (line == null) {
126127
throw new RuntimeException("Null response from the server.");
127128
}
128-
try {
129-
return json.deserialize(line, watchType);
130-
} catch (JsonParseException ex) {
131-
Type statusType = new TypeToken<Response<V1Status>>() {}.getType();
132-
Response<V1Status> status = json.deserialize(line, statusType);
133-
return new Response<T>(status.type, status.object);
134-
}
129+
return parseLine(line);
135130
} catch (IOException e) {
136131
throw new RuntimeException("IO Exception during next method.", e);
137132
}
138133
}
139134

135+
protected boolean isStatus(String line) throws IOException {
136+
boolean found = false;
137+
JsonReader reader = new JsonReader(new StringReader(line));
138+
reader.beginObject();
139+
// extract object data.
140+
while (reader.hasNext()) {
141+
String name = reader.nextName();
142+
if (name.equals("object")) {
143+
found = true;
144+
break;
145+
}
146+
reader.skipValue();
147+
}
148+
if (!found) {
149+
return false;
150+
}
151+
152+
String kind = null;
153+
String apiVersion = null;
154+
reader.beginObject();
155+
while (reader.hasNext()) {
156+
String name = reader.nextName();
157+
if (name.equals("kind")) {
158+
kind = reader.nextString();
159+
} else if (name.equals("apiVersion")) {
160+
apiVersion = reader.nextString();
161+
} else {
162+
reader.skipValue();
163+
}
164+
if (apiVersion != null && kind != null) {
165+
break;
166+
}
167+
}
168+
if ("Status".equals(kind) && "v1".equals(apiVersion)) {
169+
return true;
170+
}
171+
return false;
172+
}
173+
174+
protected Response<T> parseLine(String line) throws IOException {
175+
if (!isStatus(line)) {
176+
return json.deserialize(line, watchType);
177+
}
178+
Type statusType = new TypeToken<Response<V1Status>>() {}.getType();
179+
Response<V1Status> status = json.deserialize(line, statusType);
180+
return new Response<T>(status.type, status.object);
181+
}
182+
140183
public boolean hasNext() {
141184
try {
142185
return !response.source().exhausted();
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
Copyright 2019 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 static org.junit.Assert.assertEquals;
16+
17+
import com.google.gson.JsonObject;
18+
import com.google.gson.reflect.TypeToken;
19+
import io.kubernetes.client.JSON;
20+
import io.kubernetes.client.models.V1ConfigMap;
21+
import java.io.IOException;
22+
import org.junit.Test;
23+
24+
/** Tests for the Watch helper class */
25+
public class WatchTest {
26+
@Test
27+
public void testWatchEnd() throws IOException {
28+
JSON json = new JSON();
29+
Watch<V1ConfigMap> watch =
30+
new Watch<V1ConfigMap>(
31+
json, null, new TypeToken<Watch.Response<V1ConfigMap>>() {}.getType(), null);
32+
JsonObject metadata = new JsonObject();
33+
metadata.addProperty("name", "foo");
34+
metadata.addProperty("namespace", "bar");
35+
36+
JsonObject status = new JsonObject();
37+
status.add("metadata", metadata);
38+
status.addProperty("kind", "Status");
39+
status.addProperty("apiVersion", "v1");
40+
status.addProperty("status", "failure");
41+
status.addProperty("message", "too old resource version");
42+
status.addProperty("reason", "Gone");
43+
status.addProperty("code", 410);
44+
45+
JsonObject obj = new JsonObject();
46+
obj.addProperty("type", "ERROR");
47+
obj.add("object", status);
48+
String data = json.getGson().toJson(obj);
49+
Watch.Response<V1ConfigMap> response = watch.parseLine(data);
50+
assertEquals(null, response.object);
51+
}
52+
}

0 commit comments

Comments
 (0)