Expand description
Create Command Module
This module implements the delivery-agnostic CreateCommandHandler for orchestrating
environment creation business logic. The command is synchronous and follows
existing patterns from ProvisionCommandHandler.
§Architecture
The CreateCommandHandler implements the Command Pattern and uses Dependency Injection
to interact with infrastructure services through interfaces:
- Repository Pattern: Persists environment state via
EnvironmentRepository - Clock Abstraction: Provides deterministic time for testing via
Clocktrait - Domain-Driven Design: Uses domain objects from
domain::environment
§Design Principles
- Delivery-Agnostic: Works with CLI, REST API, or any delivery mechanism
- Synchronous: Follows existing patterns (no async/await)
- Repository Responsibility: Lets repository handle directory creation atomically
- Explicit Errors: All errors implement
.help()with actionable guidance
§Usage Example
use std::sync::Arc;
use torrust_tracker_deployer_lib::application::command_handlers::create::CreateCommandHandler;
use torrust_tracker_deployer_lib::application::command_handlers::create::config::{
EnvironmentCreationConfig, EnvironmentSection, LxdProviderSection, ProviderSection,
SshCredentialsConfig,
};
use torrust_tracker_deployer_lib::application::command_handlers::create::config::tracker::TrackerSection;
use torrust_tracker_deployer_lib::infrastructure::persistence::file_repository_factory::FileRepositoryFactory;
use torrust_tracker_deployer_lib::shared::{SystemClock, Clock};
// Setup dependencies
let file_repository_factory = FileRepositoryFactory::new(std::time::Duration::from_secs(30));
let repository = file_repository_factory.create(std::path::PathBuf::from("."));
let clock: Arc<dyn Clock> = Arc::new(SystemClock);
// Create command
let command = CreateCommandHandler::new(repository, clock);
// Prepare configuration
let config = EnvironmentCreationConfig::new(
EnvironmentSection {
name: "production".to_string(),
description: None,
instance_name: None, // Auto-generate from environment name
},
SshCredentialsConfig::new(
"keys/prod_key".to_string(),
"keys/prod_key.pub".to_string(),
"torrust".to_string(),
22,
),
ProviderSection::Lxd(LxdProviderSection {
profile_name: "lxd-production".to_string(),
}),
TrackerSection::default(),
None, // prometheus
None, // grafana
None, // https
None, // backup
);
// Execute command with working directory
let working_dir = std::path::Path::new(".");
match command.execute(config, working_dir) {
Ok(environment) => {
println!("Created environment: {}", environment.name());
}
Err(error) => {
eprintln!("Error: {}", error);
eprintln!("\n{}", error.help());
}
}Re-exports§
pub use errors::CreateCommandHandlerError;pub use handler::CreateCommandHandler;