Skip to content

Commit a04f958

Browse files
Merge branch 'dev' into snyk-upgrade-7170125e99f3edeec68e2d321843a476
2 parents 664b88d + 9d60203 commit a04f958

74 files changed

Lines changed: 1035 additions & 406 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,8 @@ KAFKA_INTER_BROKER_PASSWORD=controller_password
88
AZURITE_CONNECTION_STRING=DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://azurite:10000/devstoreaccount1
99
INTERNAL_BLOB_CONTAINER_NAME=internal
1010
EXTERNAL_BLOB_CONTAINER_NAME=external
11-
ISSUER_URI=https://oauth.nhsnlink.org/realms/NHSNLink
11+
ISSUER_URI=https://oauth.nhsnlink.org/realms/NHSNLink
12+
13+
KafkaConnection__SaslUsername=${KAFKA_SASL_CLIENT_USER}
14+
KafkaConnection__SaslPassword=${KAFKA_SASL_CLIENT_PASSWORD}
15+
Redis__Password=${REDIS_PASS}

DotNet/Account/Account.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>net8.0</TargetFramework>
5-
<Version>0.1.1-dev</Version>
5+
<Version>0.4.1</Version>
66
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
77
<Nullable>enable</Nullable>
88
<ImplicitUsings>enable</ImplicitUsings>

DotNet/Account/Program.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
using System.Text.Json.Serialization;
4444

4545
var builder = WebApplication.CreateBuilder(args);
46+
builder.Configuration.AddStandardEnvironmentConfiguration();
4647

4748
// Additional configuration is required to successfully run gRPC on macOS.
4849
// For instructions on how to configure Kestrel and gRPC clients on macOS, visit https://go.microsoft.com/fwlink/?linkid=2099682

DotNet/Account/appsettings.Docker.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
},
77
"KafkaConnection": {
88
"BootstrapServers": [
9-
"kafka_b:9094"
9+
"kafka_b:9092"
1010
],
1111
"SaslProtocolEnabled": true
1212
},

DotNet/Admin.BFF/Admin.BFF.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>net8.0</TargetFramework>
5-
<Version>0.1.1-dev</Version>
5+
<Version>0.4.1</Version>
66
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
77
<Nullable>enable</Nullable>
88
<ImplicitUsings>enable</ImplicitUsings>
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using LantanaGroup.Link.LinkAdmin.BFF.Application.Models.Health;
2+
using LantanaGroup.Link.LinkAdmin.BFF.Infrastructure.Logging;
3+
using LantanaGroup.Link.Shared.Application.Models.Configs;
4+
using Microsoft.Extensions.Diagnostics.HealthChecks;
5+
using Microsoft.Extensions.Options;
6+
using System.Net.Http.Headers;
7+
8+
namespace LantanaGroup.Link.LinkAdmin.BFF.Application.Clients
9+
{
10+
public class TerminologyService
11+
{
12+
private readonly ILogger<TerminologyService> _logger;
13+
private readonly HttpClient _client;
14+
private readonly IOptions<ServiceRegistry> _serviceRegistry;
15+
16+
public TerminologyService(ILogger<TerminologyService> logger, HttpClient client, IOptions<ServiceRegistry> serviceRegistry)
17+
{
18+
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
19+
_client = client ?? throw new ArgumentNullException(nameof(client));
20+
_serviceRegistry = serviceRegistry ?? throw new ArgumentNullException(nameof(serviceRegistry));
21+
22+
InitHttpClient();
23+
}
24+
25+
public async Task<HttpResponseMessage> ServiceHealthCheck(CancellationToken cancellationToken)
26+
{
27+
// HTTP GET
28+
HttpResponseMessage response = await _client.GetAsync($"health", cancellationToken);
29+
30+
return response;
31+
}
32+
33+
public async Task<LinkServiceHealthReport> LinkServiceHealthCheck(CancellationToken cancellationToken)
34+
{
35+
// HTTP GET
36+
try
37+
{
38+
var response = await _client.GetAsync($"health", cancellationToken);
39+
var healthResult = await response.Content.ReadFromJsonAsync<LinkServiceHealthReport>(cancellationToken: cancellationToken);
40+
41+
if (healthResult is null)
42+
{
43+
_logger.LogWarning("Terminology service health check returned null or invalid response");
44+
return new LinkServiceHealthReport() { Service = "Terminology", Status = HealthStatus.Unhealthy };
45+
}
46+
47+
healthResult.Service = "Terminology";
48+
return healthResult;
49+
}
50+
catch (Exception ex)
51+
{
52+
_logger.LogError(ex, "Terminology service health check failed");
53+
return new LinkServiceHealthReport { Service = "Terminology", Status = HealthStatus.Unhealthy };
54+
}
55+
}
56+
57+
private void InitHttpClient()
58+
{
59+
//check if the service uri is set
60+
if (string.IsNullOrEmpty(_serviceRegistry.Value.TerminologyServiceUrl))
61+
{
62+
_logger.LogGatewayServiceUriException("Terminology", "Terminology service uri is not set");
63+
throw new ArgumentNullException("Terminology Service URL is missing.");
64+
}
65+
66+
_client.BaseAddress = new Uri(_serviceRegistry.Value.TerminologyServiceUrl);
67+
_client.DefaultRequestHeaders.Accept.Clear();
68+
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
69+
}
70+
}
71+
}

DotNet/Admin.BFF/Infrastructure/Extensions/ExternalServices/LinkClientExtension.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public static IServiceCollection AddLinkClients(this IServiceCollection services
1818
services.AddHttpClient<SubmissionService>();
1919
services.AddHttpClient<TenantService>();
2020
services.AddHttpClient<ValidationService>();
21+
services.AddHttpClient<TerminologyService>();
2122

2223
return services;
2324
}

DotNet/Admin.BFF/Infrastructure/Extensions/Security/CorsServiceExtension.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,20 @@ public static IServiceCollection AddCorsService(this IServiceCollection services
4949

5050
options.AddPolicy(CorsConfig.DefaultCorsPolicyName, cpb.Build());
5151

52-
//add health check endpoint to cors policy
52+
//add health check and api info endpoint to cors policy
5353
options.AddPolicy("HealthCheckPolicy", policy =>
5454
{
5555
policy.AllowAnyHeader();
5656
policy.AllowAnyMethod();
5757
policy.AllowAnyOrigin();
5858
});
59+
60+
options.AddPolicy("ApiInfoPolicy", policy =>
61+
{
62+
policy.AllowAnyHeader();
63+
policy.AllowAnyMethod();
64+
policy.AllowAnyOrigin();
65+
});
5966
});
6067

6168
return services;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using LantanaGroup.Link.LinkAdmin.BFF.Application.Clients;
2+
using LantanaGroup.Link.LinkAdmin.BFF.Infrastructure.Logging;
3+
using Microsoft.Extensions.Diagnostics.HealthChecks;
4+
5+
namespace LantanaGroup.Link.LinkAdmin.BFF.Infrastructure.Health
6+
{
7+
public class TerminologyServiceHealthCheck : IHealthCheck
8+
{
9+
private readonly ILogger<TerminologyServiceHealthCheck> _logger;
10+
private readonly TerminologyService _terminologyService;
11+
12+
public TerminologyServiceHealthCheck(ILogger<TerminologyServiceHealthCheck> logger, TerminologyService terminologyService)
13+
{
14+
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
15+
_terminologyService = terminologyService ?? throw new ArgumentNullException(nameof(terminologyService));
16+
}
17+
18+
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
19+
{
20+
try
21+
{
22+
// make a request to the terminology service health check
23+
var response = await _terminologyService.ServiceHealthCheck(cancellationToken);
24+
25+
if (response.IsSuccessStatusCode)
26+
{
27+
return HealthCheckResult.Healthy();
28+
}
29+
else
30+
{
31+
return new HealthCheckResult(HealthStatus.Unhealthy, description: "Terminology service is not healthy");
32+
}
33+
34+
}
35+
catch (HttpRequestException ex)
36+
{
37+
_logger.LogLinkServiceRequestException("Terminology", ex.Message);
38+
return new HealthCheckResult(HealthStatus.Unhealthy, description: "HTTP request error.");
39+
}
40+
catch (Exception ex)
41+
{
42+
_logger.LogLinkServiceRequestException("Terminology", ex.Message);
43+
return new HealthCheckResult(HealthStatus.Unhealthy, description: "Failed to determine health status of the Terminology service.");
44+
}
45+
}
46+
}
47+
}

DotNet/Admin.BFF/Presentation/Endpoints/System/Hanlders/GetSystemHealth.cs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
using LantanaGroup.Link.LinkAdmin.BFF.Application.Clients;
2-
using LantanaGroup.Link.LinkAdmin.BFF.Application.Models;
32
using LantanaGroup.Link.LinkAdmin.BFF.Application.Models.Health;
3+
using Microsoft.Extensions.Diagnostics.HealthChecks;
44

55
namespace LantanaGroup.Link.LinkAdmin.BFF.Presentation.Endpoints.System.Hanlders;
66

77
public static class GetSystemHealth
88
{
99
public static async Task<IResult> Handle(HttpContext context,
10+
HealthCheckService healthCheckService,
1011
AccountService accountService,
1112
AuditService auditService,
1213
CensusService censusService,
@@ -17,7 +18,8 @@ public static async Task<IResult> Handle(HttpContext context,
1718
SubmissionService submissionService,
1819
TenantService tenantService,
1920
MeasureEvalService measureEvalService,
20-
ValidationService validationService)
21+
ValidationService validationService,
22+
TerminologyService terminologyService)
2123
{
2224

2325
var dotNetHealthCheckTasks = new List<Task<LinkServiceHealthReport>>
@@ -30,7 +32,24 @@ public static async Task<IResult> Handle(HttpContext context,
3032
queryDispatchService.LinkServiceHealthCheck(context.RequestAborted),
3133
reportService.LinkServiceHealthCheck(context.RequestAborted),
3234
submissionService.LinkServiceHealthCheck(context.RequestAborted),
33-
tenantService.LinkServiceHealthCheck(context.RequestAborted)
35+
tenantService.LinkServiceHealthCheck(context.RequestAborted),
36+
terminologyService.LinkServiceHealthCheck(context.RequestAborted)
37+
};
38+
39+
// Get Admin BFF health
40+
var bffHealthReport = await healthCheckService.CheckHealthAsync(context.RequestAborted);
41+
var bffLinkReport = new LinkServiceHealthReport
42+
{
43+
Service = "Admin BFF",
44+
Status = bffHealthReport.Status,
45+
TotalDuration = bffHealthReport.TotalDuration,
46+
Entries = bffHealthReport.Entries.ToDictionary(
47+
x => x.Key,
48+
x => new LinkServiceHealthReportEntry
49+
{
50+
Status = x.Value.Status,
51+
Duration = x.Value.Duration
52+
})
3453
};
3554

3655
//if we upgrade to .NET 9, we can use Task.WhenEach
@@ -45,6 +64,7 @@ public static async Task<IResult> Handle(HttpContext context,
4564
validationHealthSummary.CacheConnection = LinkServiceHealthStatus.NotApplicable;
4665

4766
var healthSummary = results.Select(LinkServiceHealthReportExtensions.FromDomain).ToList();
67+
healthSummary.Add(LinkServiceHealthReportExtensions.FromDomain(bffLinkReport));
4868
healthSummary.Add(measureEvalHealthSummary);
4969
healthSummary.Add(validationHealthSummary);
5070

0 commit comments

Comments
 (0)