torrust_tracker_deployer_lib/infrastructure/remote_actions/mod.rs
1//! Remote actions module (Level 3 of Three-Level Architecture)
2//!
3//! This module provides the lowest-level operations in the three-level architecture,
4//! containing leaf-level actions that directly interact with remote systems via SSH.
5//! These actions are the building blocks used by steps (Level 2) and commands (Level 1).
6//!
7//! ## Execution Context: Inside VM via SSH
8//!
9//! All remote actions in this module execute commands **INSIDE the VM via SSH**.
10//! For external validation (E2E testing from outside the VM), see `external_validators/`.
11//!
12//! **Distinction**:
13//! - **`remote_actions`** (this module): Execute commands inside VM via SSH
14//! - **`external_validators`**: Validate services from outside VM via HTTP
15//!
16//! ## Available Remote Actions
17//!
18//! - `validators::cloud_init` - Cloud-init status checking and validation
19//! - `validators::docker` - Docker installation and service management
20//! - `validators::docker_compose` - Docker Compose installation and validation
21//!
22//! ## Architecture Pattern
23//!
24//! Remote actions follow a consistent pattern:
25//! - Take SSH connection and required parameters
26//! - Execute specific remote operations via SSH
27//! - Provide structured error handling with action context
28//! - Return typed results for use by higher-level components
29//!
30//! These actions are designed to be atomic, testable, and reusable across
31//! different deployment scenarios.
32
33use std::net::IpAddr;
34use thiserror::Error;
35
36use crate::shared::command::CommandError;
37
38pub mod validators;
39
40pub use validators::cloud_init::CloudInitValidator;
41pub use validators::docker::DockerValidator;
42pub use validators::docker_compose::DockerComposeValidator;
43
44/// Errors that can occur during remote action execution
45#[derive(Error, Debug)]
46pub enum RemoteActionError {
47 /// SSH command execution failed
48 #[error("SSH command execution failed during '{action_name}': {source}")]
49 SshCommandFailed {
50 action_name: String,
51 #[source]
52 source: CommandError,
53 },
54
55 /// Action validation failed
56 #[error("Action '{action_name}' validation failed: {message}")]
57 ValidationFailed {
58 action_name: String,
59 message: String,
60 },
61
62 /// Action execution failed with custom error
63 #[error("Action '{action_name}' execution failed: {message}")]
64 ExecutionFailed {
65 action_name: String,
66 message: String,
67 },
68}
69
70/// Trait for remote actions that can be executed on a server via SSH
71///
72/// Remote actions are lightweight scripts that connect to a provisioned
73/// server via SSH to perform various operations such as:
74///
75/// - Validating server state and configuration
76/// - Retrieving server information (hostname, installed packages, etc.)
77/// - Executing maintenance tasks (updates, cleanup, etc.)
78/// - Installing or configuring software components
79#[allow(async_fn_in_trait)]
80pub trait RemoteAction {
81 /// Get the name of this action for logging purposes
82 fn name(&self) -> &'static str;
83
84 /// Execute the action against the specified server
85 ///
86 /// # Arguments
87 /// * `server_ip` - The IP address of the server to execute the action on
88 ///
89 /// # Returns
90 /// * `Ok(())` if the action executes successfully
91 /// * `Err(RemoteActionError)` if the action fails or encounters an error
92 async fn execute(&self, server_ip: &IpAddr) -> Result<(), RemoteActionError>;
93}