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>
This commit is contained in:
2026-07-24 11:06:10 +02:00
co-authored by Cursor
parent 7a9cdb6ecf
commit 12eebfc78a
23 changed files with 735 additions and 5189 deletions
@@ -1,37 +1,25 @@
using ZA.CoreService.ESBCertificateManager.Data;
using ZA.CoreService.ESBCertificateManager.Models;
namespace ZA.CoreService.ESBCertificateManager.Services;
/// <summary>
/// Nur Container-Neustart (kein Deploy, kein TLS, kein XApi).
/// </summary>
public sealed class DeploymentOrchestrator
{
private readonly CertificateDeployer _deployer = new();
private readonly RestartExecutor _restartExecutor;
private readonly TlsCertificateProbe _tlsProbe;
private readonly PreflightValidator _preflightValidator = new();
private readonly SqlRunLogger _sqlRunLogger;
private readonly AppSettings _settings;
public DeploymentOrchestrator(AppSettings settings)
{
_settings = settings;
_tlsProbe = new TlsCertificateProbe(settings.TlsTimeoutSeconds, settings.TlsRetryCount);
_restartExecutor = new RestartExecutor(settings.SonicConnections);
_sqlRunLogger = new SqlRunLogger(settings.ConnectionString);
}
public PreflightValidationResult ValidatePreflight(
string? certificatePath,
CertificateInfo? certificateInfo,
IReadOnlyList<DeploymentTarget> selectedTargets)
=> _preflightValidator.Validate(certificatePath, certificateInfo, selectedTargets);
public PreflightValidationResult ValidateRestartOnly(IReadOnlyList<DeploymentTarget> selectedTargets)
=> _preflightValidator.ValidateRestartOnly(selectedTargets);
/// <summary>
/// Nur ESB-/Container-Neustart ohne Zertifikatskopieren und ohne TLS-Probe.
/// </summary>
public async Task<DeploymentRunResult> RestartOnlyAsync(
IReadOnlyList<DeploymentTarget> selectedTargets,
IProgress<TargetProgressUpdate>? progress,
@@ -41,12 +29,30 @@ public sealed class DeploymentOrchestrator
List<TargetStepResult> results = [];
using RunLogger logger = new(_settings.LogDirectory);
logger.Write($"Neustart-only gestartet für {selectedTargets.Count} Ziel(e).");
logger.Write($"Neustart gestartet für {selectedTargets.Count} Ziel(e).");
foreach (DeploymentTarget target in selectedTargets)
{
cancellationToken.ThrowIfCancellationRequested();
results.Add(await RestartTargetOnlyAsync(target, logger, progress, cancellationToken));
DateTimeOffset targetStart = DateTimeOffset.Now;
progress?.Report(new TargetProgressUpdate(target.Id, $"Neustart {target.ContainerName}…", null));
(bool ok, string status, string? detail) =
await _restartExecutor.ExecuteAsync(target, cancellationToken);
logger.Write($"[{target.Name}] {status} | {detail}");
progress?.Report(new TargetProgressUpdate(target.Id, status, ok));
results.Add(new TargetStepResult
{
TargetId = target.Id,
TargetName = target.Name,
Success = ok,
StatusText = status,
Detail = detail,
StartedAt = targetStart,
FinishedAt = DateTimeOffset.Now
});
}
DateTimeOffset finishedAt = DateTimeOffset.Now;
@@ -54,210 +60,12 @@ public sealed class DeploymentOrchestrator
{
TargetResults = results,
StartedAt = startedAt,
FinishedAt = finishedAt,
CertificateFilePath = string.Empty,
CertificateFingerprint = string.Empty
FinishedAt = finishedAt
};
logger.Write(
$"Neustart-only beendet. Erfolg={runResult.OverallSuccess}; Dauer={(finishedAt - startedAt).TotalSeconds:F1}s; Log={logger.LogFilePath}");
try
{
await _sqlRunLogger.PersistRunResultAsync(runResult, cancellationToken);
}
catch (Exception ex)
{
logger.Write($"SQL-Protokollierung fehlgeschlagen (nicht kritisch): {ex.Message}");
}
$"Neustart beendet. Erfolg={runResult.OverallSuccess}; Dauer={(finishedAt - startedAt).TotalSeconds:F1}s; Log={logger.LogFilePath}");
return runResult;
}
private async Task<TargetStepResult> RestartTargetOnlyAsync(
DeploymentTarget target,
RunLogger logger,
IProgress<TargetProgressUpdate>? progress,
CancellationToken cancellationToken)
{
List<string> steps = [];
DateTimeOffset targetStart = DateTimeOffset.Now;
progress?.Report(new TargetProgressUpdate(target.Id, "Neustart…", false));
(bool restartOk, string restartStatus, string? restartDetail) =
await _restartExecutor.ExecuteAsync(target, cancellationToken);
RecordStep(steps, logger, target.Name, "Restart", restartStatus, restartDetail);
TargetStepResult targetResult = new()
{
TargetId = target.Id,
TargetName = target.Name,
Success = restartOk,
StatusText = restartStatus,
Detail = restartDetail,
Steps = steps,
StartedAt = targetStart,
FinishedAt = DateTimeOffset.Now,
CopySucceeded = true,
RestartSucceeded = restartOk,
TlsSucceeded = true,
ObservedFingerprint = null
};
progress?.Report(new TargetProgressUpdate(target.Id, restartStatus, restartOk));
return targetResult;
}
public async Task<DeploymentRunResult> RunAsync(
string certificatePath,
CertificateInfo certificateInfo,
IReadOnlyList<DeploymentTarget> selectedTargets,
IProgress<TargetProgressUpdate>? progress,
CancellationToken cancellationToken = default)
{
DateTimeOffset startedAt = DateTimeOffset.Now;
List<TargetStepResult> results = [];
using RunLogger logger = new(_settings.LogDirectory);
logger.Write($"Deployment gestartet für {selectedTargets.Count} Ziel(e). Zertifikat={Path.GetFileName(certificatePath)}");
foreach (DeploymentTarget target in selectedTargets)
{
cancellationToken.ThrowIfCancellationRequested();
results.Add(await RunTargetAsync(target, certificatePath, certificateInfo, logger, progress, cancellationToken));
}
DateTimeOffset finishedAt = DateTimeOffset.Now;
DeploymentRunResult runResult = new()
{
TargetResults = results,
StartedAt = startedAt,
FinishedAt = finishedAt,
CertificateFilePath = certificatePath,
CertificateFingerprint = certificateInfo.FingerprintSha256
};
logger.Write(
$"Deployment beendet. Erfolg={runResult.OverallSuccess}; Dauer={(finishedAt - startedAt).TotalSeconds:F1}s; Log={logger.LogFilePath}");
// Ergebnis in SQL-Datenbank protokollieren (wenn ConnectionString konfiguriert)
try
{
await _sqlRunLogger.PersistRunResultAsync(runResult, cancellationToken);
}
catch (Exception ex)
{
logger.Write($"SQL-Protokollierung fehlgeschlagen (nicht kritisch): {ex.Message}");
}
return runResult;
}
private async Task<TargetStepResult> RunTargetAsync(
DeploymentTarget target,
string certificatePath,
CertificateInfo certificateInfo,
RunLogger logger,
IProgress<TargetProgressUpdate>? progress,
CancellationToken cancellationToken)
{
List<string> steps = [];
DateTimeOffset targetStart = DateTimeOffset.Now;
progress?.Report(new TargetProgressUpdate(target.Id, "Läuft…", false));
(bool copyOk, string copyStatus, string? copyDetail, _) =
await _deployer.DeployAsync(certificatePath, target, cancellationToken);
RecordStep(steps, logger, target.Name, "Deploy", copyStatus, copyDetail);
if (!copyOk)
{
return Fail(target, copyStatus, copyDetail, steps, targetStart, progress);
}
progress?.Report(new TargetProgressUpdate(target.Id, copyStatus, false));
(bool restartOk, string restartStatus, string? restartDetail) =
await _restartExecutor.ExecuteAsync(target, cancellationToken);
RecordStep(steps, logger, target.Name, "Restart", restartStatus, restartDetail);
if (!restartOk)
{
return Fail(target, restartStatus, restartDetail, steps, targetStart, progress,
copySucceeded: copyOk);
}
progress?.Report(new TargetProgressUpdate(target.Id, restartStatus, false));
(bool tlsOk, string tlsStatus, string? tlsDetail, string? observedFingerprint) = await _tlsProbe.ProbeAsync(
target,
certificateInfo.FingerprintSha256,
cancellationToken);
RecordStep(steps, logger, target.Name, "TLS", tlsStatus, tlsDetail);
bool success = tlsOk;
string finalStatus = success
? (string.IsNullOrWhiteSpace(target.TlsHost) ? "Erfolg" : tlsStatus)
: tlsStatus;
TargetStepResult targetResult = new()
{
TargetId = target.Id,
TargetName = target.Name,
Success = success,
StatusText = finalStatus,
Detail = tlsDetail,
Steps = steps,
StartedAt = targetStart,
FinishedAt = DateTimeOffset.Now,
CopySucceeded = copyOk,
RestartSucceeded = restartOk,
TlsSucceeded = tlsOk,
ObservedFingerprint = observedFingerprint
};
progress?.Report(new TargetProgressUpdate(target.Id, finalStatus, success));
return targetResult;
}
private static void RecordStep(
List<string> steps,
RunLogger logger,
string targetName,
string phase,
string status,
string? detail)
{
steps.Add($"{status}: {detail}");
logger.Write($"[{targetName}] {phase}: {status} | {detail}");
}
private static TargetStepResult Fail(
DeploymentTarget target,
string status,
string? detail,
List<string> steps,
DateTimeOffset startedAt,
IProgress<TargetProgressUpdate>? progress,
bool copySucceeded = false,
bool restartSucceeded = false)
{
progress?.Report(new TargetProgressUpdate(target.Id, status, false));
return new TargetStepResult
{
TargetId = target.Id,
TargetName = target.Name,
Success = false,
StatusText = status,
Detail = detail,
Steps = steps,
StartedAt = startedAt,
FinishedAt = DateTimeOffset.Now,
CopySucceeded = copySucceeded,
RestartSucceeded = restartSucceeded,
TlsSucceeded = false
};
}
}
public readonly record struct TargetProgressUpdate(int TargetId, string StatusText, bool? SuccessHint);