1+ import os
2+ import socket
3+ import time
4+ import logging
5+ import pytest
6+ import platform
7+ import docker
8+
9+ logger = logging .getLogger (__name__ )
10+
11+ def get_docker_client ():
12+ """Connect to Docker daemon via multiple methods or fail."""
13+ connection_errors = []
14+ # Method 1: default environment
15+ try :
16+ client = docker .from_env ()
17+ client .ping ()
18+ return client
19+ except Exception as e :
20+ connection_errors .append (f"default: { e } " )
21+ # Method 2: DOCKER_HOST
22+ docker_host = os .getenv ("DOCKER_HOST" )
23+ if docker_host :
24+ try :
25+ client = docker .DockerClient (base_url = docker_host )
26+ client .ping ()
27+ return client
28+ except Exception as e :
29+ connection_errors .append (f"DOCKER_HOST: { e } " )
30+ # Method 3: common Unix sockets
31+ socket_paths = [
32+ "unix:///var/run/docker.sock" ,
33+ "unix://" + os .path .expanduser ("~/.docker/run/docker.sock" ),
34+ "unix://" + os .path .expanduser ("~/.colima/default/docker.sock" ),
35+ ]
36+ for sp in socket_paths :
37+ try :
38+ client = docker .DockerClient (base_url = sp )
39+ client .ping ()
40+ return client
41+ except Exception as e :
42+ connection_errors .append (f"{ sp } : { e } " )
43+ # All methods failed
44+ logger .error ("Docker connection errors:\n %s" , "\n " .join (connection_errors ))
45+ pytest .fail ("Could not connect to Docker. Make sure Docker daemon is running." )
46+
47+ def start_container (image : str , ** kwargs ):
48+ """Pull and run a Docker container with given parameters."""
49+ client = get_docker_client ()
50+ # Pull image
51+ client .images .pull (image )
52+ # Run container
53+ container = client .containers .run (image = image , ** kwargs )
54+ return container
55+
56+ def stop_container (container ):
57+ """Stop the given Docker container."""
58+ try :
59+ container .stop (timeout = 1 )
60+ except Exception :
61+ logger .warning ("Error stopping container %s" , container )
62+
63+ def wait_for_port (host : str , port : int , timeout : int = 30 ):
64+ """Wait until given host:port is accepting connections or fail."""
65+ for _ in range (timeout ):
66+ with socket .socket (socket .AF_INET , socket .SOCK_STREAM ) as sock :
67+ sock .settimeout (1 )
68+ try :
69+ if sock .connect_ex ((host , port )) == 0 :
70+ return
71+ except Exception :
72+ pass
73+ time .sleep (1 )
74+ pytest .fail (f"Port { host } :{ port } not ready after { timeout } s" )
75+
76+ def start_ydb_container ():
77+ """Start a YDB Docker container for integration tests."""
78+ # YDB image and ports configuration
79+ image = "ydbplatform/local-ydb:latest"
80+ env = {
81+ "GRPC_TLS_PORT" : "2135" ,
82+ "GRPC_PORT" : "2136" ,
83+ "MON_PORT" : "8765" ,
84+ "YDB_KAFKA_PROXY_PORT" : "9092" ,
85+ "YDB_USE_IN_MEMORY_PDISKS" : "1" ,
86+ }
87+ ports = {"2135/tcp" : 2135 , "2136/tcp" : 2136 , "8765/tcp" : 8765 , "9092/tcp" : 9092 }
88+ container = start_container (
89+ image = image ,
90+ detach = True ,
91+ remove = True ,
92+ hostname = "localhost" ,
93+ platform = "linux/amd64" ,
94+ environment = env ,
95+ ports = ports ,
96+ )
97+ return container
98+
99+ def start_ollama_container ():
100+ """Start an Ollama Docker container for integration tests by pulling `llama2` and serving it."""
101+ image = "ollama/ollama:latest"
102+ client = get_docker_client ()
103+ # Pull the Ollama image for linux/amd64
104+ client .images .pull (image , platform = "linux/amd64" )
105+ # Combine model pull and serve in one container to ensure the model is available
106+ shell_cmd = "ollama pull llama2 && exec ollama serve --http-port 11434 --http-address 0.0.0.0"
107+ container = client .containers .run (
108+ image = image ,
109+ command = ["sh" , "-c" , shell_cmd ],
110+ detach = True ,
111+ remove = True ,
112+ ports = {"11434/tcp" : 11434 },
113+ platform = "linux/amd64" ,
114+ )
115+ return container
0 commit comments