From 20b7ee65cf0f09d71ffda1b57efd6dd27165318a Mon Sep 17 00:00:00 2001
From: Bart Koelman <104792814+bart-vmware@users.noreply.github.com>
Date: Thu, 9 Nov 2023 14:46:27 +0100
Subject: [PATCH] Bootstrap public API review
---
shared-package.props | 4 +-
.../AutoConfiguration/AssemblyExtensions.cs | 67 ---
.../src/AutoConfiguration/AssemblyLoader.cs | 93 ++++
.../src/AutoConfiguration/BootstrapScanner.cs | 293 +++++++++++
.../ConfigurationExtensions.cs | 24 -
.../HostBuilderExtensions.cs | 382 +++-----------
.../src/AutoConfiguration/LogMessages.cs | 33 --
.../AutoConfiguration/PublicAPI.Shipped.txt | 1 +
.../AutoConfiguration/PublicAPI.Unshipped.txt | 31 ++
...teeltoe.Bootstrap.AutoConfiguration.csproj | 2 +
.../SteeltoeAssemblyNames.cs | 15 +-
.../WebApplicationBuilderExtensions.cs | 336 +++---------
.../WebHostBuilderExtensions.cs | 381 +++-----------
.../HostBuilderExtensionsTest.cs | 306 ++++-------
...oe.Bootstrap.AutoConfiguration.Test.csproj | 1 +
.../WebApplicationBuilderExtensionsTest.cs | 270 +++++-----
.../WebHostBuilderExtensionsTest.cs | 339 ++++--------
.../EmptyAutoConfigurationTest.cs | 16 +-
...otstrap.EmptyAutoConfiguration.Test.csproj | 1 +
.../xunit.runner.json | 4 -
.../DynamicTypeAccess/PackageResolver.cs | 3 +-
.../HostBuilderContextWrapper.cs | 94 ++++
.../src/Common.Hosting/HostBuilderWrapper.cs | 221 ++++++++
.../Common.Hosting/Properties/AssemblyInfo.cs | 3 +
.../KubernetesClientHelpers.cs | 29 +
.../test/Common.TestResources/TestHelpers.cs | 6 +-
.../CloudFoundryHostBuilderExtensions.cs | 4 +-
.../ConfigServerHostBuilderExtensions.cs | 4 +-
.../Client/DiscoveryHostBuilderExtensions.cs | 2 +-
.../DiscoveryWebHostBuilderExtensions.cs | 4 +-
.../HostBuilderWrapperExtensions.cs | 33 ++
.../DynamicSerilog/Properties/AssemblyInfo.cs | 1 +
.../SerilogHostBuilderExtensions.cs | 15 +-
.../SerilogWebApplicationBuilderExtensions.cs | 11 +-
.../SerilogWebHostBuilderExtensions.cs | 15 +-
.../Steeltoe.Logging.DynamicSerilog.csproj | 1 +
.../ActuatorServiceCollectionExtensions.cs | 31 +-
.../EndpointServiceCollectionExtensions.cs | 2 +-
.../Endpoint/HostBuilderWrapperExtensions.cs | 145 +++++
.../ManagementHostBuilderExtensions.cs | 484 ++++++++---------
.../Endpoint/ManagementPort/ErrorResponse.cs | 34 --
.../ManagementPortMiddleware.cs | 18 +-
.../ManagementPortWebHostBuilderExtensions.cs | 81 +++
...nagementWebApplicationBuilderExtensions.cs | 410 +++++++-------
.../ManagementWebHostBuilderExtensions.cs | 498 ++++++++----------
.../src/Endpoint/Properties/AssemblyInfo.cs | 1 +
.../src/Endpoint/PublicAPI.Unshipped.txt | 129 +++--
.../src/Kubernetes/HostBuilderExtensions.cs | 42 +-
.../src/Kubernetes/Properties/AssemblyInfo.cs | 1 +
.../Steeltoe.Management.Tracing.csproj | 1 +
.../src/Wavefront/PublicAPI.Unshipped.txt | 3 -
.../src/Wavefront/WavefrontExtensions.cs | 48 --
.../ActuatorRouteBuilderExtensionsTest.cs | 2 +-
...ActuatorServiceCollectionExtensionsTest.cs | 8 +-
...ManagementEndpointServedOnDifferentPort.cs | 171 ------
...gementEndpointServedOnDifferentPortTest.cs | 279 ++++++++++
56 files changed, 2720 insertions(+), 2713 deletions(-)
delete mode 100644 src/Bootstrap/src/AutoConfiguration/AssemblyExtensions.cs
create mode 100644 src/Bootstrap/src/AutoConfiguration/AssemblyLoader.cs
create mode 100644 src/Bootstrap/src/AutoConfiguration/BootstrapScanner.cs
delete mode 100644 src/Bootstrap/src/AutoConfiguration/ConfigurationExtensions.cs
delete mode 100644 src/Bootstrap/src/AutoConfiguration/LogMessages.cs
create mode 100644 src/Bootstrap/src/AutoConfiguration/PublicAPI.Shipped.txt
create mode 100644 src/Bootstrap/src/AutoConfiguration/PublicAPI.Unshipped.txt
delete mode 100644 src/Bootstrap/test/EmptyAutoConfiguration.Test/xunit.runner.json
create mode 100644 src/Common/src/Common.Hosting/HostBuilderContextWrapper.cs
create mode 100644 src/Common/src/Common.Hosting/HostBuilderWrapper.cs
create mode 100644 src/Logging/src/DynamicSerilog/HostBuilderWrapperExtensions.cs
create mode 100644 src/Management/src/Endpoint/HostBuilderWrapperExtensions.cs
delete mode 100644 src/Management/src/Endpoint/ManagementPort/ErrorResponse.cs
create mode 100644 src/Management/src/Endpoint/ManagementPort/ManagementPortWebHostBuilderExtensions.cs
delete mode 100644 src/Management/test/Endpoint.Test/ManagementPort/ManagementEndpointServedOnDifferentPort.cs
create mode 100644 src/Management/test/Endpoint.Test/ManagementPort/ManagementEndpointServedOnDifferentPortTest.cs
diff --git a/shared-package.props b/shared-package.props
index 610d149c10..29a1927bb4 100644
--- a/shared-package.props
+++ b/shared-package.props
@@ -53,14 +53,14 @@
+ Condition="$(MSBuildProjectName.StartsWith('Steeltoe.Configuration')) Or $(MSBuildProjectName.StartsWith('Steeltoe.Management')) Or $(MSBuildProjectName.StartsWith('Steeltoe.Connectors')) Or $(MSBuildProjectName.StartsWith('Steeltoe.Logging')) Or $(MSBuildProjectName.StartsWith('Steeltoe.Bootstrap'))">
+ Condition="!$(MSBuildProjectName.StartsWith('Steeltoe.Configuration')) And !$(MSBuildProjectName.StartsWith('Steeltoe.Management')) And !$(MSBuildProjectName.StartsWith('Steeltoe.Connectors')) And !$(MSBuildProjectName.StartsWith('Steeltoe.Logging')) And !$(MSBuildProjectName.StartsWith('Steeltoe.Bootstrap'))">
$(NoWarn);SA1401;S1168;S2360;S3900;S3956;S4004;S4023
diff --git a/src/Bootstrap/src/AutoConfiguration/AssemblyExtensions.cs b/src/Bootstrap/src/AutoConfiguration/AssemblyExtensions.cs
deleted file mode 100644
index cdd7546e45..0000000000
--- a/src/Bootstrap/src/AutoConfiguration/AssemblyExtensions.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information.
-
-using System.Reflection;
-using System.Text.RegularExpressions;
-using Steeltoe.Common.Reflection;
-
-namespace Steeltoe.Bootstrap.AutoConfiguration;
-
-internal static class AssemblyExtensions
-{
- private static readonly HashSet MissingAssemblies = new();
-
- internal static IEnumerable ExcludedAssemblies { get; set; }
-
- internal static Assembly LoadAnyVersion(object sender, ResolveEventArgs args)
- {
- // Load whatever version available - strip out version and culture info
- static string GetSimpleName(string assemblyName)
- {
- return new Regex(",.*").Replace(assemblyName, string.Empty);
- }
-
- string name = GetSimpleName(args.Name);
-
- if (MissingAssemblies.Contains(name))
- {
- return null;
- }
-
- // AssemblyName.Equals() returns false when path and full name are identical, so the code below
- // avoids a crash caused by inserting duplicate keys in dictionary.
- Dictionary assemblies = AppDomain.CurrentDomain.GetAssemblies().GroupBy(asm => asm.GetName().Name)
- .ToDictionary(grouping => grouping.Key, grouping => grouping.First());
-
- if (assemblies.TryGetValue(name, out Assembly assembly))
- {
- return assembly;
- }
-
- if (args.Name.Contains(".resources", StringComparison.Ordinal))
- {
- return args.RequestingAssembly;
- }
-
- MissingAssemblies.Add(name); // throw it in there to prevent recursive attempts to resolve
- assembly = Assembly.Load(name);
- MissingAssemblies.Remove(name);
- return assembly;
- }
-
- internal static bool IsAssemblyLoaded(string assemblyName)
- {
- if (ExcludedAssemblies.Contains(assemblyName))
- {
- return false;
- }
-
- return ReflectionHelpers.IsAssemblyLoaded(assemblyName);
- }
-
- internal static bool IsEitherAssemblyLoaded(string assemblyName1, string assemblyName2)
- {
- return IsAssemblyLoaded(assemblyName1) || IsAssemblyLoaded(assemblyName2);
- }
-}
diff --git a/src/Bootstrap/src/AutoConfiguration/AssemblyLoader.cs b/src/Bootstrap/src/AutoConfiguration/AssemblyLoader.cs
new file mode 100644
index 0000000000..6848112b21
--- /dev/null
+++ b/src/Bootstrap/src/AutoConfiguration/AssemblyLoader.cs
@@ -0,0 +1,93 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information.
+
+using System.Reflection;
+using Steeltoe.Common;
+
+namespace Steeltoe.Bootstrap.AutoConfiguration;
+
+internal sealed class AssemblyLoader
+{
+ public IReadOnlySet AssemblyNamesToExclude { get; }
+
+ static AssemblyLoader()
+ {
+ AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolver.LoadAnyVersion;
+ }
+
+ public AssemblyLoader(IReadOnlySet assemblyNamesToExclude)
+ {
+ ArgumentGuard.NotNull(assemblyNamesToExclude);
+ ArgumentGuard.ElementsNotNullOrEmpty(assemblyNamesToExclude);
+
+ // Take a copy to ensure comparisons are case insensitive.
+ AssemblyNamesToExclude = assemblyNamesToExclude.ToHashSet(StringComparer.OrdinalIgnoreCase);
+ }
+
+ public bool IsAssemblyLoaded(string assemblyName)
+ {
+ ArgumentGuard.NotNullOrEmpty(assemblyName);
+
+ if (AssemblyNamesToExclude.Contains(assemblyName))
+ {
+ return false;
+ }
+
+ return TryLoadAssembly(assemblyName);
+ }
+
+ private static bool TryLoadAssembly(string assemblyName)
+ {
+ try
+ {
+ _ = Assembly.Load(assemblyName);
+ return true;
+ }
+ catch (Exception exception) when (exception is ArgumentException or IOException or BadImageFormatException)
+ {
+ return false;
+ }
+ }
+
+ private static class AssemblyResolver
+ {
+ private static readonly HashSet FailedAssemblyNames = new(StringComparer.OrdinalIgnoreCase);
+
+ public static Assembly? LoadAnyVersion(object? sender, ResolveEventArgs args)
+ {
+ // Workaround for Sonar bug at https://github.com/SonarSource/sonar-dotnet/issues/8371.
+ _ = sender;
+
+ // Load whatever version is available (ignore Version, Culture and PublicKeyToken).
+ string assemblySimpleName = new AssemblyName(args.Name).Name!;
+
+ if (FailedAssemblyNames.Contains(assemblySimpleName))
+ {
+ return null;
+ }
+
+ // AssemblyName.Equals() returns false when path and full name are identical, so the code below
+ // avoids a crash caused by inserting duplicate keys in the dictionary.
+ Dictionary assembliesBySimpleName = AppDomain.CurrentDomain.GetAssemblies().GroupBy(nextAssembly => nextAssembly.GetName().Name!)
+ .ToDictionary(grouping => grouping.Key, grouping => grouping.First(), StringComparer.OrdinalIgnoreCase);
+
+ if (assembliesBySimpleName.TryGetValue(assemblySimpleName, out Assembly? assembly))
+ {
+ return assembly;
+ }
+
+ if (args.Name.Contains(".resources", StringComparison.Ordinal))
+ {
+ return args.RequestingAssembly;
+ }
+
+ // Prevent recursive attempts to resolve.
+ FailedAssemblyNames.Add(assemblySimpleName);
+ assembly = Assembly.Load(assemblySimpleName);
+ FailedAssemblyNames.Remove(assemblySimpleName);
+
+ return assembly;
+ }
+ }
+}
diff --git a/src/Bootstrap/src/AutoConfiguration/BootstrapScanner.cs b/src/Bootstrap/src/AutoConfiguration/BootstrapScanner.cs
new file mode 100644
index 0000000000..c06bdc8937
--- /dev/null
+++ b/src/Bootstrap/src/AutoConfiguration/BootstrapScanner.cs
@@ -0,0 +1,293 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+using Steeltoe.Common;
+using Steeltoe.Common.DynamicTypeAccess;
+using Steeltoe.Common.Hosting;
+using Steeltoe.Configuration.CloudFoundry;
+using Steeltoe.Configuration.ConfigServer;
+using Steeltoe.Configuration.Kubernetes;
+using Steeltoe.Configuration.Placeholder;
+using Steeltoe.Configuration.RandomValue;
+using Steeltoe.Connectors.CosmosDb;
+using Steeltoe.Connectors.CosmosDb.DynamicTypeAccess;
+using Steeltoe.Connectors.MongoDb;
+using Steeltoe.Connectors.MongoDb.DynamicTypeAccess;
+using Steeltoe.Connectors.MySql;
+using Steeltoe.Connectors.MySql.DynamicTypeAccess;
+using Steeltoe.Connectors.PostgreSql;
+using Steeltoe.Connectors.PostgreSql.DynamicTypeAccess;
+using Steeltoe.Connectors.RabbitMQ;
+using Steeltoe.Connectors.RabbitMQ.DynamicTypeAccess;
+using Steeltoe.Connectors.Redis;
+using Steeltoe.Connectors.Redis.DynamicTypeAccess;
+using Steeltoe.Connectors.SqlServer;
+using Steeltoe.Connectors.SqlServer.RuntimeTypeAccess;
+using Steeltoe.Discovery.Client;
+using Steeltoe.Logging.DynamicSerilog;
+using Steeltoe.Management.Endpoint;
+using Steeltoe.Management.Kubernetes;
+using Steeltoe.Management.Prometheus;
+using Steeltoe.Management.Tracing;
+using Steeltoe.Management.Wavefront;
+using Steeltoe.Management.Wavefront.Exporters;
+using Steeltoe.Security.Authentication.CloudFoundry;
+
+namespace Steeltoe.Bootstrap.AutoConfiguration;
+
+internal sealed class BootstrapScanner
+{
+ private readonly HostBuilderWrapper _wrapper;
+ private readonly AssemblyLoader _loader;
+ private readonly ILoggerFactory _loggerFactory;
+ private readonly ILogger _logger;
+
+ public BootstrapScanner(HostBuilderWrapper wrapper, IReadOnlySet assemblyNamesToExclude, ILoggerFactory loggerFactory)
+ {
+ ArgumentGuard.NotNull(wrapper);
+ ArgumentGuard.NotNull(assemblyNamesToExclude);
+ ArgumentGuard.NotNull(loggerFactory);
+
+ _wrapper = wrapper;
+ _loader = new AssemblyLoader(assemblyNamesToExclude);
+ _loggerFactory = loggerFactory;
+ _logger = loggerFactory.CreateLogger("Steeltoe.Bootstrap.AutoConfiguration");
+ }
+
+ public void ConfigureSteeltoe()
+ {
+ if (!WireIfLoaded(WireConfigServer, SteeltoeAssemblyNames.ConfigurationConfigServer))
+ {
+ WireIfLoaded(WireCloudFoundryConfiguration, SteeltoeAssemblyNames.ConfigurationCloudFoundry);
+ }
+
+ if (Platform.IsKubernetes && _loader.IsAssemblyLoaded(SteeltoeAssemblyNames.ConfigurationKubernetes))
+ {
+ WireKubernetesConfiguration();
+ }
+
+ WireIfLoaded(WireRandomValueProvider, SteeltoeAssemblyNames.ConfigurationRandomValue);
+ WireIfLoaded(WirePlaceholderResolver, SteeltoeAssemblyNames.ConfigurationPlaceholder);
+ WireIfLoaded(WireConnectors, SteeltoeAssemblyNames.Connectors);
+ WireIfLoaded(WireDynamicSerilog, SteeltoeAssemblyNames.LoggingDynamicSerilog);
+ WireIfLoaded(WireDiscoveryClient, SteeltoeAssemblyNames.DiscoveryClient);
+
+ if (_loader.IsAssemblyLoaded(SteeltoeAssemblyNames.ManagementKubernetes))
+ {
+ WireIfLoaded(WireKubernetesActuators, SteeltoeAssemblyNames.ManagementKubernetes);
+ }
+ else
+ {
+ WireIfLoaded(WireAllActuators, SteeltoeAssemblyNames.ManagementEndpoint);
+ }
+
+ WireIfLoaded(WirePrometheus, SteeltoeAssemblyNames.ManagementPrometheus);
+ WireIfLoaded(WireWavefrontMetrics, SteeltoeAssemblyNames.ManagementWavefront);
+ WireIfLoaded(WireDistributedTracing, SteeltoeAssemblyNames.ManagementTracing);
+ WireIfLoaded(WireCloudFoundryContainerIdentity, SteeltoeAssemblyNames.SecurityAuthenticationCloudFoundry);
+ }
+
+ private void WireConfigServer()
+ {
+ _wrapper.ConfigureAppConfiguration((context, configurationBuilder) => configurationBuilder.AddConfigServer(context.HostEnvironment, _loggerFactory));
+ _wrapper.ConfigureServices(services => services.AddConfigServerServices());
+
+ _logger.LogInformation("Configured Config Server configuration provider");
+ }
+
+ private void WireCloudFoundryConfiguration()
+ {
+ _wrapper.ConfigureAppConfiguration(configurationBuilder => configurationBuilder.AddCloudFoundry());
+
+ _logger.LogInformation("Configured Cloud Foundry configuration provider");
+ }
+
+ private void WireKubernetesConfiguration()
+ {
+ _wrapper.ConfigureAppConfiguration(configurationBuilder => configurationBuilder.AddKubernetes(_loggerFactory));
+ _wrapper.ConfigureServices(services => services.AddKubernetesConfigurationServices());
+
+ _logger.LogInformation("Configured Kubernetes configuration provider");
+ }
+
+ private void WireRandomValueProvider()
+ {
+ _wrapper.ConfigureAppConfiguration(configurationBuilder => configurationBuilder.AddRandomValueSource(_loggerFactory));
+
+ _logger.LogInformation("Configured random value configuration provider");
+ }
+
+ private void WirePlaceholderResolver()
+ {
+ _wrapper.ConfigureAppConfiguration(configurationBuilder => configurationBuilder.AddPlaceholderResolver(_loggerFactory));
+
+ _logger.LogInformation("Configured placeholder configuration provider");
+ }
+
+ private void WireConnectors()
+ {
+ WireIfAnyLoaded(WireCosmosDbConnector, CosmosDbPackageResolver.Default);
+ WireIfAnyLoaded(WireMongoDbConnector, MongoDbPackageResolver.Default);
+ WireIfAnyLoaded(WireMySqlConnector, MySqlPackageResolver.Default);
+ WireIfAnyLoaded(WirePostgreSqlConnector, PostgreSqlPackageResolver.Default);
+ WireIfAnyLoaded(WireRabbitMQConnector, RabbitMQPackageResolver.Default);
+ WireIfAnyLoaded(WireRedisConnector, StackExchangeRedisPackageResolver.Default, MicrosoftRedisPackageResolver.Default);
+ WireIfAnyLoaded(WireSqlServerConnector, SqlServerPackageResolver.Default);
+ }
+
+ private void WireCosmosDbConnector()
+ {
+ _wrapper.ConfigureAppConfiguration(configurationBuilder => configurationBuilder.ConfigureCosmosDb());
+ _wrapper.ConfigureServices((host, services) => services.AddCosmosDb(host.Configuration));
+
+ _logger.LogInformation("Configured CosmosDB connector");
+ }
+
+ private void WireMongoDbConnector()
+ {
+ _wrapper.ConfigureAppConfiguration(configurationBuilder => configurationBuilder.ConfigureMongoDb());
+ _wrapper.ConfigureServices((host, services) => services.AddMongoDb(host.Configuration));
+
+ _logger.LogInformation("Configured MongoDB connector");
+ }
+
+ private void WireMySqlConnector()
+ {
+ _wrapper.ConfigureAppConfiguration(configurationBuilder => configurationBuilder.ConfigureMySql());
+ _wrapper.ConfigureServices((host, services) => services.AddMySql(host.Configuration));
+
+ _logger.LogInformation("Configured MySQL connector");
+ }
+
+ private void WirePostgreSqlConnector()
+ {
+ _wrapper.ConfigureAppConfiguration(configurationBuilder => configurationBuilder.ConfigurePostgreSql());
+ _wrapper.ConfigureServices((host, services) => services.AddPostgreSql(host.Configuration));
+
+ _logger.LogInformation("Configured PostgreSQL connector");
+ }
+
+ private void WireRabbitMQConnector()
+ {
+ _wrapper.ConfigureAppConfiguration(configurationBuilder => configurationBuilder.ConfigureRabbitMQ());
+ _wrapper.ConfigureServices((host, services) => services.AddRabbitMQ(host.Configuration));
+
+ _logger.LogInformation("Configured RabbitMQ connector");
+ }
+
+ private void WireRedisConnector()
+ {
+ _wrapper.ConfigureAppConfiguration(configurationBuilder => configurationBuilder.ConfigureRedis());
+ _wrapper.ConfigureServices((host, services) => services.AddRedis(host.Configuration));
+
+ _logger.LogInformation("Configured StackExchange Redis connector");
+
+ // Intentionally ignoring excluded assemblies here.
+ if (MicrosoftRedisPackageResolver.Default.IsAvailable())
+ {
+ _logger.LogInformation("Configured Redis distributed cache connector");
+ }
+ }
+
+ private void WireSqlServerConnector()
+ {
+ _wrapper.ConfigureAppConfiguration(configurationBuilder => configurationBuilder.ConfigureSqlServer());
+ _wrapper.ConfigureServices((host, services) => services.AddSqlServer(host.Configuration));
+
+ _logger.LogInformation("Configured SQL Server connector");
+ }
+
+ private void WireDynamicSerilog()
+ {
+ _wrapper.AddDynamicSerilog(null, false);
+
+ _logger.LogInformation("Configured dynamic console logger for Serilog");
+ }
+
+ private void WireDiscoveryClient()
+ {
+ _wrapper.ConfigureServices((context, services) => services.AddDiscoveryClient(context.Configuration));
+
+ _logger.LogInformation("Configured discovery client");
+ }
+
+ private void WireKubernetesActuators()
+ {
+ _wrapper.AddKubernetesActuators(null);
+
+ _logger.LogInformation("Configured Kubernetes actuators");
+ }
+
+ private void WireAllActuators()
+ {
+ _wrapper.AddAllActuators(null, MediaTypeVersion.V2, null);
+
+ _logger.LogInformation("Configured actuators");
+ }
+
+ private void WirePrometheus()
+ {
+ _wrapper.ConfigureServices(services => services.AddPrometheusActuator());
+
+ _logger.LogInformation("Configured Prometheus");
+ }
+
+ private void WireWavefrontMetrics()
+ {
+ _wrapper.ConfigureServices((context, services) =>
+ {
+ if (HasWavefront(context.Configuration))
+ {
+ services.AddWavefrontMetrics();
+ _logger.LogInformation("Configured Wavefront metrics");
+ }
+ });
+ }
+
+ private static bool HasWavefront(IConfiguration configuration)
+ {
+ var options = new WavefrontExporterOptions();
+
+ var configurer = new ConfigureWavefrontExporterOptions(configuration);
+ configurer.Configure(options);
+
+ return !string.IsNullOrEmpty(options.Uri);
+ }
+
+ private void WireDistributedTracing()
+ {
+ _wrapper.ConfigureServices(services => services.AddDistributedTracingAspNetCore());
+
+ _logger.LogInformation("Configured distributed tracing");
+ }
+
+ private void WireCloudFoundryContainerIdentity()
+ {
+ _wrapper.ConfigureAppConfiguration(configurationBuilder => configurationBuilder.AddCloudFoundryContainerIdentity());
+ _wrapper.ConfigureServices(services => services.AddCloudFoundryCertificateAuth());
+
+ _logger.LogInformation("Configured Cloud Foundry mTLS security");
+ }
+
+ private bool WireIfLoaded(Action wireAction, string assemblyName)
+ {
+ if (!_loader.IsAssemblyLoaded(assemblyName))
+ {
+ return false;
+ }
+
+ wireAction();
+ return true;
+ }
+
+ private void WireIfAnyLoaded(Action wireAction, params PackageResolver[] packageResolvers)
+ {
+ if (Array.Exists(packageResolvers, packageResolver => packageResolver.IsAvailable(_loader.AssemblyNamesToExclude)))
+ {
+ wireAction();
+ }
+ }
+}
diff --git a/src/Bootstrap/src/AutoConfiguration/ConfigurationExtensions.cs b/src/Bootstrap/src/AutoConfiguration/ConfigurationExtensions.cs
deleted file mode 100644
index 55bc4db0fc..0000000000
--- a/src/Bootstrap/src/AutoConfiguration/ConfigurationExtensions.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information.
-
-using Microsoft.Extensions.Configuration;
-using Steeltoe.Common;
-using Steeltoe.Management.Wavefront.Exporters;
-
-namespace Steeltoe.Bootstrap.AutoConfiguration;
-
-internal static class ConfigurationExtensions
-{
- public static bool HasWavefront(this IConfiguration configuration)
- {
- ArgumentGuard.NotNull(configuration);
-
- var options = new WavefrontExporterOptions();
-
- var configurer = new ConfigureWavefrontExporterOptions(configuration);
- configurer.Configure(options);
-
- return !string.IsNullOrEmpty(options.Uri);
- }
-}
diff --git a/src/Bootstrap/src/AutoConfiguration/HostBuilderExtensions.cs b/src/Bootstrap/src/AutoConfiguration/HostBuilderExtensions.cs
index 403ad11d82..fb9365b22d 100644
--- a/src/Bootstrap/src/AutoConfiguration/HostBuilderExtensions.cs
+++ b/src/Bootstrap/src/AutoConfiguration/HostBuilderExtensions.cs
@@ -2,355 +2,93 @@
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.
-using System.Runtime.CompilerServices;
+using System.Collections.Immutable;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Steeltoe.Common;
-using Steeltoe.Common.DynamicTypeAccess;
-using Steeltoe.Configuration.CloudFoundry;
-using Steeltoe.Configuration.ConfigServer;
-using Steeltoe.Configuration.Kubernetes;
-using Steeltoe.Configuration.Placeholder;
-using Steeltoe.Configuration.RandomValue;
-using Steeltoe.Connectors.CosmosDb;
-using Steeltoe.Connectors.CosmosDb.DynamicTypeAccess;
-using Steeltoe.Connectors.MongoDb;
-using Steeltoe.Connectors.MongoDb.DynamicTypeAccess;
-using Steeltoe.Connectors.MySql;
-using Steeltoe.Connectors.MySql.DynamicTypeAccess;
-using Steeltoe.Connectors.PostgreSql;
-using Steeltoe.Connectors.PostgreSql.DynamicTypeAccess;
-using Steeltoe.Connectors.RabbitMQ;
-using Steeltoe.Connectors.RabbitMQ.DynamicTypeAccess;
-using Steeltoe.Connectors.Redis;
-using Steeltoe.Connectors.Redis.DynamicTypeAccess;
-using Steeltoe.Connectors.SqlServer;
-using Steeltoe.Connectors.SqlServer.RuntimeTypeAccess;
-using Steeltoe.Discovery.Client;
-using Steeltoe.Logging.DynamicSerilog;
-using Steeltoe.Management.Endpoint;
-using Steeltoe.Management.Kubernetes;
-using Steeltoe.Management.Prometheus;
-using Steeltoe.Management.Tracing;
-using Steeltoe.Management.Wavefront;
-using Steeltoe.Security.Authentication.CloudFoundry;
+using Steeltoe.Common.Hosting;
namespace Steeltoe.Bootstrap.AutoConfiguration;
public static class HostBuilderExtensions
{
- private const string LoggerName = "Steeltoe.AutoConfiguration";
- private static ILoggerFactory _loggerFactory;
+ private static readonly IReadOnlySet EmptySet = ImmutableHashSet.Empty;
- static HostBuilderExtensions()
+ ///
+ /// Automatically configures Steeltoe packages that have been added to your project as NuGet references.
+ ///
+ ///
+ /// The to configure.
+ ///
+ ///
+ /// The incoming , so that additional calls can be chained.
+ ///
+ public static IHostBuilder AddSteeltoe(this IHostBuilder builder)
{
- AppDomain currentDomain = AppDomain.CurrentDomain;
- currentDomain.AssemblyResolve += AssemblyExtensions.LoadAnyVersion;
+ return AddSteeltoe(builder, EmptySet, NullLoggerFactory.Instance);
}
///
- /// Automatically configure Steeltoe packages that have been added as NuGet references.
- ///
- /// PLEASE NOTE: No extensions to IApplicationBuilder will be configured.
+ /// Automatically configures Steeltoe packages that have been added to your project as NuGet references.
///
///
- /// Your .
+ /// The to configure.
///
- ///
- /// A list of assemblies to exclude from auto-configuration. For ease of use, select from .
+ ///
+ /// The set of assembly names to exclude from auto-configuration. For ease of use, select from the constants in .
///
- ///
- /// For logging within auto-configuration.
- ///
- public static IHostBuilder AddSteeltoe(this IHostBuilder builder, IEnumerable exclusions = null, ILoggerFactory loggerFactory = null)
- {
- AssemblyExtensions.ExcludedAssemblies = exclusions ?? new List();
- _loggerFactory = loggerFactory ?? NullLoggerFactory.Instance;
- ILogger logger = _loggerFactory.CreateLogger(LoggerName);
- builder.Properties[LoggerName] = logger;
-
- if (!builder.WireIfLoaded(WireConfigServer, SteeltoeAssemblyNames.ConfigurationConfigServer))
- {
- builder.WireIfLoaded(WireCloudFoundryConfiguration, SteeltoeAssemblyNames.ConfigurationCloudFoundry);
- }
-
- if (Platform.IsKubernetes && AssemblyExtensions.IsAssemblyLoaded(SteeltoeAssemblyNames.ConfigurationKubernetes))
- {
- WireKubernetesConfiguration(builder);
- }
-
- builder.WireIfLoaded(WireRandomValueProvider, SteeltoeAssemblyNames.ConfigurationRandomValue);
-
- builder.WireIfLoaded(WirePlaceholderResolver, SteeltoeAssemblyNames.ConfigurationPlaceholder);
-
- builder.WireIfLoaded(WireConnectors, SteeltoeAssemblyNames.Connectors);
-
- builder.WireIfLoaded(WireDynamicSerilog, SteeltoeAssemblyNames.LoggingDynamicSerilog);
- builder.WireIfLoaded(WireDiscoveryClient, SteeltoeAssemblyNames.DiscoveryClient);
-
- if (AssemblyExtensions.IsAssemblyLoaded(SteeltoeAssemblyNames.ManagementKubernetes))
- {
- builder.WireIfLoaded(WireKubernetesActuators, SteeltoeAssemblyNames.ManagementKubernetes);
- }
- else
- {
- builder.WireIfLoaded(WireAllActuators, SteeltoeAssemblyNames.ManagementEndpoint);
- }
-
- builder.WireIfLoaded(WireSteeltoePrometheus, SteeltoeAssemblyNames.ManagementPrometheus);
-
- builder.WireIfLoaded(WireWavefrontMetrics, SteeltoeAssemblyNames.ManagementWavefront);
-
- builder.WireIfLoaded(WireDistributedTracing, SteeltoeAssemblyNames.ManagementTracing);
-
- builder.WireIfLoaded(WireCloudFoundryContainerIdentity, SteeltoeAssemblyNames.SecurityAuthenticationCloudFoundry);
- return builder;
- }
-
- private static bool WireIfLoaded(this IHostBuilder hostBuilder, Action action, params string[] assembly)
- {
- if (Array.TrueForAll(assembly, AssemblyExtensions.IsAssemblyLoaded))
- {
- action(hostBuilder);
- return true;
- }
-
- return false;
- }
-
- private static void WireIfAnyLoaded(this IHostBuilder hostBuilder, Action action, IReadOnlySet assemblyNamesToExclude,
- params PackageResolver[] packageResolvers)
- {
- if (Array.Exists(packageResolvers, packageResolver => packageResolver.IsAvailable(assemblyNamesToExclude)))
- {
- action(hostBuilder);
- }
- }
-
- private static void Log(this IHostBuilder host, string message)
- {
- var logger = (ILogger)host.Properties[LoggerName];
- logger.LogInformation(message);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireConfigServer(this IHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration((context, cfg) => cfg.AddConfigServer(context.HostingEnvironment, _loggerFactory))
- .ConfigureServices((_, services) => services.AddConfigServerServices()).Log(LogMessages.WireConfigServerConfiguration);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireCloudFoundryConfiguration(this IHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(cfg => cfg.AddCloudFoundry()).Log(LogMessages.WireCloudFoundryConfiguration);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireKubernetesConfiguration(this IHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(cfg => cfg.AddKubernetes(_loggerFactory))
- .ConfigureServices(serviceCollection => serviceCollection.AddKubernetesConfigurationServices()).Log(LogMessages.WireKubernetesConfiguration);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireRandomValueProvider(this IHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(cfg => cfg.AddRandomValueSource(_loggerFactory)).Log(LogMessages.WireRandomValueConfiguration);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WirePlaceholderResolver(this IHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(cfg => cfg.AddPlaceholderResolver(_loggerFactory)).Log(LogMessages.WirePlaceholderConfiguration);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireConnectors(IHostBuilder builder)
- {
- var assemblyNamesToExclude = new HashSet(AssemblyExtensions.ExcludedAssemblies, StringComparer.OrdinalIgnoreCase);
-
- builder.WireIfAnyLoaded(WireCosmosDbConnector, assemblyNamesToExclude, CosmosDbPackageResolver.Default);
- builder.WireIfAnyLoaded(WireMongoDbConnector, assemblyNamesToExclude, MongoDbPackageResolver.Default);
- builder.WireIfAnyLoaded(WireMySqlConnector, assemblyNamesToExclude, MySqlPackageResolver.Default);
- builder.WireIfAnyLoaded(WirePostgreSqlConnector, assemblyNamesToExclude, PostgreSqlPackageResolver.Default);
- builder.WireIfAnyLoaded(WireRabbitMQConnector, assemblyNamesToExclude, RabbitMQPackageResolver.Default);
- builder.WireIfAnyLoaded(WireRedisConnector, assemblyNamesToExclude, StackExchangeRedisPackageResolver.Default, MicrosoftRedisPackageResolver.Default);
- builder.WireIfAnyLoaded(WireSqlServerConnector, assemblyNamesToExclude, SqlServerPackageResolver.Default);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireMySqlConnector(this IHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(configurationBuilder =>
- {
- configurationBuilder.ConfigureMySql();
- });
-
- hostBuilder.ConfigureServices((host, services) =>
- {
- services.AddMySql(host.Configuration);
- });
-
- hostBuilder.Log(LogMessages.WireMySqlConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireCosmosDbConnector(this IHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(configurationBuilder =>
- {
- configurationBuilder.ConfigureCosmosDb();
- });
-
- hostBuilder.ConfigureServices((host, services) =>
- {
- services.AddCosmosDb(host.Configuration);
- });
-
- hostBuilder.Log(LogMessages.WireCosmosDbConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireMongoDbConnector(this IHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(configurationBuilder =>
- {
- configurationBuilder.ConfigureMongoDb();
- });
-
- hostBuilder.ConfigureServices((host, services) =>
- {
- services.AddMongoDb(host.Configuration);
- });
-
- hostBuilder.Log(LogMessages.WireMongoDbConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WirePostgreSqlConnector(this IHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(configurationBuilder =>
- {
- configurationBuilder.ConfigurePostgreSql();
- });
-
- hostBuilder.ConfigureServices((host, services) =>
- {
- services.AddPostgreSql(host.Configuration);
- });
-
- hostBuilder.Log(LogMessages.WirePostgreSqlConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireRabbitMQConnector(this IHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(configurationBuilder =>
- {
- configurationBuilder.ConfigureRabbitMQ();
- });
-
- hostBuilder.ConfigureServices((host, services) =>
- {
- services.AddRabbitMQ(host.Configuration);
- });
-
- hostBuilder.Log(LogMessages.WireRabbitMQConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireRedisConnector(this IHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(configurationBuilder =>
- {
- configurationBuilder.ConfigureRedis();
- });
-
- hostBuilder.ConfigureServices((host, services) =>
- {
- services.AddRedis(host.Configuration);
- });
-
- hostBuilder.Log(LogMessages.WireStackExchangeRedisConnector);
-
- // Intentionally ignoring excluded assemblies here.
- if (MicrosoftRedisPackageResolver.Default.IsAvailable())
- {
- hostBuilder.Log(LogMessages.WireDistributedCacheRedisConnector);
- }
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireSqlServerConnector(this IHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(configurationBuilder =>
- {
- configurationBuilder.ConfigureSqlServer();
- });
-
- hostBuilder.ConfigureServices((host, services) =>
- {
- services.AddSqlServer(host.Configuration);
- });
-
- hostBuilder.Log(LogMessages.WireSqlServerConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireDiscoveryClient(this IHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureServices((host, svc) => svc.AddDiscoveryClient(host.Configuration)).Log(LogMessages.WireDiscoveryClient);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireDistributedTracing(this IHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureServices((_, svc) => svc.AddDistributedTracingAspNetCore()).Log(LogMessages.WireDistributedTracing);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireKubernetesActuators(this IHostBuilder hostBuilder)
+ ///
+ /// The incoming , so that additional calls can be chained.
+ ///
+ public static IHostBuilder AddSteeltoe(this IHostBuilder builder, IReadOnlySet assemblyNamesToExclude)
{
- hostBuilder.AddKubernetesActuators().Log(LogMessages.WireKubernetesActuators);
+ return AddSteeltoe(builder, assemblyNamesToExclude, NullLoggerFactory.Instance);
}
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireAllActuators(this IHostBuilder hostBuilder)
+ ///
+ /// Automatically configures Steeltoe packages that have been added to your project as NuGet references.
+ ///
+ ///
+ /// The to configure.
+ ///
+ ///
+ /// Used for internal logging. Pass to disable logging.
+ ///
+ ///
+ /// The incoming , so that additional calls can be chained.
+ ///
+ public static IHostBuilder AddSteeltoe(this IHostBuilder builder, ILoggerFactory loggerFactory)
{
- hostBuilder.AddAllActuators().Log(LogMessages.WireAllActuators);
+ return AddSteeltoe(builder, EmptySet, loggerFactory);
}
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireWavefrontMetrics(this IHostBuilder hostBuilder)
+ ///
+ /// Automatically configures Steeltoe packages that have been added to your project as NuGet references.
+ ///
+ ///
+ /// The to configure.
+ ///
+ ///
+ /// The set of assembly names to exclude from auto-configuration. For ease of use, select from the constants in .
+ ///
+ ///
+ /// Used for internal logging. Pass to disable logging.
+ ///
+ ///
+ /// The incoming , so that additional calls can be chained.
+ ///
+ public static IHostBuilder AddSteeltoe(this IHostBuilder builder, IReadOnlySet assemblyNamesToExclude, ILoggerFactory loggerFactory)
{
- hostBuilder.ConfigureServices((context, collection) =>
- {
- if (context.Configuration.HasWavefront())
- {
- collection.AddWavefrontMetrics();
- hostBuilder.Log(LogMessages.WireWavefrontMetrics);
- }
- });
- }
+ ArgumentGuard.NotNull(builder);
+ ArgumentGuard.NotNull(assemblyNamesToExclude);
+ ArgumentGuard.NotNull(loggerFactory);
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireSteeltoePrometheus(this IHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureServices((_, collection) => collection.AddPrometheusActuator()).Log(LogMessages.WirePrometheus);
- }
+ HostBuilderWrapper wrapper = HostBuilderWrapper.Wrap(builder);
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireDynamicSerilog(this IHostBuilder hostBuilder)
- {
- hostBuilder.AddDynamicSerilog().Log(LogMessages.WireDynamicSerilog);
- }
+ var scanner = new BootstrapScanner(wrapper, assemblyNamesToExclude, loggerFactory);
+ scanner.ConfigureSteeltoe();
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireCloudFoundryContainerIdentity(this IHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(cfg => cfg.AddCloudFoundryContainerIdentity()).ConfigureServices((_, svc) => svc.AddCloudFoundryCertificateAuth())
- .Log(LogMessages.WireCloudFoundryContainerIdentity);
+ return builder;
}
}
diff --git a/src/Bootstrap/src/AutoConfiguration/LogMessages.cs b/src/Bootstrap/src/AutoConfiguration/LogMessages.cs
deleted file mode 100644
index b321f3c85e..0000000000
--- a/src/Bootstrap/src/AutoConfiguration/LogMessages.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information.
-
-namespace Steeltoe.Bootstrap.AutoConfiguration;
-
-internal static class LogMessages
-{
- public const string WireAllActuators = "Configured actuators";
- public const string WireKubernetesActuators = "Configured Kubernetes actuators";
-
- public const string WireCloudFoundryConfiguration = "Configured Cloud Foundry configuration provider";
- public const string WireKubernetesConfiguration = "Configured Kubernetes configuration provider";
- public const string WireConfigServerConfiguration = "Configured Config Server configuration provider";
- public const string WirePlaceholderConfiguration = "Configured placeholder configuration provider";
- public const string WireRandomValueConfiguration = "Configured random value configuration provider";
-
- public const string WireCloudFoundryContainerIdentity = "Configured Cloud Foundry MTLs security";
- public const string WireDiscoveryClient = "Configured discovery client";
- public const string WireDistributedTracing = "Configured distributed tracing";
- public const string WireDynamicSerilog = "Configured dynamic console logger for Serilog";
- public const string WireWavefrontMetrics = "Configured Wavefront metrics";
- public const string WirePrometheus = "Configured Prometheus";
-
- public const string WireCosmosDbConnector = "Configured CosmosDB connector";
- public const string WireMongoDbConnector = "Configured MongoDB connector";
- public const string WireMySqlConnector = "Configured MySQL connector";
- public const string WirePostgreSqlConnector = "Configured PostgreSQL connector";
- public const string WireRabbitMQConnector = "Configured RabbitMQ connector";
- public const string WireStackExchangeRedisConnector = "Configured StackExchange Redis connector";
- public const string WireDistributedCacheRedisConnector = "Configured Redis distributed cache connector";
- public const string WireSqlServerConnector = "Configured SQL Server connector";
-}
diff --git a/src/Bootstrap/src/AutoConfiguration/PublicAPI.Shipped.txt b/src/Bootstrap/src/AutoConfiguration/PublicAPI.Shipped.txt
new file mode 100644
index 0000000000..5f282702bb
--- /dev/null
+++ b/src/Bootstrap/src/AutoConfiguration/PublicAPI.Shipped.txt
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/Bootstrap/src/AutoConfiguration/PublicAPI.Unshipped.txt b/src/Bootstrap/src/AutoConfiguration/PublicAPI.Unshipped.txt
new file mode 100644
index 0000000000..d16ec2189c
--- /dev/null
+++ b/src/Bootstrap/src/AutoConfiguration/PublicAPI.Unshipped.txt
@@ -0,0 +1,31 @@
+#nullable enable
+const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ConfigurationCloudFoundry = "Steeltoe.Configuration.CloudFoundry" -> string!
+const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ConfigurationConfigServer = "Steeltoe.Configuration.ConfigServer" -> string!
+const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ConfigurationKubernetes = "Steeltoe.Configuration.Kubernetes" -> string!
+const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ConfigurationPlaceholder = "Steeltoe.Configuration.Placeholder" -> string!
+const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ConfigurationRandomValue = "Steeltoe.Configuration.RandomValue" -> string!
+const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.Connectors = "Steeltoe.Connectors" -> string!
+const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.DiscoveryClient = "Steeltoe.Discovery.Client" -> string!
+const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.LoggingDynamicSerilog = "Steeltoe.Logging.DynamicSerilog" -> string!
+const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ManagementEndpoint = "Steeltoe.Management.Endpoint" -> string!
+const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ManagementKubernetes = "Steeltoe.Management.Kubernetes" -> string!
+const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ManagementPrometheus = "Steeltoe.Management.Prometheus" -> string!
+const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ManagementTracing = "Steeltoe.Management.Tracing" -> string!
+const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ManagementWavefront = "Steeltoe.Management.Wavefront" -> string!
+const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.SecurityAuthenticationCloudFoundry = "Steeltoe.Security.Authentication.CloudFoundry" -> string!
+static Steeltoe.Bootstrap.AutoConfiguration.HostBuilderExtensions.AddSteeltoe(this Microsoft.Extensions.Hosting.IHostBuilder! builder) -> Microsoft.Extensions.Hosting.IHostBuilder!
+static Steeltoe.Bootstrap.AutoConfiguration.HostBuilderExtensions.AddSteeltoe(this Microsoft.Extensions.Hosting.IHostBuilder! builder, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> Microsoft.Extensions.Hosting.IHostBuilder!
+static Steeltoe.Bootstrap.AutoConfiguration.HostBuilderExtensions.AddSteeltoe(this Microsoft.Extensions.Hosting.IHostBuilder! builder, System.Collections.Generic.IReadOnlySet! assemblyNamesToExclude) -> Microsoft.Extensions.Hosting.IHostBuilder!
+static Steeltoe.Bootstrap.AutoConfiguration.HostBuilderExtensions.AddSteeltoe(this Microsoft.Extensions.Hosting.IHostBuilder! builder, System.Collections.Generic.IReadOnlySet! assemblyNamesToExclude, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> Microsoft.Extensions.Hosting.IHostBuilder!
+static Steeltoe.Bootstrap.AutoConfiguration.WebApplicationBuilderExtensions.AddSteeltoe(this Microsoft.AspNetCore.Builder.WebApplicationBuilder! builder) -> Microsoft.AspNetCore.Builder.WebApplicationBuilder!
+static Steeltoe.Bootstrap.AutoConfiguration.WebApplicationBuilderExtensions.AddSteeltoe(this Microsoft.AspNetCore.Builder.WebApplicationBuilder! builder, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> Microsoft.AspNetCore.Builder.WebApplicationBuilder!
+static Steeltoe.Bootstrap.AutoConfiguration.WebApplicationBuilderExtensions.AddSteeltoe(this Microsoft.AspNetCore.Builder.WebApplicationBuilder! builder, System.Collections.Generic.IReadOnlySet! assemblyNamesToExclude) -> Microsoft.AspNetCore.Builder.WebApplicationBuilder!
+static Steeltoe.Bootstrap.AutoConfiguration.WebApplicationBuilderExtensions.AddSteeltoe(this Microsoft.AspNetCore.Builder.WebApplicationBuilder! builder, System.Collections.Generic.IReadOnlySet! assemblyNamesToExclude, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> Microsoft.AspNetCore.Builder.WebApplicationBuilder!
+static Steeltoe.Bootstrap.AutoConfiguration.WebHostBuilderExtensions.AddSteeltoe(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder!
+static Steeltoe.Bootstrap.AutoConfiguration.WebHostBuilderExtensions.AddSteeltoe(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder!
+static Steeltoe.Bootstrap.AutoConfiguration.WebHostBuilderExtensions.AddSteeltoe(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, System.Collections.Generic.IReadOnlySet! assemblyNamesToExclude) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder!
+static Steeltoe.Bootstrap.AutoConfiguration.WebHostBuilderExtensions.AddSteeltoe(this Microsoft.AspNetCore.Hosting.IWebHostBuilder! builder, System.Collections.Generic.IReadOnlySet! assemblyNamesToExclude, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> Microsoft.AspNetCore.Hosting.IWebHostBuilder!
+Steeltoe.Bootstrap.AutoConfiguration.HostBuilderExtensions
+Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames
+Steeltoe.Bootstrap.AutoConfiguration.WebApplicationBuilderExtensions
+Steeltoe.Bootstrap.AutoConfiguration.WebHostBuilderExtensions
diff --git a/src/Bootstrap/src/AutoConfiguration/Steeltoe.Bootstrap.AutoConfiguration.csproj b/src/Bootstrap/src/AutoConfiguration/Steeltoe.Bootstrap.AutoConfiguration.csproj
index 39eb33e85e..b1de6e9108 100644
--- a/src/Bootstrap/src/AutoConfiguration/Steeltoe.Bootstrap.AutoConfiguration.csproj
+++ b/src/Bootstrap/src/AutoConfiguration/Steeltoe.Bootstrap.AutoConfiguration.csproj
@@ -4,6 +4,7 @@
Package for automatically configuring Steeltoe packages that have separately been added to a project.
Autoconfiguration;automatic configuration;application bootstrapping
true
+ enable
@@ -13,6 +14,7 @@
+
diff --git a/src/Bootstrap/src/AutoConfiguration/SteeltoeAssemblyNames.cs b/src/Bootstrap/src/AutoConfiguration/SteeltoeAssemblyNames.cs
index cd5c279b68..e34691d2d8 100644
--- a/src/Bootstrap/src/AutoConfiguration/SteeltoeAssemblyNames.cs
+++ b/src/Bootstrap/src/AutoConfiguration/SteeltoeAssemblyNames.cs
@@ -6,6 +6,9 @@
namespace Steeltoe.Bootstrap.AutoConfiguration;
+///
+/// Lists the names of Steeltoe assemblies that are used in auto-configuration.
+///
public static class SteeltoeAssemblyNames
{
public const string ConfigurationCloudFoundry = "Steeltoe.Configuration.CloudFoundry";
@@ -23,6 +26,14 @@ public static class SteeltoeAssemblyNames
public const string ManagementWavefront = "Steeltoe.Management.Wavefront";
public const string SecurityAuthenticationCloudFoundry = "Steeltoe.Security.Authentication.CloudFoundry";
- internal static readonly IReadOnlyCollection All = typeof(SteeltoeAssemblyNames).GetFields().Where(field => field.FieldType == typeof(string))
- .Select(field => field.GetValue(null)).Cast().ToArray();
+ internal static readonly IReadOnlySet All = typeof(SteeltoeAssemblyNames).GetFields().Where(field => field.FieldType == typeof(string))
+ .Select(field => field.GetValue(null)).Cast().ToHashSet();
+
+ internal static IReadOnlySet Only(string assemblyName)
+ {
+ return All.Except(new[]
+ {
+ assemblyName
+ }).ToHashSet();
+ }
}
diff --git a/src/Bootstrap/src/AutoConfiguration/WebApplicationBuilderExtensions.cs b/src/Bootstrap/src/AutoConfiguration/WebApplicationBuilderExtensions.cs
index 4ae4fca40a..9abfd857d0 100644
--- a/src/Bootstrap/src/AutoConfiguration/WebApplicationBuilderExtensions.cs
+++ b/src/Bootstrap/src/AutoConfiguration/WebApplicationBuilderExtensions.cs
@@ -2,308 +2,94 @@
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.
-using System.Runtime.CompilerServices;
+using System.Collections.Immutable;
using Microsoft.AspNetCore.Builder;
-using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Steeltoe.Common;
-using Steeltoe.Common.DynamicTypeAccess;
-using Steeltoe.Configuration.CloudFoundry;
-using Steeltoe.Configuration.ConfigServer;
-using Steeltoe.Configuration.Kubernetes;
-using Steeltoe.Configuration.Placeholder;
-using Steeltoe.Configuration.RandomValue;
-using Steeltoe.Connectors.CosmosDb;
-using Steeltoe.Connectors.CosmosDb.DynamicTypeAccess;
-using Steeltoe.Connectors.MongoDb;
-using Steeltoe.Connectors.MongoDb.DynamicTypeAccess;
-using Steeltoe.Connectors.MySql;
-using Steeltoe.Connectors.MySql.DynamicTypeAccess;
-using Steeltoe.Connectors.PostgreSql;
-using Steeltoe.Connectors.PostgreSql.DynamicTypeAccess;
-using Steeltoe.Connectors.RabbitMQ;
-using Steeltoe.Connectors.RabbitMQ.DynamicTypeAccess;
-using Steeltoe.Connectors.Redis;
-using Steeltoe.Connectors.Redis.DynamicTypeAccess;
-using Steeltoe.Connectors.SqlServer;
-using Steeltoe.Connectors.SqlServer.RuntimeTypeAccess;
-using Steeltoe.Discovery.Client;
-using Steeltoe.Logging.DynamicLogger;
-using Steeltoe.Logging.DynamicSerilog;
-using Steeltoe.Management.Endpoint;
-using Steeltoe.Management.Kubernetes;
-using Steeltoe.Management.Prometheus;
-using Steeltoe.Management.Tracing;
-using Steeltoe.Management.Wavefront;
-using Steeltoe.Security.Authentication.CloudFoundry;
+using Steeltoe.Common.Hosting;
namespace Steeltoe.Bootstrap.AutoConfiguration;
public static class WebApplicationBuilderExtensions
{
- private const string LoggerName = "Steeltoe.AutoConfiguration";
- private static ILoggerFactory _loggerFactory;
- private static ILogger _logger;
+ private static readonly IReadOnlySet EmptySet = ImmutableHashSet.Empty;
- static WebApplicationBuilderExtensions()
+ ///
+ /// Automatically configures Steeltoe packages that have been added to your project as NuGet references.
+ ///
+ ///
+ /// The to configure.
+ ///
+ ///
+ /// The incoming , so that additional calls can be chained.
+ ///
+ public static WebApplicationBuilder AddSteeltoe(this WebApplicationBuilder builder)
{
- AppDomain currentDomain = AppDomain.CurrentDomain;
- currentDomain.AssemblyResolve += AssemblyExtensions.LoadAnyVersion;
+ return AddSteeltoe(builder, EmptySet, NullLoggerFactory.Instance);
}
///
- /// Automatically configure Steeltoe packages that have been added as NuGet references.
- ///
- /// PLEASE NOTE: No extensions to IApplicationBuilder will be configured.
+ /// Automatically configures Steeltoe packages that have been added to your project as NuGet references.
///
///
- /// Your .
+ /// The to configure.
///
- ///
- /// A list of assemblies to exclude from auto-configuration. For ease of use, select from .
+ ///
+ /// The set of assembly names to exclude from auto-configuration. For ease of use, select from the constants in .
///
- ///
- /// For logging within auto-configuration.
- ///
- public static WebApplicationBuilder AddSteeltoe(this WebApplicationBuilder builder, IEnumerable exclusions = null,
- ILoggerFactory loggerFactory = null)
- {
- AssemblyExtensions.ExcludedAssemblies = exclusions ?? new List();
- _loggerFactory = loggerFactory ?? NullLoggerFactory.Instance;
- _logger = _loggerFactory.CreateLogger(LoggerName);
-
- if (!builder.WireIfLoaded(WireConfigServer, SteeltoeAssemblyNames.ConfigurationConfigServer))
- {
- builder.WireIfLoaded(WireCloudFoundryConfiguration, SteeltoeAssemblyNames.ConfigurationCloudFoundry);
- }
-
- if (Platform.IsKubernetes && AssemblyExtensions.IsAssemblyLoaded(SteeltoeAssemblyNames.ConfigurationKubernetes))
- {
- WireKubernetesConfiguration(builder);
- }
-
- builder.WireIfLoaded(WireRandomValueProvider, SteeltoeAssemblyNames.ConfigurationRandomValue);
-
- builder.WireIfLoaded(WirePlaceholderResolver, SteeltoeAssemblyNames.ConfigurationPlaceholder);
-
- builder.WireIfLoaded(WireConnectors, SteeltoeAssemblyNames.Connectors);
-
- builder.WireIfLoaded(WireDynamicSerilog, SteeltoeAssemblyNames.LoggingDynamicSerilog);
-
- builder.WireIfLoaded(WireDiscoveryClient, SteeltoeAssemblyNames.DiscoveryClient);
-
- if (AssemblyExtensions.IsAssemblyLoaded(SteeltoeAssemblyNames.ManagementKubernetes))
- {
- builder.WireIfLoaded(WireKubernetesActuators, SteeltoeAssemblyNames.ManagementKubernetes);
- }
- else
- {
- builder.WireIfLoaded(WireAllActuators, SteeltoeAssemblyNames.ManagementEndpoint);
- }
-
- builder.WireIfLoaded(WireSteeltoePrometheus, SteeltoeAssemblyNames.ManagementPrometheus);
-
- builder.WireIfLoaded(WireWavefrontMetrics, SteeltoeAssemblyNames.ManagementWavefront);
-
- builder.WireIfLoaded(WireDistributedTracing, SteeltoeAssemblyNames.ManagementTracing);
-
- builder.WireIfLoaded(WireCloudFoundryContainerIdentity, SteeltoeAssemblyNames.SecurityAuthenticationCloudFoundry);
- return builder;
- }
-
- private static bool WireIfLoaded(this WebApplicationBuilder webApplicationBuilder, Action action, params string[] assembly)
- {
- if (Array.TrueForAll(assembly, AssemblyExtensions.IsAssemblyLoaded))
- {
- action(webApplicationBuilder);
- return true;
- }
-
- return false;
- }
-
- private static void WireIfAnyLoaded(this WebApplicationBuilder builder, Action action, IReadOnlySet assemblyNamesToExclude,
- params PackageResolver[] packageResolvers)
- {
- if (Array.Exists(packageResolvers, packageResolver => packageResolver.IsAvailable(assemblyNamesToExclude)))
- {
- action(builder);
- }
- }
-
- private static void Log(string message)
- {
- _logger.LogInformation(message);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireConfigServer(this WebApplicationBuilder webApplicationBuilder)
- {
- webApplicationBuilder.Configuration.AddConfigServer(webApplicationBuilder.Environment.EnvironmentName, _loggerFactory);
- webApplicationBuilder.Services.AddConfigServerServices();
- Log(LogMessages.WireConfigServerConfiguration);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireCloudFoundryConfiguration(this WebApplicationBuilder webApplicationBuilder)
- {
- webApplicationBuilder.Configuration.AddCloudFoundry();
- Log(LogMessages.WireCloudFoundryConfiguration);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireKubernetesConfiguration(this WebApplicationBuilder webApplicationBuilder)
+ ///
+ /// The incoming , so that additional calls can be chained.
+ ///
+ public static WebApplicationBuilder AddSteeltoe(this WebApplicationBuilder builder, IReadOnlySet assemblyNamesToExclude)
{
- webApplicationBuilder.Configuration.AddKubernetes(_loggerFactory);
- webApplicationBuilder.Services.AddKubernetesConfigurationServices();
- Log(LogMessages.WireKubernetesConfiguration);
+ return AddSteeltoe(builder, assemblyNamesToExclude, NullLoggerFactory.Instance);
}
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireRandomValueProvider(this WebApplicationBuilder webApplicationBuilder)
- {
- webApplicationBuilder.Configuration.AddRandomValueSource(_loggerFactory);
- Log(LogMessages.WireRandomValueConfiguration);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WirePlaceholderResolver(this WebApplicationBuilder webApplicationBuilder)
- {
- ((IConfigurationBuilder)webApplicationBuilder.Configuration).AddPlaceholderResolver(_loggerFactory);
- Log(LogMessages.WirePlaceholderConfiguration);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireConnectors(WebApplicationBuilder builder)
- {
- var assemblyNamesToExclude = new HashSet(AssemblyExtensions.ExcludedAssemblies, StringComparer.OrdinalIgnoreCase);
-
- builder.WireIfAnyLoaded(WireCosmosDbConnector, assemblyNamesToExclude, CosmosDbPackageResolver.Default);
- builder.WireIfAnyLoaded(WireMongoDbConnector, assemblyNamesToExclude, MongoDbPackageResolver.Default);
- builder.WireIfAnyLoaded(WireMySqlConnector, assemblyNamesToExclude, MySqlPackageResolver.Default);
- builder.WireIfAnyLoaded(WirePostgreSqlConnector, assemblyNamesToExclude, PostgreSqlPackageResolver.Default);
- builder.WireIfAnyLoaded(WireRabbitMQConnector, assemblyNamesToExclude, RabbitMQPackageResolver.Default);
- builder.WireIfAnyLoaded(WireRedisConnector, assemblyNamesToExclude, StackExchangeRedisPackageResolver.Default, MicrosoftRedisPackageResolver.Default);
- builder.WireIfAnyLoaded(WireSqlServerConnector, assemblyNamesToExclude, SqlServerPackageResolver.Default);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireMySqlConnector(this WebApplicationBuilder builder)
- {
- builder.AddMySql();
- Log(LogMessages.WireMySqlConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireCosmosDbConnector(this WebApplicationBuilder builder)
- {
- builder.AddCosmosDb();
- Log(LogMessages.WireCosmosDbConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireMongoDbConnector(this WebApplicationBuilder builder)
- {
- builder.AddMongoDb();
- Log(LogMessages.WireMongoDbConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WirePostgreSqlConnector(this WebApplicationBuilder builder)
- {
- builder.AddPostgreSql();
- Log(LogMessages.WirePostgreSqlConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireRabbitMQConnector(this WebApplicationBuilder builder)
- {
- builder.AddRabbitMQ();
- Log(LogMessages.WireRabbitMQConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireRedisConnector(this WebApplicationBuilder builder)
- {
- builder.AddRedis();
- Log(LogMessages.WireStackExchangeRedisConnector);
-
- // Intentionally ignoring excluded assemblies here.
- if (MicrosoftRedisPackageResolver.Default.IsAvailable())
- {
- Log(LogMessages.WireDistributedCacheRedisConnector);
- }
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireSqlServerConnector(this WebApplicationBuilder builder)
- {
- builder.AddSqlServer();
- Log(LogMessages.WireSqlServerConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireDiscoveryClient(this WebApplicationBuilder webApplicationBuilder)
- {
- webApplicationBuilder.Services.AddDiscoveryClient(webApplicationBuilder.Configuration);
- Log(LogMessages.WireDiscoveryClient);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireDistributedTracing(this WebApplicationBuilder webApplicationBuilder)
- {
- webApplicationBuilder.Services.AddDistributedTracingAspNetCore();
- Log(LogMessages.WireDistributedTracing);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireKubernetesActuators(this WebApplicationBuilder webApplicationBuilder)
- {
- webApplicationBuilder.Logging.AddDynamicConsole();
- webApplicationBuilder.Services.AddKubernetesActuators();
- webApplicationBuilder.Services.ActivateActuatorEndpoints();
- Log(LogMessages.WireKubernetesActuators);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireAllActuators(this WebApplicationBuilder webApplicationBuilder)
+ ///
+ /// Automatically configures Steeltoe packages that have been added to your project as NuGet references.
+ ///
+ ///
+ /// The to configure.
+ ///
+ ///
+ /// Used for internal logging. Pass to disable logging.
+ ///
+ ///
+ /// The incoming , so that additional calls can be chained.
+ ///
+ public static WebApplicationBuilder AddSteeltoe(this WebApplicationBuilder builder, ILoggerFactory loggerFactory)
{
- webApplicationBuilder.Logging.AddDynamicConsole();
- webApplicationBuilder.Services.AddAllActuators();
- webApplicationBuilder.Services.ActivateActuatorEndpoints();
- Log(LogMessages.WireAllActuators);
+ return AddSteeltoe(builder, EmptySet, loggerFactory);
}
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireWavefrontMetrics(this WebApplicationBuilder webApplicationBuilder)
+ ///
+ /// Automatically configures Steeltoe packages that have been added to your project as NuGet references.
+ ///
+ ///
+ /// The to configure.
+ ///
+ ///
+ /// The set of assembly names to exclude from auto-configuration. For ease of use, select from the constants in .
+ ///
+ ///
+ /// Used for internal logging. Pass to disable logging.
+ ///
+ ///
+ /// The incoming , so that additional calls can be chained.
+ ///
+ public static WebApplicationBuilder AddSteeltoe(this WebApplicationBuilder builder, IReadOnlySet assemblyNamesToExclude,
+ ILoggerFactory loggerFactory)
{
- if (webApplicationBuilder.Configuration.HasWavefront())
- {
- webApplicationBuilder.AddWavefrontMetrics();
- Log(LogMessages.WireWavefrontMetrics);
- }
- }
+ ArgumentGuard.NotNull(builder);
+ ArgumentGuard.NotNull(assemblyNamesToExclude);
+ ArgumentGuard.NotNull(loggerFactory);
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireSteeltoePrometheus(this WebApplicationBuilder webApplicationBuilder)
- {
- webApplicationBuilder.Services.AddPrometheusActuator();
- Log(LogMessages.WirePrometheus);
- }
+ HostBuilderWrapper wrapper = HostBuilderWrapper.Wrap(builder);
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireDynamicSerilog(this WebApplicationBuilder webApplicationBuilder)
- {
- webApplicationBuilder.Logging.AddDynamicSerilog();
- Log(LogMessages.WireDynamicSerilog);
- }
+ var scanner = new BootstrapScanner(wrapper, assemblyNamesToExclude, loggerFactory);
+ scanner.ConfigureSteeltoe();
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireCloudFoundryContainerIdentity(this WebApplicationBuilder webApplicationBuilder)
- {
- webApplicationBuilder.Configuration.AddCloudFoundryContainerIdentity();
- webApplicationBuilder.Services.AddCloudFoundryCertificateAuth();
- Log(LogMessages.WireCloudFoundryContainerIdentity);
+ return builder;
}
}
diff --git a/src/Bootstrap/src/AutoConfiguration/WebHostBuilderExtensions.cs b/src/Bootstrap/src/AutoConfiguration/WebHostBuilderExtensions.cs
index 99d4cd949b..17196e3b2b 100644
--- a/src/Bootstrap/src/AutoConfiguration/WebHostBuilderExtensions.cs
+++ b/src/Bootstrap/src/AutoConfiguration/WebHostBuilderExtensions.cs
@@ -2,354 +2,93 @@
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.
-using System.Runtime.CompilerServices;
+using System.Collections.Immutable;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Steeltoe.Common;
-using Steeltoe.Common.DynamicTypeAccess;
-using Steeltoe.Configuration.CloudFoundry;
-using Steeltoe.Configuration.ConfigServer;
-using Steeltoe.Configuration.Kubernetes;
-using Steeltoe.Configuration.Placeholder;
-using Steeltoe.Configuration.RandomValue;
-using Steeltoe.Connectors.CosmosDb;
-using Steeltoe.Connectors.CosmosDb.DynamicTypeAccess;
-using Steeltoe.Connectors.MongoDb;
-using Steeltoe.Connectors.MongoDb.DynamicTypeAccess;
-using Steeltoe.Connectors.MySql;
-using Steeltoe.Connectors.MySql.DynamicTypeAccess;
-using Steeltoe.Connectors.PostgreSql;
-using Steeltoe.Connectors.PostgreSql.DynamicTypeAccess;
-using Steeltoe.Connectors.RabbitMQ;
-using Steeltoe.Connectors.RabbitMQ.DynamicTypeAccess;
-using Steeltoe.Connectors.Redis;
-using Steeltoe.Connectors.Redis.DynamicTypeAccess;
-using Steeltoe.Connectors.SqlServer;
-using Steeltoe.Connectors.SqlServer.RuntimeTypeAccess;
-using Steeltoe.Discovery.Client;
-using Steeltoe.Logging.DynamicSerilog;
-using Steeltoe.Management.Endpoint;
-using Steeltoe.Management.Kubernetes;
-using Steeltoe.Management.Prometheus;
-using Steeltoe.Management.Tracing;
-using Steeltoe.Management.Wavefront;
-using Steeltoe.Security.Authentication.CloudFoundry;
+using Steeltoe.Common.Hosting;
namespace Steeltoe.Bootstrap.AutoConfiguration;
public static class WebHostBuilderExtensions
{
- private const string LoggerName = "Steeltoe.AutoConfiguration";
- private static ILoggerFactory _loggerFactory;
- private static ILogger _logger;
+ private static readonly IReadOnlySet EmptySet = ImmutableHashSet.Empty;
- static WebHostBuilderExtensions()
+ ///
+ /// Automatically configures Steeltoe packages that have been added to your project as NuGet references.
+ ///
+ ///
+ /// The to configure.
+ ///
+ ///
+ /// The incoming , so that additional calls can be chained.
+ ///
+ public static IWebHostBuilder AddSteeltoe(this IWebHostBuilder builder)
{
- AppDomain currentDomain = AppDomain.CurrentDomain;
- currentDomain.AssemblyResolve += AssemblyExtensions.LoadAnyVersion;
+ return AddSteeltoe(builder, EmptySet, NullLoggerFactory.Instance);
}
///
- /// Automatically configure Steeltoe packages that have been added as NuGet references.
- ///
- /// PLEASE NOTE: No extensions to IApplicationBuilder will be configured.
+ /// Automatically configures Steeltoe packages that have been added to your project as NuGet references.
///
///
- /// Your .
+ /// The to configure.
///
- ///
- /// A list of assemblies to exclude from auto-configuration. For ease of use, select from .
+ ///
+ /// The set of assembly names to exclude from auto-configuration. For ease of use, select from the constants in .
///
- ///
- /// For logging within auto-configuration.
- ///
- public static IWebHostBuilder AddSteeltoe(this IWebHostBuilder builder, IEnumerable exclusions = null, ILoggerFactory loggerFactory = null)
- {
- AssemblyExtensions.ExcludedAssemblies = exclusions ?? new List();
- _loggerFactory = loggerFactory ?? NullLoggerFactory.Instance;
- _logger = _loggerFactory.CreateLogger(LoggerName);
-
- if (!builder.WireIfLoaded(WireConfigServer, SteeltoeAssemblyNames.ConfigurationConfigServer))
- {
- builder.WireIfLoaded(WireCloudFoundryConfiguration, SteeltoeAssemblyNames.ConfigurationCloudFoundry);
- }
-
- if (Platform.IsKubernetes && AssemblyExtensions.IsAssemblyLoaded(SteeltoeAssemblyNames.ConfigurationKubernetes))
- {
- WireKubernetesConfiguration(builder);
- }
-
- builder.WireIfLoaded(WireRandomValueProvider, SteeltoeAssemblyNames.ConfigurationRandomValue);
-
- builder.WireIfLoaded(WirePlaceholderResolver, SteeltoeAssemblyNames.ConfigurationPlaceholder);
-
- builder.WireIfLoaded(WireConnectors, SteeltoeAssemblyNames.Connectors);
-
- builder.WireIfLoaded(WireDynamicSerilog, SteeltoeAssemblyNames.LoggingDynamicSerilog);
- builder.WireIfLoaded(WireDiscoveryClient, SteeltoeAssemblyNames.DiscoveryClient);
-
- if (AssemblyExtensions.IsAssemblyLoaded(SteeltoeAssemblyNames.ManagementKubernetes))
- {
- builder.WireIfLoaded(WireKubernetesActuators, SteeltoeAssemblyNames.ManagementKubernetes);
- }
- else
- {
- builder.WireIfLoaded(WireAllActuators, SteeltoeAssemblyNames.ManagementEndpoint);
- }
-
- builder.WireIfLoaded(WireSteeltoePrometheus, SteeltoeAssemblyNames.ManagementPrometheus);
-
- builder.WireIfLoaded(WireWavefrontMetrics, SteeltoeAssemblyNames.ManagementWavefront);
-
- builder.WireIfLoaded(WireDistributedTracing, SteeltoeAssemblyNames.ManagementTracing);
-
- builder.WireIfLoaded(WireCloudFoundryContainerIdentity, SteeltoeAssemblyNames.SecurityAuthenticationCloudFoundry);
- return builder;
- }
-
- private static bool WireIfLoaded(this IWebHostBuilder hostBuilder, Action action, params string[] assembly)
- {
- if (Array.TrueForAll(assembly, AssemblyExtensions.IsAssemblyLoaded))
- {
- action(hostBuilder);
- return true;
- }
-
- return false;
- }
-
- private static void WireIfAnyLoaded(this IWebHostBuilder hostBuilder, Action action, IReadOnlySet assemblyNamesToExclude,
- params PackageResolver[] packageResolvers)
- {
- if (Array.Exists(packageResolvers, packageResolver => packageResolver.IsAvailable(assemblyNamesToExclude)))
- {
- action(hostBuilder);
- }
- }
-
- private static void Log(this IWebHostBuilder host, string message)
- {
- _logger.LogInformation(message);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireConfigServer(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration((context, cfg) => cfg.AddConfigServer(context.HostingEnvironment, _loggerFactory))
- .ConfigureServices((_, services) => services.AddConfigServerServices()).Log(LogMessages.WireConfigServerConfiguration);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireCloudFoundryConfiguration(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(cfg => cfg.AddCloudFoundry()).Log(LogMessages.WireCloudFoundryConfiguration);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireKubernetesConfiguration(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(cfg => cfg.AddKubernetes(_loggerFactory))
- .ConfigureServices(serviceCollection => serviceCollection.AddKubernetesConfigurationServices()).Log(LogMessages.WireKubernetesConfiguration);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireRandomValueProvider(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(cfg => cfg.AddRandomValueSource(_loggerFactory)).Log(LogMessages.WireRandomValueConfiguration);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WirePlaceholderResolver(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(cfg => cfg.AddPlaceholderResolver(_loggerFactory)).Log(LogMessages.WirePlaceholderConfiguration);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireConnectors(IWebHostBuilder builder)
- {
- var assemblyNamesToExclude = new HashSet(AssemblyExtensions.ExcludedAssemblies, StringComparer.OrdinalIgnoreCase);
-
- builder.WireIfAnyLoaded(WireCosmosDbConnector, assemblyNamesToExclude, CosmosDbPackageResolver.Default);
- builder.WireIfAnyLoaded(WireMongoDbConnector, assemblyNamesToExclude, MongoDbPackageResolver.Default);
- builder.WireIfAnyLoaded(WireMySqlConnector, assemblyNamesToExclude, MySqlPackageResolver.Default);
- builder.WireIfAnyLoaded(WirePostgreSqlConnector, assemblyNamesToExclude, PostgreSqlPackageResolver.Default);
- builder.WireIfAnyLoaded(WireRabbitMQConnector, assemblyNamesToExclude, RabbitMQPackageResolver.Default);
- builder.WireIfAnyLoaded(WireRedisConnector, assemblyNamesToExclude, StackExchangeRedisPackageResolver.Default, MicrosoftRedisPackageResolver.Default);
- builder.WireIfAnyLoaded(WireSqlServerConnector, assemblyNamesToExclude, SqlServerPackageResolver.Default);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireMySqlConnector(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(configurationBuilder =>
- {
- configurationBuilder.ConfigureMySql();
- });
-
- hostBuilder.ConfigureServices((host, services) =>
- {
- services.AddMySql(host.Configuration);
- });
-
- hostBuilder.Log(LogMessages.WireMySqlConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireCosmosDbConnector(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(configurationBuilder =>
- {
- configurationBuilder.ConfigureCosmosDb();
- });
-
- hostBuilder.ConfigureServices((host, services) =>
- {
- services.AddCosmosDb(host.Configuration);
- });
-
- hostBuilder.Log(LogMessages.WireCosmosDbConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireMongoDbConnector(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(configurationBuilder =>
- {
- configurationBuilder.ConfigureMongoDb();
- });
-
- hostBuilder.ConfigureServices((host, services) =>
- {
- services.AddMongoDb(host.Configuration);
- });
-
- hostBuilder.Log(LogMessages.WireMongoDbConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WirePostgreSqlConnector(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(configurationBuilder =>
- {
- configurationBuilder.ConfigurePostgreSql();
- });
-
- hostBuilder.ConfigureServices((host, services) =>
- {
- services.AddPostgreSql(host.Configuration);
- });
-
- hostBuilder.Log(LogMessages.WirePostgreSqlConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireRabbitMQConnector(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(configurationBuilder =>
- {
- configurationBuilder.ConfigureRabbitMQ();
- });
-
- hostBuilder.ConfigureServices((host, services) =>
- {
- services.AddRabbitMQ(host.Configuration);
- });
-
- hostBuilder.Log(LogMessages.WireRabbitMQConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireRedisConnector(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(configurationBuilder =>
- {
- configurationBuilder.ConfigureRedis();
- });
-
- hostBuilder.ConfigureServices((host, services) =>
- {
- services.AddRedis(host.Configuration);
- });
-
- hostBuilder.Log(LogMessages.WireStackExchangeRedisConnector);
-
- // Intentionally ignoring excluded assemblies here.
- if (MicrosoftRedisPackageResolver.Default.IsAvailable())
- {
- hostBuilder.Log(LogMessages.WireDistributedCacheRedisConnector);
- }
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireSqlServerConnector(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(configurationBuilder =>
- {
- configurationBuilder.ConfigureSqlServer();
- });
-
- hostBuilder.ConfigureServices((host, services) =>
- {
- services.AddSqlServer(host.Configuration);
- });
-
- hostBuilder.Log(LogMessages.WireSqlServerConnector);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireDiscoveryClient(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureServices((_, svc) => svc.AddDiscoveryClient()).Log(LogMessages.WireDiscoveryClient);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireDistributedTracing(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureServices((_, svc) => svc.AddDistributedTracingAspNetCore()).Log(LogMessages.WireDistributedTracing);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireKubernetesActuators(this IWebHostBuilder hostBuilder)
+ ///
+ /// The incoming , so that additional calls can be chained.
+ ///
+ public static IWebHostBuilder AddSteeltoe(this IWebHostBuilder builder, IReadOnlySet assemblyNamesToExclude)
{
- hostBuilder.AddKubernetesActuators().Log(LogMessages.WireKubernetesActuators);
+ return AddSteeltoe(builder, assemblyNamesToExclude, NullLoggerFactory.Instance);
}
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireAllActuators(this IWebHostBuilder hostBuilder)
+ ///
+ /// Automatically configures Steeltoe packages that have been added to your project as NuGet references.
+ ///
+ ///
+ /// The to configure.
+ ///
+ ///
+ /// Used for internal logging. Pass to disable logging.
+ ///
+ ///
+ /// The incoming , so that additional calls can be chained.
+ ///
+ public static IWebHostBuilder AddSteeltoe(this IWebHostBuilder builder, ILoggerFactory loggerFactory)
{
- hostBuilder.AddAllActuators().Log(LogMessages.WireAllActuators);
+ return AddSteeltoe(builder, EmptySet, loggerFactory);
}
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireWavefrontMetrics(this IWebHostBuilder hostBuilder)
+ ///
+ /// Automatically configures Steeltoe packages that have been added to your project as NuGet references.
+ ///
+ ///
+ /// The to configure.
+ ///
+ ///
+ /// The set of assembly names to exclude from auto-configuration. For ease of use, select from the constants in .
+ ///
+ ///
+ /// Used for internal logging. Pass to disable logging.
+ ///
+ ///
+ /// The incoming , so that additional calls can be chained.
+ ///
+ public static IWebHostBuilder AddSteeltoe(this IWebHostBuilder builder, IReadOnlySet assemblyNamesToExclude, ILoggerFactory loggerFactory)
{
- hostBuilder.ConfigureServices((context, collection) =>
- {
- if (context.Configuration.HasWavefront())
- {
- collection.AddWavefrontMetrics();
- hostBuilder.Log(LogMessages.WireWavefrontMetrics);
- }
- });
- }
+ ArgumentGuard.NotNull(builder);
+ ArgumentGuard.NotNull(assemblyNamesToExclude);
+ ArgumentGuard.NotNull(loggerFactory);
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireSteeltoePrometheus(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureServices((_, collection) => collection.AddPrometheusActuator()).Log(LogMessages.WirePrometheus);
- }
+ HostBuilderWrapper wrapper = HostBuilderWrapper.Wrap(builder);
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireDynamicSerilog(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.AddDynamicSerilog().Log(LogMessages.WireDynamicSerilog);
- }
+ var scanner = new BootstrapScanner(wrapper, assemblyNamesToExclude, loggerFactory);
+ scanner.ConfigureSteeltoe();
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void WireCloudFoundryContainerIdentity(this IWebHostBuilder hostBuilder)
- {
- hostBuilder.ConfigureAppConfiguration(cfg => cfg.AddCloudFoundryContainerIdentity()).ConfigureServices((_, svc) => svc.AddCloudFoundryCertificateAuth())
- .Log(LogMessages.WireCloudFoundryContainerIdentity);
+ return builder;
}
}
diff --git a/src/Bootstrap/test/AutoConfiguration.Test/HostBuilderExtensionsTest.cs b/src/Bootstrap/test/AutoConfiguration.Test/HostBuilderExtensionsTest.cs
index 1208707594..2ef9aa128d 100644
--- a/src/Bootstrap/test/AutoConfiguration.Test/HostBuilderExtensionsTest.cs
+++ b/src/Bootstrap/test/AutoConfiguration.Test/HostBuilderExtensionsTest.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.
-using System.Net;
using System.Reflection;
using FluentAssertions;
using Microsoft.AspNetCore.Authorization;
@@ -56,133 +55,84 @@ namespace Steeltoe.Bootstrap.AutoConfiguration.Test;
public sealed class HostBuilderExtensionsTest
{
- private readonly Action _testServerWithRouting = builder =>
- builder.UseTestServer().ConfigureServices(s => s.AddRouting().AddActionDescriptorCollectionProvider()).Configure(a => a.UseRouting());
-
[Fact]
public void ConfigServerConfiguration_IsAutowired()
{
- string[] exclusions = SteeltoeAssemblyNames.All.Except(new[]
- {
- SteeltoeAssemblyNames.ConfigurationConfigServer
- }).ToArray();
-
- IHostBuilder hostBuilder = new HostBuilder().ConfigureAppConfiguration(builder => builder.AddInMemoryCollection(TestHelpers.FastTestsConfiguration));
-
- IHost host = hostBuilder.AddSteeltoe(exclusions).Build();
+ using IHost host = GetHostForOnly(SteeltoeAssemblyNames.ConfigurationConfigServer);
var configuration = host.Services.GetRequiredService();
- Assert.NotNull(configuration.FindConfigurationProvider());
- Assert.NotNull(configuration.FindConfigurationProvider());
+ configuration.FindConfigurationProvider().Should().NotBeNull();
+ configuration.FindConfigurationProvider().Should().NotBeNull();
}
[Fact]
public void CloudFoundryConfiguration_IsAutowired()
{
- string[] exclusions = SteeltoeAssemblyNames.All.Except(new[]
- {
- SteeltoeAssemblyNames.ConfigurationCloudFoundry
- }).ToArray();
-
- IHostBuilder hostBuilder = new HostBuilder();
-
- IHost host = hostBuilder.AddSteeltoe(exclusions).Build();
- var configurationRoot = (IConfigurationRoot)host.Services.GetRequiredService();
+ using IHost host = GetHostForOnly(SteeltoeAssemblyNames.ConfigurationCloudFoundry);
+ var configuration = host.Services.GetRequiredService();
- Assert.Single(configurationRoot.Providers.OfType());
+ configuration.FindConfigurationProvider().Should().NotBeNull();
}
- [Fact(Skip = "Requires Kubernetes")]
+ [Fact]
public void KubernetesConfiguration_IsAutowired()
{
- using var scope = new EnvironmentVariableScope("KUBERNETES_SERVICE_HOST", "TEST");
-
- string[] exclusions = SteeltoeAssemblyNames.All.Except(new[]
- {
- SteeltoeAssemblyNames.ConfigurationKubernetes
- }).ToArray();
-
- IHostBuilder hostBuilder = new HostBuilder();
+ using var hostScope = new EnvironmentVariableScope("KUBERNETES_SERVICE_HOST", "TEST");
+ using var testScope = new EnvironmentVariableScope("STEELTOE_USE_KUBERNETES_FAKE_CLIENT_FOR_TEST", "true");
- IHost host = hostBuilder.AddSteeltoe(exclusions).Build();
+ using IHost host = GetHostForOnly(SteeltoeAssemblyNames.ConfigurationKubernetes);
var configurationRoot = (IConfigurationRoot)host.Services.GetRequiredService();
- Assert.Equal(2, configurationRoot.Providers.OfType().Count());
- Assert.Equal(2, configurationRoot.Providers.OfType().Count());
+ configurationRoot.Providers.OfType().Should().HaveCount(2);
+ configurationRoot.Providers.OfType().Should().HaveCount(2);
}
[Fact]
public void RandomValueConfiguration_IsAutowired()
{
- string[] exclusions = SteeltoeAssemblyNames.All.Except(new[]
- {
- SteeltoeAssemblyNames.ConfigurationRandomValue
- }).ToArray();
-
- IHostBuilder hostBuilder = new HostBuilder();
-
- IHost host = hostBuilder.AddSteeltoe(exclusions).Build();
- var configurationRoot = (IConfigurationRoot)host.Services.GetRequiredService();
+ using IHost host = GetHostForOnly(SteeltoeAssemblyNames.ConfigurationRandomValue);
+ var configuration = host.Services.GetRequiredService();
- Assert.Single(configurationRoot.Providers.OfType());
+ configuration.FindConfigurationProvider().Should().NotBeNull();
}
[Fact]
public void PlaceholderResolver_IsAutowired()
{
- string[] exclusions = SteeltoeAssemblyNames.All.Except(new[]
- {
- SteeltoeAssemblyNames.ConfigurationPlaceholder
- }).ToArray();
-
- IHostBuilder hostBuilder = new HostBuilder();
-
- IHost host = hostBuilder.AddSteeltoe(exclusions).Build();
+ using IHost host = GetHostForOnly(SteeltoeAssemblyNames.ConfigurationPlaceholder);
var configurationRoot = (IConfigurationRoot)host.Services.GetRequiredService();
- Assert.Single(configurationRoot.Providers);
- Assert.Single(configurationRoot.Providers.OfType());
+ configurationRoot.Providers.OfType().Should().HaveCount(1);
}
[Fact]
public void Connectors_AreAutowired()
{
- string[] exclusions = SteeltoeAssemblyNames.All.Except(new[]
- {
- SteeltoeAssemblyNames.Connectors
- }).ToArray();
-
- IHostBuilder hostBuilder = new HostBuilder();
- hostBuilder.AddSteeltoe(exclusions);
-
- IHost host = hostBuilder.Build();
- var configurationRoot = (IConfigurationRoot)host.Services.GetRequiredService();
+ using IHost host = GetHostForOnly(SteeltoeAssemblyNames.Connectors);
+ var configuration = host.Services.GetRequiredService();
- configurationRoot.Providers.Should().ContainSingle(provider => provider is KubernetesServiceBindingConfigurationProvider);
- configurationRoot.Providers.Should().ContainSingle(provider => provider is CloudFoundryServiceBindingConfigurationProvider);
-
- host.Services.GetRequiredService>().Should().NotBeNull();
- host.Services.GetRequiredService>().Should().NotBeNull();
- host.Services.GetRequiredService>().Should().NotBeNull();
- host.Services.GetRequiredService>().Should().NotBeNull();
- host.Services.GetRequiredService>().Should().NotBeNull();
- host.Services.GetRequiredService>().Should().NotBeNull();
- host.Services.GetRequiredService>().Should().NotBeNull();
- host.Services.GetRequiredService>().Should().NotBeNull();
+ configuration.FindConfigurationProvider().Should().NotBeNull();
+ configuration.FindConfigurationProvider().Should().NotBeNull();
+
+ host.Services.GetService>().Should().NotBeNull();
+ host.Services.GetService>().Should().NotBeNull();
+ host.Services.GetService>().Should().NotBeNull();
+ host.Services.GetService>().Should().NotBeNull();
+ host.Services.GetService>().Should().NotBeNull();
+ host.Services.GetService>().Should().NotBeNull();
+ host.Services.GetService>().Should().NotBeNull();
+ host.Services.GetService>().Should().NotBeNull();
}
[Fact]
- public void SqlServerConnector_NotAutowiredIfExcluded()
+ public void SqlServerConnector_NotAutowiredIfDependenciesExcluded()
{
var exclusions = new HashSet(SteeltoeAssemblyNames.All);
exclusions.Remove(SteeltoeAssemblyNames.Connectors);
exclusions.Add("Microsoft.Data.SqlClient");
exclusions.Add("System.Data.SqlClient");
- IHostBuilder hostBuilder = new HostBuilder();
- hostBuilder.AddSteeltoe(exclusions);
-
- IHost host = hostBuilder.Build();
+ using IHost host = GetHostExcluding(exclusions);
host.Services.GetService>().Should().BeNull();
}
@@ -190,171 +140,145 @@ public void SqlServerConnector_NotAutowiredIfExcluded()
[Fact]
public void DynamicSerilog_IsAutowired()
{
- string[] exclusions = SteeltoeAssemblyNames.All.Except(new[]
- {
- SteeltoeAssemblyNames.LoggingDynamicSerilog
- }).ToArray();
-
- IHostBuilder hostBuilder = new HostBuilder();
-
- IHost host = hostBuilder.AddSteeltoe(exclusions).Build();
+ using IHost host = GetHostForOnly(SteeltoeAssemblyNames.LoggingDynamicSerilog);
var loggerProvider = host.Services.GetRequiredService();
- Assert.IsType(loggerProvider);
+ loggerProvider.Should().BeOfType();
}
[Fact]
public void ServiceDiscovery_IsAutowired()
{
- string[] exclusions = SteeltoeAssemblyNames.All.Except(new[]
- {
- SteeltoeAssemblyNames.DiscoveryClient
- }).ToArray();
+ using IHost host = GetHostForOnly(SteeltoeAssemblyNames.DiscoveryClient);
+ IDiscoveryClient[] discoveryClients = host.Services.GetServices().ToArray();
- IHostBuilder hostBuilder = new HostBuilder().ConfigureAppConfiguration(builder => builder.AddInMemoryCollection(TestHelpers.FastTestsConfiguration));
+ discoveryClients.Should().HaveCount(1);
+ discoveryClients[0].Should().BeOfType();
+ }
- IHost host = hostBuilder.AddSteeltoe(exclusions).Build();
- IDiscoveryClient[] discoveryClients = host.Services.GetServices().ToArray();
+ [Fact]
+ public void Prometheus_IsAutowired()
+ {
+ using IHost host = GetHostForOnly(SteeltoeAssemblyNames.ManagementPrometheus);
- Assert.Single(discoveryClients);
- Assert.IsType(discoveryClients[0]);
+ host.Services.GetService().Should().NotBeNull();
}
[Fact]
public void WavefrontMetricsExporter_IsAutowired()
{
- string[] exclusions = SteeltoeAssemblyNames.All.Except(new[]
- {
- SteeltoeAssemblyNames.ManagementWavefront
- }).ToArray();
+ using IHost host = GetHostForOnly(SteeltoeAssemblyNames.ManagementWavefront);
- IHost host = new HostBuilder().ConfigureAppConfiguration(builder => builder.AddInMemoryCollection(TestHelpers.WavefrontConfiguration))
- .AddSteeltoe(exclusions).Build();
-
- var meterProvider = host.Services.GetRequiredService();
- Assert.NotNull(meterProvider);
+ host.Services.GetService().Should().NotBeNull();
}
[Fact]
public void WavefrontTraceExporter_IsAutowired()
{
- string[] exclusions = SteeltoeAssemblyNames.All.Except(new[]
- {
- SteeltoeAssemblyNames.ManagementTracing
- }).ToArray();
-
- IHost host = new HostBuilder().ConfigureAppConfiguration(builder => builder.AddInMemoryCollection(TestHelpers.WavefrontConfiguration))
- .AddSteeltoe(exclusions).Build();
+ using IHost host = GetHostForOnly(SteeltoeAssemblyNames.ManagementTracing);
var tracerProvider = host.Services.GetRequiredService();
- Assert.NotNull(tracerProvider);
-
- PropertyInfo processorProperty =
- tracerProvider.GetType().GetProperty("Processor", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- Assert.NotNull(processorProperty);
+ PropertyInfo? processorProperty = tracerProvider.GetType().GetProperty("Processor", BindingFlags.NonPublic | BindingFlags.Instance);
+ processorProperty.Should().NotBeNull();
- object processor = processorProperty.GetValue(tracerProvider);
- Assert.NotNull(processor);
+ object? processor = processorProperty!.GetValue(tracerProvider);
+ processor.Should().NotBeNull();
- FieldInfo exporterField = processor.GetType().GetField("exporter", BindingFlags.NonPublic | BindingFlags.Instance);
- Assert.NotNull(exporterField);
+ FieldInfo? exporterField = processor!.GetType().GetField("exporter", BindingFlags.NonPublic | BindingFlags.Instance);
+ exporterField.Should().NotBeNull();
- object exporter = exporterField.GetValue(processor);
- Assert.NotNull(exporter);
- Assert.IsType(exporter);
+ object? exporter = exporterField!.GetValue(processor);
+ exporter.Should().BeOfType();
}
[Fact]
public async Task KubernetesActuators_AreAutowired()
{
- string[] exclusions = SteeltoeAssemblyNames.All.Except(new[]
- {
- SteeltoeAssemblyNames.ManagementKubernetes
- }).ToArray();
-
- IHostBuilder hostBuilder = new HostBuilder().ConfigureWebHost(_testServerWithRouting);
-
- IHost host = await hostBuilder.AddSteeltoe(exclusions).StartAsync();
- HttpClient testClient = host.GetTestServer().CreateClient();
-
- HttpResponseMessage response = await testClient.GetAsync(new Uri("/actuator", UriKind.Relative));
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
- response = await testClient.GetAsync(new Uri("/actuator/info", UriKind.Relative));
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
- response = await testClient.GetAsync(new Uri("/actuator/health", UriKind.Relative));
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
- response = await testClient.GetAsync(new Uri("/actuator/health/liveness", UriKind.Relative));
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
- Assert.Contains("\"LivenessState\":\"CORRECT\"", await response.Content.ReadAsStringAsync(), StringComparison.Ordinal);
- response = await testClient.GetAsync(new Uri("/actuator/health/readiness", UriKind.Relative));
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
- Assert.Contains("\"ReadinessState\":\"ACCEPTING_TRAFFIC\"", await response.Content.ReadAsStringAsync(), StringComparison.Ordinal);
+ using IHost host = GetHostForOnly(SteeltoeAssemblyNames.ManagementKubernetes);
+ await host.StartAsync();
+
+ IActuatorEndpointHandler[] handlers = host.Services.GetServices().ToArray();
+ handlers.Should().HaveCount(1);
+
+ var filter = host.Services.GetRequiredService();
+ filter.Should().BeOfType();
+
+ using HttpClient testClient = host.GetTestClient();
+ await WebApplicationBuilderExtensionsTest.AssertActuatorEndpointsSucceedAsync(testClient);
}
[Fact]
- public void AllActuators_AreAutowired()
+ public async Task AllActuators_AreAutowired()
{
- string[] exclusions = SteeltoeAssemblyNames.All.Except(new[]
- {
- SteeltoeAssemblyNames.ManagementEndpoint
- }).ToArray();
+ using IHost host = GetHostForOnly(SteeltoeAssemblyNames.ManagementEndpoint);
+ await host.StartAsync();
- IHostBuilder hostBuilder = new HostBuilder();
-
- IHost host = hostBuilder.AddSteeltoe(exclusions).Build();
- IEnumerable handlers = host.Services.GetServices();
- Assert.Single(handlers);
+ IActuatorEndpointHandler[] handlers = host.Services.GetServices().ToArray();
+ handlers.Should().HaveCount(1);
var filter = host.Services.GetRequiredService();
- Assert.IsType(filter);
+ filter.Should().BeOfType();
+
+ using HttpClient testClient = host.GetTestClient();
+ await WebApplicationBuilderExtensionsTest.AssertActuatorEndpointsSucceedAsync(testClient);
}
[Fact]
public void Tracing_IsAutowired()
{
- string[] exclusions = SteeltoeAssemblyNames.All.Except(new[]
- {
- SteeltoeAssemblyNames.ManagementTracing
- }).ToArray();
-
- IHostBuilder hostBuilder = new HostBuilder();
-
- IHost host = hostBuilder.AddSteeltoe(exclusions).Build();
+ using IHost host = GetHostForOnly(SteeltoeAssemblyNames.ManagementTracing);
var tracerProvider = host.Services.GetRequiredService();
- Assert.NotNull(host.Services.GetRequiredService());
- Assert.NotNull(host.Services.GetRequiredService());
- Assert.NotNull(host.Services.GetRequiredService());
+ host.Services.GetService().Should().NotBeNull();
+ host.Services.GetService().Should().NotBeNull();
+ host.Services.GetService().Should().NotBeNull();
+
+ FieldInfo? instrumentationsField = tracerProvider.GetType().GetField("instrumentations", BindingFlags.NonPublic | BindingFlags.Instance);
+ instrumentationsField.Should().NotBeNull();
- // confirm instrumentation(s) were added as expected
- FieldInfo instrumentationsField = tracerProvider.GetType().GetField("instrumentations", BindingFlags.NonPublic | BindingFlags.Instance);
- Assert.NotNull(instrumentationsField);
+ var instrumentations = (List