Skip to content

Commit 5320d8f

Browse files
authored
Fix watcher not fully paginating on Init (#1525)
* Fix watcher not fully paginating on Init cannot believe i missed this :( fixes #1524 Signed-off-by: clux <[email protected]> * upgrade mock test (these fail on master) Signed-off-by: clux <[email protected]> --------- Signed-off-by: clux <[email protected]>
1 parent f553c4e commit 5320d8f

File tree

2 files changed

+30
-5
lines changed

2 files changed

+30
-5
lines changed

kube-runtime/src/watcher.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -499,9 +499,12 @@ where
499499
last_bookmark,
500500
});
501501
}
502-
if let Some(resource_version) = last_bookmark {
503-
// we have drained the last page - move on to next stage
504-
return (Some(Ok(Event::InitDone)), State::InitListed { resource_version });
502+
// check if we need to perform more pages
503+
if continue_token.is_none() {
504+
if let Some(resource_version) = last_bookmark {
505+
// we have drained the last page - move on to next stage
506+
return (Some(Ok(Event::InitDone)), State::InitListed { resource_version });
507+
}
505508
}
506509
let mut lp = wc.to_list_params();
507510
lp.continue_token = continue_token;

kube/src/mock_tests.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ impl Hack {
2929
#[tokio::test]
3030
async fn watchers_respect_pagination_limits() {
3131
let (client, fakeserver) = testcontext();
32-
// NB: scenario only responds responds to TWO paginated list calls with two objects
32+
// NB: page scenario which responds to 3 paginated list calls with 3 object (one per page).
33+
// This ensures the watcher internal paging mechanism is not bypassed
34+
// and that each page is actually drained before starting the long watch.
3335
let mocksrv = fakeserver.run(Scenario::PaginatedList);
3436

3537
let api: Api<Hack> = Api::all(client);
@@ -39,6 +41,8 @@ async fn watchers_respect_pagination_limits() {
3941
assert_eq!(first.spec.num, 1);
4042
let second: Hack = stream.try_next().await.unwrap().unwrap();
4143
assert_eq!(second.spec.num, 2);
44+
let third: Hack = stream.try_next().await.unwrap().unwrap();
45+
assert_eq!(third.spec.num, 3);
4246
assert!(poll!(stream.next()).is_pending());
4347
timeout_after_1s(mocksrv).await;
4448
}
@@ -117,14 +121,32 @@ impl ApiServerVerifier {
117121
"kind": "HackList",
118122
"apiVersion": "kube.rs/v1",
119123
"metadata": {
120-
"continue": "",
124+
"continue": "second",
121125
"resourceVersion": "2"
122126
},
123127
"items": [Hack::test(2)]
124128
});
125129
let response = serde_json::to_vec(&respdata).unwrap(); // respond as the apiserver would have
126130
send.send_response(Response::builder().body(Body::from(response)).unwrap());
127131
}
132+
{
133+
// we expect a final list GET because we included a continue token
134+
let (request, send) = self.0.next_request().await.expect("service not called 3");
135+
assert_eq!(request.method(), http::Method::GET);
136+
let req_uri = request.uri().to_string();
137+
assert!(req_uri.contains("&continue=second"));
138+
let respdata = json!({
139+
"kind": "HackList",
140+
"apiVersion": "kube.rs/v1",
141+
"metadata": {
142+
"continue": "",
143+
"resourceVersion": "2"
144+
},
145+
"items": [Hack::test(3)]
146+
});
147+
let response = serde_json::to_vec(&respdata).unwrap(); // respond as the apiserver would have
148+
send.send_response(Response::builder().body(Body::from(response)).unwrap());
149+
}
128150
Ok(self)
129151
}
130152
}

0 commit comments

Comments
 (0)