Start streaming container events filtered by label. Events are sent to the returned receiver. The background task runs until the receiver is dropped.
(
&self,
label_filter: &str,
)
| 631 | /// Events are sent to the returned receiver. The background task runs |
| 632 | /// until the receiver is dropped. |
| 633 | pub async fn events_stream( |
| 634 | &self, |
| 635 | label_filter: &str, |
| 636 | ) -> Result<mpsc::Receiver<Result<PodmanEvent, PodmanApiError>>, PodmanApiError> { |
| 637 | let filters = serde_json::json!({ |
| 638 | "label": [label_filter], |
| 639 | "type": ["container"], |
| 640 | }); |
| 641 | let encoded = url_encode(&filters.to_string()); |
| 642 | let path = |
| 643 | format!("http://localhost/{API_VERSION}/libpod/events?stream=true&filters={encoded}"); |
| 644 | |
| 645 | let mut sender = self.connect().await?; |
| 646 | |
| 647 | let req = Request::builder() |
| 648 | .method(hyper::Method::GET) |
| 649 | .uri(&path) |
| 650 | .header("Host", "localhost") |
| 651 | .body(Full::new(Bytes::new())) |
| 652 | .map_err(|e| PodmanApiError::Connection(e.to_string()))?; |
| 653 | |
| 654 | let response = tokio::time::timeout(API_TIMEOUT, sender.send_request(req)) |
| 655 | .await |
| 656 | .map_err(|_| PodmanApiError::Timeout(API_TIMEOUT))? |
| 657 | .map_err(|e| PodmanApiError::Connection(e.to_string()))?; |
| 658 | |
| 659 | if !response.status().is_success() { |
| 660 | return Err(PodmanApiError::Api { |
| 661 | status: response.status().as_u16(), |
| 662 | message: "events stream request failed".to_string(), |
| 663 | }); |
| 664 | } |
| 665 | |
| 666 | let (tx, rx) = mpsc::channel(256); |
| 667 | let body = response.into_body(); |
| 668 | |
| 669 | tokio::spawn(async move { |
| 670 | let mut buffer = Vec::new(); |
| 671 | let mut body = body; |
| 672 | |
| 673 | loop { |
| 674 | use hyper::body::Body; |
| 675 | |
| 676 | let frame = |
| 677 | match std::future::poll_fn(|cx| Pin::new(&mut body).poll_frame(cx)).await { |
| 678 | Some(Ok(frame)) => frame, |
| 679 | Some(Err(e)) => { |
| 680 | let _ = tx |
| 681 | .send(Err(PodmanApiError::Connection(e.to_string()))) |
| 682 | .await; |
| 683 | break; |
| 684 | } |
| 685 | None => break, |
| 686 | }; |
| 687 | |
| 688 | if let Some(data) = frame.data_ref() { |
| 689 | buffer.extend_from_slice(data); |
| 690 | } |
no test coverage detected