fix: exact container name matching in get_container_id/get_container_name
docker ps --filter name= uses substring matching, so searching for code-server-headquarter-abc123 also matches tunnel-code-server-headquarter-abc123. This caused start_instance to store the tunnel container's ID instead of the tool container's ID, breaking tunnel connectivity and all container operations. Switched both helpers to docker inspect, which does exact name matching. Quality gates: ruff clean
This commit is contained in:
@@ -2554,11 +2554,23 @@ async def recreate_tunnel_endpoint(
|
||||
|
||||
# Also probe from inside the API container directly to the target
|
||||
probe = subprocess.run(
|
||||
["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", "--max-time", "5", target_url],
|
||||
[
|
||||
"curl",
|
||||
"-s",
|
||||
"-o",
|
||||
"/dev/null",
|
||||
"-w",
|
||||
"%{http_code}",
|
||||
"--max-time",
|
||||
"5",
|
||||
target_url,
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
logger.info("Direct probe from API to %s: HTTP %s", target_url, probe.stdout.strip())
|
||||
logger.info(
|
||||
"Direct probe from API to %s: HTTP %s", target_url, probe.stdout.strip()
|
||||
)
|
||||
|
||||
instance.tunnel_id = tunnel_info["container_name"]
|
||||
instance.public_url = tunnel_info["url"]
|
||||
|
||||
@@ -179,54 +179,43 @@ def execute_compose_command(
|
||||
def get_container_id(instance_name: str) -> str | None:
|
||||
"""Get the container ID for a compose service.
|
||||
|
||||
Searches all containers including stopped/exited ones.
|
||||
Uses exact name matching via docker inspect to avoid substring collisions
|
||||
with tunnel containers (e.g. tunnel-code-server-... matching code-server-...).
|
||||
|
||||
Args:
|
||||
instance_name: The service name in compose
|
||||
instance_name: The exact container name (case-insensitive for Docker).
|
||||
|
||||
Returns:
|
||||
Container ID or None if not found
|
||||
Container ID or None if not found.
|
||||
"""
|
||||
# Docker container names are lowercase internally; normalize to ensure match
|
||||
result = subprocess.run(
|
||||
["docker", "ps", "-a", "-q", "--filter", f"name={instance_name.lower()}"],
|
||||
["docker", "inspect", "-f", "{{.Id}}", instance_name.lower()],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
|
||||
if result.returncode == 0 and result.stdout.strip():
|
||||
return result.stdout.strip().split("\n")[0]
|
||||
return result.stdout.strip()
|
||||
return None
|
||||
|
||||
|
||||
def get_container_name(instance_name: str) -> str | None:
|
||||
"""Get the full container name for a compose service.
|
||||
|
||||
Searches all containers including stopped/exited ones.
|
||||
Uses exact name matching via docker inspect to avoid substring collisions.
|
||||
|
||||
Args:
|
||||
instance_name: The service name in compose
|
||||
instance_name: The exact container name (case-insensitive for Docker).
|
||||
|
||||
Returns:
|
||||
Container name or None if not found
|
||||
Container name or None if not found.
|
||||
"""
|
||||
# Docker container names are lowercase internally; normalize to ensure match
|
||||
result = subprocess.run(
|
||||
[
|
||||
"docker",
|
||||
"ps",
|
||||
"-a",
|
||||
"--format",
|
||||
"{{.Names}}",
|
||||
"--filter",
|
||||
f"name={instance_name.lower()}",
|
||||
],
|
||||
["docker", "inspect", "-f", "{{.Name}}", instance_name.lower()],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
|
||||
if result.returncode == 0 and result.stdout.strip():
|
||||
return result.stdout.strip().split("\n")[0]
|
||||
return result.stdout.strip().lstrip("/")
|
||||
return None
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user