80 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			80 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
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<ScannerInstaller> _logger;
 | 
						|
 | 
						|
    public ScannerInstaller(ILogger<ScannerInstaller> 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.");
 | 
						|
    }
 | 
						|
}
 |