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}