80 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			80 lines
		
	
	
		
			2.3 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.");
 | |
|     }
 | |
| }
 |