From afb308fa3f12f6bd1f4f1d9488f082ffe643ae4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?DELAGE=20Rapha=C3=ABl?= <36408929+delager@users.noreply.github.com> Date: Fri, 7 Apr 2023 18:18:38 +0200 Subject: [PATCH] #1929 Configuration logic by provider (#1984) * #1929 Configuration logic by provider - Add CloudProvider dependencies to the Server Startup - Add CloudProvider dependencies to the Infrastructure Startup - Azure first in the switch to unify * #1929 Healthcheck config - Move common healthcheck configuration * #1929 Move AWS Client - Move AWS client singletons into the infrastructure Layer --- .../AzureIoTHub.Portal.Infrastructure.csproj | 2 + .../ConfigHandlerFactory.cs | 2 +- .../Startup/AWSServiceCollectionExtension.cs | 37 +++ .../AzureServiceCollectionExtension.cs | 220 ++++++++++++++++++ .../Startup/IServiceCollectionExtension.cs | 203 +--------------- .../AzureIoTHub.Portal.Server.csproj | 4 +- src/AzureIoTHub.Portal.Server/Startup.cs | 89 +++---- 7 files changed, 320 insertions(+), 237 deletions(-) create mode 100644 src/AzureIoTHub.Portal.Infrastructure/Startup/AWSServiceCollectionExtension.cs create mode 100644 src/AzureIoTHub.Portal.Infrastructure/Startup/AzureServiceCollectionExtension.cs diff --git a/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj b/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj index b6e39fc6a..22c58a437 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj +++ b/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj @@ -106,6 +106,8 @@ + + diff --git a/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerFactory.cs b/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerFactory.cs index b45da02ed..07bb00b9b 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerFactory.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerFactory.cs @@ -26,8 +26,8 @@ public static ConfigHandler Create(IHostEnvironment env, IConfiguration config) { return config[ConfigHandlerBase.CloudProviderKey] switch { - CloudProviders.AWS => new ProductionAWSConfigHandler(config), CloudProviders.Azure => new ProductionAzureConfigHandler(config), + CloudProviders.AWS => new ProductionAWSConfigHandler(config), _ => throw new InvalidCloudProviderException(ErrorTitles.InvalidCloudProviderIncorrect), }; } diff --git a/src/AzureIoTHub.Portal.Infrastructure/Startup/AWSServiceCollectionExtension.cs b/src/AzureIoTHub.Portal.Infrastructure/Startup/AWSServiceCollectionExtension.cs new file mode 100644 index 000000000..f0d55197f --- /dev/null +++ b/src/AzureIoTHub.Portal.Infrastructure/Startup/AWSServiceCollectionExtension.cs @@ -0,0 +1,37 @@ +// Copyright (c) CGI France. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace AzureIoTHub.Portal.Infrastructure.Startup +{ + using Amazon; + using Amazon.IoT; + using Amazon.IotData; + using AzureIoTHub.Portal.Domain; + using Microsoft.Extensions.DependencyInjection; + + public static class AWSServiceCollectionExtension + { + public static IServiceCollection AddAWSInfrastructureLayer(this IServiceCollection services, ConfigHandler configuration) + { + return services.ConfigureAWSClient(configuration); + } + private static IServiceCollection ConfigureAWSClient(this IServiceCollection services, ConfigHandler configuration) + { + _ = services.AddSingleton(() => new AmazonIoTClient(configuration.AWSAccess, configuration.AWSAccessSecret, RegionEndpoint.GetBySystemName(configuration.AWSRegion))); + _ = services.AddSingleton(async sp => + { + var endpoint = await sp.GetService()!.DescribeEndpointAsync(new Amazon.IoT.Model.DescribeEndpointRequest + { + EndpointType = "iot:Data-ATS" + }); + + return new AmazonIotDataClient(configuration.AWSAccess, configuration.AWSAccessSecret, new AmazonIotDataConfig + { + ServiceURL = $"https://{endpoint.EndpointAddress}" + }); + }); + + return services; + } + } +} diff --git a/src/AzureIoTHub.Portal.Infrastructure/Startup/AzureServiceCollectionExtension.cs b/src/AzureIoTHub.Portal.Infrastructure/Startup/AzureServiceCollectionExtension.cs new file mode 100644 index 000000000..594be32b5 --- /dev/null +++ b/src/AzureIoTHub.Portal.Infrastructure/Startup/AzureServiceCollectionExtension.cs @@ -0,0 +1,220 @@ +// Copyright (c) CGI France. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace AzureIoTHub.Portal.Infrastructure.Startup +{ + using System.Net; + using Azure.Storage.Blobs; + using Azure.Storage.Blobs.Models; + using AzureIoTHub.Portal.Application.Managers; + using AzureIoTHub.Portal.Application.Mappers; + using AzureIoTHub.Portal.Application.Providers; + using AzureIoTHub.Portal.Application.Services; + using AzureIoTHub.Portal.Application.Wrappers; + using AzureIoTHub.Portal.Domain; + using AzureIoTHub.Portal.Domain.Options; + using AzureIoTHub.Portal.Domain.Repositories; + using AzureIoTHub.Portal.Infrastructure.Extensions; + using AzureIoTHub.Portal.Infrastructure.Jobs; + using AzureIoTHub.Portal.Infrastructure.Managers; + using AzureIoTHub.Portal.Infrastructure.Mappers; + using AzureIoTHub.Portal.Infrastructure.Providers; + using AzureIoTHub.Portal.Infrastructure.Repositories; + using AzureIoTHub.Portal.Infrastructure.Services; + using AzureIoTHub.Portal.Infrastructure.ServicesHealthCheck; + using AzureIoTHub.Portal.Infrastructure.Wrappers; + using AzureIoTHub.Portal.Models.v10; + using AzureIoTHub.Portal.Models.v10.LoRaWAN; + using Microsoft.Azure.Devices; + using Microsoft.Azure.Devices.Provisioning.Service; + using Microsoft.EntityFrameworkCore; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Options; + using Polly; + using Polly.Extensions.Http; + using Quartz; + + public static class AzureServiceCollectionExtension + { + public static IServiceCollection AddAzureInfrastructureLayer(this IServiceCollection services, ConfigHandler configuration) + { + return services.ConfigureRepositories() + .ConfigureImageBlobStorage(configuration) + .AddLoRaWanSupport(configuration) + .ConfigureDeviceRegstryDependencies(configuration) + .ConfigureServices() + .ConfigureMappers() + .ConfigureHealthCheck() + .ConfigureMetricsJobs(configuration) + .ConfigureSyncJobs(configuration); + } + + private static IServiceCollection AddLoRaWanSupport(this IServiceCollection services, ConfigHandler configuration) + { + _ = services.Configure(opts => + { + opts.Enabled = configuration.IsLoRaEnabled; + opts.KeyManagementApiVersion = configuration.LoRaKeyManagementApiVersion; + opts.KeyManagementCode = configuration.LoRaKeyManagementCode; + opts.KeyManagementUrl = configuration.LoRaKeyManagementUrl; + }); + + if (!configuration.IsLoRaEnabled) + { + return services; + } + + var transientHttpErrorPolicy = HttpPolicyExtensions + .HandleTransientHttpError() + .OrResult(c => c.StatusCode == HttpStatusCode.NotFound) + .WaitAndRetryAsync(3, _ => TimeSpan.FromMilliseconds(100)); + + _ = services.AddHttpClient("RestClient") + .AddPolicyHandler(transientHttpErrorPolicy); + + _ = services.AddHttpClient((sp, client) => + { + var opts = sp.GetService>()?.Value; + + client.BaseAddress = new Uri(opts?.KeyManagementUrl!); + client.DefaultRequestHeaders.Add("x-functions-key", opts?.KeyManagementCode); + client.DefaultRequestHeaders.Add("api-version", opts?.KeyManagementApiVersion ?? "2022-03-04"); + }) + .AddPolicyHandler(transientHttpErrorPolicy); + + return services; + } + + private static IServiceCollection ConfigureDeviceRegstryDependencies(this IServiceCollection services, ConfigHandler configuration) + { + _ = services.AddTransient(); + _ = services.AddTransient(); + + _ = services.AddScoped(_ => RegistryManager.CreateFromConnectionString(configuration.IoTHubConnectionString)); + _ = services.AddScoped(_ => ServiceClient.CreateFromConnectionString(configuration.IoTHubConnectionString)); + _ = services.AddScoped(_ => ProvisioningServiceClient.CreateFromConnectionString(configuration.DPSConnectionString)); + + return services; + } + + private static IServiceCollection ConfigureRepositories(this IServiceCollection services) + { + return services.AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped(); + } + + private static IServiceCollection ConfigureMappers(this IServiceCollection services) + { + _ = services.AddTransient(); + _ = services.AddTransient(); + _ = services.AddTransient(); + + return services.AddTransient, DeviceTwinMapper>() + .AddTransient, LoRaDeviceTwinMapper>() + .AddTransient, DeviceModelMapper>() + .AddTransient, LoRaDeviceModelMapper>() + .AddTransient(); + } + + private static IServiceCollection ConfigureServices(this IServiceCollection services) + { + return services.AddTransient(); + } + + private static IServiceCollection ConfigureHealthCheck(this IServiceCollection services) + { + _ = services.AddHealthChecks() + .AddCheck("iothubHealth") + .AddCheck("storageAccountHealth") + .AddCheck("tableStorageHealth") + .AddCheck("dpsHealth") + .AddCheck("loraManagementFacadeHealth"); + + return services; + } + + private static IServiceCollection ConfigureImageBlobStorage(this IServiceCollection services, ConfigHandler configuration) + { + return services.AddTransient(_ => new BlobServiceClient(configuration.StorageAccountConnectionString)) + .Configure((opts) => + { + var serviceClient = new BlobServiceClient(configuration.StorageAccountConnectionString); + var container = serviceClient.GetBlobContainerClient(opts.ImageContainerName); + + _ = container.SetAccessPolicy(PublicAccessType.Blob); + _ = container.CreateIfNotExists(); + + opts.BaseUri = container.Uri; + }); + } + + private static IServiceCollection ConfigureMetricsJobs(this IServiceCollection services, ConfigHandler configuration) + { + return services.AddQuartz(q => + { + q.AddMetricsService(configuration); + q.AddMetricsService(configuration); + q.AddMetricsService(configuration); + }); + } + + private static IServiceCollection ConfigureSyncJobs(this IServiceCollection services, ConfigHandler configuration) + { + return services.AddQuartz(q => + { + _ = q.AddJob(j => j.WithIdentity(nameof(SyncDevicesJob))) + .AddTrigger(t => t + .WithIdentity($"{nameof(SyncDevicesJob)}") + .ForJob(nameof(SyncDevicesJob)) + .WithSimpleSchedule(s => s + .WithIntervalInMinutes(configuration.SyncDatabaseJobRefreshIntervalInMinutes) + .RepeatForever())); + + _ = q.AddJob(j => j.WithIdentity(nameof(SyncConcentratorsJob))) + .AddTrigger(t => t + .WithIdentity($"{nameof(SyncConcentratorsJob)}") + .ForJob(nameof(SyncConcentratorsJob)) + .WithSimpleSchedule(s => s + .WithIntervalInMinutes(configuration.SyncDatabaseJobRefreshIntervalInMinutes) + .RepeatForever())); + + _ = q.AddJob(j => j.WithIdentity(nameof(SyncEdgeDeviceJob))) + .AddTrigger(t => t + .WithIdentity($"{nameof(SyncEdgeDeviceJob)}") + .ForJob(nameof(SyncEdgeDeviceJob)) + .WithSimpleSchedule(s => s + .WithIntervalInMinutes(configuration.SyncDatabaseJobRefreshIntervalInMinutes) + .RepeatForever())); + + _ = q.AddJob(j => j.WithIdentity(nameof(SyncGatewayIDJob))) + .AddTrigger(t => t + .WithIdentity($"{nameof(SyncGatewayIDJob)}") + .ForJob(nameof(SyncGatewayIDJob)) + .WithSimpleSchedule(s => s + .WithIntervalInMinutes(configuration.SyncDatabaseJobRefreshIntervalInMinutes) + .RepeatForever())); + + if (configuration.IsLoRaEnabled) + { + _ = q.AddJob(j => j.WithIdentity(nameof(SyncLoRaDeviceTelemetryJob))) + .AddTrigger(t => t + .WithIdentity($"{nameof(SyncLoRaDeviceTelemetryJob)}") + .ForJob(nameof(SyncLoRaDeviceTelemetryJob)) + .StartAt(DateTimeOffset.Now.AddMinutes(1))); + } + }); + } + } +} diff --git a/src/AzureIoTHub.Portal.Infrastructure/Startup/IServiceCollectionExtension.cs b/src/AzureIoTHub.Portal.Infrastructure/Startup/IServiceCollectionExtension.cs index 57c2cf988..10e7464da 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Startup/IServiceCollectionExtension.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Startup/IServiceCollectionExtension.cs @@ -3,103 +3,30 @@ namespace AzureIoTHub.Portal.Infrastructure.Startup { - using System.Net; - using Azure.Storage.Blobs; - using Azure.Storage.Blobs.Models; - using AzureIoTHub.Portal.Application.Managers; - using AzureIoTHub.Portal.Application.Mappers; - using AzureIoTHub.Portal.Application.Providers; - using AzureIoTHub.Portal.Application.Services; - using AzureIoTHub.Portal.Application.Wrappers; using AzureIoTHub.Portal.Domain; - using AzureIoTHub.Portal.Domain.Options; - using AzureIoTHub.Portal.Domain.Repositories; using AzureIoTHub.Portal.Domain.Shared.Constants; - using AzureIoTHub.Portal.Infrastructure.Extensions; using AzureIoTHub.Portal.Infrastructure.Helpers; - using AzureIoTHub.Portal.Infrastructure.Jobs; - using AzureIoTHub.Portal.Infrastructure.Managers; - using AzureIoTHub.Portal.Infrastructure.Mappers; - using AzureIoTHub.Portal.Infrastructure.Providers; - using AzureIoTHub.Portal.Infrastructure.Repositories; - using AzureIoTHub.Portal.Infrastructure.Services; using AzureIoTHub.Portal.Infrastructure.ServicesHealthCheck; - using AzureIoTHub.Portal.Infrastructure.Wrappers; - using AzureIoTHub.Portal.Models.v10; - using AzureIoTHub.Portal.Models.v10.LoRaWAN; using EntityFramework.Exceptions.PostgreSQL; - using Microsoft.Azure.Devices; - using Microsoft.Azure.Devices.Provisioning.Service; using Microsoft.EntityFrameworkCore; - using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.Options; - using Polly; - using Polly.Extensions.Http; using Quartz; public static class IServiceCollectionExtension { public static IServiceCollection AddInfrastructureLayer(this IServiceCollection services, ConfigHandler configuration) { - return services.ConfigureDatabase(configuration) - .ConfigureRepositories() - .ConfigureImageBlobStorage(configuration) - .AddLoRaWanSupport(configuration) - .ConfigureDeviceRegstryDependencies(configuration) - .ConfigureServices() - .ConfigureMappers() - .ConfigureHealthCheck() - .ConfigureMetricsJobs(configuration) - .ConfigureSyncJobs(configuration); - } - - private static IServiceCollection AddLoRaWanSupport(this IServiceCollection services, ConfigHandler configuration) - { - _ = services.Configure(opts => - { - opts.Enabled = configuration.IsLoRaEnabled; - opts.KeyManagementApiVersion = configuration.LoRaKeyManagementApiVersion; - opts.KeyManagementCode = configuration.LoRaKeyManagementCode; - opts.KeyManagementUrl = configuration.LoRaKeyManagementUrl; - }); - - if (!configuration.IsLoRaEnabled) - { - return services; - } - - var transientHttpErrorPolicy = HttpPolicyExtensions - .HandleTransientHttpError() - .OrResult(c => c.StatusCode == HttpStatusCode.NotFound) - .WaitAndRetryAsync(3, _ => TimeSpan.FromMilliseconds(100)); - - _ = services.AddHttpClient("RestClient") - .AddPolicyHandler(transientHttpErrorPolicy); + //Common configuration + services = services.ConfigureDatabase(configuration) + .ConfigureHealthCheck(); - _ = services.AddHttpClient((sp, client) => + //CloudProvider-dependant configurations + return configuration.CloudProvider switch { - var opts = sp.GetService>()?.Value; - - client.BaseAddress = new Uri(opts?.KeyManagementUrl!); - client.DefaultRequestHeaders.Add("x-functions-key", opts?.KeyManagementCode); - client.DefaultRequestHeaders.Add("api-version", opts?.KeyManagementApiVersion ?? "2022-03-04"); - }) - .AddPolicyHandler(transientHttpErrorPolicy); - - return services; - } - - private static IServiceCollection ConfigureDeviceRegstryDependencies(this IServiceCollection services, ConfigHandler configuration) - { - _ = services.AddTransient(); - _ = services.AddTransient(); - - _ = services.AddScoped(_ => RegistryManager.CreateFromConnectionString(configuration.IoTHubConnectionString)); - _ = services.AddScoped(_ => ServiceClient.CreateFromConnectionString(configuration.IoTHubConnectionString)); - _ = services.AddScoped(_ => ProvisioningServiceClient.CreateFromConnectionString(configuration.DPSConnectionString)); - - return services; + CloudProviders.Azure => services.AddAzureInfrastructureLayer(configuration), + CloudProviders.AWS => services.AddAWSInfrastructureLayer(configuration), + _ => services + }; } private static IServiceCollection ConfigureDatabase(this IServiceCollection services, ConfigHandler configuration) @@ -147,125 +74,13 @@ private static IServiceCollection ConfigureDatabase(this IServiceCollection serv return services; } - private static IServiceCollection ConfigureRepositories(this IServiceCollection services) - { - return services.AddScoped() - .AddScoped() - .AddScoped() - .AddScoped() - .AddScoped() - .AddScoped() - .AddScoped() - .AddScoped() - .AddScoped() - .AddScoped() - .AddScoped() - .AddScoped() - .AddScoped(); - } - - private static IServiceCollection ConfigureMappers(this IServiceCollection services) - { - _ = services.AddTransient(); - _ = services.AddTransient(); - _ = services.AddTransient(); - - return services.AddTransient, DeviceTwinMapper>() - .AddTransient, LoRaDeviceTwinMapper>() - .AddTransient, DeviceModelMapper>() - .AddTransient, LoRaDeviceModelMapper>() - .AddTransient(); - } - - private static IServiceCollection ConfigureServices(this IServiceCollection services) - { - return services.AddTransient(); - } - private static IServiceCollection ConfigureHealthCheck(this IServiceCollection services) { _ = services.AddHealthChecks() .AddDbContextCheck() - .AddCheck("iothubHealth") - .AddCheck("storageAccountHealth") - .AddCheck("tableStorageHealth") - .AddCheck("dpsHealth") - .AddCheck("loraManagementFacadeHealth") .AddCheck("databaseHealthCheck"); return services; } - - private static IServiceCollection ConfigureImageBlobStorage(this IServiceCollection services, ConfigHandler configuration) - { - return services.AddTransient(_ => new BlobServiceClient(configuration.StorageAccountConnectionString)) - .Configure((opts) => - { - var serviceClient = new BlobServiceClient(configuration.StorageAccountConnectionString); - var container = serviceClient.GetBlobContainerClient(opts.ImageContainerName); - - _ = container.SetAccessPolicy(PublicAccessType.Blob); - _ = container.CreateIfNotExists(); - - opts.BaseUri = container.Uri; - }); - } - - private static IServiceCollection ConfigureMetricsJobs(this IServiceCollection services, ConfigHandler configuration) - { - return services.AddQuartz(q => - { - q.AddMetricsService(configuration); - q.AddMetricsService(configuration); - q.AddMetricsService(configuration); - }); - } - - private static IServiceCollection ConfigureSyncJobs(this IServiceCollection services, ConfigHandler configuration) - { - return services.AddQuartz(q => - { - _ = q.AddJob(j => j.WithIdentity(nameof(SyncDevicesJob))) - .AddTrigger(t => t - .WithIdentity($"{nameof(SyncDevicesJob)}") - .ForJob(nameof(SyncDevicesJob)) - .WithSimpleSchedule(s => s - .WithIntervalInMinutes(configuration.SyncDatabaseJobRefreshIntervalInMinutes) - .RepeatForever())); - - _ = q.AddJob(j => j.WithIdentity(nameof(SyncConcentratorsJob))) - .AddTrigger(t => t - .WithIdentity($"{nameof(SyncConcentratorsJob)}") - .ForJob(nameof(SyncConcentratorsJob)) - .WithSimpleSchedule(s => s - .WithIntervalInMinutes(configuration.SyncDatabaseJobRefreshIntervalInMinutes) - .RepeatForever())); - - _ = q.AddJob(j => j.WithIdentity(nameof(SyncEdgeDeviceJob))) - .AddTrigger(t => t - .WithIdentity($"{nameof(SyncEdgeDeviceJob)}") - .ForJob(nameof(SyncEdgeDeviceJob)) - .WithSimpleSchedule(s => s - .WithIntervalInMinutes(configuration.SyncDatabaseJobRefreshIntervalInMinutes) - .RepeatForever())); - - _ = q.AddJob(j => j.WithIdentity(nameof(SyncGatewayIDJob))) - .AddTrigger(t => t - .WithIdentity($"{nameof(SyncGatewayIDJob)}") - .ForJob(nameof(SyncGatewayIDJob)) - .WithSimpleSchedule(s => s - .WithIntervalInMinutes(configuration.SyncDatabaseJobRefreshIntervalInMinutes) - .RepeatForever())); - - if (configuration.IsLoRaEnabled) - { - _ = q.AddJob(j => j.WithIdentity(nameof(SyncLoRaDeviceTelemetryJob))) - .AddTrigger(t => t - .WithIdentity($"{nameof(SyncLoRaDeviceTelemetryJob)}") - .ForJob(nameof(SyncLoRaDeviceTelemetryJob)) - .StartAt(DateTimeOffset.Now.AddMinutes(1))); - } - }); - } } } diff --git a/src/AzureIoTHub.Portal.Server/AzureIoTHub.Portal.Server.csproj b/src/AzureIoTHub.Portal.Server/AzureIoTHub.Portal.Server.csproj index 754049472..c9ce70a5e 100644 --- a/src/AzureIoTHub.Portal.Server/AzureIoTHub.Portal.Server.csproj +++ b/src/AzureIoTHub.Portal.Server/AzureIoTHub.Portal.Server.csproj @@ -12,7 +12,7 @@ - + @@ -35,8 +35,6 @@ - - diff --git a/src/AzureIoTHub.Portal.Server/Startup.cs b/src/AzureIoTHub.Portal.Server/Startup.cs index ce066c009..9df00e358 100644 --- a/src/AzureIoTHub.Portal.Server/Startup.cs +++ b/src/AzureIoTHub.Portal.Server/Startup.cs @@ -6,9 +6,6 @@ namespace AzureIoTHub.Portal.Server using System; using System.IO; using System.Threading.Tasks; - using Amazon; - using Amazon.IoT; - using Amazon.IotData; using AzureIoTHub.Portal.Application.Managers; using AzureIoTHub.Portal.Application.Services; using AzureIoTHub.Portal.Application.Startup; @@ -77,44 +74,24 @@ public void ConfigureServices(IServiceCollection services) AddAuthenticationAndAuthorization(services, configuration); - _ = services.AddSingleton(new PortalMetric()); - _ = services.AddSingleton(new LoRaGatewayIDList()); - - if (configuration.CloudProvider.Equals(CloudProviders.AWS, StringComparison.Ordinal)) + //CloudProvider-dependant configurations + switch (configuration.CloudProvider) { - _ = services.AddSingleton(() => new AmazonIoTClient(configuration.AWSAccess, configuration.AWSAccessSecret, RegionEndpoint.GetBySystemName(configuration.AWSRegion))); - _ = services.AddSingleton(async sp => - { - var endpoint = await sp.GetService().DescribeEndpointAsync(new Amazon.IoT.Model.DescribeEndpointRequest - { - EndpointType = "iot:Data-ATS" - }); - - return new AmazonIotDataClient(configuration.AWSAccess, configuration.AWSAccessSecret, new AmazonIotDataConfig - { - ServiceURL = $"https://{endpoint.EndpointAddress}" - }); - }); + case CloudProviders.Azure: + ConfigureServicesAzure(services); + break; + case CloudProviders.AWS: + break; + // Code line not reachable + default: + break; } - _ = services.AddRazorPages(); - - _ = services.AddTransient(); - - _ = services.AddTransient(); - _ = services.AddTransient(); - _ = services.AddTransient(); - _ = services.AddTransient(); - _ = services.AddTransient(); - _ = services.AddTransient(); - _ = services.AddTransient(); - _ = services.AddTransient(); - _ = services.AddTransient(); - _ = services.AddTransient(); - _ = services.AddTransient(typeof(IDeviceModelService<,>), typeof(DeviceModelService<,>)); - _ = services.AddTransient, DeviceService>(); - _ = services.AddTransient, LoRaWanDeviceService>(); + //Common configurations + _ = services.AddSingleton(new PortalMetric()); + _ = services.AddSingleton(new LoRaGatewayIDList()); + _ = services.AddRazorPages(); _ = services.AddMudServices(); ConfigureIdeasFeature(services, configuration); @@ -325,6 +302,24 @@ Specify the authorization token got from your IDP as a header. _ = services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true); } + private static void ConfigureServicesAzure(IServiceCollection services) + { + _ = services.AddTransient(); + _ = services.AddTransient(); + _ = services.AddTransient(); + _ = services.AddTransient(); + _ = services.AddTransient(); + _ = services.AddTransient(); + _ = services.AddTransient(); + _ = services.AddTransient(); + _ = services.AddTransient(); + _ = services.AddTransient(); + _ = services.AddTransient(); + _ = services.AddTransient(typeof(IDeviceModelService<,>), typeof(DeviceModelService<,>)); + _ = services.AddTransient, DeviceService>(); + _ = services.AddTransient, LoRaWanDeviceService>(); + } + private static void ConfigureIdeasFeature(IServiceCollection services, ConfigHandler configuration) { _ = services.AddTransient(); @@ -445,12 +440,28 @@ public async void Configure(IApplicationBuilder app, IWebHostEnvironment env) }); }); + + //CloudProvider-dependant configurations + switch (configuration.CloudProvider) + { + case CloudProviders.Azure: + await ConfigureAzureAsync(app); + break; + case CloudProviders.AWS: + break; + default: + break; + } + + await EnsureDatabaseCreatedAndUpToDate(app)!; + } + + private static async Task ConfigureAzureAsync(IApplicationBuilder app) + { var deviceModelImageManager = app.ApplicationServices.GetService(); await deviceModelImageManager?.InitializeDefaultImageBlob()!; await deviceModelImageManager?.SyncImagesCacheControl()!; - - await EnsureDatabaseCreatedAndUpToDate(app)!; } private static void UseApiExceptionMiddleware(IApplicationBuilder app)