mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-08-29 23:08:06 +02:00
Extend repair scripts with env-file support and unit tests
- Added detect_env_file() to both sys-ctl-rpr-docker-soft and sys-ctl-rpr-docker-hard * prefer .env, fallback to .env/env * append --env-file parameter automatically - Refactored soft script to use compose_cmd() for consistent command building - Adjusted error recovery path in soft script to also respect env-file - Extended unit tests for soft script to cover env-file priority and restart commands - Added new unit tests for hard script verifying env-file priority, cwd handling, and --only filter logic Ref: https://chatgpt.com/share/68ad7b30-7510-800f-8172-56f03a2f40f5
This commit is contained in:
@@ -3,15 +3,41 @@ import sys
|
||||
import subprocess
|
||||
import argparse
|
||||
|
||||
|
||||
def detect_env_file(dir_path: str) -> str | None:
|
||||
"""
|
||||
Return the path to a Compose env file if present (.env preferred, fallback to env).
|
||||
"""
|
||||
candidates = [os.path.join(dir_path, ".env"), os.path.join(dir_path, ".env", "env")]
|
||||
for candidate in candidates:
|
||||
if os.path.isfile(candidate):
|
||||
return candidate
|
||||
return None
|
||||
|
||||
|
||||
def hard_restart_docker_services(dir_path):
|
||||
"""
|
||||
Perform a hard restart of docker-compose services in the given directory
|
||||
using docker-compose down and docker-compose up -d.
|
||||
using docker-compose down and docker-compose up -d, adding --env-file if present.
|
||||
"""
|
||||
try:
|
||||
print(f"Performing hard restart for docker-compose services in: {dir_path}")
|
||||
subprocess.run(["docker-compose", "down"], cwd=dir_path, check=True)
|
||||
subprocess.run(["docker-compose", "up", "-d"], cwd=dir_path, check=True)
|
||||
|
||||
env_file = detect_env_file(dir_path)
|
||||
base = ["docker-compose"]
|
||||
down_cmd = base.copy()
|
||||
up_cmd = base.copy()
|
||||
|
||||
if env_file:
|
||||
down_cmd += ["--env-file", env_file]
|
||||
up_cmd += ["--env-file", env_file]
|
||||
|
||||
down_cmd += ["down"]
|
||||
up_cmd += ["up", "-d"]
|
||||
|
||||
subprocess.run(down_cmd, cwd=dir_path, check=True)
|
||||
subprocess.run(up_cmd, cwd=dir_path, check=True)
|
||||
|
||||
print(f"Hard restart completed successfully in: {dir_path}")
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error during hard restart in {dir_path}: {e}")
|
||||
|
@@ -43,6 +43,32 @@ def find_docker_compose_file(directory: str) -> str | None:
|
||||
return None
|
||||
|
||||
|
||||
def detect_env_file(project_path: str) -> str | None:
|
||||
"""
|
||||
Return the path to a Compose env file if present (.env preferred, fallback to env).
|
||||
"""
|
||||
candidates = [os.path.join(project_path, ".env"), os.path.join(project_path, ".env", "env")]
|
||||
for candidate in candidates:
|
||||
if os.path.isfile(candidate):
|
||||
return candidate
|
||||
return None
|
||||
|
||||
|
||||
def compose_cmd(subcmd: str, project_path: str, project_name: str | None = None) -> str:
|
||||
"""
|
||||
Build a docker-compose command string with optional -p and --env-file if present.
|
||||
Example: compose_cmd("restart", "/opt/docker/foo", "foo")
|
||||
"""
|
||||
parts: List[str] = [f'cd "{project_path}" && docker-compose']
|
||||
if project_name:
|
||||
parts += ['-p', f'"{project_name}"']
|
||||
env_file = detect_env_file(project_path)
|
||||
if env_file:
|
||||
parts += ['--env-file', f'"{env_file}"']
|
||||
parts += subcmd.split()
|
||||
return " ".join(parts)
|
||||
|
||||
|
||||
def normalize_services_arg(raw: List[str] | None, raw_str: str | None) -> List[str]:
|
||||
"""
|
||||
Accept either:
|
||||
@@ -57,6 +83,7 @@ def normalize_services_arg(raw: List[str] | None, raw_str: str | None) -> List[s
|
||||
return [p for p in parts if p]
|
||||
return []
|
||||
|
||||
|
||||
def wait_while_manipulation_running(
|
||||
services: List[str],
|
||||
waiting_time: int = 600,
|
||||
@@ -91,6 +118,7 @@ def wait_while_manipulation_running(
|
||||
print("No blocking service is running.")
|
||||
break
|
||||
|
||||
|
||||
def main(base_directory: str, manipulation_services: List[str], timeout: int | None) -> int:
|
||||
errors = 0
|
||||
wait_while_manipulation_running(manipulation_services, waiting_time=600, timeout=timeout)
|
||||
@@ -117,13 +145,15 @@ def main(base_directory: str, manipulation_services: List[str], timeout: int | N
|
||||
print("Restarting unhealthy container in:", compose_file_path)
|
||||
project_path = os.path.dirname(compose_file_path)
|
||||
try:
|
||||
print_bash(f'cd "{project_path}" && docker-compose -p "{repo}" restart')
|
||||
# restart with optional --env-file and -p
|
||||
print_bash(compose_cmd("restart", project_path, repo))
|
||||
except Exception as e:
|
||||
if "port is already allocated" in str(e):
|
||||
print("Detected port allocation problem. Executing recovery steps...")
|
||||
print_bash(f'cd "{project_path}" && docker-compose down')
|
||||
# down (no -p needed), then engine restart, then up -d with -p
|
||||
print_bash(compose_cmd("down", project_path))
|
||||
print_bash("systemctl restart docker")
|
||||
print_bash(f'cd "{project_path}" && docker-compose -p "{repo}" up -d')
|
||||
print_bash(compose_cmd("up -d", project_path, repo))
|
||||
else:
|
||||
print("Unhandled exception during restart:", e)
|
||||
errors += 1
|
||||
|
Reference in New Issue
Block a user