diff --git a/ES.FX.sln b/ES.FX.sln index 938f9aa..57dc080 100644 --- a/ES.FX.sln +++ b/ES.FX.sln @@ -133,6 +133,23 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ES.FX.Shared.Seq.Tests", "tests\ES.FX.Shared.Seq.Tests\ES.FX.Shared.Seq.Tests.csproj", "{3B260066-300E-4AD2-A0F7-BADED21F721D}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ES.FX.Ignite.OpenTelemetry.Exporter.Seq.Tests", "tests\ES.FX.Ignite.OpenTelemetry.Exporter.Seq.Tests\ES.FX.Ignite.OpenTelemetry.Exporter.Seq.Tests.csproj", "{DEFC7CD8-D546-4F51-A7D8-48FD938CEF81}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ES.FX.Ignite.Azure.Common", "src\ES.FX.Ignite.Azure.Common\ES.FX.Ignite.Azure.Common.csproj", "{C936CEE8-34B3-435C-970F-200DB84D5177}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ES.FX.Ignite.Azure.Storage.Blobs", "src\ES.FX.Ignite.Azure.Storage.Blobs\ES.FX.Ignite.Azure.Storage.Blobs.csproj", "{03D880C3-F1F1-4746-ADEC-9F59CFD12519}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ES.FX.Ignite.Azure.Storage.Queues", "src\ES.FX.Ignite.Azure.Storage.Queues\ES.FX.Ignite.Azure.Storage.Queues.csproj", "{EB2D9423-CDFF-4911-95F9-0A77FA7A750C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ES.FX.Ignite.Azure.Data.Tables", "src\ES.FX.Ignite.Azure.Data.Tables\ES.FX.Ignite.Azure.Data.Tables.csproj", "{40B14732-2810-45E8-AFFF-F25613EEE663}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ES.FX.Ignite.Azure.Security.KeyVault.Secrets", "src\ES.FX.Ignite.Azure.Security.KeyVault.Secrets\ES.FX.Ignite.Azure.Security.KeyVault.Secrets.csproj", "{C8FAFE2B-A175-4215-918D-2526D10D3830}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ES.FX.Ignite.Azure.Data.Tables.Tests", "tests\ES.FX.Ignite.Azure.Data.Tables.Tests\ES.FX.Ignite.Azure.Data.Tables.Tests.csproj", "{3159E21B-341C-4800-A812-564F07B0A03B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ES.FX.Ignite.Azure.Storage.Blobs.Tests", "tests\ES.FX.Ignite.Azure.Storage.Blobs.Tests\ES.FX.Ignite.Azure.Storage.Blobs.Tests.csproj", "{7D7DF31D-78DA-440F-A5E2-311C5CED142C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ES.FX.Ignite.Azure.Storage.Queues.Tests", "tests\ES.FX.Ignite.Azure.Storage.Queues.Tests\ES.FX.Ignite.Azure.Storage.Queues.Tests.csproj", "{ADABA0FD-C43E-4F2C-981F-480C186CFD72}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Tests", "tests\ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Tests\ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Tests.csproj", "{497C425C-451C-4D46-9693-A609D06D946D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -360,6 +377,42 @@ Global {DEFC7CD8-D546-4F51-A7D8-48FD938CEF81}.Debug|Any CPU.Build.0 = Debug|Any CPU {DEFC7CD8-D546-4F51-A7D8-48FD938CEF81}.Release|Any CPU.ActiveCfg = Release|Any CPU {DEFC7CD8-D546-4F51-A7D8-48FD938CEF81}.Release|Any CPU.Build.0 = Release|Any CPU + {C936CEE8-34B3-435C-970F-200DB84D5177}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C936CEE8-34B3-435C-970F-200DB84D5177}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C936CEE8-34B3-435C-970F-200DB84D5177}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C936CEE8-34B3-435C-970F-200DB84D5177}.Release|Any CPU.Build.0 = Release|Any CPU + {03D880C3-F1F1-4746-ADEC-9F59CFD12519}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {03D880C3-F1F1-4746-ADEC-9F59CFD12519}.Debug|Any CPU.Build.0 = Debug|Any CPU + {03D880C3-F1F1-4746-ADEC-9F59CFD12519}.Release|Any CPU.ActiveCfg = Release|Any CPU + {03D880C3-F1F1-4746-ADEC-9F59CFD12519}.Release|Any CPU.Build.0 = Release|Any CPU + {EB2D9423-CDFF-4911-95F9-0A77FA7A750C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EB2D9423-CDFF-4911-95F9-0A77FA7A750C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EB2D9423-CDFF-4911-95F9-0A77FA7A750C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EB2D9423-CDFF-4911-95F9-0A77FA7A750C}.Release|Any CPU.Build.0 = Release|Any CPU + {40B14732-2810-45E8-AFFF-F25613EEE663}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {40B14732-2810-45E8-AFFF-F25613EEE663}.Debug|Any CPU.Build.0 = Debug|Any CPU + {40B14732-2810-45E8-AFFF-F25613EEE663}.Release|Any CPU.ActiveCfg = Release|Any CPU + {40B14732-2810-45E8-AFFF-F25613EEE663}.Release|Any CPU.Build.0 = Release|Any CPU + {C8FAFE2B-A175-4215-918D-2526D10D3830}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C8FAFE2B-A175-4215-918D-2526D10D3830}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C8FAFE2B-A175-4215-918D-2526D10D3830}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C8FAFE2B-A175-4215-918D-2526D10D3830}.Release|Any CPU.Build.0 = Release|Any CPU + {3159E21B-341C-4800-A812-564F07B0A03B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3159E21B-341C-4800-A812-564F07B0A03B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3159E21B-341C-4800-A812-564F07B0A03B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3159E21B-341C-4800-A812-564F07B0A03B}.Release|Any CPU.Build.0 = Release|Any CPU + {7D7DF31D-78DA-440F-A5E2-311C5CED142C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7D7DF31D-78DA-440F-A5E2-311C5CED142C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7D7DF31D-78DA-440F-A5E2-311C5CED142C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7D7DF31D-78DA-440F-A5E2-311C5CED142C}.Release|Any CPU.Build.0 = Release|Any CPU + {ADABA0FD-C43E-4F2C-981F-480C186CFD72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ADABA0FD-C43E-4F2C-981F-480C186CFD72}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ADABA0FD-C43E-4F2C-981F-480C186CFD72}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ADABA0FD-C43E-4F2C-981F-480C186CFD72}.Release|Any CPU.Build.0 = Release|Any CPU + {497C425C-451C-4D46-9693-A609D06D946D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {497C425C-451C-4D46-9693-A609D06D946D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {497C425C-451C-4D46-9693-A609D06D946D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {497C425C-451C-4D46-9693-A609D06D946D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -425,6 +478,15 @@ Global {6C069A3F-F1C7-4852-84B0-210D6F35839C} = {32548940-0629-46AC-B9BF-E7C41F1C49DE} {3B260066-300E-4AD2-A0F7-BADED21F721D} = {BD8EB348-8F5D-41BB-BA2E-6D5C7A71FAB5} {DEFC7CD8-D546-4F51-A7D8-48FD938CEF81} = {32548940-0629-46AC-B9BF-E7C41F1C49DE} + {C936CEE8-34B3-435C-970F-200DB84D5177} = {5A5969AF-86CB-489B-B0DE-C0BAADF5B424} + {03D880C3-F1F1-4746-ADEC-9F59CFD12519} = {5A5969AF-86CB-489B-B0DE-C0BAADF5B424} + {EB2D9423-CDFF-4911-95F9-0A77FA7A750C} = {5A5969AF-86CB-489B-B0DE-C0BAADF5B424} + {40B14732-2810-45E8-AFFF-F25613EEE663} = {5A5969AF-86CB-489B-B0DE-C0BAADF5B424} + {C8FAFE2B-A175-4215-918D-2526D10D3830} = {5A5969AF-86CB-489B-B0DE-C0BAADF5B424} + {3159E21B-341C-4800-A812-564F07B0A03B} = {32548940-0629-46AC-B9BF-E7C41F1C49DE} + {7D7DF31D-78DA-440F-A5E2-311C5CED142C} = {32548940-0629-46AC-B9BF-E7C41F1C49DE} + {ADABA0FD-C43E-4F2C-981F-480C186CFD72} = {32548940-0629-46AC-B9BF-E7C41F1C49DE} + {497C425C-451C-4D46-9693-A609D06D946D} = {32548940-0629-46AC-B9BF-E7C41F1C49DE} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {388473D0-FE20-4821-BFE4-C3CD3E184C8F} diff --git a/playground/Playground.Microservice.Api.Host/HostedServices/TestHostedService.cs b/playground/Playground.Microservice.Api.Host/HostedServices/TestHostedService.cs index 3044e8c..c442f12 100644 --- a/playground/Playground.Microservice.Api.Host/HostedServices/TestHostedService.cs +++ b/playground/Playground.Microservice.Api.Host/HostedServices/TestHostedService.cs @@ -1,5 +1,9 @@ #pragma warning disable CS9113 // Parameter is unread. +using Azure.Data.Tables; +using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Models; +using Azure.Storage.Queues; using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Playground.Shared.Data.Simple.EntityFrameworkCore; @@ -11,8 +15,7 @@ internal class TestHostedService( IServiceProvider serviceProvider, IDbContextFactory dbContextFactory, SimpleDbContext context, - SqlConnection connection -) : BackgroundService + SqlConnection connection) : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { @@ -31,6 +34,23 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) var contextUsers = context.SimpleUsers.ToList(); var a = connection.State; + try + { + var blobClient = serviceProvider.GetRequiredKeyedService(null); + var containerclient = blobClient.GetBlobContainerClient("testcontainer"); + containerclient.CreateIfNotExists(PublicAccessType.Blob); + + + var queueClient = serviceProvider.GetRequiredKeyedService(null); + queueClient.CreateQueue("testqueue"); + + var tableClient = serviceProvider.GetRequiredKeyedService(null); + tableClient.CreateTableIfNotExists("testTable"); + } + catch (Exception e) + { + logger.LogError(e, "Error getting blob containers"); + } } } } \ No newline at end of file diff --git a/playground/Playground.Microservice.Api.Host/Playground.Microservice.Api.Host.csproj b/playground/Playground.Microservice.Api.Host/Playground.Microservice.Api.Host.csproj index 49950af..96374ea 100644 --- a/playground/Playground.Microservice.Api.Host/Playground.Microservice.Api.Host.csproj +++ b/playground/Playground.Microservice.Api.Host/Playground.Microservice.Api.Host.csproj @@ -17,25 +17,23 @@ - + + + + + - - + + - + - - + + \ No newline at end of file diff --git a/playground/Playground.Microservice.Api.Host/Program.cs b/playground/Playground.Microservice.Api.Host/Program.cs index 27632ba..7c451e0 100644 --- a/playground/Playground.Microservice.Api.Host/Program.cs +++ b/playground/Playground.Microservice.Api.Host/Program.cs @@ -1,5 +1,8 @@ using ES.FX.Hosting.Lifetime; using ES.FX.Ignite.AspNetCore.HealthChecks.UI.Hosting; +using ES.FX.Ignite.Azure.Data.Tables.Hosting; +using ES.FX.Ignite.Azure.Storage.Blobs.Hosting; +using ES.FX.Ignite.Azure.Storage.Queues.Hosting; using ES.FX.Ignite.FluentValidation.Hosting; using ES.FX.Ignite.Hosting; using ES.FX.Ignite.Microsoft.Data.SqlClient.Hosting; @@ -57,6 +60,10 @@ //Add Seq builder.IgniteSeqOpenTelemetryExporter(); + builder.IgniteAzureBlobServiceClient("Dev"); + builder.IgniteAzureQueueServiceClient("Dev"); + builder.IgniteAzureTableServiceClient("Dev"); + builder.Services.AddOpenApiDocument(); diff --git a/playground/Playground.Microservice.Api.Host/appsettings.json b/playground/Playground.Microservice.Api.Host/appsettings.json index 61efe10..b5be83d 100644 --- a/playground/Playground.Microservice.Api.Host/appsettings.json +++ b/playground/Playground.Microservice.Api.Host/appsettings.json @@ -72,7 +72,36 @@ "DisableHealthChecks": false } } + }, + "Azure": { + "Storage": { + "Blobs": { + "Dev": { + "ConnectionString": "UseDevelopmentStorage=true;DevelopmentStorageProxyUri=http://azurite.localenv.io:10000/devstoreaccount1;", + "Retry": { + "maxRetries": 5 + } + } + }, + "Queues": { + "Dev": { + "ConnectionString": "UseDevelopmentStorage=true;DevelopmentStorageProxyUri=http://azurite.localenv.io:10001/devstoreaccount1;", + "Retry": { + "maxRetries": 5 + } + } + } + }, + "Data": { + "Tables": { + "Dev": { + "ConnectionString": "UseDevelopmentStorage=true;DevelopmentStorageProxyUri=http://azurite.localenv.io:10002/devstoreaccount1;", + "Retry": { + "maxRetries": 5 + } + } + } + } } } - } \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Common/ES.FX.Ignite.Azure.Common.csproj b/src/ES.FX.Ignite.Azure.Common/ES.FX.Ignite.Azure.Common.csproj new file mode 100644 index 0000000..1ea9cd8 --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Common/ES.FX.Ignite.Azure.Common.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Common/Hosting/AzureCommonHostingExtensions.cs b/src/ES.FX.Ignite.Azure.Common/Hosting/AzureCommonHostingExtensions.cs new file mode 100644 index 0000000..73f0f24 --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Common/Hosting/AzureCommonHostingExtensions.cs @@ -0,0 +1,82 @@ +using Azure.Core.Extensions; +using JetBrains.Annotations; +using Microsoft.Extensions.Azure; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace ES.FX.Ignite.Azure.Common.Hosting; + +[PublicAPI] +public static class AzureCommonHostingExtensions +{ + /// + /// Registers an Azure Client with the specified settings and options + /// + /// The to read config from and add services to. + /// + /// If not null, registers a keyed service with the service key. If null, registers a default + /// service + /// + /// Configuration for the client. + /// + /// An optional delegate that can be used for customizing options. It's invoked after the + /// options are read from the configuration. + /// + public static void IgniteAzureClient(this IServiceCollection services, + string? serviceKey, + IConfigurationSection configuration, + Action? configureOptions = null) + where TOptions : class + where TClient : class + { + services.AddAzureClients(azureClientFactoryBuilder => + { + var clientBuilder = + ((IAzureClientFactoryBuilderWithConfiguration)azureClientFactoryBuilder) + .RegisterClientFactory(configuration); + + if (!string.IsNullOrWhiteSpace(serviceKey)) clientBuilder.WithName(serviceKey); + clientBuilder.ConfigureOptions(options => configureOptions?.Invoke(options)); + }); + + + if (!string.IsNullOrWhiteSpace(serviceKey)) + services.AddKeyedSingleton(serviceKey, + static (serviceProvider, serviceKey) => serviceProvider + .GetRequiredService>().CreateClient((string)serviceKey!)); + } + + /// + /// Registers the observability for the Azure Client + /// + /// The to read config from and add services to. + /// + /// If not null, registers a keyed service with the service key. If null, registers a default + /// service + /// + /// Indicates if Tracing is enabled or not. + /// Indicates if HealthChecks are enabled or not. + /// The factory used to create the health checks if enabled + public static void IgniteAzureClientObservability(this IServiceCollection services, string? serviceKey, + bool tracingEnabled, + bool healthChecksEnabled, + Func healthCheckFactory) where TClient : class + { + if (tracingEnabled) + services.AddOpenTelemetry().WithTracing(traceBuilder => + traceBuilder.AddSource([$"{typeof(TClient).Namespace}.*"])); + + if (healthChecksEnabled) + { + var healthCheckName = + $"{nameof(Azure)}-{typeof(TClient).Name}-{(string.IsNullOrWhiteSpace(serviceKey) ? string.Empty : $"[{serviceKey}]")}"; + services.AddHealthChecks().Add(new HealthCheckRegistration(healthCheckName, + serviceProvider => healthCheckFactory(serviceProvider, + serviceProvider.GetRequiredKeyedService(serviceKey)), + default, + [nameof(Azure), typeof(TClient).Name], + default)); + } + } +} \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Data.Tables/AzureDataTablesSpark.cs b/src/ES.FX.Ignite.Azure.Data.Tables/AzureDataTablesSpark.cs new file mode 100644 index 0000000..065db3e --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Data.Tables/AzureDataTablesSpark.cs @@ -0,0 +1,20 @@ +using ES.FX.Ignite.Spark.Configuration; + +namespace ES.FX.Ignite.Azure.Data.Tables; + +/// +/// definition +/// +public static class AzureDataTablesSpark +{ + /// + /// Spark name + /// + public const string Name = "AzureDataTables"; + + /// + /// The default configuration section path + /// + public const string ConfigurationSectionPath = + $"{IgniteConfigurationSections.Ignite}:{nameof(Azure)}:{nameof(Data)}:{nameof(Tables)}"; +} \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Data.Tables/Configuration/AzureDataTablesSparkSettings.cs b/src/ES.FX.Ignite.Azure.Data.Tables/Configuration/AzureDataTablesSparkSettings.cs new file mode 100644 index 0000000..46d3e65 --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Data.Tables/Configuration/AzureDataTablesSparkSettings.cs @@ -0,0 +1,20 @@ +using Azure.Data.Tables; +using ES.FX.Ignite.Spark.Configuration.Abstractions; + +namespace ES.FX.Ignite.Azure.Data.Tables.Configuration; + +/// +/// Provides the settings for connecting to Azure Storage using a +/// +public class AzureDataTablesSparkSettings : ISparkHealthCheckSettings, ISparkTracingSettings +{ + /// + /// + /// + public bool HealthChecksEnabled { get; set; } = true; + + /// + /// + /// + public bool TracingEnabled { get; set; } = true; +} \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Data.Tables/ES.FX.Ignite.Azure.Data.Tables.csproj b/src/ES.FX.Ignite.Azure.Data.Tables/ES.FX.Ignite.Azure.Data.Tables.csproj new file mode 100644 index 0000000..275b7fc --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Data.Tables/ES.FX.Ignite.Azure.Data.Tables.csproj @@ -0,0 +1,20 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Data.Tables/Hosting/AzureDataTablesHostingExtensions.cs b/src/ES.FX.Ignite.Azure.Data.Tables/Hosting/AzureDataTablesHostingExtensions.cs new file mode 100644 index 0000000..f188283 --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Data.Tables/Hosting/AzureDataTablesHostingExtensions.cs @@ -0,0 +1,61 @@ +using Azure.Data.Tables; +using ES.FX.Ignite.Azure.Common.Hosting; +using ES.FX.Ignite.Azure.Data.Tables.Configuration; +using ES.FX.Ignite.Spark.Configuration; +using HealthChecks.Azure.Data.Tables; +using JetBrains.Annotations; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace ES.FX.Ignite.Azure.Data.Tables.Hosting; + +[PublicAPI] +public static class AzureDataTablesHostingExtensions +{ + /// + /// Registers as a service in the services provided by the + /// . + /// Enables health check, logging and telemetry for the . + /// + /// The to read config from and add services to. + /// A name used to retrieve the settings and options from configuration + /// + /// If not null, registers a keyed service with the service key. If null, registers a default + /// service + /// + /// + /// An optional delegate that can be used for customizing settings. It's invoked after the + /// settings are read from the configuration. + /// + /// + /// An optional delegate that can be used for customizing options. It's invoked after the + /// options are read from the configuration. + /// + /// + /// The configuration section path. Default is + /// . + /// + public static void IgniteAzureTableServiceClient(this IHostApplicationBuilder builder, + string? name = null, + string? serviceKey = null, + Action? configureSettings = null, + Action? configureClientOptions = null, + string configurationSectionPath = AzureDataTablesSpark.ConfigurationSectionPath) + { + builder.GuardConfigurationKey($"{AzureDataTablesSpark.Name}-[{serviceKey}]"); + + var configPath = SparkConfig.Path(name, configurationSectionPath); + + var settings = SparkConfig.GetSettings(builder.Configuration, configPath, configureSettings); + builder.Services.AddKeyedSingleton(serviceKey, settings); + + builder.Services.IgniteAzureClient(serviceKey, + builder.Configuration.GetSection(configPath), + configureClientOptions); + + builder.Services.IgniteAzureClientObservability(serviceKey, + settings.TracingEnabled, + settings.HealthChecksEnabled, + (_, client) => new AzureTableServiceHealthCheck(client, null)); + } +} \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Security.KeyVault.Secrets/AzureKeyVaultSecretsSpark.cs b/src/ES.FX.Ignite.Azure.Security.KeyVault.Secrets/AzureKeyVaultSecretsSpark.cs new file mode 100644 index 0000000..f95b645 --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Security.KeyVault.Secrets/AzureKeyVaultSecretsSpark.cs @@ -0,0 +1,20 @@ +using ES.FX.Ignite.Spark.Configuration; + +namespace ES.FX.Ignite.Azure.Security.KeyVault.Secrets; + +/// +/// definition +/// +public static class AzureKeyVaultSecretsSpark +{ + /// + /// Spark name + /// + public const string Name = "AzureKeyVaultSecrets"; + + /// + /// The default configuration section path + /// + public const string ConfigurationSectionPath = + $"{IgniteConfigurationSections.Ignite}:{nameof(Azure)}:{nameof(KeyVault)}:{nameof(Secrets)}"; +} \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Security.KeyVault.Secrets/Configuration/AzureKeyVaultSecretsSparkSettings.cs b/src/ES.FX.Ignite.Azure.Security.KeyVault.Secrets/Configuration/AzureKeyVaultSecretsSparkSettings.cs new file mode 100644 index 0000000..5a843ec --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Security.KeyVault.Secrets/Configuration/AzureKeyVaultSecretsSparkSettings.cs @@ -0,0 +1,20 @@ +using Azure.Security.KeyVault.Secrets; +using ES.FX.Ignite.Spark.Configuration.Abstractions; + +namespace ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Configuration; + +/// +/// Provides the settings for connecting to Azure KeyVault using a +/// +public class AzureKeyVaultSecretsSparkSettings : ISparkHealthCheckSettings, ISparkTracingSettings +{ + /// + /// + /// + public bool HealthChecksEnabled { get; set; } = true; + + /// + /// + /// + public bool TracingEnabled { get; set; } = true; +} \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Security.KeyVault.Secrets/ES.FX.Ignite.Azure.Security.KeyVault.Secrets.csproj b/src/ES.FX.Ignite.Azure.Security.KeyVault.Secrets/ES.FX.Ignite.Azure.Security.KeyVault.Secrets.csproj new file mode 100644 index 0000000..d20a00a --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Security.KeyVault.Secrets/ES.FX.Ignite.Azure.Security.KeyVault.Secrets.csproj @@ -0,0 +1,20 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Security.KeyVault.Secrets/Hosting/AzureKeyVaultSecretsHostingExtensions.cs b/src/ES.FX.Ignite.Azure.Security.KeyVault.Secrets/Hosting/AzureKeyVaultSecretsHostingExtensions.cs new file mode 100644 index 0000000..873a774 --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Security.KeyVault.Secrets/Hosting/AzureKeyVaultSecretsHostingExtensions.cs @@ -0,0 +1,61 @@ +using Azure.Security.KeyVault.Secrets; +using ES.FX.Ignite.Azure.Common.Hosting; +using ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Configuration; +using ES.FX.Ignite.Spark.Configuration; +using HealthChecks.Azure.KeyVault.Secrets; +using JetBrains.Annotations; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Hosting; + +[PublicAPI] +public static class AzureKeyVaultSecretsHostingExtensions +{ + /// + /// Registers as a service in the services provided by the + /// . + /// Enables health check, logging and telemetry for the . + /// + /// The to read config from and add services to. + /// A name used to retrieve the settings and options from configuration + /// + /// If not null, registers a keyed service with the service key. If null, registers a default + /// service + /// + /// + /// An optional delegate that can be used for customizing settings. It's invoked after the + /// settings are read from the configuration. + /// + /// + /// An optional delegate that can be used for customizing options. It's invoked after the + /// options are read from the configuration. + /// + /// + /// The configuration section path. Default is + /// . + /// + public static void IgniteAzureKeyVaultSecretClient(this IHostApplicationBuilder builder, + string? name = null, + string? serviceKey = null, + Action? configureSettings = null, + Action? configureClientOptions = null, + string configurationSectionPath = AzureKeyVaultSecretsSpark.ConfigurationSectionPath) + { + builder.GuardConfigurationKey($"{AzureKeyVaultSecretsSpark.Name}-[{serviceKey}]"); + + var configPath = SparkConfig.Path(name, configurationSectionPath); + + var settings = SparkConfig.GetSettings(builder.Configuration, configPath, configureSettings); + builder.Services.AddKeyedSingleton(serviceKey, settings); + + builder.Services.IgniteAzureClient(serviceKey, + builder.Configuration.GetSection(configPath), + configureClientOptions); + + builder.Services.IgniteAzureClientObservability(serviceKey, + settings.TracingEnabled, + settings.HealthChecksEnabled, + (_, client) => new AzureKeyVaultSecretsHealthCheck(client)); + } +} \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Storage.Blobs/AzureBlobStorageSpark.cs b/src/ES.FX.Ignite.Azure.Storage.Blobs/AzureBlobStorageSpark.cs new file mode 100644 index 0000000..201429c --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Storage.Blobs/AzureBlobStorageSpark.cs @@ -0,0 +1,20 @@ +using ES.FX.Ignite.Spark.Configuration; + +namespace ES.FX.Ignite.Azure.Storage.Blobs; + +/// +/// definition +/// +public static class AzureBlobStorageSpark +{ + /// + /// Spark name + /// + public const string Name = "AzureBlobStorage"; + + /// + /// The default configuration section path + /// + public const string ConfigurationSectionPath = + $"{IgniteConfigurationSections.Ignite}:{nameof(Azure)}:{nameof(Storage)}:{nameof(Blobs)}"; +} \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Storage.Blobs/Configuration/AzureBlobStorageSparkSettings.cs b/src/ES.FX.Ignite.Azure.Storage.Blobs/Configuration/AzureBlobStorageSparkSettings.cs new file mode 100644 index 0000000..73bf585 --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Storage.Blobs/Configuration/AzureBlobStorageSparkSettings.cs @@ -0,0 +1,20 @@ +using Azure.Storage.Blobs; +using ES.FX.Ignite.Spark.Configuration.Abstractions; + +namespace ES.FX.Ignite.Azure.Storage.Blobs.Configuration; + +/// +/// Provides the settings for connecting to Azure Storage using a +/// +public class AzureBlobStorageSparkSettings : ISparkHealthCheckSettings, ISparkTracingSettings +{ + /// + /// + /// + public bool HealthChecksEnabled { get; set; } = true; + + /// + /// + /// + public bool TracingEnabled { get; set; } = true; +} \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Storage.Blobs/ES.FX.Ignite.Azure.Storage.Blobs.csproj b/src/ES.FX.Ignite.Azure.Storage.Blobs/ES.FX.Ignite.Azure.Storage.Blobs.csproj new file mode 100644 index 0000000..82d69e6 --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Storage.Blobs/ES.FX.Ignite.Azure.Storage.Blobs.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Storage.Blobs/Hosting/AzureBlobStorageHostingExtensions.cs b/src/ES.FX.Ignite.Azure.Storage.Blobs/Hosting/AzureBlobStorageHostingExtensions.cs new file mode 100644 index 0000000..29ae9ee --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Storage.Blobs/Hosting/AzureBlobStorageHostingExtensions.cs @@ -0,0 +1,61 @@ +using Azure.Storage.Blobs; +using ES.FX.Ignite.Azure.Common.Hosting; +using ES.FX.Ignite.Azure.Storage.Blobs.Configuration; +using ES.FX.Ignite.Spark.Configuration; +using HealthChecks.Azure.Storage.Blobs; +using JetBrains.Annotations; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace ES.FX.Ignite.Azure.Storage.Blobs.Hosting; + +[PublicAPI] +public static class AzureBlobStorageHostingExtensions +{ + /// + /// Registers as a service in the services provided by the + /// . + /// Enables health check, logging and telemetry for the . + /// + /// The to read config from and add services to. + /// A name used to retrieve the settings and options from configuration + /// + /// If not null, registers a keyed service with the service key. If null, registers a default + /// service + /// + /// + /// An optional delegate that can be used for customizing settings. It's invoked after the + /// settings are read from the configuration. + /// + /// + /// An optional delegate that can be used for customizing options. It's invoked after the + /// options are read from the configuration. + /// + /// + /// The configuration section path. Default is + /// . + /// + public static void IgniteAzureBlobServiceClient(this IHostApplicationBuilder builder, + string? name = null, + string? serviceKey = null, + Action? configureSettings = null, + Action? configureClientOptions = null, + string configurationSectionPath = AzureBlobStorageSpark.ConfigurationSectionPath) + { + builder.GuardConfigurationKey($"{AzureBlobStorageSpark.Name}-[{serviceKey}]"); + + var configPath = SparkConfig.Path(name, configurationSectionPath); + + var settings = SparkConfig.GetSettings(builder.Configuration, configPath, configureSettings); + builder.Services.AddKeyedSingleton(serviceKey, settings); + + builder.Services.IgniteAzureClient(serviceKey, + builder.Configuration.GetSection(configPath), + configureClientOptions); + + builder.Services.IgniteAzureClientObservability(serviceKey, + settings.TracingEnabled, + settings.HealthChecksEnabled, + (_, client) => new AzureBlobStorageHealthCheck(client)); + } +} \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Storage.Queues/AzureQueueStorageSpark.cs b/src/ES.FX.Ignite.Azure.Storage.Queues/AzureQueueStorageSpark.cs new file mode 100644 index 0000000..cc372a1 --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Storage.Queues/AzureQueueStorageSpark.cs @@ -0,0 +1,20 @@ +using ES.FX.Ignite.Spark.Configuration; + +namespace ES.FX.Ignite.Azure.Storage.Queues; + +/// +/// definition +/// +public static class AzureQueueStorageSpark +{ + /// + /// Spark name + /// + public const string Name = "AzureQueueStorage"; + + /// + /// The default configuration section path + /// + public const string ConfigurationSectionPath = + $"{IgniteConfigurationSections.Ignite}:{nameof(Azure)}:{nameof(Storage)}:{nameof(Queues)}"; +} \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Storage.Queues/Configuration/AzureQueueStorageSparkSettings.cs b/src/ES.FX.Ignite.Azure.Storage.Queues/Configuration/AzureQueueStorageSparkSettings.cs new file mode 100644 index 0000000..204ff35 --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Storage.Queues/Configuration/AzureQueueStorageSparkSettings.cs @@ -0,0 +1,20 @@ +using Azure.Storage.Queues; +using ES.FX.Ignite.Spark.Configuration.Abstractions; + +namespace ES.FX.Ignite.Azure.Storage.Queues.Configuration; + +/// +/// Provides the settings for connecting to Azure Storage using a +/// +public class AzureQueueStorageSparkSettings : ISparkHealthCheckSettings, ISparkTracingSettings +{ + /// + /// + /// + public bool HealthChecksEnabled { get; set; } = true; + + /// + /// + /// + public bool TracingEnabled { get; set; } = true; +} \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Storage.Queues/ES.FX.Ignite.Azure.Storage.Queues.csproj b/src/ES.FX.Ignite.Azure.Storage.Queues/ES.FX.Ignite.Azure.Storage.Queues.csproj new file mode 100644 index 0000000..06309b8 --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Storage.Queues/ES.FX.Ignite.Azure.Storage.Queues.csproj @@ -0,0 +1,19 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ES.FX.Ignite.Azure.Storage.Queues/Hosting/AzureQueueStorageHostingExtensions.cs b/src/ES.FX.Ignite.Azure.Storage.Queues/Hosting/AzureQueueStorageHostingExtensions.cs new file mode 100644 index 0000000..1c6f8a1 --- /dev/null +++ b/src/ES.FX.Ignite.Azure.Storage.Queues/Hosting/AzureQueueStorageHostingExtensions.cs @@ -0,0 +1,61 @@ +using Azure.Storage.Queues; +using ES.FX.Ignite.Azure.Common.Hosting; +using ES.FX.Ignite.Azure.Storage.Queues.Configuration; +using ES.FX.Ignite.Spark.Configuration; +using HealthChecks.Azure.Storage.Queues; +using JetBrains.Annotations; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace ES.FX.Ignite.Azure.Storage.Queues.Hosting; + +[PublicAPI] +public static class AzureQueueStorageHostingExtensions +{ + /// + /// Registers as a service in the services provided by the + /// . + /// Enables health check, logging and telemetry for the . + /// + /// The to read config from and add services to. + /// A name used to retrieve the settings and options from configuration + /// + /// If not null, registers a keyed service with the service key. If null, registers a default + /// service + /// + /// + /// An optional delegate that can be used for customizing settings. It's invoked after the + /// settings are read from the configuration. + /// + /// + /// An optional delegate that can be used for customizing options. It's invoked after the + /// options are read from the configuration. + /// + /// + /// The configuration section path. Default is + /// . + /// + public static void IgniteAzureQueueServiceClient(this IHostApplicationBuilder builder, + string? name = null, + string? serviceKey = null, + Action? configureSettings = null, + Action? configureClientOptions = null, + string configurationSectionPath = AzureQueueStorageSpark.ConfigurationSectionPath) + { + builder.GuardConfigurationKey($"{AzureQueueStorageSpark.Name}-[{serviceKey}]"); + + var configPath = SparkConfig.Path(name, configurationSectionPath); + + var settings = SparkConfig.GetSettings(builder.Configuration, configPath, configureSettings); + builder.Services.AddKeyedSingleton(serviceKey, settings); + + builder.Services.IgniteAzureClient(serviceKey, + builder.Configuration.GetSection(configPath), + configureClientOptions); + + builder.Services.IgniteAzureClientObservability(serviceKey, + settings.TracingEnabled, + settings.HealthChecksEnabled, + (_, client) => new AzureQueueStorageHealthCheck(client)); + } +} \ No newline at end of file diff --git a/src/ES.FX.Ignite.Microsoft.Data.SqlClient/Configuration/SqlServerClientSparkSettings.cs b/src/ES.FX.Ignite.Microsoft.Data.SqlClient/Configuration/SqlServerClientSparkSettings.cs index 49440f5..845320f 100644 --- a/src/ES.FX.Ignite.Microsoft.Data.SqlClient/Configuration/SqlServerClientSparkSettings.cs +++ b/src/ES.FX.Ignite.Microsoft.Data.SqlClient/Configuration/SqlServerClientSparkSettings.cs @@ -1,19 +1,20 @@ -using Microsoft.Data.SqlClient; +using ES.FX.Ignite.Spark.Configuration.Abstractions; +using Microsoft.Data.SqlClient; namespace ES.FX.Ignite.Microsoft.Data.SqlClient.Configuration; /// /// Provides the settings for connecting to a SQL Server database using a /// -public class SqlServerClientSparkSettings +public class SqlServerClientSparkSettings : ISparkHealthCheckSettings, ISparkTracingSettings { /// - /// Gets or sets a boolean value that indicates whether the database health checks are enabled. + /// /// public bool HealthChecksEnabled { get; set; } = true; /// - /// Gets or sets a boolean value that indicates whether the OpenTelemetry tracing is enabled. + /// /// public bool TracingEnabled { get; set; } = true; } \ No newline at end of file diff --git a/src/ES.FX.Ignite.Microsoft.EntityFrameworkCore.SqlServer/Configuration/SqlServerDbContextSparkSettings.cs b/src/ES.FX.Ignite.Microsoft.EntityFrameworkCore.SqlServer/Configuration/SqlServerDbContextSparkSettings.cs index 5aab625..212447a 100644 --- a/src/ES.FX.Ignite.Microsoft.EntityFrameworkCore.SqlServer/Configuration/SqlServerDbContextSparkSettings.cs +++ b/src/ES.FX.Ignite.Microsoft.EntityFrameworkCore.SqlServer/Configuration/SqlServerDbContextSparkSettings.cs @@ -1,4 +1,5 @@ -using Microsoft.EntityFrameworkCore; +using ES.FX.Ignite.Spark.Configuration.Abstractions; +using Microsoft.EntityFrameworkCore; namespace ES.FX.Ignite.Microsoft.EntityFrameworkCore.SqlServer.Configuration; @@ -7,15 +8,16 @@ namespace ES.FX.Ignite.Microsoft.EntityFrameworkCore.SqlServer.Configuration; /// /// /// type -public class SqlServerDbContextSparkSettings where TDbContext : DbContext +public class SqlServerDbContextSparkSettings : ISparkHealthCheckSettings, ISparkTracingSettings + where TDbContext : DbContext { /// - /// Gets or sets a boolean value that indicates whether the database health checks are enabled or not. + /// /// public bool HealthChecksEnabled { get; set; } = true; /// - /// Gets or sets a boolean value that indicates whether the OpenTelemetry tracing is enabled or not. + /// /// public bool TracingEnabled { get; set; } = true; } \ No newline at end of file diff --git a/src/ES.FX.Ignite.Microsoft.EntityFrameworkCore.SqlServer/ES.FX.Ignite.Microsoft.EntityFrameworkCore.SqlServer.csproj b/src/ES.FX.Ignite.Microsoft.EntityFrameworkCore.SqlServer/ES.FX.Ignite.Microsoft.EntityFrameworkCore.SqlServer.csproj index 88f416f..a7e2f18 100644 --- a/src/ES.FX.Ignite.Microsoft.EntityFrameworkCore.SqlServer/ES.FX.Ignite.Microsoft.EntityFrameworkCore.SqlServer.csproj +++ b/src/ES.FX.Ignite.Microsoft.EntityFrameworkCore.SqlServer/ES.FX.Ignite.Microsoft.EntityFrameworkCore.SqlServer.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/ES.FX.Ignite.OpenTelemetry.Exporter.Seq/Configuration/SeqOpenTelemetryExporterSparkSettings.cs b/src/ES.FX.Ignite.OpenTelemetry.Exporter.Seq/Configuration/SeqOpenTelemetryExporterSparkSettings.cs index adcb062..9d5e8f7 100644 --- a/src/ES.FX.Ignite.OpenTelemetry.Exporter.Seq/Configuration/SeqOpenTelemetryExporterSparkSettings.cs +++ b/src/ES.FX.Ignite.OpenTelemetry.Exporter.Seq/Configuration/SeqOpenTelemetryExporterSparkSettings.cs @@ -1,9 +1,11 @@ -namespace ES.FX.Ignite.OpenTelemetry.Exporter.Seq.Configuration; +using ES.FX.Ignite.Spark.Configuration.Abstractions; + +namespace ES.FX.Ignite.OpenTelemetry.Exporter.Seq.Configuration; /// /// Provides the settings for connecting to Seq /// -public class SeqOpenTelemetryExporterSparkSettings +public class SeqOpenTelemetryExporterSparkSettings : ISparkHealthCheckSettings { /// /// Gets or sets a boolean value that indicates whether the Seq is enabled. @@ -22,7 +24,7 @@ public class SeqOpenTelemetryExporterSparkSettings public bool TracesExporterEnabled { get; set; } = true; /// - /// Gets or sets a boolean value that indicates whether the health checks are enabled. + /// /// public bool HealthChecksEnabled { get; set; } = true; } \ No newline at end of file diff --git a/src/ES.FX.Ignite.OpenTelemetry.Exporter.Seq/Hosting/SeqOpenTelemetryExporterHostingExtensions.cs b/src/ES.FX.Ignite.OpenTelemetry.Exporter.Seq/Hosting/SeqOpenTelemetryExporterHostingExtensions.cs index 151d9cc..b996cfa 100644 --- a/src/ES.FX.Ignite.OpenTelemetry.Exporter.Seq/Hosting/SeqOpenTelemetryExporterHostingExtensions.cs +++ b/src/ES.FX.Ignite.OpenTelemetry.Exporter.Seq/Hosting/SeqOpenTelemetryExporterHostingExtensions.cs @@ -26,9 +26,7 @@ public static void IgniteSeqOpenTelemetryExporter(this IHostApplicationBuilder b Action? configureOptions = null, string configurationSectionPath = SeqOpenTelemetryExporterSpark.ConfigurationSectionPath) { - var configPath = string.IsNullOrWhiteSpace(name) - ? configurationSectionPath - : SparkConfig.Path(name, configurationSectionPath); + var configPath = SparkConfig.Path(name, configurationSectionPath); var settings = SparkConfig.GetSettings(builder.Configuration, configPath, configureSettings); builder.Services.AddKeyedSingleton(name, settings); diff --git a/src/ES.FX.Ignite.Spark/Configuration/Abstractions/ISparkHealthCheckSettings.cs b/src/ES.FX.Ignite.Spark/Configuration/Abstractions/ISparkHealthCheckSettings.cs new file mode 100644 index 0000000..1573ff3 --- /dev/null +++ b/src/ES.FX.Ignite.Spark/Configuration/Abstractions/ISparkHealthCheckSettings.cs @@ -0,0 +1,9 @@ +namespace ES.FX.Ignite.Spark.Configuration.Abstractions; + +public interface ISparkHealthCheckSettings +{ + /// + /// Gets or sets a boolean value that indicates whether the health checks are enabled. + /// + public bool HealthChecksEnabled { get; set; } +} \ No newline at end of file diff --git a/src/ES.FX.Ignite.Spark/Configuration/Abstractions/ISparkTracingSettings.cs b/src/ES.FX.Ignite.Spark/Configuration/Abstractions/ISparkTracingSettings.cs new file mode 100644 index 0000000..75f5494 --- /dev/null +++ b/src/ES.FX.Ignite.Spark/Configuration/Abstractions/ISparkTracingSettings.cs @@ -0,0 +1,9 @@ +namespace ES.FX.Ignite.Spark.Configuration.Abstractions; + +public interface ISparkTracingSettings +{ + /// + /// Gets or sets a boolean value that indicates whether the OpenTelemetry tracing is enabled. + /// + public bool TracingEnabled { get; set; } +} \ No newline at end of file diff --git a/src/ES.FX.Ignite.Spark/Configuration/ConfigurationGuard.cs b/src/ES.FX.Ignite.Spark/Configuration/KeyedConfigurationGuard.cs similarity index 100% rename from src/ES.FX.Ignite.Spark/Configuration/ConfigurationGuard.cs rename to src/ES.FX.Ignite.Spark/Configuration/KeyedConfigurationGuard.cs diff --git a/src/ES.FX.Ignite.Spark/Configuration/SparkConfig.cs b/src/ES.FX.Ignite.Spark/Configuration/SparkConfig.cs index 4a47e48..b413f0c 100644 --- a/src/ES.FX.Ignite.Spark/Configuration/SparkConfig.cs +++ b/src/ES.FX.Ignite.Spark/Configuration/SparkConfig.cs @@ -30,10 +30,12 @@ public static string Name(string? name, string defaultName) /// Name of the service /// Section path /// - public static string Path(string serviceName, string sectionPath) + public static string Path(string? serviceName, string sectionPath) { - serviceName = serviceName.Trim(); sectionPath = sectionPath.Trim(); + + if (string.IsNullOrWhiteSpace(serviceName)) return sectionPath; + serviceName = serviceName.Trim(); var configPath = sectionPath == string.Empty ? serviceName : $"{sectionPath}:{serviceName}"; return configPath; diff --git a/src/ES.FX.Ignite.Spark/Exceptions/SparkReconfigurationNotSupportedException.cs b/src/ES.FX.Ignite.Spark/Exceptions/ReconfigurationNotSupportedException.cs similarity index 100% rename from src/ES.FX.Ignite.Spark/Exceptions/SparkReconfigurationNotSupportedException.cs rename to src/ES.FX.Ignite.Spark/Exceptions/ReconfigurationNotSupportedException.cs diff --git a/src/ES.FX.Ignite.Swashbuckle/Configuration/SwashbuckleSparkSettings.cs b/src/ES.FX.Ignite.Swashbuckle/Configuration/SwashbuckleSparkSettings.cs index 6900ae3..448299e 100644 --- a/src/ES.FX.Ignite.Swashbuckle/Configuration/SwashbuckleSparkSettings.cs +++ b/src/ES.FX.Ignite.Swashbuckle/Configuration/SwashbuckleSparkSettings.cs @@ -5,11 +5,6 @@ /// public class SwashbuckleSparkSettings { - /// - /// Gets or sets a value indicating whether SwaggerGen is enabled - /// - public bool SwaggerGenEnabled { get; set; } = true; - /// /// Gets or sets a value indicating whether Swagger is enabled /// diff --git a/tests/ES.FX.Asp.Versioning.Tests/ES.FX.Asp.Versioning.Tests.csproj b/tests/ES.FX.Asp.Versioning.Tests/ES.FX.Asp.Versioning.Tests.csproj index 805efa6..5330fe8 100644 --- a/tests/ES.FX.Asp.Versioning.Tests/ES.FX.Asp.Versioning.Tests.csproj +++ b/tests/ES.FX.Asp.Versioning.Tests/ES.FX.Asp.Versioning.Tests.csproj @@ -14,7 +14,6 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/tests/ES.FX.Ignite.Asp.Versioning.Tests/Hosting/ApiVersioningHostingExtensionsTests.cs b/tests/ES.FX.Ignite.Asp.Versioning.Tests/HostingTests.cs similarity index 87% rename from tests/ES.FX.Ignite.Asp.Versioning.Tests/Hosting/ApiVersioningHostingExtensionsTests.cs rename to tests/ES.FX.Ignite.Asp.Versioning.Tests/HostingTests.cs index 677d4c3..3440cb1 100644 --- a/tests/ES.FX.Ignite.Asp.Versioning.Tests/Hosting/ApiVersioningHostingExtensionsTests.cs +++ b/tests/ES.FX.Ignite.Asp.Versioning.Tests/HostingTests.cs @@ -3,9 +3,9 @@ using ES.FX.Ignite.Asp.Versioning.Hosting; using Microsoft.Extensions.Hosting; -namespace ES.FX.Ignite.Asp.Versioning.Tests.Hosting; +namespace ES.FX.Ignite.Asp.Versioning.Tests; -public class ApiVersioningHostingExtensionsTests +public class HostingTests { [Fact] public void ServicesAdded() diff --git a/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests.SUT/Program.cs b/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests.SUT/Program.cs index 5eb6da5..295c19f 100644 --- a/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests.SUT/Program.cs +++ b/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests.SUT/Program.cs @@ -9,6 +9,9 @@ app.Run(); // ReSharper disable once UnusedMember.Global -public partial class Program +namespace ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests.SUT { + public class Program + { + } } \ No newline at end of file diff --git a/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests.SUT/Properties/launchSettings.json b/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests.SUT/Properties/launchSettings.json new file mode 100644 index 0000000..9e1f63f --- /dev/null +++ b/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests.SUT/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests.SUT": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:50927;http://localhost:50928" + } + } +} \ No newline at end of file diff --git a/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests.csproj b/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests.csproj index 726d989..aadc74c 100644 --- a/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests.csproj +++ b/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests.csproj @@ -33,4 +33,4 @@ - + \ No newline at end of file diff --git a/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests/Functional/HealthChecksUiFunctionalTests.cs b/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests/FunctionalTests.cs similarity index 69% rename from tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests/Functional/HealthChecksUiFunctionalTests.cs rename to tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests/FunctionalTests.cs index 0bcbee1..956bd10 100644 --- a/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests/Functional/HealthChecksUiFunctionalTests.cs +++ b/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests/FunctionalTests.cs @@ -1,9 +1,10 @@ using ES.FX.Ignite.AspNetCore.HealthChecks.UI.Configuration; +using ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests.SUT; using Microsoft.AspNetCore.Mvc.Testing; -namespace ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests.Functional; +namespace ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests; -public class HealthChecksUiFunctionalTests(WebApplicationFactory factory) +public class FunctionalTests(WebApplicationFactory factory) : IClassFixture> { [Fact] diff --git a/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests/Hosting/HealthChecksUiHostingExtensionsTests.cs b/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests/HostingTests.cs similarity index 95% rename from tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests/Hosting/HealthChecksUiHostingExtensionsTests.cs rename to tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests/HostingTests.cs index c3aa8c2..8d271f0 100644 --- a/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests/Hosting/HealthChecksUiHostingExtensionsTests.cs +++ b/tests/ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests/HostingTests.cs @@ -7,9 +7,9 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -namespace ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests.Hosting; +namespace ES.FX.Ignite.AspNetCore.HealthChecks.UI.Tests; -public class HealthChecksUiHostingExtensionsTests +public class HostingTests { [Fact] public void CanIgnite() diff --git a/tests/ES.FX.Ignite.Azure.Data.Tables.Tests/ES.FX.Ignite.Azure.Data.Tables.Tests.csproj b/tests/ES.FX.Ignite.Azure.Data.Tables.Tests/ES.FX.Ignite.Azure.Data.Tables.Tests.csproj new file mode 100644 index 0000000..fa49793 --- /dev/null +++ b/tests/ES.FX.Ignite.Azure.Data.Tables.Tests/ES.FX.Ignite.Azure.Data.Tables.Tests.csproj @@ -0,0 +1,35 @@ + + + + net8.0 + enable + enable + + false + true + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/ES.FX.Ignite.Azure.Data.Tables.Tests/HostingTests.cs b/tests/ES.FX.Ignite.Azure.Data.Tables.Tests/HostingTests.cs new file mode 100644 index 0000000..31bc71f --- /dev/null +++ b/tests/ES.FX.Ignite.Azure.Data.Tables.Tests/HostingTests.cs @@ -0,0 +1,38 @@ +using Azure.Data.Tables; +using ES.FX.Ignite.Azure.Data.Tables.Hosting; +using Microsoft.Extensions.Azure; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using static Xunit.Assert; + +namespace ES.FX.Ignite.Azure.Data.Tables.Tests; + +public class HostingTests +{ + [Theory] + [InlineData(null, null)] + [InlineData("default", null)] + [InlineData("default", "keyed")] + public void CanAdd(string? name, string? serviceKey) + { + var builder = Host.CreateEmptyApplicationBuilder(null); + builder.Configuration.AddInMemoryCollection([ + new KeyValuePair( + $"{AzureDataTablesSpark.ConfigurationSectionPath}{(string.IsNullOrWhiteSpace(name) ? string.Empty : $":{name}")}:ConnectionString", + "UseDevelopmentStorage=true;") + ]); + + builder.IgniteAzureTableServiceClient(name, serviceKey); + + var app = builder.Build(); + var client = app.Services.GetKeyedService(serviceKey); + NotNull(client); + + var factory = app.Services.GetRequiredService>(); + NotNull(factory); + + client = factory.CreateClient(serviceKey ?? "Default"); + NotNull(client); + } +} \ No newline at end of file diff --git a/tests/ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Tests/ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Tests.csproj b/tests/ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Tests/ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Tests.csproj new file mode 100644 index 0000000..2d2043e --- /dev/null +++ b/tests/ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Tests/ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Tests.csproj @@ -0,0 +1,35 @@ + + + + net8.0 + enable + enable + + false + true + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Tests/HostingTests.cs b/tests/ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Tests/HostingTests.cs new file mode 100644 index 0000000..db003a4 --- /dev/null +++ b/tests/ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Tests/HostingTests.cs @@ -0,0 +1,38 @@ +using Azure.Security.KeyVault.Secrets; +using ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Hosting; +using Microsoft.Extensions.Azure; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using static Xunit.Assert; + +namespace ES.FX.Ignite.Azure.Security.KeyVault.Secrets.Tests; + +public class HostingTests +{ + [Theory] + [InlineData(null, null)] + [InlineData("default", null)] + [InlineData("default", "keyed")] + public void CanAdd(string? name, string? serviceKey) + { + var builder = Host.CreateEmptyApplicationBuilder(null); + builder.Configuration.AddInMemoryCollection([ + new KeyValuePair( + $"{AzureKeyVaultSecretsSpark.ConfigurationSectionPath}{(string.IsNullOrWhiteSpace(name) ? string.Empty : $":{name}")}:VaultUri", + "https://vaulturi") + ]); + + builder.IgniteAzureKeyVaultSecretClient(name, serviceKey); + + var app = builder.Build(); + var client = app.Services.GetKeyedService(serviceKey); + NotNull(client); + + var factory = app.Services.GetRequiredService>(); + NotNull(factory); + + client = factory.CreateClient(serviceKey ?? "Default"); + NotNull(client); + } +} \ No newline at end of file diff --git a/tests/ES.FX.Ignite.Azure.Storage.Blobs.Tests/ES.FX.Ignite.Azure.Storage.Blobs.Tests.csproj b/tests/ES.FX.Ignite.Azure.Storage.Blobs.Tests/ES.FX.Ignite.Azure.Storage.Blobs.Tests.csproj new file mode 100644 index 0000000..48252c1 --- /dev/null +++ b/tests/ES.FX.Ignite.Azure.Storage.Blobs.Tests/ES.FX.Ignite.Azure.Storage.Blobs.Tests.csproj @@ -0,0 +1,34 @@ + + + + net8.0 + enable + enable + + false + true + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/ES.FX.Ignite.Azure.Storage.Blobs.Tests/HostingTests.cs b/tests/ES.FX.Ignite.Azure.Storage.Blobs.Tests/HostingTests.cs new file mode 100644 index 0000000..11d6799 --- /dev/null +++ b/tests/ES.FX.Ignite.Azure.Storage.Blobs.Tests/HostingTests.cs @@ -0,0 +1,38 @@ +using Azure.Storage.Blobs; +using ES.FX.Ignite.Azure.Storage.Blobs.Hosting; +using Microsoft.Extensions.Azure; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using static Xunit.Assert; + +namespace ES.FX.Ignite.Azure.Storage.Blobs.Tests; + +public class HostingTests +{ + [Theory] + [InlineData(null, null)] + [InlineData("default", null)] + [InlineData("default", "keyed")] + public void CanAdd(string? name, string? serviceKey) + { + var builder = Host.CreateEmptyApplicationBuilder(null); + builder.Configuration.AddInMemoryCollection([ + new KeyValuePair( + $"{AzureBlobStorageSpark.ConfigurationSectionPath}{(string.IsNullOrWhiteSpace(name) ? string.Empty : $":{name}")}:ConnectionString", + "UseDevelopmentStorage=true;") + ]); + + builder.IgniteAzureBlobServiceClient(name, serviceKey); + + var app = builder.Build(); + var client = app.Services.GetKeyedService(serviceKey); + NotNull(client); + + var factory = app.Services.GetRequiredService>(); + NotNull(factory); + + client = factory.CreateClient(serviceKey ?? "Default"); + NotNull(client); + } +} \ No newline at end of file diff --git a/tests/ES.FX.Ignite.Azure.Storage.Queues.Tests/ES.FX.Ignite.Azure.Storage.Queues.Tests.csproj b/tests/ES.FX.Ignite.Azure.Storage.Queues.Tests/ES.FX.Ignite.Azure.Storage.Queues.Tests.csproj new file mode 100644 index 0000000..3da5a65 --- /dev/null +++ b/tests/ES.FX.Ignite.Azure.Storage.Queues.Tests/ES.FX.Ignite.Azure.Storage.Queues.Tests.csproj @@ -0,0 +1,34 @@ + + + + net8.0 + enable + enable + + false + true + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/ES.FX.Ignite.Azure.Storage.Queues.Tests/HostingTests.cs b/tests/ES.FX.Ignite.Azure.Storage.Queues.Tests/HostingTests.cs new file mode 100644 index 0000000..825b714 --- /dev/null +++ b/tests/ES.FX.Ignite.Azure.Storage.Queues.Tests/HostingTests.cs @@ -0,0 +1,38 @@ +using Azure.Storage.Queues; +using ES.FX.Ignite.Azure.Storage.Queues.Hosting; +using Microsoft.Extensions.Azure; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using static Xunit.Assert; + +namespace ES.FX.Ignite.Azure.Storage.Queues.Tests; + +public class HostingTests +{ + [Theory] + [InlineData(null, null)] + [InlineData("default", null)] + [InlineData("default", "keyed")] + public void CanAdd(string? name, string? serviceKey) + { + var builder = Host.CreateEmptyApplicationBuilder(null); + builder.Configuration.AddInMemoryCollection([ + new KeyValuePair( + $"{AzureQueueStorageSpark.ConfigurationSectionPath}{(string.IsNullOrWhiteSpace(name) ? string.Empty : $":{name}")}:ConnectionString", + "UseDevelopmentStorage=true;") + ]); + + builder.IgniteAzureQueueServiceClient(name, serviceKey); + + var app = builder.Build(); + var client = app.Services.GetKeyedService(serviceKey); + NotNull(client); + + var factory = app.Services.GetRequiredService>(); + NotNull(factory); + + client = factory.CreateClient(serviceKey ?? "Default"); + NotNull(client); + } +} \ No newline at end of file diff --git a/tests/ES.FX.Ignite.FluentValidation.Tests.SUT/Program.cs b/tests/ES.FX.Ignite.FluentValidation.Tests.SUT/Program.cs index 1795856..cfb4caf 100644 --- a/tests/ES.FX.Ignite.FluentValidation.Tests.SUT/Program.cs +++ b/tests/ES.FX.Ignite.FluentValidation.Tests.SUT/Program.cs @@ -18,6 +18,9 @@ app.Run(); // ReSharper disable once UnusedMember.Global -public partial class Program +namespace ES.FX.Ignite.FluentValidation.Tests.SUT { + public class Program + { + } } \ No newline at end of file diff --git a/tests/ES.FX.Ignite.FluentValidation.Tests.SUT/Properties/launchSettings.json b/tests/ES.FX.Ignite.FluentValidation.Tests.SUT/Properties/launchSettings.json new file mode 100644 index 0000000..7fb7767 --- /dev/null +++ b/tests/ES.FX.Ignite.FluentValidation.Tests.SUT/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "ES.FX.Ignite.FluentValidation.Tests.SUT": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:50925;http://localhost:50926" + } + } +} \ No newline at end of file diff --git a/tests/ES.FX.Ignite.FluentValidation.Tests/Functional/FluentValidationFunctionalTests.cs b/tests/ES.FX.Ignite.FluentValidation.Tests/FunctionalTests.cs similarity index 84% rename from tests/ES.FX.Ignite.FluentValidation.Tests/Functional/FluentValidationFunctionalTests.cs rename to tests/ES.FX.Ignite.FluentValidation.Tests/FunctionalTests.cs index a0d6cd6..2a460d5 100644 --- a/tests/ES.FX.Ignite.FluentValidation.Tests/Functional/FluentValidationFunctionalTests.cs +++ b/tests/ES.FX.Ignite.FluentValidation.Tests/FunctionalTests.cs @@ -1,11 +1,12 @@ using System.Text; +using ES.FX.Ignite.FluentValidation.Tests.SUT; using ES.FX.Ignite.FluentValidation.Tests.SUT.Endpoints; using Microsoft.AspNetCore.Mvc.Testing; using Newtonsoft.Json; -namespace ES.FX.Ignite.FluentValidation.Tests.Functional; +namespace ES.FX.Ignite.FluentValidation.Tests; -public class FluentValidationFunctionalTests(WebApplicationFactory factory) +public class FunctionalTests(WebApplicationFactory factory) : IClassFixture> { [Theory] diff --git a/tests/ES.FX.Ignite.FluentValidation.Tests/Hosting/FluentValidationHostingExtensions.cs b/tests/ES.FX.Ignite.FluentValidation.Tests/HostingTests.cs similarity index 96% rename from tests/ES.FX.Ignite.FluentValidation.Tests/Hosting/FluentValidationHostingExtensions.cs rename to tests/ES.FX.Ignite.FluentValidation.Tests/HostingTests.cs index 39e51e5..558d222 100644 --- a/tests/ES.FX.Ignite.FluentValidation.Tests/Hosting/FluentValidationHostingExtensions.cs +++ b/tests/ES.FX.Ignite.FluentValidation.Tests/HostingTests.cs @@ -7,9 +7,9 @@ using Microsoft.Extensions.Hosting; using SharpGrip.FluentValidation.AutoValidation.Endpoints.Results; -namespace ES.FX.Ignite.FluentValidation.Tests.Hosting; +namespace ES.FX.Ignite.FluentValidation.Tests; -public class FluentValidationHostingExtensions +public class HostingTests { [Fact] public void IgniteDoesNotAllowReconfiguration() diff --git a/tests/ES.FX.Ignite.Microsoft.Data.SqlClient.Tests/ES.FX.Ignite.Microsoft.Data.SqlClient.Tests.csproj b/tests/ES.FX.Ignite.Microsoft.Data.SqlClient.Tests/ES.FX.Ignite.Microsoft.Data.SqlClient.Tests.csproj index 13e556b..370c7dd 100644 --- a/tests/ES.FX.Ignite.Microsoft.Data.SqlClient.Tests/ES.FX.Ignite.Microsoft.Data.SqlClient.Tests.csproj +++ b/tests/ES.FX.Ignite.Microsoft.Data.SqlClient.Tests/ES.FX.Ignite.Microsoft.Data.SqlClient.Tests.csproj @@ -1,36 +1,37 @@  - - net8.0 - enable - enable + + net8.0 + enable + enable - false - true - + false + true + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - - + + + + - - - + + + - + \ No newline at end of file diff --git a/tests/ES.FX.Ignite.Microsoft.EntityFrameworkCore.Tests/ES.FX.Ignite.Microsoft.EntityFrameworkCore.Tests.csproj b/tests/ES.FX.Ignite.Microsoft.EntityFrameworkCore.Tests/ES.FX.Ignite.Microsoft.EntityFrameworkCore.Tests.csproj index 14fa925..d4a98e9 100644 --- a/tests/ES.FX.Ignite.Microsoft.EntityFrameworkCore.Tests/ES.FX.Ignite.Microsoft.EntityFrameworkCore.Tests.csproj +++ b/tests/ES.FX.Ignite.Microsoft.EntityFrameworkCore.Tests/ES.FX.Ignite.Microsoft.EntityFrameworkCore.Tests.csproj @@ -10,8 +10,8 @@ - all - runtime; build; native; contentfiles; analyzers; buildtransitive + all + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -21,17 +21,18 @@ - all - runtime; build; native; contentfiles; analyzers; buildtransitive + all + runtime; build; native; contentfiles; analyzers; buildtransitive - + - + \ No newline at end of file diff --git a/tests/ES.FX.Ignite.Tests/Hosting/IgniteHostingExtensionsTests.cs b/tests/ES.FX.Ignite.Tests/HostingTests.cs similarity index 98% rename from tests/ES.FX.Ignite.Tests/Hosting/IgniteHostingExtensionsTests.cs rename to tests/ES.FX.Ignite.Tests/HostingTests.cs index c5eced1..ead33f2 100644 --- a/tests/ES.FX.Ignite.Tests/Hosting/IgniteHostingExtensionsTests.cs +++ b/tests/ES.FX.Ignite.Tests/HostingTests.cs @@ -14,9 +14,9 @@ using OpenTelemetry.Trace; using Polly; -namespace ES.FX.Ignite.Tests.Hosting; +namespace ES.FX.Ignite.Tests; -public class IgniteHostingExtensionsTests +public class HostingTests { [Fact] public void Ignite_WhenCalled_ShouldAddServices()