Unverified Commit b6ab4ea8 authored by Zelda Hessler's avatar Zelda Hessler Committed by GitHub
Browse files

Fix inability to create service clients when `default-features = false` (#2055)



* add: tests for config/client construction when default features are disabled
fix: enable users to create service clients when default features are disabled
update: missing HTTP connector panic messages

* Apply suggestions from code review
Co-authored-by: default avatarJohn DiSanti <jdisanti@amazon.com>
parent 5dd5f3f8
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@ use std::sync::Arc;
// unused when all crate features are disabled
/// Unwrap an [`Option<DynConnector>`](aws_smithy_client::erase::DynConnector), and panic with a helpful error message if it's `None`
pub(crate) fn expect_connector(connector: Option<DynConnector>) -> DynConnector {
    connector.expect("A connector was not available. Either set a custom connector or enable the `rustls` and `native-tls` crate features.")
    connector.expect("No HTTP connector was available. Enable the `rustls` or `native-tls` crate feature or set a connector to fix this.")
}

#[cfg(any(feature = "rustls", feature = "native-tls"))]
+26 −4
Original line number Diff line number Diff line
@@ -158,13 +158,25 @@ private class AwsFluentClientExtensions(types: Types) {
            rustTemplate(
                """
                /// Creates a new client from an [SDK Config](#{aws_types}::sdk_config::SdkConfig).
                ##[cfg(any(feature = "rustls", feature = "native-tls"))]
                ///
                /// ## Panics
                ///
                /// - This method will panic if the `sdk_config` is missing an async sleep implementation. If you experience this panic, set
                ///     the `sleep_impl` on the Config passed into this function to fix it.
                /// - This method will panic if the `sdk_config` is missing an HTTP connector. If you experience this panic, set the
                ///     `http_connector` on the Config passed into this function to fix it.
                pub fn new(sdk_config: &#{aws_types}::sdk_config::SdkConfig) -> Self {
                    Self::from_conf(sdk_config.into())
                }

                /// Creates a new client from the service [`Config`](crate::Config).
                ##[cfg(any(feature = "rustls", feature = "native-tls"))]
                ///
                /// ## Panics
                ///
                /// - This method will panic if the `conf` is missing an async sleep implementation. If you experience this panic, set
                ///     the `sleep_impl` on the Config passed into this function to fix it.
                /// - This method will panic if the `conf` is missing an HTTP connector. If you experience this panic, set the
                ///     `http_connector` on the Config passed into this function to fix it.
                pub fn from_conf(conf: crate::Config) -> Self {
                    let retry_config = conf.retry_config().cloned().unwrap_or_else(#{RetryConfig}::disabled);
                    let timeout_config = conf.timeout_config().cloned().unwrap_or_else(#{TimeoutConfig}::disabled);
@@ -186,11 +198,21 @@ private class AwsFluentClientExtensions(types: Types) {
                    });

                    let builder = #{aws_smithy_client}::Builder::new();

                    let builder = match connector {
                        // Use provided connector
                        Some(c) => builder.connector(c),
                        None =>{
                            ##[cfg(any(feature = "rustls", feature = "native-tls"))]
                            {
                                // Use default connector based on enabled features
                        None => builder.dyn_https_connector(#{ConnectorSettings}::from_timeout_config(&timeout_config)),
                                builder.dyn_https_connector(#{ConnectorSettings}::from_timeout_config(&timeout_config))
                            }
                            ##[cfg(not(any(feature = "rustls", feature = "native-tls")))]
                            {
                                panic!("No HTTP connector was available. Enable the `rustls` or `native-tls` crate feature or set a connector to fix this.");
                            }
                        }
                    };
                    let mut builder = builder
                        .middleware(#{DynMiddleware}::new(#{Middleware}::new()))
+1 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ members = [
    "iam",
    "kms",
    "lambda",
    "no-default-features",
    "polly",
    "qldbsession",
    "s3",
+19 −0
Original line number Diff line number Diff line
# This Cargo.toml is unused in generated code. It exists solely to enable these tests to compile in-situ
[package]
name = "no-default-features"
version = "0.1.0"
authors = ["Zelda Hessler <zhessler@amazon.com>"]
description = """
These tests ensure that things will fail (or not fail) as expected
when default features are disabled for all SDK and runtime crates.
"""
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dev-dependencies]
aws-config = { path = "../../build/aws-sdk/sdk/aws-config", default-features = false }
aws-sdk-s3 = { path = "../../build/aws-sdk/sdk/s3", default-features = false }
futures = "0.3.25"
tokio = { version = "1.8.4", features = ["full", "test-util"] }
tracing-subscriber = { version = "0.3.15", features = ["env-filter"] }
+24 −0
Original line number Diff line number Diff line
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

// This will fail due to lack of a connector when constructing the SDK Config
#[tokio::test]
#[should_panic(
    expected = "No HTTP connector was available. Enable the `rustls` or `native-tls` crate feature or set a connector to fix this."
)]
async fn test_clients_from_sdk_config() {
    aws_config::load_from_env().await;
}

// This will fail due to lack of a connector when constructing the service client
#[test]
#[should_panic(
    expected = "No HTTP connector was available. Enable the `rustls` or `native-tls` crate feature or set a connector to fix this."
)]
fn test_clients_from_service_config() {
    let config = aws_sdk_s3::Config::builder().build();
    // This will panic due to the lack of an HTTP connector
    aws_sdk_s3::Client::from_conf(config);
}