wait_utils/wait_strategies/wait_until_console_output.rs
1/*
2 * SPDX-License-Identifier: MIT
3 * Copyright (c) "2025" . The buildutils Authors and Contributors. All Rights Reserved.
4 */
5
6use crate::WaitStrategyError;
7use std::process::Command;
8use std::time::Duration;
9use tokio::time::Instant;
10
11/// Waits until the console output of the container with the given ID contains the
12/// specified expected output. If the expected output is not found within the given
13/// timeout, an error is returned.
14///
15/// # Arguments
16///
17/// * `container_id` - The ID of the container whose console output to check.
18/// * `expected_output` - The string to search for in the console output.
19/// * `timeout` - The timeout duration in seconds.
20///
21/// # Returns
22///
23/// Returns `Ok(())` if the expected output is found within the timeout, or an
24/// `Err(DockerError)` if the expected output is not found.
25///
26pub fn wait_until_console_output(
27 dbg: bool,
28 container_id: &str,
29 expected_output: &str,
30 timeout: &u64,
31) -> Result<(), WaitStrategyError> {
32 let start_time = Instant::now();
33 let timeout = Duration::from_secs(*timeout);
34
35 loop {
36 std::thread::sleep(Duration::from_millis(100));
37
38 if start_time.elapsed() > timeout {
39 return Err(WaitStrategyError::from(format!(
40 "[start_container]: !!Timeout!! Waited {} seconds for console output to contain {}",
41 timeout.as_secs(),
42 expected_output
43 )));
44 }
45
46 // Example: docker logs apiproxy-7777
47 // https://docs.docker.com/reference/cli/docker/container/logs/
48 let output = Command::new("docker")
49 .arg("logs")
50 .arg(container_id)
51 .output()
52 .map_err(|e| {
53 WaitStrategyError::from(format!(
54 "[start_container]: Failed to run docker logs for container: {container_id} Error: {e}"
55 ))
56 })?;
57
58 if output.status.success() {
59 if dbg {
60 println!("Service online");
61 }
62 if String::from_utf8_lossy(&output.stdout).contains(expected_output) {
63 // Apparently, when the success log message appears in Docker,
64 // some services still need more time to become ready.
65 std::thread::sleep(Duration::from_millis(250));
66 break;
67 }
68 }
69 }
70
71 Ok(())
72}