tustvold commented on code in PR #4161:
URL: https://github.com/apache/arrow-rs/pull/4161#discussion_r1181472471
##########
object_store/src/aws/profile.rs:
##########
@@ -0,0 +1,99 @@
+#![cfg(feature = "aws_profile")]
+
+use aws_config::profile::ProfileFileCredentialsProvider;
+use aws_config::provider_config::ProviderConfig;
+use aws_credential_types::provider::ProvideCredentials;
+use aws_types::region::Region;
+use futures::future::BoxFuture;
+use std::sync::Arc;
+use std::time::Instant;
+use std::time::SystemTime;
+
+use super::credential::CredentialProvider;
+use crate::aws::AwsCredential;
+use crate::client::token::{TemporaryToken, TokenCache};
+use crate::Result;
+
+#[derive(Debug)]
+pub struct ProfileProvider {
+ name: String,
+ region: Option<String>,
+ cache: TokenCache<Arc<AwsCredential>>,
+}
+
+impl ProfileProvider {
+ pub fn new(name: String, region: Option<String>) -> Self {
+ Self {
+ name,
+ region,
+ cache: Default::default(),
+ }
+ }
+}
+
+impl CredentialProvider for ProfileProvider {
+ fn get_credential(&self) -> BoxFuture<'_, Result<Arc<AwsCredential>>> {
+ Box::pin(self.cache.get_or_insert_with(move || async move {
+ let region = match self.region.clone() {
+ Some(r) => Some(Region::new(r)),
+ None => None,
+ };
+
+ let config = ProviderConfig::default().with_region(region);
+
+ let credentials = ProfileFileCredentialsProvider::builder()
+ .configure(&config)
+ .profile_name(&self.name)
+ .build();
+
+ let c = credentials.provide_credentials().await.map_err(|source| {
+ crate::Error::Generic {
+ store: "S3",
+ source: Box::new(source),
+ }
+ })?;
+ let t_now = SystemTime::now();
+ let expiry = c
+ .expiry()
+ .and_then(|e| e.duration_since(t_now).ok())
+ .map(|ttl| Instant::now() + ttl);
+
+ Ok(TemporaryToken {
+ token: Arc::new(AwsCredential {
+ key_id: c.access_key_id().to_string(),
+ secret_key: c.secret_access_key().to_string(),
+ token: c.session_token().map(ToString::to_string),
+ }),
+ expiry,
+ })
+ }))
+ }
+}
+
+#[cfg(not(test))]
+mod region {
+ use super::*;
+ use crate::aws::region::RegionProvider;
+ use aws_config::meta::region::ProvideRegion;
+ use aws_config::profile::region::Builder as ProfileRegionBuilder;
+
+ impl RegionProvider for ProfileProvider {
+ #[tokio::main(flavor = "current_thread")]
Review Comment:
This will spawn a tokio runtime per request, perhaps we could use the
BoxFuture approach used by CredentialProvider?
##########
object_store/src/aws/region.rs:
##########
@@ -0,0 +1,3 @@
+pub trait RegionProvider {
Review Comment:
This new file will need a license header, this is what RAT is complaining
about.
Tbh given how small it is, it might not even warrant its own module
##########
object_store/src/aws/mod.rs:
##########
@@ -1563,3 +1591,64 @@ mod tests {
}
}
}
+
+#[cfg(all(test, feature = "aws_profile"))]
+mod profile_tests {
+ use super::*;
+ use profile::ProfileProvider;
+ use region::RegionProvider;
+ use std::env;
+
+ impl RegionProvider for ProfileProvider {
+ fn get_region(&self) -> Option<String> {
Review Comment:
I can't help feeling this formulation doesn't really test the region
inference logic? Is there some way to create a fake profile for testing
purposes?
Perhaps
https://docs.rs/aws-config/latest/aws_config/profile/profile_file/struct.ProfileFiles.html
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]