terraguardian-cli 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,11 +1,16 @@
1
1
  {
2
2
  "name": "terraguardian-cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "CLI that helps with projects that are built with terraform and helps with deployments of lambda src code",
5
5
  "main": "index.js",
6
6
  "bin": {
7
7
  "tg-cli": "src/index.js"
8
8
  },
9
+ "files": [
10
+ "src",
11
+ "bin"
12
+
13
+ ],
9
14
  "scripts": {
10
15
  "test": "jest",
11
16
  "lint": "eslint src",
@@ -0,0 +1,23 @@
1
+ const chalk = require('chalk');
2
+ const util = require('util');
3
+ const exec = util.promisify(require('child_process').exec);
4
+
5
+ const GO_BINARY_NAME = 'bootstrap';
6
+ const GO_ARCHITECTURE = 'arm64';
7
+
8
+ const { GO_LAMBDA_SRC_DIR, LAMBDA_BUILD_DIR } = require('../../common/constants');
9
+
10
+ async function buildGoLambda(lambdaName) {
11
+ console.log('Building the go lambda...');
12
+ const goLambdaSrcPath = `${GO_LAMBDA_SRC_DIR}/${lambdaName.split('lambda_')[1]}`;
13
+ const buildOutputDir = `${LAMBDA_BUILD_DIR}/${lambdaName}`;
14
+ const buildCommand = `GOOS='linux' GOARCH='${GO_ARCHITECTURE}' GO111MODULE='on' go build -tags 'lambda.norpc' -o '${buildOutputDir}/${GO_BINARY_NAME}' '${goLambdaSrcPath}'`;
15
+
16
+ await exec(buildCommand);
17
+ console.log(chalk.green('Successfully built the lambda'));
18
+ return `${buildOutputDir}/${GO_BINARY_NAME}`;
19
+ }
20
+
21
+ module.exports = {
22
+ buildGoLambda,
23
+ };
@@ -0,0 +1,44 @@
1
+ const { execSync } = require('child_process');
2
+ const { NODE_RUNTIME_TF_VAR, GO_RUNTIME_TF_VAR } = require('../../common/constants');
3
+
4
+ const getEntryPointPaths = (config) => execSync(`${config.search} -name "${config.entryPoint}" -print`)
5
+ .toString()
6
+ .split('\n')
7
+ .filter(Boolean);
8
+
9
+ const getNormalizedLambdaNames = (lamdbdaPaths) => lamdbdaPaths.map((lambdaPath) => {
10
+ const regex = /lambda_(\w+)/g;
11
+ return regex.exec(lambdaPath)[0];
12
+ });
13
+
14
+ function findEntryPoints(runtime, lambdaName) {
15
+ const findConfig = {
16
+ [GO_RUNTIME_TF_VAR]: {
17
+ search: 'find "$(pwd)/build" -path "$(pwd)/build" -prune -o -name node_modules -prune -o -path "$(pwd)/dist" -prune -o',
18
+ entryPoint: 'main.go',
19
+ regexFilter: null,
20
+ },
21
+ [NODE_RUNTIME_TF_VAR]: {
22
+ search: 'find "$(pwd)/modules" -path "$(pwd)/dist" -prune -o -name node_modules -prune -o -path "$(pwd)/build" -prune -o',
23
+ entryPoint: 'index.js',
24
+ regexFilter: 'lambda_[^/]+/src/index.js',
25
+ },
26
+ }[runtime];
27
+ const entryPointPaths = getEntryPointPaths(findConfig);
28
+
29
+ if (lambdaName) {
30
+ return entryPointPaths.find((path) => path.includes(lambdaName));
31
+ }
32
+
33
+ const regex = new RegExp(findConfig.regexFilter);
34
+ if (regex) {
35
+ return entryPointPaths.filter((path) => regex.test(path));
36
+ }
37
+ return entryPointPaths;
38
+ }
39
+
40
+ module.exports = {
41
+ findEntryPoints,
42
+ getEntryPointPaths,
43
+ getNormalizedLambdaNames,
44
+ };
@@ -0,0 +1,63 @@
1
+ const chalk = require('chalk');
2
+
3
+ const {
4
+ LAMBDA_BUILD_DIR,
5
+ WEBPACK_FILE_PATH,
6
+ NODE_LIBARY_TYPE,
7
+ DEFAULT_WEBPACK_MODE,
8
+ NODE_BUILD_FILE_NAME,
9
+ NODE_RUNTIME_TF_VAR,
10
+ } = require('../../common/constants');
11
+ const { executeCommand } = require('../../common/helpers');
12
+ const FileHandler = require('../../fs-utils/FileHandler');
13
+ const { findEntryPoints, getNormalizedLambdaNames } = require('./helpers');
14
+
15
+ function getWebpackBuildCommand(lambdaName, lambdaPath, buildOutputDir) {
16
+ let buildCommand;
17
+ const webpackExists = FileHandler.doesFileExist('webpack.config.js');
18
+
19
+ if (webpackExists) {
20
+ console.log('Webpack exists');
21
+ buildCommand = (`npx webpack --config ${WEBPACK_FILE_PATH} --entry ${lambdaPath} --output-path "${buildOutputDir}" --output-filename ${NODE_BUILD_FILE_NAME}`);
22
+ } else {
23
+ console.log('Webpack does not exist');
24
+ buildCommand = (`npx webpack -entry ${lambdaPath} --output "${buildOutputDir}" --output-filename ${NODE_BUILD_FILE_NAME} -t ${NODE_LIBARY_TYPE} -target 'node' -mode ${DEFAULT_WEBPACK_MODE}`);
25
+ }
26
+ return buildCommand;
27
+ }
28
+
29
+ async function buildNodeLambda(lambdaName, lambdaPath) {
30
+ console.log(chalk.blue(`Building the Node Lambda ${lambdaName}...`));
31
+
32
+ const buildOutputDir = `${LAMBDA_BUILD_DIR}/${lambdaName}`;
33
+
34
+ const buildCommand = await getWebpackBuildCommand(lambdaName, lambdaPath, buildOutputDir);
35
+ console.log(await executeCommand(buildCommand));
36
+ console.log(chalk.green('Successfully built the Lambda'));
37
+ return `${buildOutputDir}/${NODE_BUILD_FILE_NAME}`;
38
+ }
39
+
40
+ async function buildNodeLambdas() {
41
+ const lambdaPaths = findEntryPoints(NODE_RUNTIME_TF_VAR);
42
+ const normalizedLambdaNames = getNormalizedLambdaNames(lambdaPaths);
43
+ if (lambdaPaths.length > 0) {
44
+ if (FileHandler.doesPathExist('./node_modules')) {
45
+ console.log('node_modules exists');
46
+ } else {
47
+ console.log('node_modules does not exist');
48
+ console.log('Installing node_modules');
49
+ const { stdout, stderr } = await executeCommand('npm install');
50
+ console.log(stdout);
51
+ console.log(stderr);
52
+ }
53
+ }
54
+
55
+ lambdaPaths.forEach((lambdaPath, index) => {
56
+ buildNodeLambda(normalizedLambdaNames[index], lambdaPath);
57
+ });
58
+ }
59
+
60
+ module.exports = {
61
+ buildNodeLambda,
62
+ buildNodeLambdas,
63
+ };
@@ -0,0 +1,100 @@
1
+ const fs = require('fs');
2
+ const archiver = require('archiver');
3
+ const path = require('path');
4
+ const { promisify } = require('util');
5
+
6
+ const readdir = promisify(fs.readdir);
7
+ const stat = promisify(fs.stat);
8
+ const mkdir = promisify(fs.mkdir);
9
+ // const rename = promisify(fs.rename);
10
+
11
+ // TODO: Revist this later for hasing the build dir
12
+ // function getFileHash(filePath) {
13
+ // const data = fs.readFileSync(filePath);
14
+ // return crypto.createHash('md5').update(data).digest('hex');
15
+ // }
16
+
17
+ async function setTimestampToSameTimeRecursive(dirPath, timestamp) {
18
+ fs.readdirSync(dirPath).forEach((file) => {
19
+ const filePath = path.join(dirPath, file);
20
+ const statOutput = fs.statSync(filePath);
21
+
22
+ if (statOutput.isDirectory()) {
23
+ fs.utimesSync(filePath, timestamp, timestamp);
24
+ setTimestampToSameTimeRecursive(filePath, timestamp);
25
+ } else {
26
+ fs.utimesSync(filePath, timestamp, timestamp);
27
+ }
28
+ });
29
+ }
30
+
31
+ async function zipFolder(sourceFolder, destinationZip) {
32
+ return new Promise((resolve, reject) => {
33
+ const output = fs.createWriteStream(destinationZip);
34
+ const archive = archiver('zip');
35
+
36
+ output.on('close', async () => {
37
+ // TODO: Return to this if needed for hashing
38
+ // console.log("zipFileName")
39
+ // console.log(zipFileName)
40
+
41
+ // const zipHash = getFileHash(path.join(zipFileName))
42
+ // const zipName = await getZipName(zipFileName, "zipHash")
43
+ // await fs.renameSync(zipFileName, path.join(destinationZip, zipName))
44
+ // console.log(`${zipFileName} zip file has been created`)
45
+ resolve();
46
+ });
47
+
48
+ output.on('error', (err) => {
49
+ reject(err);
50
+ });
51
+
52
+ archive.pipe(output);
53
+ archive.directory(sourceFolder, false);
54
+ archive.finalize();
55
+ });
56
+ }
57
+
58
+ async function zipAndMoveFolders(sourceFolder, destinationFolder) {
59
+ const zipFiles = {}; // Object to store zip file information
60
+
61
+ try {
62
+ const ts = new Date(2020, 0, 1);
63
+ await setTimestampToSameTimeRecursive(sourceFolder, ts);
64
+ // Ensure the destination folder exists
65
+ await mkdir(destinationFolder, { recursive: true });
66
+
67
+ // Read all files and subdirectories in the source folder
68
+ const entries = await readdir(sourceFolder);
69
+ // eslint-disable-next-line
70
+ for (const entry of entries) {
71
+ const entryPath = path.join(sourceFolder, entry);
72
+ const stats = await stat(entryPath);
73
+
74
+ if (stats.isDirectory()) {
75
+ // If the entry is a directory, zip it and move the resulting zip file
76
+ const zipFileName = `${entry}.zip`;
77
+ const zipFilePath = path.join(destinationFolder, zipFileName);
78
+ await zipFolder(entryPath, zipFilePath, zipFileName);
79
+
80
+ // Add the zip file details to the object
81
+ zipFiles[entry] = {
82
+ name: zipFileName,
83
+ path: zipFilePath,
84
+ };
85
+ }
86
+ }
87
+ console.log('All folders have been zipped and moved successfully.');
88
+ } catch (error) {
89
+ console.error('Failed to zip and move folders:', error);
90
+ }
91
+ return zipFiles; // Return the JSON object
92
+ }
93
+ // TODO: Revist later
94
+ // async function getZipName(builtLambda, zipHash) {
95
+ // return `${builtLambda}_-_${zipHash}.zip`
96
+ // }
97
+
98
+ module.exports = {
99
+ zipAndMoveFolders,
100
+ };
package/src/index.js CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  const yargs = require('yargs');
4
4
  const chalk = require('chalk');
5
+ const path = require('path');
6
+ const fs = require('fs');
5
7
  const { zipAndMoveFolders } = require('./features/build/zip');
6
8
  const { buildNodeLambdas } = require('./features/build/node-build');
7
9
  const { deployLambda } = require('./features/deploy');
@@ -30,8 +32,19 @@ const argv = yargs
30
32
 
31
33
  async function executeUserCommand(userCommands) {
32
34
  if (userCommands.z || userCommands.zip) {
33
- zipAndMoveFolders('build', 'dist');
34
- console.log('zipping');
35
+ // Write the result to a JSON file
36
+ console.log('Zipping folders...');
37
+ const zipDetails = await zipAndMoveFolders('build', 'dist');
38
+
39
+ // Write the result to a JSON file
40
+ const resultFilePath = path.join(process.cwd(), 'zip-details.json');
41
+ await fs.promises.writeFile(
42
+ resultFilePath,
43
+ JSON.stringify(zipDetails, null, 2),
44
+ 'utf-8',
45
+ );
46
+
47
+ console.log(`Zipping complete. Details saved to ${resultFilePath}`);
35
48
  } else if (userCommands.d || userCommands.deploy) {
36
49
  console.log('deploying');
37
50
  await deployLambda();
package/.babelrc DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "presets": [
3
- "@babel/preset-env"
4
- ],
5
- "plugins": []
6
- }
7
-
package/.eslintrc.yaml DELETED
@@ -1,12 +0,0 @@
1
- extends:
2
- - airbnb-base
3
- - plugin:import/errors
4
- - plugin:import/warnings
5
- rules:
6
- prefer-destructuring: off
7
- no-template-curly-in-string: warn
8
- no-return-await: off
9
- no-await-in-loop: warn
10
- no-plusplus: off
11
- import/extensions: off
12
- import/no-unresolved: "off"
package/.gitlab-ci.yml DELETED
@@ -1,5 +0,0 @@
1
- include:
2
- - project: 'grp-development-utils/cicd-pipeline-utilities/node-cicd'
3
- ref: v1-latest
4
- file:
5
- - 'consumer/templates/node-package.yml'
package/.prettierrc DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "semi": false,
3
- "singleQuote": true,
4
- "tabWidth": 2,
5
- "useTabs": false
6
- }
package/jest.config.js DELETED
@@ -1,21 +0,0 @@
1
- module.exports = {
2
- roots: ['<rootDir>'],
3
- moduleFileExtensions: ['js', 'json'],
4
- testEnvironment: 'node',
5
- testRegex: '\\.test\\.js$',
6
- transform: {
7
- '^.+\\.js$': 'babel-jest',
8
- },
9
- collectCoverage: true,
10
- coverageDirectory: 'test/coverage',
11
- collectCoverageFrom: ['<rootDir>/src/**/*.js'],
12
- coveragePathIgnorePatterns: ['/node_modules/', '/build/', '/dist/'], // Add paths to ignore here
13
- coverageThreshold: {
14
- global: {
15
- branches: 0,
16
- functions: 0,
17
- lines: 0,
18
- statements: 0,
19
- },
20
- },
21
- };
package/test/main.test.js DELETED
@@ -1,3 +0,0 @@
1
- test('adds 1 + 2 to equal 3', () => {
2
- expect(1+2).toBe(3);
3
- });