Skip to content

Commit

Permalink
Merge pull request #1762 from snyk/refactor/cleanup-local-iac-cache
Browse files Browse the repository at this point in the history
feat: Delete local .iac-data directory after scan is finished [CC-765]
  • Loading branch information
ipapast authored Mar 26, 2021
2 parents 4235d0c + b6803e8 commit ef0bcbb
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 9 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
"promise-queue": "^2.2.5",
"proxy-agent": "^3.1.1",
"proxy-from-env": "^1.0.0",
"rimraf": "^2.6.3",
"semver": "^6.0.0",
"snyk-config": "4.0.0",
"snyk-cpp-plugin": "2.2.1",
Expand Down Expand Up @@ -162,7 +163,6 @@
"prettier": "^1.18.2",
"proxyquire": "^1.7.4",
"restify": "^8.5.1",
"rimraf": "^2.6.3",
"sinon": "^4.0.0",
"tap": "^12.6.1",
"tape": "^4.0.0",
Expand Down
3 changes: 2 additions & 1 deletion src/cli/commands/test/iac-local-execution/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
IacFileParseFailure,
SafeAnalyticsOutput,
} from './types';
import { initLocalCache } from './local-cache';
import { cleanLocalCache, initLocalCache } from './local-cache';
import { addIacAnalytics } from './analytics';
import { TestResult } from '../../../../lib/snyk-test/legacy';
import { IacFileInDirectory } from '../../../../lib/types';
Expand All @@ -32,6 +32,7 @@ export async function test(
const scannedFiles = await scanFiles(parsedFiles);
const formattedResults = formatScanResults(scannedFiles, options);
addIacAnalytics(formattedResults);
cleanLocalCache();

// TODO: add support for proper typing of old TestResult interface.
return {
Expand Down
19 changes: 19 additions & 0 deletions src/cli/commands/test/iac-local-execution/local-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ import * as path from 'path';
import * as fs from 'fs';
import { EngineType } from './types';
import * as needle from 'needle';
import * as rimraf from 'rimraf';
import { createIacDir, extractBundle } from './file-utils';
import * as Debug from 'debug';
import ReadableStream = NodeJS.ReadableStream;

const debug = Debug('iac-local-cache');

export const LOCAL_POLICY_ENGINE_DIR = '.iac-data';

const KUBERNETES_POLICY_ENGINE_WASM_PATH = path.join(
Expand All @@ -30,6 +34,7 @@ export const REQUIRED_LOCAL_CACHE_FILES = [
TERRAFORM_POLICY_ENGINE_WASM_PATH,
TERRAFORM_POLICY_ENGINE_DATA_PATH,
];

function doesLocalCacheExist(): boolean {
return REQUIRED_LOCAL_CACHE_FILES.every(fs.existsSync);
}
Expand Down Expand Up @@ -65,3 +70,17 @@ export async function initLocalCache(): Promise<void> {
);
}
}

export function cleanLocalCache() {
// path to delete is hardcoded for now
const iacPath: fs.PathLike = path.join(`${process.cwd()}`, '.iac-data');
if (fs.existsSync(iacPath) && fs.lstatSync(iacPath).isDirectory()) {
try {
// when we support Node version >= 12.10.0 , we can replace rimraf
// with the native fs.rmdirSync(path, {recursive: true})
rimraf.sync(iacPath);
} catch (e) {
debug('The local cache directory could not be deleted');
}
}
}
32 changes: 25 additions & 7 deletions test/jest/unit/iac-unit-tests/local-cache.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ import * as localCacheModule from '../../../../src/cli/commands/test/iac-local-e
import * as fileUtilsModule from '../../../../src/cli/commands/test/iac-local-execution/file-utils';
import { PassThrough } from 'stream';
import * as needle from 'needle';
import * as rimraf from 'rimraf';
import * as fs from 'fs';
import * as path from 'path';

describe('initLocalCache - downloads bundle successfully', () => {
beforeEach(() => {
jest.resetAllMocks();
jest.spyOn(fs, 'existsSync').mockReturnValueOnce(true);
});

const fs = require('fs');
fs.existsSync = jest.fn().mockReturnValue(true);

it('downloads and extracts the bundle successfully', () => {
const mockReadable = new PassThrough();
const spy = jest.spyOn(fileUtilsModule, 'extractBundle');
Expand All @@ -21,22 +22,31 @@ describe('initLocalCache - downloads bundle successfully', () => {

expect(spy).toHaveBeenCalledWith(mockReadable);
});

it('cleans up the custom folder after finishes', () => {
const iacPath: fs.PathLike = path.join(`${process.cwd()}`, '.iac-data');
const stats: fs.Stats = new fs.Stats();
stats.isDirectory = jest.fn().mockReturnValue(true);
jest.spyOn(fs, 'lstatSync').mockReturnValueOnce(stats);
const spy = jest.spyOn(rimraf, 'sync');

localCacheModule.cleanLocalCache();

expect(spy).toHaveBeenCalledWith(iacPath);
});
});

describe('initLocalCache - Missing IaC local cache data', () => {
beforeEach(() => {
jest.resetAllMocks();
jest.spyOn(fs, 'existsSync').mockReturnValueOnce(false);
});

const fs = require('fs');

it('throws an error on download', () => {
const error = new Error(
'The .iac-data directory can not be created. ' +
'Please make sure that the current working directory has write permissions',
);

fs.existsSync = jest.fn().mockReturnValue(false);
jest.spyOn(fileUtilsModule, 'extractBundle');
jest.spyOn(fileUtilsModule, 'createIacDir').mockImplementation(() => {
throw error;
Expand All @@ -47,4 +57,12 @@ describe('initLocalCache - Missing IaC local cache data', () => {
expect(fileUtilsModule.extractBundle).not.toHaveBeenCalled();
expect(promise).rejects.toThrow(error);
});

it('does not delete the local cacheDir if it does not exist', () => {
const spy = jest.spyOn(rimraf, 'sync');

localCacheModule.cleanLocalCache();

expect(spy).not.toHaveBeenCalled();
});
});

0 comments on commit ef0bcbb

Please sign in to comment.