Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions src/Spd.Utilities.Hosting/S3V2HealthCheck.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Amazon.S3;
using Amazon.S3.Model;
using Microsoft.Extensions.Diagnostics.HealthChecks;

namespace Spd.Utilities.Hosting;
public class S3V2HealthCheck : IHealthCheck
{
private readonly IAmazonS3 _s3Client;
private readonly string _bucketName;

public S3V2HealthCheck(IAmazonS3 s3Client, string bucketName)
{
_s3Client = s3Client;
_bucketName = bucketName;
}

public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
try
{
var request = new ListObjectsV2Request
{
BucketName = _bucketName,
MaxKeys = 1
};

await _s3Client.ListObjectsV2Async(request, cancellationToken);

return HealthCheckResult.Healthy("S3 bucket is reachable.");
}
catch (Exception ex)
{
return HealthCheckResult.Unhealthy("S3 health check failed.", ex);
}
}
}

35 changes: 21 additions & 14 deletions src/Spd.Utilities.Hosting/ServiceExtensionsHealthChecks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,32 @@ public static IServiceCollection AddHealthChecks(this IServiceCollection service
healthCheckBuilder.AddRedis(redisConnection);
}

//after awssdk upgrade to 4.0.6.8, AspNetCore.HealthChecks.Aws.S3 does not upgrade accordingly,
//The AddS3 health check extension internally uses the older ListObjectsRequest API to check connectivity.
//In newer versions of the AWS SDK, ListObjectsRequest.MaxKeys has been deprecated or removed, replaced by ListObjectsV2Request
//When your runtime uses a newer AWSSDK.S3 version, that setter no longer exists, triggering the MissingMethodException.
//We have to Override with a custom health check
// Replacement for AddS3 (uses ListObjectsV2)
var s3url = configuration.GetValue<string?>("storage:MainBucketSettings:url");
if (s3url != null)
var bucket = configuration.GetValue<string?>("storage:MainBucketSettings:bucket");
var accessKey = configuration.GetValue<string?>("storage:MainBucketSettings:accessKey");
var secretKey = configuration.GetValue<string?>("storage:MainBucketSettings:secret");

if (!string.IsNullOrEmpty(s3url) && !string.IsNullOrEmpty(bucket))
{
healthCheckBuilder.AddS3(options =>
services.AddSingleton<S3V2HealthCheck>(sp =>
{
options.S3Config = new AmazonS3Config
{
ServiceURL = s3url,
ForcePathStyle = true,
UseHttp = false,
};

options.BucketName = configuration.GetValue("storage:MainBucketSettings:bucket", string.Empty)!;
options.Credentials = new BasicAWSCredentials(
configuration.GetValue("storage:MainBucketSettings:accessKey", string.Empty),
configuration.GetValue("storage:MainBucketSettings:secret", string.Empty));
var s3Client = new AmazonS3Client(
new BasicAWSCredentials(accessKey, secretKey),
new AmazonS3Config
{
ServiceURL = s3url,
ForcePathStyle = true,
UseHttp = false
});
return new S3V2HealthCheck(s3Client, bucket);
});
}

return services;
}

Expand Down