Skip to main content

Module create

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 Clock trait
  • 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;

Modules§

config
Configuration Module for Create Command
errors
Error types for the Create Command
handler
Create Command Implementation
schema
Create Schema Command Handler