Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
606 changes: 606 additions & 0 deletions COMPREHENSIVE_BUG_FIX_REPORT_2025_11_18.md

Large diffs are not rendered by default.

13 changes: 2 additions & 11 deletions blastdock/cli/config_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,13 @@
import click
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich.syntax import Syntax
from rich.tree import Tree

from ..config import (
get_config_manager,
ConfigManager,
BlastDockConfig,
ProfileManager,
ConfigBackup,
EnvironmentManager,
)
from ..exceptions import ConfigurationError
from ..utils.logging import get_logger

logger = get_logger(__name__)
Expand All @@ -32,7 +26,6 @@
@click.group(name="config")
def config_group():
"""Configuration management commands"""
pass


@config_group.command("show")
Expand Down Expand Up @@ -156,7 +149,7 @@ def reset_config(profile: str, section: Optional[str], confirm: bool):
console.print(f"[green]Reset section '{section}' to defaults[/green]")
else:
config_manager.reset_to_defaults()
console.print(f"[green]Reset configuration to defaults[/green]")
console.print("[green]Reset configuration to defaults[/green]")

except Exception as e:
console.print(f"[red]Error resetting configuration: {e}[/red]")
Expand All @@ -180,7 +173,7 @@ def validate_config(profile: str, section: Optional[str], suggestions: bool):
issues = config_manager.validate_current_config()

if not issues:
console.print(f"[green]βœ“ Configuration is valid[/green]")
console.print("[green]βœ“ Configuration is valid[/green]")
else:
console.print(f"[red]Found {len(issues)} validation issues:[/red]")
for i, issue in enumerate(issues, 1):
Expand Down Expand Up @@ -260,7 +253,6 @@ def import_config(import_path: str, profile: str, merge: bool, confirm: bool):
@config_group.group("profile")
def profile_group():
"""Configuration profile management"""
pass


@profile_group.command("list")
Expand Down Expand Up @@ -368,7 +360,6 @@ def copy_profile(source_profile: str, target_profile: str, description: Optional
@config_group.group("backup")
def backup_group():
"""Configuration backup management"""
pass


@backup_group.command("create")
Expand Down
19 changes: 7 additions & 12 deletions blastdock/cli/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,25 @@
Handles project deployment using templates
"""

import os
import sys
import time
import tempfile
import subprocess
from pathlib import Path
from typing import Dict, Any, Optional, List
from typing import Dict, Any

import click
import yaml
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, TextColumn

from ..core.config import get_config_manager
from ..performance.template_registry import get_template_registry
from ..performance.traefik_enhancer import get_traefik_enhancer, SecurityLevel
from ..performance.traefik_enhancer import get_traefik_enhancer
from ..utils.docker_utils import EnhancedDockerClient
from ..utils.template_validator import TemplateValidator
from ..utils.logging import get_logger
from ..exceptions import DeploymentError, TemplateNotFoundError
from ..models.project import ProjectConfig

logger = get_logger(__name__)
console = Console()
Expand Down Expand Up @@ -442,7 +438,6 @@ def _show_deployment_info(self, project_name: str, template_data: Dict[str, Any]
@click.group(name="deploy")
def deploy_group():
"""Deployment management commands"""
pass


@deploy_group.command("create")
Expand Down Expand Up @@ -618,7 +613,7 @@ def deployment_status(project_name):

@deploy_group.command("remove")
@click.argument("project_name")
@click.option("--force", "-f", is_flag=True, help="Force removal without confirmation")
@click.option("--force", "-", is_flag=True, help="Force removal without confirmation")
@click.option("--keep-volumes", is_flag=True, help="Keep data volumes")
def remove_deployment(project_name, force, keep_volumes):
"""Remove a deployed project"""
Expand Down Expand Up @@ -664,19 +659,19 @@ def remove_deployment(project_name, force, keep_volumes):
import shutil

shutil.rmtree(project_dir)
console.print(f"[green]βœ“ Project files removed[/green]")
console.print("[green]βœ“ Project files removed[/green]")
else:
console.print(f"[red]Failed to remove project: {result.stderr}[/red]")
else:
console.print(f"[yellow]Project directory not found[/yellow]")
console.print("[yellow]Project directory not found[/yellow]")

except Exception as e:
console.print(f"[red]Error removing project: {e}[/red]")


@deploy_group.command("logs")
@click.argument("project_name")
@click.option("--follow", "-f", is_flag=True, help="Follow log output")
@click.option("--follow", "-", is_flag=True, help="Follow log output")
@click.option("--tail", type=int, default=50, help="Number of lines to show")
@click.option("--service", help="Show logs for specific service")
def deployment_logs(project_name, follow, tail, service):
Expand All @@ -702,7 +697,7 @@ def deployment_logs(project_name, follow, tail, service):
cmd = ["docker-compose", "-p", project_name, "logs"]

if follow:
cmd.append("-f")
cmd.append("-")

if tail:
cmd.extend(["--tail", str(tail)])
Expand Down
4 changes: 1 addition & 3 deletions blastdock/cli/diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from rich.progress import Progress, SpinnerColumn, TextColumn

from ..utils.error_diagnostics import get_diagnostics
from ..utils.error_handler import EnhancedErrorHandler


console = Console()
Expand All @@ -22,7 +21,6 @@
@click.group()
def diagnostics():
"""System diagnostics and error reporting commands"""
pass


@diagnostics.command()
Expand Down Expand Up @@ -365,7 +363,7 @@ def _display_detailed_error(error):
f"[bold]Time:[/bold] {error.timestamp.strftime('%Y-%m-%d %H:%M:%S')}"
)
error_content.append("")
error_content.append(f"[bold]Message:[/bold]")
error_content.append("[bold]Message:[/bold]")
error_content.append(f" {error.error_message}")

if error.project_name:
Expand Down
17 changes: 8 additions & 9 deletions blastdock/cli/marketplace.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""

import sys
from typing import Optional, List
from typing import Optional

import click
from rich.console import Console
Expand All @@ -13,7 +13,7 @@
from rich.columns import Columns
from rich import box

from ..marketplace import TemplateMarketplace, TemplateRepository, TemplateInstaller
from ..marketplace import TemplateMarketplace, TemplateInstaller
from ..marketplace.marketplace import TemplateCategory
from ..utils.logging import get_logger

Expand All @@ -24,7 +24,6 @@
@click.group(name="marketplace")
def marketplace():
"""Template marketplace commands"""
pass


@marketplace.command("search")
Expand Down Expand Up @@ -127,7 +126,7 @@ def template_info(template_id: str):
return

# Create info panel
info_content = f"""[bold]{template.display_name}[/bold]
info_content = """[bold]{template.display_name}[/bold]
{template.description}

[bold]Details:[/bold]
Expand Down Expand Up @@ -187,7 +186,7 @@ def show_featured(limit: int):
columns = []
for i, template in enumerate(featured, 1):
# Create template card
card_content = f"""[bold green]{template.display_name}[/bold green]
card_content = """[bold green]{template.display_name}[/bold green]
{template.description[:80]}...

Rating: {"⭐" * int(template.rating)} {template.rating:.1f}
Expand Down Expand Up @@ -272,7 +271,7 @@ def show_categories():
@click.argument("template_id")
@click.option("--version", "-v", default="latest", help="Template version to install")
@click.option(
"--force", "-f", is_flag=True, help="Force reinstall if already installed"
"--force", "-", is_flag=True, help="Force reinstall if already installed"
)
def install_template(template_id: str, version: str, force: bool):
"""Install a template from the marketplace"""
Expand All @@ -295,7 +294,7 @@ def install_template(template_id: str, version: str, force: bool):
console.print("[green]βœ… Traefik compatible[/green]")

if result.get("additional_files"):
console.print(f"\nAdditional files installed:")
console.print("\nAdditional files installed:")
for file_path in result["additional_files"]:
console.print(f" β€’ {file_path}")

Expand All @@ -304,7 +303,7 @@ def install_template(template_id: str, version: str, force: bool):
f"--template {result['template_name']}[/dim]"
)
else:
console.print(f"\n[bold red]❌ Installation failed[/bold red]")
console.print("\n[bold red]❌ Installation failed[/bold red]")
console.print(f"Error: {result['error']}")

if "validation_errors" in result:
Expand Down Expand Up @@ -386,7 +385,7 @@ def list_templates(installed: bool):
)

console.print(
f"\n[dim]Use 'blastdock marketplace search' for detailed search[/dim]"
"\n[dim]Use 'blastdock marketplace search' for detailed search[/dim]"
)

except Exception as e:
Expand Down
34 changes: 16 additions & 18 deletions blastdock/cli/monitoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,14 @@
get_log_analyzer,
)
from ..monitoring.web_dashboard import WebDashboard
from ..monitoring.health_checker import HealthStatus, ServiceHealthConfig
from ..monitoring.alert_manager import AlertRule, AlertSeverity, NotificationChannel
from ..monitoring.health_checker import HealthStatus

console = Console()


@click.group()
def monitoring():
"""Advanced monitoring and health check commands"""
pass


@monitoring.command()
Expand Down Expand Up @@ -88,7 +86,7 @@ def health(project_name, output_format, detailed):
# Service details
services = health_data.get("services", {})
if services:
console.print(f"\n[bold]Service Health Details:[/bold]")
console.print("\n[bold]Service Health Details:[/bold]")

table = Table(show_header=True, header_style="bold magenta")
table.add_column("Service", style="cyan")
Expand Down Expand Up @@ -122,7 +120,7 @@ def health(project_name, output_format, detailed):

# Detailed information
if detailed:
console.print(f"\n[bold]Detailed Service Information:[/bold]")
console.print("\n[bold]Detailed Service Information:[/bold]")
for service_name, service_info in services.items():
details = service_info.get("details", {})
suggestions = service_info.get("suggestions", [])
Expand Down Expand Up @@ -256,7 +254,7 @@ def metrics(project_name, window, output_format):
# Container-specific metrics
containers = dashboard_data.get("containers", {})
if containers:
console.print(f"\n[bold]Container Metrics:[/bold]")
console.print("\n[bold]Container Metrics:[/bold]")

container_table = Table(show_header=True, header_style="bold magenta")
container_table.add_column("Container", style="cyan")
Expand All @@ -283,7 +281,7 @@ def metrics(project_name, window, output_format):

console.print(container_table)

console.print(f"\n[green]βœ… Metrics retrieved successfully[/green]")
console.print("\n[green]βœ… Metrics retrieved successfully[/green]")

except Exception as e:
console.print(f"[red]❌ Metrics retrieval failed: {e}[/red]")
Expand All @@ -304,7 +302,7 @@ def alerts(output_format, active_only):
alert_manager = get_alert_manager()

try:
console.print(f"\n[bold blue]🚨 Alert Status[/bold blue]\n")
console.print("\n[bold blue]🚨 Alert Status[/bold blue]\n")

# Get alerts
if active_only:
Expand Down Expand Up @@ -456,7 +454,7 @@ def logs(project_name, tail, window, output_format):

# Patterns found
if analysis_result.patterns_found:
console.print(f"\n[bold]Patterns Detected:[/bold]")
console.print("\n[bold]Patterns Detected:[/bold]")

patterns_table = Table(show_header=True, header_style="bold magenta")
patterns_table.add_column("Pattern", style="cyan")
Expand All @@ -481,7 +479,7 @@ def logs(project_name, tail, window, output_format):

# Top errors
if analysis_result.top_errors:
console.print(f"\n[bold]Top Errors:[/bold]")
console.print("\n[bold]Top Errors:[/bold]")

for i, error in enumerate(analysis_result.top_errors[:5], 1):
error_text = Text()
Expand All @@ -495,13 +493,13 @@ def logs(project_name, tail, window, output_format):

# Recommendations
if analysis_result.recommendations:
console.print(f"\n[bold yellow]πŸ”§ Recommendations:[/bold yellow]")
console.print("\n[bold yellow]πŸ”§ Recommendations:[/bold yellow]")
for i, rec in enumerate(analysis_result.recommendations, 1):
console.print(f" {i}. {rec}", style="yellow")

# Timeline (if table format)
if output_format == "table" and analysis_result.timeline:
console.print(f"\n[bold]Timeline (Last 24h):[/bold]")
console.print("\n[bold]Timeline (Last 24h):[/bold]")

timeline_table = Table(show_header=True, header_style="bold magenta")
timeline_table.add_column("Hour", style="cyan")
Expand All @@ -520,7 +518,7 @@ def logs(project_name, tail, window, output_format):

console.print(timeline_table)

console.print(f"\n[green]βœ… Log analysis completed[/green]")
console.print("\n[green]βœ… Log analysis completed[/green]")

except Exception as e:
console.print(f"[red]❌ Log analysis failed: {e}[/red]")
Expand Down Expand Up @@ -565,7 +563,7 @@ def background(start, stop, status, interval):
try:
if start:
console.print(
f"\n[bold blue]πŸš€ Starting background monitoring[/bold blue]\n"
"\n[bold blue]πŸš€ Starting background monitoring[/bold blue]\n"
)

# Start all monitoring services
Expand All @@ -582,18 +580,18 @@ def background(start, stop, status, interval):

elif stop:
console.print(
f"\n[bold blue]⏹️ Stopping background monitoring[/bold blue]\n"
"\n[bold blue]⏹️ Stopping background monitoring[/bold blue]\n"
)

# Stop all monitoring services
health_checker.stop_background_monitoring()
metrics_collector.stop_collection()
alert_manager.stop_evaluation()

console.print(f"[green]βœ… Background monitoring stopped[/green]")
console.print("[green]βœ… Background monitoring stopped[/green]")

elif status:
console.print(f"\n[bold blue]πŸ“Š Background Monitoring Status[/bold blue]\n")
console.print("\n[bold blue]πŸ“Š Background Monitoring Status[/bold blue]\n")

# Get status from each service
health_stats = health_checker.get_health_statistics()
Expand Down Expand Up @@ -673,7 +671,7 @@ def export(project_name, output):
@click.pass_context
def web(ctx, host, port, browser):
"""Launch web-based monitoring dashboard"""
console.print(f"\n[bold blue]🌐 Starting BlastDock Web Dashboard...[/bold blue]\n")
console.print("\n[bold blue]🌐 Starting BlastDock Web Dashboard...[/bold blue]\n")
console.print(f" Host: {host}")
console.print(f" Port: {port}")

Expand Down
Loading
Loading