diff --git a/examples/log_stream.rs b/examples/log_stream.rs index 601ab03ba..d78047202 100644 --- a/examples/log_stream.rs +++ b/examples/log_stream.rs @@ -1,5 +1,8 @@ use futures::{AsyncBufReadExt, TryStreamExt}; -use k8s_openapi::api::core::v1::Pod; +use k8s_openapi::{ + api::core::v1::Pod, + chrono::{DateTime, Utc}, +}; use kube::{ api::{Api, LogParams}, Client, @@ -19,8 +22,11 @@ struct App { follow: bool, /// Since seconds - #[arg(long, short = 's')] + #[arg(long, conflicts_with = "since_time")] since: Option, + /// Since time + #[arg(long, conflicts_with = "since")] + since_time: Option>, /// Include timestamps in the log output #[arg(long, default_value = "false")] @@ -43,6 +49,7 @@ async fn main() -> anyhow::Result<()> { container: app.container, tail_lines: app.tail, since_seconds: app.since, + since_time: app.since_time, timestamps: app.timestamps, ..LogParams::default() }) diff --git a/kube-core/src/subresource.rs b/kube-core/src/subresource.rs index ebf560ddb..6687b86f9 100644 --- a/kube-core/src/subresource.rs +++ b/kube-core/src/subresource.rs @@ -30,6 +30,11 @@ pub struct LogParams { /// If this value precedes the time a pod was started, only logs since the pod start will be returned. /// If this value is in the future, no logs will be returned. Only one of sinceSeconds or sinceTime may be specified. pub since_seconds: Option, + /// An RFC3339 timestamp from which to show logs. If this value + /// precedes the time a pod was started, only logs since the pod start will be returned. + /// If this value is in the future, no logs will be returned. + /// Only one of sinceSeconds or sinceTime may be specified. + pub since_time: Option>, /// If set, the number of lines from the end of the logs to show. /// If not specified, logs are shown from the creation of the container or sinceSeconds or sinceTime pub tail_lines: Option, @@ -65,6 +70,9 @@ impl Request { if let Some(ss) = &lp.since_seconds { qp.append_pair("sinceSeconds", &ss.to_string()); + } else if let Some(st) = &lp.since_time { + let ser_since = st.to_rfc3339_opts(chrono::SecondsFormat::Secs, true); + qp.append_pair("sinceTime", &ser_since); } if let Some(tl) = &lp.tail_lines { @@ -347,6 +355,7 @@ impl Request { #[cfg(test)] mod test { use crate::{request::Request, resource::Resource}; + use chrono::{DateTime, TimeZone, Utc}; use k8s::core::v1 as corev1; use k8s_openapi::api as k8s; @@ -362,12 +371,29 @@ mod test { pretty: true, previous: true, since_seconds: Some(3600), + since_time: None, tail_lines: Some(4096), timestamps: true, }; let req = Request::new(url).logs("mypod", &lp).unwrap(); assert_eq!(req.uri(), "/api/v1/namespaces/ns/pods/mypod/log?&container=nginx&follow=true&limitBytes=10485760&pretty=true&previous=true&sinceSeconds=3600&tailLines=4096×tamps=true"); } + + #[test] + fn logs_since_time() { + let url = corev1::Pod::url_path(&(), Some("ns")); + let date: DateTime = Utc.with_ymd_and_hms(2023, 10, 19, 13, 14, 26).unwrap(); + let lp = LogParams { + since_seconds: None, + since_time: Some(date), + ..Default::default() + }; + let req = Request::new(url).logs("mypod", &lp).unwrap(); + assert_eq!( + req.uri(), + "/api/v1/namespaces/ns/pods/mypod/log?&sinceTime=2023-10-19T13%3A14%3A26Z" // cross-referenced with kubectl + ); + } } // ----------------------------------------------------------------------------