Skip to content

Commit f634cad

Browse files
committed
fix(logs): work with multiple containers
1 parent cc1fcb3 commit f634cad

File tree

2 files changed

+48
-17
lines changed

2 files changed

+48
-17
lines changed

TODO.md

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626

2727
## TUI
2828

29+
- Allow wrapping around with the tabs (so left from 0 goes to the end).
30+
2931
- Dashboard as a struct doesn't really make sense anymore, it should likely be
3032
converted over to a simple function.
3133

@@ -59,6 +61,7 @@
5961
- Allow globs in file paths, eg `/*/nginx**/etc/passwd`.
6062
- Return an error that is nicer than "no files found" when a container doesn't
6163
have cat/ls.
64+
- Test `rsync` SSH integration.
6265

6366
## SSH Functionality
6467

src/widget/log.rs

+45-17
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ use std::sync::Arc;
22

33
use color_eyre::{Section, SectionExt};
44
use eyre::{eyre, Report, Result};
5-
use futures::{future::BoxFuture, AsyncBufReadExt, FutureExt, TryStreamExt};
5+
use futures::{
6+
future::{try_join_all, BoxFuture},
7+
io::AsyncBufRead,
8+
stream, AsyncBufReadExt, FutureExt, TryStreamExt,
9+
};
610
use k8s_openapi::api::core::v1::Pod;
711
use kube::{api::LogParams, Api, ResourceExt};
812
use ratatui::{layout::Rect, text::Line, widgets::Paragraph, Frame};
@@ -12,7 +16,13 @@ use tokio::{
1216
};
1317

1418
use super::{tabs::Tab, Widget, WIDGET_VIEWS};
15-
use crate::events::{Broadcast, Event, Keypress};
19+
use crate::{
20+
events::{Broadcast, Event, Keypress},
21+
resources::{
22+
container::{Container, ContainerExt},
23+
pod::PodExt,
24+
},
25+
};
1626

1727
pub struct Log {
1828
task: JoinHandle<Result<()>>,
@@ -185,11 +195,37 @@ fn log_stream<'a>(
185195
params: LogParams,
186196
) -> BoxFuture<'a, Result<()>> {
187197
async move {
188-
let mut stream = match Api::<Pod>::namespaced(client.clone(), &pod.namespace().unwrap())
189-
.log_stream(&pod.name_any(), &params)
190-
.await
191-
{
192-
Ok(stream) => stream.lines(),
198+
let client = Api::<Pod>::namespaced(client.clone(), &pod.namespace().unwrap());
199+
200+
let containers = try_join_all(pod.containers(None).iter().map(|c| {
201+
let mut params = params.clone();
202+
params.container = Some(c.name_any());
203+
204+
container_stream(&client, c, params)
205+
}))
206+
.await?;
207+
208+
let mut all_logs = stream::select_all(containers.into_iter().map(AsyncBufReadExt::lines));
209+
210+
while let Some(line) = all_logs.try_next().await? {
211+
tx.send(line)?;
212+
}
213+
214+
tracing::debug!(pod = pod.name_any(), "stream ended");
215+
216+
Ok(())
217+
}
218+
.boxed()
219+
}
220+
221+
fn container_stream<'a>(
222+
client: &'a Api<Pod>,
223+
container: &'a Container,
224+
params: LogParams,
225+
) -> BoxFuture<'a, Result<impl AsyncBufRead>> {
226+
async move {
227+
match client.log_stream(&container.pod_name(), &params).await {
228+
Ok(stream) => Ok(stream),
193229
Err(err) => {
194230
let kube::Error::Api(resp) = &err else {
195231
return Err(Report::new(err));
@@ -200,20 +236,12 @@ fn log_stream<'a>(
200236

201237
new_params.previous = false;
202238

203-
return log_stream(client, pod, tx, new_params).await;
239+
return container_stream(client, container, new_params).await;
204240
}
205241

206-
return Err(eyre!(err));
242+
Err(eyre!(err))
207243
}
208-
};
209-
210-
while let Some(line) = stream.try_next().await? {
211-
tx.send(line)?;
212244
}
213-
214-
tracing::debug!(pod = pod.name_any(), "stream ended");
215-
216-
Ok(())
217245
}
218246
.boxed()
219247
}

0 commit comments

Comments
 (0)