mountpoint_s3_client/
instance_info.rs1use std::cell::LazyCell;
5use std::env;
6
7use thiserror::Error;
8
9use crate::imds_crt_client::{IdentityDocument, ImdsCrtClient, ImdsQueryRequestError};
10
11#[derive(Debug)]
14pub struct InstanceInfo {
15 document: LazyCell<Result<IdentityDocument, InstanceInfoError>>,
16}
17
18impl InstanceInfo {
19 pub fn new() -> Self {
22 Self {
23 document: LazyCell::new(|| {
24 if !imds_disabled() {
25 match retrieve_instance_identity_document() {
26 Ok(identity_document) => {
27 tracing::debug!(?identity_document, "got instance info from IMDS");
28 Ok(identity_document)
29 }
30 Err(err) => {
31 tracing::debug!("EC2 instance info not retrieved: {err:?}");
32 Err(err)
33 }
34 }
35 } else {
36 tracing::debug!("EC2 instance info not retrieved: IMDS was disabled");
37 Err(InstanceInfoError::ImdsDisabled)
38 }
39 }),
40 }
41 }
42
43 pub fn region(&self) -> Result<&str, &InstanceInfoError> {
45 self.document.as_ref().map(|d| d.region.as_str())
46 }
47
48 pub fn instance_type(&self) -> Result<&str, &InstanceInfoError> {
50 self.document.as_ref().map(|d| d.instance_type.as_str())
51 }
52}
53
54impl Default for InstanceInfo {
55 fn default() -> Self {
56 Self::new()
57 }
58}
59
60fn retrieve_instance_identity_document() -> Result<IdentityDocument, InstanceInfoError> {
61 let imds_crt_client = ImdsCrtClient::new().map_err(InstanceInfoError::ImdsClientFailed)?;
62
63 let identity_document = futures::executor::block_on(imds_crt_client.get_identity_document())?;
64 Ok(identity_document)
65}
66
67fn imds_disabled() -> bool {
68 match env::var_os("AWS_EC2_METADATA_DISABLED") {
69 Some(val) => !val.eq_ignore_ascii_case("false"),
70 None => false,
71 }
72}
73
74#[derive(Debug, Error)]
76pub enum InstanceInfoError {
77 #[error("IMDS is disabled")]
79 ImdsDisabled,
80
81 #[error("IMDS query failed: {0}")]
83 ImdsQueryFailed(#[from] ImdsQueryRequestError),
84
85 #[error("could not construct IMDS client: {0}")]
87 ImdsClientFailed(mountpoint_s3_crt::common::error::Error),
88}