diff --git a/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/CommunicationControlService.cs b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/CommunicationControlService.cs index 2e1a753..dea50b7 100644 --- a/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/CommunicationControlService.cs +++ b/src/CommunicationControl/DevOpsProject.CommunicationControl.Logic/Services/CommunicationControlService.cs @@ -141,8 +141,8 @@ namespace DevOpsProject.CommunicationControl.Logic.Services Timestamp = DateTime.Now }; - var result = await _hiveHttpClient.SendHiveControlCommandAsync(_communicationControlConfiguration.CurrentValue.RequestScheme, - hive.HiveIP, hive.HivePort, _communicationControlConfiguration.CurrentValue.HiveMindPath, command); + var result = await _hiveHttpClient.SendHiveControlCommandAsync(hive.HiveSchema, hive.HiveIP, hive.HivePort, + _communicationControlConfiguration.CurrentValue.HiveMindPath, command); isSuccessfullySent = true; return result; } diff --git a/src/CommunicationControl/DevOpsProject.HiveMind.API/DI/ApiVersioningConfiguration.cs b/src/CommunicationControl/DevOpsProject.HiveMind.API/DI/ApiVersioningConfiguration.cs new file mode 100644 index 0000000..8ad0c38 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.HiveMind.API/DI/ApiVersioningConfiguration.cs @@ -0,0 +1,29 @@ +using DevOpsProject.HiveMind.Logic.Services.Interfaces; +using DevOpsProject.HiveMind.Logic.Services; +using Asp.Versioning; + +namespace DevOpsProject.HiveMind.API.DI +{ + public static class ApiVersioningConfiguration + { + public static IServiceCollection AddApiVersioningConfiguration(this IServiceCollection serviceCollection) + { + serviceCollection.AddApiVersioning(options => + { + options.DefaultApiVersion = new ApiVersion(1, 0); + options.AssumeDefaultVersionWhenUnspecified = true; + options.ReportApiVersions = true; + options.ApiVersionReader = ApiVersionReader.Combine( + new UrlSegmentApiVersionReader(), + new HeaderApiVersionReader("X-Api-Version") + ); + }).AddApiExplorer(options => + { + options.GroupNameFormat = "'v'VVV"; + options.SubstituteApiVersionInUrl = true; + }); + + return serviceCollection; + } + } +} diff --git a/src/CommunicationControl/DevOpsProject.HiveMind.API/DI/CorsConfiguration.cs b/src/CommunicationControl/DevOpsProject.HiveMind.API/DI/CorsConfiguration.cs new file mode 100644 index 0000000..6544b85 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.HiveMind.API/DI/CorsConfiguration.cs @@ -0,0 +1,21 @@ +namespace DevOpsProject.HiveMind.API.DI +{ + public static class CorsConfiguration + { + public static IServiceCollection AddCorsConfiguration(this IServiceCollection serviceCollection, string corsPolicyName) + { + serviceCollection.AddCors(options => + { + options.AddPolicy(name: corsPolicyName, + policy => + { + policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins + .AllowAnyMethod() + .AllowAnyHeader(); + }); + }); + + return serviceCollection; + } + } +} diff --git a/src/CommunicationControl/DevOpsProject.HiveMind.API/DI/HttpClientsConfiguration.cs b/src/CommunicationControl/DevOpsProject.HiveMind.API/DI/HttpClientsConfiguration.cs new file mode 100644 index 0000000..c1ffa3e --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.HiveMind.API/DI/HttpClientsConfiguration.cs @@ -0,0 +1,21 @@ +using DevOpsProject.Shared.Clients; +using Polly.Extensions.Http; +using Polly; + +namespace DevOpsProject.HiveMind.API.DI +{ + public static class HttpClientsConfiguration + { + public static IServiceCollection AddHttpClientsConfiguration(this IServiceCollection serviceCollection) + { + var communicationControlTelemetryPolicy = HttpPolicyExtensions + .HandleTransientHttpError() + .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); + serviceCollection.AddHttpClient() + .AddPolicyHandler(communicationControlTelemetryPolicy); + serviceCollection.AddHttpClient("HiveConnectClient"); + + return serviceCollection; + } + } +} diff --git a/src/CommunicationControl/DevOpsProject.HiveMind.API/DI/OptionsConfiguration.cs b/src/CommunicationControl/DevOpsProject.HiveMind.API/DI/OptionsConfiguration.cs new file mode 100644 index 0000000..701b349 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject.HiveMind.API/DI/OptionsConfiguration.cs @@ -0,0 +1,14 @@ +using DevOpsProject.Shared.Configuration; + +namespace DevOpsProject.HiveMind.API.DI +{ + public static class OptionsConfiguration + { + public static IServiceCollection AddOptionsConfiguration(this IServiceCollection serviceCollection, IConfiguration configuration) + { + serviceCollection.Configure(configuration.GetSection("CommunicationConfiguration")); + + return serviceCollection; + } + } +} diff --git a/src/CommunicationControl/DevOpsProject.HiveMind.API/Program.cs b/src/CommunicationControl/DevOpsProject.HiveMind.API/Program.cs index 65003c5..013786e 100644 --- a/src/CommunicationControl/DevOpsProject.HiveMind.API/Program.cs +++ b/src/CommunicationControl/DevOpsProject.HiveMind.API/Program.cs @@ -3,13 +3,10 @@ using Asp.Versioning.Builder; using DevOpsProject.HiveMind.API.DI; using DevOpsProject.HiveMind.API.Middleware; using DevOpsProject.HiveMind.Logic.Services.Interfaces; -using DevOpsProject.Shared.Clients; using DevOpsProject.Shared.Configuration; using DevOpsProject.Shared.Models; using Microsoft.Extensions.Options; using Microsoft.OpenApi.Models; -using Polly; -using Polly.Extensions.Http; using Serilog; var builder = WebApplication.CreateBuilder(args); @@ -19,52 +16,23 @@ builder.Host.UseSerilog((context, services, loggerConfig) => .ReadFrom.Services(services) .Enrich.FromLogContext()); -builder.Services.AddApiVersioning(options => -{ - options.DefaultApiVersion = new ApiVersion(1, 0); - options.AssumeDefaultVersionWhenUnspecified = true; - options.ReportApiVersions = true; - options.ApiVersionReader = ApiVersionReader.Combine( - new UrlSegmentApiVersionReader(), - new HeaderApiVersionReader("X-Api-Version") - ); -}).AddApiExplorer(options => -{ - options.GroupNameFormat = "'v'VVV"; - options.SubstituteApiVersionInUrl = true; -}); +builder.Services.AddApiVersioningConfiguration(); -// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddAuthorization(); builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "HiveMind - V1", Version = "v1.0" }); }); + +builder.Services.AddOptionsConfiguration(builder.Configuration); + builder.Services.AddHiveMindLogic(); -builder.Services.Configure(builder.Configuration.GetSection("CommunicationConfiguration")); - -var communicationControlTelemetryPolicy = HttpPolicyExtensions - .HandleTransientHttpError() - .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); -builder.Services.AddHttpClient() - .AddPolicyHandler(communicationControlTelemetryPolicy); - -// register NAMED client for connect request -builder.Services.AddHttpClient("HiveConnectClient"); +builder.Services.AddHttpClientsConfiguration(); string corsPolicyName = "HiveMindCorsPolicy"; -builder.Services.AddCors(options => -{ - options.AddPolicy(name: corsPolicyName, - policy => - { - policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins - .AllowAnyMethod() - .AllowAnyHeader(); - }); -}); +builder.Services.AddCorsConfiguration(corsPolicyName); builder.Services.AddExceptionHandler(); builder.Services.AddProblemDetails(); @@ -82,7 +50,7 @@ using (var scope = app.Services.CreateScope()) catch (Exception ex) { logger.LogError($"Error occured while connecting Hive to Communication Control. \nException text: {ex.Message}"); - System.Diagnostics.Process.GetCurrentProcess().Kill(); + Environment.Exit(1); } } @@ -105,7 +73,6 @@ ApiVersionSet apiVersionSet = app.NewApiVersionSet() .HasApiVersion(new ApiVersion(1)) .ReportApiVersions() .Build(); - RouteGroupBuilder groupBuilder = app.MapGroup("api/v{apiVersion:apiVersion}").WithApiVersionSet(apiVersionSet); groupBuilder.MapGet("ping", (IOptionsSnapshot config) => diff --git a/src/CommunicationControl/DevOpsProject.HiveMind.API/appsettings.json b/src/CommunicationControl/DevOpsProject.HiveMind.API/appsettings.json index f12b9a4..376b264 100644 --- a/src/CommunicationControl/DevOpsProject.HiveMind.API/appsettings.json +++ b/src/CommunicationControl/DevOpsProject.HiveMind.API/appsettings.json @@ -38,7 +38,7 @@ "rollingInterval": "Day", "rollOnFileSizeLimit": true, "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact", - "restrictedToMinimumLevel": "Warning" + "restrictedToMinimumLevel": "Information" } } ], diff --git a/src/CommunicationControl/DevOpsProject.HiveMind.Logic/Services/HiveMindService.cs b/src/CommunicationControl/DevOpsProject.HiveMind.Logic/Services/HiveMindService.cs index 4d3204f..6bf94d2 100644 --- a/src/CommunicationControl/DevOpsProject.HiveMind.Logic/Services/HiveMindService.cs +++ b/src/CommunicationControl/DevOpsProject.HiveMind.Logic/Services/HiveMindService.cs @@ -31,6 +31,7 @@ namespace DevOpsProject.HiveMind.Logic.Services { var request = new HiveConnectRequest { + HiveSchema = _communicationConfigurationOptions.RequestSchema, HiveIP = _communicationConfigurationOptions.HiveIP, HivePort = _communicationConfigurationOptions.HivePort, HiveID = _communicationConfigurationOptions.HiveID @@ -68,7 +69,6 @@ namespace DevOpsProject.HiveMind.Logic.Services HiveInMemoryState.OperationalArea = hiveConnectResponse.OperationalArea; HiveInMemoryState.CurrentLocation = _communicationConfigurationOptions.InitialLocation; - // HERE - we are starting to send telemetry StartTelemetry(); } else @@ -80,7 +80,7 @@ namespace DevOpsProject.HiveMind.Logic.Services else { _logger.LogError($"Failed to connect hive, terminating process"); - System.Diagnostics.Process.GetCurrentProcess().Kill(); + Environment.Exit(1); } } diff --git a/src/CommunicationControl/DevOpsProject.Shared/Configuration/ComControlCommunicationConfiguration.cs b/src/CommunicationControl/DevOpsProject.Shared/Configuration/ComControlCommunicationConfiguration.cs index 731d58d..e70b84b 100644 --- a/src/CommunicationControl/DevOpsProject.Shared/Configuration/ComControlCommunicationConfiguration.cs +++ b/src/CommunicationControl/DevOpsProject.Shared/Configuration/ComControlCommunicationConfiguration.cs @@ -2,7 +2,6 @@ { public class ComControlCommunicationConfiguration { - public string RequestScheme { get; set; } public string HiveMindPath { get; set; } } } diff --git a/src/CommunicationControl/DevOpsProject.Shared/Models/HiveConnectRequest.cs b/src/CommunicationControl/DevOpsProject.Shared/Models/HiveConnectRequest.cs index 86a2570..4776bc7 100644 --- a/src/CommunicationControl/DevOpsProject.Shared/Models/HiveConnectRequest.cs +++ b/src/CommunicationControl/DevOpsProject.Shared/Models/HiveConnectRequest.cs @@ -1,13 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace DevOpsProject.Shared.Models +namespace DevOpsProject.Shared.Models { public class HiveConnectRequest { + public string HiveSchema { get; set; } public string HiveIP { get; set; } public int HivePort { get; set; } public string HiveID { get; set; } diff --git a/src/CommunicationControl/DevOpsProject.Shared/Models/HiveModel.cs b/src/CommunicationControl/DevOpsProject.Shared/Models/HiveModel.cs index 9a77869..174dca2 100644 --- a/src/CommunicationControl/DevOpsProject.Shared/Models/HiveModel.cs +++ b/src/CommunicationControl/DevOpsProject.Shared/Models/HiveModel.cs @@ -5,6 +5,7 @@ public string HiveID { get; set; } public string HiveIP { get; set; } public int HivePort { get; set; } + public string HiveSchema { get; set; } public HiveTelemetryModel Telemetry { get; set; } } } diff --git a/src/CommunicationControl/DevOpsProject/Controllers/HiveController.cs b/src/CommunicationControl/DevOpsProject/Controllers/HiveController.cs index 4e4cd00..c346207 100644 --- a/src/CommunicationControl/DevOpsProject/Controllers/HiveController.cs +++ b/src/CommunicationControl/DevOpsProject/Controllers/HiveController.cs @@ -25,6 +25,7 @@ namespace DevOpsProject.CommunicationControl.API.Controllers HiveID = request.HiveID, HiveIP = request.HiveIP, HivePort = request.HivePort, + HiveSchema = request.HiveSchema }; var hiveOperationalArea = await _communicationControlService.ConnectHive(hiveModel); diff --git a/src/CommunicationControl/DevOpsProject/DI/ApiVersioningConfiguration.cs b/src/CommunicationControl/DevOpsProject/DI/ApiVersioningConfiguration.cs new file mode 100644 index 0000000..8886291 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/DI/ApiVersioningConfiguration.cs @@ -0,0 +1,27 @@ +using Asp.Versioning; + +namespace DevOpsProject.CommunicationControl.API.DI +{ + public static class ApiVersioningConfiguration + { + public static IServiceCollection AddApiVersioningConfiguration(this IServiceCollection serviceCollection) + { + serviceCollection.AddApiVersioning(options => + { + options.DefaultApiVersion = new ApiVersion(1, 0); + options.AssumeDefaultVersionWhenUnspecified = true; + options.ReportApiVersions = true; + options.ApiVersionReader = ApiVersionReader.Combine( + new UrlSegmentApiVersionReader(), + new HeaderApiVersionReader("X-Api-Version") + ); + }).AddApiExplorer(options => + { + options.GroupNameFormat = "'v'VVV"; + options.SubstituteApiVersionInUrl = true; + }); + + return serviceCollection; + } + } +} diff --git a/src/CommunicationControl/DevOpsProject/DI/CorsConfiguration.cs b/src/CommunicationControl/DevOpsProject/DI/CorsConfiguration.cs new file mode 100644 index 0000000..efb3832 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/DI/CorsConfiguration.cs @@ -0,0 +1,21 @@ +namespace DevOpsProject.CommunicationControl.API.DI +{ + public static class CorsConfiguration + { + public static IServiceCollection AddCorsConfiguration(this IServiceCollection serviceCollection, string corsPolicyName) + { + serviceCollection.AddCors(options => + { + options.AddPolicy(name: corsPolicyName, + policy => + { + policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins + .AllowAnyMethod() + .AllowAnyHeader(); + }); + }); + + return serviceCollection; + } + } +} diff --git a/src/CommunicationControl/DevOpsProject/DI/HttpClientsConfiguration.cs b/src/CommunicationControl/DevOpsProject/DI/HttpClientsConfiguration.cs new file mode 100644 index 0000000..ddced4d --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/DI/HttpClientsConfiguration.cs @@ -0,0 +1,20 @@ +using DevOpsProject.Shared.Clients; +using Polly; +using Polly.Extensions.Http; + +namespace DevOpsProject.CommunicationControl.API.DI +{ + public static class HttpClientsConfiguration + { + public static IServiceCollection AddHttpClientsConfiguration(this IServiceCollection serviceCollection) + { + var hiveRetryPolicy = HttpPolicyExtensions + .HandleTransientHttpError() + .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); + serviceCollection.AddHttpClient() + .AddPolicyHandler(hiveRetryPolicy); + + return serviceCollection; + } + } +} diff --git a/src/CommunicationControl/DevOpsProject/DI/JsonControllerOptionsConfiguration.cs b/src/CommunicationControl/DevOpsProject/DI/JsonControllerOptionsConfiguration.cs new file mode 100644 index 0000000..c797ad6 --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/DI/JsonControllerOptionsConfiguration.cs @@ -0,0 +1,15 @@ +namespace DevOpsProject.CommunicationControl.API.DI +{ + public static class JsonControllerOptionsConfiguration + { + public static IServiceCollection AddJsonControllerOptionsConfiguration(this IServiceCollection serviceCollection) + { + serviceCollection.AddControllers().AddJsonOptions(options => + { + options.JsonSerializerOptions.PropertyNamingPolicy = null; + }); + + return serviceCollection; + } + } +} diff --git a/src/CommunicationControl/DevOpsProject/DI/OptionsConfiguration.cs b/src/CommunicationControl/DevOpsProject/DI/OptionsConfiguration.cs new file mode 100644 index 0000000..dcf856b --- /dev/null +++ b/src/CommunicationControl/DevOpsProject/DI/OptionsConfiguration.cs @@ -0,0 +1,16 @@ +using DevOpsProject.Shared.Configuration; +using DevOpsProject.Shared.Models; + +namespace DevOpsProject.CommunicationControl.API.DI +{ + public static class OptionsConfiguration + { + public static IServiceCollection AddOptionsConfiguration(this IServiceCollection serviceCollection, IConfiguration configuration) + { + serviceCollection.Configure(configuration.GetSection("OperationalArea")); + serviceCollection.Configure(configuration.GetSection("CommunicationConfiguration")); + + return serviceCollection; + } + } +} diff --git a/src/CommunicationControl/DevOpsProject/Program.cs b/src/CommunicationControl/DevOpsProject/Program.cs index 3b276c9..46db467 100644 --- a/src/CommunicationControl/DevOpsProject/Program.cs +++ b/src/CommunicationControl/DevOpsProject/Program.cs @@ -1,13 +1,6 @@ -using Asp.Versioning; using DevOpsProject.CommunicationControl.API.DI; using DevOpsProject.CommunicationControl.API.Middleware; -using DevOpsProject.Shared.Clients; -using DevOpsProject.Shared.Configuration; -using DevOpsProject.Shared.Models; -using Microsoft.Extensions.Options; using Microsoft.OpenApi.Models; -using Polly; -using Polly.Extensions.Http; using Serilog; internal class Program @@ -21,26 +14,11 @@ internal class Program .ReadFrom.Services(services) .Enrich.FromLogContext()); - builder.Services.AddApiVersioning(options => - { - options.DefaultApiVersion = new ApiVersion(1, 0); - options.AssumeDefaultVersionWhenUnspecified = true; - options.ReportApiVersions = true; - options.ApiVersionReader = ApiVersionReader.Combine( - new UrlSegmentApiVersionReader(), - new HeaderApiVersionReader("X-Api-Version") - ); - }).AddApiExplorer(options => - { - options.GroupNameFormat = "'v'VVV"; - options.SubstituteApiVersionInUrl = true; - }); + builder.Services.AddApiVersioningConfiguration(); // TODO: consider this approach - builder.Services.AddControllers().AddJsonOptions(options => - { - options.JsonSerializerOptions.PropertyNamingPolicy = null; - }); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle + builder.Services.AddJsonControllerOptionsConfiguration(); + builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => { @@ -52,36 +30,12 @@ internal class Program builder.Services.AddRedis(builder.Configuration); builder.Services.AddCommunicationControlLogic(); - builder.Services.Configure(builder.Configuration.GetSection("OperationalArea")); - builder.Services.Configure(builder.Configuration.GetSection("CommunicationConfiguration")); - - var hiveRetryPolicy = HttpPolicyExtensions - .HandleTransientHttpError() - .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); - builder.Services.AddHttpClient() - .AddPolicyHandler(hiveRetryPolicy); + builder.Services.AddOptionsConfiguration(builder.Configuration); + builder.Services.AddHttpClientsConfiguration(); var corsPolicyName = "AllowReactApp"; - var localCorsPolicyName = "AllowLocalHtml"; - builder.Services.AddCors(options => - { - options.AddPolicy(name: corsPolicyName, - policy => - { - policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins - .AllowAnyMethod() - .AllowAnyHeader(); - }); - - options.AddPolicy(name: localCorsPolicyName, - policy => - { - policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins - .AllowAnyMethod() - .AllowAnyHeader(); - }); - }); + builder.Services.AddCorsConfiguration(corsPolicyName); builder.Services.AddExceptionHandler(); builder.Services.AddProblemDetails(); @@ -97,7 +51,6 @@ internal class Program } app.UseCors(corsPolicyName); - //app.UseCors(localCorsPolicyName); app.UseAuthorization(); diff --git a/src/CommunicationControl/DevOpsProject/appsettings.json b/src/CommunicationControl/DevOpsProject/appsettings.json index 16d1344..882ad53 100644 --- a/src/CommunicationControl/DevOpsProject/appsettings.json +++ b/src/CommunicationControl/DevOpsProject/appsettings.json @@ -14,10 +14,8 @@ "InitialSpeed_KM": 5, "TelemetryInterval_MS": 30000, "PingInterval_MS": 15000 - }, "CommunicationConfiguration": { - "RequestScheme": "http", "HiveMindPath": "api/v1" }, "AllowedHosts": "*", @@ -45,7 +43,7 @@ "rollingInterval": "Day", "rollOnFileSizeLimit": true, "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact", - "restrictedToMinimumLevel": "Warning" + "restrictedToMinimumLevel": "Information" } } ],