torrust_tracker_deployer_lib/presentation/cli/controllers/show/
handler.rs1use std::cell::RefCell;
7use std::sync::Arc;
8
9use parking_lot::ReentrantMutex;
10
11use crate::application::command_handlers::show::info::EnvironmentInfo;
12use crate::application::command_handlers::show::{ShowCommandHandler, ShowCommandHandlerError};
13use crate::domain::environment::name::EnvironmentName;
14use crate::domain::environment::repository::EnvironmentRepository;
15use crate::presentation::cli::input::cli::OutputFormat;
16use crate::presentation::cli::views::commands::show::{JsonView, TextView};
17use crate::presentation::cli::views::progress::ProgressReporter;
18use crate::presentation::cli::views::Render;
19use crate::presentation::cli::views::UserOutput;
20
21use super::errors::ShowSubcommandError;
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25enum ShowStep {
26 ValidateEnvironment,
27 LoadEnvironment,
28 DisplayInformation,
29}
30
31impl ShowStep {
32 const ALL: &'static [Self] = &[
34 Self::ValidateEnvironment,
35 Self::LoadEnvironment,
36 Self::DisplayInformation,
37 ];
38
39 const fn count() -> usize {
41 Self::ALL.len()
42 }
43
44 fn description(self) -> &'static str {
46 match self {
47 Self::ValidateEnvironment => "Validating environment name",
48 Self::LoadEnvironment => "Loading environment",
49 Self::DisplayInformation => "Displaying information",
50 }
51 }
52}
53
54pub struct ShowCommandController {
71 handler: ShowCommandHandler,
72 progress: ProgressReporter,
73}
74
75impl ShowCommandController {
76 #[allow(clippy::needless_pass_by_value)] pub fn new(
84 repository: Arc<dyn EnvironmentRepository + Send + Sync>,
85 user_output: Arc<ReentrantMutex<RefCell<UserOutput>>>,
86 ) -> Self {
87 let handler = ShowCommandHandler::new(repository);
88 let progress = ProgressReporter::new(user_output, ShowStep::count());
89
90 Self { handler, progress }
91 }
92
93 pub fn execute(
109 &mut self,
110 environment_name: &str,
111 output_format: OutputFormat,
112 ) -> Result<(), ShowSubcommandError> {
113 let env_name = self.validate_environment_name(environment_name)?;
115
116 let env_info = self.load_environment(&env_name)?;
118
119 self.display_information(&env_info, output_format)?;
121
122 Ok(())
123 }
124
125 fn validate_environment_name(
127 &mut self,
128 name: &str,
129 ) -> Result<EnvironmentName, ShowSubcommandError> {
130 self.progress
131 .start_step(ShowStep::ValidateEnvironment.description())?;
132
133 let env_name = EnvironmentName::new(name.to_string()).map_err(|source| {
134 ShowSubcommandError::InvalidEnvironmentName {
135 name: name.to_string(),
136 source,
137 }
138 })?;
139
140 self.progress
141 .complete_step(Some(&format!("Environment name validated: {name}")))?;
142
143 Ok(env_name)
144 }
145
146 fn load_environment(
148 &mut self,
149 env_name: &EnvironmentName,
150 ) -> Result<EnvironmentInfo, ShowSubcommandError> {
151 self.progress
152 .start_step(ShowStep::LoadEnvironment.description())?;
153
154 let env_info = self
155 .handler
156 .execute(env_name)
157 .map_err(|e| Self::map_handler_error(e, env_name))?;
158
159 self.progress
160 .complete_step(Some(&format!("Environment loaded: {env_name}")))?;
161
162 Ok(env_info)
163 }
164
165 fn map_handler_error(
167 error: ShowCommandHandlerError,
168 env_name: &EnvironmentName,
169 ) -> ShowSubcommandError {
170 match error {
171 ShowCommandHandlerError::EnvironmentNotFound { .. } => {
172 ShowSubcommandError::EnvironmentNotFound {
173 name: env_name.to_string(),
174 }
175 }
176 ShowCommandHandlerError::LoadError(e) => ShowSubcommandError::LoadError {
177 name: env_name.to_string(),
178 message: e.to_string(),
179 },
180 }
181 }
182
183 fn display_information(
199 &mut self,
200 env_info: &EnvironmentInfo,
201 output_format: OutputFormat,
202 ) -> Result<(), ShowSubcommandError> {
203 self.progress
204 .start_step(ShowStep::DisplayInformation.description())?;
205
206 let output = match output_format {
208 OutputFormat::Text => TextView::render(env_info)?,
209 OutputFormat::Json => JsonView::render(env_info)?,
210 };
211
212 self.progress.result(&output)?;
214
215 self.progress.complete_step(Some("Information displayed"))?;
216
217 Ok(())
218 }
219}