Unverified Commit 346cdfe9 authored by Russell Cohen's avatar Russell Cohen Committed by GitHub
Browse files

Make async provide credentials async-trait compatible (#588)

parent 4002a740
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -14,3 +14,4 @@ zeroize = "1.2.0"
[dev-dependencies]
http = "0.2.3"
tokio = { version = "1.0", features = ["rt", "macros"] }
async-trait = "0.1.50"
+5 −2
Original line number Diff line number Diff line
@@ -72,13 +72,16 @@ impl AsyncMapRequest for CredentialsStage {

    fn apply(&self, mut request: Request) -> BoxFuture<Result<Request, Self::Error>> {
        Box::pin(async move {
            let cred_future = {
            let provider = {
                let config = request.config();
                let credential_provider = config
                    .get::<CredentialsProvider>()
                    .ok_or(CredentialsStageError::MissingCredentialsProvider)?;
                credential_provider.provide_credentials()
                // we need to enable releasing the config lock so that we don't hold the config
                // lock across an await point
                credential_provider.clone()
            };
            let cred_future = { provider.provide_credentials() };
            let credentials = cred_future.await?;
            request.config_mut().insert(credentials);
            Ok(request)
+38 −5
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ impl Error for CredentialsError {
}

pub type CredentialsResult = Result<Credentials, CredentialsError>;
type BoxFuture<T> = Pin<Box<dyn Future<Output = T> + Send>>;
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;

/// An asynchronous credentials provider
///
@@ -48,7 +48,9 @@ type BoxFuture<T> = Pin<Box<dyn Future<Output = T> + Send>>;
/// consider using [`async_provide_credentials_fn`] with a closure rather than directly implementing
/// this trait.
pub trait AsyncProvideCredentials: Send + Sync {
    fn provide_credentials(&self) -> BoxFuture<CredentialsResult>;
    fn provide_credentials<'a>(&'a self) -> BoxFuture<'a, CredentialsResult>
    where
        Self: 'a;
}

pub type CredentialsProvider = Arc<dyn AsyncProvideCredentials>;
@@ -66,7 +68,10 @@ where
    T: Fn() -> F + Send + Sync,
    F: Future<Output = CredentialsResult> + Send + 'static,
{
    fn provide_credentials(&self) -> BoxFuture<CredentialsResult> {
    fn provide_credentials<'a>(&'a self) -> BoxFuture<'a, CredentialsResult>
    where
        Self: 'a,
    {
        Box::pin((self.f)())
    }
}
@@ -81,9 +86,13 @@ where
/// use aws_auth::Credentials;
/// use aws_auth::provider::async_provide_credentials_fn;
///
/// async fn load_credentials() -> Credentials {
///     todo!()
/// }
///
/// async_provide_credentials_fn(|| async {
///     // Async process to retrieve credentials goes here
///     let credentials: Credentials = todo!().await?;
///     let credentials = load_credentials().await;
///     Ok(credentials)
/// });
/// ```
@@ -107,7 +116,10 @@ impl<T> AsyncProvideCredentials for T
where
    T: ProvideCredentials,
{
    fn provide_credentials(&self) -> BoxFuture<CredentialsResult> {
    fn provide_credentials<'a>(&'a self) -> BoxFuture<'a, CredentialsResult>
    where
        Self: 'a,
    {
        let result = self.provide_credentials();
        Box::pin(future::ready(result))
    }
@@ -130,7 +142,9 @@ pub fn set_provider(config: &mut PropertyBag, provider: Arc<dyn AsyncProvideCred

#[cfg(test)]
mod test {
    use crate::provider::{AsyncProvideCredentials, BoxFuture, CredentialsResult};
    use crate::Credentials;
    use async_trait::async_trait;

    fn assert_send_sync<T: Send + Sync>() {}

@@ -138,4 +152,23 @@ mod test {
    fn creds_are_send_sync() {
        assert_send_sync::<Credentials>()
    }

    #[async_trait]
    trait AnotherTrait: Send + Sync {
        async fn creds(&self) -> Credentials;
    }

    struct AnotherTraitWrapper<T> {
        inner: T,
    }

    impl<T: AnotherTrait> AsyncProvideCredentials for AnotherTraitWrapper<T> {
        fn provide_credentials<'a>(&'a self) -> BoxFuture<'a, CredentialsResult>
        where
            Self: 'a,
        {
            let inner_fut = self.inner.creds();
            Box::pin(async move { Ok(inner_fut.await) })
        }
    }
}