aws_config/imds/client/
error.rs1use aws_smithy_runtime_api::client::orchestrator::HttpResponse;
9use aws_smithy_runtime_api::client::result::SdkError;
10use std::error::Error;
11use std::fmt;
12
13#[derive(Debug)]
15pub struct FailedToLoadToken {
16 source: SdkError<TokenError, HttpResponse>,
17}
18
19impl FailedToLoadToken {
20 pub fn is_dispatch_failure(&self) -> bool {
22 matches!(self.source, SdkError::DispatchFailure(_))
23 }
24
25 pub(crate) fn into_source(self) -> SdkError<TokenError, HttpResponse> {
26 self.source
27 }
28}
29
30#[derive(Debug)]
32pub struct ErrorResponse {
33 raw: HttpResponse,
34}
35
36impl ErrorResponse {
37 pub fn response(&self) -> &HttpResponse {
39 &self.raw
40 }
41}
42
43#[derive(Debug)]
45pub struct IoError {
46 source: Box<dyn Error + Send + Sync + 'static>,
47}
48
49#[derive(Debug)]
51pub struct Unexpected {
52 source: Box<dyn Error + Send + Sync + 'static>,
53}
54
55#[derive(Debug)]
57#[non_exhaustive]
58pub enum ImdsError {
59 FailedToLoadToken(FailedToLoadToken),
64
65 ErrorResponse(ErrorResponse),
67
68 IoError(IoError),
72
73 Unexpected(Unexpected),
75}
76
77impl ImdsError {
78 pub(super) fn failed_to_load_token(source: SdkError<TokenError, HttpResponse>) -> Self {
79 Self::FailedToLoadToken(FailedToLoadToken { source })
80 }
81
82 pub(super) fn error_response(raw: HttpResponse) -> Self {
83 Self::ErrorResponse(ErrorResponse { raw })
84 }
85
86 pub(super) fn io_error(source: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self {
87 Self::IoError(IoError {
88 source: source.into(),
89 })
90 }
91
92 pub(super) fn unexpected(source: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self {
93 Self::Unexpected(Unexpected {
94 source: source.into(),
95 })
96 }
97}
98
99impl fmt::Display for ImdsError {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 match self {
102 ImdsError::FailedToLoadToken(_) => {
103 write!(f, "failed to load IMDS session token")
104 }
105 ImdsError::ErrorResponse(context) => write!(
106 f,
107 "error response from IMDS (code: {}). {:?}",
108 context.raw.status().as_u16(),
109 context.raw
110 ),
111 ImdsError::IoError(_) => {
112 write!(f, "an IO error occurred communicating with IMDS")
113 }
114 ImdsError::Unexpected(_) => {
115 write!(f, "an unexpected error occurred communicating with IMDS",)
116 }
117 }
118 }
119}
120
121impl Error for ImdsError {
122 fn source(&self) -> Option<&(dyn Error + 'static)> {
123 match &self {
124 ImdsError::FailedToLoadToken(context) => Some(&context.source),
125 ImdsError::IoError(context) => Some(context.source.as_ref()),
126 ImdsError::Unexpected(context) => Some(context.source.as_ref()),
127 ImdsError::ErrorResponse(_) => None,
128 }
129 }
130}
131
132#[derive(Debug)]
133pub(super) enum InnerImdsError {
134 BadStatus,
135 InvalidUtf8,
136}
137
138impl fmt::Display for InnerImdsError {
139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
140 match self {
141 InnerImdsError::BadStatus => write!(f, "failing status code returned from IMDS"),
142 InnerImdsError::InvalidUtf8 => write!(f, "IMDS did not return valid UTF-8"),
143 }
144 }
145}
146
147impl Error for InnerImdsError {}
148
149#[derive(Debug)]
151pub struct InvalidEndpointMode {
152 mode: String,
153}
154
155impl InvalidEndpointMode {
156 pub(super) fn new(mode: impl Into<String>) -> Self {
157 Self { mode: mode.into() }
158 }
159}
160
161impl fmt::Display for InvalidEndpointMode {
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 write!(
164 f,
165 "`{}` is not a valid endpoint mode. Valid values are [`IPv4`, `IPv6`]",
166 &self.mode
167 )
168 }
169}
170
171impl Error for InvalidEndpointMode {}
172
173#[derive(Debug)]
174#[allow(clippy::enum_variant_names)]
175enum BuildErrorKind {
176 InvalidEndpointMode(InvalidEndpointMode),
178
179 InvalidEndpointUri(Box<dyn Error + Send + Sync + 'static>),
181}
182
183#[derive(Debug)]
185pub struct BuildError {
186 kind: BuildErrorKind,
187}
188
189impl BuildError {
190 pub(super) fn invalid_endpoint_mode(source: InvalidEndpointMode) -> Self {
191 Self {
192 kind: BuildErrorKind::InvalidEndpointMode(source),
193 }
194 }
195
196 pub(super) fn invalid_endpoint_uri(
197 source: impl Into<Box<dyn Error + Send + Sync + 'static>>,
198 ) -> Self {
199 Self {
200 kind: BuildErrorKind::InvalidEndpointUri(source.into()),
201 }
202 }
203}
204
205impl fmt::Display for BuildError {
206 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
207 use BuildErrorKind::*;
208 write!(f, "failed to build IMDS client: ")?;
209 match self.kind {
210 InvalidEndpointMode(_) => write!(f, "invalid endpoint mode"),
211 InvalidEndpointUri(_) => write!(f, "invalid URI"),
212 }
213 }
214}
215
216impl Error for BuildError {
217 fn source(&self) -> Option<&(dyn Error + 'static)> {
218 use BuildErrorKind::*;
219 match &self.kind {
220 InvalidEndpointMode(e) => Some(e),
221 InvalidEndpointUri(e) => Some(e.as_ref()),
222 }
223 }
224}
225
226#[derive(Debug)]
227pub(super) enum TokenErrorKind {
228 InvalidToken,
232
233 NoTtl,
237
238 InvalidTtl,
242
243 InvalidParameters,
247
248 Forbidden,
252}
253
254#[derive(Debug)]
256pub struct TokenError {
257 kind: TokenErrorKind,
258}
259
260impl fmt::Display for TokenError {
261 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262 use TokenErrorKind::*;
263 match self.kind {
264 InvalidToken => write!(f, "invalid token"),
265 NoTtl => write!(f, "token response did not contain a TTL header"),
266 InvalidTtl => write!(f, "the returned TTL was invalid"),
267 InvalidParameters => {
268 write!(f, "invalid request parameters. This indicates an SDK bug.")
269 }
270 Forbidden => write!(
271 f,
272 "request forbidden: IMDS is disabled or the caller has insufficient permissions."
273 ),
274 }
275 }
276}
277
278impl Error for TokenError {}
279
280impl From<TokenErrorKind> for TokenError {
281 fn from(kind: TokenErrorKind) -> Self {
282 Self { kind }
283 }
284}