diff --git a/src/Microsoft.ComponentDetection.Orchestrator/Commands/ListDetectorsCommand.cs b/src/Microsoft.ComponentDetection.Orchestrator/Commands/ListDetectorsCommand.cs index 2704e4e28..6eb145330 100644 --- a/src/Microsoft.ComponentDetection.Orchestrator/Commands/ListDetectorsCommand.cs +++ b/src/Microsoft.ComponentDetection.Orchestrator/Commands/ListDetectorsCommand.cs @@ -9,24 +9,12 @@ namespace Microsoft.ComponentDetection.Orchestrator.Commands; /// /// Lists available detectors. /// -public sealed class ListDetectorsCommand : Command +/// The detectors. +/// The console. +public sealed class ListDetectorsCommand( + IEnumerable detectors, + IAnsiConsole console) : Command { - private readonly IEnumerable detectors; - private readonly IAnsiConsole console; - - /// - /// Initializes a new instance of the class. - /// - /// The detectors. - /// The console. - public ListDetectorsCommand( - IEnumerable detectors, - IAnsiConsole console) - { - this.detectors = detectors; - this.console = console; - } - /// public override int Execute( CommandContext context, @@ -36,12 +24,12 @@ public override int Execute( var table = new Table(); table.AddColumn("Name"); - foreach (var detector in this.detectors) + foreach (var detector in detectors) { table.AddRow(detector.Id); } - this.console.Write(table); + console.Write(table); return (int)ProcessingResultCode.Success; } diff --git a/src/Microsoft.ComponentDetection.Orchestrator/Commands/ListDetectorsSettings.cs b/src/Microsoft.ComponentDetection.Orchestrator/Commands/ListDetectorsSettings.cs index 4877364f3..b224dff6f 100644 --- a/src/Microsoft.ComponentDetection.Orchestrator/Commands/ListDetectorsSettings.cs +++ b/src/Microsoft.ComponentDetection.Orchestrator/Commands/ListDetectorsSettings.cs @@ -3,6 +3,4 @@ namespace Microsoft.ComponentDetection.Orchestrator.Commands; /// /// Settings for the ListDetectors command. /// -public class ListDetectorsSettings : BaseSettings -{ -} +public class ListDetectorsSettings : BaseSettings; diff --git a/src/Microsoft.ComponentDetection.Orchestrator/Commands/ScanCommand.cs b/src/Microsoft.ComponentDetection.Orchestrator/Commands/ScanCommand.cs index de4a28048..385ba605e 100644 --- a/src/Microsoft.ComponentDetection.Orchestrator/Commands/ScanCommand.cs +++ b/src/Microsoft.ComponentDetection.Orchestrator/Commands/ScanCommand.cs @@ -44,7 +44,7 @@ public override async Task ExecuteAsync( CancellationToken cancellationToken) { this.fileWritingService.Init(settings.Output); - var result = await this.scanExecutionService.ExecuteScanAsync(settings); + var result = await this.scanExecutionService.ExecuteScanAsync(settings, cancellationToken); this.WriteComponentManifest(settings, result); return 0; } @@ -53,11 +53,12 @@ public override async Task ExecuteAsync( /// Method to provide a way to execute the scan command and obtain the ScanResult object. /// /// ScanSettings object specifying the parameters for the scan execution. + /// CancellationToken to monitor for cancellation requests. /// A ScanResult object. - public async Task ExecuteScanCommandAsync(ScanSettings settings) + public async Task ExecuteScanCommandAsync(ScanSettings settings, CancellationToken cancellationToken = default) { this.fileWritingService.Init(settings.Output); - var result = await this.scanExecutionService.ExecuteScanAsync(settings); + var result = await this.scanExecutionService.ExecuteScanAsync(settings, cancellationToken); this.WriteComponentManifest(settings, result); return result; } diff --git a/src/Microsoft.ComponentDetection.Orchestrator/Services/DetectorProcessingService.cs b/src/Microsoft.ComponentDetection.Orchestrator/Services/DetectorProcessingService.cs index 248c401d1..24364fc9b 100644 --- a/src/Microsoft.ComponentDetection.Orchestrator/Services/DetectorProcessingService.cs +++ b/src/Microsoft.ComponentDetection.Orchestrator/Services/DetectorProcessingService.cs @@ -41,10 +41,12 @@ public DetectorProcessingService( this.logger = logger; } + /// public async Task ProcessDetectorsAsync( ScanSettings settings, IEnumerable detectors, - DetectorRestrictions detectorRestrictions) + DetectorRestrictions detectorRestrictions, + CancellationToken cancellationToken = default) { using var scope = this.logger.BeginScope("Processing detectors"); this.logger.LogInformation($"Finding components..."); diff --git a/src/Microsoft.ComponentDetection.Orchestrator/Services/IDetectorProcessingService.cs b/src/Microsoft.ComponentDetection.Orchestrator/Services/IDetectorProcessingService.cs index 748b676ad..465ea1cfc 100644 --- a/src/Microsoft.ComponentDetection.Orchestrator/Services/IDetectorProcessingService.cs +++ b/src/Microsoft.ComponentDetection.Orchestrator/Services/IDetectorProcessingService.cs @@ -1,14 +1,27 @@ namespace Microsoft.ComponentDetection.Orchestrator.Services; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using Microsoft.ComponentDetection.Contracts; using Microsoft.ComponentDetection.Orchestrator.Commands; +/// +/// Defines a service for processing component detectors during a scan operation. +/// public interface IDetectorProcessingService { - Task ProcessDetectorsAsync( + /// + /// Processes the specified detectors asynchronously based on the provided scan settings and detector restrictions. + /// + /// The scan settings that configure how the detection process should be executed. + /// The collection of component detectors to be processed. + /// The restrictions that determine which detectors should be included or excluded from processing. + /// A token to monitor for cancellation requests. + /// A task that represents the asynchronous operation. The task result contains the with information about the detection process outcome. + public Task ProcessDetectorsAsync( ScanSettings settings, IEnumerable detectors, - DetectorRestrictions detectorRestrictions); + DetectorRestrictions detectorRestrictions, + CancellationToken cancellationToken = default); } diff --git a/src/Microsoft.ComponentDetection.Orchestrator/Services/IScanExecutionService.cs b/src/Microsoft.ComponentDetection.Orchestrator/Services/IScanExecutionService.cs index 6132b0628..e3712e6ed 100644 --- a/src/Microsoft.ComponentDetection.Orchestrator/Services/IScanExecutionService.cs +++ b/src/Microsoft.ComponentDetection.Orchestrator/Services/IScanExecutionService.cs @@ -1,10 +1,20 @@ namespace Microsoft.ComponentDetection.Orchestrator.Services; +using System.Threading; using System.Threading.Tasks; using Microsoft.ComponentDetection.Contracts.BcdeModels; using Microsoft.ComponentDetection.Orchestrator.Commands; +/// +/// Defines a service responsible for executing component detection scans. +/// public interface IScanExecutionService { - Task ExecuteScanAsync(ScanSettings settings); + /// + /// Executes a scan asynchronously based on the provided scan settings. + /// + /// The scan settings that configure how the scan should be executed. + /// A token to monitor for cancellation requests. + /// A task that represents the asynchronous scan operation. The task result contains the with information about the scan execution. + public Task ExecuteScanAsync(ScanSettings settings, CancellationToken cancellationToken = default); } diff --git a/src/Microsoft.ComponentDetection.Orchestrator/Services/ScanExecutionService.cs b/src/Microsoft.ComponentDetection.Orchestrator/Services/ScanExecutionService.cs index 94ef6f64b..d065adff3 100644 --- a/src/Microsoft.ComponentDetection.Orchestrator/Services/ScanExecutionService.cs +++ b/src/Microsoft.ComponentDetection.Orchestrator/Services/ScanExecutionService.cs @@ -4,6 +4,7 @@ namespace Microsoft.ComponentDetection.Orchestrator.Services; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Microsoft.ComponentDetection.Contracts; using Microsoft.ComponentDetection.Contracts.BcdeModels; @@ -33,7 +34,8 @@ public ScanExecutionService( this.logger = logger; } - public async Task ExecuteScanAsync(ScanSettings settings) + /// + public async Task ExecuteScanAsync(ScanSettings settings, CancellationToken cancellationToken = default) { using var scope = this.logger.BeginScope("Executing BCDE scan"); @@ -44,7 +46,7 @@ public async Task ExecuteScanAsync(ScanSettings settings) this.logger.LogDebug("Finished applying restrictions to detectors."); - var processingResult = await this.detectorProcessingService.ProcessDetectorsAsync(settings, detectorsWithAppliedRestrictions, detectorRestrictions); + var processingResult = await this.detectorProcessingService.ProcessDetectorsAsync(settings, detectorsWithAppliedRestrictions, detectorRestrictions, cancellationToken); var scanResult = this.graphTranslationService.GenerateScanResultFromProcessingResult(processingResult, settings); scanResult.DetectorsInScan = detectorsWithAppliedRestrictions.Select(ConvertToContract).ToList(); diff --git a/test/Microsoft.ComponentDetection.Orchestrator.Tests/Commands/ScanCommandTests.cs b/test/Microsoft.ComponentDetection.Orchestrator.Tests/Commands/ScanCommandTests.cs index 77687ec32..38fa2ff1f 100644 --- a/test/Microsoft.ComponentDetection.Orchestrator.Tests/Commands/ScanCommandTests.cs +++ b/test/Microsoft.ComponentDetection.Orchestrator.Tests/Commands/ScanCommandTests.cs @@ -44,7 +44,7 @@ public async Task ScanCommand_ExecutesScanAndWritesManifestAsync() var result = await this.command.ExecuteAsync(null, settings, CancellationToken.None); this.fileWritingServiceMock.Verify(x => x.Init(settings.Output), Times.Once); - this.scanExecutionServiceMock.Verify(x => x.ExecuteScanAsync(settings), Times.Once); + this.scanExecutionServiceMock.Verify(x => x.ExecuteScanAsync(settings, CancellationToken.None), Times.Once); this.fileWritingServiceMock.Verify(x => x.ResolveFilePath(It.IsAny()), Times.Once); this.fileWritingServiceMock.Verify(x => x.AppendToFile(It.IsAny(), It.IsAny())); result.Should().Be(0); @@ -58,7 +58,7 @@ public async Task ScanCommand_ExecutesScanAndWritesUserManifestAsync() var result = await this.command.ExecuteAsync(null, settings, CancellationToken.None); this.fileWritingServiceMock.Verify(x => x.Init(settings.Output), Times.Once); - this.scanExecutionServiceMock.Verify(x => x.ExecuteScanAsync(settings), Times.Once); + this.scanExecutionServiceMock.Verify(x => x.ExecuteScanAsync(settings, CancellationToken.None), Times.Once); this.fileWritingServiceMock.Verify(x => x.WriteFile(It.Is(x => x == settings.ManifestFile), It.IsAny())); result.Should().Be(0); @@ -75,7 +75,7 @@ public async Task ScanCommand_ExecutesScanAndPrintsManifestAsync() var result = await this.command.ExecuteAsync(null, settings, CancellationToken.None); this.fileWritingServiceMock.Verify(x => x.Init(settings.Output), Times.Once); - this.scanExecutionServiceMock.Verify(x => x.ExecuteScanAsync(settings), Times.Once); + this.scanExecutionServiceMock.Verify(x => x.ExecuteScanAsync(settings, CancellationToken.None), Times.Once); this.fileWritingServiceMock.Verify(x => x.ResolveFilePath(It.IsAny()), Times.Once); this.fileWritingServiceMock.Verify(x => x.AppendToFile(It.IsAny(), It.IsAny())); @@ -95,7 +95,7 @@ public async Task ExecuteScanCommandAsync_PrintsManifestAsync() var result = await this.command.ExecuteScanCommandAsync(settings); this.fileWritingServiceMock.Verify(x => x.Init(settings.Output), Times.Once); - this.scanExecutionServiceMock.Verify(x => x.ExecuteScanAsync(settings), Times.Once); + this.scanExecutionServiceMock.Verify(x => x.ExecuteScanAsync(settings, CancellationToken.None), Times.Once); this.fileWritingServiceMock.Verify(x => x.ResolveFilePath(It.IsAny()), Times.Once); this.fileWritingServiceMock.Verify(x => x.AppendToFile(It.IsAny(), It.IsAny())); @@ -111,7 +111,7 @@ public async Task ExecuteScanCommandAsync_WritesUserManifestAsync() var result = await this.command.ExecuteScanCommandAsync(settings); this.fileWritingServiceMock.Verify(x => x.Init(settings.Output), Times.Once); - this.scanExecutionServiceMock.Verify(x => x.ExecuteScanAsync(settings), Times.Once); + this.scanExecutionServiceMock.Verify(x => x.ExecuteScanAsync(settings, CancellationToken.None), Times.Once); this.fileWritingServiceMock.Verify(x => x.WriteFile(It.Is(x => x == settings.ManifestFile), It.IsAny())); } } diff --git a/test/Microsoft.ComponentDetection.Orchestrator.Tests/Services/BcdeScanExecutionServiceTests.cs b/test/Microsoft.ComponentDetection.Orchestrator.Tests/Services/BcdeScanExecutionServiceTests.cs index e55ec78b0..91567178a 100644 --- a/test/Microsoft.ComponentDetection.Orchestrator.Tests/Services/BcdeScanExecutionServiceTests.cs +++ b/test/Microsoft.ComponentDetection.Orchestrator.Tests/Services/BcdeScanExecutionServiceTests.cs @@ -4,6 +4,7 @@ namespace Microsoft.ComponentDetection.Orchestrator.Tests.Services; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using System.Threading.Tasks; using AwesomeAssertions; using Microsoft.ComponentDetection.Common.DependencyGraph; @@ -765,10 +766,11 @@ private async Task DetectComponentsHappyPathAsync( x.ProcessDetectorsAsync( settings, It.Is>(inputDetectors => restrictedDetectors.Intersect(inputDetectors).Count() == restrictedDetectors.Length), - Match.Create(restriction => true))) + Match.Create(restriction => true), + CancellationToken.None)) .ReturnsAsync(processingResult); - var result = await this.serviceUnderTest.ExecuteScanAsync(settings); + var result = await this.serviceUnderTest.ExecuteScanAsync(settings, CancellationToken.None); result.ResultCode.Should().Be(ProcessingResultCode.Success); result.SourceDirectory.Should().NotBeNull(); result.SourceDirectory.Should().Be(settings.SourceDirectory.ToString()); @@ -824,10 +826,11 @@ private async Task DetectComponentsHappyPathAsync( x.ProcessDetectorsAsync( settings, It.Is>(inputDetectors => restrictedDetectors.Intersect(inputDetectors).Count() == restrictedDetectors.Length), - Match.Create(restriction => true))) + Match.Create(restriction => true), + CancellationToken.None)) .ReturnsAsync(processingResult); - var result = await this.serviceUnderTest.ExecuteScanAsync(settings); + var result = await this.serviceUnderTest.ExecuteScanAsync(settings, CancellationToken.None); result.ResultCode.Should().Be(ProcessingResultCode.Success); result.SourceDirectory.Should().NotBeNull(); result.SourceDirectory.Should().Be(settings.SourceDirectory.ToString()); @@ -880,10 +883,11 @@ private async Task SetupRecorderBasedScanningAsync( x.ProcessDetectorsAsync( settings, It.Is>(inputDetectors => restrictedDetectors.Intersect(inputDetectors).Count() == restrictedDetectors.Length), - Match.Create(restriction => true))) + Match.Create(restriction => true), + CancellationToken.None)) .ReturnsAsync(processingResult); - var result = await this.serviceUnderTest.ExecuteScanAsync(settings); + var result = await this.serviceUnderTest.ExecuteScanAsync(settings, CancellationToken.None); result.ResultCode.Should().Be(ProcessingResultCode.Success); result.SourceDirectory.Should().NotBeNull(); result.SourceDirectory.Should().Be(settings.SourceDirectory.ToString());