Skip to content

Commit 912668b

Browse files
committed
Handle watch status that is missing or for 410 doesn't include good resource version
1 parent 2f1ff60 commit 912668b

File tree

3 files changed

+52
-2
lines changed

3 files changed

+52
-2
lines changed

operator/src/main/java/oracle/kubernetes/operator/Watcher.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,14 +187,22 @@ private void handleRegularUpdate(Watch.Response<T> item) {
187187

188188
private void handleErrorResponse(Watch.Response<T> item) {
189189
V1Status status = item.status;
190-
if (status != null && status.getCode() == HTTP_GONE) {
190+
if (status == null) {
191+
// The kubernetes client parsing logic can mistakenly parse a status as a type
192+
// with similar fields, such as V1ConfigMap. In this case, the actual status is
193+
// not available to our layer, so respond defensively by resetting resource version.
194+
resourceVersion = 0l;
195+
} else if (status.getCode() == HTTP_GONE) {
196+
resourceVersion = 0l;
191197
String message = status.getMessage();
192198
int index1 = message.indexOf('(');
193199
if (index1 > 0) {
194200
int index2 = message.indexOf(')', index1 + 1);
195201
if (index2 > 0) {
196202
String val = message.substring(index1 + 1, index2);
197-
resourceVersion = !isNullOrEmptyString(val) ? Long.parseLong(val) : 0;
203+
if (!isNullOrEmptyString(val)) {
204+
resourceVersion = Long.parseLong(val);
205+
}
198206
}
199207
}
200208
}

operator/src/test/java/oracle/kubernetes/operator/WatcherTestBase.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ private Watch.Response createHttpGoneErrorResponse(int nextResourceVersion) {
107107
return WatchEvent.createErrorEvent(HTTP_GONE, nextResourceVersion).toWatchResponse();
108108
}
109109

110+
private Watch.Response createHttpGoneErrorWithoutResourceVersionResponse() {
111+
return WatchEvent.createErrorEvent(HTTP_GONE).toWatchResponse();
112+
}
113+
114+
private Watch.Response createErrorWithoutStatusResponse() {
115+
return WatchEvent.createErrorEventWithoutStatus().toWatchResponse();
116+
}
117+
110118
@SuppressWarnings({"unchecked", "rawtypes"})
111119
@Test
112120
public void receivedEvents_areSentToListeners() {
@@ -152,6 +160,36 @@ public void afterHttpGoneError_nextRequestSendsIncludedResourceVersion() {
152160
}
153161
}
154162

163+
@SuppressWarnings({"unchecked", "rawtypes"})
164+
@Test
165+
public void afterHttpGoneErrorWithoutResourceVersion_nextRequestSendsResourceVersionZero() {
166+
try {
167+
StubWatchFactory.addCallResponses(createHttpGoneErrorWithoutResourceVersionResponse());
168+
scheduleDeleteResponse(createObjectWithMetaData());
169+
170+
createAndRunWatcher(NAMESPACE, stopping, INITIAL_RESOURCE_VERSION);
171+
172+
assertThat(StubWatchFactory.getRequestParameters().get(1), hasEntry("resourceVersion", "0"));
173+
} catch (Throwable t) {
174+
t.printStackTrace();
175+
}
176+
}
177+
178+
@SuppressWarnings({"unchecked", "rawtypes"})
179+
@Test
180+
public void afterErrorWithoutStatus_nextRequestSendsResourceVersionZero() {
181+
try {
182+
StubWatchFactory.addCallResponses(createErrorWithoutStatusResponse());
183+
scheduleDeleteResponse(createObjectWithMetaData());
184+
185+
createAndRunWatcher(NAMESPACE, stopping, INITIAL_RESOURCE_VERSION);
186+
187+
assertThat(StubWatchFactory.getRequestParameters().get(1), hasEntry("resourceVersion", "0"));
188+
} catch (Throwable t) {
189+
t.printStackTrace();
190+
}
191+
}
192+
155193
@SuppressWarnings({"unchecked", "rawtypes"})
156194
@Test
157195
public void afterDelete_nextRequestSendsIncrementedResourceVersion() {

operator/src/test/java/oracle/kubernetes/operator/builders/WatchEvent.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ public static <S> WatchEvent<S> createDeleteEvent(S object) {
4848
return new WatchEvent<>("DELETED", object);
4949
}
5050

51+
public static <S> WatchEvent<S> createErrorEventWithoutStatus() {
52+
return new WatchEvent<>(null);
53+
}
54+
5155
public static <S> WatchEvent<S> createErrorEvent(int statusCode) {
5256
return new WatchEvent<>(new V1Status().code(statusCode).message("Oops"));
5357
}

0 commit comments

Comments
 (0)