torrust_tracker_deployer_lib/domain/environment/state/
configuring.rs1use serde::{Deserialize, Serialize};
13
14use crate::domain::environment::state::{
15 AnyEnvironmentState, ConfigureFailed, Configured, StateTypeError,
16};
17use crate::domain::environment::Environment;
18
19#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
28pub struct Configuring;
29
30impl Environment<Configuring> {
32 #[must_use]
36 pub fn configured(self) -> Environment<Configured> {
37 self.with_state(Configured)
38 }
39
40 #[must_use]
46 pub fn configure_failed(
47 self,
48 context: crate::domain::environment::state::ConfigureFailureContext,
49 ) -> Environment<ConfigureFailed> {
50 self.with_state(ConfigureFailed { context })
51 }
52}
53
54impl Environment<Configuring> {
56 #[must_use]
58 pub fn into_any(self) -> AnyEnvironmentState {
59 AnyEnvironmentState::Configuring(self)
60 }
61}
62
63impl AnyEnvironmentState {
65 pub fn try_into_configuring(self) -> Result<Environment<Configuring>, StateTypeError> {
71 match self {
72 Self::Configuring(env) => Ok(env),
73 other => Err(StateTypeError::UnexpectedState {
74 expected: "configuring",
75 actual: other.state_name().to_string(),
76 }),
77 }
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn it_should_create_configuring_state() {
87 let state = Configuring;
88 assert_eq!(state, Configuring);
89 }
90
91 mod conversion_tests {
92 use super::*;
93 use crate::adapters::ssh::SshCredentials;
94 use crate::domain::environment::name::EnvironmentName;
95 use crate::domain::environment::runtime_outputs::ProvisionMethod;
96 use crate::domain::provider::{LxdConfig, ProviderConfig};
97 use crate::domain::ProfileName;
98 use crate::shared::Username;
99 use std::net::{IpAddr, Ipv4Addr};
100 use std::path::PathBuf;
101
102 fn default_lxd_provider_config(env_name: &EnvironmentName) -> ProviderConfig {
103 ProviderConfig::Lxd(LxdConfig {
104 profile_name: ProfileName::new(format!("lxd-{}", env_name.as_str())).unwrap(),
105 })
106 }
107
108 fn create_test_ssh_credentials() -> SshCredentials {
109 let username = Username::new("test-user".to_string()).unwrap();
110 SshCredentials::new(
111 PathBuf::from("/tmp/test_key"),
112 PathBuf::from("/tmp/test_key.pub"),
113 username,
114 )
115 }
116
117 fn create_test_environment_configuring() -> Environment<Configuring> {
118 let name = EnvironmentName::new("test-env".to_string()).unwrap();
119 let ssh_creds = create_test_ssh_credentials();
120 Environment::new(
121 name.clone(),
122 default_lxd_provider_config(&name),
123 ssh_creds,
124 22,
125 chrono::Utc::now(),
126 )
127 .start_provisioning()
128 .provisioned(
129 IpAddr::V4(Ipv4Addr::new(192, 168, 1, 100)),
130 ProvisionMethod::Provisioned,
131 )
132 .start_configuring()
133 }
134
135 #[test]
136 fn it_should_convert_configuring_environment_into_any() {
137 let env = create_test_environment_configuring();
138 let any_env = env.into_any();
139 assert!(matches!(any_env, AnyEnvironmentState::Configuring(_)));
140 }
141
142 #[test]
143 fn it_should_convert_any_to_configuring_successfully() {
144 let env = create_test_environment_configuring();
145 let any_env = env.into_any();
146 let result = any_env.try_into_configuring();
147 assert!(result.is_ok());
148 }
149 }
150
151 mod transition_tests {
152 use super::*;
153 use crate::adapters::ssh::SshCredentials;
154 use crate::domain::environment::name::EnvironmentName;
155 use crate::domain::environment::runtime_outputs::ProvisionMethod;
156 use crate::domain::environment::state::Configured;
157 use crate::domain::provider::{LxdConfig, ProviderConfig};
158 use crate::domain::ProfileName;
159 use crate::shared::Username;
160 use std::net::{IpAddr, Ipv4Addr};
161 use std::path::PathBuf;
162
163 fn default_lxd_provider_config(env_name: &EnvironmentName) -> ProviderConfig {
164 ProviderConfig::Lxd(LxdConfig {
165 profile_name: ProfileName::new(format!("lxd-{}", env_name.as_str())).unwrap(),
166 })
167 }
168
169 fn create_test_environment() -> Environment<Configuring> {
170 let env_name = EnvironmentName::new("test-state".to_string()).unwrap();
171 let ssh_username = Username::new("torrust".to_string()).unwrap();
172 let ssh_credentials = SshCredentials::new(
173 PathBuf::from("test_key"),
174 PathBuf::from("test_key.pub"),
175 ssh_username,
176 );
177 Environment::new(
178 env_name.clone(),
179 default_lxd_provider_config(&env_name),
180 ssh_credentials,
181 22,
182 chrono::Utc::now(),
183 )
184 .start_provisioning()
185 .provisioned(
186 IpAddr::V4(Ipv4Addr::new(192, 168, 1, 100)),
187 ProvisionMethod::Provisioned,
188 )
189 .start_configuring()
190 }
191
192 #[test]
193 fn it_should_transition_from_configuring_to_configured() {
194 let env = create_test_environment();
195 let env = env.configured();
196
197 assert_eq!(*env.state(), Configured);
198 assert_eq!(env.name().as_str(), "test-state");
199 }
200
201 #[test]
202 fn it_should_transition_from_configuring_to_configure_failed() {
203 use crate::domain::environment::state::{
204 BaseFailureContext, ConfigureFailureContext, ConfigureStep,
205 };
206 use crate::domain::environment::TraceId;
207 use crate::shared::ErrorKind;
208 use chrono::Utc;
209 use std::time::Duration;
210
211 let env = create_test_environment();
212 let context = ConfigureFailureContext {
213 failed_step: ConfigureStep::InstallDocker,
214 error_kind: ErrorKind::CommandExecution,
215 base: BaseFailureContext {
216 error_summary: "ansible_playbook_error".to_string(),
217 failed_at: Utc::now(),
218 execution_started_at: Utc::now(),
219 execution_duration: Duration::from_secs(15),
220 trace_id: TraceId::new(),
221 trace_file_path: None,
222 },
223 };
224 let env = env.configure_failed(context.clone());
225
226 assert_eq!(
227 env.state().context.failed_step,
228 ConfigureStep::InstallDocker
229 );
230 assert_eq!(env.name().as_str(), "test-state");
231 }
232 }
233}