Skip to content

EPIC: UI Layer Destroy Command #10

@josecelano

Description

@josecelano

Epic Type: Child Epic #10 (Phase 2 of Task 1.2)
Parent Epic: #8 (epic-destroy-command.md)
Dependencies: Child Epic #9 (epic-app-layer-destroy-command.md) must be completed first
Related Roadmap: Section 1.2
Parent Issue: #2 (Scaffolding for main app)
Roadmap Section: 1.2 - Create command torrust-tracker-deployer destroy
Type: Epic
Priority: High


📋 Epic Overview

Implement the user-facing CLI interface for the destroy command. This epic builds on top of the application layer implementation from Epic #9 to provide a complete, production-ready CLI experience.

This is Phase 2 of the inside-outside approach: after the core application logic is implemented and tested, we add the user-friendly CLI interface.

🎯 Goals

  1. Fix E2E infrastructure preservation for manual testing workflow
  2. Rename existing app commands to command handlers for clarity
  3. Add Clap subcommand configuration for destroy
  4. Implement user-friendly progress messages and feedback
  5. Provide comprehensive user documentation

Note: Force flags (--force, --yes) and skip confirmation features are out of scope for MVP. These are easy to implement later and not essential for the initial destroy command functionality.

🚫 Non-Goals

📦 Sub-Issues

Issue #21: Fix E2E Infrastructure Preservation

Description: Restore the --keep flag functionality for E2E tests to enable proper manual testing of the destroy command.

Scope: Fix the E2E infrastructure preservation feature that was lost during recent refactoring.

Acceptance Criteria:

  • --keep flag functionality restored in E2E tests
  • Manual testing verification using lxc list | grep e2e-provision shows preserved infrastructure
  • Documentation updated with manual testing procedures
  • All existing E2E tests continue to pass

GitHub Issue: #21 - 21-fix-e2e-infrastructure-preservation.md

Estimated Effort: 1-2 hours


Issue #22: Rename App Commands to Command Handlers

Description: Refactor existing command terminology for clarity as we introduce UI-level Clap subcommands.

Scope:

  • Rename structs/modules in src/application/commands/ for clarity
  • Update documentation to use "command handler" terminology
  • Ensure consistent naming across the codebase

Rationale: As we introduce UI-level commands (Clap subcommands), we need clear terminology:

  • UI Command: Clap subcommand (e.g., destroy, provision)
  • Command Handler: DDD Application Layer command (e.g., DestroyCommand, ProvisionCommand)

Acceptance Criteria:

  • Command handlers renamed consistently
  • Documentation updated with new terminology
  • No breaking changes to functionality
  • All tests pass after refactoring
  • Code follows project conventions

GitHub Issue: #22 - 22-rename-app-commands-to-command-handlers.md

Estimated Effort: 2-3 hours


Issue #23: Add Clap Subcommand Configuration

Description: Implement the destroy subcommand in the CLI with basic functionality and UserOutput scaffolding.

Dependencies: Issue #21 must be completed first to enable manual testing workflow.

Scope:

  • Add destroy subcommand to src/app.rs
  • Wire up subcommand to call DestroyCommand handler
  • Add environment name parameter (required)
  • Add UserOutput type and VerbosityLevel enum (following docs/research/UX/user-output-vs-logging-separation.md)
  • Implement basic progress messages using UserOutput
  • Basic command structure without advanced options

UserOutput Integration:

  • Add VerbosityLevel enum (Quiet, Normal, Verbose, VeryVerbose, Debug)
  • Add UserOutput struct with methods for different message types
  • Note: Only enum definition for now, no Clap verbosity flags yet
  • Use UserOutput for essential destroy command messages

Example Usage:

torrust-tracker-deployer destroy <ENVIRONMENT_NAME>

Example Output (Normal verbosity level):

⏳ Destroying environment 'my-env'...
⏳ Tearing down infrastructure...
⏳ Cleaning up resources...
✅ Environment 'my-env' destroyed successfully

Acceptance Criteria:

  • destroy subcommand added to Clap configuration
  • Subcommand calls DestroyCommand from Application Layer
  • Environment name parameter required
  • VerbosityLevel enum implemented (5 levels)
  • UserOutput struct implemented with basic methods (progress, success, warn)
  • Essential destroy messages implemented using UserOutput
  • Help text provides clear usage information
  • Basic error handling for missing environment
  • Unit tests for CLI argument parsing
  • User output separated from internal logging

GitHub Issue: #23 - 23-add-clap-subcommand-configuration.md

Estimated Effort: 3-4 hours


Issue #24: Add User Documentation

Description: Create comprehensive user-facing documentation for the destroy command.

Scope:

  • Add section to docs/user-guide/ about destroy command
  • Document command usage and examples
  • Document flags and options
  • Add troubleshooting section
  • Document safety considerations

Acceptance Criteria:

  • User guide created/updated
  • Usage examples provided
  • Flags and options documented
  • Troubleshooting section added
  • Safety considerations documented
  • All markdown linting passes

GitHub Issue: #24 - 24-add-user-documentation.md

Estimated Effort: 2-3 hours


📊 Epic Summary

Total Estimated Effort: 8-12 hours

Sub-Issues:

  1. Issue Fix E2E Infrastructure Preservation #21: Fix E2E Infrastructure Preservation (1-2h)
  2. Issue Rename App Commands to Command Handlers #22: Rename App Commands to Command Handlers (2-3h)
  3. Issue Add Clap Subcommand Configuration #23: Add Clap Subcommand Configuration with Basic Progress (3-4h)
  4. Issue Add User Documentation #24: Add User Documentation (2-3h)

Out of Scope for MVP: Force flags (--force, --yes) and skip confirmation features - these can be implemented as separate improvements later.

🔗 Dependencies

📝 Technical Notes

MVP Focus

This epic focuses on the essential functionality for MVP:

  • E2E infrastructure preservation for manual testing (prerequisite)
  • Basic destroy subcommand with clear interface
  • UserOutput type and VerbosityLevel enum (scaffolding for future verbosity flags)
  • Essential progress messages using Normal verbosity level
  • User-friendly feedback with proper separation from logging
  • Basic user documentation
  • Clean separation between UI and Application layers

Future Improvements (out of scope for MVP):

  • Clap verbosity flags (-v, -vv, -q)
  • Force and skip confirmation flags
  • Interactive mode with detailed prompts
  • Selective resource destruction
  • Advanced verbosity level implementations

UI Command vs. Command Handler

After this epic, we'll have clear separation:

// UI Layer (src/app.rs) - Clap subcommands
#[derive(Subcommand)]
enum Commands {
    Provision { /* ... */ },
    Destroy { environment: String },
    Configure { /* ... */ },
}

// Application Layer (src/application/commands/) - DDD command handlers
pub struct DestroyCommandHandler { /* ... */ }
pub struct ProvisionCommandHandler { /* ... */ }
pub struct ConfigureCommandHandler { /* ... */ }

User Output vs. Logging

Follow project principles established in docs/research/UX/user-output-vs-logging-separation.md:

  • User Output: Directed to stdout via UserOutput type, clear and concise
  • Logging: Directed to files/stderr via tracing, detailed for debugging
  • Complete separation between user-facing messages and internal logging

UserOutput Implementation

// Verbosity levels (enum only for MVP, no CLI flags yet)
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum VerbosityLevel {
    Quiet,      // Minimal output
    Normal,     // Default: Essential progress (MVP focus)
    Verbose,    // Detailed progress
    VeryVerbose, // Including decisions & retries
    Debug,      // Maximum detail for troubleshooting
}

// UserOutput type for destroy command
pub struct UserOutput {
    verbosity: VerbosityLevel,
}

impl UserOutput {
    pub fn progress(&self, message: &str) { /* ... */ }
    pub fn success(&self, message: &str) { /* ... */ }
    pub fn warn(&self, message: &str) { /* ... */ }
}

Example Destroy Output

Normal Verbosity (MVP implementation):

⏳ Destroying environment 'my-env'...
⏳ Tearing down infrastructure...
⏳ Cleaning up resources...
✅ Environment 'my-env' destroyed successfully

Parallel Internal Logging (always present):

2025-10-21T10:15:00.123Z INFO destroy_command: Starting environment destruction
    environment="my-env" command_type="destroy"
2025-10-21T10:15:01.456Z INFO opentofu_client: Executing destroy operation
    workspace="/path/to/env" operation="destroy"
2025-10-21T10:15:15.789Z INFO destroy_command: Environment destruction completed
    environment="my-env" duration=15.666s

🚀 Next Steps After Completion

After completing this epic:

  1. User testing with real environments
  2. Gather feedback on UX
  3. Consider future improvements:
    • Interactive confirmation with resource preview
    • Selective destruction (only OpenTofu, only Ansible, etc.)
    • Batch destruction for multiple environments
    • Integration with CI/CD pipelines

📋 Related Documentation

Epic Document: docs/issues/10-epic-ui-layer-destroy-command.md

Sub-issues

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions