@datadog/datadog-ci 2.18.0 → 2.18.1
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/dist/commands/cloud-run/cli.d.ts +1 -0
- package/dist/commands/cloud-run/cli.js +5 -0
- package/dist/commands/cloud-run/cli.js.map +1 -0
- package/dist/commands/cloud-run/constants.d.ts +1 -0
- package/dist/commands/cloud-run/constants.js +22 -0
- package/dist/commands/cloud-run/constants.js.map +1 -0
- package/dist/commands/cloud-run/flare.d.ts +60 -0
- package/dist/commands/cloud-run/flare.js +369 -0
- package/dist/commands/cloud-run/flare.js.map +1 -0
- package/dist/commands/cloud-run/interfaces.d.ts +27 -0
- package/dist/commands/cloud-run/interfaces.js +3 -0
- package/dist/commands/cloud-run/interfaces.js.map +1 -0
- package/dist/commands/cloud-run/renderer.d.ts +4 -0
- package/dist/commands/cloud-run/renderer.js +38 -0
- package/dist/commands/cloud-run/renderer.js.map +1 -0
- package/dist/commands/lambda/constants.d.ts +10 -8
- package/dist/commands/lambda/constants.js +41 -25
- package/dist/commands/lambda/constants.js.map +1 -1
- package/dist/commands/lambda/flare.d.ts +10 -45
- package/dist/commands/lambda/flare.js +121 -215
- package/dist/commands/lambda/flare.js.map +1 -1
- package/dist/commands/lambda/functions/commons.d.ts +7 -13
- package/dist/commands/lambda/functions/commons.js +39 -56
- package/dist/commands/lambda/functions/commons.js.map +1 -1
- package/dist/commands/lambda/functions/instrument.js +46 -45
- package/dist/commands/lambda/functions/instrument.js.map +1 -1
- package/dist/commands/lambda/functions/uninstrument.js +29 -28
- package/dist/commands/lambda/functions/uninstrument.js.map +1 -1
- package/dist/commands/lambda/instrument.js +19 -16
- package/dist/commands/lambda/instrument.js.map +1 -1
- package/dist/commands/lambda/prompt.d.ts +0 -2
- package/dist/commands/lambda/prompt.js +16 -35
- package/dist/commands/lambda/prompt.js.map +1 -1
- package/dist/commands/lambda/renderers/common-renderer.d.ts +0 -26
- package/dist/commands/lambda/renderers/common-renderer.js +4 -32
- package/dist/commands/lambda/renderers/common-renderer.js.map +1 -1
- package/dist/commands/lambda/renderers/instrument-uninstrument-renderer.js +27 -27
- package/dist/commands/lambda/renderers/instrument-uninstrument-renderer.js.map +1 -1
- package/dist/commands/lambda/uninstrument.js +9 -7
- package/dist/commands/lambda/uninstrument.js.map +1 -1
- package/dist/commands/sarif/api.js +2 -18
- package/dist/commands/sarif/api.js.map +1 -1
- package/dist/commands/synthetics/interfaces.d.ts +2 -1
- package/dist/commands/synthetics/interfaces.js.map +1 -1
- package/dist/commands/synthetics/reporters/default.js +3 -5
- package/dist/commands/synthetics/reporters/default.js.map +1 -1
- package/dist/commands/synthetics/utils.js +1 -0
- package/dist/commands/synthetics/utils.js.map +1 -1
- package/dist/constants.d.ts +10 -0
- package/dist/constants.js +14 -1
- package/dist/constants.js.map +1 -1
- package/dist/helpers/flare.d.ts +19 -0
- package/dist/helpers/flare.js +81 -0
- package/dist/helpers/flare.js.map +1 -0
- package/dist/helpers/fs.d.ts +31 -0
- package/dist/helpers/fs.js +117 -0
- package/dist/helpers/fs.js.map +1 -0
- package/dist/helpers/prompt.d.ts +6 -0
- package/dist/helpers/prompt.js +39 -0
- package/dist/helpers/prompt.js.map +1 -0
- package/dist/helpers/renderer.d.ts +36 -0
- package/dist/helpers/renderer.js +47 -0
- package/dist/helpers/renderer.js.map +1 -0
- package/dist/helpers/utils.d.ts +8 -0
- package/dist/helpers/utils.js +40 -1
- package/dist/helpers/utils.js.map +1 -1
- package/package.json +8 -2
- package/dist/commands/lambda/renderers/flare-renderer.d.ts +0 -9
- package/dist/commands/lambda/renderers/flare-renderer.js +0 -22
- package/dist/commands/lambda/renderers/flare-renderer.js.map +0 -1
- package/dist/helpers/file.d.ts +0 -1
- package/dist/helpers/file.js +0 -9
- package/dist/helpers/file.js.map +0 -1
|
@@ -31,33 +31,31 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
31
31
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
32
32
|
};
|
|
33
33
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
-
exports.
|
|
34
|
+
exports.generateInsightsFile = exports.getFramework = exports.sleep = exports.convertToCSV = exports.getUniqueFileNames = exports.getTags = exports.getAllLogs = exports.getLogEvents = exports.getLogStreamNames = exports.validateFilePath = exports.getProjectFiles = exports.validateStartEndFlags = exports.LambdaFlareCommand = void 0;
|
|
35
35
|
const fs = __importStar(require("fs"));
|
|
36
36
|
const path = __importStar(require("path"));
|
|
37
37
|
const util_1 = __importDefault(require("util"));
|
|
38
38
|
const client_cloudwatch_logs_1 = require("@aws-sdk/client-cloudwatch-logs");
|
|
39
39
|
const client_lambda_1 = require("@aws-sdk/client-lambda");
|
|
40
|
-
const axios_1 = __importDefault(require("axios"));
|
|
41
40
|
const chalk_1 = __importDefault(require("chalk"));
|
|
42
41
|
const clipanion_1 = require("clipanion");
|
|
43
|
-
const form_data_1 = __importDefault(require("form-data"));
|
|
44
|
-
const jszip_1 = __importDefault(require("jszip"));
|
|
45
42
|
const constants_1 = require("../../constants");
|
|
46
|
-
const
|
|
43
|
+
const flare_1 = require("../../helpers/flare");
|
|
44
|
+
const fs_1 = require("../../helpers/fs");
|
|
45
|
+
const prompt_1 = require("../../helpers/prompt");
|
|
46
|
+
const helpersRenderer = __importStar(require("../../helpers/renderer"));
|
|
47
|
+
const utils_1 = require("../../helpers/utils");
|
|
47
48
|
const constants_2 = require("./constants");
|
|
48
49
|
const commons_1 = require("./functions/commons");
|
|
49
|
-
const
|
|
50
|
+
const prompt_2 = require("./prompt");
|
|
50
51
|
const commonRenderer = __importStar(require("./renderers/common-renderer"));
|
|
51
|
-
const
|
|
52
|
-
const { version } = require('../../../package.json');
|
|
53
|
-
const ENDPOINT_PATH = '/api/ui/support/serverless/flare';
|
|
54
|
-
const FLARE_OUTPUT_DIRECTORY = '.datadog-ci';
|
|
55
|
-
const LOGS_DIRECTORY = 'logs';
|
|
52
|
+
const version = require('../../../package.json').version;
|
|
56
53
|
const PROJECT_FILES_DIRECTORY = 'project_files';
|
|
57
54
|
const ADDITIONAL_FILES_DIRECTORY = 'additional_files';
|
|
58
55
|
const FUNCTION_CONFIG_FILE_NAME = 'function_config.json';
|
|
59
56
|
const TAGS_FILE_NAME = 'tags.json';
|
|
60
|
-
const
|
|
57
|
+
const INSIGHTS_FILE_NAME = 'INSIGHTS.md';
|
|
58
|
+
const FLARE_ZIP_FILE_NAME = 'lambda-flare-output.zip';
|
|
61
59
|
const MAX_LOG_STREAMS = 50;
|
|
62
60
|
const DEFAULT_LOG_STREAMS = 3;
|
|
63
61
|
const MAX_LOG_EVENTS_PER_STREAM = 1000;
|
|
@@ -69,16 +67,17 @@ class LambdaFlareCommand extends clipanion_1.Command {
|
|
|
69
67
|
}
|
|
70
68
|
/**
|
|
71
69
|
* Entry point for the `lambda flare` command.
|
|
72
|
-
* Gathers
|
|
70
|
+
* Gathers config, logs, tags, project files, and more from a
|
|
71
|
+
* Lambda function and sends them to Datadog support.
|
|
73
72
|
* @returns 0 if the command ran successfully, 1 otherwise.
|
|
74
73
|
*/
|
|
75
74
|
execute() {
|
|
76
75
|
var _a, _b, _c;
|
|
77
76
|
return __awaiter(this, void 0, void 0, function* () {
|
|
78
|
-
this.context.stdout.write(
|
|
77
|
+
this.context.stdout.write(helpersRenderer.renderFlareHeader('Lambda', this.isDryRun));
|
|
79
78
|
// Validate function name
|
|
80
79
|
if (this.functionName === undefined) {
|
|
81
|
-
this.context.stderr.write(
|
|
80
|
+
this.context.stderr.write(helpersRenderer.renderError('No function name specified. [-f,--function]'));
|
|
82
81
|
return 1;
|
|
83
82
|
}
|
|
84
83
|
const errorMessages = [];
|
|
@@ -88,18 +87,18 @@ class LambdaFlareCommand extends clipanion_1.Command {
|
|
|
88
87
|
errorMessages.push(commonRenderer.renderNoDefaultRegionSpecifiedError());
|
|
89
88
|
}
|
|
90
89
|
// Validate Datadog API key
|
|
91
|
-
this.apiKey = (_c = process.env[
|
|
90
|
+
this.apiKey = (_c = process.env[constants_1.CI_API_KEY_ENV_VAR]) !== null && _c !== void 0 ? _c : process.env[constants_1.API_KEY_ENV_VAR];
|
|
92
91
|
if (this.apiKey === undefined) {
|
|
93
|
-
errorMessages.push(
|
|
92
|
+
errorMessages.push(helpersRenderer.renderError('No Datadog API key specified. Set an API key with the DATADOG_API_KEY environment variable.'));
|
|
94
93
|
}
|
|
95
94
|
if (!this.isDryRun) {
|
|
96
95
|
// Validate case ID
|
|
97
96
|
if (this.caseId === undefined) {
|
|
98
|
-
errorMessages.push(
|
|
97
|
+
errorMessages.push(helpersRenderer.renderError('No case ID specified. [-c,--case-id]'));
|
|
99
98
|
}
|
|
100
99
|
// Validate email
|
|
101
100
|
if (this.email === undefined) {
|
|
102
|
-
errorMessages.push(
|
|
101
|
+
errorMessages.push(helpersRenderer.renderError('No email specified. [-e,--email]'));
|
|
103
102
|
}
|
|
104
103
|
}
|
|
105
104
|
// Validate start/end flags if both are specified
|
|
@@ -111,7 +110,7 @@ class LambdaFlareCommand extends clipanion_1.Command {
|
|
|
111
110
|
}
|
|
112
111
|
catch (err) {
|
|
113
112
|
if (err instanceof Error) {
|
|
114
|
-
errorMessages.push(
|
|
113
|
+
errorMessages.push(helpersRenderer.renderError(err.message));
|
|
115
114
|
}
|
|
116
115
|
}
|
|
117
116
|
if (errorMessages.length > 0) {
|
|
@@ -127,18 +126,18 @@ class LambdaFlareCommand extends clipanion_1.Command {
|
|
|
127
126
|
}
|
|
128
127
|
catch (err) {
|
|
129
128
|
if (err instanceof Error) {
|
|
130
|
-
this.context.stderr.write(
|
|
129
|
+
this.context.stderr.write(helpersRenderer.renderError(err.message));
|
|
131
130
|
}
|
|
132
131
|
return 1;
|
|
133
132
|
}
|
|
134
133
|
if (this.credentials === undefined) {
|
|
135
134
|
this.context.stdout.write('\n' + commonRenderer.renderNoAWSCredentialsFound());
|
|
136
135
|
try {
|
|
137
|
-
yield
|
|
136
|
+
yield prompt_2.requestAWSCredentials();
|
|
138
137
|
}
|
|
139
138
|
catch (err) {
|
|
140
139
|
if (err instanceof Error) {
|
|
141
|
-
this.context.stderr.write(
|
|
140
|
+
this.context.stderr.write(helpersRenderer.renderError(err.message));
|
|
142
141
|
}
|
|
143
142
|
return 1;
|
|
144
143
|
}
|
|
@@ -156,11 +155,11 @@ class LambdaFlareCommand extends clipanion_1.Command {
|
|
|
156
155
|
}
|
|
157
156
|
catch (err) {
|
|
158
157
|
if (err instanceof Error) {
|
|
159
|
-
this.context.stderr.write(
|
|
158
|
+
this.context.stderr.write(helpersRenderer.renderError(`Unable to get Lambda function configuration: ${err.message}`));
|
|
160
159
|
}
|
|
161
160
|
return 1;
|
|
162
161
|
}
|
|
163
|
-
config =
|
|
162
|
+
config = commons_1.maskConfig(config);
|
|
164
163
|
const configStr = util_1.default.inspect(config, false, undefined, true);
|
|
165
164
|
this.context.stdout.write(`\n${configStr}\n`);
|
|
166
165
|
// Get project files
|
|
@@ -168,7 +167,7 @@ class LambdaFlareCommand extends clipanion_1.Command {
|
|
|
168
167
|
const projectFilePaths = yield exports.getProjectFiles();
|
|
169
168
|
let projectFilesMessage = chalk_1.default.bold(`\n✅ Found project file(s) in ${process.cwd()}:\n`);
|
|
170
169
|
if (projectFilePaths.size === 0) {
|
|
171
|
-
projectFilesMessage =
|
|
170
|
+
projectFilesMessage = helpersRenderer.renderSoftWarning('No project files found.');
|
|
172
171
|
}
|
|
173
172
|
this.context.stdout.write(projectFilesMessage);
|
|
174
173
|
for (const filePath of projectFilePaths) {
|
|
@@ -184,7 +183,7 @@ class LambdaFlareCommand extends clipanion_1.Command {
|
|
|
184
183
|
}
|
|
185
184
|
catch (err) {
|
|
186
185
|
if (err instanceof Error) {
|
|
187
|
-
this.context.stderr.write(
|
|
186
|
+
this.context.stderr.write(helpersRenderer.renderError(err.message));
|
|
188
187
|
}
|
|
189
188
|
return 1;
|
|
190
189
|
}
|
|
@@ -192,11 +191,11 @@ class LambdaFlareCommand extends clipanion_1.Command {
|
|
|
192
191
|
this.context.stdout.write('\n');
|
|
193
192
|
let filePath;
|
|
194
193
|
try {
|
|
195
|
-
filePath = yield
|
|
194
|
+
filePath = yield prompt_2.requestFilePath();
|
|
196
195
|
}
|
|
197
196
|
catch (err) {
|
|
198
197
|
if (err instanceof Error) {
|
|
199
|
-
this.context.stderr.write(
|
|
198
|
+
this.context.stderr.write(helpersRenderer.renderError(err.message));
|
|
200
199
|
}
|
|
201
200
|
return 1;
|
|
202
201
|
}
|
|
@@ -228,13 +227,13 @@ class LambdaFlareCommand extends clipanion_1.Command {
|
|
|
228
227
|
}
|
|
229
228
|
catch (err) {
|
|
230
229
|
if (err instanceof Error) {
|
|
231
|
-
this.context.stderr.write(
|
|
230
|
+
this.context.stderr.write(helpersRenderer.renderError(err.message));
|
|
232
231
|
}
|
|
233
232
|
return 1;
|
|
234
233
|
}
|
|
235
234
|
const tagsLength = Object.keys(tags).length;
|
|
236
235
|
if (tagsLength === 0) {
|
|
237
|
-
this.context.stdout.write(
|
|
236
|
+
this.context.stdout.write(helpersRenderer.renderSoftWarning(`No resource tags were found.`));
|
|
238
237
|
}
|
|
239
238
|
else {
|
|
240
239
|
this.context.stdout.write(`Found ${tagsLength} resource tag(s).\n`);
|
|
@@ -248,7 +247,7 @@ class LambdaFlareCommand extends clipanion_1.Command {
|
|
|
248
247
|
}
|
|
249
248
|
catch (err) {
|
|
250
249
|
if (err instanceof Error) {
|
|
251
|
-
this.context.stderr.write(
|
|
250
|
+
this.context.stderr.write(helpersRenderer.renderError(err.message));
|
|
252
251
|
}
|
|
253
252
|
return 1;
|
|
254
253
|
}
|
|
@@ -258,25 +257,25 @@ class LambdaFlareCommand extends clipanion_1.Command {
|
|
|
258
257
|
if (this.withLogs) {
|
|
259
258
|
let message = chalk_1.default.bold('\n✅ Found log streams:\n');
|
|
260
259
|
if (logs.size === 0) {
|
|
261
|
-
message =
|
|
260
|
+
message = helpersRenderer.renderSoftWarning('No CloudWatch log streams were found. Logs will not be retrieved or sent.');
|
|
262
261
|
}
|
|
263
262
|
this.context.stdout.write(message);
|
|
264
263
|
for (const [logStreamName, logEvents] of logs) {
|
|
265
264
|
let warningMessage = '\n';
|
|
266
265
|
if (logEvents.length === 0) {
|
|
267
|
-
warningMessage =
|
|
266
|
+
warningMessage = ` - ${helpersRenderer.renderSoftWarning('No log events found in this stream')}`;
|
|
268
267
|
}
|
|
269
268
|
this.context.stdout.write(`• ${logStreamName}${warningMessage}`);
|
|
270
269
|
}
|
|
271
270
|
}
|
|
272
271
|
// Create folders
|
|
273
|
-
const rootFolderPath = path.join(process.cwd(), FLARE_OUTPUT_DIRECTORY);
|
|
274
|
-
const logsFolderPath = path.join(rootFolderPath, LOGS_DIRECTORY);
|
|
272
|
+
const rootFolderPath = path.join(process.cwd(), constants_1.FLARE_OUTPUT_DIRECTORY);
|
|
273
|
+
const logsFolderPath = path.join(rootFolderPath, constants_1.LOGS_DIRECTORY);
|
|
275
274
|
const projectFilesFolderPath = path.join(rootFolderPath, PROJECT_FILES_DIRECTORY);
|
|
276
275
|
const additionalFilesFolderPath = path.join(rootFolderPath, ADDITIONAL_FILES_DIRECTORY);
|
|
277
276
|
this.context.stdout.write(chalk_1.default.bold(`\n💾 Saving files to ${rootFolderPath}...\n`));
|
|
278
277
|
if (fs.existsSync(rootFolderPath)) {
|
|
279
|
-
|
|
278
|
+
fs_1.deleteFolder(rootFolderPath);
|
|
280
279
|
}
|
|
281
280
|
const subFolders = [];
|
|
282
281
|
if (logs.size > 0) {
|
|
@@ -288,15 +287,15 @@ class LambdaFlareCommand extends clipanion_1.Command {
|
|
|
288
287
|
if (additionalFilePaths.size > 0) {
|
|
289
288
|
subFolders.push(additionalFilesFolderPath);
|
|
290
289
|
}
|
|
291
|
-
|
|
290
|
+
fs_1.createDirectories(rootFolderPath, subFolders);
|
|
292
291
|
// Write config file
|
|
293
292
|
const configFilePath = path.join(rootFolderPath, FUNCTION_CONFIG_FILE_NAME);
|
|
294
|
-
|
|
293
|
+
fs_1.writeFile(configFilePath, JSON.stringify(config, undefined, 2));
|
|
295
294
|
this.context.stdout.write(`• Saved function config to ./${FUNCTION_CONFIG_FILE_NAME}\n`);
|
|
296
295
|
// Write tags file
|
|
297
296
|
if (tagsLength > 0) {
|
|
298
297
|
const tagsFilePath = path.join(rootFolderPath, TAGS_FILE_NAME);
|
|
299
|
-
|
|
298
|
+
fs_1.writeFile(tagsFilePath, JSON.stringify(tags, undefined, 2));
|
|
300
299
|
this.context.stdout.write(`• Saved tags to ./${TAGS_FILE_NAME}\n`);
|
|
301
300
|
}
|
|
302
301
|
// Write log files
|
|
@@ -306,8 +305,8 @@ class LambdaFlareCommand extends clipanion_1.Command {
|
|
|
306
305
|
}
|
|
307
306
|
const logFilePath = path.join(logsFolderPath, `${logStreamName.split('/').join('-')}.csv`);
|
|
308
307
|
const data = exports.convertToCSV(logEvents);
|
|
309
|
-
|
|
310
|
-
this.context.stdout.write(`• Saved logs to ./${LOGS_DIRECTORY}/${logStreamName}\n`);
|
|
308
|
+
fs_1.writeFile(logFilePath, data);
|
|
309
|
+
this.context.stdout.write(`• Saved logs to ./${constants_1.LOGS_DIRECTORY}/${logStreamName}\n`);
|
|
311
310
|
// Sleep for 1 millisecond so creation times are different
|
|
312
311
|
// This allows the logs to be sorted by creation time by the support team
|
|
313
312
|
yield exports.sleep(1);
|
|
@@ -327,6 +326,10 @@ class LambdaFlareCommand extends clipanion_1.Command {
|
|
|
327
326
|
fs.copyFileSync(originalFilePath, newFilePath);
|
|
328
327
|
this.context.stdout.write(`• Copied ${originalFileName} to ./${ADDITIONAL_FILES_DIRECTORY}/${newFileName}\n`);
|
|
329
328
|
}
|
|
329
|
+
// Write insights file
|
|
330
|
+
const insightsFilePath = path.join(rootFolderPath, INSIGHTS_FILE_NAME);
|
|
331
|
+
exports.generateInsightsFile(insightsFilePath, this.isDryRun, config);
|
|
332
|
+
this.context.stdout.write(`• Saved insights file to ./${INSIGHTS_FILE_NAME}\n`);
|
|
330
333
|
// Exit if dry run
|
|
331
334
|
const outputMsg = `\nℹ️ Your output files are located at: ${rootFolderPath}\n\n`;
|
|
332
335
|
if (this.isDryRun) {
|
|
@@ -336,34 +339,25 @@ class LambdaFlareCommand extends clipanion_1.Command {
|
|
|
336
339
|
}
|
|
337
340
|
// Confirm before sending
|
|
338
341
|
this.context.stdout.write('\n');
|
|
339
|
-
|
|
340
|
-
try {
|
|
341
|
-
confirmSendFiles = yield prompt_1.requestConfirmation('Are you sure you want to send the flare file to Datadog Support?', false);
|
|
342
|
-
}
|
|
343
|
-
catch (err) {
|
|
344
|
-
if (err instanceof Error) {
|
|
345
|
-
this.context.stderr.write(commonRenderer.renderError(err.message));
|
|
346
|
-
}
|
|
347
|
-
return 1;
|
|
348
|
-
}
|
|
342
|
+
const confirmSendFiles = yield prompt_1.requestConfirmation('Are you sure you want to send the flare file to Datadog Support?', false);
|
|
349
343
|
if (!confirmSendFiles) {
|
|
350
344
|
this.context.stdout.write('\n🚫 The flare files were not sent based on your selection.');
|
|
351
345
|
this.context.stdout.write(outputMsg);
|
|
352
346
|
return 0;
|
|
353
347
|
}
|
|
354
348
|
// Zip folder
|
|
355
|
-
const zipPath = path.join(rootFolderPath,
|
|
356
|
-
yield
|
|
349
|
+
const zipPath = path.join(rootFolderPath, FLARE_ZIP_FILE_NAME);
|
|
350
|
+
yield fs_1.zipContents(rootFolderPath, zipPath);
|
|
357
351
|
// Send to Datadog
|
|
358
352
|
this.context.stdout.write(chalk_1.default.bold('\n🚀 Sending to Datadog Support...\n'));
|
|
359
|
-
yield
|
|
353
|
+
yield flare_1.sendToDatadog(zipPath, this.caseId, this.email, this.apiKey, rootFolderPath);
|
|
360
354
|
this.context.stdout.write(chalk_1.default.bold('\n✅ Successfully sent flare file to Datadog Support!\n'));
|
|
361
355
|
// Delete contents
|
|
362
|
-
|
|
356
|
+
fs_1.deleteFolder(rootFolderPath);
|
|
363
357
|
}
|
|
364
358
|
catch (err) {
|
|
365
359
|
if (err instanceof Error) {
|
|
366
|
-
this.context.stderr.write(
|
|
360
|
+
this.context.stderr.write(helpersRenderer.renderError(err.message));
|
|
367
361
|
}
|
|
368
362
|
return 1;
|
|
369
363
|
}
|
|
@@ -405,57 +399,6 @@ const validateStartEndFlags = (start, end) => {
|
|
|
405
399
|
return [startMillis, endMillis];
|
|
406
400
|
};
|
|
407
401
|
exports.validateStartEndFlags = validateStartEndFlags;
|
|
408
|
-
/**
|
|
409
|
-
* Mask the environment variables in a Lambda function configuration
|
|
410
|
-
* @param config
|
|
411
|
-
*/
|
|
412
|
-
const maskConfig = (config) => {
|
|
413
|
-
var _a;
|
|
414
|
-
const environmentVariables = (_a = config.Environment) === null || _a === void 0 ? void 0 : _a.Variables;
|
|
415
|
-
if (!environmentVariables) {
|
|
416
|
-
return config;
|
|
417
|
-
}
|
|
418
|
-
const replacer = commons_1.maskStringifiedEnvVar(environmentVariables);
|
|
419
|
-
const stringifiedConfig = JSON.stringify(config, replacer);
|
|
420
|
-
return JSON.parse(stringifiedConfig);
|
|
421
|
-
};
|
|
422
|
-
exports.maskConfig = maskConfig;
|
|
423
|
-
/**
|
|
424
|
-
* Delete a folder and all its contents
|
|
425
|
-
* @param folderPath the folder to delete
|
|
426
|
-
* @throws Error if the deletion fails
|
|
427
|
-
*/
|
|
428
|
-
const deleteFolder = (folderPath) => {
|
|
429
|
-
try {
|
|
430
|
-
fs.rmSync(folderPath, { recursive: true, force: true });
|
|
431
|
-
}
|
|
432
|
-
catch (err) {
|
|
433
|
-
if (err instanceof Error) {
|
|
434
|
-
throw Error(`Failed to delete files located at ${folderPath}: ${err.message}`);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
};
|
|
438
|
-
exports.deleteFolder = deleteFolder;
|
|
439
|
-
/**
|
|
440
|
-
* Creates the root folder and any subfolders
|
|
441
|
-
* @param rootFolderPath path to the root folder
|
|
442
|
-
* @param subFolders paths to any subfolders to be created
|
|
443
|
-
* @throws Error if the root folder cannot be deleted or folders cannot be created
|
|
444
|
-
*/
|
|
445
|
-
const createDirectories = (rootFolderPath, subFolders) => {
|
|
446
|
-
try {
|
|
447
|
-
fs.mkdirSync(rootFolderPath);
|
|
448
|
-
for (const subFolder of subFolders) {
|
|
449
|
-
fs.mkdirSync(subFolder);
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
catch (err) {
|
|
453
|
-
if (err instanceof Error) {
|
|
454
|
-
throw Error(`Unable to create directories: ${err.message}`);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
};
|
|
458
|
-
exports.createDirectories = createDirectories;
|
|
459
402
|
/**
|
|
460
403
|
* Searches current directory for project files
|
|
461
404
|
* @returns a set of file paths of project files
|
|
@@ -484,11 +427,11 @@ const validateFilePath = (filePath, projectFilePaths, additionalFiles) => {
|
|
|
484
427
|
const originalPath = filePath;
|
|
485
428
|
filePath = fs.existsSync(filePath) ? filePath : path.join(process.cwd(), filePath);
|
|
486
429
|
if (!fs.existsSync(filePath)) {
|
|
487
|
-
throw Error(
|
|
430
|
+
throw Error(helpersRenderer.renderError(`File path '${originalPath}' not found. Please try again.`));
|
|
488
431
|
}
|
|
489
432
|
filePath = path.resolve(filePath);
|
|
490
433
|
if (projectFilePaths.has(filePath) || additionalFiles.has(filePath)) {
|
|
491
|
-
throw Error(
|
|
434
|
+
throw Error(helpersRenderer.renderSoftWarning(`File '${filePath}' has already been added.`));
|
|
492
435
|
}
|
|
493
436
|
return filePath;
|
|
494
437
|
};
|
|
@@ -636,23 +579,6 @@ const getTags = (lambdaClient, region, arn) => __awaiter(void 0, void 0, void 0,
|
|
|
636
579
|
}
|
|
637
580
|
});
|
|
638
581
|
exports.getTags = getTags;
|
|
639
|
-
/**
|
|
640
|
-
* Write the function config to a file
|
|
641
|
-
* @param filePath path to the file
|
|
642
|
-
* @param data the data to write
|
|
643
|
-
* @throws Error if the file cannot be written
|
|
644
|
-
*/
|
|
645
|
-
const writeFile = (filePath, data) => {
|
|
646
|
-
try {
|
|
647
|
-
fs.writeFileSync(filePath, data);
|
|
648
|
-
}
|
|
649
|
-
catch (err) {
|
|
650
|
-
if (err instanceof Error) {
|
|
651
|
-
throw Error(`Unable to create function configuration file: ${err.message}`);
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
};
|
|
655
|
-
exports.writeFile = writeFile;
|
|
656
582
|
/**
|
|
657
583
|
* Generate unique file names
|
|
658
584
|
* If the original file name is unique, keep it as is
|
|
@@ -716,101 +642,81 @@ const sleep = (ms) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
716
642
|
});
|
|
717
643
|
exports.sleep = sleep;
|
|
718
644
|
/**
|
|
719
|
-
*
|
|
720
|
-
* @
|
|
721
|
-
* @param zipPath path to save the zip file
|
|
722
|
-
* @throws Error if the zip fails
|
|
645
|
+
* Get the framework used based on the files in the directory
|
|
646
|
+
* @returns the framework used or undefined if no framework is found
|
|
723
647
|
*/
|
|
724
|
-
const
|
|
725
|
-
const
|
|
726
|
-
const
|
|
727
|
-
|
|
728
|
-
|
|
648
|
+
const getFramework = () => {
|
|
649
|
+
const frameworks = new Set();
|
|
650
|
+
const files = fs.readdirSync(process.cwd());
|
|
651
|
+
files.forEach((file) => {
|
|
652
|
+
if (constants_2.FRAMEWORK_FILES_MAPPING.has(file)) {
|
|
653
|
+
frameworks.add(constants_2.FRAMEWORK_FILES_MAPPING.get(file));
|
|
729
654
|
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
}
|
|
734
|
-
const contents = fs.readdirSync(folderPath);
|
|
735
|
-
for (const item of contents) {
|
|
736
|
-
const fullPath = path.join(folderPath, item);
|
|
737
|
-
const file = fs.statSync(fullPath);
|
|
738
|
-
if (file.isDirectory()) {
|
|
739
|
-
addFolderToZip(fullPath);
|
|
740
|
-
}
|
|
741
|
-
else {
|
|
742
|
-
const data = fs.readFileSync(fullPath);
|
|
743
|
-
zip.file(path.relative(rootFolderPath, fullPath), data);
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
};
|
|
747
|
-
try {
|
|
748
|
-
addFolderToZip(rootFolderPath);
|
|
749
|
-
const zipContent = yield zip.generateAsync({ type: 'nodebuffer' });
|
|
750
|
-
fs.writeFileSync(zipPath, zipContent);
|
|
751
|
-
}
|
|
752
|
-
catch (err) {
|
|
753
|
-
if (err instanceof Error) {
|
|
754
|
-
throw Error(`Unable to zip the flare files: ${err.message}`);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
});
|
|
758
|
-
exports.zipContents = zipContents;
|
|
759
|
-
/**
|
|
760
|
-
* Calculates the full endpoint URL
|
|
761
|
-
* @throws Error if the site is invalid
|
|
762
|
-
* @returns the full endpoint URL
|
|
763
|
-
*/
|
|
764
|
-
const getEndpointUrl = () => {
|
|
765
|
-
var _a, _b;
|
|
766
|
-
const baseUrl = (_b = (_a = process.env[constants_2.CI_SITE_ENV_VAR]) !== null && _a !== void 0 ? _a : process.env[constants_2.SITE_ENV_VAR]) !== null && _b !== void 0 ? _b : constants_1.DATADOG_SITE_US1;
|
|
767
|
-
// The DNS doesn't redirect to the proper endpoint when a subdomain is not present in the baseUrl.
|
|
768
|
-
// There is a DNS inconsistency
|
|
769
|
-
let endpointUrl = baseUrl;
|
|
770
|
-
if ([constants_1.DATADOG_SITE_US1, constants_1.DATADOG_SITE_EU1, constants_1.DATADOG_SITE_GOV].includes(baseUrl)) {
|
|
771
|
-
endpointUrl = 'app.' + baseUrl;
|
|
772
|
-
}
|
|
773
|
-
if (!validation_1.isValidDatadogSite(baseUrl)) {
|
|
774
|
-
throw Error(`Invalid site: ${baseUrl}. Must be one of: ${constants_1.DATADOG_SITES.join(', ')}`);
|
|
655
|
+
});
|
|
656
|
+
if (frameworks.size > 0) {
|
|
657
|
+
return Array.from(frameworks).join(', ');
|
|
775
658
|
}
|
|
776
|
-
return
|
|
659
|
+
return constants_2.DeploymentFrameworks.Unknown;
|
|
777
660
|
};
|
|
778
|
-
exports.
|
|
661
|
+
exports.getFramework = getFramework;
|
|
779
662
|
/**
|
|
780
|
-
*
|
|
781
|
-
* @param
|
|
782
|
-
* @param
|
|
783
|
-
* @param
|
|
784
|
-
* @param apiKey
|
|
785
|
-
* @param rootFolderPath
|
|
786
|
-
* @throws Error if the request fails
|
|
663
|
+
* Generate the insights file
|
|
664
|
+
* @param insightsFilePath path to the insights file
|
|
665
|
+
* @param isDryRun whether or not this is a dry run
|
|
666
|
+
* @param config Lambda function configuration
|
|
787
667
|
*/
|
|
788
|
-
const
|
|
789
|
-
var _b, _c, _d;
|
|
790
|
-
const
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
668
|
+
const generateInsightsFile = (insightsFilePath, isDryRun, config) => {
|
|
669
|
+
var _a, _b, _c, _d, _e;
|
|
670
|
+
const lines = [];
|
|
671
|
+
// Header
|
|
672
|
+
lines.push('# Flare Insights');
|
|
673
|
+
lines.push('\n_Autogenerated file from `lambda flare`_ ');
|
|
674
|
+
if (isDryRun) {
|
|
675
|
+
lines.push('_This command was run in dry mode._');
|
|
676
|
+
}
|
|
677
|
+
// AWS Lambda Configuration
|
|
678
|
+
lines.push('\n## AWS Lambda Configuration');
|
|
679
|
+
lines.push(`**Function Name**: \`${config.FunctionName}\` `);
|
|
680
|
+
lines.push(`**Function ARN**: \`${config.FunctionArn}\` `);
|
|
681
|
+
lines.push(`**Runtime**: \`${config.Runtime}\` `);
|
|
682
|
+
lines.push(`**Handler**: \`${config.Handler}\` `);
|
|
683
|
+
lines.push(`**Timeout**: \`${config.Timeout}\` `);
|
|
684
|
+
lines.push(`**Memory Size**: \`${config.MemorySize}\` `);
|
|
685
|
+
const architectures = (_a = config.Architectures) !== null && _a !== void 0 ? _a : ['Unknown'];
|
|
686
|
+
lines.push(`**Architecture**: \`${architectures.join(', ')}\` `);
|
|
687
|
+
lines.push('**Environment Variables**:');
|
|
688
|
+
const envVars = Object.entries((_c = (_b = config.Environment) === null || _b === void 0 ? void 0 : _b.Variables) !== null && _c !== void 0 ? _c : {});
|
|
689
|
+
if (envVars.length === 0) {
|
|
690
|
+
lines.push('- No environment variables found.');
|
|
691
|
+
}
|
|
692
|
+
for (const [key, value] of envVars) {
|
|
693
|
+
lines.push(`- \`${key}\`: \`${value}\``);
|
|
694
|
+
}
|
|
695
|
+
lines.push('\n**Layers**:');
|
|
696
|
+
const layers = (_d = config.Layers) !== null && _d !== void 0 ? _d : [];
|
|
697
|
+
if (layers.length === 0) {
|
|
698
|
+
lines.push(' - No layers found.');
|
|
699
|
+
}
|
|
700
|
+
let codeSize = (_e = config.CodeSize) !== null && _e !== void 0 ? _e : 0;
|
|
701
|
+
layers.forEach((layer) => {
|
|
702
|
+
var _a, _b;
|
|
703
|
+
const nameAndVersion = commons_1.getLayerNameWithVersion((_a = layer.Arn) !== null && _a !== void 0 ? _a : '');
|
|
704
|
+
if (nameAndVersion) {
|
|
705
|
+
lines.push(`- \`${nameAndVersion}\``);
|
|
809
706
|
}
|
|
810
|
-
|
|
811
|
-
}
|
|
812
|
-
});
|
|
813
|
-
|
|
707
|
+
codeSize += (_b = layer.CodeSize) !== null && _b !== void 0 ? _b : 0;
|
|
708
|
+
});
|
|
709
|
+
lines.push(`\n**Package Size**: \`${utils_1.formatBytes(codeSize)}\``);
|
|
710
|
+
// CLI Insights
|
|
711
|
+
lines.push('\n ## CLI');
|
|
712
|
+
lines.push(`**Run Location**: \`${process.cwd()}\` `);
|
|
713
|
+
lines.push(`**CLI Version**: \`${version}\` `);
|
|
714
|
+
const timeString = new Date().toISOString().replace('T', ' ').replace('Z', '') + ' UTC';
|
|
715
|
+
lines.push(`**Timestamp**: \`${timeString}\` `);
|
|
716
|
+
lines.push(`**Framework**: \`${exports.getFramework()}\``);
|
|
717
|
+
fs_1.writeFile(insightsFilePath, lines.join('\n'));
|
|
718
|
+
};
|
|
719
|
+
exports.generateInsightsFile = generateInsightsFile;
|
|
814
720
|
LambdaFlareCommand.addPath('lambda', 'flare');
|
|
815
721
|
LambdaFlareCommand.addOption('isDryRun', clipanion_1.Command.Boolean('-d,--dry'));
|
|
816
722
|
LambdaFlareCommand.addOption('withLogs', clipanion_1.Command.Boolean('--with-logs'));
|