ansible/
errors.rs

1//! Comprehensive error handling for Ansible operations.
2//!
3//! This module provides detailed error types for different failure modes
4//! that can occur when working with Ansible commands and operations.
5
6use thiserror::Error;
7
8/// Comprehensive error types for Ansible operations.
9///
10/// The `AnsibleError` enum provides detailed error information for different
11/// types of failures that can occur when executing Ansible commands, managing
12/// configurations, or working with inventories.
13///
14/// # Examples
15///
16/// ## Error Handling
17///
18/// ```rust,no_run
19/// use ansible::{Ansible, AnsibleError};
20///
21/// let result = Ansible::default().ping();
22/// match result {
23///     Ok(output) => println!("Success: {}", output),
24///     Err(AnsibleError::CommandFailed { message, exit_code, stdout, stderr }) => {
25///         eprintln!("Command failed: {}", message);
26///         if let Some(code) = exit_code {
27///             eprintln!("Exit code: {}", code);
28///         }
29///         if let Some(stderr) = stderr {
30///             eprintln!("Error output: {}", stderr);
31///         }
32///     }
33///     Err(AnsibleError::UnsupportedPlatform(msg)) => {
34///         eprintln!("Platform not supported: {}", msg);
35///     }
36///     Err(e) => eprintln!("Other error: {}", e),
37/// }
38/// ```
39///
40/// ## Error Construction
41///
42/// ```rust
43/// use ansible::AnsibleError;
44///
45/// // Create specific error types
46/// let cmd_error = AnsibleError::command_failed(
47///     "ansible ping failed",
48///     Some(1),
49///     Some("output".to_string()),
50///     Some("error".to_string())
51/// );
52///
53/// let platform_error = AnsibleError::unsupported_platform("Windows not supported");
54/// ```
55#[derive(Error, Debug)]
56pub enum AnsibleError {
57    /// I/O operation failed
58    #[error("I/O operation failed: {0}")]
59    Io(#[from] std::io::Error),
60
61    /// Ansible command execution failed
62    #[error("Ansible command execution failed: {message}")]
63    CommandFailed {
64        message: String,
65        exit_code: Option<i32>,
66        stdout: Option<String>,
67        stderr: Option<String>,
68    },
69
70    /// Invalid module configuration
71    #[error("Invalid module configuration: {0}")]
72    InvalidModule(String),
73
74    /// Invalid inventory configuration
75    #[error("Invalid inventory configuration: {0}")]
76    InvalidInventory(String),
77
78    /// Playbook parsing or execution error
79    #[error("Playbook error: {0}")]
80    PlaybookError(String),
81
82    /// Environment variable error
83    #[error("Environment variable error: {0}")]
84    EnvironmentError(String),
85
86    /// Configuration error
87    #[error("Configuration error: {0}")]
88    ConfigError(String),
89
90    /// Unsupported platform error
91    #[error("Unsupported platform: {0}")]
92    UnsupportedPlatform(String),
93
94    /// Command not found error
95    #[error("Command not found: {0}")]
96    CommandNotFound(String),
97
98    /// System requirement not met
99    #[error("System requirement not met: {0}")]
100    SystemRequirement(String),
101
102    /// Unknown error
103    #[error("Unknown error occurred")]
104    Unknown,
105}
106
107impl AnsibleError {
108    /// Create a command failed error with detailed information
109    pub fn command_failed(
110        message: impl Into<String>,
111        exit_code: Option<i32>,
112        stdout: Option<String>,
113        stderr: Option<String>,
114    ) -> Self {
115        Self::CommandFailed {
116            message: message.into(),
117            exit_code,
118            stdout,
119            stderr,
120        }
121    }
122
123    /// Create an invalid module error
124    pub fn invalid_module(message: impl Into<String>) -> Self {
125        Self::InvalidModule(message.into())
126    }
127
128    /// Create an invalid inventory error
129    pub fn invalid_inventory(message: impl Into<String>) -> Self {
130        Self::InvalidInventory(message.into())
131    }
132
133    /// Create a playbook error
134    pub fn playbook_error(message: impl Into<String>) -> Self {
135        Self::PlaybookError(message.into())
136    }
137
138    /// Create an environment error
139    pub fn environment_error(message: impl Into<String>) -> Self {
140        Self::EnvironmentError(message.into())
141    }
142
143    /// Create a configuration error
144    pub fn config_error(message: impl Into<String>) -> Self {
145        Self::ConfigError(message.into())
146    }
147
148    /// Create an unsupported platform error
149    pub fn unsupported_platform(message: impl Into<String>) -> Self {
150        Self::UnsupportedPlatform(message.into())
151    }
152
153    /// Create a command not found error
154    pub fn command_not_found(message: impl Into<String>) -> Self {
155        Self::CommandNotFound(message.into())
156    }
157
158    /// Create a system requirement error
159    pub fn system_requirement(message: impl Into<String>) -> Self {
160        Self::SystemRequirement(message.into())
161    }
162
163    /// Create a parsing failed error
164    pub fn parsing_failed(message: impl Into<String>) -> Self {
165        Self::ConfigError(message.into())
166    }
167
168    /// Create an IO error
169    pub fn io_error(message: impl Into<String>) -> Self {
170        Self::ConfigError(message.into())
171    }
172}
173
174/// Type alias for Results with AnsibleError
175pub type Result<T> = std::result::Result<T, AnsibleError>;