torrust_tracker_deployer_lib/presentation/cli/controllers/mod.rs
1//! Controllers Layer - Presentation Layer Component
2//!
3//! The Controllers Layer handles command execution and business logic coordination.
4//! This is the third layer in the presentation layer's four-layer architecture:
5//! Input โ Dispatch โ **Controllers** โ Views.
6//!
7//! ## ๐ง Current Status: Proposal #3 In Progress
8//!
9//! This layer is being refactored to establish consistent controller patterns.
10//! The goal is to align all command controllers with the clean architecture
11//! established by the destroy command controller.
12//!
13//! ## Command Architecture Types
14//!
15//! There are two types of commands in the system, each with different internal structure:
16//!
17//! ### 1. Single Commands (Direct Execution)
18//!
19//! Commands that execute directly without subcommands (e.g., `destroy`).
20//! These follow the clean handler pattern with direct execution.
21//!
22//! ### 2. Commands with Subcommands (Router + Subcontrollers)
23//!
24//! Commands that route to multiple subcommands (e.g., `create environment`, `create template`).
25//! These have an **extra routing layer** but subcommands maintain the same internal
26//! structure as single commands.
27//!
28//! **Key Principle**: Subcommands should have internally the same structure as normal
29//! commands, but with an additional routing layer to dispatch between subcommands.
30//!
31//! ## Controller Maturity Levels
32//!
33//! ### โ
Reference Implementation: Destroy Controller (Single Command)
34//!
35//! The `destroy` controller demonstrates the target architecture for single commands:
36//! - **Clean Handler Pattern**: Single `handler.rs` with focused responsibility
37//! - **Dedicated Error Types**: Command-specific errors with help methods
38//! - **Minimal Dependencies**: Takes `ExecutionContext`, delegates to application layer
39//! - **Comprehensive Tests**: Full test coverage with clear test organization
40//!
41//! ```text
42//! destroy/
43//! โโโ handler.rs # Main command handler function
44//! โโโ errors.rs # DestroySubcommandError with help methods
45//! โโโ tests/ # Command-specific tests
46//! โโโ mod.rs # Module exports
47//! ```
48//!
49//! ### ๐ง Needs Refactoring: Create Controller (Command with Subcommands)
50//!
51//! The `create` controller needs refactoring to match the target pattern for commands
52//! with subcommands. It demonstrates the **router + subcontroller** pattern but needs
53//! architectural cleanup.
54//!
55//! **Current Structure (Transitional)**:
56//! ```text
57//! create/
58//! โโโ router.rs # Routes between environment and template subcommands
59//! โโโ errors.rs # Unified CreateCommandError wrapper
60//! โโโ subcommands/ # Temporary: should become separate controllers
61//! โ โโโ environment/ # Environment creation logic
62//! โ โโโ template/ # Template generation logic
63//! โโโ tests/ # Tests organized by function
64//! โ โโโ environment.rs # Environment creation tests
65//! โ โโโ template.rs # Template generation tests
66//! โโโ mod.rs # Module exports
67//! ```
68//!
69//! **Target Structure (After Refactoring)**:
70//!
71//! The refactoring will split this into separate controllers for each subcommand,
72//! each following the same clean structure as single commands:
73//!
74//! ```text
75//! create_environment/ # NEW: Dedicated environment controller
76//! โโโ handler.rs # Environment creation handler (same structure as destroy)
77//! โโโ errors.rs # Environment-specific errors
78//! โโโ tests/ # Environment tests
79//! โโโ mod.rs # Module exports
80//!
81//! create_template/ # NEW: Dedicated template controller
82//! โโโ handler.rs # Template generation handler (same structure as destroy)
83//! โโโ errors.rs # Template-specific errors
84//! โโโ tests/ # Template tests
85//! โโโ mod.rs # Module exports
86//! ```
87//!
88//! **Key Insight**: Each subcommand becomes a separate controller with the same
89//! internal structure as single commands. The routing is handled at the dispatch
90//! layer, not within controllers.
91//!
92//! ## ๐ฏ Controller Design Principles
93//!
94//! Based on the destroy controller reference implementation:
95//!
96//! ### 1. Single Responsibility
97//! - Each controller handles **one specific command** (destroy, create environment, create template)
98//! - No routing logic within controllers - routing handled by dispatch layer for subcommands
99//! - No presentation logic - controllers coordinate, views handle output
100//!
101//! ### 2. Clean Handler Pattern (Universal for All Controllers)
102//! - Main logic in `handler.rs` with descriptive function name (`handle_destroy_command`)
103//! - Take `ExecutionContext` for dependencies
104//! - Return command-specific error types
105//! - Focus on orchestrating application layer services
106//!
107//! **Note**: This pattern applies to both single commands and subcommand controllers.
108//! Subcommand controllers have the same internal structure, just different routing.
109//!
110//! ### 3. Dedicated Error Types
111//! - Command-specific error enums (e.g., `DestroySubcommandError`)
112//! - Use thiserror for structured errors
113//! - Implement `.help()` method for detailed troubleshooting
114//! - Include context and actionable guidance
115//!
116//! ### 4. Application Layer Integration
117//! - Controllers call application layer command handlers
118//! - Pass through domain entities and value objects
119//! - Handle application errors and convert to presentation errors
120//! - Don't contain business logic - delegate to application layer
121//!
122//! ## ๐ Subcommand Routing Architecture
123//!
124//! For commands with subcommands (like `create`), the current architecture uses:
125//!
126//! 1. **Dispatch Layer**: Receives full command (e.g., `create environment`)
127//! 2. **Router**: Routes to appropriate subcommand handler based on action type
128//! 3. **Subcommand Handler**: Executes specific logic (environment creation or template generation)
129//!
130//! **Current Implementation Example** (from `create/router.rs`):
131//! ```ignore
132//! use std::path::Path;
133//! use torrust_tracker_deployer_lib::domain::provider::Provider;
134//! use torrust_tracker_deployer_lib::presentation::cli::input::cli::commands::CreateAction;
135//! use torrust_tracker_deployer_lib::presentation::cli::dispatch::context::ExecutionContext;
136//! use torrust_tracker_deployer_lib::presentation::cli::controllers::create::errors::CreateCommandError;
137//! use torrust_tracker_deployer_lib::presentation::cli::controllers::create::subcommands;
138//!
139//! # #[tokio::main]
140//! # async fn main() {
141//! # let action = todo!();
142//! # let working_dir = todo!();
143//! # let context = todo!();
144//! pub async fn route_command(
145//! action: CreateAction,
146//! working_dir: &Path,
147//! context: &ExecutionContext,
148//! ) -> Result<(), CreateCommandError> {
149//! match action {
150//! CreateAction::Environment { env_file } => {
151//! context
152//! .container()
153//! .create_environment_controller()
154//! .execute(&env_file, working_dir)
155//! .await
156//! .map(|_| ()) // Convert Environment<Created> to ()
157//! .map_err(CreateCommandError::Environment)
158//! }
159//! CreateAction::Template { output_path, provider } => {
160//! let template_path = output_path.unwrap_or_else(CreateAction::default_template_path);
161//! context
162//! .container()
163//! .create_template_controller()
164//! .execute(&template_path, provider)
165//! .await
166//! .map_err(CreateCommandError::Template)
167//! }
168//! CreateAction::Schema { output_path } => {
169//! context
170//! .container()
171//! .create_schema_controller()
172//! .execute(output_path.as_ref())
173//! .map_err(CreateCommandError::Schema)
174//! }
175//! }
176//! }
177//! # }
178//! ```
179//!
180//! **Target Architecture**: Move routing to dispatch layer, make each subcommand
181//! a separate controller with the same structure as single commands.
182//!
183//! ## ๐ Refactoring Plan for Create Controller
184//!
185//! To complete Proposal #3, the create controller needs to be split into separate
186//! controllers that each follow the same clean structure as single commands:
187//!
188//! ### Current Challenge
189//! The `create` command currently uses internal routing with subcommands. This needs
190//! to be refactored so each subcommand becomes a separate controller with the same
191//! internal structure as single commands.
192//!
193//! ### Step 1: Create Environment Controller
194//! 1. Create `src/presentation/controllers/create_environment/`
195//! 2. Move environment logic from `create/subcommands/environment/`
196//! 3. Create clean handler following destroy pattern (same structure)
197//! 4. Move environment tests to new controller
198//!
199//! ### Step 2: Create Template Controller
200//! 1. Create `src/presentation/controllers/create_template/`
201//! 2. Move template logic from `create/subcommands/template/`
202//! 3. Create clean handler following destroy pattern (same structure)
203//! 4. Move template tests to new controller
204//!
205//! ### Step 3: Update Dispatch Router
206//! 1. Remove create controller router (no more internal subcommand routing)
207//! 2. Update dispatch layer to route directly to separate controllers
208//! 3. Update error handling for separate error types
209//! 4. Each subcommand treated as independent controller
210//!
211//! ### Step 4: Remove Old Create Structure
212//! 1. Remove `create/` directory entirely
213//! 2. Update imports throughout codebase
214//! 3. Update documentation and tests
215//!
216//! **Result**: Both `create environment` and `create template` will be handled by
217//! separate controllers with identical structure to `destroy` - just different routing
218//! at the dispatch level.
219//!
220//! ## ๐งช Testing Strategy
221//!
222//! Each controller should have comprehensive test coverage:
223//! - **Unit Tests**: Handler function behavior with various inputs
224//! - **Error Tests**: All error variants and help text validation
225//! - **Integration Tests**: End-to-end command execution with `ExecutionContext`
226//!
227//! Tests should be **isolated** - each controller's tests run independently
228//! without depending on other controllers or external state.
229//!
230//! ## ๐ Future Controllers
231//!
232//! After establishing the controller pattern, additional commands will follow
233//! the same structure:
234//!
235//! ```text
236//! controllers/
237//! โโโ create_environment/ # Environment creation
238//! โโโ create_template/ # Template generation
239//! โโโ destroy/ # Environment destruction โ
240//! โโโ provision/ # Future: Infrastructure provisioning
241//! โโโ configure/ # Future: Software configuration
242//! โโโ release/ # Future: Application deployment
243//! โโโ run/ # Future: Service management
244//! ```
245//!
246//! Each controller will:
247//! - Follow the established handler pattern
248//! - Have dedicated error types
249//! - Integrate cleanly with the dispatch layer
250//! - Maintain comprehensive test coverage
251
252// Re-export command modules
253pub mod configure;
254pub mod constants;
255pub mod create;
256pub mod destroy;
257pub mod docs;
258pub mod exists;
259pub mod list;
260pub mod provision;
261pub mod purge;
262pub mod register;
263pub mod release;
264pub mod render;
265pub mod run;
266pub mod show;
267pub mod test;
268pub mod validate;
269
270// Shared test utilities
271#[cfg(test)]
272pub mod tests;