-
Couldn't load subscription status.
- Fork 0
Closed
Description
Overview
Implement the CLI presentation layer for the create command, handling Figment integration for configuration file parsing, argument processing, and user interaction.
Parent EPIC: #34 - Implement Create Environment Command
Depends On: #36 (Application Layer CreateCommand)
Related: Full Specification
Key Points
- Add
--working-dirflag to main CLI for production use (not just tests) - Figment stays in presentation layer as delivery mechanism
- All errors use tiered help system with
.help()methods
Goals
-
Create
createsubcommand in presentation layer- Figment integration for configuration file parsing (JSON format)
- Argument parsing (
--env-file,--working-dir) - Configuration file loading using Figment
- Conversion from raw file data to clean domain objects
- Call application layer CreateCommand with domain objects
- User feedback and progress indication
- Error message presentation with helpful context
-
Add explicit presentation error enums
-
CreateSubcommandErrorfor CLI-specific errors - Error conversion from application layer to user-friendly messages
- All errors implement
.help()methods
-
-
Command help documentation
- Usage examples
- Argument descriptions
- Error guidance
-
Tests
- Integration tests for CLI interface with temporary directories
- Unit tests for argument parsing and Figment integration
- Error presentation tests
Module Structure
src/presentation/console/subcommands/create/
├── mod.rs # Module exports
├── subcommand.rs # CreateSubcommand implementation
├── args.rs # CLI argument definitions
├── config_loader.rs # Figment integration
├── errors.rs # Presentation error types with .help()
└── tests/
├── mod.rs
├── integration.rs # CLI integration tests
└── fixtures.rs # Test fixtures
CLI Arguments
#[derive(Debug, Args)]
pub struct CreateArgs {
#[command(subcommand)]
pub action: CreateAction,
}
#[derive(Debug, Subcommand)]
pub enum CreateAction {
Environment {
/// Path to the environment configuration file
#[arg(long, short = 'f', value_name = "FILE")]
env_file: PathBuf,
},
// Future: Template generation
}Configuration Loader (Figment)
pub struct ConfigLoader;
impl ConfigLoader {
pub fn load_from_file(
&self,
config_path: &Path
) -> Result<EnvironmentCreationConfig, CreateSubcommandError> {
// Verify file exists
if !config_path.exists() {
return Err(CreateSubcommandError::ConfigFileNotFound {
path: config_path.to_path_buf(),
});
}
// Load with Figment
let config = Figment::new()
.merge(Serialized::defaults(EnvironmentCreationConfig::default()))
.merge(Json::file(config_path))
.extract()
.map_err(|source| CreateSubcommandError::ConfigParsingFailed {
path: config_path.to_path_buf(),
format: ConfigFormat::Json,
source: Box::new(source),
})?;
// Validate using domain rules
config.validate()
.map_err(CreateSubcommandError::ConfigValidationFailed)?;
Ok(config)
}
}Error Types with .help()
#[derive(Debug, Error)]
pub enum CreateSubcommandError {
#[error("Configuration file not found: {path}")]
ConfigFileNotFound { path: PathBuf },
#[error("Failed to parse configuration file: {path}")]
ConfigParsingFailed {
path: PathBuf,
format: ConfigFormat,
#[source]
source: Box<dyn std::error::Error + Send + Sync>,
},
#[error("Configuration validation failed")]
ConfigValidationFailed(#[source] ConfigValidationError),
#[error("Command execution failed")]
CommandFailed(#[source] CreateCommandError),
}
impl CreateSubcommandError {
pub fn help(&self) -> &'static str {
// Detailed troubleshooting guidance
}
}Usage Examples
# Create environment from configuration file
torrust-tracker-deployer create environment --env-file ./config/environment.json
# With custom working directory
torrust-tracker-deployer --working-dir /path/to/workspace create environment --env-file ./config/env.json
# Show help
torrust-tracker-deployer create --help
torrust-tracker-deployer create environment --helpAcceptance Criteria
-
create environment --env-fileloads and parses JSON configuration -
--working-dirflag works in production (main CLI args) - Invalid file paths rejected with clear errors
- JSON parsing errors show clear messages
- Validation errors show actionable guidance
- Command help documentation is comprehensive
- Error messages use tiered help system (
.help()methods) - Integration tests cover all CLI scenarios
- Figment integration tested with various JSON formats
Estimated Time
3-4 hours
Notes
- Figment integration stays in presentation layer (DDD boundary)
- Support
--working-dirat main CLI level for production use - All errors must be user-friendly with
.help()guidance - TOML support will be added in future separate issue
Copilot
Metadata
Metadata
Assignees
Labels
No labels