AWS SDK

AWS SDK

rev. cfbc45257ca5184ce76d3ab47374cc3ec29771e2

Files changed:

tmp-codegen-diff/aws-sdk/sdk/aws-config/Cargo.toml

@@ -39,39 +99,99 @@
   59     59   
path = "../aws-smithy-http"
   60     60   
version = "0.62.3"
   61     61   
   62     62   
[dependencies.aws-smithy-json]
   63     63   
path = "../aws-smithy-json"
   64     64   
version = "0.61.4"
   65     65   
   66     66   
[dependencies.aws-smithy-runtime]
   67     67   
path = "../aws-smithy-runtime"
   68     68   
features = ["client"]
   69         -
version = "1.9.0"
          69  +
version = "1.9.1"
   70     70   
   71     71   
[dependencies.aws-smithy-runtime-api]
   72     72   
path = "../aws-smithy-runtime-api"
   73     73   
features = ["client"]
   74     74   
version = "1.9.0"
   75     75   
   76     76   
[dependencies.aws-smithy-types]
   77     77   
path = "../aws-smithy-types"
   78     78   
version = "1.3.2"
   79     79   
@@ -106,106 +157,157 @@
  126    126   
version = "1.2.5"
  127    127   
  128    128   
[dev-dependencies.aws-smithy-http-client]
  129    129   
path = "../aws-smithy-http-client"
  130    130   
features = ["default-client", "test-util"]
  131    131   
version = "1.1.0"
  132    132   
  133    133   
[dev-dependencies.aws-smithy-runtime]
  134    134   
path = "../aws-smithy-runtime"
  135    135   
features = ["client", "test-util"]
  136         -
version = "1.9.0"
         136  +
version = "1.9.1"
  137    137   
  138    138   
[dev-dependencies.aws-smithy-runtime-api]
  139    139   
path = "../aws-smithy-runtime-api"
  140    140   
features = ["test-util"]
  141    141   
version = "1.9.0"
  142    142   
  143    143   
[dev-dependencies.futures-util]
  144    144   
version = "0.3.29"
  145    145   
default-features = false
  146    146   

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/Cargo.toml

@@ -28,28 +88,88 @@
   48     48   
optional = true
   49     49   
version = "0.60.11"
   50     50   
   51     51   
[dependencies.aws-smithy-http]
   52     52   
path = "../aws-smithy-http"
   53     53   
version = "0.62.3"
   54     54   
   55     55   
[dependencies.aws-smithy-runtime]
   56     56   
path = "../aws-smithy-runtime"
   57     57   
features = ["client"]
   58         -
version = "1.9.0"
          58  +
version = "1.9.1"
   59     59   
   60     60   
[dependencies.aws-smithy-runtime-api]
   61     61   
path = "../aws-smithy-runtime-api"
   62     62   
features = ["client"]
   63     63   
version = "1.9.0"
   64     64   
   65     65   
[dependencies.aws-smithy-types]
   66     66   
path = "../aws-smithy-types"
   67     67   
version = "1.3.2"
   68     68   

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-mocks/Cargo.toml

@@ -14,14 +0,44 @@
   34     34   
features = ["full"]
   35     35   
   36     36   
[dev-dependencies.aws-smithy-async]
   37     37   
path = "../aws-smithy-async"
   38     38   
features = ["rt-tokio"]
   39     39   
version = "1.2.5"
   40     40   
   41     41   
[dev-dependencies.aws-smithy-runtime]
   42     42   
path = "../aws-smithy-runtime"
   43     43   
features = ["client"]
   44         -
version = "1.9.0"
          44  +
version = "1.9.1"

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/Cargo.toml

@@ -1,1 +94,98 @@
    1      1   
# Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
    2      2   
[package]
    3      3   
name = "aws-smithy-runtime"
    4         -
version = "1.9.0"
           4  +
version = "1.9.1"
    5      5   
authors = ["AWS Rust SDK Team <aws-sdk-rust@amazon.com>", "Zelda Hessler <zhessler@amazon.com>"]
    6      6   
description = "The new smithy runtime crate"
    7      7   
edition = "2021"
    8      8   
license = "Apache-2.0"
    9      9   
repository = "https://github.com/smithy-lang/smithy-rs"
   10     10   
[package.metadata.docs.rs]
   11     11   
all-features = true
   12     12   
targets = ["x86_64-unknown-linux-gnu"]
   13     13   
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
   14     14   
rustdoc-args = ["--cfg", "docsrs"]
   15     15   
   16     16   
[package.metadata.smithy-rs-release-tooling]
   17     17   
stable = true
   18     18   
[package.metadata.cargo-udeps.ignore]
   19     19   
normal = ["aws-smithy-http"]
   20     20   
   21     21   
[features]
   22     22   
client = ["aws-smithy-runtime-api/client", "aws-smithy-types/http-body-1-x"]
   23     23   
http-auth = ["aws-smithy-runtime-api/http-auth"]
   24     24   
connector-hyper-0-14-x = ["dep:aws-smithy-http-client", "aws-smithy-http-client?/hyper-014"]
   25     25   
tls-rustls = ["dep:aws-smithy-http-client", "aws-smithy-http-client?/legacy-rustls-ring", "connector-hyper-0-14-x"]
   26     26   
default-https-client = ["dep:aws-smithy-http-client", "aws-smithy-http-client?/rustls-aws-lc"]
   27         -
rt-tokio = ["tokio/rt"]
          27  +
rt-tokio = ["tokio/rt", "hickory-resolver"]
   28     28   
test-util = ["aws-smithy-runtime-api/test-util", "dep:tracing-subscriber", "aws-smithy-http-client/test-util", "legacy-test-util"]
   29     29   
legacy-test-util = ["aws-smithy-runtime-api/test-util", "dep:tracing-subscriber", "aws-smithy-http-client/test-util", "connector-hyper-0-14-x", "aws-smithy-http-client/legacy-test-util"]
   30     30   
wire-mock = ["legacy-test-util", "aws-smithy-http-client/wire-mock"]
   31     31   
   32     32   
[dependencies]
   33     33   
bytes = "1.10.0"
   34     34   
fastrand = "2.3.0"
   35     35   
pin-project-lite = "0.2.14"
   36     36   
pin-utils = "0.1.0"
   37     37   
tracing = "0.1.40"
   38     38   
   39     39   
[dependencies.aws-smithy-async]
   40     40   
path = "../aws-smithy-async"
   41     41   
version = "1.2.5"
   42     42   
   43     43   
[dependencies.aws-smithy-http]
   44     44   
path = "../aws-smithy-http"
   45     45   
version = "0.62.3"
   46     46   
   47     47   
[dependencies.aws-smithy-observability]
   48     48   
path = "../aws-smithy-observability"
   49     49   
version = "0.1.3"
   50     50   
   51     51   
[dependencies.aws-smithy-runtime-api]
   52     52   
path = "../aws-smithy-runtime-api"
   53     53   
version = "1.9.0"
   54     54   
   55     55   
[dependencies.aws-smithy-types]
   56     56   
path = "../aws-smithy-types"
   57     57   
features = ["http-body-0-4-x"]
   58     58   
version = "1.3.2"
   59     59   
   60     60   
[dependencies.aws-smithy-http-client]
   61     61   
path = "../aws-smithy-http-client"
   62     62   
optional = true
   63     63   
version = "1.1.0"
   64     64   
          65  +
[dependencies.hickory-resolver]
          66  +
version = "0.25.2"
          67  +
optional = true
          68  +
   65     69   
[dependencies.http-02x]
   66     70   
package = "http"
   67     71   
version = "0.2.9"
   68     72   
   69     73   
[dependencies.http-1x]
   70     74   
package = "http"
   71     75   
version = "1"
   72     76   
   73     77   
[dependencies.http-body-04x]
   74     78   
package = "http-body"

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/client/dns.rs

@@ -1,1 +0,18 @@
    1      1   
/*
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
    6      6   
//! Built-in DNS resolver implementations.
    7      7   
    8      8   
#[cfg(all(feature = "rt-tokio", not(target_family = "wasm")))]
    9         -
mod tokio {
   10         -
    use aws_smithy_runtime_api::client::dns::{DnsFuture, ResolveDns, ResolveDnsError};
   11         -
    use std::io::{Error as IoError, ErrorKind as IoErrorKind};
   12         -
    use std::net::ToSocketAddrs;
           9  +
mod tokio;
   13     10   
   14         -
    /// DNS resolver that uses `tokio::spawn_blocking` to resolve DNS using the standard library.
   15         -
    ///
   16         -
    /// This implementation isn't available for WASM targets.
   17         -
    #[non_exhaustive]
   18         -
    #[derive(Debug, Default)]
   19         -
    pub struct TokioDnsResolver;
   20         -
   21         -
    impl TokioDnsResolver {
   22         -
        /// Creates a new Tokio DNS resolver
   23         -
        pub fn new() -> Self {
   24         -
            Self
   25         -
        }
   26         -
    }
          11  +
#[cfg(all(feature = "rt-tokio", not(target_family = "wasm")))]
          12  +
pub use self::tokio::TokioDnsResolver;
   27     13   
   28         -
    impl ResolveDns for TokioDnsResolver {
   29         -
        fn resolve_dns<'a>(&'a self, name: &'a str) -> DnsFuture<'a> {
   30         -
            let name = name.to_string();
   31         -
            DnsFuture::new(async move {
   32         -
                let result = tokio::task::spawn_blocking(move || (name, 0).to_socket_addrs()).await;
   33         -
                match result {
   34         -
                    Err(join_failure) => Err(ResolveDnsError::new(IoError::new(
   35         -
                        IoErrorKind::Other,
   36         -
                        join_failure,
   37         -
                    ))),
   38         -
                    Ok(Ok(dns_result)) => {
   39         -
                        Ok(dns_result.into_iter().map(|addr| addr.ip()).collect())
   40         -
                    }
   41         -
                    Ok(Err(dns_failure)) => Err(ResolveDnsError::new(dns_failure)),
   42         -
                }
   43         -
            })
   44         -
        }
   45         -
    }
   46         -
}
          14  +
#[cfg(all(feature = "rt-tokio", not(target_family = "wasm")))]
          15  +
mod caching;
   47     16   
   48     17   
#[cfg(all(feature = "rt-tokio", not(target_family = "wasm")))]
   49         -
pub use self::tokio::TokioDnsResolver;
          18  +
pub use self::caching::CachingDnsResolver;

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/client/dns/caching.rs

@@ -0,1 +0,159 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
use std::{
           7  +
    io::{Error as IoError, ErrorKind as IoErrorKind},
           8  +
    net::IpAddr,
           9  +
    time::Duration,
          10  +
};
          11  +
          12  +
use aws_smithy_runtime_api::client::dns::{DnsFuture, ResolveDns, ResolveDnsError};
          13  +
use hickory_resolver::{
          14  +
    config::{NameServerConfigGroup, ResolverConfig},
          15  +
    name_server::TokioConnectionProvider,
          16  +
    Resolver,
          17  +
};
          18  +
          19  +
/// DNS resolver that uses [hickory_resolver] and caches DNS entries in memory.
          20  +
///
          21  +
/// This resolver requires a [tokio] runtime to function and isn't available for WASM targets.
          22  +
#[non_exhaustive]
          23  +
#[derive(Debug)]
          24  +
pub struct CachingDnsResolver {
          25  +
    resolver: Resolver<TokioConnectionProvider>,
          26  +
}
          27  +
          28  +
impl Default for CachingDnsResolver {
          29  +
    /// Constructs a new Tokio based [ResolveDns] with the system configuration.
          30  +
    /// This uses `/etc/resolv.conf` on Unix OSes and registry settings on Windows.
          31  +
    fn default() -> Self {
          32  +
        Self {
          33  +
            resolver: Resolver::builder_tokio().expect("In tokio runtime").build(),
          34  +
        }
          35  +
    }
          36  +
}
          37  +
          38  +
impl CachingDnsResolver {
          39  +
    /// Creates a new DNS resolver that caches IP addresses in memory.
          40  +
    pub fn builder() -> CachingDnsResolverBuilder {
          41  +
        CachingDnsResolverBuilder {
          42  +
            nameservers: None,
          43  +
            timeout: None,
          44  +
            attempts: None,
          45  +
            cache_size: None,
          46  +
            num_concurrent_reqs: None,
          47  +
        }
          48  +
    }
          49  +
          50  +
    /// Flush the cache
          51  +
    pub fn clear_cache(&self) {
          52  +
        self.resolver.clear_cache();
          53  +
    }
          54  +
}
          55  +
          56  +
impl ResolveDns for CachingDnsResolver {
          57  +
    fn resolve_dns<'a>(&'a self, name: &'a str) -> DnsFuture<'a> {
          58  +
        DnsFuture::new(async move {
          59  +
            let result = self.resolver.lookup_ip(name).await;
          60  +
          61  +
            match result {
          62  +
                Ok(ips) => Ok(ips.into_iter().collect()),
          63  +
                Err(failure) => Err(ResolveDnsError::new(IoError::new(
          64  +
                    IoErrorKind::Other,
          65  +
                    failure,
          66  +
                ))),
          67  +
            }
          68  +
        })
          69  +
    }
          70  +
}
          71  +
          72  +
pub struct CachingDnsResolverBuilder {
          73  +
    nameservers: Option<Nameservers>,
          74  +
    timeout: Option<Duration>,
          75  +
    attempts: Option<usize>,
          76  +
    cache_size: Option<usize>,
          77  +
    num_concurrent_reqs: Option<usize>,
          78  +
}
          79  +
          80  +
struct Nameservers {
          81  +
    ips: Vec<IpAddr>,
          82  +
    port: u16,
          83  +
}
          84  +
          85  +
impl CachingDnsResolverBuilder {
          86  +
    /// Configure upstream nameservers to use for resolution. Defaults to the system
          87  +
    /// configuration.
          88  +
    pub fn nameservers(mut self, ips: &[IpAddr], port: u16) -> Self {
          89  +
        self.nameservers = Some(Nameservers {
          90  +
            ips: ips.to_vec(),
          91  +
            port,
          92  +
        });
          93  +
        self
          94  +
    }
          95  +
          96  +
    /// Specify the timeout for a request. Defaults to 5 seconds.
          97  +
    pub fn timeout(mut self, timeout: Duration) -> Self {
          98  +
        self.timeout = Some(timeout);
          99  +
        self
         100  +
    }
         101  +
         102  +
    /// Number of retries after lookup failure before giving up. Defaults to 2.
         103  +
    pub fn attempts(mut self, attempts: usize) -> Self {
         104  +
        self.attempts = Some(attempts);
         105  +
        self
         106  +
    }
         107  +
         108  +
    /// Cache size is in number of records (some records can be large). Defaults to 32.
         109  +
    /// Note: cache items are not evicted by new items, they are only evicted when their
         110  +
    /// TTL expires.
         111  +
    pub fn cache_size(mut self, cache_size: usize) -> Self {
         112  +
        self.cache_size = Some(cache_size);
         113  +
        self
         114  +
    }
         115  +
         116  +
    /// Number of concurrent requests per query.
         117  +
    ///
         118  +
    /// Where more than one nameserver is configured, this configures the resolver
         119  +
    /// to send queries to a number of servers in parallel. Defaults to 2. Setting
         120  +
    /// to 0 or 1 will execute requests serially.
         121  +
    pub fn num_concurrent_reqs(mut self, num_concurrent_reqs: usize) -> Self {
         122  +
        self.num_concurrent_reqs = Some(num_concurrent_reqs);
         123  +
        self
         124  +
    }
         125  +
         126  +
    pub fn build(self) -> CachingDnsResolver {
         127  +
        let mut builder = if let Some(nameservers) = self.nameservers {
         128  +
            let nameserver_config =
         129  +
                NameServerConfigGroup::from_ips_clear(&nameservers.ips, nameservers.port, true);
         130  +
            let resolver_config = ResolverConfig::from_parts(None, vec![], nameserver_config);
         131  +
         132  +
            Resolver::builder_with_config(resolver_config, TokioConnectionProvider::default())
         133  +
        } else {
         134  +
            Resolver::builder_tokio().expect("Successfully read system config")
         135  +
        };
         136  +
         137  +
        let opts = builder.options_mut();
         138  +
         139  +
        if let Some(timeout) = self.timeout {
         140  +
            opts.timeout = timeout;
         141  +
        }
         142  +
         143  +
        if let Some(attempts) = self.attempts {
         144  +
            opts.attempts = attempts;
         145  +
        }
         146  +
         147  +
        if let Some(cache_size) = self.cache_size {
         148  +
            opts.cache_size = cache_size;
         149  +
        }
         150  +
         151  +
        if let Some(num_concurrent_reqs) = self.num_concurrent_reqs {
         152  +
            opts.num_concurrent_reqs = num_concurrent_reqs;
         153  +
        }
         154  +
         155  +
        CachingDnsResolver {
         156  +
            resolver: builder.build(),
         157  +
        }
         158  +
    }
         159  +
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/src/client/dns/tokio.rs

@@ -0,1 +0,39 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
use aws_smithy_runtime_api::client::dns::{DnsFuture, ResolveDns, ResolveDnsError};
           7  +
use std::io::{Error as IoError, ErrorKind as IoErrorKind};
           8  +
use std::net::ToSocketAddrs;
           9  +
          10  +
/// DNS resolver that uses `tokio::spawn_blocking` to resolve DNS using the standard library.
          11  +
///
          12  +
/// This implementation isn't available for WASM targets.
          13  +
#[non_exhaustive]
          14  +
#[derive(Debug, Default)]
          15  +
pub struct TokioDnsResolver;
          16  +
          17  +
impl TokioDnsResolver {
          18  +
    /// Creates a new Tokio DNS resolver
          19  +
    pub fn new() -> Self {
          20  +
        Self
          21  +
    }
          22  +
}
          23  +
          24  +
impl ResolveDns for TokioDnsResolver {
          25  +
    fn resolve_dns<'a>(&'a self, name: &'a str) -> DnsFuture<'a> {
          26  +
        let name = name.to_string();
          27  +
        DnsFuture::new(async move {
          28  +
            let result = tokio::task::spawn_blocking(move || (name, 0).to_socket_addrs()).await;
          29  +
            match result {
          30  +
                Err(join_failure) => Err(ResolveDnsError::new(IoError::new(
          31  +
                    IoErrorKind::Other,
          32  +
                    join_failure,
          33  +
                ))),
          34  +
                Ok(Ok(dns_result)) => Ok(dns_result.into_iter().map(|addr| addr.ip()).collect()),
          35  +
                Ok(Err(dns_failure)) => Err(ResolveDnsError::new(dns_failure)),
          36  +
            }
          37  +
        })
          38  +
    }
          39  +
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-runtime/tests/dns_caching.rs

@@ -0,1 +0,309 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
#![cfg(all(feature = "client", feature = "rt-tokio",))]
           7  +
           8  +
use aws_smithy_runtime::client::dns::CachingDnsResolver;
           9  +
use aws_smithy_runtime_api::client::dns::ResolveDns;
          10  +
use std::{
          11  +
    collections::HashMap,
          12  +
    net::{IpAddr, Ipv4Addr},
          13  +
    time::Instant,
          14  +
};
          15  +
use tokio::test;
          16  +
          17  +
// Note: I couldn't come up with a way to mock the DNS returns to hickory so these
          18  +
// tests actually hit the network. We should ideally find a better way to do this.
          19  +
          20  +
#[test]
          21  +
async fn test_dns_caching_performance() {
          22  +
    let resolver = CachingDnsResolver::default();
          23  +
    let hostname = "example.com";
          24  +
          25  +
    // First resolution should hit the network
          26  +
    let start = Instant::now();
          27  +
    let first_result = resolver.resolve_dns(hostname).await;
          28  +
    let first_duration = start.elapsed();
          29  +
          30  +
    let first_ips = first_result.unwrap();
          31  +
    assert!(!first_ips.is_empty());
          32  +
          33  +
    // Second resolution should hit the cache
          34  +
    let start = Instant::now();
          35  +
    let second_result = resolver.resolve_dns(hostname).await;
          36  +
    let second_duration = start.elapsed();
          37  +
          38  +
    let second_ips = second_result.unwrap();
          39  +
          40  +
    // Verify same IPs returned
          41  +
    assert_eq!(first_ips, second_ips);
          42  +
          43  +
    // Cache hit should be faster
          44  +
    assert!(second_duration < first_duration);
          45  +
}
          46  +
          47  +
#[test]
          48  +
#[tracing_test::traced_test]
          49  +
async fn test_dns_cache_size_limit() {
          50  +
    let mut records = HashMap::new();
          51  +
    records.insert(
          52  +
        "example.com".to_string(),
          53  +
        IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4)),
          54  +
    );
          55  +
    records.insert("aws.com".to_string(), IpAddr::V4(Ipv4Addr::new(5, 6, 7, 8)));
          56  +
          57  +
    let dns_server = test_dns_server::TestDnsServer::start(records)
          58  +
        .await
          59  +
        .unwrap();
          60  +
          61  +
    let (dns_ip, dns_port) = dns_server.addr();
          62  +
    println!("DNS_IP: {dns_ip:#?}, DNS_PORT: {dns_port:#?}");
          63  +
    let resolver = CachingDnsResolver::builder()
          64  +
        .nameservers(&[dns_ip], dns_port)
          65  +
        .cache_size(1)
          66  +
        .build();
          67  +
          68  +
    // Resolve first hostname
          69  +
    let result1 = resolver.resolve_dns("example.com").await;
          70  +
    // assert!(result1.is_ok());
          71  +
          72  +
    // Resolve second hostname (should not be placed into cache because result1 is already occupying
          73  +
    // the single allocated space and entries are only evicted from the cache when their TTL expires)
          74  +
    let result2 = resolver.resolve_dns("aws.com").await;
          75  +
    // assert!(result2.is_ok());
          76  +
          77  +
    println!("RESULT1: {result1:#?}");
          78  +
    println!("RESULT2: {result2:#?}");
          79  +
          80  +
    let start = Instant::now();
          81  +
    let result2_again = resolver.resolve_dns("aws.com").await;
          82  +
    let result2_again_duration = start.elapsed();
          83  +
          84  +
    let start = Instant::now();
          85  +
    let result1_again = resolver.resolve_dns("example.com").await;
          86  +
    let result1_again_duration = start.elapsed();
          87  +
          88  +
    assert!(result1_again.is_ok());
          89  +
    assert!(result2_again.is_ok());
          90  +
          91  +
    // result1_again should be resolved more quickly than result2_again
          92  +
    println!("result1_again_duration: {:?}", result1_again_duration);
          93  +
    println!("result2_again_duration: {:?}", result2_again_duration);
          94  +
    assert!(result1_again_duration < result2_again_duration);
          95  +
}
          96  +
          97  +
#[test]
          98  +
async fn test_dns_error_handling() {
          99  +
    let resolver = CachingDnsResolver::default();
         100  +
         101  +
    // Try to resolve an invalid hostname
         102  +
    let result = resolver
         103  +
        .resolve_dns("invalid.nonexistent.domain.test")
         104  +
        .await;
         105  +
    assert!(result.is_err());
         106  +
}
         107  +
// Test utility for creating a local DNS server
         108  +
#[cfg(test)]
         109  +
mod test_dns_server {
         110  +
    use std::{
         111  +
        collections::HashMap,
         112  +
        net::{IpAddr, Ipv4Addr, SocketAddr},
         113  +
        sync::Arc,
         114  +
    };
         115  +
    use tokio::{net::UdpSocket, sync::Notify, task::JoinHandle};
         116  +
         117  +
    pub struct TestDnsServer {
         118  +
        handle: JoinHandle<()>,
         119  +
        addr: SocketAddr,
         120  +
        shutdown: Arc<Notify>,
         121  +
    }
         122  +
         123  +
    impl TestDnsServer {
         124  +
        pub async fn start(
         125  +
            records: HashMap<String, IpAddr>,
         126  +
        ) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
         127  +
            // localhost, random port
         128  +
            let socket = UdpSocket::bind("127.0.0.1:0").await?;
         129  +
            let addr = socket.local_addr()?;
         130  +
         131  +
            let shutdown = Arc::new(Notify::new());
         132  +
            let shutdown_clone = shutdown.clone();
         133  +
         134  +
            let handle = tokio::spawn(async move {
         135  +
                let mut buf = [0; 512];
         136  +
                loop {
         137  +
                    tokio::select! {
         138  +
                        _ = shutdown_clone.notified() => break,
         139  +
                        result = socket.recv_from(&mut buf) => {
         140  +
                            // println!("IN SOCKET RECV_FROM: {buf:#?}");
         141  +
                            if let Ok((len, src)) = result {
         142  +
                                // Simple DNS response - just echo back with a mock A record
         143  +
                                // This is a minimal implementation for testing purposes
         144  +
                                let response = create_dns_response(&buf[..len], &records);
         145  +
                                // println!("SOCKET SEND RES: {response:#?}");
         146  +
                                let res = socket.send_to(&response, src).await;
         147  +
         148  +
                            }
         149  +
                        }
         150  +
                    }
         151  +
                }
         152  +
            });
         153  +
         154  +
            Ok(TestDnsServer {
         155  +
                handle,
         156  +
                addr,
         157  +
                shutdown,
         158  +
            })
         159  +
        }
         160  +
         161  +
        pub fn addr(&self) -> (IpAddr, u16) {
         162  +
            (self.addr.ip(), self.addr.port())
         163  +
        }
         164  +
    }
         165  +
         166  +
    impl Drop for TestDnsServer {
         167  +
        fn drop(&mut self) {
         168  +
            self.shutdown.notify_one();
         169  +
            self.handle.abort();
         170  +
        }
         171  +
    }
         172  +
         173  +
    fn create_dns_response(query: &[u8], records: &HashMap<String, IpAddr>) -> Vec<u8> {
         174  +
        let parsed = DnsQuery::parse(query).unwrap_or_default();
         175  +
        let ip = records
         176  +
            .get(&parsed.domain)
         177  +
            .copied()
         178  +
            .unwrap_or(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
         179  +
         180  +
        let response = DnsResponse {
         181  +
            id: parsed.id,
         182  +
            flags: 0x8180, // Standard response flags
         183  +
            question: parsed.domain,
         184  +
            answer_ip: ip,
         185  +
            ttl: 300,
         186  +
        };
         187  +
         188  +
        response.serialize()
         189  +
    }
         190  +
         191  +
    #[derive(Debug, Default)]
         192  +
    struct DnsQuery {
         193  +
        id: u16,
         194  +
        flags: u16,
         195  +
        question_count: u16,
         196  +
        domain: String,
         197  +
        query_type: u16,
         198  +
        query_class: u16,
         199  +
    }
         200  +
         201  +
    impl DnsQuery {
         202  +
        fn parse(data: &[u8]) -> Option<Self> {
         203  +
            if data.len() < 12 {
         204  +
                return None;
         205  +
            }
         206  +
         207  +
            let id = u16::from_be_bytes([data[0], data[1]]);
         208  +
            let flags = u16::from_be_bytes([data[2], data[3]]);
         209  +
            let question_count = u16::from_be_bytes([data[4], data[5]]);
         210  +
         211  +
            if question_count == 0 {
         212  +
                return None;
         213  +
            }
         214  +
         215  +
            // Parse domain name starting at byte 12
         216  +
            let mut pos = 12;
         217  +
            let mut domain = String::new();
         218  +
         219  +
            while pos < data.len() {
         220  +
                let len = data[pos] as usize;
         221  +
                if len == 0 {
         222  +
                    pos += 1;
         223  +
                    break;
         224  +
                }
         225  +
         226  +
                if !domain.is_empty() {
         227  +
                    domain.push('.');
         228  +
                }
         229  +
         230  +
                pos += 1;
         231  +
                if pos + len > data.len() {
         232  +
                    return None;
         233  +
                }
         234  +
         235  +
                if let Ok(label) = std::str::from_utf8(&data[pos..pos + len]) {
         236  +
                    domain.push_str(label);
         237  +
                }
         238  +
                pos += len;
         239  +
            }
         240  +
         241  +
            if pos + 4 > data.len() {
         242  +
                return None;
         243  +
            }
         244  +
         245  +
            let query_type = u16::from_be_bytes([data[pos], data[pos + 1]]);
         246  +
            let query_class = u16::from_be_bytes([data[pos + 2], data[pos + 3]]);
         247  +
         248  +
            Some(DnsQuery {
         249  +
                id,
         250  +
                flags,
         251  +
                question_count,
         252  +
                domain,
         253  +
                query_type,
         254  +
                query_class,
         255  +
            })
         256  +
        }
         257  +
    }
         258  +
         259  +
    #[derive(Debug)]
         260  +
    struct DnsResponse {
         261  +
        id: u16,
         262  +
        flags: u16,
         263  +
        question: String,
         264  +
        answer_ip: IpAddr,
         265  +
        ttl: u32,
         266  +
    }
         267  +
         268  +
    impl DnsResponse {
         269  +
        fn serialize(&self) -> Vec<u8> {
         270  +
            let mut response = Vec::new();
         271  +
         272  +
            // Header (12 bytes)
         273  +
            response.extend_from_slice(&self.id.to_be_bytes());
         274  +
            response.extend_from_slice(&self.flags.to_be_bytes());
         275  +
            response.extend_from_slice(&1u16.to_be_bytes()); // Questions: 1
         276  +
            response.extend_from_slice(&1u16.to_be_bytes()); // Answers: 1
         277  +
            response.extend_from_slice(&0u16.to_be_bytes()); // Authority: 0
         278  +
            response.extend_from_slice(&0u16.to_be_bytes()); // Additional: 0
         279  +
         280  +
            // Question section
         281  +
            for label in self.question.split('.') {
         282  +
                response.push(label.len() as u8);
         283  +
                response.extend_from_slice(label.as_bytes());
         284  +
            }
         285  +
            response.push(0); // End of name
         286  +
            response.extend_from_slice(&1u16.to_be_bytes()); // Type A
         287  +
            response.extend_from_slice(&1u16.to_be_bytes()); // Class IN
         288  +
         289  +
            // Answer section
         290  +
            response.extend_from_slice(&[0xc0, 0x0c]); // Name pointer
         291  +
            response.extend_from_slice(&1u16.to_be_bytes()); // Type A
         292  +
            response.extend_from_slice(&1u16.to_be_bytes()); // Class IN
         293  +
            response.extend_from_slice(&self.ttl.to_be_bytes()); // TTL
         294  +
         295  +
            match self.answer_ip {
         296  +
                IpAddr::V4(ipv4) => {
         297  +
                    response.extend_from_slice(&4u16.to_be_bytes()); // Data length
         298  +
                    response.extend_from_slice(&ipv4.octets());
         299  +
                }
         300  +
                IpAddr::V6(_) => {
         301  +
                    response.extend_from_slice(&4u16.to_be_bytes()); // Fallback to IPv4
         302  +
                    response.extend_from_slice(&[127, 0, 0, 1]);
         303  +
                }
         304  +
            }
         305  +
         306  +
            response
         307  +
        }
         308  +
    }
         309  +
}

tmp-codegen-diff/aws-sdk/sdk/aws-types/Cargo.toml

@@ -12,12 +69,69 @@
   32     32   
path = "../aws-smithy-async"
   33     33   
version = "1.2.5"
   34     34   
   35     35   
[dependencies.aws-smithy-types]
   36     36   
path = "../aws-smithy-types"
   37     37   
version = "1.3.2"
   38     38   
   39     39   
[dependencies.aws-smithy-runtime]
   40     40   
path = "../aws-smithy-runtime"
   41     41   
optional = true
   42         -
version = "1.9.0"
          42  +
version = "1.9.1"
   43     43   
   44     44   
[dependencies.aws-smithy-runtime-api]
   45     45   
path = "../aws-smithy-runtime-api"
   46     46   
features = ["client"]
   47     47   
version = "1.9.0"
   48     48   
   49     49   
[dependencies.hyper-rustls]
   50     50   
version = "0.24"
   51     51   
optional = true
   52     52   
features = ["rustls-native-certs", "http2", "webpki-roots"]

tmp-codegen-diff/aws-sdk/sdk/bedrockruntime/Cargo.toml

@@ -20,20 +80,80 @@
   40     40   
features = ["event-stream"]
   41     41   
version = "0.62.3"
   42     42   
   43     43   
[dependencies.aws-smithy-json]
   44     44   
path = "../aws-smithy-json"
   45     45   
version = "0.61.4"
   46     46   
   47     47   
[dependencies.aws-smithy-runtime]
   48     48   
path = "../aws-smithy-runtime"
   49     49   
features = ["client", "http-auth"]
   50         -
version = "1.9.0"
          50  +
version = "1.9.1"
   51     51   
   52     52   
[dependencies.aws-smithy-runtime-api]
   53     53   
path = "../aws-smithy-runtime-api"
   54     54   
features = ["client", "http-02x", "http-auth"]
   55     55   
version = "1.9.0"
   56     56   
   57     57   
[dependencies.aws-smithy-types]
   58     58   
path = "../aws-smithy-types"
   59     59   
features = ["http-body-0-4-x"]
   60     60   
version = "1.3.2"
@@ -90,90 +150,150 @@
  110    110   
features = ["test-util", "wire-mock"]
  111    111   
version = "1.1.0"
  112    112   
  113    113   
[dev-dependencies.aws-smithy-protocol-test]
  114    114   
path = "../aws-smithy-protocol-test"
  115    115   
version = "0.63.4"
  116    116   
  117    117   
[dev-dependencies.aws-smithy-runtime]
  118    118   
path = "../aws-smithy-runtime"
  119    119   
features = ["test-util"]
  120         -
version = "1.9.0"
         120  +
version = "1.9.1"
  121    121   
  122    122   
[dev-dependencies.aws-smithy-runtime-api]
  123    123   
path = "../aws-smithy-runtime-api"
  124    124   
features = ["test-util"]
  125    125   
version = "1.9.0"
  126    126   
  127    127   
[dev-dependencies.aws-smithy-types]
  128    128   
path = "../aws-smithy-types"
  129    129   
features = ["test-util"]
  130    130   
version = "1.3.2"

tmp-codegen-diff/aws-sdk/sdk/cloudwatchlogs/Cargo.toml

@@ -16,16 +76,76 @@
   36     36   
features = ["event-stream"]
   37     37   
version = "0.62.3"
   38     38   
   39     39   
[dependencies.aws-smithy-json]
   40     40   
path = "../aws-smithy-json"
   41     41   
version = "0.61.4"
   42     42   
   43     43   
[dependencies.aws-smithy-runtime]
   44     44   
path = "../aws-smithy-runtime"
   45     45   
features = ["client"]
   46         -
version = "1.9.0"
          46  +
version = "1.9.1"
   47     47   
   48     48   
[dependencies.aws-smithy-runtime-api]
   49     49   
path = "../aws-smithy-runtime-api"
   50     50   
features = ["client", "http-02x"]
   51     51   
version = "1.9.0"
   52     52   
   53     53   
[dependencies.aws-smithy-types]
   54     54   
path = "../aws-smithy-types"
   55     55   
version = "1.3.2"
   56     56   
@@ -81,81 +141,141 @@
  101    101   
features = ["test-util", "wire-mock"]
  102    102   
version = "1.1.0"
  103    103   
  104    104   
[dev-dependencies.aws-smithy-protocol-test]
  105    105   
path = "../aws-smithy-protocol-test"
  106    106   
version = "0.63.4"
  107    107   
  108    108   
[dev-dependencies.aws-smithy-runtime]
  109    109   
path = "../aws-smithy-runtime"
  110    110   
features = ["test-util"]
  111         -
version = "1.9.0"
         111  +
version = "1.9.1"
  112    112   
  113    113   
[dev-dependencies.aws-smithy-runtime-api]
  114    114   
path = "../aws-smithy-runtime-api"
  115    115   
features = ["test-util"]
  116    116   
version = "1.9.0"
  117    117   
  118    118   
[dev-dependencies.aws-smithy-types]
  119    119   
path = "../aws-smithy-types"
  120    120   
features = ["test-util"]
  121    121   
version = "1.3.2"

tmp-codegen-diff/aws-sdk/sdk/codecatalyst/Cargo.toml

@@ -10,10 +130,130 @@
   30     30   
path = "../aws-smithy-http"
   31     31   
version = "0.62.3"
   32     32   
   33     33   
[dependencies.aws-smithy-json]
   34     34   
path = "../aws-smithy-json"
   35     35   
version = "0.61.4"
   36     36   
   37     37   
[dependencies.aws-smithy-runtime]
   38     38   
path = "../aws-smithy-runtime"
   39     39   
features = ["client", "http-auth"]
   40         -
version = "1.9.0"
          40  +
version = "1.9.1"
   41     41   
   42     42   
[dependencies.aws-smithy-runtime-api]
   43     43   
path = "../aws-smithy-runtime-api"
   44     44   
features = ["client", "http-02x", "http-auth"]
   45     45   
version = "1.9.0"
   46     46   
   47     47   
[dependencies.aws-smithy-types]
   48     48   
path = "../aws-smithy-types"
   49     49   
version = "1.3.2"
   50     50   
   51     51   
[dependencies.aws-types]
   52     52   
path = "../aws-types"
   53     53   
version = "1.3.8"
   54     54   
   55     55   
[dependencies.bytes]
   56     56   
version = "1.4.0"
   57     57   
   58     58   
[dependencies.fastrand]
   59     59   
version = "2.0.0"
   60     60   
   61     61   
[dependencies.http]
   62     62   
version = "0.2.9"
   63     63   
   64     64   
[dependencies.regex-lite]
   65     65   
version = "0.1.5"
   66     66   
   67     67   
[dependencies.tracing]
   68     68   
version = "0.1"
   69     69   
[dev-dependencies.aws-config]
   70     70   
path = "../aws-config"
   71     71   
version = "1.8.5"
   72     72   
   73     73   
[dev-dependencies.aws-credential-types]
   74     74   
path = "../aws-credential-types"
   75     75   
features = ["test-util"]
   76     76   
version = "1.2.5"
   77     77   
   78     78   
[dev-dependencies.aws-runtime]
   79     79   
path = "../aws-runtime"
   80     80   
features = ["test-util"]
   81     81   
version = "1.5.10"
   82     82   
   83     83   
[dev-dependencies.aws-smithy-async]
   84     84   
path = "../aws-smithy-async"
   85     85   
features = ["test-util"]
   86     86   
version = "1.2.5"
   87     87   
   88     88   
[dev-dependencies.aws-smithy-http-client]
   89     89   
path = "../aws-smithy-http-client"
   90     90   
features = ["test-util", "wire-mock"]
   91     91   
version = "1.1.0"
   92     92   
   93     93   
[dev-dependencies.aws-smithy-protocol-test]
   94     94   
path = "../aws-smithy-protocol-test"
   95     95   
version = "0.63.4"
   96     96   
   97     97   
[dev-dependencies.aws-smithy-runtime]
   98     98   
path = "../aws-smithy-runtime"
   99     99   
features = ["test-util"]
  100         -
version = "1.9.0"
         100  +
version = "1.9.1"
  101    101   
  102    102   
[dev-dependencies.aws-smithy-runtime-api]
  103    103   
path = "../aws-smithy-runtime-api"
  104    104   
features = ["test-util"]
  105    105   
version = "1.9.0"
  106    106   
  107    107   
[dev-dependencies.aws-smithy-types]
  108    108   
path = "../aws-smithy-types"
  109    109   
features = ["test-util"]
  110    110   
version = "1.3.2"

tmp-codegen-diff/aws-sdk/sdk/config/Cargo.toml

@@ -10,10 +70,70 @@
   30     30   
path = "../aws-smithy-http"
   31     31   
version = "0.62.3"
   32     32   
   33     33   
[dependencies.aws-smithy-json]
   34     34   
path = "../aws-smithy-json"
   35     35   
version = "0.61.4"
   36     36   
   37     37   
[dependencies.aws-smithy-runtime]
   38     38   
path = "../aws-smithy-runtime"
   39     39   
features = ["client"]
   40         -
version = "1.9.0"
          40  +
version = "1.9.1"
   41     41   
   42     42   
[dependencies.aws-smithy-runtime-api]
   43     43   
path = "../aws-smithy-runtime-api"
   44     44   
features = ["client", "http-02x"]
   45     45   
version = "1.9.0"
   46     46   
   47     47   
[dependencies.aws-smithy-types]
   48     48   
path = "../aws-smithy-types"
   49     49   
version = "1.3.2"
   50     50   

tmp-codegen-diff/aws-sdk/sdk/dynamodb/Cargo.toml

@@ -10,10 +70,70 @@
   30     30   
path = "../aws-smithy-http"
   31     31   
version = "0.62.3"
   32     32   
   33     33   
[dependencies.aws-smithy-json]
   34     34   
path = "../aws-smithy-json"
   35     35   
version = "0.61.4"
   36     36   
   37     37   
[dependencies.aws-smithy-runtime]
   38     38   
path = "../aws-smithy-runtime"
   39     39   
features = ["client"]
   40         -
version = "1.9.0"
          40  +
version = "1.9.1"
   41     41   
   42     42   
[dependencies.aws-smithy-runtime-api]
   43     43   
path = "../aws-smithy-runtime-api"
   44     44   
features = ["client", "http-02x"]
   45     45   
version = "1.9.0"
   46     46   
   47     47   
[dependencies.aws-smithy-types]
   48     48   
path = "../aws-smithy-types"
   49     49   
version = "1.3.2"
   50     50   
@@ -73,73 +133,133 @@
   93     93   
features = ["test-util", "wire-mock"]
   94     94   
version = "1.1.0"
   95     95   
   96     96   
[dev-dependencies.aws-smithy-protocol-test]
   97     97   
path = "../aws-smithy-protocol-test"
   98     98   
version = "0.63.4"
   99     99   
  100    100   
[dev-dependencies.aws-smithy-runtime]
  101    101   
path = "../aws-smithy-runtime"
  102    102   
features = ["test-util"]
  103         -
version = "1.9.0"
         103  +
version = "1.9.1"
  104    104   
  105    105   
[dev-dependencies.aws-smithy-runtime-api]
  106    106   
path = "../aws-smithy-runtime-api"
  107    107   
features = ["test-util"]
  108    108   
version = "1.9.0"
  109    109   
  110    110   
[dev-dependencies.aws-smithy-types]
  111    111   
path = "../aws-smithy-types"
  112    112   
features = ["test-util"]
  113    113   
version = "1.3.2"

tmp-codegen-diff/aws-sdk/sdk/ec2/Cargo.toml

@@ -14,14 +135,135 @@
   34     34   
path = "../aws-smithy-json"
   35     35   
version = "0.61.4"
   36     36   
   37     37   
[dependencies.aws-smithy-query]
   38     38   
path = "../aws-smithy-query"
   39     39   
version = "0.60.7"
   40     40   
   41     41   
[dependencies.aws-smithy-runtime]
   42     42   
path = "../aws-smithy-runtime"
   43     43   
features = ["client"]
   44         -
version = "1.9.0"
          44  +
version = "1.9.1"
   45     45   
   46     46   
[dependencies.aws-smithy-runtime-api]
   47     47   
path = "../aws-smithy-runtime-api"
   48     48   
features = ["client", "http-02x"]
   49     49   
version = "1.9.0"
   50     50   
   51     51   
[dependencies.aws-smithy-types]
   52     52   
path = "../aws-smithy-types"
   53     53   
version = "1.3.2"
   54     54   
   55     55   
[dependencies.aws-smithy-xml]
   56     56   
path = "../aws-smithy-xml"
   57     57   
version = "0.60.10"
   58     58   
   59     59   
[dependencies.aws-types]
   60     60   
path = "../aws-types"
   61     61   
version = "1.3.8"
   62     62   
   63     63   
[dependencies.fastrand]
   64     64   
version = "2.0.0"
   65     65   
   66     66   
[dependencies.http]
   67     67   
version = "0.2.9"
   68     68   
   69     69   
[dependencies.regex-lite]
   70     70   
version = "0.1.5"
   71     71   
   72     72   
[dependencies.tracing]
   73     73   
version = "0.1"
   74     74   
[dev-dependencies.aws-config]
   75     75   
path = "../aws-config"
   76     76   
version = "1.8.5"
   77     77   
   78     78   
[dev-dependencies.aws-credential-types]
   79     79   
path = "../aws-credential-types"
   80     80   
features = ["test-util"]
   81     81   
version = "1.2.5"
   82     82   
   83     83   
[dev-dependencies.aws-runtime]
   84     84   
path = "../aws-runtime"
   85     85   
features = ["test-util"]
   86     86   
version = "1.5.10"
   87     87   
   88     88   
[dev-dependencies.aws-smithy-async]
   89     89   
path = "../aws-smithy-async"
   90     90   
features = ["test-util"]
   91     91   
version = "1.2.5"
   92     92   
   93     93   
[dev-dependencies.aws-smithy-http-client]
   94     94   
path = "../aws-smithy-http-client"
   95     95   
features = ["test-util", "wire-mock"]
   96     96   
version = "1.1.0"
   97     97   
   98     98   
[dev-dependencies.aws-smithy-protocol-test]
   99     99   
path = "../aws-smithy-protocol-test"
  100    100   
version = "0.63.4"
  101    101   
  102    102   
[dev-dependencies.aws-smithy-runtime]
  103    103   
path = "../aws-smithy-runtime"
  104    104   
features = ["test-util"]
  105         -
version = "1.9.0"
         105  +
version = "1.9.1"
  106    106   
  107    107   
[dev-dependencies.aws-smithy-runtime-api]
  108    108   
path = "../aws-smithy-runtime-api"
  109    109   
features = ["test-util"]
  110    110   
version = "1.9.0"
  111    111   
  112    112   
[dev-dependencies.aws-smithy-types]
  113    113   
path = "../aws-smithy-types"
  114    114   
features = ["test-util"]
  115    115   
version = "1.3.2"