"""Readiness probe service for checking if containers are ready.""" import asyncio import logging import subprocess logger = logging.getLogger(__name__) async def execute_probe( container_id: str, command: str, timeout: int = 30, interval: int = 2, ) -> tuple[bool, list[str]]: """Execute a readiness probe command inside a container. Args: container_id: Docker container ID or name command: Command to execute inside the container timeout: Maximum total time to wait (seconds) interval: Time between retries (seconds) Returns: Tuple of (success, logs) """ logs = [] start_time = asyncio.get_event_loop().time() attempt = 0 while True: attempt += 1 elapsed = asyncio.get_event_loop().time() - start_time if elapsed >= timeout: logs.append(f"Probe timed out after {timeout}s ({attempt} attempts)") return False, logs try: logger.debug("Probe attempt %d: %s", attempt, command) # Execute command inside container result = subprocess.run( ["docker", "exec", container_id, "sh", "-c", command], capture_output=True, text=True, timeout=interval, # Each attempt has its own timeout ) if result.returncode == 0: logs.append(f"Attempt {attempt}: Success") if result.stdout: logs.append(f"Output: {result.stdout.strip()}") return True, logs else: logs.append(f"Attempt {attempt}: Failed (exit code {result.returncode})") if result.stderr: logs.append(f"Stderr: {result.stderr.strip()[:200]}") except subprocess.TimeoutExpired: logs.append(f"Attempt {attempt}: Command timed out") except Exception as exc: logs.append(f"Attempt {attempt}: Error - {exc}") # Wait before next attempt await asyncio.sleep(interval)