Skip to main content

torrust_tracker_deployer_lib/application/command_handlers/create/
mod.rs

1//! Create Command Module
2//!
3//! This module implements the delivery-agnostic `CreateCommandHandler` for orchestrating
4//! environment creation business logic. The command is synchronous and follows
5//! existing patterns from `ProvisionCommandHandler`.
6//!
7//! ## Architecture
8//!
9//! The `CreateCommandHandler` implements the Command Pattern and uses Dependency Injection
10//! to interact with infrastructure services through interfaces:
11//!
12//! - **Repository Pattern**: Persists environment state via `EnvironmentRepository`
13//! - **Clock Abstraction**: Provides deterministic time for testing via `Clock` trait
14//! - **Domain-Driven Design**: Uses domain objects from `domain::environment`
15//!
16//! ## Design Principles
17//!
18//! - **Delivery-Agnostic**: Works with CLI, REST API, or any delivery mechanism
19//! - **Synchronous**: Follows existing patterns (no async/await)
20//! - **Repository Responsibility**: Lets repository handle directory creation atomically
21//! - **Explicit Errors**: All errors implement `.help()` with actionable guidance
22//!
23//! ## Usage Example
24//!
25//! ```rust,no_run
26//! use std::sync::Arc;
27//! use torrust_tracker_deployer_lib::application::command_handlers::create::CreateCommandHandler;
28//! use torrust_tracker_deployer_lib::application::command_handlers::create::config::{
29//!     EnvironmentCreationConfig, EnvironmentSection, LxdProviderSection, ProviderSection,
30//!     SshCredentialsConfig,
31//! };
32//! use torrust_tracker_deployer_lib::application::command_handlers::create::config::tracker::TrackerSection;
33//! use torrust_tracker_deployer_lib::infrastructure::persistence::file_repository_factory::FileRepositoryFactory;
34//! use torrust_tracker_deployer_lib::shared::{SystemClock, Clock};
35//!
36//! // Setup dependencies
37//! let file_repository_factory = FileRepositoryFactory::new(std::time::Duration::from_secs(30));
38//! let repository = file_repository_factory.create(std::path::PathBuf::from("."));
39//! let clock: Arc<dyn Clock> = Arc::new(SystemClock);
40//!
41//! // Create command
42//! let command = CreateCommandHandler::new(repository, clock);
43//!
44//! // Prepare configuration
45//! let config = EnvironmentCreationConfig::new(
46//!     EnvironmentSection {
47//!         name: "production".to_string(),
48//!         description: None,
49//!         instance_name: None, // Auto-generate from environment name
50//!     },
51//!     SshCredentialsConfig::new(
52//!         "keys/prod_key".to_string(),
53//!         "keys/prod_key.pub".to_string(),
54//!         "torrust".to_string(),
55//!         22,
56//!     ),
57//!     ProviderSection::Lxd(LxdProviderSection {
58//!         profile_name: "lxd-production".to_string(),
59//!     }),
60//!     TrackerSection::default(),
61//!     None, // prometheus
62//!     None, // grafana
63//!     None, // https
64//!     None, // backup
65//! );
66//!
67//! // Execute command with working directory
68//! let working_dir = std::path::Path::new(".");
69//! match command.execute(config, working_dir) {
70//!     Ok(environment) => {
71//!         println!("Created environment: {}", environment.name());
72//!     }
73//!     Err(error) => {
74//!         eprintln!("Error: {}", error);
75//!         eprintln!("\n{}", error.help());
76//!     }
77//! }
78//! ```
79
80pub mod config;
81pub mod errors;
82pub mod handler;
83pub mod schema;
84
85#[cfg(test)]
86mod tests;
87
88// Re-export main types for convenience
89pub use errors::CreateCommandHandlerError;
90pub use handler::CreateCommandHandler;