Skip to content

Commit d2eaa8d

Browse files
authored
Merge pull request #1937 from feloy/fix-1933/reset-resourceVersion-cherrypick
Port of #1934 and #1936
2 parents 01e9d81 + 95072a6 commit d2eaa8d

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

src/cache.ts

+5
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,11 @@ export class ListWatch<T extends KubernetesObject> implements ObjectCache<T>, In
186186

187187
private watchHandler(phase: string, obj: T, watchObj?: any): void {
188188
switch (phase) {
189+
case 'ERROR':
190+
if ((obj as { code?: number }).code === 410) {
191+
this.resourceVersion = '';
192+
}
193+
break;
189194
case 'ADDED':
190195
case 'MODIFIED':
191196
addOrUpdateObject(

src/cache_test.ts

+69
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,75 @@ describe('ListWatchCache', () => {
10981098
expect(listCalls).to.be.equal(2);
10991099
});
11001100

1101+
it('should list if the watch cannot be restarted from the latest resourceVersion with an ERROR event', async () => {
1102+
const fakeWatch = mock.mock(Watch);
1103+
const list: V1Pod[] = [];
1104+
const listObj = {
1105+
metadata: {
1106+
resourceVersion: '12345',
1107+
} as V1ListMeta,
1108+
items: list,
1109+
} as V1NamespaceList;
1110+
1111+
let listCalls = 0;
1112+
const listFn: ListPromise<V1Namespace> = function (): Promise<V1NamespaceList> {
1113+
return new Promise<V1NamespaceList>((resolve) => {
1114+
listCalls++;
1115+
resolve(listObj);
1116+
});
1117+
};
1118+
let promise = new Promise((resolve) => {
1119+
mock.when(
1120+
fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
1121+
).thenCall(() => {
1122+
resolve(new AbortController());
1123+
});
1124+
});
1125+
1126+
const informer = new ListWatch('/some/path', mock.instance(fakeWatch), listFn, false);
1127+
1128+
informer.start();
1129+
await promise;
1130+
1131+
const [, , watchHandler] = mock.capture(fakeWatch.watch).last();
1132+
watchHandler(
1133+
'ADDED',
1134+
{
1135+
metadata: {
1136+
name: 'name3',
1137+
} as V1ObjectMeta,
1138+
} as V1Namespace,
1139+
{ metadata: { resourceVersion: '23456' } },
1140+
);
1141+
1142+
await informer.stop();
1143+
1144+
let errorEmitted = false;
1145+
informer.on('error', () => (errorEmitted = true));
1146+
1147+
promise = new Promise((resolve) => {
1148+
mock.when(
1149+
fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
1150+
).thenCall(() => {
1151+
resolve(new AbortController());
1152+
});
1153+
});
1154+
1155+
informer.start();
1156+
await promise;
1157+
1158+
const [, , watchHandler2, doneHandler] = mock.capture(fakeWatch.watch).last();
1159+
watchHandler2('ERROR', {
1160+
code: 410,
1161+
});
1162+
doneHandler(undefined);
1163+
mock.verify(
1164+
fakeWatch.watch(mock.anything(), mock.anything(), mock.anything(), mock.anything()),
1165+
).twice();
1166+
expect(errorEmitted).to.equal(false);
1167+
expect(listCalls).to.be.equal(2);
1168+
});
1169+
11011170
it('should send label selector', async () => {
11021171
const APP_LABEL_SELECTOR = 'app=foo';
11031172

0 commit comments

Comments
 (0)