mirror of
https://github.com/kossakovsky/n8n-install.git
synced 2026-03-07 14:23:08 +00:00
Refactor service management in start_services.py and scripts
- Updated the is_supabase_enabled function to read COMPOSE_PROFILES from the .env file instead of os.environ, improving clarity. - Simplified the run_command function by removing the unused env parameter. - Refined the stop_existing_containers function to streamline the shutdown process for the 'localai' project, conditionally including the Supabase compose file. - Enhanced logging for better user feedback during service management operations. - Adjusted the scripts for generating secrets and applying updates to improve clarity and functionality.
This commit is contained in:
@@ -187,19 +187,8 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
# Determine N8N_WORKFLOWS_IMPORTED_EVER based on RUN_N8N_IMPORT and existing values
|
||||
N8N_WORKFLOWS_IMPORTED_EVER_VALUE="false" # Default to false
|
||||
if [[ -n "${existing_env_vars[N8N_WORKFLOWS_IMPORTED_EVER]}" ]]; then
|
||||
N8N_WORKFLOWS_IMPORTED_EVER_VALUE="${existing_env_vars[N8N_WORKFLOWS_IMPORTED_EVER]}"
|
||||
log_info "Using existing N8N_WORKFLOWS_IMPORTED_EVER value from .env: $N8N_WORKFLOWS_IMPORTED_EVER_VALUE"
|
||||
else
|
||||
# If N8N_WORKFLOWS_IMPORTED_EVER is not in .env, set it based on RUN_N8N_IMPORT choice
|
||||
if [[ "$RUN_N8N_IMPORT" == "true" ]]; then
|
||||
N8N_WORKFLOWS_IMPORTED_EVER_VALUE="true"
|
||||
fi
|
||||
# No else needed, it's already defaulted to false
|
||||
log_info "Setting N8N_WORKFLOWS_IMPORTED_EVER based on current import choice (or default): $N8N_WORKFLOWS_IMPORTED_EVER_VALUE"
|
||||
fi
|
||||
# Set N8N_WORKFLOWS_IMPORTED_EVER_VALUE based on RUN_N8N_IMPORT
|
||||
N8N_WORKFLOWS_IMPORTED_EVER_VALUE="$RUN_N8N_IMPORT"
|
||||
|
||||
# Prompt for number of n8n workers
|
||||
echo "" # Add a newline for better formatting
|
||||
|
||||
@@ -28,15 +28,35 @@ fi
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# Stop all services
|
||||
log_info "Stopping all services..."
|
||||
$COMPOSE_CMD down || {
|
||||
log_warning "Failed to stop containers with 'docker compose down'. Continuing with update anyway...";
|
||||
}
|
||||
# Stop all services for project 'localai'
|
||||
log_info "Stopping all services for project 'localai'..."
|
||||
PROJECT_CONTAINERS=$(docker ps -a -q --filter "label=com.docker.compose.project=localai")
|
||||
if [ -n "$PROJECT_CONTAINERS" ]; then
|
||||
docker stop $PROJECT_CONTAINERS || log_warning "Some containers for project 'localai' failed to stop."
|
||||
docker rm $PROJECT_CONTAINERS || log_warning "Some containers for project 'localai' failed to be removed."
|
||||
else
|
||||
log_info "No containers found for project 'localai' to stop/remove."
|
||||
fi
|
||||
|
||||
# Pull latest versions of all containers
|
||||
log_info "Pulling latest versions of all containers..."
|
||||
$COMPOSE_CMD pull || { log_error "Failed to pull Docker images. Check network connection and Docker Hub status."; exit 1; }
|
||||
# Pull latest versions of all potentially needed containers
|
||||
log_info "Pulling latest versions of all potentially needed containers..."
|
||||
COMPOSE_FILES_FOR_PULL=("-f" "$PROJECT_ROOT/docker-compose.yml")
|
||||
SUPABASE_DOCKER_DIR="$PROJECT_ROOT/supabase/docker"
|
||||
SUPABASE_COMPOSE_FILE_PATH="$SUPABASE_DOCKER_DIR/docker-compose.yml"
|
||||
|
||||
# Check if Supabase directory and its docker-compose.yml exist
|
||||
if [ -d "$SUPABASE_DOCKER_DIR" ] && [ -f "$SUPABASE_COMPOSE_FILE_PATH" ]; then
|
||||
COMPOSE_FILES_FOR_PULL+=("-f" "$SUPABASE_COMPOSE_FILE_PATH")
|
||||
log_info "Supabase docker-compose.yml found, will be included in pull."
|
||||
else
|
||||
log_info "Supabase docker-compose.yml not found or directory does not exist, skipping for pull."
|
||||
fi
|
||||
|
||||
# Use the project name "localai" for consistency
|
||||
$COMPOSE_CMD -p "localai" "${COMPOSE_FILES_FOR_PULL[@]}" pull --ignore-buildable || {
|
||||
log_error "Failed to pull Docker images. Check network connection and Docker Hub status."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# --- Run Service Selection Wizard ---
|
||||
log_info "Running Service Selection Wizard to update service choices..."
|
||||
|
||||
@@ -14,18 +14,18 @@ import time
|
||||
import argparse
|
||||
import platform
|
||||
import sys
|
||||
from dotenv import dotenv_values, load_dotenv
|
||||
from dotenv import dotenv_values
|
||||
|
||||
def is_supabase_enabled():
|
||||
"""Check if 'supabase' is in COMPOSE_PROFILES in the environment."""
|
||||
# Relies on load_dotenv() being called in main()
|
||||
compose_profiles = os.environ.get("COMPOSE_PROFILES", "")
|
||||
"""Check if 'supabase' is in COMPOSE_PROFILES in .env file."""
|
||||
env_values = dotenv_values(".env")
|
||||
compose_profiles = env_values.get("COMPOSE_PROFILES", "")
|
||||
return "supabase" in compose_profiles.split(',')
|
||||
|
||||
def run_command(cmd, cwd=None, env=None):
|
||||
def run_command(cmd, cwd=None):
|
||||
"""Run a shell command and print it."""
|
||||
print("Running:", " ".join(cmd))
|
||||
subprocess.run(cmd, cwd=cwd, check=True, env=env)
|
||||
subprocess.run(cmd, cwd=cwd, check=True)
|
||||
|
||||
def clone_supabase_repo():
|
||||
"""Clone the Supabase repository using sparse checkout if not already present."""
|
||||
@@ -60,92 +60,17 @@ def prepare_supabase_env():
|
||||
shutil.copyfile(env_example_path, env_path)
|
||||
|
||||
def stop_existing_containers():
|
||||
"""Stop and remove all existing containers for our unified project ('localai')."""
|
||||
print("Stopping and removing all existing containers for the unified project 'localai'...")
|
||||
|
||||
compose_files_args = ["-f", "docker-compose.yml"]
|
||||
|
||||
# Only include Supabase compose file if Supabase is enabled
|
||||
if is_supabase_enabled():
|
||||
supabase_docker_dir = os.path.join("supabase", "docker")
|
||||
supabase_compose_file = os.path.join(supabase_docker_dir, "docker-compose.yml")
|
||||
if os.path.exists(supabase_compose_file):
|
||||
print(f"Supabase is enabled and compose file found at {supabase_compose_file}, adding to commands.")
|
||||
compose_files_args.extend(["-f", supabase_compose_file])
|
||||
else:
|
||||
# This case should ideally not happen if Supabase is enabled and cloned properly
|
||||
print(f"Supabase is enabled but its compose file was not found at {supabase_compose_file}.")
|
||||
else:
|
||||
# If Supabase is not enabled, we don't include its compose file.
|
||||
# Lingering Supabase containers will be handled by force_stop_lingering_containers()
|
||||
print("Supabase is not enabled, its compose file will not be used for stop/rm Docker Compose commands.")
|
||||
# We also check if the Supabase compose file path exists to provide more context,
|
||||
# as it might exist from a previous run where Supabase was enabled.
|
||||
supabase_compose_file_if_exists = os.path.join("supabase", "docker", "docker-compose.yml")
|
||||
if os.path.exists(supabase_compose_file_if_exists):
|
||||
print(f"Note: Supabase compose file exists at {supabase_compose_file_if_exists} but is not being used as Supabase is disabled.")
|
||||
|
||||
base_cmd_prefix = ["docker", "compose", "-p", "localai"] + compose_files_args
|
||||
|
||||
# Prepare an environment for stop/rm that has COMPOSE_PROFILES explicitly removed
|
||||
# to ensure these commands affect all services in the specified compose files.
|
||||
env_for_stop_rm = os.environ.copy()
|
||||
env_for_stop_rm.pop("COMPOSE_PROFILES", None) # Remove COMPOSE_PROFILES if it exists
|
||||
|
||||
# Explicitly stop all services defined in the compose files
|
||||
stop_cmd = base_cmd_prefix + ["stop"]
|
||||
print("Attempting to stop all services...")
|
||||
run_command(stop_cmd, env=env_for_stop_rm)
|
||||
|
||||
# Explicitly remove all stopped containers
|
||||
rm_cmd = base_cmd_prefix + ["rm", "-f"]
|
||||
print("Attempting to remove all stopped services...")
|
||||
run_command(rm_cmd, env=env_for_stop_rm)
|
||||
|
||||
# Force stop containers that might be running outside of compose management
|
||||
force_stop_lingering_containers()
|
||||
|
||||
def force_stop_lingering_containers():
|
||||
"""Force stop and remove specific containers that might be lingering."""
|
||||
print("Force stopping and removing any lingering service containers...")
|
||||
|
||||
# Define service container patterns that we want to ensure are stopped
|
||||
# These are containers that might be running but not managed by the current compose setup
|
||||
container_patterns = [
|
||||
"qdrant", "langfuse", "grafana", "crawl4ai", "letta", "clickhouse",
|
||||
"node-exporter", "minio", "cadvisor", "open-webui", "ollama",
|
||||
"prometheus", "searxng", "supabase-", "localai-langfuse-",
|
||||
"localai-clickhouse-", "localai-minio-", "realtime-dev.supabase-"
|
||||
"""Stop and remove existing containers for our unified project ('localai')."""
|
||||
print("Stopping and removing existing containers for the unified project 'localai'...")
|
||||
cmd = [
|
||||
"docker", "compose",
|
||||
"-p", "localai",
|
||||
"-f", "docker-compose.yml"
|
||||
]
|
||||
|
||||
try:
|
||||
# Get list of all running containers
|
||||
result = subprocess.run(
|
||||
["docker", "ps", "--format", "{{.Names}}"],
|
||||
capture_output=True, text=True, check=True
|
||||
)
|
||||
running_containers = result.stdout.strip().split('\n')
|
||||
|
||||
containers_to_stop = []
|
||||
for container in running_containers:
|
||||
if container and any(pattern in container for pattern in container_patterns):
|
||||
containers_to_stop.append(container)
|
||||
|
||||
if containers_to_stop:
|
||||
print(f"Found lingering containers: {', '.join(containers_to_stop)}")
|
||||
# Stop containers
|
||||
subprocess.run(["docker", "stop"] + containers_to_stop, check=True)
|
||||
print("Stopped lingering containers.")
|
||||
# Remove containers
|
||||
subprocess.run(["docker", "rm", "-f"] + containers_to_stop, check=True)
|
||||
print("Removed lingering containers.")
|
||||
else:
|
||||
print("No lingering containers found.")
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error during force stop: {e}")
|
||||
except Exception as e:
|
||||
print(f"Unexpected error during force stop: {e}")
|
||||
if is_supabase_enabled():
|
||||
cmd.extend(["-f", "supabase/docker/docker-compose.yml"])
|
||||
cmd.append("down")
|
||||
run_command(cmd)
|
||||
|
||||
def start_supabase():
|
||||
"""Start the Supabase services (using its compose file)."""
|
||||
@@ -153,18 +78,16 @@ def start_supabase():
|
||||
print("Supabase is not enabled, skipping start.")
|
||||
return
|
||||
print("Starting Supabase services...")
|
||||
# Pass os.environ.copy() to ensure it uses the correct COMPOSE_PROFILES
|
||||
run_command([
|
||||
"docker", "compose", "-p", "localai", "-f", "supabase/docker/docker-compose.yml", "up", "-d"
|
||||
], env=os.environ.copy())
|
||||
])
|
||||
|
||||
def start_local_ai():
|
||||
"""Start the local AI services (using its compose file)."""
|
||||
print("Starting local AI services...")
|
||||
cmd = ["docker", "compose", "-p", "localai"]
|
||||
cmd.extend(["-f", "docker-compose.yml", "up", "-d"])
|
||||
# Pass os.environ.copy() to ensure it uses the correct COMPOSE_PROFILES
|
||||
run_command(cmd, env=os.environ.copy())
|
||||
run_command(cmd)
|
||||
|
||||
def generate_searxng_secret_key():
|
||||
"""Generate a secret key for SearXNG based on the current platform."""
|
||||
@@ -307,8 +230,6 @@ def check_and_fix_docker_compose_for_searxng():
|
||||
print(f"Error checking/modifying docker-compose.yml for SearXNG: {e}")
|
||||
|
||||
def main():
|
||||
load_dotenv(".env") # Load/Reload .env into os.environ
|
||||
|
||||
if is_supabase_enabled():
|
||||
clone_supabase_repo()
|
||||
prepare_supabase_env()
|
||||
|
||||
Reference in New Issue
Block a user