using System; using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; namespace StellaOps.Cli.Services; internal sealed class ScannerInstaller : IScannerInstaller { private readonly ILogger _logger; public ScannerInstaller(ILogger logger) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } public async Task InstallAsync(string artifactPath, bool verbose, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(artifactPath) || !File.Exists(artifactPath)) { throw new FileNotFoundException("Scanner artifact not found for installation.", artifactPath); } // Current implementation assumes docker-based scanner bundle. var processInfo = new ProcessStartInfo { FileName = "docker", ArgumentList = { "load", "-i", artifactPath }, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false }; using var process = new Process { StartInfo = processInfo, EnableRaisingEvents = true }; process.OutputDataReceived += (_, args) => { if (args.Data is null) { return; } if (verbose) { _logger.LogInformation("[install] {Line}", args.Data); } }; process.ErrorDataReceived += (_, args) => { if (args.Data is null) { return; } _logger.LogError("[install] {Line}", args.Data); }; _logger.LogInformation("Installing scanner container from {Path}...", artifactPath); if (!process.Start()) { throw new InvalidOperationException("Failed to start container installation process."); } process.BeginOutputReadLine(); process.BeginErrorReadLine(); await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false); if (process.ExitCode != 0) { throw new InvalidOperationException($"Container installation failed with exit code {process.ExitCode}."); } _logger.LogInformation("Scanner container installed successfully."); } }