89 lines
2.8 KiB
C#
89 lines
2.8 KiB
C#
using System.Text.Json;
|
|
using Microsoft.Extensions.Logging;
|
|
using StellaOps.Scanner.Sources.Contracts;
|
|
using StellaOps.Scanner.Sources.Domain;
|
|
|
|
namespace StellaOps.Scanner.Sources.Services;
|
|
|
|
/// <summary>
|
|
/// Dispatches connection tests to type-specific testers.
|
|
/// </summary>
|
|
public sealed class SourceConnectionTester : ISourceConnectionTester
|
|
{
|
|
private readonly IEnumerable<ISourceTypeConnectionTester> _testers;
|
|
private readonly ILogger<SourceConnectionTester> _logger;
|
|
private readonly TimeProvider _timeProvider;
|
|
|
|
public SourceConnectionTester(
|
|
IEnumerable<ISourceTypeConnectionTester> testers,
|
|
ILogger<SourceConnectionTester> logger,
|
|
TimeProvider? timeProvider = null)
|
|
{
|
|
_testers = testers;
|
|
_logger = logger;
|
|
_timeProvider = timeProvider ?? TimeProvider.System;
|
|
}
|
|
|
|
public Task<ConnectionTestResult> TestAsync(SbomSource source, CancellationToken ct = default)
|
|
{
|
|
return TestAsync(source, null, ct);
|
|
}
|
|
|
|
public async Task<ConnectionTestResult> TestAsync(
|
|
SbomSource source,
|
|
JsonDocument? testCredentials,
|
|
CancellationToken ct = default)
|
|
{
|
|
var tester = _testers.FirstOrDefault(t => t.SourceType == source.SourceType);
|
|
if (tester == null)
|
|
{
|
|
_logger.LogWarning(
|
|
"No connection tester registered for source type {SourceType}",
|
|
source.SourceType);
|
|
|
|
return new ConnectionTestResult
|
|
{
|
|
Success = false,
|
|
Message = $"No connection tester available for source type {source.SourceType}",
|
|
TestedAt = _timeProvider.GetUtcNow()
|
|
};
|
|
}
|
|
|
|
try
|
|
{
|
|
_logger.LogDebug(
|
|
"Testing connection for source {SourceId} ({SourceType})",
|
|
source.SourceId, source.SourceType);
|
|
|
|
var result = await tester.TestAsync(source, testCredentials, ct);
|
|
|
|
_logger.LogInformation(
|
|
"Connection test for source {SourceId} {Result}: {Message}",
|
|
source.SourceId,
|
|
result.Success ? "succeeded" : "failed",
|
|
result.Message);
|
|
|
|
return result;
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
throw;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Connection test failed for source {SourceId}", source.SourceId);
|
|
|
|
return new ConnectionTestResult
|
|
{
|
|
Success = false,
|
|
Message = $"Connection test error: {ex.Message}",
|
|
TestedAt = _timeProvider.GetUtcNow(),
|
|
Details = new Dictionary<string, object>
|
|
{
|
|
["exceptionType"] = ex.GetType().Name
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|