Files
123123/ZA.CoreService.ESBCertificateManager/Services/SonicContainerDiscovery.cs
T
GizzlerandCursor 12eebfc78a Simplify app to certificate recognition and MfApi restart only.
Remove XApi, WinRM, LocalCmd, HTTP API, TLS probe, SQL deploy model, and deploy UI.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 11:06:10 +02:00

125 lines
4.5 KiB
C#

using ZA.CoreService.ESBCertificateManager.Models;
namespace ZA.CoreService.ESBCertificateManager.Services;
public sealed class SonicContainerDiscovery
{
private readonly IReadOnlyList<SonicConnection> _connections;
public SonicContainerDiscovery(IReadOnlyList<SonicConnection> connections)
{
_connections = connections;
}
public bool HasConnections => _connections.Count > 0;
public IReadOnlyList<SonicConnection> Connections => _connections;
public async Task<SonicDiscoveryResult> DiscoverAsync(
string connectionName,
IReadOnlyList<DeploymentTarget> knownTargets,
CancellationToken cancellationToken = default)
{
SonicConnection? connection = _connections
.FirstOrDefault(c => string.Equals(c.Name, connectionName, StringComparison.OrdinalIgnoreCase));
if (connection is null)
{
return SonicDiscoveryResult.Failed(connectionName,
$"Sonic-Verbindung '{connectionName}' fehlt in appsettings.");
}
using SonicManagementClient client = new(connection);
(bool reachable, string? pingError, _) = await client.CheckConnectionAsync(cancellationToken);
List<string> remoteContainers = [];
List<string> diagnostics = [];
if (!reachable)
{
diagnostics.Add($"Ping: {pingError}");
}
else
{
(bool listOk, IReadOnlyList<string> remoteNames, string? listError) =
await client.GetContainersAsync(cancellationToken);
if (listOk)
{
remoteContainers.AddRange(remoteNames.Where(n =>
!n.StartsWith("WARN:", StringComparison.OrdinalIgnoreCase)
&& !n.StartsWith("INFO:", StringComparison.OrdinalIgnoreCase)));
}
else if (!string.IsNullOrWhiteSpace(listError))
{
diagnostics.Add(listError);
}
}
List<string> merged = [];
foreach (string name in remoteContainers
.Concat(connection.KnownContainers)
.Concat(knownTargets
.Where(t => string.Equals(t.SonicConnectionName, connection.Name, StringComparison.OrdinalIgnoreCase))
.Select(t => t.ContainerName))
.Where(n => !string.IsNullOrWhiteSpace(n)))
{
if (!merged.Any(m => string.Equals(m, name, StringComparison.OrdinalIgnoreCase)))
{
merged.Add(name);
}
}
if (merged.Count == 0)
{
return SonicDiscoveryResult.Failed(connectionName,
string.Join(" | ", diagnostics.DefaultIfEmpty("Keine Container gefunden.")));
}
int id = 1;
List<DeploymentTarget> targets = merged.Select(name =>
{
DeploymentTarget? known = knownTargets.FirstOrDefault(t =>
string.Equals(t.ContainerName, name, StringComparison.OrdinalIgnoreCase)
&& string.Equals(t.SonicConnectionName, connection.Name, StringComparison.OrdinalIgnoreCase));
return new DeploymentTarget
{
Id = known?.Id ?? id++,
Name = known?.Name ?? $"{connection.Name} / {name}",
Environment = known?.Environment ?? "TEST",
IsActive = true,
ContainerName = name,
SonicConnectionName = connection.Name,
SortOrder = known?.SortOrder ?? id * 10
};
}).ToList();
return new SonicDiscoveryResult
{
ConnectionName = connectionName,
DomainName = connection.DomainName,
Success = true,
ErrorMessage = diagnostics.Count == 0 ? null : string.Join(" | ", diagnostics),
DiscoveredTargets = targets,
RawContainerNames = remoteContainers
};
}
}
public sealed class SonicDiscoveryResult
{
public required string ConnectionName { get; init; }
public string DomainName { get; init; } = string.Empty;
public bool Success { get; init; }
public string? ErrorMessage { get; init; }
public IReadOnlyList<DeploymentTarget> DiscoveredTargets { get; init; } = [];
public IReadOnlyList<string> RawContainerNames { get; init; } = [];
public static SonicDiscoveryResult Failed(string connectionName, string error)
=> new()
{
ConnectionName = connectionName,
Success = false,
ErrorMessage = error
};
}