diff --git a/.gitignore b/.gitignore index 5042327fe021..866f8b931f4c 100644 --- a/.gitignore +++ b/.gitignore @@ -69,4 +69,7 @@ sdk/test/Performance/**/BenchmarkDotNet.Artifacts/* #protocol-tests sdk/test/ProtocolTests/Generated/**/model sdk/test/ProtocolTests/Generated/**/sources -sdk/test/ProtocolTests/Generated/**/build-info \ No newline at end of file +sdk/test/ProtocolTests/Generated/**/build-info + +# macOS +.DS_Store \ No newline at end of file diff --git a/extensions/src/AWSSDK.Extensions.NETCore.Setup/DefaultAWSCredentials.cs b/extensions/src/AWSSDK.Extensions.NETCore.Setup/DefaultAWSCredentials.cs index 7f7439187535..182a4156505a 100644 --- a/extensions/src/AWSSDK.Extensions.NETCore.Setup/DefaultAWSCredentials.cs +++ b/extensions/src/AWSSDK.Extensions.NETCore.Setup/DefaultAWSCredentials.cs @@ -4,7 +4,7 @@ using Amazon.Runtime.Credentials.Internal; using Microsoft.Extensions.Logging; -namespace AWSSDK.Extensions.NETCore.Setup +namespace AWSSDK.Extensions.NETCore.Setup.Impl { /// /// diff --git a/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSCredentialsServiceCollectionExtensions.cs b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSCredentialsServiceCollectionExtensions.cs new file mode 100644 index 000000000000..4db21aefb634 --- /dev/null +++ b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSCredentialsServiceCollectionExtensions.cs @@ -0,0 +1,100 @@ +using System; +using Amazon.Runtime; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.Extensions.DependencyInjection +{ + /// + /// + /// + public static class AWSCredentialsServiceCollectionExtensions + { + /// + /// + /// + /// + /// + /// + public static IServiceCollection AddAWSCredentials( + this IServiceCollection collection, + ServiceLifetime lifetime = ServiceLifetime.Singleton) + { + collection.Add(new ServiceDescriptor(typeof(AWSCredentials), sp => sp.CreateDefaultAWSCredentials(), lifetime)); + return collection; + } + + /// + /// + /// + /// + /// + /// + public static IServiceCollection AddAWSCredentials( + this IServiceCollection collection, + AWSCredentials credentials) + { + collection.Add(new ServiceDescriptor(typeof(AWSCredentials), credentials)); + return collection; + } + + /// + /// + /// + /// + /// + /// + /// + public static IServiceCollection AddAWSCredentials( + this IServiceCollection collection, + Func credentialsFunc, + ServiceLifetime lifetime = ServiceLifetime.Singleton) + { + collection.Add(new ServiceDescriptor(typeof(AWSCredentials), credentialsFunc, lifetime)); + return collection; + } + + /// + /// + /// + /// + /// + /// + public static IServiceCollection TryAddAWSCredentials( + this IServiceCollection collection, + ServiceLifetime lifetime = ServiceLifetime.Singleton) + { + collection.TryAdd(new ServiceDescriptor(typeof(AWSCredentials), sp => sp.CreateDefaultAWSCredentials(), lifetime)); + return collection; + } + + /// + /// + /// + /// + /// + /// + public static IServiceCollection TryAddAWSCredentials( + this IServiceCollection collection, + AWSCredentials credentials) + { + collection.TryAdd(new ServiceDescriptor(typeof(AWSCredentials), credentials)); + return collection; + } + + /// + /// + /// + /// + /// + /// + /// + public static IServiceCollection TryAddAWSCredentials( + this IServiceCollection collection, + Func credentialsFunc, + ServiceLifetime lifetime = ServiceLifetime.Singleton) + { + collection.TryAdd(new ServiceDescriptor(typeof(AWSCredentials), credentialsFunc, lifetime)); + return collection; + } + } +} \ No newline at end of file diff --git a/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSCredentialsServiceProviderExtensions.cs b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSCredentialsServiceProviderExtensions.cs new file mode 100644 index 000000000000..943dc3312333 --- /dev/null +++ b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSCredentialsServiceProviderExtensions.cs @@ -0,0 +1,28 @@ +using System; +using Amazon.Extensions.NETCore.Setup; +using Amazon.Runtime; +using AWSSDK.Extensions.NETCore.Setup; +using AWSSDK.Extensions.NETCore.Setup.Impl; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.DependencyInjection +{ + /// + /// + /// + public static class AWSCredentialsServiceProviderExtensions + { + /// + /// + /// + /// + /// + /// + public static AWSCredentials CreateDefaultAWSCredentials(this IServiceProvider sp, AWSOptions options = null) + { + options = options ?? sp.GetService() ?? new AWSOptions(); + return new DefaultAWSCredentials(options, sp.GetService()); + } + } +} \ No newline at end of file diff --git a/extensions/src/AWSSDK.Extensions.NETCore.Setup/AWSOptionsExtensions.cs b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSOptionsExtensions.cs similarity index 57% rename from extensions/src/AWSSDK.Extensions.NETCore.Setup/AWSOptionsExtensions.cs rename to extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSOptionsExtensions.cs index d7f4341f61f0..90299f1d8c88 100644 --- a/extensions/src/AWSSDK.Extensions.NETCore.Setup/AWSOptionsExtensions.cs +++ b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSOptionsExtensions.cs @@ -1,5 +1,7 @@ +using System; using Amazon.Extensions.NETCore.Setup; using Amazon.Runtime; +using AWSSDK.Extensions.NETCore.Setup.Impl; namespace AWSSDK.Extensions.NETCore.Setup { @@ -15,13 +17,15 @@ public static class AWSOptionsExtensions /// /// The service interface that a service client will be created for. /// The service client that implements the service interface. - public static T CreateServiceClient(this AWSOptions options) + [Obsolete("Prefer creating a service client via one of the IServiceCollection or IServiceProvider extensions.")] + public static T CreateServiceClient(this AWSOptions options, AWSCredentials credentials = null, IClientConfigFactory clientConfigFactory = null) where T : class, IAmazonService { - var credentials = new DefaultAWSCredentials(options, null); - var clientFactory = new ClientFactory(options, credentials, null); + credentials = credentials ?? new DefaultAWSCredentials(options, null); + clientConfigFactory = clientConfigFactory ?? new DefaultClientConfigFactory(); + var clientFactory = new DefaultClientFactory(options, credentials, null, clientConfigFactory); - return clientFactory.CreateServiceClient() as T; + return clientFactory.CreateServiceClient() as T; } } } \ No newline at end of file diff --git a/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSOptionsServiceCollectionExtensions.cs b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSOptionsServiceCollectionExtensions.cs new file mode 100644 index 000000000000..edc1c2bce429 --- /dev/null +++ b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSOptionsServiceCollectionExtensions.cs @@ -0,0 +1,91 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +using System; +using Amazon.Extensions.NETCore.Setup; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.Extensions.DependencyInjection +{ + /// + /// This class adds extension methods to IServiceCollection making it easier to add Amazon service clients + /// to the NET Core dependency injection framework. + /// + public static class AWSOptionsServiceCollectionExtensions + { + /// + /// Adds the AWSOptions object to the dependency injection framework providing information + /// that will be used to construct Amazon service clients. + /// + /// + /// The default AWS options used to construct AWS service clients with. + /// Returns back the IServiceCollection to continue the fluent system of IServiceCollection. + public static IServiceCollection AddDefaultAWSOptions(this IServiceCollection collection, AWSOptions options) + { + collection.Add(new ServiceDescriptor(typeof(AWSOptions), options)); + return collection; + } + + /// + /// Adds the AWSOptions object to the dependency injection framework providing information + /// that will be used to construct Amazon service clients. + /// + /// + /// The factory that creates the default AWS options. + /// The AWS options will be used to construct AWS service clients + /// + /// The lifetime of the AWSOptions. The default is Singleton. + /// Returns back the IServiceCollection to continue the fluent system of IServiceCollection. + public static IServiceCollection AddDefaultAWSOptions( + this IServiceCollection collection, + Func implementationFactory, + ServiceLifetime lifetime = ServiceLifetime.Singleton) + { + collection.Add(new ServiceDescriptor(typeof(AWSOptions), implementationFactory, lifetime)); + return collection; + } + + /// + /// Adds the AWSOptions object to the dependency injection framework providing information + /// that will be used to construct Amazon service clients if they haven't already been registered. + /// + /// + /// The default AWS options used to construct AWS service clients with. + /// Returns back the IServiceCollection to continue the fluent system of IServiceCollection. + public static IServiceCollection TryAddDefaultAWSOptions(this IServiceCollection collection, AWSOptions options) + { + collection.TryAdd(new ServiceDescriptor(typeof(AWSOptions), options)); + return collection; + } + + /// + /// Adds the AWSOptions object to the dependency injection framework providing information + /// that will be used to construct Amazon service clients if they haven't already been registered. + /// + /// + /// The factory that creates the default AWS options. + /// The AWS options will be used to construct AWS service clients + /// + /// The lifetime of the AWSOptions. The default is Singleton. + /// Returns back the IServiceCollection to continue the fluent system of IServiceCollection. + public static IServiceCollection TryAddDefaultAWSOptions( + this IServiceCollection collection, + Func implementationFactory, + ServiceLifetime lifetime = ServiceLifetime.Singleton) + { + collection.TryAdd(new ServiceDescriptor(typeof(AWSOptions), implementationFactory, lifetime)); + return collection; + } + } +} diff --git a/extensions/src/AWSSDK.Extensions.NETCore.Setup/ServiceCollectionExtensions.cs b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSServiceServiceCollectionExtensions.cs similarity index 66% rename from extensions/src/AWSSDK.Extensions.NETCore.Setup/ServiceCollectionExtensions.cs rename to extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSServiceServiceCollectionExtensions.cs index fae7be2a6564..ace6bc62281c 100644 --- a/extensions/src/AWSSDK.Extensions.NETCore.Setup/ServiceCollectionExtensions.cs +++ b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSServiceServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). @@ -13,17 +13,9 @@ * permissions and limitations under the License. */ using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -using Microsoft.Extensions.DependencyInjection; - using Amazon.Runtime; using Amazon.Extensions.NETCore.Setup; -using AWSSDK.Extensions.NETCore.Setup; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Logging; namespace Microsoft.Extensions.DependencyInjection { @@ -31,160 +23,8 @@ namespace Microsoft.Extensions.DependencyInjection /// This class adds extension methods to IServiceCollection making it easier to add Amazon service clients /// to the NET Core dependency injection framework. /// - public static class ServiceCollectionExtensions + public static class AWSServiceServiceCollectionExtensions { - /// - /// Adds the AWSOptions object to the dependency injection framework providing information - /// that will be used to construct Amazon service clients. - /// - /// - /// The default AWS options used to construct AWS service clients with. - /// Returns back the IServiceCollection to continue the fluent system of IServiceCollection. - public static IServiceCollection AddDefaultAWSOptions(this IServiceCollection collection, AWSOptions options) - { - collection.Add(new ServiceDescriptor(typeof(AWSOptions), options)); - return collection; - } - - /// - /// Adds the AWSOptions object to the dependency injection framework providing information - /// that will be used to construct Amazon service clients. - /// - /// - /// The factory that creates the default AWS options. - /// The AWS options will be used to construct AWS service clients - /// - /// The lifetime of the AWSOptions. The default is Singleton. - /// Returns back the IServiceCollection to continue the fluent system of IServiceCollection. - public static IServiceCollection AddDefaultAWSOptions( - this IServiceCollection collection, - Func implementationFactory, - ServiceLifetime lifetime = ServiceLifetime.Singleton) - { - collection.Add(new ServiceDescriptor(typeof(AWSOptions), implementationFactory, lifetime)); - return collection; - } - - /// - /// - /// - /// - /// - /// - public static IServiceCollection AddAWSCredentials( - this IServiceCollection collection, - ServiceLifetime lifetime = ServiceLifetime.Singleton) - { - collection.Add(new ServiceDescriptor(typeof(AWSCredentials), sp => sp.CreateDefaultAWSCredentials(), lifetime)); - return collection; - } - - /// - /// - /// - /// - /// - /// - public static IServiceCollection AddAWSCredentials( - this IServiceCollection collection, - AWSCredentials credentials) - { - collection.Add(new ServiceDescriptor(typeof(AWSCredentials), credentials)); - return collection; - } - - /// - /// - /// - /// - /// - /// - /// - public static IServiceCollection AddAWSCredentials( - this IServiceCollection collection, - Func credentialsFunc, - ServiceLifetime lifetime = ServiceLifetime.Singleton) - { - collection.Add(new ServiceDescriptor(typeof(AWSCredentials), credentialsFunc, lifetime)); - return collection; - } - - /// - /// - /// - /// - /// - /// - public static IServiceCollection TryAddAWSCredentials( - this IServiceCollection collection, - ServiceLifetime lifetime = ServiceLifetime.Singleton) - { - collection.TryAdd(new ServiceDescriptor(typeof(AWSCredentials), sp => sp.CreateDefaultAWSCredentials(), lifetime)); - return collection; - } - - /// - /// - /// - /// - /// - /// - public static IServiceCollection TryAddAWSCredentials( - this IServiceCollection collection, - AWSCredentials credentials) - { - collection.TryAdd(new ServiceDescriptor(typeof(AWSCredentials), credentials)); - return collection; - } - - /// - /// - /// - /// - /// - /// - /// - public static IServiceCollection TryAddAWSCredentials( - this IServiceCollection collection, - Func credentialsFunc, - ServiceLifetime lifetime = ServiceLifetime.Singleton) - { - collection.TryAdd(new ServiceDescriptor(typeof(AWSCredentials), credentialsFunc, lifetime)); - return collection; - } - - /// - /// Adds the AWSOptions object to the dependency injection framework providing information - /// that will be used to construct Amazon service clients if they haven't already been registered. - /// - /// - /// The default AWS options used to construct AWS service clients with. - /// Returns back the IServiceCollection to continue the fluent system of IServiceCollection. - public static IServiceCollection TryAddDefaultAWSOptions(this IServiceCollection collection, AWSOptions options) - { - collection.TryAdd(new ServiceDescriptor(typeof(AWSOptions), options)); - return collection; - } - - /// - /// Adds the AWSOptions object to the dependency injection framework providing information - /// that will be used to construct Amazon service clients if they haven't already been registered. - /// - /// - /// The factory that creates the default AWS options. - /// The AWS options will be used to construct AWS service clients - /// - /// The lifetime of the AWSOptions. The default is Singleton. - /// Returns back the IServiceCollection to continue the fluent system of IServiceCollection. - public static IServiceCollection TryAddDefaultAWSOptions( - this IServiceCollection collection, - Func implementationFactory, - ServiceLifetime lifetime = ServiceLifetime.Singleton) - { - collection.TryAdd(new ServiceDescriptor(typeof(AWSOptions), implementationFactory, lifetime)); - return collection; - } - /// /// Adds the Amazon service client to the dependency injection framework. The Amazon service client is not /// created until it is requested. If the ServiceLifetime property is set to Singleton, the default, then the same @@ -211,7 +51,7 @@ public static IServiceCollection AddAWSService(this IServiceCollection collec /// Returns back the IServiceCollection to continue the fluent system of IServiceCollection. public static IServiceCollection AddAWSService(this IServiceCollection collection, AWSOptions options, ServiceLifetime lifetime = ServiceLifetime.Singleton) where T : IAmazonService { - var descriptor = new ServiceDescriptor(typeof(T), sp => CreateServiceClient(options, sp), lifetime); + var descriptor = new ServiceDescriptor(typeof(T), sp => sp.CreateServiceClient(options), lifetime); collection.Add(descriptor); return collection; } @@ -228,7 +68,7 @@ public static IServiceCollection AddAWSService(this IServiceCollection collec /// Returns back the IServiceCollection to continue the fluent system of IServiceCollection. public static IServiceCollection AddAWSService(this IServiceCollection collection, Func optionsFunc, ServiceLifetime lifetime = ServiceLifetime.Singleton) where T : IAmazonService { - var descriptor = new ServiceDescriptor(typeof(T), sp => CreateServiceClient(optionsFunc(sp), sp), lifetime); + var descriptor = new ServiceDescriptor(typeof(T), sp => sp.CreateServiceClient(optionsFunc(sp)), lifetime); collection.Add(descriptor); return collection; } @@ -259,7 +99,7 @@ public static IServiceCollection TryAddAWSService(this IServiceCollection col /// Returns back the IServiceCollection to continue the fluent system of IServiceCollection. public static IServiceCollection TryAddAWSService(this IServiceCollection collection, AWSOptions options, ServiceLifetime lifetime = ServiceLifetime.Singleton) where T : IAmazonService { - var descriptor = new ServiceDescriptor(typeof(T), sp => CreateServiceClient(options, sp), lifetime); + var descriptor = new ServiceDescriptor(typeof(T), sp => sp.CreateServiceClient(options), lifetime); collection.TryAdd(descriptor); return collection; } @@ -276,7 +116,7 @@ public static IServiceCollection TryAddAWSService(this IServiceCollection col /// Returns back the IServiceCollection to continue the fluent system of IServiceCollection. public static IServiceCollection TryAddAWSService(this IServiceCollection collection, Func optionsFunc, ServiceLifetime lifetime = ServiceLifetime.Singleton) where T : IAmazonService { - var descriptor = new ServiceDescriptor(typeof(T), sp => CreateServiceClient(optionsFunc(sp), sp), lifetime); + var descriptor = new ServiceDescriptor(typeof(T), sp => sp.CreateServiceClient(optionsFunc(sp)), lifetime); collection.TryAdd(descriptor); return collection; } @@ -311,7 +151,7 @@ public static IServiceCollection AddKeyedAWSService(this IServiceCollection c /// Returns back the IServiceCollection to continue the fluent system of IServiceCollection. public static IServiceCollection AddKeyedAWSService(this IServiceCollection collection, object serviceKey, AWSOptions options, ServiceLifetime lifetime = ServiceLifetime.Singleton) where T : IAmazonService { - var descriptor = new ServiceDescriptor(typeof(T), serviceKey, (sp, _) => CreateServiceClient(options, sp), lifetime); + var descriptor = new ServiceDescriptor(typeof(T), serviceKey, (sp, _) => sp.CreateServiceClient(options), lifetime); collection.Add(descriptor); return collection; } @@ -329,7 +169,7 @@ public static IServiceCollection AddKeyedAWSService(this IServiceCollection c /// Returns back the IServiceCollection to continue the fluent system of IServiceCollection. public static IServiceCollection AddKeyedAWSService(this IServiceCollection collection, object serviceKey, Func optionsFunc, ServiceLifetime lifetime = ServiceLifetime.Singleton) where T : IAmazonService { - var descriptor = new ServiceDescriptor(typeof(T), serviceKey, (sp, _) => CreateServiceClient(optionsFunc(sp), sp), lifetime); + var descriptor = new ServiceDescriptor(typeof(T), serviceKey, (sp, _) => sp.CreateServiceClient(optionsFunc(sp)), lifetime); collection.Add(descriptor); return collection; } @@ -362,7 +202,7 @@ public static IServiceCollection TryAddKeyedAWSService(this IServiceCollectio /// Returns back the IServiceCollection to continue the fluent system of IServiceCollection. public static IServiceCollection TryAddKeyedAWSService(this IServiceCollection collection, object serviceKey, AWSOptions options, ServiceLifetime lifetime = ServiceLifetime.Singleton) where T : IAmazonService { - var descriptor = new ServiceDescriptor(typeof(T), serviceKey, (sp, _) => CreateServiceClient(options, sp), lifetime); + var descriptor = new ServiceDescriptor(typeof(T), serviceKey, (sp, _) => sp.CreateServiceClient(options), lifetime); collection.TryAdd(descriptor); return collection; } @@ -380,27 +220,10 @@ public static IServiceCollection TryAddKeyedAWSService(this IServiceCollectio /// Returns back the IServiceCollection to continue the fluent system of IServiceCollection. public static IServiceCollection TryAddKeyedAWSService(this IServiceCollection collection, object serviceKey, Func optionsFunc, ServiceLifetime lifetime = ServiceLifetime.Singleton) where T : IAmazonService { - var descriptor = new ServiceDescriptor(typeof(T), serviceKey, (sp, _) => CreateServiceClient(optionsFunc(sp), sp), lifetime); + var descriptor = new ServiceDescriptor(typeof(T), serviceKey, (sp, _) => sp.CreateServiceClient(optionsFunc(sp)), lifetime); collection.TryAdd(descriptor); return collection; } #endif - - private static object CreateServiceClient(AWSOptions options, IServiceProvider sp) where T : IAmazonService - { - var logger = sp.GetService(); - var awsOptions = options ?? sp.GetService() ?? new AWSOptions(); - var credentialsFactory = sp.GetService() ?? sp.CreateDefaultAWSCredentials(options); - - var factory = new ClientFactory(awsOptions, credentialsFactory, logger); - - return factory.CreateServiceClient(); - } - - private static AWSCredentials CreateDefaultAWSCredentials(this IServiceProvider sp, AWSOptions options = null) - { - options = options ?? sp.GetService() ?? new AWSOptions(); - return sp.GetService() ?? new DefaultAWSCredentials(options, sp.GetService()); - } } } diff --git a/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSServiceServiceProviderExtensions.cs b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSServiceServiceProviderExtensions.cs new file mode 100644 index 000000000000..bc3214c737f3 --- /dev/null +++ b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/AWSServiceServiceProviderExtensions.cs @@ -0,0 +1,26 @@ +using System; +using Amazon.Extensions.NETCore.Setup; +using Amazon.Runtime; +using AWSSDK.Extensions.NETCore.Setup; + +namespace Microsoft.Extensions.DependencyInjection +{ + /// + /// + /// + public static class AWSServiceServiceProviderExtensions + { + /// + /// + /// + /// + /// + /// + /// + public static object CreateServiceClient(this IServiceProvider sp, AWSOptions options = null) where T : IAmazonService + { + var factory = sp.GetService() ?? sp.CreateDefaultClientFactory(options); + return factory.CreateServiceClient(); + } + } +} \ No newline at end of file diff --git a/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/ClientConfigFactoryServiceCollectionExtensions.cs b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/ClientConfigFactoryServiceCollectionExtensions.cs new file mode 100644 index 000000000000..411fe99d035d --- /dev/null +++ b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/ClientConfigFactoryServiceCollectionExtensions.cs @@ -0,0 +1,78 @@ +using System; +using AWSSDK.Extensions.NETCore.Setup; +using AWSSDK.Extensions.NETCore.Setup.Impl; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.Extensions.DependencyInjection +{ + /// + /// + /// + public static class ClientConfigFactoryServiceCollectionExtensions + { + /// + /// + /// + /// + /// + /// + public static IServiceCollection AddClientConfigFactory( + this IServiceCollection collection, + ServiceLifetime lifetime = ServiceLifetime.Singleton) + { + collection.Add(new ServiceDescriptor(typeof(IClientConfigFactory), CreateDefaultCredentialsFactory, lifetime)); + return collection; + } + + /// + /// + /// + /// + /// + /// + /// + public static IServiceCollection AddClientConfigFactory( + this IServiceCollection collection, + Func clientConfigFactoryFunc, + ServiceLifetime lifetime = ServiceLifetime.Singleton) + { + collection.Add(new ServiceDescriptor(typeof(IClientConfigFactory), clientConfigFactoryFunc, lifetime)); + return collection; + } + + /// + /// + /// + /// + /// + /// + public static IServiceCollection TryAddClientConfigFactory( + this IServiceCollection collection, + ServiceLifetime lifetime = ServiceLifetime.Singleton) + { + collection.TryAdd(new ServiceDescriptor(typeof(IClientConfigFactory), CreateDefaultCredentialsFactory, lifetime)); + return collection; + } + + /// + /// + /// + /// + /// + /// + /// + public static IServiceCollection TryAddClientConfigFactory( + this IServiceCollection collection, + Func clientConfigFactoryFunc, + ServiceLifetime lifetime = ServiceLifetime.Singleton) + { + collection.TryAdd(new ServiceDescriptor(typeof(IClientConfigFactory), clientConfigFactoryFunc, lifetime)); + return collection; + } + + private static IClientConfigFactory CreateDefaultCredentialsFactory(IServiceProvider sp) + { + return new DefaultClientConfigFactory(); + } + } +} \ No newline at end of file diff --git a/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/ClientFactoryServiceCollectionExtensions.cs b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/ClientFactoryServiceCollectionExtensions.cs new file mode 100644 index 000000000000..cd6c68d1acf9 --- /dev/null +++ b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/ClientFactoryServiceCollectionExtensions.cs @@ -0,0 +1,96 @@ +using System; +using AWSSDK.Extensions.NETCore.Setup; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.Extensions.DependencyInjection +{ + /// + /// + /// + public static class ClientFactoryServiceCollectionExtensions + { + /// + /// + /// + /// + /// + /// + public static IServiceCollection AddClientConfigFactory( + this IServiceCollection collection, + ServiceLifetime lifetime = ServiceLifetime.Singleton) + { + collection.Add(new ServiceDescriptor(typeof(IClientConfigFactory), sp => sp.CreateDefaultClientFactory(), lifetime)); + return collection; + } + + /// + /// + /// + /// + /// + /// + public static IServiceCollection TryAddClientConfigFactory( + this IServiceCollection collection, + ServiceLifetime lifetime = ServiceLifetime.Singleton) + { + collection.TryAdd(new ServiceDescriptor(typeof(IClientConfigFactory), sp => sp.CreateDefaultClientFactory(), lifetime)); + return collection; + } + + /// + /// + /// + /// + /// + /// + public static IServiceCollection AddClientConfigFactory( + this IServiceCollection collection, + IClientFactory clientFactory) + { + collection.Add(new ServiceDescriptor(typeof(IClientConfigFactory), clientFactory)); + return collection; + } + + /// + /// + /// + /// + /// + /// + public static IServiceCollection TryAddClientConfigFactory( + this IServiceCollection collection, + IClientFactory clientFactory) + { + collection.TryAdd(new ServiceDescriptor(typeof(IClientConfigFactory), clientFactory)); + return collection; + } + + /// + /// + /// + /// + /// + /// + public static IServiceCollection AddClientConfigFactory( + this IServiceCollection collection, + Func clientFactoryFunc) + { + collection.Add(new ServiceDescriptor(typeof(IClientConfigFactory), clientFactoryFunc)); + return collection; + } + + /// + /// + /// + /// + /// + /// + public static IServiceCollection TryAddClientConfigFactory( + this IServiceCollection collection, + Func clientFactoryFunc) + { + collection.TryAdd(new ServiceDescriptor(typeof(IClientConfigFactory), clientFactoryFunc)); + return collection; + } + } +} \ No newline at end of file diff --git a/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/ClientFactoryServiceProviderExtensions.cs b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/ClientFactoryServiceProviderExtensions.cs new file mode 100644 index 000000000000..03b6bfa1bacc --- /dev/null +++ b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/ClientFactoryServiceProviderExtensions.cs @@ -0,0 +1,37 @@ +using System; +using Amazon.Extensions.NETCore.Setup; +using Amazon.Runtime; +using AWSSDK.Extensions.NETCore.Setup; +using AWSSDK.Extensions.NETCore.Setup.Impl; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.DependencyInjection +{ + /// + /// + /// + public static class ClientFactoryServiceProviderExtensions + { + /// + /// + /// + /// + /// + /// + /// + /// + public static IClientFactory CreateDefaultClientFactory( + this IServiceProvider sp, + AWSOptions optionsOverride = null, + AWSCredentials credentialsOverride = null, + IClientConfigFactory clientConfigFactoryOverride = null) + { + var logger = sp.GetService(); + var awsOptions = optionsOverride ?? sp.GetService() ?? new AWSOptions(); + var credentials = credentialsOverride ?? sp.GetService() ?? sp.CreateDefaultAWSCredentials(awsOptions); + var clientConfigFactory = clientConfigFactoryOverride ?? sp.GetService() ?? new DefaultClientConfigFactory(); + + return new DefaultClientFactory(awsOptions, credentials, logger, clientConfigFactory); + } + } +} \ No newline at end of file diff --git a/extensions/src/AWSSDK.Extensions.NETCore.Setup/ConfigurationExtensions.cs b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/ConfigurationExtensions.cs similarity index 99% rename from extensions/src/AWSSDK.Extensions.NETCore.Setup/ConfigurationExtensions.cs rename to extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/ConfigurationExtensions.cs index 3d1fe4504c35..d0664b2a3b04 100644 --- a/extensions/src/AWSSDK.Extensions.NETCore.Setup/ConfigurationExtensions.cs +++ b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Extensions/ConfigurationExtensions.cs @@ -13,16 +13,9 @@ * permissions and limitations under the License. */ using System; -using System.Reflection; - using Amazon; using Amazon.Runtime; -using Amazon.Util; - using Amazon.Extensions.NETCore.Setup; -using System.Linq; -using System.Threading; -using System.Collections.Generic; namespace Microsoft.Extensions.Configuration { diff --git a/extensions/src/AWSSDK.Extensions.NETCore.Setup/IClientConfigFactory.cs b/extensions/src/AWSSDK.Extensions.NETCore.Setup/IClientConfigFactory.cs new file mode 100644 index 000000000000..0117957c7cf9 --- /dev/null +++ b/extensions/src/AWSSDK.Extensions.NETCore.Setup/IClientConfigFactory.cs @@ -0,0 +1,19 @@ +using Amazon.Extensions.NETCore.Setup; +using Amazon.Runtime; + +namespace AWSSDK.Extensions.NETCore.Setup +{ + /// + /// + /// + public interface IClientConfigFactory + { + /// + /// + /// + /// + /// + ClientConfig CreateConfig(AWSOptions options) + where T : IAmazonService; + } +} \ No newline at end of file diff --git a/extensions/src/AWSSDK.Extensions.NETCore.Setup/IClientFactory.cs b/extensions/src/AWSSDK.Extensions.NETCore.Setup/IClientFactory.cs new file mode 100644 index 000000000000..dbda88ecb931 --- /dev/null +++ b/extensions/src/AWSSDK.Extensions.NETCore.Setup/IClientFactory.cs @@ -0,0 +1,16 @@ +using Amazon.Runtime; + +namespace AWSSDK.Extensions.NETCore.Setup +{ + /// + /// + /// + public interface IClientFactory + { + /// + /// + /// + /// + IAmazonService CreateServiceClient() where T : IAmazonService; + } +} \ No newline at end of file diff --git a/extensions/src/AWSSDK.Extensions.NETCore.Setup/ClientFactory.cs b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Impl/DefaultClientConfigFactory.cs similarity index 57% rename from extensions/src/AWSSDK.Extensions.NETCore.Setup/ClientFactory.cs rename to extensions/src/AWSSDK.Extensions.NETCore.Setup/Impl/DefaultClientConfigFactory.cs index 503fbee761c5..0376a0c9db74 100644 --- a/extensions/src/AWSSDK.Extensions.NETCore.Setup/ClientFactory.cs +++ b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Impl/DefaultClientConfigFactory.cs @@ -1,154 +1,28 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; -using System.Xml.Linq; +using Amazon.Extensions.NETCore.Setup; using Amazon.Runtime; -using Amazon.Runtime.CredentialManagement; -using Amazon.Runtime.Credentials.Internal; -using AWSSDK.Extensions.NETCore.Setup; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -namespace Amazon.Extensions.NETCore.Setup +namespace AWSSDK.Extensions.NETCore.Setup.Impl { /// - /// The factory class for creating AWS service clients from the AWS SDK for .NET. + /// /// - internal class ClientFactory - where T : IAmazonService + public class DefaultClientConfigFactory : IClientConfigFactory { private static readonly Type[] EMPTY_TYPES = Array.Empty(); private static readonly object[] EMPTY_PARAMETERS = Array.Empty(); - private readonly AWSOptions _options; - private readonly AWSCredentials _credentials; - private readonly ILogger _logger; - - /// - /// Constructs an instance of the ClientFactory - /// - /// The AWS options used for creating service clients. - /// - /// - internal ClientFactory(AWSOptions awsOptions, AWSCredentials credentials, ILogger logger) - { - _options = awsOptions ?? throw new ArgumentNullException(nameof(awsOptions)); - _credentials = credentials ?? throw new ArgumentNullException(nameof(credentials)); - _logger = logger; - } - - /// - /// Creates the AWS service client that implements the service client interface. - /// - /// The AWS service client - internal IAmazonService CreateServiceClient() - { - PerformGlobalConfig(_logger, _options); - var credentials = _credentials; - - if (!string.IsNullOrEmpty(_options?.SessionRoleArn)) - { - if (string.IsNullOrEmpty(_options?.ExternalId)) - { - credentials = new AssumeRoleAWSCredentials(credentials, _options.SessionRoleArn, _options.SessionName); - } - else - { - credentials = new AssumeRoleAWSCredentials(credentials, _options.SessionRoleArn, _options.SessionName, new AssumeRoleAWSCredentialsOptions() { ExternalId = _options.ExternalId }); - } - } - - var config = CreateConfig(_options); - var client = CreateClient(credentials, config); - return client as IAmazonService; - } - - /// - /// Performs all of the global settings that have been specified in AWSOptions. - /// - /// - /// - private static void PerformGlobalConfig(ILogger logger, AWSOptions options) - { - if(options?.Logging != null) - { - if(options.Logging.LogTo.HasValue && AWSConfigs.LoggingConfig.LogTo != options.Logging.LogTo.Value) - { - AWSConfigs.LoggingConfig.LogTo = options.Logging.LogTo.Value; - logger?.LogDebug($"Configuring SDK LogTo: {AWSConfigs.LoggingConfig.LogTo}"); - } - - if (options.Logging.LogResponses.HasValue && AWSConfigs.LoggingConfig.LogResponses != options.Logging.LogResponses.Value) - { - AWSConfigs.LoggingConfig.LogResponses = options.Logging.LogResponses.Value; - logger?.LogDebug($"Configuring SDK LogResponses: {AWSConfigs.LoggingConfig.LogResponses}"); - } - - if (options.Logging.LogMetrics.HasValue && AWSConfigs.LoggingConfig.LogMetrics != options.Logging.LogMetrics.Value) - { - AWSConfigs.LoggingConfig.LogMetrics = options.Logging.LogMetrics.Value; - logger?.LogDebug($"Configuring SDK LogMetrics: {AWSConfigs.LoggingConfig.LogMetrics}"); - } - - if (options.Logging.LogResponsesSizeLimit.HasValue && AWSConfigs.LoggingConfig.LogResponsesSizeLimit != options.Logging.LogResponsesSizeLimit.Value) - { - AWSConfigs.LoggingConfig.LogResponsesSizeLimit = options.Logging.LogResponsesSizeLimit.Value; - logger?.LogDebug($"Configuring SDK LogResponsesSizeLimit: {AWSConfigs.LoggingConfig.LogResponsesSizeLimit}"); - } - } - } - - /// - /// Creates the service client using the credentials and client config. - /// - /// - /// - /// - private static AmazonServiceClient CreateClient(AWSCredentials credentials, ClientConfig config) - { -#if NET8_0_OR_GREATER - return T.CreateDefaultServiceClient(credentials, config) as AmazonServiceClient; -#else - var clientTypeName = typeof(T).Namespace + "." + typeof(T).Name.Substring(1) + "Client"; - var clientType = typeof(T).GetTypeInfo().Assembly.GetType(clientTypeName); - if (clientType == null) - { - throw new AmazonClientException($"Failed to find service client {clientTypeName} which implements {typeof(T).FullName}."); - } - - var constructor = clientType.GetConstructor(new Type[] { typeof(AWSCredentials), config.GetType() }); - if (constructor == null) - { - throw new AmazonClientException($"Service client {clientTypeName} missing a constructor with parameters AWSCredentials and {config.GetType().FullName}."); - } - - return constructor.Invoke(new object[] { credentials, config }) as AmazonServiceClient; -#endif - } - /// /// Creates the ClientConfig object for the service client. /// /// /// - private ClientConfig CreateConfig(AWSOptions options) + public ClientConfig CreateConfig(AWSOptions options) + where T : IAmazonService { #if NET8_0_OR_GREATER ClientConfig config = T.CreateDefaultClientConfig(); @@ -340,4 +214,4 @@ private void ProcessServiceSpecificSettings(ClientConfig clientConfig, IDictiona } } } -} +} \ No newline at end of file diff --git a/extensions/src/AWSSDK.Extensions.NETCore.Setup/Impl/DefaultClientFactory.cs b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Impl/DefaultClientFactory.cs new file mode 100644 index 000000000000..eb088fd64b3e --- /dev/null +++ b/extensions/src/AWSSDK.Extensions.NETCore.Setup/Impl/DefaultClientFactory.cs @@ -0,0 +1,141 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +using System; +using System.Reflection; +using Amazon; +using Amazon.Extensions.NETCore.Setup; +using Amazon.Runtime; +using Microsoft.Extensions.Logging; + +namespace AWSSDK.Extensions.NETCore.Setup.Impl +{ + /// + /// The factory class for creating AWS service clients from the AWS SDK for .NET. + /// + internal class DefaultClientFactory : IClientFactory + { + private readonly AWSOptions _options; + private readonly AWSCredentials _credentials; + private readonly IClientConfigFactory _clientConfigFactory; + private readonly ILogger _logger; + + /// + /// Constructs an instance of the ClientFactory + /// + /// The AWS options used for creating service clients. + /// + /// + /// + internal DefaultClientFactory(AWSOptions awsOptions, AWSCredentials credentials, ILogger logger, IClientConfigFactory clientConfigFactory) + { + _options = awsOptions ?? throw new ArgumentNullException(nameof(awsOptions)); + _credentials = credentials ?? throw new ArgumentNullException(nameof(credentials)); + _logger = logger; + _clientConfigFactory = clientConfigFactory; + } + + /// + /// Creates the AWS service client that implements the service client interface. + /// + /// The AWS service client + public IAmazonService CreateServiceClient() + where T : IAmazonService + { + PerformGlobalConfig(_logger, _options); + var credentials = _credentials; + + if (!string.IsNullOrEmpty(_options?.SessionRoleArn)) + { + if (string.IsNullOrEmpty(_options?.ExternalId)) + { + credentials = new AssumeRoleAWSCredentials(credentials, _options.SessionRoleArn, _options.SessionName); + } + else + { + credentials = new AssumeRoleAWSCredentials(credentials, _options.SessionRoleArn, _options.SessionName, new AssumeRoleAWSCredentialsOptions() { ExternalId = _options.ExternalId }); + } + } + + var config = _clientConfigFactory.CreateConfig(_options); + var client = CreateClient(credentials, config); + return client as IAmazonService; + } + + /// + /// Performs all of the global settings that have been specified in AWSOptions. + /// + /// + /// + private static void PerformGlobalConfig(ILogger logger, AWSOptions options) + { + if(options?.Logging != null) + { + if(options.Logging.LogTo.HasValue && AWSConfigs.LoggingConfig.LogTo != options.Logging.LogTo.Value) + { + AWSConfigs.LoggingConfig.LogTo = options.Logging.LogTo.Value; + logger?.LogDebug($"Configuring SDK LogTo: {AWSConfigs.LoggingConfig.LogTo}"); + } + + if (options.Logging.LogResponses.HasValue && AWSConfigs.LoggingConfig.LogResponses != options.Logging.LogResponses.Value) + { + AWSConfigs.LoggingConfig.LogResponses = options.Logging.LogResponses.Value; + logger?.LogDebug($"Configuring SDK LogResponses: {AWSConfigs.LoggingConfig.LogResponses}"); + } + + if (options.Logging.LogMetrics.HasValue && AWSConfigs.LoggingConfig.LogMetrics != options.Logging.LogMetrics.Value) + { + AWSConfigs.LoggingConfig.LogMetrics = options.Logging.LogMetrics.Value; + logger?.LogDebug($"Configuring SDK LogMetrics: {AWSConfigs.LoggingConfig.LogMetrics}"); + } + + if (options.Logging.LogResponsesSizeLimit.HasValue && AWSConfigs.LoggingConfig.LogResponsesSizeLimit != options.Logging.LogResponsesSizeLimit.Value) + { + AWSConfigs.LoggingConfig.LogResponsesSizeLimit = options.Logging.LogResponsesSizeLimit.Value; + logger?.LogDebug($"Configuring SDK LogResponsesSizeLimit: {AWSConfigs.LoggingConfig.LogResponsesSizeLimit}"); + } + } + } + + /// + /// Creates the service client using the credentials and client config. + /// + /// + /// + /// + private static AmazonServiceClient CreateClient(AWSCredentials credentials, ClientConfig config) + where T : IAmazonService + { +#if NET8_0_OR_GREATER + return T.CreateDefaultServiceClient(credentials, config) as AmazonServiceClient; +#else + var clientTypeName = typeof(T).Namespace + "." + typeof(T).Name.Substring(1) + "Client"; + var clientType = typeof(T).GetTypeInfo().Assembly.GetType(clientTypeName); + if (clientType == null) + { + throw new AmazonClientException($"Failed to find service client {clientTypeName} which implements {typeof(T).FullName}."); + } + + var constructor = clientType.GetConstructor(new Type[] { typeof(AWSCredentials), config.GetType() }); + if (constructor == null) + { + throw new AmazonClientException($"Service client {clientTypeName} missing a constructor with parameters AWSCredentials and {config.GetType().FullName}."); + } + + return constructor.Invoke(new object[] { credentials, config }) as AmazonServiceClient; +#endif + } + } +}