diff --git a/src/main/scanLogic/scanRunners/analyzerManager.ts b/src/main/scanLogic/scanRunners/analyzerManager.ts index 90fc3c25..50e0a032 100644 --- a/src/main/scanLogic/scanRunners/analyzerManager.ts +++ b/src/main/scanLogic/scanRunners/analyzerManager.ts @@ -8,7 +8,6 @@ import { IProxyConfig, JfrogClient } from 'jfrog-client-js'; import { ConnectionUtils } from '../../connect/connectionUtils'; import { Configuration } from '../../utils/configuration'; import { Translators } from '../../utils/translators'; -import { RunUtils } from '../../utils/runUtils'; /** * Analyzer manager is responsible for running the analyzer on the workspace. @@ -93,20 +92,13 @@ export class AnalyzerManager { return false; } - public async runWithTimeout(checkCancel: () => void, args: string[], executionLogDirectory?: string): Promise { - await AnalyzerManager.FINISH_UPDATE_PROMISE; - await RunUtils.runWithTimeout(AnalyzerManager.TIMEOUT_MILLISECS, checkCancel, { - title: this._binary.name, - task: this.run(args, executionLogDirectory) - }); - } - /** * Execute the cmd command to run the binary with given arguments * @param args - the arguments for the command * @param executionLogDirectory - the directory to save the execution log in */ - private async run(args: string[], executionLogDirectory?: string): Promise { + public async run(args: string[], executionLogDirectory?: string): Promise { + await AnalyzerManager.FINISH_UPDATE_PROMISE; let std: any = await this._binary.run(args, this.createEnvForRun(executionLogDirectory)); if (std.stdout && std.stdout.length > 0) { this._logManager.logMessage('Done executing with log, log:\n' + std.stdout, 'DEBUG'); diff --git a/src/main/scanLogic/scanRunners/applicabilityScan.ts b/src/main/scanLogic/scanRunners/applicabilityScan.ts index 4b80527d..6959e292 100644 --- a/src/main/scanLogic/scanRunners/applicabilityScan.ts +++ b/src/main/scanLogic/scanRunners/applicabilityScan.ts @@ -61,7 +61,7 @@ export class ApplicabilityRunner extends JasRunner { /** @override */ protected async runBinary(yamlConfigPath: string, executionLogDirectory: string | undefined, checkCancel: () => void): Promise { - await this.executeBinary(checkCancel, ['ca', yamlConfigPath], executionLogDirectory); + await this.runAnalyzerManager(checkCancel, ['ca', yamlConfigPath], executionLogDirectory); } /** @override */ diff --git a/src/main/scanLogic/scanRunners/iacScan.ts b/src/main/scanLogic/scanRunners/iacScan.ts index d9089d6b..8c129621 100644 --- a/src/main/scanLogic/scanRunners/iacScan.ts +++ b/src/main/scanLogic/scanRunners/iacScan.ts @@ -31,7 +31,7 @@ export class IacRunner extends JasRunner { /** @override */ protected async runBinary(yamlConfigPath: string, executionLogDirectory: string | undefined, checkCancel: () => void): Promise { - await this.executeBinary(checkCancel, ['iac', yamlConfigPath], executionLogDirectory); + await this.runAnalyzerManager(checkCancel, ['iac', yamlConfigPath], executionLogDirectory); } /** diff --git a/src/main/scanLogic/scanRunners/jasRunner.ts b/src/main/scanLogic/scanRunners/jasRunner.ts index aea1517c..4bfb6eac 100644 --- a/src/main/scanLogic/scanRunners/jasRunner.ts +++ b/src/main/scanLogic/scanRunners/jasRunner.ts @@ -83,13 +83,13 @@ export abstract class JasRunner { } /** - * Execute the cmd command to run the binary with given arguments and an option to abort the operation. - * @param checkCancel - Check if should cancel + * Run Analyzer Manager with given arguments and an option to abort the operation. * @param args - Arguments for the command * @param executionLogDirectory - Directory to save the execution log in */ - protected async executeBinary(checkCancel: () => void, args: string[], executionLogDirectory?: string): Promise { - await this._analyzerManager.runWithTimeout(checkCancel, args, executionLogDirectory); + protected async runAnalyzerManager(checkCancel: () => void, args: string[], executionLogDirectory?: string): Promise { + checkCancel(); + await this._analyzerManager.run(args, executionLogDirectory); } protected logStartScanning(request: AnalyzeScanRequest): void { diff --git a/src/main/scanLogic/scanRunners/sastScan.ts b/src/main/scanLogic/scanRunners/sastScan.ts index c39cd2dd..28501dbd 100644 --- a/src/main/scanLogic/scanRunners/sastScan.ts +++ b/src/main/scanLogic/scanRunners/sastScan.ts @@ -74,7 +74,7 @@ export class SastRunner extends JasRunner { checkCancel: () => void, responsePath: string ): Promise { - await this.executeBinary(checkCancel, ['zd', yamlConfigPath, responsePath], executionLogDirectory); + await this.runAnalyzerManager(checkCancel, ['zd', yamlConfigPath, responsePath], executionLogDirectory); } /** @override */ diff --git a/src/main/scanLogic/scanRunners/secretsScan.ts b/src/main/scanLogic/scanRunners/secretsScan.ts index a707c156..69bf5806 100644 --- a/src/main/scanLogic/scanRunners/secretsScan.ts +++ b/src/main/scanLogic/scanRunners/secretsScan.ts @@ -31,7 +31,7 @@ export class SecretsRunner extends JasRunner { /** @override */ protected async runBinary(yamlConfigPath: string, executionLogDirectory: string | undefined, checkCancel: () => void): Promise { - await this.executeBinary(checkCancel, ['sec', yamlConfigPath], executionLogDirectory); + await this.runAnalyzerManager(checkCancel, ['sec', yamlConfigPath], executionLogDirectory); } /** diff --git a/src/main/utils/runUtils.ts b/src/main/utils/runUtils.ts index 7b087dcc..a2717451 100644 --- a/src/main/utils/runUtils.ts +++ b/src/main/utils/runUtils.ts @@ -1,53 +1,4 @@ -import { ScanTimeoutError } from './scanUtils'; - -export interface Task { - title: string; - task: Promise; -} - export class RunUtils { - // every 0.1 sec - private static readonly CHECK_INTERVAL_MILLISECS: number = 100; - - /** - * Creates a Promise that is resolved with an array of results when all of the provided Promises resolve, or rejected when: - * 1. Any Promise is rejected. - * 2. Cancel was requested. - * 3. Timeout reached. - * @param timeout - time in millisecs until execution timeout - * @param checkCancel - check if cancel was requested - * @param tasks - the promises that the new promise will wrap - * @returns Promise that wrap the given promises - */ - static async runWithTimeout(timeout: number, checkCancel: () => void, ...tasks: (Promise | Task)[]): Promise { - let results: T[] = []; - const wrappedTasks: Promise[] = []>tasks.map(async (task, index) => { - let result: T = await Promise.race([ - // Add task from argument - !(task instanceof Promise) && task.task ? task.task : task, - // Add task to check if cancel was requested from the user or reached timeout - this.checkCancelAndTimeoutTask(!(task instanceof Promise) && task.title ? task.title : '' + (index + 1), timeout, checkCancel) - ]); - results.push(result); - }); - await Promise.all(wrappedTasks); - return results; - } - - /** - * Async task that checks if an abort signal was given. - * If the active task is <= 0 the task is completed - * @param tasksBundle - an object that holds the information about the active async tasks count and the abort signal for them - */ - private static async checkCancelAndTimeoutTask(title: string, timeout: number, checkCancel: () => void): Promise { - let checkInterval: number = timeout < RunUtils.CHECK_INTERVAL_MILLISECS ? timeout : RunUtils.CHECK_INTERVAL_MILLISECS; - for (let elapsed: number = 0; elapsed < timeout; elapsed += checkInterval) { - checkCancel(); - await this.delay(checkInterval); - } - throw new ScanTimeoutError(title, timeout); - } - /** * Sleep and delay task for sleepIntervalMilliseconds * @param sleepIntervalMilliseconds - the amount of time in milliseconds to wait diff --git a/src/test/tests/runUtils.test.ts b/src/test/tests/runUtils.test.ts deleted file mode 100644 index 400bf092..00000000 --- a/src/test/tests/runUtils.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { assert } from 'chai'; -import { RunUtils, Task } from '../../main/utils/runUtils'; -import { ScanCancellationError, ScanTimeoutError } from '../../main/utils/scanUtils'; - -describe('Run Utils tests', async () => { - [ - { - name: 'Task ended', - timeout: false, - shouldAbort: false, - addTitle: undefined, - expectedErr: undefined - }, - { - name: 'Task aborted', - timeout: false, - shouldAbort: true, - addTitle: undefined, - expectedErr: new ScanCancellationError() - }, - { - name: 'Task timeout with title', - timeout: true, - shouldAbort: false, - addTitle: "'TitledTask'", - expectedErr: new ScanTimeoutError("'TitledTask'", 100) - }, - { - name: 'Task timeout no title', - timeout: true, - shouldAbort: false, - addTitle: undefined, - expectedErr: new Error() - }, - { - name: 'Task throws error', - timeout: false, - shouldAbort: false, - addTitle: undefined, - expectedErr: new Error('general error') - } - ].forEach(async test => { - it('Run with abort controller - ' + test.name, async () => { - let tasks: (Promise | Task)[] = []; - let expectedResults: number[] = [0, 1, 2, 3]; - - for (let i: number = 0; i < expectedResults.length; i++) { - let task: Promise | Task = - test.name.includes('Task throws error') && i == expectedResults.length - 1 - ? RunUtils.delay(200).then(() => { - throw new Error('general error'); - }) - : RunUtils.delay((expectedResults.length - i) * 200).then(() => { - return i; - }); - tasks.push(test.addTitle ? ({ title: test.addTitle, task: task } as Task) : task); - } - - try { - let activeTasks: Promise = RunUtils.runWithTimeout( - test.timeout ? 100 : 1000, - () => { - if (test.shouldAbort) { - throw new ScanCancellationError(); - } - }, - ...tasks - ); - let actualResults: number[] = await activeTasks; - if (test.expectedErr) { - assert.fail('Expected run to throw error'); - } - // Make sure all tasks ended - assert.sameMembers(actualResults, expectedResults); - } catch (err) { - if (!test.expectedErr) { - assert.fail('Expected run not to throw error but got ' + err); - } - if (err instanceof Error) { - if (test.timeout && !test.addTitle) { - assert.include(err.message, 'timed out after'); - } else { - assert.equal(err.message, test.expectedErr.message); - } - } - } - }); - }); -}); diff --git a/src/test/tests/scanAnlayzerRunner.test.ts b/src/test/tests/scanAnlayzerRunner.test.ts index f76c95a7..a9b3d4e6 100644 --- a/src/test/tests/scanAnlayzerRunner.test.ts +++ b/src/test/tests/scanAnlayzerRunner.test.ts @@ -9,7 +9,7 @@ import { AnalyzeScanRequest, AnalyzerScanRun, ScanType } from '../../main/scanLo import { JasRunner } from '../../main/scanLogic/scanRunners/jasRunner'; import { AppsConfigModule } from '../../main/utils/jfrogAppsConfig/jfrogAppsConfig'; import { RunUtils } from '../../main/utils/runUtils'; -import { NotEntitledError, ScanCancellationError, ScanTimeoutError, ScanUtils } from '../../main/utils/scanUtils'; +import { NotEntitledError, ScanCancellationError, ScanUtils } from '../../main/utils/scanUtils'; import { Translators } from '../../main/utils/translators'; import { AnalyzerManager } from '../../main/scanLogic/scanRunners/analyzerManager'; @@ -41,7 +41,6 @@ describe('Analyzer BinaryRunner tests', async () => { function createDummyBinaryRunner( connection: ConnectionManager = connectionManager, - timeout: number = AnalyzerManager.TIMEOUT_MILLISECS, dummyAction: () => Promise = () => Promise.resolve() ): JasRunner { return new (class extends JasRunner { @@ -57,14 +56,14 @@ describe('Analyzer BinaryRunner tests', async () => { _executionLogDirectory: string | undefined, checkCancel: () => void ): Promise { - await RunUtils.runWithTimeout(timeout, checkCancel, dummyAction()); + checkCancel(); + await dummyAction(); } })(connection, dummyName, logManager, new AppsConfigModule(''), {} as AnalyzerManager); } function createDummyAnalyzerManager( connection: ConnectionManager = connectionManager, - timeout: number = AnalyzerManager.TIMEOUT_MILLISECS, dummyAction: () => Promise = () => Promise.resolve() ): AnalyzerManager { return new (class extends AnalyzerManager { @@ -80,7 +79,8 @@ describe('Analyzer BinaryRunner tests', async () => { _executionLogDirectory: string | undefined, checkCancel: () => void ): Promise { - await RunUtils.runWithTimeout(timeout, checkCancel, dummyAction()); + checkCancel(); + await dummyAction(); } })(connection, logManager); } @@ -215,13 +215,7 @@ describe('Analyzer BinaryRunner tests', async () => { shouldAbort: true, expectedErr: new ScanCancellationError() }, - { - name: 'Timeout', - timeout: 1, - createDummyResponse: true, - shouldAbort: false, - expectedErr: new ScanTimeoutError('' + 1, 1) - }, + { name: 'Response not created', timeout: AnalyzerManager.TIMEOUT_MILLISECS, @@ -237,7 +231,7 @@ describe('Analyzer BinaryRunner tests', async () => { let requestPath: string = path.join(tempFolder, 'request'); let responsePath: string = path.join(tempFolder, 'response'); - let runner: JasRunner = createDummyBinaryRunner(connectionManager, test.timeout, async () => { + let runner: JasRunner = createDummyBinaryRunner(connectionManager, async () => { if (test.shouldAbort) { throw new ScanCancellationError(); } else if (test.name === 'Not entitled') {