torrust_tracker_deployer_lib/bootstrap/app.rs
1//! Main Application Bootstrap
2//!
3//! This module provides a thin bootstrap layer for the Torrust Tracker Deployer CLI.
4//! It handles application initialization, logging setup, and command dispatch while
5//! delegating all CLI parsing and business logic to the presentation layer.
6//!
7//! ## Responsibilities
8//!
9//! - **Application Lifecycle**: Initialize and shutdown the application
10//! - **Logging Setup**: Configure logging based on CLI arguments
11//! - **Command Dispatch**: Route commands to the presentation layer for execution
12//! - **Exit Handling**: Manage application exit codes and cleanup
13//!
14//! ## Design Principles
15//!
16//! - **Thin Layer**: Minimal logic, maximum delegation to appropriate layers
17//! - **Single Responsibility**: Focus only on application bootstrap concerns
18//! - **Clean Separation**: No CLI parsing or business logic in this module
19
20use std::sync::Arc;
21
22use clap::Parser;
23use tracing::info;
24
25use crate::bootstrap;
26use crate::presentation::cli::dispatch::route_command;
27use crate::presentation::cli::dispatch::ExecutionContext;
28use crate::presentation::cli::error::handle_error;
29use crate::presentation::cli::Cli;
30
31/// Main application entry point
32///
33/// This function serves as the application bootstrap, handling:
34/// 1. CLI argument parsing (delegated to presentation layer)
35/// 2. Logging initialization using `LoggingConfig`
36/// 3. Service container creation for dependency injection
37/// 4. Command execution (delegated to presentation layer)
38/// 5. Error handling and exit code management
39///
40/// # Panics
41///
42/// This function will panic if:
43/// - Log directory cannot be created (filesystem permissions issue)
44/// - Logging initialization fails (usually means it was already initialized)
45///
46/// Both panics are intentional as logging is critical for observability.
47pub async fn run() {
48 let cli = Cli::parse();
49
50 let logging_config = cli.global.logging_config();
51
52 bootstrap::logging::init_subscriber(logging_config);
53
54 info!(
55 app = "torrust-tracker-deployer",
56 version = env!("CARGO_PKG_VERSION"),
57 log_dir = %cli.global.log_dir.display(),
58 log_file_format = ?cli.global.log_file_format,
59 log_stderr_format = ?cli.global.log_stderr_format,
60 log_output = ?cli.global.log_output,
61 "Application started"
62 );
63
64 // Initialize service container for dependency injection
65 let container = Arc::new(bootstrap::Container::new(
66 cli.global.verbosity_level(),
67 &cli.global.working_dir,
68 ));
69 let context = ExecutionContext::new(container, cli.global.clone());
70
71 match cli.command {
72 Some(command) => {
73 if let Err(e) = route_command(command, &cli.global.working_dir, &context).await {
74 handle_error(&e, &context.user_output());
75 std::process::exit(1);
76 }
77 }
78 None => {
79 bootstrap::help::display_getting_started();
80 }
81 }
82
83 info!("Application finished");
84}